Snap for 8426163 from b524450998ffe19bc7c6872f1002e487bb53021d to mainline-tzdata2-release

Change-Id: Ife47a2176f8ec37a6b2cec306bc2934876520592
diff --git a/.clang-tidy b/.clang-tidy
deleted file mode 100644
index 07073df..0000000
--- a/.clang-tidy
+++ /dev/null
@@ -1,6 +0,0 @@
-Checks: android-cloexec-*,bugprone-*,google-explicit-constructor,android-comparison-in-temp-failure-retry,modernize-use-nullptr,performance-for-range-copy,performance-noexcept-move-constructor,readability-container-size-empty,readability-else-after-return
-CheckOptions:
-  - key:             bugprone-assert-side-effect.AssertMacros
-    value:           'PERFETTO_DCHECK'
-  - key:             android-comparison-in-temp-failure-retry.RetryMacros
-    value:           'PERFETTO_EINTR,TEMP_FAILURE_RETRY'
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index c77d717..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-src/perfetto_cmd/perfetto_config.descriptor.h binary
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index b8c67a0..0000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Please do not submit a Pull Request via GitHub.
-Our project makes use of Gerrit for patch submission and review.
-
-For more details please see
-https://perfetto.dev/docs/contributing/getting-started
-
diff --git a/.gitignore b/.gitignore
index 0dbc578..f24c442 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
 .android_config
-.cache
-.ccls
 .ccls-cache
 .clangd
 .cproject
@@ -13,17 +11,15 @@
 .project
 .recipe_deps/
 .settings/
-.vscode
-*.code-workspace
 *.iml
 *.pyc
-*.sock
 *.swp
 /bazel-*
-/compile_commands.json
-/fuzz_out/
-/node_modules/
 /out*
-/ui/dist
 TAGS
-/venv/*
\ No newline at end of file
+/node_modules/
+/compile_commands.json
+.vscode
+*.code-workspace
+/fuzz_out/
+/bazel-*
diff --git a/.gn b/.gn
index d7ecabe..692a951 100644
--- a/.gn
+++ b/.gn
@@ -13,4 +13,3 @@
 # limitations under the License.
 
 buildconfig = "//gn/standalone/BUILDCONFIG.gn"
-script_executable = "python3"
diff --git a/Android.bp b/Android.bp
index 090910d..722ba58 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,6 +14,55 @@
 //
 // 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_cpu_raw_metrics_per_core.sql",
+    "src/trace_processor/metrics/android/android_hwui_metric.sql",
+    "src/trace_processor/metrics/android/android_ion.sql",
+    "src/trace_processor/metrics/android/android_lmk.sql",
+    "src/trace_processor/metrics/android/android_lmk_reason.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_startup.sql",
+    "src/trace_processor/metrics/android/android_startup_launches.sql",
+    "src/trace_processor/metrics/android/android_task_names.sql",
+    "src/trace_processor/metrics/android/android_task_state.sql",
+    "src/trace_processor/metrics/android/android_thread_time_in_state.sql",
+    "src/trace_processor/metrics/android/counter_span_view.sql",
+    "src/trace_processor/metrics/android/cpu_info.sql",
+    "src/trace_processor/metrics/android/display_metrics.sql",
+    "src/trace_processor/metrics/android/heap_profile_callsites.sql",
+    "src/trace_processor/metrics/android/hsc_startups.sql",
+    "src/trace_processor/metrics/android/java_heap_histogram.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_counter_span_view.sql",
+    "src/trace_processor/metrics/android/process_mem.sql",
+    "src/trace_processor/metrics/android/process_metadata.sql",
+    "src/trace_processor/metrics/android/process_oom_score.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/unmapped_java_symbols.sql",
+    "src/trace_processor/metrics/android/unsymbolized_frames.sql",
+    "src/trace_processor/metrics/chrome/chrome_processes.sql",
+    "src/trace_processor/metrics/trace_metadata.sql",
+  ],
+  cmd: "$(location tools/gen_merged_sql_metrics.py) --cpp_out=$(out) $(in)",
+  out: [
+    "src/trace_processor/metrics/sql_metrics.h",
+  ],
+  tool_files: [
+    "tools/gen_merged_sql_metrics.py",
+  ],
+}
+
 // GN: //src/profiling/memory:heapprofd
 cc_binary {
   name: "heapprofd",
@@ -39,8 +88,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -79,15 +126,12 @@
     ":perfetto_src_profiling_common_interner",
     ":perfetto_src_profiling_common_interning_output",
     ":perfetto_src_profiling_common_proc_utils",
-    ":perfetto_src_profiling_common_producer_support",
-    ":perfetto_src_profiling_common_profiler_guardrails",
     ":perfetto_src_profiling_common_unwind_support",
     ":perfetto_src_profiling_memory_daemon",
     ":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_packages_list_packages_list_parser",
     ":perfetto_src_tracing_common",
     ":perfetto_src_tracing_core_core",
     ":perfetto_src_tracing_ipc_common",
@@ -115,8 +159,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -147,7 +189,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -156,30 +197,6 @@
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
   ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
-}
-
-// GN: //src/profiling/memory:heapprofd_api_noop
-cc_library_shared {
-  name: "heapprofd_api_noop",
-  srcs: [
-    "src/profiling/memory/client_api_noop.cc",
-  ],
-  export_include_dirs: [
-    "src/profiling/memory/include",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  version_script: "src/profiling/memory/heapprofd_client_api.map.txt",
-  stubs: {
-    versions: [
-      "S",
-    ],
-    symbol_file: "src/profiling/memory/heapprofd_client_api.map.txt",
-  },
 }
 
 // GN: //src/profiling/memory:heapprofd_client
@@ -188,18 +205,27 @@
   srcs: [
     ":perfetto_include_perfetto_base_base",
     ":perfetto_include_perfetto_ext_base_base",
+    ":perfetto_include_perfetto_profiling_normalize",
     ":perfetto_src_base_base",
-    ":perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
-    ":perfetto_src_profiling_memory_wrap_allocators",
+    ":perfetto_src_base_unix_socket",
+    ":perfetto_src_profiling_common_proc_utils",
+    ":perfetto_src_profiling_memory_client",
+    ":perfetto_src_profiling_memory_malloc_hooks",
+    ":perfetto_src_profiling_memory_ring_buffer",
+    ":perfetto_src_profiling_memory_scoped_spinlock",
+    ":perfetto_src_profiling_memory_wire_protocol",
   ],
   shared_libs: [
-    "heapprofd_client_api",
+    "libbase",
+    "libprocinfo",
+    "libunwindstack",
   ],
   static_libs: [
     "libasync_safe",
   ],
-  generated_headers: [
-    "perfetto_src_base_version_gen_h",
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
   ],
   defaults: [
     "perfetto_defaults",
@@ -215,214 +241,6 @@
   ],
 }
 
-// GN: //src/profiling/memory:heapprofd_client_api
-cc_library_shared {
-  name: "heapprofd_client_api",
-  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_common_proc_utils",
-    ":perfetto_src_profiling_memory_client",
-    ":perfetto_src_profiling_memory_client_api",
-    ":perfetto_src_profiling_memory_ring_buffer",
-    ":perfetto_src_profiling_memory_scoped_spinlock",
-    ":perfetto_src_profiling_memory_wire_protocol",
-    "src/profiling/memory/client_api_factory_android.cc",
-  ],
-  shared_libs: [
-    "libbase",
-    "libprocinfo",
-    "libunwindstack",
-  ],
-  static_libs: [
-    "libasync_safe",
-  ],
-  export_include_dirs: [
-    "src/profiling/memory/include",
-  ],
-  generated_headers: [
-    "perfetto_src_base_version_gen_h",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG",
-    "-Werror=global-constructors",
-    "-Wglobal-constructors",
-  ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
-  version_script: "src/profiling/memory/heapprofd_client_api.map.txt",
-  stubs: {
-    versions: [
-      "S",
-    ],
-    symbol_file: "src/profiling/memory/heapprofd_client_api.map.txt",
-  },
-}
-
-// GN: //src/profiling/memory:heapprofd_standalone_client
-cc_library_shared {
-  name: "heapprofd_standalone_client",
-  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_core_forward_decls",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
-    ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_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_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_track_event_cpp_gen",
-    ":perfetto_protos_perfetto_config_track_event_zero_gen",
-    ":perfetto_protos_perfetto_config_zero_gen",
-    ":perfetto_protos_perfetto_ipc_cpp_gen",
-    ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_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_profiling_zero_gen",
-    ":perfetto_protos_perfetto_trace_ps_zero_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_trace_system_info_zero_gen",
-    ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
-    ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_client",
-    ":perfetto_src_ipc_common",
-    ":perfetto_src_profiling_common_callstack_trie",
-    ":perfetto_src_profiling_common_interner",
-    ":perfetto_src_profiling_common_interning_output",
-    ":perfetto_src_profiling_common_proc_utils",
-    ":perfetto_src_profiling_common_producer_support",
-    ":perfetto_src_profiling_common_profiler_guardrails",
-    ":perfetto_src_profiling_common_unwind_support",
-    ":perfetto_src_profiling_memory_client",
-    ":perfetto_src_profiling_memory_client_api",
-    ":perfetto_src_profiling_memory_client_api_standalone",
-    ":perfetto_src_profiling_memory_daemon",
-    ":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_packages_list_packages_list_parser",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_core_core",
-    ":perfetto_src_tracing_ipc_common",
-    ":perfetto_src_tracing_ipc_producer_producer",
-  ],
-  shared_libs: [
-    "liblog",
-  ],
-  static_libs: [
-    "libasync_safe",
-    "libbase",
-    "libdexfile_support",
-    "liblzma",
-    "libprocinfo",
-    "libunwindstack",
-  ],
-  export_include_dirs: [
-    "src/profiling/memory/include",
-  ],
-  generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
-    "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_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_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_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_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_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_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_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_zero_gen_headers",
-    "perfetto_protos_perfetto_config_track_event_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_config_zero_gen_headers",
-    "perfetto_protos_perfetto_ipc_cpp_gen_headers",
-    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_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_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_system_info_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-    "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG",
-  ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
-  stl: "libc++_static",
-  version_script: "src/profiling/memory/heapprofd_client_api.map.txt",
-}
-
 // GN: //src/ipc/protoc_plugin:ipc_plugin
 cc_binary_host {
   name: "ipc_plugin",
@@ -435,9 +253,6 @@
   static_libs: [
     "libprotoc",
   ],
-  generated_headers: [
-    "perfetto_src_base_version_gen_h",
-  ],
   defaults: [
     "perfetto_defaults",
   ],
@@ -474,8 +289,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -508,29 +321,22 @@
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
-    ":perfetto_src_kallsyms_kallsyms",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_traced_probes_android_log_android_log",
     ":perfetto_src_traced_probes_common_common",
     ":perfetto_src_traced_probes_data_source",
     ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
     ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
     ":perfetto_src_traced_probes_metatrace_metatrace",
     ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_traced_probes_power_power",
     ":perfetto_src_traced_probes_probes",
     ":perfetto_src_traced_probes_probes_src",
@@ -547,6 +353,9 @@
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
   ],
+  shared_libs: [
+    "liblog",
+  ],
   host_supported: true,
   export_include_dirs: [
     "include",
@@ -564,8 +373,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -596,7 +403,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -605,32 +411,19 @@
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
   ],
-  target: {
-    android: {
-      shared_libs: [
-        "liblog",
-      ],
-    },
-  },
 }
 
 // GN: //src/android_internal:libperfetto_android_internal
 cc_library_shared {
   name: "libperfetto_android_internal",
   srcs: [
+    ":perfetto_src_android_internal_android_internal",
     ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_stats_perfetto_atoms",
-    "src/android_internal/atrace_hal.cc",
-    "src/android_internal/health_hal.cc",
-    "src/android_internal/incident_service.cc",
-    "src/android_internal/power_stats.cc",
-    "src/android_internal/statsd_logging.cc",
-    "src/android_internal/tracing_service_proxy.cc",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
   ],
   shared_libs: [
     "android.hardware.atrace@1.0",
     "android.hardware.health@2.0",
-    "android.hardware.power.stats-V1-cpp",
     "android.hardware.power.stats@1.0",
     "libbase",
     "libbinder",
@@ -640,13 +433,16 @@
     "liblog",
     "libservices",
     "libstatssocket",
-    "libtracingproxy",
     "libutils",
   ],
   static_libs: [
     "libhealthhalutils",
     "libstatslog_perfetto",
   ],
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
+  ],
   defaults: [
     "perfetto_defaults",
   ],
@@ -681,8 +477,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -713,18 +507,11 @@
     ":perfetto_protos_perfetto_trace_system_info_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_tracing_client_api_without_backends",
     ":perfetto_src_tracing_common",
@@ -735,12 +522,9 @@
     ":perfetto_src_tracing_ipc_consumer_consumer",
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
-    ":perfetto_src_tracing_platform_impl",
+    ":perfetto_src_tracing_platform_posix",
     ":perfetto_src_tracing_system_backend",
   ],
-  shared_libs: [
-    "liblog",
-  ],
   export_include_dirs: [
     "include",
     "include/perfetto/base/build_configs/android_tree",
@@ -757,8 +541,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -789,7 +571,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   export_generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
@@ -803,8 +584,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -835,7 +614,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -846,10 +624,9 @@
   ],
   apex_available: [
     "//apex_available:platform",
-    "com.android.art",
     "com.android.art.debug",
+    "com.android.art.release",
   ],
-  min_sdk_version: "S",
 }
 
 // GN: //src/perfetto_cmd:perfetto
@@ -877,8 +654,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -911,12 +686,11 @@
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_perfetto_cmd_perfetto_cmd",
     ":perfetto_src_perfetto_cmd_protos_gen",
     ":perfetto_src_perfetto_cmd_trigger_producer",
@@ -944,8 +718,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -976,8 +748,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
-    "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
@@ -1016,8 +786,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -1064,31 +832,23 @@
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_test_support",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
-    ":perfetto_src_ipc_perfetto_ipc",
-    ":perfetto_src_kallsyms_kallsyms",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_traced_probes_android_log_android_log",
     ":perfetto_src_traced_probes_common_common",
     ":perfetto_src_traced_probes_data_source",
     ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
     ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
     ":perfetto_src_traced_probes_metatrace_metatrace",
     ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_traced_probes_power_power",
     ":perfetto_src_traced_probes_probes_src",
     ":perfetto_src_traced_probes_ps_ps",
@@ -1108,6 +868,7 @@
     "test/cts/heapprofd_java_test_cts.cc",
     "test/cts/heapprofd_test_cts.cc",
     "test/cts/traced_perf_test_cts.cc",
+    "test/cts/utils.cc",
   ],
   static_libs: [
     "libgmock",
@@ -1117,6 +878,10 @@
   whole_static_libs: [
     "perfetto_gtest_logcat_printer",
   ],
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
+  ],
   generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
@@ -1129,8 +894,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -1175,7 +938,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   export_generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
@@ -1189,8 +951,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -1235,7 +995,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -1272,8 +1031,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -1320,31 +1077,23 @@
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_test_support",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
-    ":perfetto_src_ipc_perfetto_ipc",
-    ":perfetto_src_kallsyms_kallsyms",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_traced_probes_android_log_android_log",
     ":perfetto_src_traced_probes_common_common",
     ":perfetto_src_traced_probes_data_source",
     ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
     ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
     ":perfetto_src_traced_probes_metatrace_metatrace",
     ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_traced_probes_power_power",
     ":perfetto_src_traced_probes_probes_src",
     ":perfetto_src_traced_probes_ps_ps",
@@ -1359,6 +1108,10 @@
     ":perfetto_src_tracing_ipc_service_service",
     ":perfetto_test_test_helper",
   ],
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
+  ],
   generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
@@ -1371,8 +1124,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -1417,7 +1168,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   export_generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
@@ -1431,8 +1181,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -1477,7 +1225,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -1503,7 +1250,6 @@
     "external/perfetto",
     "external/perfetto/include",
     "external/perfetto/include/perfetto/base/build_configs/android_tree",
-    "external/perfetto/src/profiling/memory/include",
   ],
   product_variables: {
     debuggable: {
@@ -1529,6 +1275,10 @@
     "libgmock",
     "libgtest",
   ],
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
+  ],
   defaults: [
     "perfetto_defaults",
   ],
@@ -1554,11 +1304,6 @@
   name: "perfetto_include_perfetto_ext_trace_processor_export_json",
 }
 
-// GN: //include/perfetto/ext/trace_processor/importers/memory_tracker:memory_tracker
-filegroup {
-  name: "perfetto_include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
-}
-
 // GN: //include/perfetto/ext/traced:sys_stats_counters
 filegroup {
   name: "perfetto_include_perfetto_ext_traced_sys_stats_counters",
@@ -1579,6 +1324,11 @@
   name: "perfetto_include_perfetto_ext_tracing_ipc_ipc",
 }
 
+// GN: //include/perfetto/profiling:deobfuscator
+filegroup {
+  name: "perfetto_include_perfetto_profiling_deobfuscator",
+}
+
 // GN: //include/perfetto/profiling:normalize
 filegroup {
   name: "perfetto_include_perfetto_profiling_normalize",
@@ -1599,11 +1349,6 @@
   name: "perfetto_include_perfetto_public_public",
 }
 
-// GN: //include/perfetto/test:test_support
-filegroup {
-  name: "perfetto_include_perfetto_test_test_support",
-}
-
 // GN: //include/perfetto/trace_processor:basic_types
 filegroup {
   name: "perfetto_include_perfetto_trace_processor_basic_types",
@@ -1641,17 +1386,12 @@
     ":perfetto_include_perfetto_base_base",
     ":perfetto_include_perfetto_ext_base_base",
     ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_trace_processor_export_json",
-    ":perfetto_include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
     ":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_core_forward_decls",
     ":perfetto_include_perfetto_tracing_tracing",
@@ -1666,8 +1406,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -1702,8 +1440,6 @@
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_cpp_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
-    ":perfetto_protos_perfetto_trace_processor_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_cpp_gen",
@@ -1716,22 +1452,17 @@
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_test_support",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
     ":perfetto_src_ipc_host",
-    ":perfetto_src_ipc_perfetto_ipc",
-    ":perfetto_src_kallsyms_kallsyms",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_profiling_common_callstack_trie",
     ":perfetto_src_profiling_common_interner",
     ":perfetto_src_profiling_common_interning_output",
     ":perfetto_src_profiling_common_proc_utils",
-    ":perfetto_src_profiling_common_producer_support",
-    ":perfetto_src_profiling_common_profiler_guardrails",
     ":perfetto_src_profiling_common_unwind_support",
     ":perfetto_src_profiling_memory_client",
     ":perfetto_src_profiling_memory_daemon",
@@ -1739,43 +1470,18 @@
     ":perfetto_src_profiling_memory_ring_buffer",
     ":perfetto_src_profiling_memory_scoped_spinlock",
     ":perfetto_src_profiling_memory_wire_protocol",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
     ":perfetto_src_protozero_protozero",
-    ":perfetto_src_trace_processor_analysis_analysis",
-    ":perfetto_src_trace_processor_containers_containers",
-    ":perfetto_src_trace_processor_db_db",
-    ":perfetto_src_trace_processor_export_json",
-    ":perfetto_src_trace_processor_ftrace_descriptors",
-    ":perfetto_src_trace_processor_importers_common_common",
-    ":perfetto_src_trace_processor_importers_memory_tracker_graph_processor",
-    ":perfetto_src_trace_processor_lib",
-    ":perfetto_src_trace_processor_metatrace",
-    ":perfetto_src_trace_processor_metrics_lib",
-    ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_storage_full",
-    ":perfetto_src_trace_processor_storage_minimal",
-    ":perfetto_src_trace_processor_storage_storage",
-    ":perfetto_src_trace_processor_tables_tables",
-    ":perfetto_src_trace_processor_types_types",
-    ":perfetto_src_trace_processor_util_descriptors",
-    ":perfetto_src_trace_processor_util_proto_to_args_parser",
-    ":perfetto_src_trace_processor_util_protozero_to_text",
-    ":perfetto_src_trace_processor_util_util",
     ":perfetto_src_traced_probes_android_log_android_log",
     ":perfetto_src_traced_probes_common_common",
     ":perfetto_src_traced_probes_data_source",
     ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
     ":perfetto_src_traced_probes_ftrace_integrationtests",
     ":perfetto_src_traced_probes_ftrace_test_support",
     ":perfetto_src_traced_probes_initial_display_state_initial_display_state",
     ":perfetto_src_traced_probes_metatrace_metatrace",
     ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_traced_probes_power_power",
     ":perfetto_src_traced_probes_probes_src",
     ":perfetto_src_traced_probes_ps_ps",
@@ -1790,7 +1496,7 @@
     ":perfetto_src_tracing_ipc_consumer_consumer",
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
-    ":perfetto_src_tracing_platform_impl",
+    ":perfetto_src_tracing_platform_posix",
     ":perfetto_src_tracing_system_backend",
     ":perfetto_src_tracing_test_api_test_support",
     ":perfetto_src_tracing_test_client_api_integrationtests",
@@ -1798,15 +1504,10 @@
     ":perfetto_test_test_helper",
   ],
   shared_libs: [
-    "heapprofd_client_api",
-    "libandroidicu",
     "libbase",
     "liblog",
     "libprocinfo",
-    "libsqlite",
     "libunwindstack",
-    "libutils",
-    "libz",
   ],
   static_libs: [
     "libgmock",
@@ -1828,8 +1529,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -1864,8 +1563,6 @@
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_processor_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
@@ -1876,13 +1573,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
-    "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_merged_sql_metrics",
   ],
   defaults: [
     "perfetto_defaults",
@@ -1890,31 +1580,20 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-    "-DHAVE_HIDDEN",
   ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
-  test_suites: [
-    "general-tests",
-  ],
-  test_config: "PerfettoIntegrationTests.xml",
 }
 
 // GN: //protos/perfetto/common:cpp
 genrule {
   name: "perfetto_protos_perfetto_common_cpp_gen",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -1927,16 +1606,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/common/android_energy_consumer_descriptor.gen.cc",
     "external/perfetto/protos/perfetto/common/android_log_constants.gen.cc",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.gen.cc",
     "external/perfetto/protos/perfetto/common/observable_events.gen.cc",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.gen.cc",
@@ -1949,16 +1625,13 @@
 genrule {
   name: "perfetto_protos_perfetto_common_cpp_gen_headers",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -1971,16 +1644,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/common/android_energy_consumer_descriptor.gen.h",
     "external/perfetto/protos/perfetto/common/android_log_constants.gen.h",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.gen.h",
     "external/perfetto/protos/perfetto/common/observable_events.gen.h",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.gen.h",
@@ -1997,16 +1667,13 @@
 genrule {
   name: "perfetto_protos_perfetto_common_lite_gen",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -2018,16 +1685,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/common/android_energy_consumer_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/common/android_log_constants.pb.cc",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/common/observable_events.pb.cc",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.pb.cc",
@@ -2040,16 +1704,13 @@
 genrule {
   name: "perfetto_protos_perfetto_common_lite_gen_headers",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -2061,16 +1722,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/common/android_energy_consumer_descriptor.pb.h",
     "external/perfetto/protos/perfetto/common/android_log_constants.pb.h",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.pb.h",
     "external/perfetto/protos/perfetto/common/observable_events.pb.h",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.pb.h",
@@ -2087,16 +1745,13 @@
 genrule {
   name: "perfetto_protos_perfetto_common_zero_gen",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -2109,16 +1764,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/common/android_energy_consumer_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.cc",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/common/observable_events.pbzero.cc",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.pbzero.cc",
@@ -2131,16 +1783,13 @@
 genrule {
   name: "perfetto_protos_perfetto_common_zero_gen_headers",
   srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
     "protos/perfetto/common/android_log_constants.proto",
     "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -2153,16 +1802,13 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/common/android_energy_consumer_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.h",
     "external/perfetto/protos/perfetto/common/builtin_clock.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/interceptor_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/common/observable_events.pbzero.h",
-    "external/perfetto/protos/perfetto/common/perf_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_capabilities.pbzero.h",
@@ -2311,8 +1957,6 @@
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -2324,8 +1968,6 @@
   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/interceptor_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/stress_test_config.gen.cc",
     "external/perfetto/protos/perfetto/config/test_config.gen.cc",
     "external/perfetto/protos/perfetto/config/trace_config.gen.cc",
   ],
@@ -2337,8 +1979,6 @@
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -2350,8 +1990,6 @@
   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/interceptor_config.gen.h",
-    "external/perfetto/protos/perfetto/config/stress_test_config.gen.h",
     "external/perfetto/protos/perfetto/config/test_config.gen.h",
     "external/perfetto/protos/perfetto/config/trace_config.gen.h",
   ],
@@ -2361,56 +1999,6 @@
   ],
 }
 
-// GN: //protos/perfetto/config:descriptor
-genrule {
-  name: "perfetto_protos_perfetto_config_descriptor",
-  srcs: [
-    "protos/perfetto/common/android_energy_consumer_descriptor.proto",
-    "protos/perfetto/common/android_log_constants.proto",
-    "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
-    "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/perf_events.proto",
-    "protos/perfetto/common/sys_stats_counters.proto",
-    "protos/perfetto/common/trace_stats.proto",
-    "protos/perfetto/common/tracing_service_capabilities.proto",
-    "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/android_polled_state_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/gpu/gpu_counter_config.proto",
-    "protos/perfetto/config/gpu/vulkan_memory_config.proto",
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/interceptors/console_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/profiling/java_hprof_config.proto",
-    "protos/perfetto/config/profiling/perf_event_config.proto",
-    "protos/perfetto/config/stress_test_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/track_event/track_event_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
-  out: [
-    "perfetto_protos_perfetto_config_descriptor.bin",
-  ],
-}
-
 // GN: //protos/perfetto/config/ftrace:cpp
 genrule {
   name: "perfetto_protos_perfetto_config_ftrace_cpp_gen",
@@ -2741,120 +2329,12 @@
   ],
 }
 
-// GN: //protos/perfetto/config/interceptors:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/interceptors/console_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/interceptors:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/interceptors/console_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/interceptors:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_lite_gen",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/interceptors/console_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/interceptors:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/interceptors/console_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/interceptors:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_zero_gen",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/interceptors/console_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/interceptors:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/interceptors/console_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/interceptors/console_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
 // GN: //protos/perfetto/config:lite
 genrule {
   name: "perfetto_protos_perfetto_config_lite_gen",
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -2865,8 +2345,6 @@
   out: [
     "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/interceptor_config.pb.cc",
-    "external/perfetto/protos/perfetto/config/stress_test_config.pb.cc",
     "external/perfetto/protos/perfetto/config/test_config.pb.cc",
     "external/perfetto/protos/perfetto/config/trace_config.pb.cc",
   ],
@@ -2878,8 +2356,6 @@
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -2890,8 +2366,6 @@
   out: [
     "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/interceptor_config.pb.h",
-    "external/perfetto/protos/perfetto/config/stress_test_config.pb.h",
     "external/perfetto/protos/perfetto/config/test_config.pb.h",
     "external/perfetto/protos/perfetto/config/trace_config.pb.h",
   ],
@@ -2901,21 +2375,6 @@
   ],
 }
 
-// GN: //protos/perfetto/config:perfetto_config_descriptor
-genrule {
-  name: "perfetto_protos_perfetto_config_perfetto_config_descriptor",
-  srcs: [
-    "protos/perfetto/config/perfetto_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
-  out: [
-    "perfetto_protos_perfetto_config_perfetto_config_descriptor.bin",
-  ],
-}
-
 // GN: //protos/perfetto/config/power:cpp
 genrule {
   name: "perfetto_protos_perfetto_config_power_cpp_gen",
@@ -3476,8 +2935,6 @@
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -3489,8 +2946,6 @@
   out: [
     "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/interceptor_config.pbzero.cc",
-    "external/perfetto/protos/perfetto/config/stress_test_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/test_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/trace_config.pbzero.cc",
   ],
@@ -3502,8 +2957,6 @@
   srcs: [
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/interceptor_config.proto",
-    "protos/perfetto/config/stress_test_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
@@ -3515,8 +2968,6 @@
   out: [
     "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/interceptor_config.pbzero.h",
-    "external/perfetto/protos/perfetto/config/stress_test_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/test_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/trace_config.pbzero.h",
   ],
@@ -3642,21 +3093,16 @@
   ],
 }
 
-// GN: //protos/perfetto/metrics/chrome:descriptor
+// GN: //protos/perfetto/metrics/android:zero
 genrule {
-  name: "perfetto_protos_perfetto_metrics_chrome_descriptor",
+  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/display_metrics.proto",
-    "protos/perfetto/metrics/android/dma_heap_metric.proto",
-    "protos/perfetto/metrics/android/fastrpc_metric.proto",
-    "protos/perfetto/metrics/android/g2d_metric.proto",
-    "protos/perfetto/metrics/android/gpu_metric.proto",
-    "protos/perfetto/metrics/android/hwcomposer.proto",
+    "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/hwui_metric.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
-    "protos/perfetto/metrics/android/jank_metric.proto",
     "protos/perfetto/metrics/android/java_heap_histogram.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
@@ -3667,45 +3113,50 @@
     "protos/perfetto/metrics/android/powrails_metric.proto",
     "protos/perfetto/metrics/android/process_metadata.proto",
     "protos/perfetto/metrics/android/startup_metric.proto",
-    "protos/perfetto/metrics/android/surfaceflinger.proto",
-    "protos/perfetto/metrics/android/sysui_cuj_metrics.proto",
     "protos/perfetto/metrics/android/task_names.proto",
     "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
+    "protos/perfetto/metrics/android/unmapped_java_symbols.proto",
     "protos/perfetto/metrics/android/unsymbolized_frames.proto",
-    "protos/perfetto/metrics/chrome/all_chrome_metrics.proto",
-    "protos/perfetto/metrics/chrome/blink_gc_metric.proto",
-    "protos/perfetto/metrics/chrome/frame_times.proto",
-    "protos/perfetto/metrics/chrome/media_metric.proto",
-    "protos/perfetto/metrics/chrome/reported_by_page.proto",
-    "protos/perfetto/metrics/chrome/scroll_jank.proto",
-    "protos/perfetto/metrics/chrome/test_chrome_metric.proto",
-    "protos/perfetto/metrics/custom_options.proto",
-    "protos/perfetto/metrics/metrics.proto",
   ],
   tools: [
     "aprotoc",
+    "protozero_plugin",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --proto_path=external/protobuf/src --descriptor_set_out=$(out) $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "perfetto_protos_perfetto_metrics_chrome_descriptor.bin",
+    "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/display_metrics.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/java_heap_histogram.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/lmk_reason_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_metadata.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/task_names.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/thread_time_in_state_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/unmapped_java_symbols.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/metrics:descriptor
+// GN: //protos/perfetto/metrics/android:zero
 genrule {
-  name: "perfetto_protos_perfetto_metrics_descriptor",
+  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/display_metrics.proto",
-    "protos/perfetto/metrics/android/dma_heap_metric.proto",
-    "protos/perfetto/metrics/android/fastrpc_metric.proto",
-    "protos/perfetto/metrics/android/g2d_metric.proto",
-    "protos/perfetto/metrics/android/gpu_metric.proto",
-    "protos/perfetto/metrics/android/hwcomposer.proto",
+    "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/hwui_metric.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
-    "protos/perfetto/metrics/android/jank_metric.proto",
     "protos/perfetto/metrics/android/java_heap_histogram.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
@@ -3716,19 +3167,77 @@
     "protos/perfetto/metrics/android/powrails_metric.proto",
     "protos/perfetto/metrics/android/process_metadata.proto",
     "protos/perfetto/metrics/android/startup_metric.proto",
-    "protos/perfetto/metrics/android/surfaceflinger.proto",
-    "protos/perfetto/metrics/android/sysui_cuj_metrics.proto",
     "protos/perfetto/metrics/android/task_names.proto",
     "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
+    "protos/perfetto/metrics/android/unmapped_java_symbols.proto",
     "protos/perfetto/metrics/android/unsymbolized_frames.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "protozero_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/metrics/android/batt_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/display_metrics.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/java_heap_histogram.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/lmk_reason_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_metadata.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/task_names.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/thread_time_in_state_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/unmapped_java_symbols.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
+// GN: //protos/perfetto/metrics:zero
+genrule {
+  name: "perfetto_protos_perfetto_metrics_zero_gen",
+  srcs: [
     "protos/perfetto/metrics/metrics.proto",
   ],
   tools: [
     "aprotoc",
+    "protozero_plugin",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "perfetto_protos_perfetto_metrics_descriptor.bin",
+    "external/perfetto/protos/perfetto/metrics/metrics.pbzero.cc",
+  ],
+}
+
+// GN: //protos/perfetto/metrics:zero
+genrule {
+  name: "perfetto_protos_perfetto_metrics_zero_gen_headers",
+  srcs: [
+    "protos/perfetto/metrics/metrics.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "protozero_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/metrics/metrics.pbzero.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
   ],
 }
 
@@ -3737,7 +3246,6 @@
   name: "perfetto_protos_perfetto_trace_android_cpp_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3750,7 +3258,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.gen.cc",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.gen.cc",
@@ -3763,7 +3270,6 @@
   name: "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3776,7 +3282,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.gen.h",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.gen.h",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.gen.h",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.gen.h",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.gen.h",
@@ -3793,7 +3298,6 @@
   name: "perfetto_protos_perfetto_trace_android_lite_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3805,7 +3309,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.cc",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.pb.cc",
@@ -3818,7 +3321,6 @@
   name: "perfetto_protos_perfetto_trace_android_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3830,7 +3332,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.h",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.pb.h",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.pb.h",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.h",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.pb.h",
@@ -3847,7 +3348,6 @@
   name: "perfetto_protos_perfetto_trace_android_zero_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3860,7 +3360,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/android/android_log.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.pbzero.cc",
@@ -3873,7 +3372,6 @@
   name: "perfetto_protos_perfetto_trace_android_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/frame_timeline_event.proto",
     "protos/perfetto/trace/android/gpu_mem_event.proto",
     "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/initial_display_state.proto",
@@ -3886,7 +3384,6 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/android/android_log.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/android/frame_timeline_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/android/gpu_mem_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/android/initial_display_state.pbzero.h",
@@ -4143,19 +3640,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4164,7 +3656,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4172,14 +3663,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4194,19 +3683,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.cc",
@@ -4215,7 +3699,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.gen.cc",
@@ -4223,14 +3706,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/task.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.gen.cc",
   ],
@@ -4245,19 +3726,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4266,7 +3742,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4274,14 +3749,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4296,19 +3769,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.h",
@@ -4317,7 +3785,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.gen.h",
@@ -4325,14 +3792,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/task.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.gen.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.gen.h",
   ],
@@ -4351,19 +3816,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4372,7 +3832,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4380,14 +3839,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4401,19 +3858,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.cc",
@@ -4422,7 +3874,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.pb.cc",
@@ -4430,14 +3881,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/task.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.pb.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pb.cc",
   ],
@@ -4452,19 +3901,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4473,7 +3917,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4481,14 +3924,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4502,19 +3943,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.h",
@@ -4523,7 +3959,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.pb.h",
@@ -4531,14 +3966,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/task.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.pb.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pb.h",
   ],
@@ -4557,19 +3990,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4578,7 +4006,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4586,14 +4013,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4608,19 +4033,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.cc",
@@ -4629,7 +4049,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.pbzero.cc",
@@ -4637,14 +4056,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/task.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pbzero.cc",
   ],
@@ -4659,19 +4076,14 @@
     "protos/perfetto/trace/ftrace/cgroup.proto",
     "protos/perfetto/trace/ftrace/clk.proto",
     "protos/perfetto/trace/ftrace/compaction.proto",
-    "protos/perfetto/trace/ftrace/cpuhp.proto",
-    "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-    "protos/perfetto/trace/ftrace/dpu.proto",
     "protos/perfetto/trace/ftrace/ext4.proto",
     "protos/perfetto/trace/ftrace/f2fs.proto",
-    "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/gpu_mem.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
@@ -4680,7 +4092,6 @@
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
     "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-    "protos/perfetto/trace/ftrace/mali.proto",
     "protos/perfetto/trace/ftrace/mdss.proto",
     "protos/perfetto/trace/ftrace/mm_event.proto",
     "protos/perfetto/trace/ftrace/oom.proto",
@@ -4688,14 +4099,12 @@
     "protos/perfetto/trace/ftrace/raw_syscalls.proto",
     "protos/perfetto/trace/ftrace/regulator.proto",
     "protos/perfetto/trace/ftrace/sched.proto",
-    "protos/perfetto/trace/ftrace/scm.proto",
     "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
     "protos/perfetto/trace/ftrace/vmscan.proto",
     "protos/perfetto/trace/ftrace/workqueue.proto",
   ],
@@ -4710,19 +4119,14 @@
     "external/perfetto/protos/perfetto/trace/ftrace/cgroup.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/clk.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/compaction.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/dpu.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ext4.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/f2fs.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/fastrpc.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/fence.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/filemap.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/g2d.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/gpu_mem.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.h",
@@ -4731,7 +4135,6 @@
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/mali.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mdss.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/mm_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/oom.pbzero.h",
@@ -4739,14 +4142,12 @@
     "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/regulator.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sched.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/scm.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sde.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/signal.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/sync.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/systrace.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/task.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/ftrace/thermal.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/vmscan.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pbzero.h",
   ],
@@ -5150,14 +4551,10 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
@@ -5165,14 +4562,10 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/extension_descriptor.gen.cc",
-    "external/perfetto/protos/perfetto/trace/memory_graph.gen.cc",
     "external/perfetto/protos/perfetto/trace/test_event.gen.cc",
-    "external/perfetto/protos/perfetto/trace/test_extensions.gen.cc",
     "external/perfetto/protos/perfetto/trace/trace.gen.cc",
     "external/perfetto/protos/perfetto/trace/trace_packet.gen.cc",
     "external/perfetto/protos/perfetto/trace/trace_packet_defaults.gen.cc",
-    "external/perfetto/protos/perfetto/trace/ui_state.gen.cc",
   ],
 }
 
@@ -5180,14 +4573,10 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
@@ -5195,14 +4584,10 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/extension_descriptor.gen.h",
-    "external/perfetto/protos/perfetto/trace/memory_graph.gen.h",
     "external/perfetto/protos/perfetto/trace/test_event.gen.h",
-    "external/perfetto/protos/perfetto/trace/test_extensions.gen.h",
     "external/perfetto/protos/perfetto/trace/trace.gen.h",
     "external/perfetto/protos/perfetto/trace/trace_packet.gen.h",
     "external/perfetto/protos/perfetto/trace/trace_packet_defaults.gen.h",
-    "external/perfetto/protos/perfetto/trace/ui_state.gen.h",
   ],
   export_include_dirs: [
     ".",
@@ -5214,28 +4599,20 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_lite_gen",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/extension_descriptor.pb.cc",
-    "external/perfetto/protos/perfetto/trace/memory_graph.pb.cc",
     "external/perfetto/protos/perfetto/trace/test_event.pb.cc",
-    "external/perfetto/protos/perfetto/trace/test_extensions.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",
-    "external/perfetto/protos/perfetto/trace/ui_state.pb.cc",
   ],
 }
 
@@ -5243,28 +4620,20 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/extension_descriptor.pb.h",
-    "external/perfetto/protos/perfetto/trace/memory_graph.pb.h",
     "external/perfetto/protos/perfetto/trace/test_event.pb.h",
-    "external/perfetto/protos/perfetto/trace/test_extensions.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",
-    "external/perfetto/protos/perfetto/trace/ui_state.pb.h",
   ],
   export_include_dirs: [
     ".",
@@ -5276,14 +4645,10 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_zero_gen",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
@@ -5291,14 +4656,10 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/extension_descriptor.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/memory_graph.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/test_event.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/test_extensions.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",
-    "external/perfetto/protos/perfetto/trace/ui_state.pbzero.cc",
   ],
 }
 
@@ -5306,14 +4667,10 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/extension_descriptor.proto",
-    "protos/perfetto/trace/memory_graph.proto",
     "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/test_extensions.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
     "protos/perfetto/trace/trace_packet_defaults.proto",
-    "protos/perfetto/trace/ui_state.proto",
   ],
   tools: [
     "aprotoc",
@@ -5321,14 +4678,10 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/extension_descriptor.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/memory_graph.pbzero.h",
     "external/perfetto/protos/perfetto/trace/test_event.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/test_extensions.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",
-    "external/perfetto/protos/perfetto/trace/ui_state.pbzero.h",
   ],
   export_include_dirs: [
     ".",
@@ -5458,7 +4811,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_cpp_gen",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5468,7 +4820,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/power/android_energy_estimation_breakdown.gen.cc",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.gen.cc",
     "external/perfetto/protos/perfetto/trace/power/power_rails.gen.cc",
   ],
@@ -5478,7 +4829,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5488,7 +4838,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/power/android_energy_estimation_breakdown.gen.h",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.gen.h",
     "external/perfetto/protos/perfetto/trace/power/power_rails.gen.h",
   ],
@@ -5502,7 +4851,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_lite_gen",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5511,7 +4859,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/power/android_energy_estimation_breakdown.pb.cc",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pb.cc",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pb.cc",
   ],
@@ -5521,7 +4868,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5530,7 +4876,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/power/android_energy_estimation_breakdown.pb.h",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pb.h",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pb.h",
   ],
@@ -5544,7 +4889,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_zero_gen",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5554,7 +4898,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_energy_estimation_breakdown.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pbzero.cc",
   ],
@@ -5564,7 +4907,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_power_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
     "protos/perfetto/trace/power/battery_counters.proto",
     "protos/perfetto/trace/power/power_rails.proto",
   ],
@@ -5574,7 +4916,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/power/android_energy_estimation_breakdown.pbzero.h",
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pbzero.h",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pbzero.h",
   ],
@@ -5620,47 +4961,10 @@
   ],
 }
 
-// GN: //protos/perfetto/trace_processor:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_processor_zero_gen",
-  srcs: [
-    "protos/perfetto/trace_processor/trace_processor.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/trace_processor.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace_processor:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_processor_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace_processor/trace_processor.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/trace_processor.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
 // GN: //protos/perfetto/trace/profiling:cpp
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_cpp_gen",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5672,7 +4976,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/deobfuscation.gen.cc",
     "external/perfetto/protos/perfetto/trace/profiling/heap_graph.gen.cc",
     "external/perfetto/protos/perfetto/trace/profiling/profile_common.gen.cc",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.gen.cc",
@@ -5684,7 +4987,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5696,7 +4998,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/deobfuscation.gen.h",
     "external/perfetto/protos/perfetto/trace/profiling/heap_graph.gen.h",
     "external/perfetto/protos/perfetto/trace/profiling/profile_common.gen.h",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.gen.h",
@@ -5712,7 +5013,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_lite_gen",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5723,7 +5023,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/deobfuscation.pb.cc",
     "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",
@@ -5735,7 +5034,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5746,7 +5044,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/deobfuscation.pb.h",
     "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",
@@ -5762,7 +5059,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_zero_gen",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5774,7 +5070,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/profiling/deobfuscation.pbzero.cc",
     "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",
@@ -5786,7 +5081,6 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/profiling/deobfuscation.proto",
     "protos/perfetto/trace/profiling/heap_graph.proto",
     "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -5798,7 +5092,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/profiling/deobfuscation.pbzero.h",
     "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",
@@ -6144,21 +5437,14 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_cpp_gen",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6175,21 +5461,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.gen.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.cc",
@@ -6206,21 +5485,14 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6237,21 +5509,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.gen.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.h",
@@ -6272,21 +5537,14 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6302,21 +5560,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
@@ -6333,21 +5584,14 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6363,21 +5607,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
@@ -6394,63 +5631,18 @@
   ],
 }
 
-// GN: //protos/perfetto/trace/track_event:track_event_descriptor
-genrule {
-  name: "perfetto_protos_perfetto_trace_track_event_track_event_descriptor",
-  srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
-    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
-    "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
-    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
-    "protos/perfetto/trace/track_event/chrome_latency_info.proto",
-    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
-    "protos/perfetto/trace/track_event/counter_descriptor.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",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
-  out: [
-    "perfetto_protos_perfetto_trace_track_event_track_event_descriptor.bin",
-  ],
-}
-
 // GN: //protos/perfetto/trace/track_event:zero
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6467,21 +5659,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/track_event/chrome_application_state_info.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
@@ -6498,21 +5683,14 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_latency_info.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
     "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
     "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
     "protos/perfetto/trace/track_event/counter_descriptor.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -6529,21 +5707,14 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --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/track_event/chrome_application_state_info.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_content_settings_event_info.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/counter_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
@@ -6560,45 +5731,6 @@
   ],
 }
 
-// GN: //protos/third_party/chromium:chrome_track_event_descriptor
-genrule {
-  name: "perfetto_protos_third_party_chromium_chrome_track_event_descriptor",
-  srcs: [
-    "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
-    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
-    "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
-    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
-    "protos/perfetto/trace/track_event/chrome_latency_info.proto",
-    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-    "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-    "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
-    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
-    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/chrome_user_event.proto",
-    "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
-    "protos/perfetto/trace/track_event/counter_descriptor.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/third_party/chromium/chrome_track_event.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
-  out: [
-    "perfetto_protos_third_party_chromium_chrome_track_event_descriptor.bin",
-  ],
-}
-
 // GN: //protos/third_party/pprof:zero
 genrule {
   name: "perfetto_protos_third_party_pprof_zero_gen",
@@ -6635,6 +5767,19 @@
   ],
 }
 
+// GN: //src/android_internal:android_internal
+filegroup {
+  name: "perfetto_src_android_internal_android_internal",
+  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/android_internal/statsd_logging.cc",
+  ],
+}
+
 // GN: //src/android_internal:headers
 filegroup {
   name: "perfetto_src_android_internal_headers",
@@ -6648,47 +5793,26 @@
   ],
 }
 
-// GN: //src/android_stats:android_stats
-filegroup {
-  name: "perfetto_src_android_stats_android_stats",
-  srcs: [
-    "src/android_stats/statsd_logging_helper.cc",
-  ],
-}
-
-// GN: //src/android_stats:perfetto_atoms
-filegroup {
-  name: "perfetto_src_android_stats_perfetto_atoms",
-}
-
 // GN: //src/base:base
 filegroup {
   name: "perfetto_src_base_base",
   srcs: [
-    "src/base/ctrl_c_handler.cc",
     "src/base/event_fd.cc",
     "src/base/file_utils.cc",
-    "src/base/getopt_compat.cc",
     "src/base/logging.cc",
     "src/base/metatrace.cc",
     "src/base/paged_memory.cc",
-    "src/base/periodic_task.cc",
     "src/base/pipe.cc",
-    "src/base/status.cc",
     "src/base/string_splitter.cc",
     "src/base/string_utils.cc",
     "src/base/string_view.cc",
     "src/base/subprocess.cc",
-    "src/base/subprocess_posix.cc",
-    "src/base/subprocess_windows.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/utils.cc",
     "src/base/uuid.cc",
-    "src/base/version.cc",
     "src/base/virtual_destructors.cc",
     "src/base/waitable_event.cc",
     "src/base/watchdog_posix.cc",
@@ -6711,13 +5835,10 @@
   srcs: [
     "src/base/circular_queue_unittest.cc",
     "src/base/flat_set_unittest.cc",
-    "src/base/getopt_compat_unittest.cc",
-    "src/base/logging_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/periodic_task_unittest.cc",
     "src/base/scoped_file_unittest.cc",
     "src/base/string_splitter_unittest.cc",
     "src/base/string_utils_unittest.cc",
@@ -6732,7 +5853,6 @@
     "src/base/unix_socket_unittest.cc",
     "src/base/utils_unittest.cc",
     "src/base/uuid_unittest.cc",
-    "src/base/watchdog_posix_unittest.cc",
     "src/base/watchdog_unittest.cc",
     "src/base/weak_ptr_unittest.cc",
   ],
@@ -6746,21 +5866,6 @@
   ],
 }
 
-// GN: //src/base:version_gen_h
-genrule {
-  name: "perfetto_src_base_version_gen_h",
-  srcs: [
-    "CHANGELOG",
-  ],
-  cmd: "python3 $(location tools/write_version_header.py) --no_git --changelog=$(location CHANGELOG) --cpp_out=$(out)",
-  out: [
-    "perfetto_version.gen.h",
-  ],
-  tool_files: [
-    "tools/write_version_header.py",
-  ],
-}
-
 // GN: //src/ipc:client
 filegroup {
   name: "perfetto_src_ipc_client",
@@ -6788,11 +5893,6 @@
   ],
 }
 
-// GN: //src/ipc:perfetto_ipc
-filegroup {
-  name: "perfetto_src_ipc_perfetto_ipc",
-}
-
 // GN: //src/ipc:test_messages_cpp
 genrule {
   name: "perfetto_src_ipc_test_messages_cpp_gen",
@@ -6893,37 +5993,9 @@
   ],
 }
 
-// GN: //src/kallsyms:kallsyms
+// GN: //src/perfetto_cmd:perfetto_atoms
 filegroup {
-  name: "perfetto_src_kallsyms_kallsyms",
-  srcs: [
-    "src/kallsyms/kernel_symbol_map.cc",
-    "src/kallsyms/lazy_kernel_symbolizer.cc",
-  ],
-}
-
-// GN: //src/kallsyms:unittests
-filegroup {
-  name: "perfetto_src_kallsyms_unittests",
-  srcs: [
-    "src/kallsyms/kernel_symbol_map_unittest.cc",
-    "src/kallsyms/lazy_kernel_symbolizer_unittest.cc",
-  ],
-}
-
-// GN: //src/perfetto_cmd:gen_cc_config_descriptor
-genrule {
-  name: "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
-  srcs: [
-    ":perfetto_protos_perfetto_config_perfetto_config_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/perfetto_cmd/perfetto_config.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
+  name: "perfetto_src_perfetto_cmd_perfetto_atoms",
 }
 
 // GN: //src/perfetto_cmd:perfetto_cmd
@@ -7031,30 +6103,12 @@
   ],
 }
 
-// GN: //src/profiling/common:producer_support
-filegroup {
-  name: "perfetto_src_profiling_common_producer_support",
-  srcs: [
-    "src/profiling/common/producer_support.cc",
-  ],
-}
-
-// GN: //src/profiling/common:profiler_guardrails
-filegroup {
-  name: "perfetto_src_profiling_common_profiler_guardrails",
-  srcs: [
-    "src/profiling/common/profiler_guardrails.cc",
-  ],
-}
-
 // GN: //src/profiling/common:unittests
 filegroup {
   name: "perfetto_src_profiling_common_unittests",
   srcs: [
     "src/profiling/common/interner_unittest.cc",
     "src/profiling/common/proc_utils_unittest.cc",
-    "src/profiling/common/producer_support_unittest.cc",
-    "src/profiling/common/profiler_guardrails_unittest.cc",
   ],
 }
 
@@ -7074,33 +6128,11 @@
   ],
 }
 
-// GN: //src/profiling/memory:bionic_libc_platform_headers_on_android
-filegroup {
-  name: "perfetto_src_profiling_memory_bionic_libc_platform_headers_on_android",
-}
-
 // GN: //src/profiling/memory:client
 filegroup {
   name: "perfetto_src_profiling_memory_client",
   srcs: [
     "src/profiling/memory/client.cc",
-    "src/profiling/memory/sampler.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:client_api
-filegroup {
-  name: "perfetto_src_profiling_memory_client_api",
-  srcs: [
-    "src/profiling/memory/client_api.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:client_api_standalone
-filegroup {
-  name: "perfetto_src_profiling_memory_client_api_standalone",
-  srcs: [
-    "src/profiling/memory/client_api_factory_standalone.cc",
   ],
 }
 
@@ -7112,7 +6144,7 @@
     "src/profiling/memory/bookkeeping_dump.cc",
     "src/profiling/memory/heapprofd_producer.cc",
     "src/profiling/memory/java_hprof_producer.cc",
-    "src/profiling/memory/log_histogram.cc",
+    "src/profiling/memory/page_idle_checker.cc",
     "src/profiling/memory/system_property.cc",
     "src/profiling/memory/unwinding.cc",
   ],
@@ -7126,11 +6158,11 @@
   ],
 }
 
-// GN: //src/profiling/memory:malloc_interceptor_bionic_hooks
+// GN: //src/profiling/memory:malloc_hooks
 filegroup {
-  name: "perfetto_src_profiling_memory_malloc_interceptor_bionic_hooks",
+  name: "perfetto_src_profiling_memory_malloc_hooks",
   srcs: [
-    "src/profiling/memory/malloc_interceptor_bionic_hooks.cc",
+    "src/profiling/memory/malloc_hooks.cc",
   ],
 }
 
@@ -7165,6 +6197,7 @@
     "src/profiling/memory/bookkeeping_unittest.cc",
     "src/profiling/memory/client_unittest.cc",
     "src/profiling/memory/heapprofd_producer_unittest.cc",
+    "src/profiling/memory/page_idle_checker_unittest.cc",
     "src/profiling/memory/parse_smaps_unittest.cc",
     "src/profiling/memory/sampler_unittest.cc",
     "src/profiling/memory/system_property_unittest.cc",
@@ -7181,14 +6214,6 @@
   ],
 }
 
-// GN: //src/profiling/memory:wrap_allocators
-filegroup {
-  name: "perfetto_src_profiling_memory_wrap_allocators",
-  srcs: [
-    "src/profiling/memory/wrap_allocators.cc",
-  ],
-}
-
 // GN: //src/profiling/perf:common_types
 filegroup {
   name: "perfetto_src_profiling_perf_common_types",
@@ -7257,25 +6282,11 @@
 filegroup {
   name: "perfetto_src_profiling_symbolizer_symbolizer",
   srcs: [
-    "src/profiling/symbolizer/filesystem_posix.cc",
-    "src/profiling/symbolizer/filesystem_windows.cc",
     "src/profiling/symbolizer/local_symbolizer.cc",
-    "src/profiling/symbolizer/scoped_read_mmap_posix.cc",
-    "src/profiling/symbolizer/scoped_read_mmap_windows.cc",
-    "src/profiling/symbolizer/subprocess_posix.cc",
-    "src/profiling/symbolizer/subprocess_windows.cc",
     "src/profiling/symbolizer/symbolizer.cc",
   ],
 }
 
-// GN: //src/profiling/symbolizer:unittests
-filegroup {
-  name: "perfetto_src_profiling_symbolizer_unittests",
-  srcs: [
-    "src/profiling/symbolizer/local_symbolizer_unittest.cc",
-  ],
-}
-
 // GN: //src/profiling:unittests
 filegroup {
   name: "perfetto_src_profiling_unittests",
@@ -7284,55 +6295,6 @@
   ],
 }
 
-// GN: //src/protozero/filtering:bytecode_common
-filegroup {
-  name: "perfetto_src_protozero_filtering_bytecode_common",
-}
-
-// GN: //src/protozero/filtering:bytecode_generator
-filegroup {
-  name: "perfetto_src_protozero_filtering_bytecode_generator",
-  srcs: [
-    "src/protozero/filtering/filter_bytecode_generator.cc",
-  ],
-}
-
-// GN: //src/protozero/filtering:bytecode_parser
-filegroup {
-  name: "perfetto_src_protozero_filtering_bytecode_parser",
-  srcs: [
-    "src/protozero/filtering/filter_bytecode_parser.cc",
-  ],
-}
-
-// GN: //src/protozero/filtering:filter_util
-filegroup {
-  name: "perfetto_src_protozero_filtering_filter_util",
-  srcs: [
-    "src/protozero/filtering/filter_util.cc",
-  ],
-}
-
-// GN: //src/protozero/filtering:message_filter
-filegroup {
-  name: "perfetto_src_protozero_filtering_message_filter",
-  srcs: [
-    "src/protozero/filtering/message_filter.cc",
-  ],
-}
-
-// GN: //src/protozero/filtering:unittests
-filegroup {
-  name: "perfetto_src_protozero_filtering_unittests",
-  srcs: [
-    "src/protozero/filtering/filter_bytecode_generator_unittest.cc",
-    "src/protozero/filtering/filter_bytecode_parser_unittest.cc",
-    "src/protozero/filtering/filter_util_unittest.cc",
-    "src/protozero/filtering/message_filter_unittest.cc",
-    "src/protozero/filtering/message_tokenizer_unittest.cc",
-  ],
-}
-
 // GN: //src/protozero/protoc_plugin:cppgen_plugin
 cc_binary_host {
   name: "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
@@ -7345,9 +6307,6 @@
   static_libs: [
     "libprotoc",
   ],
-  generated_headers: [
-    "perfetto_src_base_version_gen_h",
-  ],
   defaults: [
     "perfetto_defaults",
   ],
@@ -7363,7 +6322,6 @@
   srcs: [
     "src/protozero/field.cc",
     "src/protozero/message.cc",
-    "src/protozero/message_arena.cc",
     "src/protozero/message_handle.cc",
     "src/protozero/packed_repeated_fields.cc",
     "src/protozero/proto_decoder.cc",
@@ -7375,30 +6333,10 @@
   ],
 }
 
-// GN: //src/protozero:test_messages_descriptor
-genrule {
-  name: "perfetto_src_protozero_test_messages_descriptor",
-  srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
-    "src/protozero/test/example_proto/library.proto",
-    "src/protozero/test/example_proto/library_internals/galaxies.proto",
-    "src/protozero/test/example_proto/test_messages.proto",
-    "src/protozero/test/example_proto/upper_import.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
-  out: [
-    "perfetto_src_protozero_test_messages_descriptor.bin",
-  ],
-}
-
 // GN: //src/protozero:testing_messages_cpp
 genrule {
   name: "perfetto_src_protozero_testing_messages_cpp_gen",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7410,7 +6348,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.gen.cc",
     "external/perfetto/src/protozero/test/example_proto/library.gen.cc",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.gen.cc",
     "external/perfetto/src/protozero/test/example_proto/test_messages.gen.cc",
@@ -7422,7 +6359,6 @@
 genrule {
   name: "perfetto_src_protozero_testing_messages_cpp_gen_headers",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7434,7 +6370,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.gen.h",
     "external/perfetto/src/protozero/test/example_proto/library.gen.h",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.gen.h",
     "external/perfetto/src/protozero/test/example_proto/test_messages.gen.h",
@@ -7450,7 +6385,6 @@
 genrule {
   name: "perfetto_src_protozero_testing_messages_lite_gen",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7461,7 +6395,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.pb.cc",
     "external/perfetto/src/protozero/test/example_proto/library.pb.cc",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.cc",
     "external/perfetto/src/protozero/test/example_proto/test_messages.pb.cc",
@@ -7473,7 +6406,6 @@
 genrule {
   name: "perfetto_src_protozero_testing_messages_lite_gen_headers",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7484,7 +6416,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.pb.h",
     "external/perfetto/src/protozero/test/example_proto/library.pb.h",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.h",
     "external/perfetto/src/protozero/test/example_proto/test_messages.pb.h",
@@ -7500,7 +6431,6 @@
 genrule {
   name: "perfetto_src_protozero_testing_messages_zero_gen",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7512,7 +6442,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.pbzero.cc",
     "external/perfetto/src/protozero/test/example_proto/library.pbzero.cc",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pbzero.cc",
     "external/perfetto/src/protozero/test/example_proto/test_messages.pbzero.cc",
@@ -7524,7 +6453,6 @@
 genrule {
   name: "perfetto_src_protozero_testing_messages_zero_gen_headers",
   srcs: [
-    "src/protozero/test/example_proto/extensions.proto",
     "src/protozero/test/example_proto/library.proto",
     "src/protozero/test/example_proto/library_internals/galaxies.proto",
     "src/protozero/test/example_proto/test_messages.proto",
@@ -7536,7 +6464,6 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/src/protozero/test/example_proto/extensions.pbzero.h",
     "external/perfetto/src/protozero/test/example_proto/library.pbzero.h",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pbzero.h",
     "external/perfetto/src/protozero/test/example_proto/test_messages.pbzero.h",
@@ -7596,9 +6523,9 @@
   ],
 }
 
-// GN: //src/trace_processor/db:db
+// GN: //src/trace_processor/db:lib
 filegroup {
-  name: "perfetto_src_trace_processor_db_db",
+  name: "perfetto_src_trace_processor_db_lib",
   srcs: [
     "src/trace_processor/db/column.cc",
     "src/trace_processor/db/table.cc",
@@ -7630,29 +6557,13 @@
   ],
 }
 
-// GN: //src/trace_processor:gen_cc_test_messages_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_gen_cc_test_messages_descriptor",
-  srcs: [
-    ":perfetto_src_protozero_test_messages_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/test_messages.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/importers/common:common
+// GN: //src/trace_processor/importers:common
 filegroup {
-  name: "perfetto_src_trace_processor_importers_common_common",
+  name: "perfetto_src_trace_processor_importers_common",
   srcs: [
     "src/trace_processor/importers/common/args_tracker.cc",
     "src/trace_processor/importers/common/clock_tracker.cc",
     "src/trace_processor/importers/common/event_tracker.cc",
-    "src/trace_processor/importers/common/flow_tracker.cc",
     "src/trace_processor/importers/common/global_args_tracker.cc",
     "src/trace_processor/importers/common/process_tracker.cc",
     "src/trace_processor/importers/common/slice_tracker.cc",
@@ -7661,90 +6572,25 @@
   ],
 }
 
-// GN: //src/trace_processor/importers/common:unittests
+// GN: //src/trace_processor/importers:unittests
 filegroup {
-  name: "perfetto_src_trace_processor_importers_common_unittests",
+  name: "perfetto_src_trace_processor_importers_unittests",
   srcs: [
     "src/trace_processor/importers/common/clock_tracker_unittest.cc",
     "src/trace_processor/importers/common/event_tracker_unittest.cc",
-    "src/trace_processor/importers/common/flow_tracker_unittest.cc",
     "src/trace_processor/importers/common/process_tracker_unittest.cc",
     "src/trace_processor/importers/common/slice_tracker_unittest.cc",
   ],
 }
 
-// GN: //src/trace_processor/importers:gen_cc_chrome_track_event_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-  srcs: [
-    ":perfetto_protos_third_party_chromium_chrome_track_event_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/importers/chrome_track_event.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/importers:gen_cc_config_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
-  srcs: [
-    ":perfetto_protos_perfetto_config_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/importers/config.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/importers:gen_cc_track_event_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
-  srcs: [
-    ":perfetto_protos_perfetto_trace_track_event_track_event_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/importers/track_event.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/importers/memory_tracker:graph_processor
-filegroup {
-  name: "perfetto_src_trace_processor_importers_memory_tracker_graph_processor",
-  srcs: [
-    "src/trace_processor/importers/memory_tracker/graph.cc",
-    "src/trace_processor/importers/memory_tracker/graph_processor.cc",
-    "src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc",
-    "src/trace_processor/importers/memory_tracker/raw_memory_graph_node.cc",
-    "src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc",
-  ],
-}
-
 // GN: //src/trace_processor:lib
 filegroup {
   name: "perfetto_src_trace_processor_lib",
   srcs: [
-    "src/trace_processor/dynamic/ancestor_generator.cc",
-    "src/trace_processor/dynamic/connected_flow_generator.cc",
-    "src/trace_processor/dynamic/descendant_slice_generator.cc",
     "src/trace_processor/dynamic/describe_slice_generator.cc",
-    "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
     "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
     "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
-    "src/trace_processor/dynamic/experimental_sched_upid_generator.cc",
     "src/trace_processor/dynamic/experimental_slice_layout_generator.cc",
-    "src/trace_processor/dynamic/thread_state_generator.cc",
-    "src/trace_processor/iterator_impl.cc",
     "src/trace_processor/read_trace.cc",
     "src/trace_processor/trace_processor.cc",
     "src/trace_processor/trace_processor_impl.cc",
@@ -7759,122 +6605,6 @@
   ],
 }
 
-// GN: //src/trace_processor/metrics:gen_cc_all_chrome_metrics_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-  srcs: [
-    ":perfetto_protos_perfetto_metrics_chrome_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/metrics/chrome/all_chrome_metrics.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/metrics:gen_cc_metrics_descriptor
-genrule {
-  name: "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
-  srcs: [
-    ":perfetto_protos_perfetto_metrics_descriptor",
-  ],
-  cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/metrics/metrics.descriptor.h",
-  ],
-  tool_files: [
-    "tools/gen_cc_proto_descriptor.py",
-  ],
-}
-
-// GN: //src/trace_processor/metrics:gen_merged_sql_metrics
-genrule {
-  name: "perfetto_src_trace_processor_metrics_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_cpu_raw_metrics_per_core.sql",
-    "src/trace_processor/metrics/android/android_dma_heap.sql",
-    "src/trace_processor/metrics/android/android_fastrpc.sql",
-    "src/trace_processor/metrics/android/android_gpu.sql",
-    "src/trace_processor/metrics/android/android_hwcomposer.sql",
-    "src/trace_processor/metrics/android/android_hwui_metric.sql",
-    "src/trace_processor/metrics/android/android_hwui_threads.sql",
-    "src/trace_processor/metrics/android/android_ion.sql",
-    "src/trace_processor/metrics/android/android_jank.sql",
-    "src/trace_processor/metrics/android/android_lmk.sql",
-    "src/trace_processor/metrics/android/android_lmk_reason.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_proxy_power.sql",
-    "src/trace_processor/metrics/android/android_startup.sql",
-    "src/trace_processor/metrics/android/android_startup_launches.sql",
-    "src/trace_processor/metrics/android/android_surfaceflinger.sql",
-    "src/trace_processor/metrics/android/android_sysui_cuj.sql",
-    "src/trace_processor/metrics/android/android_task_names.sql",
-    "src/trace_processor/metrics/android/android_thread_time_in_state.sql",
-    "src/trace_processor/metrics/android/composer_execution.sql",
-    "src/trace_processor/metrics/android/composition_layers.sql",
-    "src/trace_processor/metrics/android/cpu_info.sql",
-    "src/trace_processor/metrics/android/display_metrics.sql",
-    "src/trace_processor/metrics/android/frame_missed.sql",
-    "src/trace_processor/metrics/android/g2d.sql",
-    "src/trace_processor/metrics/android/g2d_duration.sql",
-    "src/trace_processor/metrics/android/global_counter_span_view.sql",
-    "src/trace_processor/metrics/android/hsc_startups.sql",
-    "src/trace_processor/metrics/android/java_heap_histogram.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/power_drain_in_watts.sql",
-    "src/trace_processor/metrics/android/power_profile_data.sql",
-    "src/trace_processor/metrics/android/process_counter_span_view.sql",
-    "src/trace_processor/metrics/android/process_mem.sql",
-    "src/trace_processor/metrics/android/process_metadata.sql",
-    "src/trace_processor/metrics/android/process_oom_score.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/chrome/actual_power_by_category.sql",
-    "src/trace_processor/metrics/chrome/actual_power_by_rail_mode.sql",
-    "src/trace_processor/metrics/chrome/chrome_event_metadata.sql",
-    "src/trace_processor/metrics/chrome/chrome_processes.sql",
-    "src/trace_processor/metrics/chrome/chrome_thread_slice_with_cpu_time.sql",
-    "src/trace_processor/metrics/chrome/cpu_time_by_category.sql",
-    "src/trace_processor/metrics/chrome/cpu_time_by_rail_mode.sql",
-    "src/trace_processor/metrics/chrome/estimated_power_by_category.sql",
-    "src/trace_processor/metrics/chrome/estimated_power_by_rail_mode.sql",
-    "src/trace_processor/metrics/chrome/rail_modes.sql",
-    "src/trace_processor/metrics/chrome/scroll_flow_event.sql",
-    "src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank_cause.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_task.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_touch_move.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql",
-    "src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql",
-    "src/trace_processor/metrics/chrome/test_chrome_metric.sql",
-    "src/trace_processor/metrics/experimental/blink_gc_metric.sql",
-    "src/trace_processor/metrics/experimental/frame_times.sql",
-    "src/trace_processor/metrics/experimental/media_metric.sql",
-    "src/trace_processor/metrics/experimental/reported_by_page.sql",
-    "src/trace_processor/metrics/trace_metadata.sql",
-    "src/trace_processor/metrics/trace_stats.sql",
-    "src/trace_processor/metrics/webview/webview_power_usage.sql",
-  ],
-  cmd: "$(location tools/gen_merged_sql_metrics.py) --cpp_out=$(out) $(in)",
-  out: [
-    "src/trace_processor/metrics/sql_metrics.h",
-  ],
-  tool_files: [
-    "tools/gen_merged_sql_metrics.py",
-  ],
-}
-
 // GN: //src/trace_processor/metrics:lib
 filegroup {
   name: "perfetto_src_trace_processor_metrics_lib",
@@ -7891,25 +6621,6 @@
   ],
 }
 
-// GN: //src/trace_processor/rpc:rpc
-filegroup {
-  name: "perfetto_src_trace_processor_rpc_rpc",
-  srcs: [
-    "src/trace_processor/rpc/proto_ring_buffer.cc",
-    "src/trace_processor/rpc/query_result_serializer.cc",
-    "src/trace_processor/rpc/rpc.cc",
-  ],
-}
-
-// GN: //src/trace_processor/rpc:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_rpc_unittests",
-  srcs: [
-    "src/trace_processor/rpc/proto_ring_buffer_unittest.cc",
-    "src/trace_processor/rpc/query_result_serializer_unittest.cc",
-  ],
-}
-
 // GN: //src/trace_processor/sqlite:sqlite
 filegroup {
   name: "perfetto_src_trace_processor_sqlite_sqlite",
@@ -7934,7 +6645,6 @@
     "src/trace_processor/sqlite/query_constraints_unittest.cc",
     "src/trace_processor/sqlite/span_join_operator_table_unittest.cc",
     "src/trace_processor/sqlite/sqlite3_str_split_unittest.cc",
-    "src/trace_processor/sqlite/sqlite_utils_unittest.cc",
   ],
 }
 
@@ -7960,7 +6670,6 @@
     "src/trace_processor/importers/proto/android_probes_module.cc",
     "src/trace_processor/importers/proto/android_probes_parser.cc",
     "src/trace_processor/importers/proto/android_probes_tracker.cc",
-    "src/trace_processor/importers/proto/frame_timeline_event_parser.cc",
     "src/trace_processor/importers/proto/gpu_event_parser.cc",
     "src/trace_processor/importers/proto/graphics_event_module.cc",
     "src/trace_processor/importers/proto/graphics_frame_event_parser.cc",
@@ -7987,29 +6696,20 @@
     "src/trace_processor/importers/gzip/gzip_utils.cc",
     "src/trace_processor/importers/json/json_utils.cc",
     "src/trace_processor/importers/ninja/ninja_log_parser.cc",
-    "src/trace_processor/importers/proto/async_track_set_tracker.cc",
-    "src/trace_processor/importers/proto/chrome_string_lookup.cc",
-    "src/trace_processor/importers/proto/chrome_system_probes_module.cc",
-    "src/trace_processor/importers/proto/chrome_system_probes_parser.cc",
+    "src/trace_processor/importers/proto/args_table_utils.cc",
     "src/trace_processor/importers/proto/heap_profile_tracker.cc",
-    "src/trace_processor/importers/proto/memory_tracker_snapshot_module.cc",
-    "src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc",
-    "src/trace_processor/importers/proto/metadata_module.cc",
     "src/trace_processor/importers/proto/metadata_tracker.cc",
     "src/trace_processor/importers/proto/packet_sequence_state.cc",
     "src/trace_processor/importers/proto/perf_sample_tracker.cc",
     "src/trace_processor/importers/proto/profile_module.cc",
     "src/trace_processor/importers/proto/profile_packet_utils.cc",
-    "src/trace_processor/importers/proto/profiler_util.cc",
     "src/trace_processor/importers/proto/proto_importer_module.cc",
     "src/trace_processor/importers/proto/proto_trace_parser.cc",
-    "src/trace_processor/importers/proto/proto_trace_reader.cc",
     "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
     "src/trace_processor/importers/proto/stack_profile_tracker.cc",
     "src/trace_processor/importers/proto/track_event_module.cc",
     "src/trace_processor/importers/proto/track_event_parser.cc",
     "src/trace_processor/importers/proto/track_event_tokenizer.cc",
-    "src/trace_processor/importers/proto/track_event_tracker.cc",
     "src/trace_processor/trace_processor_context.cc",
     "src/trace_processor/trace_processor_storage.cc",
     "src/trace_processor/trace_processor_storage_impl.cc",
@@ -8042,6 +6742,11 @@
   ],
 }
 
+// GN: //src/trace_processor:track_event_descriptor
+filegroup {
+  name: "perfetto_src_trace_processor_track_event_descriptor",
+}
+
 // GN: //src/trace_processor/types:types
 filegroup {
   name: "perfetto_src_trace_processor_types_types",
@@ -8067,17 +6772,12 @@
   srcs: [
     "src/trace_processor/dynamic/experimental_counter_dur_generator_unittest.cc",
     "src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc",
-    "src/trace_processor/dynamic/thread_state_generator_unittest.cc",
     "src/trace_processor/forwarding_trace_parser_unittest.cc",
     "src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc",
     "src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc",
-    "src/trace_processor/importers/memory_tracker/graph_processor_unittest.cc",
-    "src/trace_processor/importers/memory_tracker/graph_unittest.cc",
-    "src/trace_processor/importers/memory_tracker/raw_process_memory_node_unittest.cc",
-    "src/trace_processor/importers/proto/async_track_set_tracker_unittest.cc",
+    "src/trace_processor/importers/proto/args_table_utils_unittest.cc",
     "src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc",
     "src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc",
-    "src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc",
     "src/trace_processor/importers/proto/proto_trace_parser_unittest.cc",
     "src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc",
     "src/trace_processor/importers/systrace/systrace_parser_unittest.cc",
@@ -8093,14 +6793,6 @@
   ],
 }
 
-// GN: //src/trace_processor/util:proto_to_args_parser
-filegroup {
-  name: "perfetto_src_trace_processor_util_proto_to_args_parser",
-  srcs: [
-    "src/trace_processor/util/proto_to_args_parser.cc",
-  ],
-}
-
 // GN: //src/trace_processor/util:protozero_to_text
 filegroup {
   name: "perfetto_src_trace_processor_util_protozero_to_text",
@@ -8113,7 +6805,6 @@
 filegroup {
   name: "perfetto_src_trace_processor_util_unittests",
   srcs: [
-    "src/trace_processor/util/proto_to_args_parser_unittest.cc",
     "src/trace_processor/util/protozero_to_text_unittests.cc",
   ],
 }
@@ -8197,19 +6888,11 @@
   ],
 }
 
-// GN: //src/traced/probes/ftrace/format_parser:format_parser
+// GN: //src/traced/probes/ftrace:format_parser
 filegroup {
-  name: "perfetto_src_traced_probes_ftrace_format_parser_format_parser",
+  name: "perfetto_src_traced_probes_ftrace_format_parser",
   srcs: [
-    "src/traced/probes/ftrace/format_parser/format_parser.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace/format_parser:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_format_parser_unittests",
-  srcs: [
-    "src/traced/probes/ftrace/format_parser/format_parser_unittest.cc",
+    "src/traced/probes/ftrace/format_parser.cc",
   ],
 }
 
@@ -8229,17 +6912,9 @@
     "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_stats.cc",
-    "src/traced/probes/ftrace/printk_formats_parser.cc",
-    "src/traced/probes/ftrace/proto_translation_table.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:ftrace_procfs
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_ftrace_procfs",
-  srcs: [
     "src/traced/probes/ftrace/ftrace_procfs.cc",
+    "src/traced/probes/ftrace/ftrace_stats.cc",
+    "src/traced/probes/ftrace/proto_translation_table.cc",
   ],
 }
 
@@ -8251,6 +6926,22 @@
   ],
 }
 
+// GN: //src/traced/probes/ftrace/kallsyms:kallsyms
+filegroup {
+  name: "perfetto_src_traced_probes_ftrace_kallsyms_kallsyms",
+  srcs: [
+    "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc",
+  ],
+}
+
+// GN: //src/traced/probes/ftrace/kallsyms:unittests
+filegroup {
+  name: "perfetto_src_traced_probes_ftrace_kallsyms_unittests",
+  srcs: [
+    "src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc",
+  ],
+}
+
 // GN: //src/traced/probes/ftrace:test_messages_cpp
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
@@ -8373,11 +7064,11 @@
     "src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
     "src/traced/probes/ftrace/discover_vendor_tracepoints_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/printk_formats_parser_unittest.cc",
     "src/traced/probes/ftrace/proto_translation_table_unittest.cc",
   ],
 }
@@ -8414,19 +7105,11 @@
   ],
 }
 
-// GN: //src/traced/probes/packages_list:packages_list_parser
-filegroup {
-  name: "perfetto_src_traced_probes_packages_list_packages_list_parser",
-  srcs: [
-    "src/traced/probes/packages_list/packages_list_parser.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_unittest.cc",
+    "src/traced/probes/packages_list/packages_list_data_source_unittest.cc",
   ],
 }
 
@@ -8450,7 +7133,6 @@
 filegroup {
   name: "perfetto_src_traced_probes_probes_src",
   srcs: [
-    "src/traced/probes/kmem_activity_trigger.cc",
     "src/traced/probes/probes_producer.cc",
   ],
 }
@@ -8529,26 +7211,16 @@
 filegroup {
   name: "perfetto_src_tracing_client_api_without_backends",
   srcs: [
-    "src/tracing/console_interceptor.cc",
     "src/tracing/data_source.cc",
     "src/tracing/debug_annotation.cc",
     "src/tracing/event_context.cc",
-    "src/tracing/interceptor.cc",
-    "src/tracing/internal/checked_scope.cc",
-    "src/tracing/internal/interceptor_trace_writer.cc",
-    "src/tracing/internal/tracing_backend_fake.cc",
-    "src/tracing/internal/tracing_muxer_fake.cc",
     "src/tracing/internal/tracing_muxer_impl.cc",
     "src/tracing/internal/track_event_internal.cc",
-    "src/tracing/internal/track_event_interned_fields.cc",
     "src/tracing/platform.cc",
-    "src/tracing/traced_value.cc",
     "src/tracing/tracing.cc",
-    "src/tracing/tracing_policy.cc",
     "src/tracing/track.cc",
     "src/tracing/track_event_category_registry.cc",
     "src/tracing/track_event_legacy.cc",
-    "src/tracing/track_event_state_tracker.cc",
     "src/tracing/virtual_destructors.cc",
   ],
 }
@@ -8671,9 +7343,9 @@
   ],
 }
 
-// GN: //src/tracing:platform_impl
+// GN: //src/tracing:platform_posix
 filegroup {
-  name: "perfetto_src_tracing_platform_impl",
+  name: "perfetto_src_tracing_platform_posix",
   srcs: [
     "src/tracing/platform_posix.cc",
   ],
@@ -8714,7 +7386,6 @@
     "src/tracing/test/mock_consumer.cc",
     "src/tracing/test/mock_producer.cc",
     "src/tracing/test/test_shared_memory.cc",
-    "src/tracing/test/traced_value_test_support.cc",
   ],
 }
 
@@ -8722,20 +7393,10 @@
 filegroup {
   name: "perfetto_src_tracing_test_tracing_integration_test",
   srcs: [
-    "src/tracing/test/platform_unittest.cc",
     "src/tracing/test/tracing_integration_test.cc",
   ],
 }
 
-// GN: //src/tracing:unittests
-filegroup {
-  name: "perfetto_src_tracing_unittests",
-  srcs: [
-    "src/tracing/traced_proto_unittest.cc",
-    "src/tracing/traced_value_unittest.cc",
-  ],
-}
-
 // GN: //test:end_to_end_integrationtests
 filegroup {
   name: "perfetto_test_end_to_end_integrationtests",
@@ -8748,7 +7409,6 @@
 filegroup {
   name: "perfetto_test_test_helper",
   srcs: [
-    "test/android_test_utils.cc",
     "test/fake_producer.cc",
     "test/test_helper.cc",
   ],
@@ -8769,7 +7429,6 @@
     "tools/trace_to_text/deobfuscate_profile.cc",
     "tools/trace_to_text/main.cc",
     "tools/trace_to_text/symbolize_profile.cc",
-    "tools/trace_to_text/trace_to_hprof.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",
@@ -8810,7 +7469,6 @@
     ":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_interceptors_lite_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
     ":perfetto_protos_perfetto_config_power_lite_gen",
     ":perfetto_protos_perfetto_config_process_stats_lite_gen",
@@ -8837,13 +7495,16 @@
     "libprotobuf-cpp-lite",
   ],
   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_interceptors_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",
@@ -8872,7 +7533,6 @@
     "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_interceptors_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",
@@ -8904,10 +7564,9 @@
   ],
   apex_available: [
     "//apex_available:platform",
-    "com.android.art",
     "com.android.art.debug",
+    "com.android.art.release",
   ],
-  min_sdk_version: "S",
 }
 
 // GN: //:perfetto_unittests
@@ -8918,14 +7577,13 @@
     ":perfetto_include_perfetto_ext_base_base",
     ":perfetto_include_perfetto_ext_ipc_ipc",
     ":perfetto_include_perfetto_ext_trace_processor_export_json",
-    ":perfetto_include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
     ":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_deobfuscator",
     ":perfetto_include_perfetto_profiling_normalize",
     ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_test_test_support",
     ":perfetto_include_perfetto_trace_processor_basic_types",
     ":perfetto_include_perfetto_trace_processor_storage",
     ":perfetto_include_perfetto_trace_processor_trace_processor",
@@ -8933,95 +7591,65 @@
     ":perfetto_include_perfetto_tracing_core_forward_decls",
     ":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_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_lite_gen",
-    ":perfetto_protos_perfetto_config_interceptors_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_track_event_cpp_gen",
-    ":perfetto_protos_perfetto_config_track_event_lite_gen",
     ":perfetto_protos_perfetto_config_track_event_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_cpp_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
     ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_metrics_android_zero_gen",
+    ":perfetto_protos_perfetto_metrics_zero_gen",
     ":perfetto_protos_perfetto_trace_android_cpp_gen",
-    ":perfetto_protos_perfetto_trace_android_lite_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
-    ":perfetto_protos_perfetto_trace_chrome_lite_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
-    ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
-    ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
     ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_cpp_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_processor_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_trace_profiling_lite_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_cpp_gen",
-    ":perfetto_protos_perfetto_trace_ps_lite_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_system_info_cpp_gen",
-    ":perfetto_protos_perfetto_trace_system_info_lite_gen",
     ":perfetto_protos_perfetto_trace_system_info_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
-    ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_test_support",
     ":perfetto_src_base_unittests",
@@ -9032,8 +7660,7 @@
     ":perfetto_src_ipc_test_messages_cpp_gen",
     ":perfetto_src_ipc_test_messages_ipc_gen",
     ":perfetto_src_ipc_unittests",
-    ":perfetto_src_kallsyms_kallsyms",
-    ":perfetto_src_kallsyms_unittests",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
     ":perfetto_src_perfetto_cmd_perfetto_cmd",
     ":perfetto_src_perfetto_cmd_protos_gen",
     ":perfetto_src_perfetto_cmd_trigger_producer",
@@ -9042,8 +7669,6 @@
     ":perfetto_src_profiling_common_interner",
     ":perfetto_src_profiling_common_interning_output",
     ":perfetto_src_profiling_common_proc_utils",
-    ":perfetto_src_profiling_common_producer_support",
-    ":perfetto_src_profiling_common_profiler_guardrails",
     ":perfetto_src_profiling_common_unittests",
     ":perfetto_src_profiling_common_unwind_support",
     ":perfetto_src_profiling_deobfuscator",
@@ -9060,15 +7685,7 @@
     ":perfetto_src_profiling_perf_producer_unittests",
     ":perfetto_src_profiling_perf_regs_parsing",
     ":perfetto_src_profiling_perf_unwinding",
-    ":perfetto_src_profiling_symbolizer_symbolizer",
-    ":perfetto_src_profiling_symbolizer_unittests",
     ":perfetto_src_profiling_unittests",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_generator",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_filter_util",
-    ":perfetto_src_protozero_filtering_message_filter",
-    ":perfetto_src_protozero_filtering_unittests",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_protozero_testing_messages_cpp_gen",
     ":perfetto_src_protozero_testing_messages_lite_gen",
@@ -9077,19 +7694,16 @@
     ":perfetto_src_trace_processor_analysis_analysis",
     ":perfetto_src_trace_processor_containers_containers",
     ":perfetto_src_trace_processor_containers_unittests",
-    ":perfetto_src_trace_processor_db_db",
+    ":perfetto_src_trace_processor_db_lib",
     ":perfetto_src_trace_processor_db_unittests",
     ":perfetto_src_trace_processor_export_json",
     ":perfetto_src_trace_processor_ftrace_descriptors",
-    ":perfetto_src_trace_processor_importers_common_common",
-    ":perfetto_src_trace_processor_importers_common_unittests",
-    ":perfetto_src_trace_processor_importers_memory_tracker_graph_processor",
+    ":perfetto_src_trace_processor_importers_common",
+    ":perfetto_src_trace_processor_importers_unittests",
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metatrace",
     ":perfetto_src_trace_processor_metrics_lib",
     ":perfetto_src_trace_processor_metrics_unittests",
-    ":perfetto_src_trace_processor_rpc_rpc",
-    ":perfetto_src_trace_processor_rpc_unittests",
     ":perfetto_src_trace_processor_sqlite_sqlite",
     ":perfetto_src_trace_processor_sqlite_unittests",
     ":perfetto_src_trace_processor_storage_full",
@@ -9097,11 +7711,11 @@
     ":perfetto_src_trace_processor_storage_storage",
     ":perfetto_src_trace_processor_tables_tables",
     ":perfetto_src_trace_processor_tables_unittests",
+    ":perfetto_src_trace_processor_track_event_descriptor",
     ":perfetto_src_trace_processor_types_types",
     ":perfetto_src_trace_processor_types_unittests",
     ":perfetto_src_trace_processor_unittests",
     ":perfetto_src_trace_processor_util_descriptors",
-    ":perfetto_src_trace_processor_util_proto_to_args_parser",
     ":perfetto_src_trace_processor_util_protozero_to_text",
     ":perfetto_src_trace_processor_util_unittests",
     ":perfetto_src_trace_processor_util_util",
@@ -9113,10 +7727,10 @@
     ":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_format_parser",
-    ":perfetto_src_traced_probes_ftrace_format_parser_unittests",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
+    ":perfetto_src_traced_probes_ftrace_kallsyms_kallsyms",
+    ":perfetto_src_traced_probes_ftrace_kallsyms_unittests",
     ":perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
@@ -9126,7 +7740,6 @@
     ":perfetto_src_traced_probes_initial_display_state_unittests",
     ":perfetto_src_traced_probes_metatrace_metatrace",
     ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_traced_probes_packages_list_unittests",
     ":perfetto_src_traced_probes_power_power",
     ":perfetto_src_traced_probes_probes_src",
@@ -9139,7 +7752,6 @@
     ":perfetto_src_traced_probes_unittests",
     ":perfetto_src_traced_service_service",
     ":perfetto_src_traced_service_unittests",
-    ":perfetto_src_tracing_client_api_without_backends",
     ":perfetto_src_tracing_common",
     ":perfetto_src_tracing_core_core",
     ":perfetto_src_tracing_core_service",
@@ -9150,22 +7762,16 @@
     ":perfetto_src_tracing_ipc_producer_producer",
     ":perfetto_src_tracing_ipc_service_service",
     ":perfetto_src_tracing_ipc_unittests",
-    ":perfetto_src_tracing_platform_impl",
     ":perfetto_src_tracing_test_test_support",
     ":perfetto_src_tracing_test_tracing_integration_test",
-    ":perfetto_src_tracing_unittests",
     ":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
   ],
   shared_libs: [
-    "libandroidicu",
     "libbase",
     "liblog",
     "libprocinfo",
-    "libprotobuf-cpp-full",
     "libprotobuf-cpp-lite",
-    "libsqlite",
     "libunwindstack",
-    "libutils",
     "libz",
   ],
   static_libs: [
@@ -9176,107 +7782,71 @@
     "perfetto_gtest_logcat_printer",
   ],
   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_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_lite_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_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_track_event_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_cpp_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
     "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
+    "perfetto_protos_perfetto_metrics_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_cpp_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_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_cpp_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_processor_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_system_info_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_system_info_lite_gen_headers",
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
     "perfetto_src_ipc_test_messages_cpp_gen_headers",
     "perfetto_src_ipc_test_messages_ipc_gen_headers",
-    "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
     "perfetto_src_protozero_testing_messages_cpp_gen_headers",
     "perfetto_src_protozero_testing_messages_lite_gen_headers",
     "perfetto_src_protozero_testing_messages_zero_gen_headers",
-    "perfetto_src_trace_processor_gen_cc_test_messages_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_merged_sql_metrics",
     "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
     "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
     "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
@@ -9292,13 +7862,25 @@
   include_dirs: [
     "bionic/libc/kernel",
   ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
   data: [
     "src/traced/probes/filesystem/testdata/**/*",
     "src/traced/probes/ftrace/test/data/**/*",
   ],
+  target: {
+    android: {
+      shared_libs: [
+        "libandroidicu",
+        "liblog",
+        "libsqlite",
+        "libutils",
+      ],
+    },
+    host: {
+      static_libs: [
+        "libsqlite",
+      ],
+    },
+  },
 }
 
 // GN: //src/protozero/protoc_plugin:protozero_plugin
@@ -9313,9 +7895,6 @@
   static_libs: [
     "libprotoc",
   ],
-  generated_headers: [
-    "perfetto_src_base_version_gen_h",
-  ],
   defaults: [
     "perfetto_defaults",
   ],
@@ -9326,13 +7905,12 @@
 }
 
 // GN: //src/trace_processor:trace_processor_shell
-cc_binary {
+cc_binary_host {
   name: "trace_processor_shell",
   srcs: [
     ":perfetto_include_perfetto_base_base",
     ":perfetto_include_perfetto_ext_base_base",
     ":perfetto_include_perfetto_ext_trace_processor_export_json",
-    ":perfetto_include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
     ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
     ":perfetto_include_perfetto_protozero_protozero",
     ":perfetto_include_perfetto_trace_processor_basic_types",
@@ -9343,13 +7921,14 @@
     ":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_interceptors_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_track_event_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",
@@ -9361,24 +7940,21 @@
     ":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_processor_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_system_info_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_base_base",
-    ":perfetto_src_profiling_deobfuscator",
     ":perfetto_src_profiling_symbolizer_symbolize_database",
     ":perfetto_src_profiling_symbolizer_symbolizer",
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_trace_processor_analysis_analysis",
     ":perfetto_src_trace_processor_containers_containers",
-    ":perfetto_src_trace_processor_db_db",
+    ":perfetto_src_trace_processor_db_lib",
     ":perfetto_src_trace_processor_export_json",
     ":perfetto_src_trace_processor_ftrace_descriptors",
-    ":perfetto_src_trace_processor_importers_common_common",
-    ":perfetto_src_trace_processor_importers_memory_tracker_graph_processor",
+    ":perfetto_src_trace_processor_importers_common",
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metatrace",
     ":perfetto_src_trace_processor_metrics_lib",
@@ -9387,28 +7963,33 @@
     ":perfetto_src_trace_processor_storage_minimal",
     ":perfetto_src_trace_processor_storage_storage",
     ":perfetto_src_trace_processor_tables_tables",
+    ":perfetto_src_trace_processor_track_event_descriptor",
     ":perfetto_src_trace_processor_types_types",
     ":perfetto_src_trace_processor_util_descriptors",
-    ":perfetto_src_trace_processor_util_proto_to_args_parser",
-    ":perfetto_src_trace_processor_util_protozero_to_text",
     ":perfetto_src_trace_processor_util_util",
     "src/trace_processor/trace_processor_shell.cc",
     "src/trace_processor/util/proto_to_json.cc",
   ],
-  host_supported: true,
+  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_interceptors_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_track_event_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",
@@ -9420,19 +8001,11 @@
     "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_processor_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_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
-    "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_merged_sql_metrics",
   ],
   defaults: [
     "perfetto_defaults",
@@ -9442,34 +8015,7 @@
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
     "-DHAVE_HIDDEN",
   ],
-  strip: {
-    all: true,
-  },
-  target: {
-    android: {
-      shared_libs: [
-        "libandroidicu",
-        "liblog",
-        "libprotobuf-cpp-full",
-        "libsqlite",
-        "libutils",
-        "libz",
-      ],
-    },
-    host: {
-      static_libs: [
-        "libprotobuf-cpp-full",
-        "libsqlite",
-        "libz",
-      ],
-      stl: "libc++_static",
-      dist: {
-        targets: [
-          "sdk_repo",
-        ],
-      },
-    },
-  },
+  stl: "libc++_static",
 }
 
 // GN: //tools/trace_to_text:trace_to_text
@@ -9479,8 +8025,8 @@
     ":perfetto_include_perfetto_base_base",
     ":perfetto_include_perfetto_ext_base_base",
     ":perfetto_include_perfetto_ext_trace_processor_export_json",
-    ":perfetto_include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
     ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+    ":perfetto_include_perfetto_profiling_deobfuscator",
     ":perfetto_include_perfetto_profiling_pprof_builder",
     ":perfetto_include_perfetto_protozero_protozero",
     ":perfetto_include_perfetto_trace_processor_basic_types",
@@ -9491,13 +8037,14 @@
     ":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_interceptors_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_track_event_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",
@@ -9509,7 +8056,6 @@
     ":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_processor_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
@@ -9523,11 +8069,10 @@
     ":perfetto_src_protozero_protozero",
     ":perfetto_src_trace_processor_analysis_analysis",
     ":perfetto_src_trace_processor_containers_containers",
-    ":perfetto_src_trace_processor_db_db",
+    ":perfetto_src_trace_processor_db_lib",
     ":perfetto_src_trace_processor_export_json",
     ":perfetto_src_trace_processor_ftrace_descriptors",
-    ":perfetto_src_trace_processor_importers_common_common",
-    ":perfetto_src_trace_processor_importers_memory_tracker_graph_processor",
+    ":perfetto_src_trace_processor_importers_common",
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metatrace",
     ":perfetto_src_trace_processor_metrics_lib",
@@ -9536,34 +8081,37 @@
     ":perfetto_src_trace_processor_storage_minimal",
     ":perfetto_src_trace_processor_storage_storage",
     ":perfetto_src_trace_processor_tables_tables",
+    ":perfetto_src_trace_processor_track_event_descriptor",
     ":perfetto_src_trace_processor_types_types",
     ":perfetto_src_trace_processor_util_descriptors",
-    ":perfetto_src_trace_processor_util_proto_to_args_parser",
-    ":perfetto_src_trace_processor_util_protozero_to_text",
     ":perfetto_src_trace_processor_util_util",
     ":perfetto_tools_trace_to_text_common",
     ":perfetto_tools_trace_to_text_full",
     ":perfetto_tools_trace_to_text_pprofbuilder",
     ":perfetto_tools_trace_to_text_utils",
   ],
-  static_libs: [
+  shared_libs: [
     "libprotobuf-cpp-full",
+  ],
+  static_libs: [
     "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_interceptors_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_track_event_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",
@@ -9575,20 +8123,12 @@
     "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_processor_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_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_third_party_pprof_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
-    "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
-    "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
-    "perfetto_src_trace_processor_metrics_gen_merged_sql_metrics",
   ],
   defaults: [
     "perfetto_defaults",
@@ -9644,8 +8184,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -9676,21 +8214,14 @@
     ":perfetto_protos_perfetto_trace_system_info_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
     ":perfetto_src_ipc_common",
-    ":perfetto_src_kallsyms_kallsyms",
     ":perfetto_src_profiling_common_callstack_trie",
     ":perfetto_src_profiling_common_interner",
     ":perfetto_src_profiling_common_interning_output",
     ":perfetto_src_profiling_common_proc_utils",
-    ":perfetto_src_profiling_common_producer_support",
-    ":perfetto_src_profiling_common_profiler_guardrails",
     ":perfetto_src_profiling_common_unwind_support",
     ":perfetto_src_profiling_perf_common_types",
     ":perfetto_src_profiling_perf_proc_descriptors",
@@ -9698,12 +8229,7 @@
     ":perfetto_src_profiling_perf_regs_parsing",
     ":perfetto_src_profiling_perf_traced_perf_main",
     ":perfetto_src_profiling_perf_unwinding",
-    ":perfetto_src_protozero_filtering_bytecode_common",
-    ":perfetto_src_protozero_filtering_bytecode_parser",
-    ":perfetto_src_protozero_filtering_message_filter",
     ":perfetto_src_protozero_protozero",
-    ":perfetto_src_traced_probes_ftrace_ftrace_procfs",
-    ":perfetto_src_traced_probes_packages_list_packages_list_parser",
     ":perfetto_src_tracing_common",
     ":perfetto_src_tracing_core_core",
     ":perfetto_src_tracing_core_service",
@@ -9732,8 +8258,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -9764,7 +8288,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
   ],
   defaults: [
     "perfetto_defaults",
@@ -9794,7 +8317,6 @@
   ],
   required: [
     "libperfetto_android_internal",
-    "mm_events",
     "traced_perf",
     "trigger_perfetto",
   ],
@@ -9825,8 +8347,6 @@
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
-    ":perfetto_protos_perfetto_config_interceptors_zero_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
@@ -9857,10 +8377,6 @@
     ":perfetto_protos_perfetto_trace_system_info_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_android_stats_android_stats",
-    ":perfetto_src_android_stats_perfetto_atoms",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_client",
@@ -9890,8 +8406,6 @@
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
@@ -9922,7 +8436,6 @@
     "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_src_base_version_gen_h",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
@@ -10015,72 +8528,28 @@
     ],
 }
 
-sh_binary {
-    name: "mm_events",
-    src: "tools/mm_events",
-}
-
-package {
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
-python_library {
-    name: "perfetto-trace-processor-python",
-    srcs: [
-        ":perfetto-trace-processor-python-srcs",
+cc_genrule {
+  name: "trace_processor_shell.stripped",
+  device_supported: false,
+  host_supported: true,
+  cmd: "$(location tools/strip_android_host_binary.py) $(in) -o $(out)",
+  enabled: false,
+  compile_multilib: "64",
+  tool_files: [
+    "tools/strip_android_host_binary.py",
+  ],
+  dist: {
+    targets: [
+      "sdk_repo",
     ],
-    data: [
-        ":perfetto-trace-processor-python-data",
-    ],
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
+  },
+  target: {
+    linux: {
+      out: [
+        "trace_processor_shell.stripped",
+      ],
+      srcs: [":trace_processor_shell"],
+      enabled: true,
     },
-    libs: [
-        "libprotobuf-python",
-    ],
-    host_supported: true,
-}
-
-filegroup {
-    name: "perfetto-trace-processor-python-srcs",
-    srcs: ["src/trace_processor/python/perfetto/**/*.py"],
-    path: "src/trace_processor/python",
-}
-
-filegroup {
-    name: "perfetto-trace-processor-python-data",
-    srcs: ["src/trace_processor/python/perfetto/**/*.descriptor*"],
-    path: "src/trace_processor/python",
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
-    name: "external_perfetto_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-        "SPDX-license-identifier-BSD",
-        "SPDX-license-identifier-CC-BY",
-    ],
-    license_text: [
-        "LICENSE",
-    ],
-}
+  },
+}
\ No newline at end of file
diff --git a/Android.bp.extras b/Android.bp.extras
index 53140dd..a4615eb 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -79,72 +79,28 @@
     ],
 }
 
-sh_binary {
-    name: "mm_events",
-    src: "tools/mm_events",
-}
-
-package {
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
-python_library {
-    name: "perfetto-trace-processor-python",
-    srcs: [
-        ":perfetto-trace-processor-python-srcs",
+cc_genrule {
+  name: "trace_processor_shell.stripped",
+  device_supported: false,
+  host_supported: true,
+  cmd: "$(location tools/strip_android_host_binary.py) $(in) -o $(out)",
+  enabled: false,
+  compile_multilib: "64",
+  tool_files: [
+    "tools/strip_android_host_binary.py",
+  ],
+  dist: {
+    targets: [
+      "sdk_repo",
     ],
-    data: [
-        ":perfetto-trace-processor-python-data",
-    ],
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
+  },
+  target: {
+    linux: {
+      out: [
+        "trace_processor_shell.stripped",
+      ],
+      srcs: [":trace_processor_shell"],
+      enabled: true,
     },
-    libs: [
-        "libprotobuf-python",
-    ],
-    host_supported: true,
-}
-
-filegroup {
-    name: "perfetto-trace-processor-python-srcs",
-    srcs: ["src/trace_processor/python/perfetto/**/*.py"],
-    path: "src/trace_processor/python",
-}
-
-filegroup {
-    name: "perfetto-trace-processor-python-data",
-    srcs: ["src/trace_processor/python/perfetto/**/*.descriptor*"],
-    path: "src/trace_processor/python",
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
-    name: "external_perfetto_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-        "SPDX-license-identifier-BSD",
-        "SPDX-license-identifier-CC-BY",
-    ],
-    license_text: [
-        "LICENSE",
-    ],
+  },
 }
diff --git a/BUILD b/BUILD
index 0e006ec..7bdb892 100644
--- a/BUILD
+++ b/BUILD
@@ -20,16 +20,13 @@
     "perfetto_cc_binary",
     "perfetto_cc_ipc_library",
     "perfetto_cc_library",
-    "perfetto_cc_proto_descriptor",
     "perfetto_cc_proto_library",
     "perfetto_cc_protocpp_library",
     "perfetto_cc_protozero_library",
     "perfetto_java_proto_library",
     "perfetto_java_lite_proto_library",
     "perfetto_proto_library",
-    "perfetto_proto_descriptor",
     "perfetto_py_binary",
-    "perfetto_py_library",
     "perfetto_gensignature_internal_only",
 )
 
@@ -48,9 +45,11 @@
     name = "ipc_plugin",
     srcs = [
         "src/ipc/protoc_plugin/ipc_plugin.cc",
+        ":include_perfetto_base_base",
+        ":include_perfetto_ext_base_base",
+        ":src_base_base",
     ],
     deps = [
-        ":src_base_base",
     ] + PERFETTO_CONFIG.deps.protoc_lib,
 )
 
@@ -58,6 +57,8 @@
 perfetto_cc_library(
     name = "perfetto_ipc",
     srcs = [
+        ":src_base_base",
+        ":src_base_unix_socket",
         ":src_ipc_client",
         ":src_ipc_common",
         ":src_ipc_host",
@@ -70,8 +71,6 @@
     ],
     deps = [
         ":protos_perfetto_ipc_wire_protocol_cpp",
-        ":src_base_base",
-        ":src_base_unix_socket",
     ],
     linkstatic = True,
 )
@@ -81,9 +80,11 @@
     name = "cppgen_plugin",
     srcs = [
         "src/protozero/protoc_plugin/cppgen_plugin.cc",
+        ":include_perfetto_base_base",
+        ":include_perfetto_ext_base_base",
+        ":src_base_base",
     ],
     deps = [
-        ":src_base_base",
     ] + PERFETTO_CONFIG.deps.protoc_lib,
 )
 
@@ -92,35 +93,26 @@
     name = "protozero_plugin",
     srcs = [
         "src/protozero/protoc_plugin/protozero_plugin.cc",
+        ":include_perfetto_base_base",
+        ":include_perfetto_ext_base_base",
+        ":src_base_base",
     ],
     deps = [
-        ":src_base_base",
     ] + PERFETTO_CONFIG.deps.protoc_lib,
 )
 
-# GN target: //src/protozero:protozero
+# GN target: //src/protozero:libprotozero
 perfetto_cc_library(
-    name = "protozero",
+    name = "libprotozero",
     srcs = [
-        "src/protozero/field.cc",
-        "src/protozero/message.cc",
-        "src/protozero/message_arena.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",
-        "src/protozero/static_buffer.cc",
-        "src/protozero/virtual_destructors.cc",
+        ":src_base_base",
+        ":src_protozero_protozero",
     ],
     hdrs = [
         ":include_perfetto_base_base",
+        ":include_perfetto_ext_base_base",
         ":include_perfetto_protozero_protozero",
     ],
-    deps = [
-        ":src_base_base",
-    ],
     linkstatic = True,
 )
 
@@ -128,11 +120,11 @@
 perfetto_cc_binary(
     name = "client_api_example",
     srcs = [
+        "test/client_api_example.cc",
         ":include_perfetto_base_base",
         ":include_perfetto_protozero_protozero",
         ":include_perfetto_tracing_core_forward_decls",
         ":include_perfetto_tracing_tracing",
-        "test/client_api_example.cc",
     ],
     deps = [
         ":libperfetto_client_experimental",
@@ -142,7 +134,6 @@
         ":protos_perfetto_config_ftrace_zero",
         ":protos_perfetto_config_gpu_zero",
         ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_interceptors_zero",
         ":protos_perfetto_config_power_zero",
         ":protos_perfetto_config_process_stats_zero",
         ":protos_perfetto_config_profiling_zero",
@@ -175,23 +166,22 @@
     srcs = [
         ":src_android_internal_headers",
         ":src_android_internal_lazy_library_loader",
-        ":src_android_stats_android_stats",
-        ":src_android_stats_perfetto_atoms",
-        ":src_kallsyms_kallsyms",
-        ":src_protozero_filtering_bytecode_common",
-        ":src_protozero_filtering_bytecode_parser",
-        ":src_protozero_filtering_message_filter",
+        ":src_base_base",
+        ":src_base_unix_socket",
+        ":src_ipc_client",
+        ":src_ipc_common",
+        ":src_ipc_host",
+        ":src_perfetto_cmd_perfetto_atoms",
+        ":src_protozero_protozero",
         ":src_traced_probes_android_log_android_log",
         ":src_traced_probes_common_common",
         ":src_traced_probes_data_source",
         ":src_traced_probes_filesystem_filesystem",
-        ":src_traced_probes_ftrace_format_parser_format_parser",
+        ":src_traced_probes_ftrace_format_parser",
         ":src_traced_probes_ftrace_ftrace",
-        ":src_traced_probes_ftrace_ftrace_procfs",
         ":src_traced_probes_initial_display_state_initial_display_state",
         ":src_traced_probes_metatrace_metatrace",
         ":src_traced_probes_packages_list_packages_list",
-        ":src_traced_probes_packages_list_packages_list_parser",
         ":src_traced_probes_power_power",
         ":src_traced_probes_probes",
         ":src_traced_probes_probes_src",
@@ -223,7 +213,6 @@
         ":include_perfetto_tracing_tracing",
     ],
     deps = [
-        ":perfetto_ipc",
         ":protos_perfetto_common_cpp",
         ":protos_perfetto_common_zero",
         ":protos_perfetto_config_android_cpp",
@@ -235,8 +224,6 @@
         ":protos_perfetto_config_gpu_zero",
         ":protos_perfetto_config_inode_file_cpp",
         ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_interceptors_zero",
         ":protos_perfetto_config_power_cpp",
         ":protos_perfetto_config_power_zero",
         ":protos_perfetto_config_process_stats_cpp",
@@ -250,6 +237,7 @@
         ":protos_perfetto_config_zero",
         ":protos_perfetto_ipc_cpp",
         ":protos_perfetto_ipc_ipc",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
         ":protos_perfetto_trace_android_zero",
         ":protos_perfetto_trace_chrome_zero",
         ":protos_perfetto_trace_filesystem_zero",
@@ -266,8 +254,6 @@
         ":protos_perfetto_trace_system_info_zero",
         ":protos_perfetto_trace_track_event_cpp",
         ":protos_perfetto_trace_track_event_zero",
-        ":protozero",
-        ":src_base_base",
     ],
     linkstatic = True,
 )
@@ -281,11 +267,8 @@
         "include/perfetto/base/export.h",
         "include/perfetto/base/flat_set.h",
         "include/perfetto/base/logging.h",
-        "include/perfetto/base/platform_handle.h",
         "include/perfetto/base/proc_utils.h",
-        "include/perfetto/base/status.h",
         "include/perfetto/base/task_runner.h",
-        "include/perfetto/base/template_util.h",
         "include/perfetto/base/thread_utils.h",
         "include/perfetto/base/time.h",
     ],
@@ -297,19 +280,15 @@
     srcs = [
         "include/perfetto/ext/base/circular_queue.h",
         "include/perfetto/ext/base/container_annotations.h",
-        "include/perfetto/ext/base/ctrl_c_handler.h",
-        "include/perfetto/ext/base/endian.h",
         "include/perfetto/ext/base/event_fd.h",
         "include/perfetto/ext/base/file_utils.h",
-        "include/perfetto/ext/base/getopt.h",
-        "include/perfetto/ext/base/getopt_compat.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/periodic_task.h",
         "include/perfetto/ext/base/pipe.h",
         "include/perfetto/ext/base/scoped_file.h",
         "include/perfetto/ext/base/small_set.h",
@@ -327,7 +306,6 @@
         "include/perfetto/ext/base/unix_task_runner.h",
         "include/perfetto/ext/base/utils.h",
         "include/perfetto/ext/base/uuid.h",
-        "include/perfetto/ext/base/version.h",
         "include/perfetto/ext/base/waitable_event.h",
         "include/perfetto/ext/base/watchdog.h",
         "include/perfetto/ext/base/watchdog_noop.h",
@@ -353,19 +331,6 @@
     ],
 )
 
-# GN target: //include/perfetto/ext/trace_processor/importers/memory_tracker:memory_tracker
-filegroup(
-    name = "include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
-    srcs = [
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h",
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h",
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h",
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h",
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h",
-        "include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h",
-    ],
-)
-
 # GN target: //include/perfetto/ext/trace_processor:export_json
 filegroup(
     name = "include_perfetto_ext_trace_processor_export_json",
@@ -422,6 +387,14 @@
     ],
 )
 
+# GN target: //include/perfetto/profiling:deobfuscator
+filegroup(
+    name = "include_perfetto_profiling_deobfuscator",
+    srcs = [
+        "include/perfetto/profiling/deobfuscator.h",
+    ],
+)
+
 # GN target: //include/perfetto/profiling:pprof_builder
 filegroup(
     name = "include_perfetto_profiling_pprof_builder",
@@ -438,14 +411,11 @@
         "include/perfetto/protozero/copyable_ptr.h",
         "include/perfetto/protozero/cpp_message_obj.h",
         "include/perfetto/protozero/field.h",
-        "include/perfetto/protozero/field_writer.h",
         "include/perfetto/protozero/message.h",
-        "include/perfetto/protozero/message_arena.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/root_message.h",
         "include/perfetto/protozero/scattered_heap_buffer.h",
         "include/perfetto/protozero/scattered_stream_null_delegate.h",
         "include/perfetto/protozero/scattered_stream_writer.h",
@@ -482,7 +452,6 @@
 filegroup(
     name = "include_perfetto_trace_processor_trace_processor",
     srcs = [
-        "include/perfetto/trace_processor/iterator.h",
         "include/perfetto/trace_processor/read_trace.h",
         "include/perfetto/trace_processor/trace_processor.h",
     ],
@@ -513,44 +482,29 @@
 filegroup(
     name = "include_perfetto_tracing_tracing",
     srcs = [
-        "include/perfetto/tracing/backend_type.h",
         "include/perfetto/tracing/buffer_exhausted_policy.h",
-        "include/perfetto/tracing/console_interceptor.h",
         "include/perfetto/tracing/data_source.h",
         "include/perfetto/tracing/debug_annotation.h",
         "include/perfetto/tracing/event_context.h",
-        "include/perfetto/tracing/interceptor.h",
         "include/perfetto/tracing/internal/basic_types.h",
-        "include/perfetto/tracing/internal/checked_scope.h",
-        "include/perfetto/tracing/internal/compile_time_hash.h",
         "include/perfetto/tracing/internal/data_source_internal.h",
         "include/perfetto/tracing/internal/in_process_tracing_backend.h",
-        "include/perfetto/tracing/internal/interceptor_trace_writer.h",
         "include/perfetto/tracing/internal/system_tracing_backend.h",
-        "include/perfetto/tracing/internal/tracing_backend_fake.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_interned_fields.h",
         "include/perfetto/tracing/internal/track_event_macros.h",
-        "include/perfetto/tracing/internal/write_track_event_args.h",
         "include/perfetto/tracing/locked_handle.h",
         "include/perfetto/tracing/platform.h",
-        "include/perfetto/tracing/string_helpers.h",
         "include/perfetto/tracing/trace_writer_base.h",
-        "include/perfetto/tracing/traced_proto.h",
-        "include/perfetto/tracing/traced_value.h",
-        "include/perfetto/tracing/traced_value_forward.h",
         "include/perfetto/tracing/tracing.h",
         "include/perfetto/tracing/tracing_backend.h",
-        "include/perfetto/tracing/tracing_policy.h",
         "include/perfetto/tracing/track.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/perfetto/tracing/track_event_legacy.h",
-        "include/perfetto/tracing/track_event_state_tracker.h",
     ],
 )
 
@@ -559,11 +513,11 @@
     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.h",
+        "src/android_internal/power_stats_hal.h",
         "src/android_internal/statsd_logging.h",
-        "src/android_internal/tracing_service_proxy.h",
     ],
 )
 
@@ -576,89 +530,38 @@
     ],
 )
 
-# GN target: //src/android_stats:android_stats
-filegroup(
-    name = "src_android_stats_android_stats",
-    srcs = [
-        "src/android_stats/statsd_logging_helper.cc",
-        "src/android_stats/statsd_logging_helper.h",
-    ],
-)
-
-# GN target: //src/android_stats:perfetto_atoms
-filegroup(
-    name = "src_android_stats_perfetto_atoms",
-    srcs = [
-        "src/android_stats/perfetto_atoms.h",
-    ],
-)
-
 # GN target: //src/base:base
-perfetto_cc_library(
+filegroup(
     name = "src_base_base",
     srcs = [
-        "src/base/ctrl_c_handler.cc",
         "src/base/event_fd.cc",
         "src/base/file_utils.cc",
-        "src/base/getopt_compat.cc",
         "src/base/logging.cc",
         "src/base/metatrace.cc",
         "src/base/paged_memory.cc",
-        "src/base/periodic_task.cc",
         "src/base/pipe.cc",
-        "src/base/status.cc",
         "src/base/string_splitter.cc",
         "src/base/string_utils.cc",
         "src/base/string_view.cc",
         "src/base/subprocess.cc",
-        "src/base/subprocess_posix.cc",
-        "src/base/subprocess_windows.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/utils.cc",
         "src/base/uuid.cc",
-        "src/base/version.cc",
         "src/base/virtual_destructors.cc",
         "src/base/waitable_event.cc",
         "src/base/watchdog_posix.cc",
     ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-    ],
-    deps = [
-    ] + PERFETTO_CONFIG.deps.version_header,
-    linkstatic = True,
 )
 
 # GN target: //src/base:unix_socket
-perfetto_cc_library(
+filegroup(
     name = "src_base_unix_socket",
     srcs = [
         "src/base/unix_socket.cc",
     ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-    ],
-    linkstatic = True,
-)
-
-genrule(
-    name = "src_base_version_gen_h",
-    srcs = [
-        "CHANGELOG",
-    ],
-    outs = [
-        "perfetto_version.gen.h",
-    ],
-    cmd = "$(location gen_version_header_py) --cpp_out=$@ --changelog=$(location CHANGELOG)",
-    exec_tools = [
-        ":gen_version_header_py",
-    ],
 )
 
 # GN target: //src/ipc:client
@@ -691,24 +594,11 @@
     ],
 )
 
-# GN target: //src/kallsyms:kallsyms
+# GN target: //src/perfetto_cmd:perfetto_atoms
 filegroup(
-    name = "src_kallsyms_kallsyms",
+    name = "src_perfetto_cmd_perfetto_atoms",
     srcs = [
-        "src/kallsyms/kernel_symbol_map.cc",
-        "src/kallsyms/kernel_symbol_map.h",
-        "src/kallsyms/lazy_kernel_symbolizer.cc",
-        "src/kallsyms/lazy_kernel_symbolizer.h",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_perfetto_cmd_gen_cc_config_descriptor",
-    deps = [
-        ":protos_perfetto_config_perfetto_config_descriptor",
-    ],
-    outs = [
-        "src/perfetto_cmd/perfetto_config.descriptor.h",
+        "src/perfetto_cmd/perfetto_atoms.h",
     ],
 )
 
@@ -724,6 +614,7 @@
         "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",
     ],
@@ -751,17 +642,8 @@
 filegroup(
     name = "src_profiling_symbolizer_symbolizer",
     srcs = [
-        "src/profiling/symbolizer/filesystem.h",
-        "src/profiling/symbolizer/filesystem_posix.cc",
-        "src/profiling/symbolizer/filesystem_windows.cc",
         "src/profiling/symbolizer/local_symbolizer.cc",
         "src/profiling/symbolizer/local_symbolizer.h",
-        "src/profiling/symbolizer/scoped_read_mmap.h",
-        "src/profiling/symbolizer/scoped_read_mmap_posix.cc",
-        "src/profiling/symbolizer/scoped_read_mmap_windows.cc",
-        "src/profiling/symbolizer/subprocess.h",
-        "src/profiling/symbolizer/subprocess_posix.cc",
-        "src/profiling/symbolizer/subprocess_windows.cc",
         "src/profiling/symbolizer/symbolizer.cc",
         "src/profiling/symbolizer/symbolizer.h",
     ],
@@ -772,34 +654,23 @@
     name = "src_profiling_deobfuscator",
     srcs = [
         "src/profiling/deobfuscator.cc",
-        "src/profiling/deobfuscator.h",
     ],
 )
 
-# GN target: //src/protozero/filtering:bytecode_common
+# GN target: //src/protozero:protozero
 filegroup(
-    name = "src_protozero_filtering_bytecode_common",
+    name = "src_protozero_protozero",
     srcs = [
-        "src/protozero/filtering/filter_bytecode_common.h",
-    ],
-)
-
-# GN target: //src/protozero/filtering:bytecode_parser
-filegroup(
-    name = "src_protozero_filtering_bytecode_parser",
-    srcs = [
-        "src/protozero/filtering/filter_bytecode_parser.cc",
-        "src/protozero/filtering/filter_bytecode_parser.h",
-    ],
-)
-
-# GN target: //src/protozero/filtering:message_filter
-filegroup(
-    name = "src_protozero_filtering_message_filter",
-    srcs = [
-        "src/protozero/filtering/message_filter.cc",
-        "src/protozero/filtering/message_filter.h",
-        "src/protozero/filtering/message_tokenizer.h",
+        "src/protozero/field.cc",
+        "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",
+        "src/protozero/static_buffer.cc",
+        "src/protozero/virtual_destructors.cc",
     ],
 )
 
@@ -813,34 +684,26 @@
 )
 
 # GN target: //src/trace_processor/containers:containers
-perfetto_cc_library(
+filegroup(
     name = "src_trace_processor_containers_containers",
     srcs = [
         "src/trace_processor/containers/bit_vector.cc",
-        "src/trace_processor/containers/bit_vector_iterators.cc",
-        "src/trace_processor/containers/nullable_vector.cc",
-        "src/trace_processor/containers/row_map.cc",
-        "src/trace_processor/containers/string_pool.cc",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_protozero_protozero",
         "src/trace_processor/containers/bit_vector.h",
+        "src/trace_processor/containers/bit_vector_iterators.cc",
         "src/trace_processor/containers/bit_vector_iterators.h",
         "src/trace_processor/containers/null_term_string_view.h",
+        "src/trace_processor/containers/nullable_vector.cc",
         "src/trace_processor/containers/nullable_vector.h",
+        "src/trace_processor/containers/row_map.cc",
         "src/trace_processor/containers/row_map.h",
+        "src/trace_processor/containers/string_pool.cc",
         "src/trace_processor/containers/string_pool.h",
     ],
-    deps = [
-        ":src_base_base",
-    ],
-    linkstatic = True,
 )
 
-# GN target: //src/trace_processor/db:db
+# GN target: //src/trace_processor/db:lib
 filegroup(
-    name = "src_trace_processor_db_db",
+    name = "src_trace_processor_db_lib",
     srcs = [
         "src/trace_processor/db/column.cc",
         "src/trace_processor/db/column.h",
@@ -852,19 +715,16 @@
     ],
 )
 
-# GN target: //src/trace_processor/importers/common:common
+# GN target: //src/trace_processor/importers:common
 filegroup(
-    name = "src_trace_processor_importers_common_common",
+    name = "src_trace_processor_importers_common",
     srcs = [
         "src/trace_processor/importers/common/args_tracker.cc",
         "src/trace_processor/importers/common/args_tracker.h",
-        "src/trace_processor/importers/common/chunked_trace_reader.h",
         "src/trace_processor/importers/common/clock_tracker.cc",
         "src/trace_processor/importers/common/clock_tracker.h",
         "src/trace_processor/importers/common/event_tracker.cc",
         "src/trace_processor/importers/common/event_tracker.h",
-        "src/trace_processor/importers/common/flow_tracker.cc",
-        "src/trace_processor/importers/common/flow_tracker.h",
         "src/trace_processor/importers/common/global_args_tracker.cc",
         "src/trace_processor/importers/common/global_args_tracker.h",
         "src/trace_processor/importers/common/process_tracker.cc",
@@ -873,75 +733,11 @@
         "src/trace_processor/importers/common/slice_tracker.h",
         "src/trace_processor/importers/common/system_info_tracker.cc",
         "src/trace_processor/importers/common/system_info_tracker.h",
-        "src/trace_processor/importers/common/trace_blob_view.h",
-        "src/trace_processor/importers/common/trace_parser.h",
         "src/trace_processor/importers/common/track_tracker.cc",
         "src/trace_processor/importers/common/track_tracker.h",
     ],
 )
 
-# GN target: //src/trace_processor/importers/memory_tracker:graph_processor
-filegroup(
-    name = "src_trace_processor_importers_memory_tracker_graph_processor",
-    srcs = [
-        "src/trace_processor/importers/memory_tracker/graph.cc",
-        "src/trace_processor/importers/memory_tracker/graph_processor.cc",
-        "src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc",
-        "src/trace_processor/importers/memory_tracker/raw_memory_graph_node.cc",
-        "src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-    deps = [
-        ":protos_third_party_chromium_chrome_track_event_descriptor",
-    ],
-    outs = [
-        "src/trace_processor/importers/chrome_track_event.descriptor.h",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_trace_processor_importers_gen_cc_config_descriptor",
-    deps = [
-        ":protos_perfetto_config_descriptor",
-    ],
-    outs = [
-        "src/trace_processor/importers/config.descriptor.h",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_trace_processor_importers_gen_cc_track_event_descriptor",
-    deps = [
-        ":protos_perfetto_trace_track_event_track_event_descriptor",
-    ],
-    outs = [
-        "src/trace_processor/importers/track_event.descriptor.h",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-    deps = [
-        ":protos_perfetto_metrics_chrome_descriptor",
-    ],
-    outs = [
-        "src/trace_processor/metrics/chrome/all_chrome_metrics.descriptor.h",
-    ],
-)
-
-perfetto_cc_proto_descriptor(
-    name = "src_trace_processor_metrics_gen_cc_metrics_descriptor",
-    deps = [
-        ":protos_perfetto_metrics_descriptor",
-    ],
-    outs = [
-        "src/trace_processor/metrics/metrics.descriptor.h",
-    ],
-)
-
 genrule(
     name = "src_trace_processor_metrics_gen_merged_sql_metrics",
     srcs = [
@@ -949,80 +745,43 @@
         "src/trace_processor/metrics/android/android_cpu.sql",
         "src/trace_processor/metrics/android/android_cpu_agg.sql",
         "src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql",
-        "src/trace_processor/metrics/android/android_dma_heap.sql",
-        "src/trace_processor/metrics/android/android_fastrpc.sql",
-        "src/trace_processor/metrics/android/android_gpu.sql",
-        "src/trace_processor/metrics/android/android_hwcomposer.sql",
         "src/trace_processor/metrics/android/android_hwui_metric.sql",
-        "src/trace_processor/metrics/android/android_hwui_threads.sql",
         "src/trace_processor/metrics/android/android_ion.sql",
-        "src/trace_processor/metrics/android/android_jank.sql",
         "src/trace_processor/metrics/android/android_lmk.sql",
         "src/trace_processor/metrics/android/android_lmk_reason.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_proxy_power.sql",
         "src/trace_processor/metrics/android/android_startup.sql",
         "src/trace_processor/metrics/android/android_startup_launches.sql",
-        "src/trace_processor/metrics/android/android_surfaceflinger.sql",
-        "src/trace_processor/metrics/android/android_sysui_cuj.sql",
         "src/trace_processor/metrics/android/android_task_names.sql",
+        "src/trace_processor/metrics/android/android_task_state.sql",
         "src/trace_processor/metrics/android/android_thread_time_in_state.sql",
-        "src/trace_processor/metrics/android/composer_execution.sql",
-        "src/trace_processor/metrics/android/composition_layers.sql",
+        "src/trace_processor/metrics/android/counter_span_view.sql",
         "src/trace_processor/metrics/android/cpu_info.sql",
         "src/trace_processor/metrics/android/display_metrics.sql",
-        "src/trace_processor/metrics/android/frame_missed.sql",
-        "src/trace_processor/metrics/android/g2d.sql",
-        "src/trace_processor/metrics/android/g2d_duration.sql",
-        "src/trace_processor/metrics/android/global_counter_span_view.sql",
+        "src/trace_processor/metrics/android/heap_profile_callsites.sql",
         "src/trace_processor/metrics/android/hsc_startups.sql",
         "src/trace_processor/metrics/android/java_heap_histogram.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/power_drain_in_watts.sql",
-        "src/trace_processor/metrics/android/power_profile_data.sql",
         "src/trace_processor/metrics/android/process_counter_span_view.sql",
         "src/trace_processor/metrics/android/process_mem.sql",
         "src/trace_processor/metrics/android/process_metadata.sql",
         "src/trace_processor/metrics/android/process_oom_score.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/unmapped_java_symbols.sql",
         "src/trace_processor/metrics/android/unsymbolized_frames.sql",
-        "src/trace_processor/metrics/chrome/actual_power_by_category.sql",
-        "src/trace_processor/metrics/chrome/actual_power_by_rail_mode.sql",
-        "src/trace_processor/metrics/chrome/chrome_event_metadata.sql",
         "src/trace_processor/metrics/chrome/chrome_processes.sql",
-        "src/trace_processor/metrics/chrome/chrome_thread_slice_with_cpu_time.sql",
-        "src/trace_processor/metrics/chrome/cpu_time_by_category.sql",
-        "src/trace_processor/metrics/chrome/cpu_time_by_rail_mode.sql",
-        "src/trace_processor/metrics/chrome/estimated_power_by_category.sql",
-        "src/trace_processor/metrics/chrome/estimated_power_by_rail_mode.sql",
-        "src/trace_processor/metrics/chrome/rail_modes.sql",
-        "src/trace_processor/metrics/chrome/scroll_flow_event.sql",
-        "src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank_cause.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_task.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_touch_move.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql",
-        "src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql",
-        "src/trace_processor/metrics/chrome/test_chrome_metric.sql",
-        "src/trace_processor/metrics/experimental/blink_gc_metric.sql",
-        "src/trace_processor/metrics/experimental/frame_times.sql",
-        "src/trace_processor/metrics/experimental/media_metric.sql",
-        "src/trace_processor/metrics/experimental/reported_by_page.sql",
         "src/trace_processor/metrics/trace_metadata.sql",
-        "src/trace_processor/metrics/trace_stats.sql",
-        "src/trace_processor/metrics/webview/webview_power_usage.sql",
     ],
     outs = [
         "src/trace_processor/metrics/sql_metrics.h",
     ],
     cmd = "$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)",
-    exec_tools = [
+    tools = [
         ":gen_merged_sql_metrics_py",
     ],
 )
@@ -1031,7 +790,9 @@
 filegroup(
     name = "src_trace_processor_metrics_lib",
     srcs = [
+        "src/trace_processor/metrics/custom_options.descriptor.h",
         "src/trace_processor/metrics/metrics.cc",
+        "src/trace_processor/metrics/metrics.descriptor.h",
         "src/trace_processor/metrics/metrics.h",
     ],
 )
@@ -1049,10 +810,6 @@
 filegroup(
     name = "src_trace_processor_rpc_rpc",
     srcs = [
-        "src/trace_processor/rpc/proto_ring_buffer.cc",
-        "src/trace_processor/rpc/proto_ring_buffer.h",
-        "src/trace_processor/rpc/query_result_serializer.cc",
-        "src/trace_processor/rpc/query_result_serializer.h",
         "src/trace_processor/rpc/rpc.cc",
         "src/trace_processor/rpc/rpc.h",
     ],
@@ -1103,10 +860,8 @@
     srcs = [
         "src/trace_processor/tables/android_tables.h",
         "src/trace_processor/tables/counter_tables.h",
-        "src/trace_processor/tables/flow_tables.h",
         "src/trace_processor/tables/macros.h",
         "src/trace_processor/tables/macros_internal.h",
-        "src/trace_processor/tables/memory_tables.h",
         "src/trace_processor/tables/metadata_tables.h",
         "src/trace_processor/tables/profiler_tables.h",
         "src/trace_processor/tables/slice_tables.h",
@@ -1123,7 +878,6 @@
         "src/trace_processor/types/destructible.h",
         "src/trace_processor/types/gfp_flags.cc",
         "src/trace_processor/types/gfp_flags.h",
-        "src/trace_processor/types/softirq_action.h",
         "src/trace_processor/types/task_state.cc",
         "src/trace_processor/types/task_state.h",
         "src/trace_processor/types/trace_processor_context.h",
@@ -1142,24 +896,6 @@
     ],
 )
 
-# GN target: //src/trace_processor/util:proto_to_args_parser
-filegroup(
-    name = "src_trace_processor_util_proto_to_args_parser",
-    srcs = [
-        "src/trace_processor/util/proto_to_args_parser.cc",
-        "src/trace_processor/util/proto_to_args_parser.h",
-    ],
-)
-
-# GN target: //src/trace_processor/util:protozero_to_text
-filegroup(
-    name = "src_trace_processor_util_protozero_to_text",
-    srcs = [
-        "src/trace_processor/util/protozero_to_text.cc",
-        "src/trace_processor/util/protozero_to_text.h",
-    ],
-)
-
 # GN target: //src/trace_processor/util:util
 filegroup(
     name = "src_trace_processor_util_util",
@@ -1190,28 +926,14 @@
 filegroup(
     name = "src_trace_processor_lib",
     srcs = [
-        "src/trace_processor/dynamic/ancestor_generator.cc",
-        "src/trace_processor/dynamic/ancestor_generator.h",
-        "src/trace_processor/dynamic/connected_flow_generator.cc",
-        "src/trace_processor/dynamic/connected_flow_generator.h",
-        "src/trace_processor/dynamic/descendant_slice_generator.cc",
-        "src/trace_processor/dynamic/descendant_slice_generator.h",
         "src/trace_processor/dynamic/describe_slice_generator.cc",
         "src/trace_processor/dynamic/describe_slice_generator.h",
-        "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
-        "src/trace_processor/dynamic/experimental_annotated_stack_generator.h",
         "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
         "src/trace_processor/dynamic/experimental_counter_dur_generator.h",
         "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
         "src/trace_processor/dynamic/experimental_flamegraph_generator.h",
-        "src/trace_processor/dynamic/experimental_sched_upid_generator.cc",
-        "src/trace_processor/dynamic/experimental_sched_upid_generator.h",
         "src/trace_processor/dynamic/experimental_slice_layout_generator.cc",
         "src/trace_processor/dynamic/experimental_slice_layout_generator.h",
-        "src/trace_processor/dynamic/thread_state_generator.cc",
-        "src/trace_processor/dynamic/thread_state_generator.h",
-        "src/trace_processor/iterator_impl.cc",
-        "src/trace_processor/iterator_impl.h",
         "src/trace_processor/read_trace.cc",
         "src/trace_processor/trace_processor.cc",
         "src/trace_processor/trace_processor_impl.cc",
@@ -1266,8 +988,6 @@
         "src/trace_processor/importers/proto/android_probes_parser.h",
         "src/trace_processor/importers/proto/android_probes_tracker.cc",
         "src/trace_processor/importers/proto/android_probes_tracker.h",
-        "src/trace_processor/importers/proto/frame_timeline_event_parser.cc",
-        "src/trace_processor/importers/proto/frame_timeline_event_parser.h",
         "src/trace_processor/importers/proto/gpu_event_parser.cc",
         "src/trace_processor/importers/proto/gpu_event_parser.h",
         "src/trace_processor/importers/proto/graphics_event_module.cc",
@@ -1305,6 +1025,7 @@
 filegroup(
     name = "src_trace_processor_storage_minimal",
     srcs = [
+        "src/trace_processor/chunked_trace_reader.h",
         "src/trace_processor/forwarding_trace_parser.cc",
         "src/trace_processor/forwarding_trace_parser.h",
         "src/trace_processor/importers/default_modules.cc",
@@ -1319,22 +1040,10 @@
         "src/trace_processor/importers/json/json_utils.h",
         "src/trace_processor/importers/ninja/ninja_log_parser.cc",
         "src/trace_processor/importers/ninja/ninja_log_parser.h",
-        "src/trace_processor/importers/proto/async_track_set_tracker.cc",
-        "src/trace_processor/importers/proto/async_track_set_tracker.h",
-        "src/trace_processor/importers/proto/chrome_string_lookup.cc",
-        "src/trace_processor/importers/proto/chrome_string_lookup.h",
-        "src/trace_processor/importers/proto/chrome_system_probes_module.cc",
-        "src/trace_processor/importers/proto/chrome_system_probes_module.h",
-        "src/trace_processor/importers/proto/chrome_system_probes_parser.cc",
-        "src/trace_processor/importers/proto/chrome_system_probes_parser.h",
+        "src/trace_processor/importers/proto/args_table_utils.cc",
+        "src/trace_processor/importers/proto/args_table_utils.h",
         "src/trace_processor/importers/proto/heap_profile_tracker.cc",
         "src/trace_processor/importers/proto/heap_profile_tracker.h",
-        "src/trace_processor/importers/proto/memory_tracker_snapshot_module.cc",
-        "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h",
-        "src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc",
-        "src/trace_processor/importers/proto/memory_tracker_snapshot_parser.h",
-        "src/trace_processor/importers/proto/metadata_module.cc",
-        "src/trace_processor/importers/proto/metadata_module.h",
         "src/trace_processor/importers/proto/metadata_tracker.cc",
         "src/trace_processor/importers/proto/metadata_tracker.h",
         "src/trace_processor/importers/proto/packet_sequence_state.cc",
@@ -1345,15 +1054,11 @@
         "src/trace_processor/importers/proto/profile_module.h",
         "src/trace_processor/importers/proto/profile_packet_utils.cc",
         "src/trace_processor/importers/proto/profile_packet_utils.h",
-        "src/trace_processor/importers/proto/profiler_util.cc",
-        "src/trace_processor/importers/proto/profiler_util.h",
         "src/trace_processor/importers/proto/proto_importer_module.cc",
         "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_reader.cc",
-        "src/trace_processor/importers/proto/proto_trace_reader.h",
         "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
         "src/trace_processor/importers/proto/proto_trace_tokenizer.h",
         "src/trace_processor/importers/proto/stack_profile_tracker.cc",
@@ -1364,11 +1069,11 @@
         "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/proto/track_event_tracker.cc",
-        "src/trace_processor/importers/proto/track_event_tracker.h",
         "src/trace_processor/importers/syscalls/syscall_tracker.h",
         "src/trace_processor/importers/systrace/systrace_line.h",
         "src/trace_processor/timestamped_trace_piece.h",
+        "src/trace_processor/trace_blob_view.h",
+        "src/trace_processor/trace_parser.h",
         "src/trace_processor/trace_processor_context.cc",
         "src/trace_processor/trace_processor_storage.cc",
         "src/trace_processor/trace_processor_storage_impl.cc",
@@ -1379,6 +1084,14 @@
     ],
 )
 
+# GN target: //src/trace_processor:track_event_descriptor
+filegroup(
+    name = "src_trace_processor_track_event_descriptor",
+    srcs = [
+        "src/trace_processor/importers/proto/track_event.descriptor.h",
+    ],
+)
+
 # GN target: //src/traced/probes/android_log:android_log
 filegroup(
     name = "src_traced_probes_android_log_android_log",
@@ -1416,12 +1129,12 @@
     ],
 )
 
-# GN target: //src/traced/probes/ftrace/format_parser:format_parser
+# GN target: //src/traced/probes/ftrace:format_parser
 filegroup(
-    name = "src_traced_probes_ftrace_format_parser_format_parser",
+    name = "src_traced_probes_ftrace_format_parser",
     srcs = [
-        "src/traced/probes/ftrace/format_parser/format_parser.cc",
-        "src/traced/probes/ftrace/format_parser/format_parser.h",
+        "src/traced/probes/ftrace/format_parser.cc",
+        "src/traced/probes/ftrace/format_parser.h",
     ],
 )
 
@@ -1454,21 +1167,12 @@
         "src/traced/probes/ftrace/ftrace_data_source.cc",
         "src/traced/probes/ftrace/ftrace_data_source.h",
         "src/traced/probes/ftrace/ftrace_metadata.h",
-        "src/traced/probes/ftrace/ftrace_stats.cc",
-        "src/traced/probes/ftrace/ftrace_stats.h",
-        "src/traced/probes/ftrace/printk_formats_parser.cc",
-        "src/traced/probes/ftrace/printk_formats_parser.h",
-        "src/traced/probes/ftrace/proto_translation_table.cc",
-        "src/traced/probes/ftrace/proto_translation_table.h",
-    ],
-)
-
-# GN target: //src/traced/probes/ftrace:ftrace_procfs
-filegroup(
-    name = "src_traced_probes_ftrace_ftrace_procfs",
-    srcs = [
         "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",
     ],
 )
 
@@ -1499,15 +1203,6 @@
     ],
 )
 
-# GN target: //src/traced/probes/packages_list:packages_list_parser
-filegroup(
-    name = "src_traced_probes_packages_list_packages_list_parser",
-    srcs = [
-        "src/traced/probes/packages_list/packages_list_parser.cc",
-        "src/traced/probes/packages_list/packages_list_parser.h",
-    ],
-)
-
 # GN target: //src/traced/probes/power:power
 filegroup(
     name = "src_traced_probes_power_power",
@@ -1565,8 +1260,6 @@
 filegroup(
     name = "src_traced_probes_probes_src",
     srcs = [
-        "src/traced/probes/kmem_activity_trigger.cc",
-        "src/traced/probes/kmem_activity_trigger.h",
         "src/traced/probes/probes_producer.cc",
         "src/traced/probes/probes_producer.h",
     ],
@@ -1671,28 +1364,17 @@
 filegroup(
     name = "src_tracing_client_api_without_backends",
     srcs = [
-        "src/tracing/console_interceptor.cc",
         "src/tracing/data_source.cc",
         "src/tracing/debug_annotation.cc",
         "src/tracing/event_context.cc",
-        "src/tracing/interceptor.cc",
-        "src/tracing/internal/checked_scope.cc",
-        "src/tracing/internal/interceptor_trace_writer.cc",
-        "src/tracing/internal/tracing_backend_fake.cc",
-        "src/tracing/internal/tracing_muxer_fake.cc",
-        "src/tracing/internal/tracing_muxer_fake.h",
         "src/tracing/internal/tracing_muxer_impl.cc",
         "src/tracing/internal/tracing_muxer_impl.h",
         "src/tracing/internal/track_event_internal.cc",
-        "src/tracing/internal/track_event_interned_fields.cc",
         "src/tracing/platform.cc",
-        "src/tracing/traced_value.cc",
         "src/tracing/tracing.cc",
-        "src/tracing/tracing_policy.cc",
         "src/tracing/track.cc",
         "src/tracing/track_event_category_registry.cc",
         "src/tracing/track_event_legacy.cc",
-        "src/tracing/track_event_state_tracker.cc",
         "src/tracing/virtual_destructors.cc",
     ],
 )
@@ -1713,9 +1395,9 @@
     ],
 )
 
-# GN target: //src/tracing:platform_impl
+# GN target: //src/tracing:platform_posix
 filegroup(
-    name = "src_tracing_platform_impl",
+    name = "src_tracing_platform_posix",
     srcs = [
         "src/tracing/platform_posix.cc",
     ],
@@ -1738,8 +1420,6 @@
         "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_hprof.cc",
-        "tools/trace_to_text/trace_to_hprof.h",
         "tools/trace_to_text/trace_to_json.cc",
         "tools/trace_to_text/trace_to_json.h",
         "tools/trace_to_text/trace_to_profile.cc",
@@ -1801,16 +1481,13 @@
 perfetto_proto_library(
     name = "protos_perfetto_common_protos",
     srcs = [
-        "protos/perfetto/common/android_energy_consumer_descriptor.proto",
         "protos/perfetto/common/android_log_constants.proto",
         "protos/perfetto/common/builtin_clock.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/interceptor_descriptor.proto",
         "protos/perfetto/common/observable_events.proto",
-        "protos/perfetto/common/perf_events.proto",
         "protos/perfetto/common/sys_stats_counters.proto",
         "protos/perfetto/common/trace_stats.proto",
         "protos/perfetto/common/tracing_service_capabilities.proto",
@@ -1834,8 +1511,8 @@
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_config_android_cpp",
     deps = [
-        ":protos_perfetto_common_cpp",
         ":protos_perfetto_config_android_protos",
+        ":protos_perfetto_common_cpp",
     ],
 )
 
@@ -1867,7 +1544,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_config_android_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_config_android_protos",
     ],
 )
@@ -1876,29 +1552,17 @@
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_config_cpp",
     deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_power_cpp",
+        ":protos_perfetto_config_protos",
         ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_cpp",
+        ":protos_perfetto_config_android_cpp",
+        ":protos_perfetto_config_inode_file_cpp",
         ":protos_perfetto_config_track_event_cpp",
-    ],
-)
-
-# GN target: //protos/perfetto/config:descriptor
-perfetto_proto_descriptor(
-    name = "protos_perfetto_config_descriptor",
-    deps = [
-        ":protos_perfetto_config_protos",
-    ],
-    outs = [
-        "protos_perfetto_config_descriptor.bin",
+        ":protos_perfetto_config_ftrace_cpp",
+        ":protos_perfetto_config_profiling_cpp",
+        ":protos_perfetto_config_gpu_cpp",
+        ":protos_perfetto_config_power_cpp",
+        ":protos_perfetto_common_cpp",
+        ":protos_perfetto_config_sys_stats_cpp",
     ],
 )
 
@@ -2008,46 +1672,6 @@
     ],
 )
 
-# GN target: //protos/perfetto/config/interceptors:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_interceptors_cpp",
-    deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_interceptors_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/interceptors:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_interceptors_lite",
-    deps = [
-        ":protos_perfetto_config_interceptors_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/interceptors:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_interceptors_protos",
-    srcs = [
-        "protos/perfetto/config/interceptors/console_config.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/interceptors:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_interceptors_zero",
-    deps = [
-        ":protos_perfetto_common_zero",
-        ":protos_perfetto_config_interceptors_protos",
-    ],
-)
-
 # GN target: //protos/perfetto/config:lite
 perfetto_cc_proto_library(
     name = "protos_perfetto_config_lite",
@@ -2073,28 +1697,6 @@
     visibility = PERFETTO_CONFIG.public_visibility,
 )
 
-# GN target: //protos/perfetto/config:perfetto_config_descriptor
-perfetto_proto_descriptor(
-    name = "protos_perfetto_config_perfetto_config_descriptor",
-    deps = [
-        ":protos_perfetto_config_perfetto_config_protos",
-    ],
-    outs = [
-        "protos_perfetto_config_perfetto_config_descriptor.bin",
-    ],
-)
-
-# GN target: //protos/perfetto/config:perfetto_config_descriptor
-perfetto_proto_library(
-    name = "protos_perfetto_config_perfetto_config_protos",
-    srcs = [
-        "protos/perfetto/config/perfetto_config.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
-)
-
 # GN target: //protos/perfetto/config/power:cpp
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_config_power_cpp",
@@ -2169,7 +1771,6 @@
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_config_profiling_cpp",
     deps = [
-        ":protos_perfetto_common_cpp",
         ":protos_perfetto_config_profiling_protos",
     ],
 )
@@ -2193,16 +1794,12 @@
     visibility = [
         PERFETTO_CONFIG.proto_library_visibility,
     ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
 )
 
 # GN target: //protos/perfetto/config/profiling:zero
 perfetto_cc_protozero_library(
     name = "protos_perfetto_config_profiling_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_config_profiling_protos",
     ],
 )
@@ -2213,8 +1810,6 @@
     srcs = [
         "protos/perfetto/config/chrome/chrome_config.proto",
         "protos/perfetto/config/data_source_config.proto",
-        "protos/perfetto/config/interceptor_config.proto",
-        "protos/perfetto/config/stress_test_config.proto",
         "protos/perfetto/config/test_config.proto",
         "protos/perfetto/config/trace_config.proto",
     ],
@@ -2225,7 +1820,6 @@
         ":protos_perfetto_config_ftrace_protos",
         ":protos_perfetto_config_gpu_protos",
         ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_interceptors_protos",
         ":protos_perfetto_config_power_protos",
         ":protos_perfetto_config_process_stats_protos",
         ":protos_perfetto_config_profiling_protos",
@@ -2238,8 +1832,8 @@
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_config_sys_stats_cpp",
     deps = [
-        ":protos_perfetto_common_cpp",
         ":protos_perfetto_config_sys_stats_protos",
+        ":protos_perfetto_common_cpp",
     ],
 )
 
@@ -2269,7 +1863,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_config_sys_stats_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_config_sys_stats_protos",
     ],
 )
@@ -2313,18 +1906,7 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_config_zero",
     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_interceptors_zero",
-        ":protos_perfetto_config_power_zero",
-        ":protos_perfetto_config_process_stats_zero",
-        ":protos_perfetto_config_profiling_zero",
         ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_zero",
-        ":protos_perfetto_config_track_event_zero",
     ],
 )
 
@@ -2332,19 +1914,18 @@
 perfetto_cc_protocpp_library(
     name = "protos_perfetto_ipc_cpp",
     deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_cpp",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_sys_stats_cpp",
-        ":protos_perfetto_config_track_event_cpp",
         ":protos_perfetto_ipc_protos",
+        ":protos_perfetto_config_process_stats_cpp",
+        ":protos_perfetto_config_android_cpp",
+        ":protos_perfetto_config_inode_file_cpp",
+        ":protos_perfetto_config_track_event_cpp",
+        ":protos_perfetto_config_ftrace_cpp",
+        ":protos_perfetto_config_profiling_cpp",
+        ":protos_perfetto_config_gpu_cpp",
+        ":protos_perfetto_config_cpp",
+        ":protos_perfetto_config_power_cpp",
+        ":protos_perfetto_common_cpp",
+        ":protos_perfetto_config_sys_stats_cpp",
     ],
 )
 
@@ -2352,20 +1933,20 @@
 perfetto_cc_ipc_library(
     name = "protos_perfetto_ipc_ipc",
     deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_cpp",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_sys_stats_cpp",
-        ":protos_perfetto_config_track_event_cpp",
-        ":protos_perfetto_ipc_cpp",
         ":protos_perfetto_ipc_protos",
+        ":protos_perfetto_config_android_cpp",
+        ":protos_perfetto_config_track_event_cpp",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
+        ":protos_perfetto_common_cpp",
+        ":protos_perfetto_config_process_stats_cpp",
+        ":protos_perfetto_config_ftrace_cpp",
+        ":protos_perfetto_config_inode_file_cpp",
+        ":protos_perfetto_config_profiling_cpp",
+        ":protos_perfetto_config_gpu_cpp",
+        ":protos_perfetto_config_cpp",
+        ":protos_perfetto_config_power_cpp",
+        ":protos_perfetto_ipc_cpp",
+        ":protos_perfetto_config_sys_stats_cpp",
     ],
 )
 
@@ -2385,13 +1966,13 @@
         ":protos_perfetto_config_ftrace_protos",
         ":protos_perfetto_config_gpu_protos",
         ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_interceptors_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_config_track_event_protos",
+        ":protos_perfetto_ipc_wire_protocol_protos",
     ],
 )
 
@@ -2422,21 +2003,16 @@
     ],
 )
 
-# GN target: //protos/perfetto/metrics/android:source_set
+# 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/display_metrics.proto",
-        "protos/perfetto/metrics/android/dma_heap_metric.proto",
-        "protos/perfetto/metrics/android/fastrpc_metric.proto",
-        "protos/perfetto/metrics/android/g2d_metric.proto",
-        "protos/perfetto/metrics/android/gpu_metric.proto",
-        "protos/perfetto/metrics/android/hwcomposer.proto",
+        "protos/perfetto/metrics/android/heap_profile_callsites.proto",
         "protos/perfetto/metrics/android/hwui_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
-        "protos/perfetto/metrics/android/jank_metric.proto",
         "protos/perfetto/metrics/android/java_heap_histogram.proto",
         "protos/perfetto/metrics/android/java_heap_stats.proto",
         "protos/perfetto/metrics/android/lmk_metric.proto",
@@ -2447,69 +2023,19 @@
         "protos/perfetto/metrics/android/powrails_metric.proto",
         "protos/perfetto/metrics/android/process_metadata.proto",
         "protos/perfetto/metrics/android/startup_metric.proto",
-        "protos/perfetto/metrics/android/surfaceflinger.proto",
-        "protos/perfetto/metrics/android/sysui_cuj_metrics.proto",
         "protos/perfetto/metrics/android/task_names.proto",
         "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
+        "protos/perfetto/metrics/android/unmapped_java_symbols.proto",
         "protos/perfetto/metrics/android/unsymbolized_frames.proto",
     ],
     visibility = PERFETTO_CONFIG.public_visibility,
 )
 
-# GN target: //protos/perfetto/metrics/chrome:descriptor
-perfetto_proto_descriptor(
-    name = "protos_perfetto_metrics_chrome_descriptor",
-    deps = [
-        ":protos_perfetto_metrics_chrome_protos",
-    ],
-    outs = [
-        "protos_perfetto_metrics_chrome_descriptor.bin",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics/chrome:source_set
-perfetto_proto_library(
-    name = "protos_perfetto_metrics_chrome_protos",
-    srcs = [
-        "protos/perfetto/metrics/chrome/all_chrome_metrics.proto",
-        "protos/perfetto/metrics/chrome/blink_gc_metric.proto",
-        "protos/perfetto/metrics/chrome/frame_times.proto",
-        "protos/perfetto/metrics/chrome/media_metric.proto",
-        "protos/perfetto/metrics/chrome/reported_by_page.proto",
-        "protos/perfetto/metrics/chrome/scroll_jank.proto",
-        "protos/perfetto/metrics/chrome/test_chrome_metric.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
+# GN target: //protos/perfetto/metrics/android:zero
+perfetto_cc_protozero_library(
+    name = "protos_perfetto_metrics_android_zero",
     deps = [
         ":protos_perfetto_metrics_android_protos",
-        ":protos_perfetto_metrics_custom_options_protos",
-        ":protos_perfetto_metrics_protos",
-    ] + PERFETTO_CONFIG.deps.protobuf_descriptor_proto,
-)
-
-# GN target: //protos/perfetto/metrics:custom_options_source_set
-perfetto_proto_library(
-    name = "protos_perfetto_metrics_custom_options_protos",
-    srcs = [
-        "protos/perfetto/metrics/custom_options.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
-    deps = [
-    ] + PERFETTO_CONFIG.deps.protobuf_descriptor_proto,
-)
-
-# GN target: //protos/perfetto/metrics:descriptor
-perfetto_proto_descriptor(
-    name = "protos_perfetto_metrics_descriptor",
-    deps = [
-        ":protos_perfetto_metrics_protos",
-    ],
-    outs = [
-        "protos_perfetto_metrics_descriptor.bin",
     ],
 )
 
@@ -2521,7 +2047,7 @@
     ],
 )
 
-# GN target: //protos/perfetto/metrics:source_set
+# GN target: //protos/perfetto/metrics:zero
 perfetto_proto_library(
     name = "protos_perfetto_metrics_protos",
     srcs = [
@@ -2533,6 +2059,14 @@
     ],
 )
 
+# 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",
@@ -2546,7 +2080,6 @@
     name = "protos_perfetto_trace_android_protos",
     srcs = [
         "protos/perfetto/trace/android/android_log.proto",
-        "protos/perfetto/trace/android/frame_timeline_event.proto",
         "protos/perfetto/trace/android/gpu_mem_event.proto",
         "protos/perfetto/trace/android/graphics_frame_event.proto",
         "protos/perfetto/trace/android/initial_display_state.proto",
@@ -2564,7 +2097,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_android_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_android_protos",
     ],
 )
@@ -2642,19 +2174,14 @@
         "protos/perfetto/trace/ftrace/cgroup.proto",
         "protos/perfetto/trace/ftrace/clk.proto",
         "protos/perfetto/trace/ftrace/compaction.proto",
-        "protos/perfetto/trace/ftrace/cpuhp.proto",
-        "protos/perfetto/trace/ftrace/dmabuf_heap.proto",
-        "protos/perfetto/trace/ftrace/dpu.proto",
         "protos/perfetto/trace/ftrace/ext4.proto",
         "protos/perfetto/trace/ftrace/f2fs.proto",
-        "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto",
         "protos/perfetto/trace/ftrace/generic.proto",
         "protos/perfetto/trace/ftrace/gpu_mem.proto",
         "protos/perfetto/trace/ftrace/i2c.proto",
@@ -2663,7 +2190,6 @@
         "protos/perfetto/trace/ftrace/irq.proto",
         "protos/perfetto/trace/ftrace/kmem.proto",
         "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-        "protos/perfetto/trace/ftrace/mali.proto",
         "protos/perfetto/trace/ftrace/mdss.proto",
         "protos/perfetto/trace/ftrace/mm_event.proto",
         "protos/perfetto/trace/ftrace/oom.proto",
@@ -2671,14 +2197,12 @@
         "protos/perfetto/trace/ftrace/raw_syscalls.proto",
         "protos/perfetto/trace/ftrace/regulator.proto",
         "protos/perfetto/trace/ftrace/sched.proto",
-        "protos/perfetto/trace/ftrace/scm.proto",
         "protos/perfetto/trace/ftrace/sde.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/thermal.proto",
         "protos/perfetto/trace/ftrace/vmscan.proto",
         "protos/perfetto/trace/ftrace/workqueue.proto",
     ],
@@ -2725,7 +2249,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_gpu_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_gpu_protos",
     ],
 )
@@ -2748,8 +2271,6 @@
         PERFETTO_CONFIG.proto_library_visibility,
     ],
     deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_trace_gpu_protos",
         ":protos_perfetto_trace_profiling_protos",
         ":protos_perfetto_trace_track_event_protos",
     ],
@@ -2759,11 +2280,7 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_interned_data_zero",
     deps = [
-        ":protos_perfetto_common_zero",
-        ":protos_perfetto_trace_gpu_zero",
         ":protos_perfetto_trace_interned_data_protos",
-        ":protos_perfetto_trace_profiling_zero",
-        ":protos_perfetto_trace_track_event_zero",
     ],
 )
 
@@ -2809,7 +2326,6 @@
         ":protos_perfetto_config_ftrace_protos",
         ":protos_perfetto_config_gpu_protos",
         ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_interceptors_protos",
         ":protos_perfetto_config_power_protos",
         ":protos_perfetto_config_process_stats_protos",
         ":protos_perfetto_config_profiling_protos",
@@ -2823,18 +2339,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_minimal_zero",
     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_interceptors_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_track_event_zero",
-        ":protos_perfetto_config_zero",
         ":protos_perfetto_trace_minimal_protos",
     ],
 )
@@ -2851,14 +2355,10 @@
 perfetto_proto_library(
     name = "protos_perfetto_trace_non_minimal_protos",
     srcs = [
-        "protos/perfetto/trace/extension_descriptor.proto",
-        "protos/perfetto/trace/memory_graph.proto",
         "protos/perfetto/trace/test_event.proto",
-        "protos/perfetto/trace/test_extensions.proto",
         "protos/perfetto/trace/trace.proto",
         "protos/perfetto/trace/trace_packet.proto",
         "protos/perfetto/trace/trace_packet_defaults.proto",
-        "protos/perfetto/trace/ui_state.proto",
     ],
     visibility = PERFETTO_CONFIG.public_visibility,
     deps = [
@@ -2867,7 +2367,6 @@
         ":protos_perfetto_config_ftrace_protos",
         ":protos_perfetto_config_gpu_protos",
         ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_interceptors_protos",
         ":protos_perfetto_config_power_protos",
         ":protos_perfetto_config_process_stats_protos",
         ":protos_perfetto_config_profiling_protos",
@@ -2895,33 +2394,7 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_non_minimal_zero",
     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_interceptors_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_track_event_zero",
-        ":protos_perfetto_config_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_protos",
-        ":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_system_info_zero",
-        ":protos_perfetto_trace_track_event_zero",
     ],
 )
 
@@ -2965,23 +2438,18 @@
 perfetto_proto_library(
     name = "protos_perfetto_trace_power_protos",
     srcs = [
-        "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto",
         "protos/perfetto/trace/power/battery_counters.proto",
         "protos/perfetto/trace/power/power_rails.proto",
     ],
     visibility = [
         PERFETTO_CONFIG.proto_library_visibility,
     ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
 )
 
 # GN target: //protos/perfetto/trace/power:zero
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_power_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_power_protos",
     ],
 )
@@ -3015,7 +2483,8 @@
         PERFETTO_CONFIG.proto_library_visibility,
     ],
     deps = [
-        ":protos_perfetto_common_protos",
+        ":protos_perfetto_metrics_android_protos",
+        ":protos_perfetto_metrics_protos",
     ],
 )
 
@@ -3023,7 +2492,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_processor_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_processor_protos",
     ],
 )
@@ -3040,7 +2508,6 @@
 perfetto_proto_library(
     name = "protos_perfetto_trace_profiling_protos",
     srcs = [
-        "protos/perfetto/trace/profiling/deobfuscation.proto",
         "protos/perfetto/trace/profiling/heap_graph.proto",
         "protos/perfetto/trace/profiling/profile_common.proto",
         "protos/perfetto/trace/profiling/profile_packet.proto",
@@ -3049,16 +2516,12 @@
     visibility = [
         PERFETTO_CONFIG.proto_library_visibility,
     ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
 )
 
 # GN target: //protos/perfetto/trace/profiling:zero
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_profiling_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_profiling_protos",
     ],
 )
@@ -3117,7 +2580,6 @@
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_sys_stats_zero",
     deps = [
-        ":protos_perfetto_common_zero",
         ":protos_perfetto_trace_sys_stats_protos",
     ],
 )
@@ -3169,21 +2631,14 @@
 perfetto_proto_library(
     name = "protos_perfetto_trace_track_event_protos",
     srcs = [
-        "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
         "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
-        "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
-        "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
         "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
         "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
         "protos/perfetto/trace/track_event/chrome_latency_info.proto",
         "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
-        "protos/perfetto/trace/track_event/chrome_message_pump.proto",
-        "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
         "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
-        "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
         "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
         "protos/perfetto/trace/track_event/chrome_user_event.proto",
-        "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
         "protos/perfetto/trace/track_event/counter_descriptor.proto",
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
@@ -3199,31 +2654,6 @@
     ],
 )
 
-# GN target: //protos/perfetto/trace/track_event:track_event_descriptor
-perfetto_proto_descriptor(
-    name = "protos_perfetto_trace_track_event_track_event_descriptor",
-    deps = [
-        ":protos_perfetto_trace_track_event_track_event_protos",
-    ],
-    outs = [
-        "protos_perfetto_trace_track_event_track_event_descriptor.bin",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/track_event:track_event_descriptor
-perfetto_proto_library(
-    name = "protos_perfetto_trace_track_event_track_event_protos",
-    srcs = [
-        "protos/perfetto/trace/track_event/track_event.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
-    deps = [
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
 # GN target: //protos/perfetto/trace/track_event:zero
 perfetto_cc_protozero_library(
     name = "protos_perfetto_trace_track_event_zero",
@@ -3232,31 +2662,6 @@
     ],
 )
 
-# GN target: //protos/third_party/chromium:chrome_track_event_descriptor
-perfetto_proto_descriptor(
-    name = "protos_third_party_chromium_chrome_track_event_descriptor",
-    deps = [
-        ":protos_third_party_chromium_chrome_track_event_protos",
-    ],
-    outs = [
-        "protos_third_party_chromium_chrome_track_event_descriptor.bin",
-    ],
-)
-
-# GN target: //protos/third_party/chromium:chrome_track_event_descriptor
-perfetto_proto_library(
-    name = "protos_third_party_chromium_chrome_track_event_protos",
-    srcs = [
-        "protos/third_party/chromium/chrome_track_event.proto",
-    ],
-    visibility = [
-        PERFETTO_CONFIG.proto_library_visibility,
-    ],
-    deps = [
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
 # GN target: //protos/third_party/pprof:zero
 perfetto_proto_library(
     name = "protos_third_party_pprof_protos",
@@ -3303,11 +2708,12 @@
 perfetto_cc_library(
     name = "libperfetto_client_experimental",
     srcs = [
-        ":src_android_stats_android_stats",
-        ":src_android_stats_perfetto_atoms",
-        ":src_protozero_filtering_bytecode_common",
-        ":src_protozero_filtering_bytecode_parser",
-        ":src_protozero_filtering_message_filter",
+        ":src_base_base",
+        ":src_base_unix_socket",
+        ":src_ipc_client",
+        ":src_ipc_common",
+        ":src_ipc_host",
+        ":src_protozero_protozero",
         ":src_tracing_client_api_without_backends",
         ":src_tracing_common",
         ":src_tracing_core_core",
@@ -3317,7 +2723,7 @@
         ":src_tracing_ipc_consumer_consumer",
         ":src_tracing_ipc_producer_producer",
         ":src_tracing_ipc_service_service",
-        ":src_tracing_platform_impl",
+        ":src_tracing_platform_posix",
         ":src_tracing_system_backend",
     ],
     hdrs = [
@@ -3336,7 +2742,6 @@
         "//visibility:public",
     ],
     deps = [
-        ":perfetto_ipc",
         ":protos_perfetto_common_cpp",
         ":protos_perfetto_common_zero",
         ":protos_perfetto_config_android_cpp",
@@ -3348,8 +2753,6 @@
         ":protos_perfetto_config_gpu_zero",
         ":protos_perfetto_config_inode_file_cpp",
         ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_interceptors_zero",
         ":protos_perfetto_config_power_cpp",
         ":protos_perfetto_config_power_zero",
         ":protos_perfetto_config_process_stats_cpp",
@@ -3363,6 +2766,7 @@
         ":protos_perfetto_config_zero",
         ":protos_perfetto_ipc_cpp",
         ":protos_perfetto_ipc_ipc",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
         ":protos_perfetto_trace_android_zero",
         ":protos_perfetto_trace_chrome_zero",
         ":protos_perfetto_trace_filesystem_zero",
@@ -3379,8 +2783,6 @@
         ":protos_perfetto_trace_system_info_zero",
         ":protos_perfetto_trace_track_event_cpp",
         ":protos_perfetto_trace_track_event_zero",
-        ":protozero",
-        ":src_base_base",
     ],
     linkstatic = True,
 )
@@ -3389,6 +2791,7 @@
 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",
@@ -3399,22 +2802,26 @@
         ":include_perfetto_tracing_core_core",
         ":include_perfetto_tracing_core_forward_decls",
         ":include_perfetto_tracing_tracing",
-        ":src_android_stats_android_stats",
-        ":src_android_stats_perfetto_atoms",
+        ":src_android_internal_headers",
+        ":src_android_internal_lazy_library_loader",
+        ":src_base_base",
+        ":src_base_unix_socket",
+        ":src_ipc_client",
+        ":src_ipc_common",
+        ":src_perfetto_cmd_perfetto_atoms",
         ":src_perfetto_cmd_perfetto_cmd",
         ":src_perfetto_cmd_trigger_producer",
+        ":src_protozero_protozero",
         ":src_tracing_common",
         ":src_tracing_core_core",
         ":src_tracing_ipc_common",
         ":src_tracing_ipc_consumer_consumer",
         ":src_tracing_ipc_producer_producer",
-        "src/perfetto_cmd/main.cc",
     ],
     visibility = [
         "//visibility:public",
     ],
     deps = [
-        ":perfetto_ipc",
         ":protos_perfetto_common_cpp",
         ":protos_perfetto_common_zero",
         ":protos_perfetto_config_android_cpp",
@@ -3426,8 +2833,6 @@
         ":protos_perfetto_config_gpu_zero",
         ":protos_perfetto_config_inode_file_cpp",
         ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_interceptors_cpp",
-        ":protos_perfetto_config_interceptors_zero",
         ":protos_perfetto_config_power_cpp",
         ":protos_perfetto_config_power_zero",
         ":protos_perfetto_config_process_stats_cpp",
@@ -3441,6 +2846,7 @@
         ":protos_perfetto_config_zero",
         ":protos_perfetto_ipc_cpp",
         ":protos_perfetto_ipc_ipc",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
         ":protos_perfetto_trace_android_zero",
         ":protos_perfetto_trace_chrome_zero",
         ":protos_perfetto_trace_filesystem_zero",
@@ -3457,9 +2863,6 @@
         ":protos_perfetto_trace_system_info_zero",
         ":protos_perfetto_trace_track_event_cpp",
         ":protos_perfetto_trace_track_event_zero",
-        ":protozero",
-        ":src_base_base",
-        ":src_perfetto_cmd_gen_cc_config_descriptor",
         ":src_perfetto_cmd_protos",
     ] + PERFETTO_CONFIG.deps.zlib,
 )
@@ -3468,12 +2871,14 @@
 perfetto_cc_library(
     name = "trace_processor",
     srcs = [
+        ":src_base_base",
+        ":src_protozero_protozero",
         ":src_trace_processor_analysis_analysis",
-        ":src_trace_processor_db_db",
+        ":src_trace_processor_containers_containers",
+        ":src_trace_processor_db_lib",
         ":src_trace_processor_export_json",
         ":src_trace_processor_ftrace_descriptors",
-        ":src_trace_processor_importers_common_common",
-        ":src_trace_processor_importers_memory_tracker_graph_processor",
+        ":src_trace_processor_importers_common",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_lib",
@@ -3482,18 +2887,17 @@
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
         ":src_trace_processor_tables_tables",
+        ":src_trace_processor_track_event_descriptor",
         ":src_trace_processor_types_types",
         ":src_trace_processor_util_descriptors",
-        ":src_trace_processor_util_proto_to_args_parser",
-        ":src_trace_processor_util_protozero_to_text",
         ":src_trace_processor_util_util",
     ],
     hdrs = [
         ":include_perfetto_base_base",
         ":include_perfetto_ext_base_base",
         ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
         ":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",
@@ -3507,13 +2911,14 @@
                ":protos_perfetto_config_ftrace_zero",
                ":protos_perfetto_config_gpu_zero",
                ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_interceptors_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_track_event_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",
@@ -3525,20 +2930,11 @@
                ":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_system_info_zero",
                ":protos_perfetto_trace_track_event_zero",
-               ":protozero",
-               ":src_base_base",
-               ":src_trace_processor_containers_containers",
-               ":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-               ":src_trace_processor_importers_gen_cc_config_descriptor",
-               ":src_trace_processor_importers_gen_cc_track_event_descriptor",
-               ":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-               ":src_trace_processor_metrics_gen_cc_metrics_descriptor",
            ] + PERFETTO_CONFIG.deps.jsoncpp +
            PERFETTO_CONFIG.deps.sqlite +
            PERFETTO_CONFIG.deps.sqlite_ext_percentile +
@@ -3552,24 +2948,28 @@
 perfetto_cc_binary(
     name = "trace_processor_shell",
     srcs = [
+        "src/trace_processor/trace_processor_shell.cc",
+        "src/trace_processor/util/proto_to_json.cc",
+        "src/trace_processor/util/proto_to_json.h",
         ":include_perfetto_base_base",
         ":include_perfetto_ext_base_base",
         ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
         ":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_profiling_deobfuscator",
+        ":src_base_base",
+        ":src_base_unix_socket",
         ":src_profiling_symbolizer_symbolize_database",
         ":src_profiling_symbolizer_symbolizer",
+        ":src_protozero_protozero",
         ":src_trace_processor_analysis_analysis",
-        ":src_trace_processor_db_db",
+        ":src_trace_processor_containers_containers",
+        ":src_trace_processor_db_lib",
         ":src_trace_processor_export_json",
         ":src_trace_processor_ftrace_descriptors",
-        ":src_trace_processor_importers_common_common",
-        ":src_trace_processor_importers_memory_tracker_graph_processor",
+        ":src_trace_processor_importers_common",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_lib",
@@ -3580,14 +2980,10 @@
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
         ":src_trace_processor_tables_tables",
+        ":src_trace_processor_track_event_descriptor",
         ":src_trace_processor_types_types",
         ":src_trace_processor_util_descriptors",
-        ":src_trace_processor_util_proto_to_args_parser",
-        ":src_trace_processor_util_protozero_to_text",
         ":src_trace_processor_util_util",
-        "src/trace_processor/trace_processor_shell.cc",
-        "src/trace_processor/util/proto_to_json.cc",
-        "src/trace_processor/util/proto_to_json.h",
     ],
     visibility = [
         "//visibility:public",
@@ -3598,13 +2994,14 @@
                ":protos_perfetto_config_ftrace_zero",
                ":protos_perfetto_config_gpu_zero",
                ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_interceptors_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_track_event_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",
@@ -3622,18 +3019,9 @@
                ":protos_perfetto_trace_sys_stats_zero",
                ":protos_perfetto_trace_system_info_zero",
                ":protos_perfetto_trace_track_event_zero",
-               ":protozero",
-               ":src_base_base",
-               ":src_base_unix_socket",
-               ":src_trace_processor_containers_containers",
-               ":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-               ":src_trace_processor_importers_gen_cc_config_descriptor",
-               ":src_trace_processor_importers_gen_cc_track_event_descriptor",
-               ":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-               ":src_trace_processor_metrics_gen_cc_metrics_descriptor",
            ] + PERFETTO_CONFIG.deps.jsoncpp +
            PERFETTO_CONFIG.deps.linenoise +
-           PERFETTO_CONFIG.deps.protobuf_full +
+           PERFETTO_CONFIG.deps.protoc_lib +
            PERFETTO_CONFIG.deps.sqlite +
            PERFETTO_CONFIG.deps.sqlite_ext_percentile +
            PERFETTO_CONFIG.deps.zlib + [
@@ -3645,8 +3033,8 @@
 perfetto_cc_binary(
     name = "traced_probes",
     srcs = [
-        ":include_perfetto_ext_traced_traced",
         "src/traced/probes/main.cc",
+        ":include_perfetto_ext_traced_traced",
     ],
     visibility = [
         "//visibility:public",
@@ -3660,8 +3048,8 @@
 perfetto_cc_binary(
     name = "traced",
     srcs = [
-        ":include_perfetto_ext_traced_traced",
         "src/traced/service/main.cc",
+        ":include_perfetto_ext_traced_traced",
     ],
     visibility = [
         "//visibility:public",
@@ -3684,6 +3072,7 @@
     hdrs = [
         ":include_perfetto_base_base",
         ":include_perfetto_ext_base_base",
+        ":include_perfetto_profiling_deobfuscator",
         ":include_perfetto_profiling_pprof_builder",
         ":include_perfetto_protozero_protozero",
         ":include_perfetto_trace_processor_basic_types",
@@ -3699,7 +3088,6 @@
         ":protos_perfetto_config_ftrace_zero",
         ":protos_perfetto_config_gpu_zero",
         ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_interceptors_zero",
         ":protos_perfetto_config_power_zero",
         ":protos_perfetto_config_process_stats_zero",
         ":protos_perfetto_config_profiling_zero",
@@ -3722,8 +3110,6 @@
         ":protos_perfetto_trace_system_info_zero",
         ":protos_perfetto_trace_track_event_zero",
         ":protos_third_party_pprof_zero",
-        ":protozero",
-        ":src_trace_processor_containers_containers",
     ] + PERFETTO_CONFIG.deps.zlib,
     linkstatic = True,
 )
@@ -3735,22 +3121,24 @@
         ":include_perfetto_base_base",
         ":include_perfetto_ext_base_base",
         ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_trace_processor_importers_memory_tracker_memory_tracker",
         ":include_perfetto_ext_traced_sys_stats_counters",
+        ":include_perfetto_profiling_deobfuscator",
         ":include_perfetto_profiling_pprof_builder",
         ":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_profiling_deobfuscator",
         ":src_profiling_symbolizer_symbolize_database",
         ":src_profiling_symbolizer_symbolizer",
+        ":src_protozero_protozero",
         ":src_trace_processor_analysis_analysis",
-        ":src_trace_processor_db_db",
+        ":src_trace_processor_containers_containers",
+        ":src_trace_processor_db_lib",
         ":src_trace_processor_export_json",
         ":src_trace_processor_ftrace_descriptors",
-        ":src_trace_processor_importers_common_common",
-        ":src_trace_processor_importers_memory_tracker_graph_processor",
+        ":src_trace_processor_importers_common",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_lib",
@@ -3759,10 +3147,9 @@
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
         ":src_trace_processor_tables_tables",
+        ":src_trace_processor_track_event_descriptor",
         ":src_trace_processor_types_types",
         ":src_trace_processor_util_descriptors",
-        ":src_trace_processor_util_proto_to_args_parser",
-        ":src_trace_processor_util_protozero_to_text",
         ":src_trace_processor_util_util",
         ":tools_trace_to_text_common",
         ":tools_trace_to_text_full",
@@ -3778,13 +3165,14 @@
                ":protos_perfetto_config_ftrace_zero",
                ":protos_perfetto_config_gpu_zero",
                ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_interceptors_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_track_event_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",
@@ -3796,21 +3184,12 @@
                ":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_system_info_zero",
                ":protos_perfetto_trace_track_event_zero",
                ":protos_third_party_pprof_zero",
-               ":protozero",
-               ":src_base_base",
-               ":src_trace_processor_containers_containers",
-               ":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
-               ":src_trace_processor_importers_gen_cc_config_descriptor",
-               ":src_trace_processor_importers_gen_cc_track_event_descriptor",
-               ":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
-               ":src_trace_processor_metrics_gen_cc_metrics_descriptor",
            ] + PERFETTO_CONFIG.deps.jsoncpp +
            PERFETTO_CONFIG.deps.protobuf_full +
            PERFETTO_CONFIG.deps.sqlite +
@@ -3846,15 +3225,6 @@
     python_version = "PY3",
 )
 
-perfetto_py_binary(
-    name = "gen_cc_proto_descriptor_py",
-    srcs = [
-        "tools/gen_cc_proto_descriptor.py",
-    ],
-    main = "tools/gen_cc_proto_descriptor.py",
-    python_version = "PY3",
-)
-
 perfetto_java_proto_library(
     name = "protos_perfetto_metrics_java",
     deps = [
@@ -3901,72 +3271,3 @@
         "__TRACE_PROCESSOR_SIG_TAG2",
     ],
 )
-
-# This is overridden in google internal builds via
-# PERFETTO_CONFIG.deps.version_header (see perfetto_cfg.bzl).
-perfetto_cc_library(
-    name = "cc_perfetto_version_header",
-    hdrs = ["perfetto_version.gen.h"],
-)
-
-perfetto_py_binary(
-    name = "gen_version_header_py",
-    srcs = ["tools/write_version_header.py"],
-    data = ["CHANGELOG"],
-    main = "tools/write_version_header.py",
-    python_version = "PY3",
-)
-
-# Noop targets used to represent targets of the protobuf library.
-# These will be rewritten in Google3 to be dependencies on the real targets.
-
-perfetto_py_library(
-    name = "pyglib_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "protobuf_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "protobuf_descriptor_pb2_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "gfile_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "trace_processor_init_noop",
-    srcs = [],
-)
-
-perfetto_py_binary(
-    name = "trace_processor_py_example",
-    srcs = ["src/trace_processor/python/example.py"],
-    deps = [":trace_processor_py"],
-    main = "src/trace_processor/python/example.py",
-    python_version = "PY3",
-)
-
-perfetto_py_library(
-    name = "trace_processor_py",
-    srcs = glob(["src/trace_processor/python/perfetto/trace_processor/*.py"]),
-    data = [
-        ":trace_processor_init_noop",
-        "src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor",
-        "src/trace_processor/python/perfetto/trace_processor/metrics.descriptor",
-        ":trace_processor_shell",
-    ],
-    deps = [
-        ":gfile_noop",
-        ":protobuf_noop",
-        ":protobuf_descriptor_pb2_noop",
-        ":pyglib_noop",
-    ],
-    visibility = PERFETTO_CONFIG.public_visibility,
-)
diff --git a/BUILD.extras b/BUILD.extras
index 53392a7..6a0c30e 100644
--- a/BUILD.extras
+++ b/BUILD.extras
@@ -22,15 +22,6 @@
     python_version = "PY3",
 )
 
-perfetto_py_binary(
-    name = "gen_cc_proto_descriptor_py",
-    srcs = [
-        "tools/gen_cc_proto_descriptor.py",
-    ],
-    main = "tools/gen_cc_proto_descriptor.py",
-    python_version = "PY3",
-)
-
 perfetto_java_proto_library(
     name = "protos_perfetto_metrics_java",
     deps = [
@@ -77,72 +68,3 @@
         "__TRACE_PROCESSOR_SIG_TAG2",
     ],
 )
-
-# This is overridden in google internal builds via
-# PERFETTO_CONFIG.deps.version_header (see perfetto_cfg.bzl).
-perfetto_cc_library(
-    name = "cc_perfetto_version_header",
-    hdrs = ["perfetto_version.gen.h"],
-)
-
-perfetto_py_binary(
-    name = "gen_version_header_py",
-    srcs = ["tools/write_version_header.py"],
-    data = ["CHANGELOG"],
-    main = "tools/write_version_header.py",
-    python_version = "PY3",
-)
-
-# Noop targets used to represent targets of the protobuf library.
-# These will be rewritten in Google3 to be dependencies on the real targets.
-
-perfetto_py_library(
-    name = "pyglib_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "protobuf_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "protobuf_descriptor_pb2_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "gfile_noop",
-    srcs = [],
-)
-
-perfetto_py_library(
-    name = "trace_processor_init_noop",
-    srcs = [],
-)
-
-perfetto_py_binary(
-    name = "trace_processor_py_example",
-    srcs = ["src/trace_processor/python/example.py"],
-    deps = [":trace_processor_py"],
-    main = "src/trace_processor/python/example.py",
-    python_version = "PY3",
-)
-
-perfetto_py_library(
-    name = "trace_processor_py",
-    srcs = glob(["src/trace_processor/python/perfetto/trace_processor/*.py"]),
-    data = [
-        ":trace_processor_init_noop",
-        "src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor",
-        "src/trace_processor/python/perfetto/trace_processor/metrics.descriptor",
-        ":trace_processor_shell",
-    ],
-    deps = [
-        ":gfile_noop",
-        ":protobuf_noop",
-        ":protobuf_descriptor_pb2_noop",
-        ":pyglib_noop",
-    ],
-    visibility = PERFETTO_CONFIG.public_visibility,
-)
diff --git a/BUILD.gn b/BUILD.gn
index 6f6cc7d..cb5ee8a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -35,10 +35,8 @@
     "src/perfetto_cmd:perfetto",
     "src/perfetto_cmd:trigger_perfetto",
     "src/traced/service:traced",
+    "src/traced/probes:traced_probes",
   ]
-  if (enable_perfetto_traced_probes) {
-    all_targets += [ "src/traced/probes:traced_probes" ]
-  }
 }
 
 if (enable_perfetto_trace_processor && enable_perfetto_trace_processor_sqlite) {
@@ -47,15 +45,8 @@
 
 if (enable_perfetto_heapprofd) {
   all_targets += [ "src/profiling/memory:heapprofd" ]
-
-  if (is_linux && !is_android) {
-    all_targets += [ "src/profiling/memory:heapprofd_glibc_preload" ]
-  }
   if (perfetto_build_with_android) {
-    all_targets += [
-      "src/profiling/memory:heapprofd_client",
-      "src/profiling/memory:heapprofd_client_api",
-    ]
+    all_targets += [ "src/profiling/memory:heapprofd_client" ]
   }
 }
 
@@ -64,7 +55,7 @@
 }
 
 if (perfetto_build_with_android) {
-  all_targets += [ "src/android_internal:libperfetto_android_internal" ]
+  all_targets += [ "src/android_internal/:libperfetto_android_internal" ]
 }
 
 if (enable_perfetto_tools) {
@@ -87,7 +78,6 @@
   all_targets += [
     ":perfetto_integrationtests",
     "test:client_api_example",
-    "test/stress_test",
   ]
 }
 
@@ -124,6 +114,7 @@
 # compile-time checks for the CI.
 if (perfetto_build_standalone) {
   all_targets += [
+    "src/tracing/consumer_api_deprecated:consumer_api_test",
     "test/configs",
 
     # For syntax-checking the proto.
@@ -135,15 +126,16 @@
     "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",
 
     # Checks that the "fake" backend implementations build.
     "src/tracing:client_api_no_backends_compile_test",
   ]
-  if (is_linux || is_android) {
-    all_targets += [ "src/tracing/consumer_api_deprecated:consumer_api_test" ]
-  }
 }
 
 # The CTS code is built (but not ran) also in standalone builds. This is to
@@ -177,6 +169,10 @@
   group("ui") {
     deps = [ "ui" ]
   }
+
+  group("site") {
+    deps = [ "infra/perfetto.dev:site" ]
+  }
 }
 
 # In Android builds, we build the code of traced and traced_probes in one shared
@@ -203,16 +199,10 @@
     }
     deps = [
       "gn:default_deps",
+      "src/traced/probes",
       "src/traced/service",
+      "src/tracing/consumer_api_deprecated",
     ]
-    if (enable_perfetto_traced_probes) {
-      deps += [ "src/traced/probes" ]
-    }
-    if (is_linux || is_android || is_mac) {
-      # TODO(primiano): this is here only for Android's iorapd. At some point
-      # we need to migrate iorapd to the Perfetto SDK.
-      deps += [ "src/tracing/consumer_api_deprecated" ]
-    }
   }
 }
 
@@ -226,7 +216,7 @@
     public_deps = [
       "gn:default_deps",
       "src/tracing:client_api",
-      "src/tracing:platform_impl",
+      "src/tracing:platform_posix",
     ]
     sources = [ "include/perfetto/tracing.h" ]
     assert_no_deps = [ "//gn:protobuf_lite" ]
@@ -241,7 +231,6 @@
   component("libperfetto") {
     public_configs = [ "gn:public_config" ]
     deps = [
-      "src/trace_processor/importers/memory_tracker:graph_processor",
       "src/tracing:client_api",
       "src/tracing/core",
 
@@ -251,7 +240,6 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     public_deps = [
-      "include/perfetto/ext/trace_processor/importers/memory_tracker",
       "include/perfetto/ext/tracing/core",
       "include/perfetto/tracing",
       "protos/perfetto/common:zero",
@@ -259,7 +247,6 @@
       "protos/perfetto/trace/chrome:zero",
       "protos/perfetto/trace/interned_data:zero",
       "protos/perfetto/trace/profiling:zero",
-      "protos/perfetto/trace/ps:zero",
       "protos/perfetto/trace/track_event:zero",
     ]
     if (enable_perfetto_ipc) {
@@ -287,12 +274,4 @@
     configs += [ "//build/config/compiler:no_chromium_code" ]
     public_deps = [ "include/perfetto/trace_processor" ]
   }
-  component("perfetto_test_support") {
-    testonly = true
-    public_configs = [ "gn:public_config" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    public_deps = [ "include/perfetto/test:test_support" ]
-    deps = [ "src/tracing/test:test_support" ]
-  }
 }
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 114c03d..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,308 +0,0 @@
-Unreleased:
-  Tracing service and probes:
-    *
-  Trace Processor:
-    *
-  UI:
-    *
-  SDK:
-    *
-
-
-v15.0 - 2021-05-05:
-  Tracing service and probes:
-    * Added support for {host,target}=aarch64 standalone builds.
-    * Added --background cmdline switch to traced and traced_probes services.
-    * Changed trigger_perfetto to ignore unknown command line arguments to
-      preserve forward compatibility.
-    * Added -a / --app cmdline argument to tools/record_android_trace.
-  Trace Processor:
-    * Added sanitisation of keys in nested debug annotation dictionaries.
-    * Changed Android startup metric: count CPU time of JIT thread pool, report
-      timestamp of activities during startup.
-    * Changed android_surfaceflinger metric, added missed frame counters.
-    * Changed version of SQLite to 3.35.4.
-    * Fixed importing of JSON traces with decimal (sub-us) timestamp.
-    * Fixed prepending "debug." prefix to debug annotations with non-interned
-      names.
-  UI:
-    * Added support to visualize the lifetime of individual dmabuf allocations
-      as async slices (datasource: already existing ftrace dmabuf event).
-    * Fixed visualization of unfinished slices to extend to the end of the
-      viewport.
-  SDK:
-    * Added support for passing arbitrary number of debug annotations to
-      TRACE_EVENT and combining them with lambdas.
-    * Added support for writing typed TrackEvent arguments using TRACE_EVENT
-      inline without lambdas.
-    * Changed ConvertTimestampToTraceTimeNs to be a member of
-      TraceTimestampTraits<T> struct instead of a standalone function.
-    * Changed TracedValue to use nested DebugAnnotation proto instead of
-      DebugAnnotation::NestedValue.
-
-
-v14.0 - 2021-04-01:
-  Tracing service and probes:
-    * Added support for polling power rails on Android from the newer
-      IPowerStats AIDL interface (previously using only the HAL interface).
-    * Fixed native heap profiler crash when ABI of heapprofd and profiled
-      process mismatch.
-    * Changed encoding format of Anroid managed heap profiler to reduce heap
-      dump sizes by delta-encoding object IDs.
-  Trace Processor:
-    * Added activity create/resume, layout inflation and resource timings to
-      the Android startup metric.
-    * Added chrome metadata key/value pairs (e.g. chrome version) into the
-      `metadata` table with 'cr-' prefixed keys.
-    * Added dma-buf-based memory metrics reporting total/avg/min/max dmabuf
-      allocation per-dmabuf-heap and per-process.
-    * Removed |force_full_sort| flag from config. This has been replaced
-      by setting the sorting mode to force a full sort.
-  UI:
-    * Added tools/symbolize-ui-crash script to resolve crash reports via
-      TypeScript source maps.
-    * Fixed newlines when copying Android event log lines into the clipboard.
-    * Fixed crash when selecting "Did not finish" slices.
-    * Fixed OOM dialog to give actionable instructions when opening large traces
-      rather than suggesting to file a bug.
-  SDK:
-    * Added /meson.build for bundling /sdk/perfetto.{cc,h} in Meson builds.
-    * Added support for counter trace points with the TRACE_COUNTER macro.
-
-
-v13.0 - 2021-03-01:
-  Tracing service and probes:
-    * Added ability to sample callstacks using kernel tracepoints as timebase.
-    * Added abililty to record the perf timebase counter values into the trace,
-      both combined callstack+counter or counter-only.
-    * Added abillity to trigger traces based on VM pressure on Android. Requires
-      a dedicated tracing instance in $tracefs/instances/mm_events.
-  Trace Processor:
-    * Added sorting mode to trace processor config to specify how trace
-      processor should sort events. The |force_full_sort| flag has been
-      deprecated (with replacement) and will be removed in the next version.
-    * Added ingestion of frame timeline events into the
-      {expected,actual}_frame_timeline_slice tables.
-    * Added support for Mali's trace_marker_write ftrace event.
-    * Added memory metric based on newer android_fastrpc kernel events.
-  UI:
-    * Added flow events support for instant events and async tracks.
-    * Added support for Android frame timeline events. They allow inspecting
-      end-to-end expected vs actual app-to-surfaceflinger frame times.
-    * Added ability to switch between Canary and Stable channels in the UI.
-    * Added ability to drag&drop to open trace files.
-    * Changed UI serving infrastructure, old ui versions can be now retrieved by
-      directly opening https://ui.perfetto.dev/v12.1.269/ .
-    * Removed thread state track for threads that have no activity.
-  SDK:
-    * Use process start time hashed with the process id as a unique process
-      identifier, allowing multiple independent users of the SDK in the same
-      process to interleave their events on shared tracks.
-    * Record process and thread names into the trace.
-    * Add ring buffer tracing support, i.e., periodic clearing of incremental
-      state.
-  Misc:
-    * Convert python scripts to python3.
-
-
-v12.1 - 2021-02-01:
-  Misc:
-    * Fixed CHANGELOG which was missed in the 12.0 branch cut, causing
-      mis-labeling of the version code in the v12.x branch as v11.0..N
-
-
-v12.0 - 2021-02-01:
-  Tracing service and probes:
-    * Added more helpful error messages if the client library is used without
-      having been initialized.
-    * Added //tools/record_android_trace script to facilitate recording traces
-      from Android devices, automating start + stop-via-ctrl+c + pull + open.
-    * Added auto-attachment of traces to Android bugreports if dumpstate is
-      invoked when a trace with bugreport_score > 0 is running.
-  SDK:
-    * Added ability to customize the timestamp of events via
-      ConvertTimestampToTraceTimeNs().
-    * Fixed support for category names that contain a space.
-  Trace Processor:
-    * Added ingestion and query support for Android end-to-end frame timing
-      events through the {actual, expected}_frame_timeline_slice tables.
-    * Added time-to-reportFullyDrawn (Android's API) to startup metrics.
-    * Fixed excessive memory usage when decoding traces containing callstacks
-      (https://github.com/google/perfetto/issues/83).
-  UI:
-    * Added ability to inspect the full trace config string from the
-      'Info and stats' page.
-    * Fixed 'TABLE/VIEW XXX already exists' in the Metrics page when running the
-      same metric twice.
-    * Fixed sorting of tracks using numeric sorting instead of lexicographic:
-      Thread {1, 2, 10, 11, 20} rather than Thread {1, 10, 11, 2, 20}.
-    * Fixed CSP-related bug that was preventing the UI to work on Firefox.
-    * Changed max zoom resolution to allow to zoom to sub-us events.
-
-
-v11.0 - 2021-01-01:
-  Tracing service and probes:
-    * Added trace packet interceptor API for rerouting trace data into
-      non-Perfetto systems.
-    * Added support for printing track events to the console.
-    * Added a way to observe track event tracing sessions starting and
-      stopping.
-  Trace Processor:
-    * Added "ancestor_slice" and "experimental_ancestor_stack_profile_callsite"
-      table functions to look up ancestors of CPU stack samples in profiler
-      tables.
-    * Added power metric reporting suspend/resume time periods.
-  UI:
-    * Fixed CPU time calculation in example queries.
-    * Added tracks to debug Android SystemUI jank.
-
-
-v10.0 - 2020-12-01:
-  Tracing service and probes:
-    * Fixed crash of tracing service if a client is unresponsive on the IPC
-      channel. Clients are disconnected if they don't respond to IPCs for 10s.
-    * Added cmdline arguments for integration within ChromeOS system image
-      (--{producer,consumer}-socket-{group,mode} for chmod-ing sockets).
-    * Changed path lookup logic for traced socket. /run/perfetto/ is used if the
-      directory exists, falling back on /tmp/ otherwise.
-    * Added support for kernel frame symbolization to the traced_perf callstack
-      sampler.
-    * Added support for resolving ftrace event arguments that require
-      symbolization against printk_format.
-  Trace Processor:
-    * Added .read command to inject a SQL query file, similar to the -q cmdline.
-    * Added trace-based metrics to root cause jank in Android System UI.
-    * Added symbolization support for ELF files on Windows for heap and
-      callstack profilers.
-    * Added support for symbolizing names of workqueue ftrace events.
-    * Improved Android startup metric with activity restart time.
-  UI:
-    * Added support for navigating flows with Ctrl+[ / Ctr+].
-    * Improved query result panel, moved to the bottom group allowing
-      simultaneous query result and timeline views.
-    * Fixed data corruption when recording traces via the WebUSB-based Record
-      page in the UI.
-
-
-v9.0 - 2020-11-01:
-  Tracing service and probes:
-    * Added support for recording traces from a system service through the
-      client API.
-    * The client library now reconnects producers automatically if the
-      connection to the tracing service is lost. Also fixed crashes in ongoing
-      tracing sessions when a disconnect occurs.
-    * Added support for dpu and g2d ftrace events.
-    * Enabled commit batching and producer side patching of chunks.
-    * Add support for symbolizing kernel symbols for ftrace events.
-  Trace Processor:
-    * Fixed type affinity of string columns.
-  UI:
-    * Added initial support for running metrics from the UI.
-    * Added support for displaying all flows when a slice or area is selected.
-    * Highlight nodes that match the 'focus' string in the flamegraph.
-    * Added search within slice args.
-    * Fixed details panel height and moved query panel into details panel.
-    * Enabled re-sharing of postMessage traces by echoing back the original URL.
-    * Improved record page error messages.
-
-
-v8.0 - 2020-10-01:
-  Tracing service and probes:
-    * Added API for querying registered data sources and their capabilities.
-    * Added support for profiling heap allocations on Linux via LD_PRELOAD.
-    * Fixed possible race when initializing the consumer library.
-    * Fixed subtle bugs on systems with 16KB system pages.
-  Trace Processor:
-    * Added a table which lists available metrics.
-    * Added Python bindings on PyPi in the 'perfetto' package.
-    * Added support for running trace_processor_shell on Android.
-    * Added per-process metrics for GPU memory usage.
-    * Added support for exporting flow events to JSON.
-    * Added dynamic tables for navigating between slices of flows.
-  UI:
-    * Changed time marking: horizontal selection doesn't gray out anymore,
-      pressing 'm' marks the range.
-    * Added initial support for displaying flow event arrows.
-    * Improved ordering of all thread tracks under process grouping.
-    * Fixed UI crashes due to metric errors
-    * Fixed selection of thread state slices.
-
-
-v7.0 - 2020-09-01:
-  Tracing service and probes:
-    * Added auto-reconnection to the SDK. Tracing::Initialize() now retries in
-      the background, instead of failing, if the tracing service is unrechable.
-    * Added support for recording cpuhp (CPU hotplug) ftrace events.
-    * Fixed heap profiling unwinding on multi-ABI systems.
-    * Fixed reporting of live objects in the native heap profiler when using
-      --dump-at-max.
-    * Fixed crash when writing trace events with field nesting level > 10.
-  Trace Processor:
-    * Added Python bindings, see
-      https://perfetto.dev/docs/analysis/trace-processor#python-api .
-    * Added ingestion for Chrome instant events and Chrome flow events.
-    * Added ingestion for Android GPU memory events and sched_blocked_reason.
-    * Added WebView power metric.
-    * Added support for WSL1 where Async I/O is not available.
-    * Improved detection of Android suspend/resume events.
-  UI:
-    * Added GPU memory recording controls and ingestion code. Requires a recent
-      Android 12+ kernel.
-    * Added details panel for flow events, showed when the user selects a slice
-      involved in a flow (arrows in the UI are still being worked on).
-    * Added instant events rendering.
-    * Added Google Analytics.
-    * Fixed I/O thread-states in 4.14 kernels to deal with the removal of
-      wake-kill using sched_blocked_reason.
-    * Fixed "Perfetto UI started debugging this browser" showing when opening
-      the UI and the Chrome extension is installed.
-  Misc:
-    * Update language to comply with Android's inclusive language guidance.
-
-
-v6.0 - 2020-08-01:
-  Tracing service and probes:
-    * Added ftrace thermal events.
-    * Added support for custom allocators to the heap profiler. Allows
-      developers to report memory allocations that are not done through malloc.
-    * Added detailed timestamping of key tracing session events.
-    * Added support for building tracing services on CrOS (system-wide tracing).
-    * Fixed filtering out of stale ftrace data that predates the beginning of
-      the tracing session.
-  Trace Processor:
-    * Improved profile symbolizer. PERFETTO_SYMBOLIZER_MODE=index discovers
-      symbol files by build id rather than name.
-    * Added screen-state Android metrics.
-  UI:
-    * Added 'Info and stats' page to debug data losses and trace stats.
-    * Added full cmdline to process detail panel.
-    * Improved performance of async tracks using quantized queries.
-    * Improved performance of counter and slice tracks for long traces by
-      pre-caching quantized track data.
-    * Improved actionablility of crash dialog when the Wasm module OOMs.
-
-
-v5.0 - 2020-07-01:
-  Tracing service and probes:
-    * Added gpu_mem_total ftrace event.
-    * Added TrustZone (scm start/end) event.
-    * Added protos for GPU memory tracking and updated render stages proto.
-    * Added time_in_state probe for Android (CPU time broken down by frequency).
-
-  Trace Processor:
-    * Added ingestion of IRQ and SoftIRQ events.
-    * Added ingestion of workqueue events. KAddr symbolization still missing.
-    * Added ingestion of voltage regulators and board clock change events.
-    * Added ingestion of new ION ion_buffer_create/destroy events.
-    * Added ingestion of TrustZone (scm start/end) events.
-    * Added SurfaceFlinger derived events (tracking of missed frames).
-    * Changed parsing of scheduler task state on 4.14 kernels.
-    * Changed importing of Java heap graphs: allow partial dumps.
-    * Improved performance of the SQL query engine.
-
-  UI:
-    * Added dedicated query page for custom SQL queries.
-    * Added navigation links for Binder slices.
-    * Removed overview summary mode when zoomed out.
-    * Fixed recording page when targeting Android P.
-    * Improved slice pan/zoom performance by quantizing.
diff --git a/DIR_METADATA b/DIR_METADATA
deleted file mode 100644
index 592fce2..0000000
--- a/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail {
-  component: "Speed>Tracing"
-}
-team_email: "tracing@chromium.org"
diff --git a/OWNERS b/OWNERS
index 9e51e74..b61ef9c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -14,9 +14,11 @@
 khokhlov@google.com
 ssid@google.com
 ddrone@google.com
-altimin@google.com
 
 # chromium.org aliases for DEPS on third_party/perfetto.
 eseckler@chromium.org
 nuskos@chromium.org
 skyostil@chromium.org
+
+# TEAM: tracing@chromium.org
+# COMPONENT: Speed>Tracing
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 97acb3e..30eb1c1 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -22,10 +22,10 @@
   def long_line_sources(x):
     return input.FilterSourceFile(
         x,
-        files_to_check='.*',
-        files_to_skip=[
+        white_list=".*",
+        black_list=[
             'Android[.]bp', '.*[.]json$', '.*[.]sql$', '.*[.]out$',
-            'test/trace_processor/.*/index$', '(.*/)?BUILD$', 'WORKSPACE',
+            'test/trace_processor/index$', '.*\bBUILD$', 'WORKSPACE',
             '.*/Makefile$', '/perfetto_build_flags.h$'
         ])
 
@@ -39,14 +39,12 @@
   results += input.canned_checks.CheckGNFormatted(input, output)
   results += CheckIncludeGuards(input, output)
   results += CheckIncludeViolations(input, output)
-  results += CheckProtoComments(input, output)
   results += CheckBuild(input, output)
   results += CheckAndroidBlueprint(input, output)
   results += CheckBinaryDescriptors(input, output)
   results += CheckMergedTraceConfigProto(input, output)
-  results += CheckProtoEventList(input, output)
+  results += CheckWhitelist(input, output)
   results += CheckBannedCpp(input, output)
-  results += CheckSqlMetrics(input, output)
   return results
 
 
@@ -64,7 +62,7 @@
   # If no GN files were modified, bail out.
   def build_file_filter(x):
     return input_api.FilterSourceFile(
-        x, files_to_check=('.*BUILD[.]gn$', '.*[.]gni$', 'BUILD\.extras', tool))
+        x, white_list=('.*BUILD[.]gn$', '.*[.]gni$', 'BUILD\.extras', tool))
 
   if not input_api.AffectedSourceFiles(build_file_filter):
     return []
@@ -82,7 +80,7 @@
   # If no GN files were modified, bail out.
   def build_file_filter(x):
     return input_api.FilterSourceFile(
-        x, files_to_check=('.*BUILD[.]gn$', '.*[.]gni$', tool))
+        x, white_list=('.*BUILD[.]gn$', '.*[.]gni$', tool))
 
   if not input_api.AffectedSourceFiles(build_file_filter):
     return []
@@ -99,7 +97,7 @@
 
   def file_filter(x):
     return input_api.FilterSourceFile(
-        x, files_to_check=['.*[.]cc$', '.*[.]h$', tool])
+        x, white_list=['.*[.]cc$', '.*[.]h$', tool])
 
   if not input_api.AffectedSourceFiles(file_filter):
     return []
@@ -113,6 +111,7 @@
 
 def CheckBannedCpp(input_api, output_api):
   bad_cpp = [
+      (r'\bNULL\b', 'New code should not use NULL prefer nullptr'),
       (r'\bstd::stoi\b',
        'std::stoi throws exceptions prefer base::StringToInt32()'),
       (r'\bstd::stol\b',
@@ -135,7 +134,7 @@
   ]
 
   def file_filter(x):
-    return input_api.FilterSourceFile(x, files_to_check=[r'.*\.h$', r'.*\.cc$'])
+    return input_api.FilterSourceFile(x, white_list=[r'.*\.h$', r'.*\.cc$'])
 
   errors = []
   for f in input_api.AffectedSourceFiles(file_filter):
@@ -152,8 +151,7 @@
   tool = 'tools/check_include_violations'
 
   def file_filter(x):
-    return input_api.FilterSourceFile(
-        x, files_to_check=['include/.*[.]h$', tool])
+    return input_api.FilterSourceFile(x, white_list=['include/.*[.]h$', tool])
 
   if not input_api.AffectedSourceFiles(file_filter):
     return []
@@ -167,7 +165,7 @@
 
   def file_filter(x):
     return input_api.FilterSourceFile(
-        x, files_to_check=['protos/perfetto/.*[.]proto$', '.*[.]h', tool])
+        x, white_list=['protos/perfetto/.*[.]proto$', '.*[.]h', tool])
 
   if not input_api.AffectedSourceFiles(file_filter):
     return []
@@ -184,7 +182,7 @@
 
   def build_file_filter(x):
     return input_api.FilterSourceFile(
-        x, files_to_check=['protos/perfetto/.*[.]proto$', tool])
+        x, white_list=['protos/perfetto/.*[.]proto$', tool])
 
   if not input_api.AffectedSourceFiles(build_file_filter):
     return []
@@ -197,45 +195,17 @@
   return []
 
 
-# Prevent removing or changing lines in event_list.
-def CheckProtoEventList(input_api, output_api):
+# Prevent removing or changing lines in event_whitelist.
+def CheckWhitelist(input_api, output_api):
   for f in input_api.AffectedFiles():
-    if f.LocalPath() != 'tools/ftrace_proto_gen/event_list':
+    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())):
       return [
           output_api.PresubmitError(
-              'event_list only has two supported changes: '
+              'event_whitelist only has two supported changes: '
               'appending a new line, and replacing a line with removed.')
       ]
   return []
-
-
-def CheckProtoComments(input_api, output_api):
-  tool = 'tools/check_proto_comments'
-
-  def file_filter(x):
-    return input_api.FilterSourceFile(
-        x, files_to_check=['protos/perfetto/.*[.]proto$', tool])
-
-  if not input_api.AffectedSourceFiles(file_filter):
-    return []
-  if subprocess.call([tool]):
-    return [output_api.PresubmitError(tool + ' failed')]
-  return []
-
-
-def CheckSqlMetrics(input_api, output_api):
-  tool = 'tools/check_sql_metrics.py'
-
-  def file_filter(x):
-    return input_api.FilterSourceFile(
-        x, files_to_check=['src/trace_processor/metrics/.*[.]sql$', tool])
-
-  if not input_api.AffectedSourceFiles(file_filter):
-    return []
-  if subprocess.call([tool]):
-    return [output_api.PresubmitError(tool + ' failed')]
-  return []
diff --git a/PerfettoIntegrationTests.xml b/PerfettoIntegrationTests.xml
deleted file mode 100644
index 97e7c3a..0000000
--- a/PerfettoIntegrationTests.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs perfetto_integrationtests.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-native" />
-
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push"
-                value="perfetto_integrationtests->/data/local/tests/unrestricted/perfetto_integrationtests" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path"
-                value="/data/local/tests/unrestricted" />
-        <option name="module-name" value="perfetto_integrationtests" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/README.md b/README.md
index 3ef3430..a1a3a74 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,4 @@
 library for analyzing traces using SQL and a web-based UI to visualize and
 explore multi-GB traces.
 
-See https://perfetto.dev/docs or the /docs/ directory for documentation.
+See https://docs.perfetto.dev or the /docs/ directory for documentation.
diff --git a/TEST_MAPPING b/TEST_MAPPING
index d971a20..4c2f19d 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -6,7 +6,12 @@
     // Additional presubmit tests that explicitly exercise
     // Perfetto's backend
     {
-      "name": "libsurfaceflinger_unittest"
+      "name": "libsurfaceflinger_unittest",
+      "options": [
+          {
+	      "include-filter": "FrameTracerTest.*"
+	  }
+      ]
     }
   ]
 }
diff --git a/bazel/deps.bzl b/bazel/deps.bzl
index 63cbde2..6f19f3d 100644
--- a/bazel/deps.bzl
+++ b/bazel/deps.bzl
@@ -60,9 +60,9 @@
         new_git_repository,
         name = "perfetto_dep_jsoncpp",
         remote = "https://github.com/open-source-parsers/jsoncpp",
-        commit = "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2",  # v1.9.3
+        commit = "7165f6ac4c482e68475c9e1dac086f9e12fff0d0",  # v1.0.0
         build_file = "//bazel:jsoncpp.BUILD",
-        shallow_since = "1590760226 +0800",
+        shallow_since = "1416494758 -0600",
     )
 
     _add_repo_if_not_existing(
diff --git a/bazel/jsoncpp.BUILD b/bazel/jsoncpp.BUILD
index ec5a48b..bef06a1 100644
--- a/bazel/jsoncpp.BUILD
+++ b/bazel/jsoncpp.BUILD
@@ -17,6 +17,9 @@
 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",
@@ -24,12 +27,12 @@
         "src/lib_json/json_writer.cpp",
     ],
     hdrs = [
-        "include/json/allocator.h",
         "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/json_features.h",
         "include/json/reader.h",
         "include/json/value.h",
         "include/json/version.h",
diff --git a/bazel/proto_gen.bzl b/bazel/proto_gen.bzl
index eb9d7e8..50f5747 100644
--- a/bazel/proto_gen.bzl
+++ b/bazel/proto_gen.bzl
@@ -124,30 +124,3 @@
     output_to_genfiles = True,
     implementation = _proto_gen_impl,
 )
-
-
-def _proto_descriptor_gen_impl(ctx):
-    descriptors = [
-        f
-        for dep in ctx.attr.deps
-        for f in dep[ProtoInfo].transitive_descriptor_sets.to_list()
-    ]
-    ctx.actions.run_shell(
-        inputs=descriptors,
-        outputs=ctx.outputs.outs,
-        command='cat %s > %s' % (
-            ' '.join([f.path for f in descriptors]), ctx.outputs.outs[0].path)
-    )
-
-
-proto_descriptor_gen = rule(
-    implementation=_proto_descriptor_gen_impl,
-    attrs = {
-        "deps": attr.label_list(
-            mandatory = True,
-            allow_empty = False,
-            providers = [ProtoInfo],
-        ),
-        "outs": attr.output_list(mandatory=True),
-    }
-)
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
index 4503867..af272f5 100644
--- a/bazel/rules.bzl
+++ b/bazel/rules.bzl
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-load("@perfetto//bazel:proto_gen.bzl", "proto_descriptor_gen", "proto_gen")
+load("@perfetto//bazel:proto_gen.bzl", "proto_gen")
 
 # +----------------------------------------------------------------------------+
 # | Base C++ rules.                                                            |
@@ -48,10 +48,6 @@
     if not _rule_override("py_binary", **kwargs):
         native.py_binary(**kwargs)
 
-def perfetto_py_library(**kwargs):
-    if not _rule_override("py_library", **kwargs):
-        native.py_library(**kwargs)
-
 # +----------------------------------------------------------------------------+
 # | Proto-related rules                                                        |
 # +----------------------------------------------------------------------------+
@@ -93,20 +89,9 @@
     ):
         return
 
-    # A perfetto_cc_protozero_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_protozero_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]
-    if len(_proto_deps) != 1:
-        fail("Too many proto deps for target %s" % name)
-
     proto_gen(
         name = name + "_src",
-        deps = _proto_deps,
+        deps = deps,
         suffix = "pbzero",
         plugin = PERFETTO_CONFIG.root + ":protozero_plugin",
         wrapper_namespace = "pbzero",
@@ -124,7 +109,7 @@
         name = name,
         srcs = [":" + name + "_src"],
         hdrs = [":" + name + "_h"],
-        deps = [PERFETTO_CONFIG.root + ":protozero"] + _cc_deps,
+        deps = [PERFETTO_CONFIG.root + ":libprotozero"],
         **kwargs
     )
 
@@ -169,11 +154,12 @@
         deps = [
             # Generated .ipc.{cc,h} depend on this and protozero.
             PERFETTO_CONFIG.root + ":perfetto_ipc",
-            PERFETTO_CONFIG.root + ":protozero",
+            PERFETTO_CONFIG.root + ":libprotozero",
         ] + _cc_deps,
         **kwargs
     )
 
+
 # Generates .gen.{cc,h} from .proto(s).
 def perfetto_cc_protocpp_library(name, deps, **kwargs):
     if _rule_override(
@@ -219,42 +205,11 @@
         srcs = [":" + name + "_gen"],
         textual_hdrs = [":" + name + "_gen_h"],
         deps = [
-            PERFETTO_CONFIG.root + ":protozero",
+            PERFETTO_CONFIG.root + ":libprotozero"
         ] + _cc_deps,
         **kwargs
     )
 
-def perfetto_proto_descriptor(name, deps, outs, **kwargs):
-    proto_descriptor_gen(
-        name = name,
-        deps = deps,
-        outs = outs,
-    )
-
-# Generator .descriptor.h from protos
-def perfetto_cc_proto_descriptor(name, deps, outs, **kwargs):
-    cmd = [
-        "$(location gen_cc_proto_descriptor_py)",
-        "--cpp_out=$@",
-        "--gen_dir=$(GENDIR)",
-        "$<"
-    ]
-    native.genrule(
-        name = name + "_gen",
-        cmd = " ".join(cmd),
-        exec_tools = [
-            ":gen_cc_proto_descriptor_py",
-        ],
-        srcs = deps,
-        outs = outs,
-    )
-
-    perfetto_cc_library(
-        name = name,
-        hdrs = [":" + name + "_gen"],
-        **kwargs
-    )
-
 # +----------------------------------------------------------------------------+
 # | Misc utility functions                                                     |
 # +----------------------------------------------------------------------------+
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
index 2d71aa8..68a0ead 100644
--- a/bazel/standalone/perfetto_cfg.bzl
+++ b/bazel/standalone/perfetto_cfg.bzl
@@ -34,12 +34,6 @@
         # "perfetto_build_flags.h" file that can be included via:
         # #include "perfetto_build_flags.h".
         build_config = ["//:build_config_hdr"],
-
-        # Target exposing the PERFETTO_VERSION_STRING() and
-        # PERFETTO_VERSION_SCM_REVISION() macros. This is overridden in google
-        # internal builds.
-        version_header = ["//:cc_perfetto_version_header"],
-
         zlib = ["@perfetto_dep_zlib//:zlib"],
         jsoncpp = ["@perfetto_dep_jsoncpp//:jsoncpp"],
         linenoise = ["@perfetto_dep_linenoise//:linenoise"],
@@ -49,7 +43,6 @@
         protoc_lib = ["@com_google_protobuf//:protoc_lib"],
         protobuf_lite = ["@com_google_protobuf//:protobuf_lite"],
         protobuf_full = ["@com_google_protobuf//:protobuf"],
-        protobuf_descriptor_proto = ["@com_google_protobuf//:descriptor_proto"]
     ),
 
     # This struct allows embedders to customize the cc_opts for Perfetto
@@ -92,7 +85,6 @@
 
         proto_library = None,
         py_binary = None,
-        py_library = None,
 
         # We only need this for internal binaries. No other embeedder should
         # care about this.
diff --git a/buildtools/.gitignore b/buildtools/.gitignore
index 0888b62..c3961bc 100644
--- a/buildtools/.gitignore
+++ b/buildtools/.gitignore
@@ -1,8 +1,4 @@
 android-core/
-android-libbase/
-android-libprocinfo/
-android-logging/
-android-unwinding/
 android_sdk/
 aosp-*/
 benchmark/
@@ -15,7 +11,6 @@
 googletest/
 jsoncpp/
 libbacktrace/
-libbase/
 libcxx/
 libcxxabi/
 libfuzzer/
@@ -32,5 +27,4 @@
 sqlite_src/
 test_data/
 typefaces/
-win/
 zlib/
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index 98022c9..e75f35a 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -37,21 +37,16 @@
   visibility = _buildtools_visibility
   if (is_clang) {
     cflags = [
-      "-Wno-covered-switch-default",
-      "-Wno-deprecated-copy-dtor",
-      "-Wno-global-constructors",
-      "-Wno-inconsistent-missing-override",
-      "-Wno-language-extension-token",
-      "-Wno-suggest-destructor-override",
-      "-Wno-suggest-override",
-      "-Wno-undef",
       "-Wno-unknown-warning-option",
-      "-Wno-unused-member-function",
+      "-Wno-global-constructors",
+      "-Wno-covered-switch-default",
       "-Wno-used-but-marked-unused",
-      "-Wno-weak-vtables",
+      "-Wno-inconsistent-missing-override",
+      "-Wno-unused-member-function",
       "-Wno-zero-as-null-pointer-constant",
+      "-Wno-weak-vtables",
     ]
-  } else if (!is_win) {
+  } else {
     cflags = [
       "-Wno-unknown-warning-option",
       "-Wno-deprecated-copy",
@@ -65,18 +60,18 @@
     # Using -isystem instead of include_dirs (-I), so we don't need to suppress
     # warnings coming from libunwindstack headers. Doing so would mask warnings
     # in our own code.
-    perfetto_isystem_cflag,
-    rebase_path("android-unwinding/libunwindstack/include", root_build_dir),
-    perfetto_isystem_cflag,
-    rebase_path("android-libprocinfo/include", root_build_dir),
-    perfetto_isystem_cflag,
-    rebase_path("android-libbase/include", root_build_dir),
-    perfetto_isystem_cflag,
+    "-isystem",
+    rebase_path("android-core/libunwindstack/include", root_build_dir),
+    "-isystem",
+    rebase_path("android-core/libprocinfo/include", root_build_dir),
+    "-isystem",
+    rebase_path("android-core/base/include", root_build_dir),
+    "-isystem",
     rebase_path("android-core/demangle/include", root_build_dir),
   ]
   if (is_android) {
     cflags += [
-      perfetto_isystem_cflag,
+      "-isystem",
       rebase_path("bionic/libc/include", root_build_dir),
     ]
   }
@@ -133,31 +128,15 @@
   configs = [ "//gn:protobuf_gen_config" ]
 
   defines = [ "HAVE_PTHREAD=1" ]
-  cflags = []
   if (is_clang) {
-    # We do NOT build libprotobuf with -Wextra or -Weverything. But still it
-    # hits some warnings that we need to suppress.
-    cflags += [
+    cflags = [
       "-Wno-unknown-warning-option",
       "-Wno-enum-compare-switch",
       "-Wno-user-defined-warnings",
       "-Wno-tautological-constant-compare",
-      "-Wno-inconsistent-missing-override",
     ]
-  } else if (!is_win) {  # implies gcc
-    cflags += [ "-Wno-return-type" ]
-  }
-  if (is_win) {
-    cflags += [ "/W0" ]
-  }
-}
-
-# Configuration propagated to targets depending on protobuf_full.
-config("protobuf_full_public_config") {
-  visibility = _buildtools_visibility
-  cflags = []
-  if (is_clang) {
-    cflags += [ "-Wno-switch-enum" ]
+  } else {  # implies gcc
+    cflags = [ "-Wno-return-type" ]
   }
 }
 
@@ -239,10 +218,6 @@
     "protobuf/src/google/protobuf/wire_format_lite.h",
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
-  if (is_win) {
-    # Protobuf has its own #define WIN32_LEAN_AND_MEAN.
-    configs -= [ "//gn/standalone:win32_lean_and_mean" ]
-  }
   configs += [ ":protobuf_config" ]
   public_configs = [ "//gn:protobuf_gen_config" ]
   deps = [ "//gn:default_deps" ]
@@ -371,15 +346,8 @@
     "protobuf/src/google/protobuf/wrappers.pb.h",
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
-  if (is_win) {
-    # Protobuf has its own #define WIN32_LEAN_AND_MEAN.
-    configs -= [ "//gn/standalone:win32_lean_and_mean" ]
-  }
   configs += [ ":protobuf_config" ]
-  public_configs = [
-    "//gn:protobuf_gen_config",
-    ":protobuf_full_public_config",
-  ]
+  public_configs = [ "//gn:protobuf_gen_config" ]
 }
 
 source_set("protoc_lib") {
@@ -557,15 +525,8 @@
     "protobuf/src/google/protobuf/compiler/zip_writer.h",
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
-  if (is_win) {
-    # Protobuf does has its own #define WIN32_LEAN_AND_MEAN.
-    configs -= [ "//gn/standalone:win32_lean_and_mean" ]
-  }
   configs += [ ":protobuf_config" ]
-  public_configs = [
-    "//gn:protobuf_gen_config",
-    ":protobuf_full_public_config",
-  ]
+  public_configs = [ "//gn:protobuf_gen_config" ]
 }
 
 if (current_toolchain == host_toolchain) {
@@ -577,10 +538,6 @@
     ]
     sources = [ "protobuf/src/google/protobuf/compiler/main.cc" ]
     configs -= [ "//gn/standalone:extra_warnings" ]
-    if (is_win) {
-      # Protobuf does has its own #define WIN32_LEAN_AND_MEAN.
-      configs -= [ "//gn/standalone:win32_lean_and_mean" ]
-    }
   }
 }  # host_toolchain
 
@@ -593,17 +550,14 @@
       "_LIBCXXABI_NO_EXCEPTIONS",
       "_LIBCPP_OVERRIDABLE_FUNC_VIS=__attribute__((__visibility__(\"default\")))",
     ]
-    cflags = [ "-fstrict-aliasing" ]
+    cflags = [
+      "-fPIC",
+      "-fstrict-aliasing",
+    ]
   }
 
   source_set("libunwind") {
     visibility = _buildtools_visibility
-    cflags = [
-      # libunwind expects to be compiled with unwind tables so it can
-      # unwind its own frames.
-      "-funwind-tables",
-      "-fstrict-aliasing",
-    ]
     sources = [
       "libunwind/src/Unwind-EHABI.cpp",
       "libunwind/src/Unwind-sjlj.c",
@@ -833,7 +787,7 @@
   include_dirs = [ "sqlite" ]
   cflags = [
     "-DSQLITE_THREADSAFE=0",
-    "-DSQLITE_DEFAULT_MEMSTATUS=0",
+    "-DQLITE_DEFAULT_MEMSTATUS=0",
     "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
     "-DSQLITE_OMIT_DEPRECATED",
     "-DSQLITE_OMIT_SHARED_CACHE",
@@ -928,61 +882,49 @@
 source_set("zlib") {
   visibility = _buildtools_visibility
   sources = [
-    "zlib/adler32.c",
-    "zlib/compress.c",
-    "zlib/cpu_features.c",
-    "zlib/crc32.c",
-    "zlib/deflate.c",
-    "zlib/gzclose.c",
-    "zlib/gzlib.c",
-    "zlib/gzread.c",
-    "zlib/gzwrite.c",
-    "zlib/infback.c",
-    "zlib/inffast.c",
-    "zlib/inflate.c",
-    "zlib/inftrees.c",
-    "zlib/trees.c",
-    "zlib/uncompr.c",
-    "zlib/zutil.c",
+    "zlib/src/adler32.c",
+    "zlib/src/compress.c",
+    "zlib/src/crc32.c",
+    "zlib/src/deflate.c",
+    "zlib/src/gzclose.c",
+    "zlib/src/gzlib.c",
+    "zlib/src/gzread.c",
+    "zlib/src/gzwrite.c",
+    "zlib/src/infback.c",
+    "zlib/src/inffast.c",
+    "zlib/src/inflate.c",
+    "zlib/src/inftrees.c",
+    "zlib/src/trees.c",
+    "zlib/src/uncompr.c",
+    "zlib/src/zutil.c",
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
   cflags = []
   public_configs = [ ":zlib_config" ]
   deps = [ "//gn:default_deps" ]
-
-  # TODO(primiano): look into ADLER32_SIMD_SSSE3 and other SIMD optimizations
-  # (from chromium's third_party/zlib/BUILD.gn).
-  if (is_win) {
-    defines = [ "X86_WINDOWS" ]
-  }
 }
 
 config("zlib_config") {
   visibility = _buildtools_visibility
-  if (!is_win) {
-    defines = [ "HAVE_HIDDEN" ]
-  }
+  defines = [ "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
     # our own code.
-    perfetto_isystem_cflag,
-    rebase_path("zlib", root_build_dir),
+    "-isystem",
+    rebase_path("zlib/src", root_build_dir),
   ]
 }
 
 source_set("libunwindstack") {
   visibility = _buildtools_visibility
   include_dirs = [
-    "android-unwinding/libunwindstack/include",
-    "android-unwinding/libunwindstack",
-    "android-libbase/include",
-    "android-logging/liblog/include",
-    "android-libprocinfo/include",
+    "android-core/libunwindstack/include",
+    "android-core/libunwindstack",
+    "android-core/base/include",
+    "android-core/liblog/include",
+    "android-core/libprocinfo/include",
     "android-core/include",
-    "android-core/libcutils/include",
-    "bionic/libc/async_safe/include",
-    "bionic/libc/platform/",
     "lzma/C",
   ]
   deps = [
@@ -990,49 +932,44 @@
     "//gn:default_deps",
   ]
   sources = [
-    "android-libbase/file.cpp",
-    "android-libbase/stringprintf.cpp",
-    "android-libbase/strings.cpp",
-    "android-unwinding/libunwindstack/ArmExidx.cpp",
-    "android-unwinding/libunwindstack/DwarfCfa.cpp",
-    "android-unwinding/libunwindstack/DwarfEhFrameWithHdr.cpp",
-    "android-unwinding/libunwindstack/DwarfMemory.cpp",
-    "android-unwinding/libunwindstack/DwarfOp.cpp",
-    "android-unwinding/libunwindstack/DwarfSection.cpp",
-    "android-unwinding/libunwindstack/Elf.cpp",
-    "android-unwinding/libunwindstack/ElfInterface.cpp",
-    "android-unwinding/libunwindstack/ElfInterfaceArm.cpp",
-    "android-unwinding/libunwindstack/Global.cpp",
-    "android-unwinding/libunwindstack/JitDebug.cpp",
-    "android-unwinding/libunwindstack/LocalUnwinder.cpp",
-    "android-unwinding/libunwindstack/Log.cpp",
-    "android-unwinding/libunwindstack/MapInfo.cpp",
-    "android-unwinding/libunwindstack/Maps.cpp",
-    "android-unwinding/libunwindstack/Memory.cpp",
-    "android-unwinding/libunwindstack/Regs.cpp",
-    "android-unwinding/libunwindstack/RegsArm.cpp",
-    "android-unwinding/libunwindstack/RegsArm64.cpp",
-    "android-unwinding/libunwindstack/RegsMips.cpp",
-    "android-unwinding/libunwindstack/RegsMips64.cpp",
-    "android-unwinding/libunwindstack/RegsX86.cpp",
-    "android-unwinding/libunwindstack/RegsX86_64.cpp",
-    "android-unwinding/libunwindstack/Symbols.cpp",
-    "android-unwinding/libunwindstack/Unwinder.cpp",
+    "android-core/base/file.cpp",
+    "android-core/base/liblog_symbols.cpp",
+    "android-core/base/logging.cpp",
+    "android-core/base/stringprintf.cpp",
+    "android-core/base/strings.cpp",
+    "android-core/base/threads.cpp",
+    "android-core/liblog/fake_log_device.cpp",
+    "android-core/liblog/logger_write.cpp",
+    "android-core/libunwindstack/ArmExidx.cpp",
+    "android-core/libunwindstack/DwarfCfa.cpp",
+    "android-core/libunwindstack/DwarfEhFrameWithHdr.cpp",
+    "android-core/libunwindstack/DwarfMemory.cpp",
+    "android-core/libunwindstack/DwarfOp.cpp",
+    "android-core/libunwindstack/DwarfSection.cpp",
+    "android-core/libunwindstack/Elf.cpp",
+    "android-core/libunwindstack/ElfInterface.cpp",
+    "android-core/libunwindstack/ElfInterfaceArm.cpp",
+    "android-core/libunwindstack/Global.cpp",
+    "android-core/libunwindstack/JitDebug.cpp",
+    "android-core/libunwindstack/LocalUnwinder.cpp",
+    "android-core/libunwindstack/Log.cpp",
+    "android-core/libunwindstack/MapInfo.cpp",
+    "android-core/libunwindstack/Maps.cpp",
+    "android-core/libunwindstack/Memory.cpp",
+    "android-core/libunwindstack/Regs.cpp",
+    "android-core/libunwindstack/RegsArm.cpp",
+    "android-core/libunwindstack/RegsArm64.cpp",
+    "android-core/libunwindstack/RegsMips.cpp",
+    "android-core/libunwindstack/RegsMips64.cpp",
+    "android-core/libunwindstack/RegsX86.cpp",
+    "android-core/libunwindstack/RegsX86_64.cpp",
+    "android-core/libunwindstack/Symbols.cpp",
+    "android-core/libunwindstack/Unwinder.cpp",
   ]
-  if (!is_android) {
-    sources += [
-      "android-libbase/liblog_symbols.cpp",
-      "android-libbase/logging.cpp",
-      "android-libbase/threads.cpp",
-      "android-logging/liblog/logger_write.cpp",
-      "android-logging/liblog/properties.cpp",
-      "android-unwinding/libunwindstack/MemoryMte.cpp",
-    ]
-  }
   if (current_cpu == "x86") {
-    sources += [ "android-unwinding/libunwindstack/AsmGetRegsX86.S" ]
+    sources += [ "android-core/libunwindstack/AsmGetRegsX86.S" ]
   } else if (current_cpu == "x64") {
-    sources += [ "android-unwinding/libunwindstack/AsmGetRegsX86_64.S" ]
+    sources += [ "android-core/libunwindstack/AsmGetRegsX86_64.S" ]
   }
   configs -= [
     "//gn/standalone:extra_warnings",
@@ -1040,16 +977,14 @@
     "//gn/standalone:visibility_hidden",
   ]
   cflags = [ "-DFAKE_LOG_DEVICE=1" ]
-  public_configs = [
-    ":libunwindstack_config",
-    "//gn/standalone:c++17",
-  ]
+  configs += [ "//gn/standalone:c++17" ]
+  public_configs = [ ":libunwindstack_config" ]
 }
 
 config("bionic_kernel_uapi_headers") {
   visibility = _buildtools_visibility
   cflags = [
-    perfetto_isystem_cflag,
+    "-isystem",
     rebase_path("bionic/libc/kernel", root_build_dir),
   ]
 }
@@ -1058,12 +993,11 @@
   visibility = _buildtools_visibility
   cflags = [
     "-DJSON_USE_EXCEPTION=0",
-    "-Wno-deprecated-declarations",
 
     # 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.
-    perfetto_isystem_cflag,
+    "-isystem",
     rebase_path("jsoncpp/include", root_build_dir),
   ]
 }
@@ -1086,7 +1020,7 @@
     # 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.
-    perfetto_isystem_cflag,
+    "-isystem",
     rebase_path("linenoise", root_build_dir),
   ]
 }
diff --git a/buildtools/emsdk/.gitignore b/buildtools/emsdk/.gitignore
new file mode 100644
index 0000000..6dfe23f
--- /dev/null
+++ b/buildtools/emsdk/.gitignore
@@ -0,0 +1,2 @@
+emscripten/
+llvm/
diff --git a/debian/changelog b/debian/changelog
index 2b4ba12..6e2b4fc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,26 +1,3 @@
-perfetto (15.0-1) unstable; urgency=medium
-  * Performance improvements.
-  * Bugfixes.
-  * More flexible SDK.
-  * New data-sources.
-
- -- Florian Mayer <fmayer@google.com>  Fri, 14 May 2021 10:50:00 +0000
-
-perfetto (11.0-1) unstable; urgency=medium
-  * Add the Perfetto perf sampling and profiling service.
-
- -- Sami Kyostila <skyostil@google.com>  Mon, 18 Jan 2021 12:10:00 +0000
-
-perfetto (9.0-1) unstable; urgency=medium
-
-  * Run traced under a dedicated system user account and set socket
-    permissions accordingly so that any user can write trace events, but
-    only the users in the "traced-consumer" group can read trace data.
-  * Update to debhelper 10.
-  * Bump version to match Perfetto release.
-
- -- Sami Kyostila <skyostil@google.com>  Mon, 9 Nov 2020 15:24:00 +0000
-
 perfetto (0.1-1) unstable; urgency=medium
 
   * Initial release
diff --git a/debian/compat b/debian/compat
index b1bd38b..ec63514 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-13
+9
diff --git a/debian/control b/debian/control
index 94a03bb..b16354f 100644
--- a/debian/control
+++ b/debian/control
@@ -1,25 +1,16 @@
 Source: perfetto
-Section: kernel
+Section: unknown
 Priority: optional
 Maintainer: Sami Kyostila <skyostil@google.com>
-Build-Depends: debhelper (>= 13),
-  generate-ninja,
-  git,
-  libprotoc-dev,
-  ninja-build,
-  protobuf-compiler,
-  python3,
-  zlib1g-dev,
-  zlib1g
-Standards-Version: 4.5.1
-Homepage: https://perfetto.dev
+Build-Depends: debhelper (>= 9)
+Standards-Version: 3.9.8
+Homepage: https://android.googlesource.com/platform/external/perfetto/
 Vcs-Git: https://android.googlesource.com/platform/external/perfetto/
 Vcs-Browser: https://android.googlesource.com/platform/external/perfetto/
-Rules-Requires-Root: no
 
 Package: perfetto
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, zlib1g
-Description: Performance instrumentation and logging framework
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Performance instrumentation and logging for POSIX platforms
  Perfetto is a performance instrumentation and logging framework for POSIX
  systems.
diff --git a/debian/copyright b/debian/copyright
index 7b7058c..e23f57d 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -4,12 +4,12 @@
 
 Files: *
 Copyright: Copyright (C) 2017 The Android Open Source Project
-License: Apache-2
+License: Apache 2
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  .
-      /usr/share/common-licenses/Apache-2.0
+      http://www.apache.org/licenses/LICENSE-2.0
  .
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/debian/gitlab-ci.yml b/debian/gitlab-ci.yml
deleted file mode 100644
index 892f3cd..0000000
--- a/debian/gitlab-ci.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-include:
- - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
- - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
diff --git a/debian/postinst b/debian/postinst
deleted file mode 100755
index e6cdff5..0000000
--- a/debian/postinst
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-set -e
-adduser --home /nonexistent --quiet --system --no-create-home --group traced
-addgroup --quiet --system traced-consumer
-usermod -a -G traced-consumer traced
-
-#DEBHELPER#
diff --git a/debian/postrm b/debian/postrm
deleted file mode 100755
index efa1590..0000000
--- a/debian/postrm
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -e
-rm -f /tmp/perfetto-consumer /tmp/perfetto-producer
-
-#DEBHELPER#
diff --git a/debian/rules b/debian/rules
index a081c5c..594466f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,39 +1,13 @@
 #!/usr/bin/make -f
-
-export DEB_BUILD_MAINT_OPTIONS = hardening=+all
-DPKG_EXPORT_BUILDFLAGS = 1
-include /usr/share/dpkg/buildflags.mk
-
 %:
 	dh $@
 
-override_dh_auto_configure: MAYBE_HOST_CPU=$(shell \
-	if [ "${DEB_BUILD_GNU_CPU}" = "i686" ]; then \
-	  echo "host_cpu=\\\"x86\\\"";\
-	elif [ "${DEB_BUILD_GNU_CPU}" = "x86_64" ]; then \
-	  echo "host_cpu=\\\"x64\\\"";\
-	elif [ "${DEB_BUILD_GNU_CPU}" = "aarch64" ]; then \
-	  echo "host_cpu=\\\"arm64\\\"";\
-	elif [ "${DEB_BUILD_GNU_CPU}" = "arm64" ]; then \
-	  echo "host_cpu=\\\"arm64\\\"";\
-	elif [ "${DEB_BUILD_GNU_CPU:0:3}" == "arm" ]; then \
-	  echo "host_cpu=\\\"arm\\\"";\
-	fi\
-)
 override_dh_auto_configure:
-	env
-	uname -a
-	gn gen out/release --args="is_debug=false use_custom_libcxx=false\
-	  is_hermetic_clang=false is_system_compiler=true is_clang=false\
-	  skip_buildtools_check=true enable_perfetto_integration_tests=false\
-	  enable_perfetto_unittests=false perfetto_use_system_protobuf=true\
-	  perfetto_use_system_zlib=true perfetto_enable_git_rev_version_header=false\
-	  extra_cflags=\"${CFLAGS}\" extra_cxxflags=\"${CXXFLAGS}\"\
-	  extra_ldflags=\"${LDFLAGS}\" cc=\"${CC}\" cxx=\"${CXX}\"\
-	  ${MAYBE_HOST_CPU}"
+	tools/install-build-deps
+	tools/gn gen out/release --args="is_debug=false"
 
 override_dh_auto_build:
-	ninja -C out/release perfetto traced traced_probes
+	tools/ninja -C out/release
 
 override_dh_auto_clean:
-	rm -rf out/release
+	tools/gn clean out/release
diff --git a/debian/traced-perf.service b/debian/traced-perf.service
deleted file mode 100644
index 73bffb9..0000000
--- a/debian/traced-perf.service
+++ /dev/null
@@ -1,8 +0,0 @@
-[Unit]
-Description=Perfetto sampling and profiling data source
-Documentation=https://perfetto.dev/docs/
-
-[Service]
-ExecStart=/usr/sbin/traced_perf
-User=root
-Group=root
diff --git a/debian/traced-probes.service b/debian/traced-probes.service
index 1d853b0..3209123 100644
--- a/debian/traced-probes.service
+++ b/debian/traced-probes.service
@@ -1,6 +1,5 @@
 [Unit]
-Description=Perfetto data sources for system tracing (ftrace and /proc pollers)
-Documentation=https://perfetto.dev/docs/
+Description=Perfetto probes daemon
 
 [Service]
 ExecStart=/usr/sbin/traced_probes
diff --git a/debian/traced.service b/debian/traced.service
index 4ca8d7a..b082e9c 100644
--- a/debian/traced.service
+++ b/debian/traced.service
@@ -1,12 +1,10 @@
 [Unit]
-Description=Perfetto tracing service daemon
-Documentation=https://perfetto.dev/docs/
+Description=Perfetto trace daemon
 
 [Service]
-ExecStart=/usr/sbin/traced \
-    --set-socket-permissions traced:0666:traced-consumer:0660
-User=traced
-Group=traced
+ExecStart=/usr/sbin/traced
+User=nobody
+Group=nogroup
 PrivateTmp=no
 PrivateDevices=yes
 PrivateNetwork=yes
diff --git a/debian/triggers b/debian/triggers
deleted file mode 100644
index dd86603..0000000
--- a/debian/triggers
+++ /dev/null
@@ -1 +0,0 @@
-activate-noawait ldconfig
diff --git a/docs/README.md b/docs/README.md
index bec4a7e..00a5e9a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,7 +1,7 @@
 # Perfetto - System profiling, app tracing and trace analysis
 
 Perfetto is a production-grade open-source stack for performance
-instrumentation and trace analysis. It offers services and libraries for
+instrumentation and trace analysis. It offers services and libraries and for
 recording system-level and app-level traces, native + java heap profiling, a
 library for analyzing traces using SQL and a web-based UI to visualize and
 explore multi-GB traces.
@@ -12,25 +12,25 @@
 
 At its core, Perfetto introduces a novel userspace-to-userspace
 [tracing protocol](/docs/design-docs/api-and-abi.md#tracing-protocol-abi) based
-on direct protobuf serialization onto a shared memory buffer. The tracing
-protocol is used both internally for the built-in data sources and exposed to
-C++ apps through the [Tracing SDK](/docs/instrumentation/tracing-sdk.md) and the
+on direct protobuf serization onto a shared memory buffer. The tracing protocol
+is used both internally for the built-in data sources and exposed to C++ apps
+through the [Tracing SDK](/docs/instrumentation/tracing-sdk.md) and the
 [Track Event Library](/docs/instrumentation/track-events.md).
 
 This new tracing protocol allows dynamic configuration of all aspects of tracing
 through an extensible protobuf-based capability advertisement and data source
 configuration mechanism (see
 [Trace configuration docs](/docs/concepts/config.md)).
-Different data sources can be multiplexed onto different subsets of
+Different data sources can be multiplexed onto different sub-sets of
 user-defined buffers, allowing also streaming of
 [arbitrarily long traces](/docs/concepts/config.md#long-traces) into the
 filesystem.
 
 ### System-wide tracing on Android and Linux
 
-On Linux and Android, Perfetto bundles a number of data sources that are able to
+On Linux and Anroid, Perfetto bundles a number of data sources that are able to
 gather detailed performance data from different system interfaces. For the full
-sets and details see the _Data Sources_ section of the documentation. Some
+sets and details see the _Data Sources_ section of the documentation. Same
 examples:
 
 * [Kernel tracing](/docs/data-sources/cpu-scheduling.md): Perfetto integrates
@@ -46,7 +46,7 @@
 
 * [Native heap profiling](/docs/data-sources/native-heap-profiler.md): a
   low-overhead heap profiler for hooking malloc/free/new/delete and associating
-  memory to call-stacks, based on out-of-process unwinding, configurable
+  memory to callstacks, based on out-of-process unwinding, configurable
   sampling, attachable to already running processes.
 
 * [Java heap profiling](/docs/data-sources/java-heap-profiler.md): an
@@ -58,7 +58,7 @@
 
 On Android, Perfetto is the next-generation system tracing system and replaces
 the chromium-based systrace.
-[ATrace-based instrumentation](/docs/data-sources/atrace.md) remains fully
+[ATrace-based intstrumentation](/docs/data-sources/atrace.md) remains fully
 supported.
 See [Android developer docs](https://developer.android.com/topic/performance/tracing)
 for more details.
@@ -70,7 +70,7 @@
 between the flexibility of defining your own strongly-typed events and creating
 custom data sources or using the easier-to-use
 [Track Event Library](/docs/instrumentation/track-events.md) which allows to
-easily create time-bounded slices, counters and time markers using annotations
+easily create time-boudned slices, counters and time markers using annotations
 of the form `TRACE_EVENT("category", "event_name", "x", "str", "y", 42)`.
 
 The SDK is designed for tracing of multi-process systems and multi-threaded
@@ -109,8 +109,8 @@
 dedicated project for importing, parsing and querying new and legacy trace
 formats, [Trace Processor](/docs/analysis/trace-processor.md).
 
-Trace Processor is a portable C++11 library that provides column-oriented
-table storage, designed ad-hoc for efficiently holding hours of trace data
+Trace Processor is a portable C++11 library that provides a column-oriented
+table storage, designed ad-hoc for for efficiently holding hours of trace data
 into memory and exposes a SQL query interface based on the popular SQLite query
 engine.
 The trace data model becomes a set of
@@ -136,7 +136,7 @@
 
 Perfetto provides also a brand new trace visualizer for opening and querying
 hours-long traces, available at [ui.perfetto.dev](https://ui.perfetto.dev).
-The new visualizer takes advantage of modern web platform technologies.
+The new visualizer takes advantage of modern web platform technolgies.
 Its multi-threading design based WebWorkers keeps the UI always responsive;
 the analytical power of Trace Processor and SQLite is fully available in-browser
 through WebAssembly.
diff --git a/docs/analysis/metrics.md b/docs/analysis/metrics.md
index 6798ae2..7ab44d2 100644
--- a/docs/analysis/metrics.md
+++ b/docs/analysis/metrics.md
@@ -65,9 +65,6 @@
 
 ### Case for upstreaming
 
-NOTE: Googlers: for internal usage of metrics in Google3 (i.e. metrics which are
-confidential), please see [this internal page](https://goto.google.com/viecd).
-
 Authors are strongly encouraged to add all metrics derived on Perfetto traces to
 the Perfetto repo unless there is a clear usecase (e.g. confidentiality) why
 these metrics should not be publicly available.
@@ -88,7 +85,7 @@
 
 ## Walkthrough: prototyping a metric
 
-TIP: To see how to add a new metric to trace processor, see the checklist
+TIP: To see how to add to add a new metric to trace processor, see the checklist
 [here](/docs/contributing/common-tasks.md#new-metric)
 
 This walkthrough will outline how to prototype a metric locally without needing
@@ -100,7 +97,7 @@
       the walkthrough. The prerequisites and Step 4 below give instructions on
       how to get trace processor and run the metrics code.
 
-[gist]: https://gist.github.com/LalitMaganti/c221cf0cae17e298dfa82b118edf9080
+[gist]: https://gist.github.com/tilal6991/c221cf0cae17e298dfa82b118edf9080
 
 ### Prerequisites
 
@@ -135,7 +132,7 @@
 
 ```protobuf
 extend TraceMetrics {
-  optional TopProcesses top_five_processes = 450;
+  optional TopProcesses top_processes = 450;
 }
 ```
 
@@ -167,7 +164,7 @@
 }
 
 extend TraceMetrics {
-  optional TopProcesses top_five_processes = 450;
+  optional TopProcesses top_processes = 450;
 }
 ```
 
@@ -177,11 +174,11 @@
 sum of the CPU time they ran for and the number of threads which were associated
 with the process.
 
-The following SQL should be added to a file called `top_five_processes.sql` in
-the workspace:
+The following SQL should added to a file called `top_five_processes.sql` in the
+workspace:
 
 ```sql
-CREATE VIEW top_five_processes_by_cpu AS
+CREATE VIEW top_five_processes_by_cpu
 SELECT
   process.name as process_name,
   CAST(SUM(sched.dur) / 1e6 as INT64) as cpu_time_ms,
@@ -224,7 +221,7 @@
 Let's look at how it works for our table above.
 
 ```sql
-CREATE VIEW top_five_processes_output AS
+CREATE VIEW top_processes_output AS
 SELECT TopProcesses(
   'process_info', (
     SELECT RepeatedField(
@@ -296,7 +293,7 @@
 ORDER BY cpu_time_ms DESC
 LIMIT 5;
 
-CREATE top_five_processes_output AS
+CREATE top_processes_output AS
 SELECT TopProcesses(
   'process_info', (
     SELECT RepeatedField(
@@ -330,7 +327,7 @@
 
 _Notes:_
 
-- If something doesn't work as intended, check that the workspace looks the same as the contents of this [GitHub gist](https://gist.github.com/LalitMaganti/c221cf0cae17e298dfa82b118edf9080).
+- If something doesn't work as intended, check that the 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).
 - stderr is redirected to remove any noise from parsing the trace that trace processor generates.
 
diff --git a/docs/analysis/trace-processor.md b/docs/analysis/trace-processor.md
index f12afb6..236d871 100644
--- a/docs/analysis/trace-processor.md
+++ b/docs/analysis/trace-processor.md
@@ -244,150 +244,6 @@
 GROUP BY thread_name
 ```
 
-## Operator tables
-SQL queries are usually sufficient to retrieve data from trace processor.
-Sometimes though, certain constructs can be difficult to express pure SQL.
-
-In these situations, trace processor has special "operator tables" which solve
-a particular problem in C++ but expose an SQL interface for queries to take
-advantage of.
-
-### Span join
-Span join is a custom operator table which computes the intersection of
-spans of time from two tables or views. A column (called the *partition*)
-can optionally be specified which divides the rows from each table into
-partitions before computing the intersection.
-
-![Span join block diagram](/docs/images/span-join.png)
-
-```sql
--- Get all the scheduling slices
-CREATE VIEW sp_sched AS
-SELECT ts, dur, cpu, utid
-FROM sched
-
--- Get all the cpu frequency slices
-CREATE VIEW sp_frequency AS
-SELECT
-  ts,
-  lead(ts) OVER (PARTITION BY cpu ORDER BY ts) - ts as dur,
-  cpu,
-  value as freq
-FROM counter
-
--- Create the span joined table which combines cpu frequency with
--- scheduling slices.
-CREATE VIRTUAL TABLE sched_with_frequency
-USING SPAN_JOIN(sp_sched PARTITIONED cpu, sp_frequency PARTITIONED cpu)
-
--- This span joined table can be queried as normal and has the columns from both
--- tables.
-SELECT ts, dur, cpu, utid, freq
-FROM sched_with_frequency
-```
-
-NOTE: A partition can be specified on neither, either or both tables. If
-specified on both, the same column name has to be specified on each table.
-
-WARNING: An important restriction on span joined tables is that spans from
-the same table in the same partition *cannot* overlap. For performance
-reasons, span join does not attempt to detect and error out in this situation;
-instead, incorrect rows will silently be produced.
-
-### Ancestor slice
-ancestor_slice is a custom operator table that takes a
-[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and computes
-all slices on the same track that are direct parents above that id (i.e. given
-a slice id it will return as rows all slices that can be found by following
-the parent_id column to the top slice (depth = 0)).
-
-The returned format is the same as the
-[slice table](/docs/analysis/sql-tables.autogen#slice)
-
-For example, the following finds the top level slice given a bunch of slices of
-interest.
-
-```sql
-CREATE VIEW interesting_slices AS
-SELECT id, ts, dur, track_id
-FROM slice WHERE name LIKE "%interesting slice name%";
-
-SELECT
-  *
-FROM
-  interesting_slices LEFT JOIN
-  ancestor_slice(interesting_slices.id) AS ancestor ON ancestor.depth = 0
-```
-
-### Descendant slice
-descendant_slice is a custom operator table that takes a
-[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and
-computes all slices on the same track that are nested under that id (i.e.
-all slices that are on the same track at the same time frame with a depth
-greater than the given slice's depth.
-
-The returned format is the same as the
-[slice table](/docs/analysis/sql-tables.autogen#slice)
-
-For example, the following finds the number of slices under each slice of
-interest.
-
-```sql
-CREATE VIEW interesting_slices AS
-SELECT id, ts, dur, track_id
-FROM slice WHERE name LIKE "%interesting slice name%";
-
-SELECT
-  *
-  (
-    SELECT
-      COUNT(*) AS total_descendants
-    FROM descendant_slice(interesting_slice.id)
-  )
-FROM interesting_slices
-```
-
-### Connected/Following/Preceding flows
-
-DIRECTLY_CONNECTED_FLOW, FOLLOWING_FLOW and PRECEDING_FLOW are custom operator
-tables that take a
-[slice table's id column](/docs/analysis/sql-tables.autogen#slice) and collect
-all entries of [flow table](/docs/analysis/sql-tables.autogen#flow), that are
-directly or indirectly connected to the given starting slice.
-
-`DIRECTLY_CONNECTED_FLOW(start_slice_id)` - contains all entries of
-[flow table](/docs/analysis/sql-tables.autogen#flow) that are present in any
-chain of kind: `flow[0] -> flow[1] -> ... -> flow[n]`, where
-`flow[i].slice_out = flow[i+1].slice_in` and `flow[0].slice_out = start_slice_id
-OR start_slice_id = flow[n].slice_in`.
-
-NOTE: Unlike the following/preceding flow functions, this function will not
-include flows connected to ancestors or descendants while searching for flows
-from a slice. It only includes the slices in the directly connected chain.
-
-`FOLLOWING_FLOW(start_slice_id)` - contains all flows which can be reached from
-a given slice via recursively following from flow's outgoing slice to its
-incoming one and from a reached slice to its child. The return table contains
-all entries of [flow table](/docs/analysis/sql-tables.autogen#flow) that are
-present in any chain of kind: `flow[0] -> flow[1] -> ... -> flow[n]`, where
-`flow[i+1].slice_out IN DESCENDANT_SLICE(flow[i].slice_in) OR
-flow[i+1].slice_out = flow[i].slice_in` and `flow[0].slice_out IN
-DESCENDANT_SLICE(start_slice_id) OR flow[0].slice_out = start_slice_id`.
-
-`PRECEDING_FLOW(start_slice_id)` - contains all flows which can be reached from
-a given slice via recursively following from flow's incoming slice to its
-outgoing one and from a reached slice to its parent. The return table contains
-all entries of [flow table](/docs/analysis/sql-tables.autogen#flow) that are
-present in any chain of kind: `flow[n] -> flow[n-1] -> ... -> flow[0]`, where
-`flow[i].slice_in IN ANCESTOR_SLICE(flow[i+1].slice_out) OR flow[i].slice_in =
-flow[i+1].slice_out` and `flow[0].slice_in IN ANCESTOR_SLICE(start_slice_id) OR
-flow[0].slice_in = start_slice_id`.
-
-```sql
---number of following flows for each slice
-SELECT (SELECT COUNT(*) FROM FOLLOWING_FLOW(slice_id)) as following FROM slice;
-```
-
 ## Metrics
 
 TIP: To see how to add to add a new metric to trace processor, see the checklist
@@ -461,278 +317,6 @@
       and alerts added on these instead; this is because the trace processor
       storage is monotonic-append-only.
 
-## Python API
-
-The trace processor Python API is built on the existing HTTP interface of `trace processor`
-and is available as part of the standalone build. The API allows you to load in traces and
-query tables and run metrics without requiring the `trace_processor` binary to be
-downloaded or installed.
-
-### Setup
-```
-pip install perfetto
-```
-NOTE: The API is only compatible with Python3.
-
-```python
-from perfetto.trace_processor import TraceProcessor
-# Initialise TraceProcessor with a trace file
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-```
-
-NOTE: The TraceProcessor can be initialized in a combination of ways including:
-      <br> - An address at which there exists a running instance of `trace_processor` with a
-      loaded trace (e.g. `TraceProcessor(addr='localhost:9001')`)
-      <br> - An address at which there exists a running instance of `trace_processor` and
-      needs a trace to be loaded in
-      (e.g. `TraceProcessor(addr='localhost:9001', file_path='trace.perfetto-trace')`)
-      <br> - A path to a `trace_processor` binary and the trace to be loaded in
-      (e.g. `TraceProcessor(bin_path='./trace_processor', file_path='trace.perfetto-trace')`)
-
-
-### API
-
-The `trace_processor.api` module contains the `TraceProcessor` class which provides various
-functions that can be called on the loaded trace. For more information on how to use
-these functions, see this [`example`](/src/trace_processor/python/example.py).
-
-#### Query
-The query() function takes an SQL query as input and returns an iterator through the rows
-of the result.
-
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-qr_it = tp.query('SELECT ts, dur, name FROM slice')
-for row in qr_it:
-  print(row.ts, row.dur, row.name)
-```
-**Output**
-```
-261187017446933 358594 eglSwapBuffersWithDamageKHR
-261187017518340 357 onMessageReceived
-261187020825163 9948 queueBuffer
-261187021345235 642 bufferLoad
-261187121345235 153 query
-...
-```
-The QueryResultIterator can also be converted to a Pandas DataFrame, although this
-requires you to have both the `NumPy` and `Pandas` modules installed.
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-qr_it = tp.query('SELECT ts, dur, name FROM slice')
-qr_df = qr_it.as_pandas_dataframe()
-print(qr_df.to_string())
-```
-**Output**
-```
-ts                   dur                  name
--------------------- -------------------- ---------------------------
-     261187017446933               358594 eglSwapBuffersWithDamageKHR
-     261187017518340                  357 onMessageReceived
-     261187020825163                 9948 queueBuffer
-     261187021345235                  642 bufferLoad
-     261187121345235                  153 query
-     ...
-```
-Furthermore, you can use the query result in a Pandas DataFrame format to easily
-make visualisations from the trace data.
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-qr_it = tp.query('SELECT ts, value FROM counter WHERE track_id=50')
-qr_df = qr_it.as_pandas_dataframe()
-qr_df = qr_df.replace(np.nan,0)
-qr_df = qr_df.set_index('ts')['value'].plot()
-```
-**Output**
-
-![Graph made frpm the query results](/docs/images/example_pd_graph.png)
-
-
-#### Metric
-The metric() function takes in a list of trace metrics and returns the results as a Protobuf.
-
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-ad_cpu_metrics = tp.metric(['android_cpu'])
-print(ad_cpu_metrics)
-```
-**Output**
-```
-metrics {
-  android_cpu {
-    process_info {
-      name: "/system/bin/init"
-      threads {
-        name: "init"
-        core {
-          id: 1
-          metrics {
-            mcycles: 1
-            runtime_ns: 570365
-            min_freq_khz: 1900800
-            max_freq_khz: 1900800
-            avg_freq_khz: 1902017
-          }
-        }
-        core {
-          id: 3
-          metrics {
-            mcycles: 0
-            runtime_ns: 366406
-            min_freq_khz: 1900800
-            max_freq_khz: 1900800
-            avg_freq_khz: 1902908
-          }
-        }
-        ...
-      }
-      ...
-    }
-    process_info {
-      name: "/system/bin/logd"
-      threads {
-        name: "logd.writer"
-        core {
-          id: 0
-          metrics {
-            mcycles: 8
-            runtime_ns: 33842357
-            min_freq_khz: 595200
-            max_freq_khz: 1900800
-            avg_freq_khz: 1891825
-          }
-        }
-        core {
-          id: 1
-          metrics {
-            mcycles: 9
-            runtime_ns: 36019300
-            min_freq_khz: 1171200
-            max_freq_khz: 1900800
-            avg_freq_khz: 1887969
-          }
-        }
-        ...
-      }
-      ...
-    }
-    ...
-  }
-}
-```
-
-### HTTP
-The `trace_processor.http` module contains the `TraceProcessorHttp` class which
-provides methods to make HTTP requests to an address at which there already
-exists a running instance of `trace_processor` with a trace loaded in. All
-results are returned in Protobuf format
-(see [`trace_processor_proto`](/protos/perfetto/trace_processor/trace_processor.proto)).
-Some functions include:
-* `execute_query()` - Takes in an SQL query and returns a `QueryResult` Protobuf
-  message
-* `compute_metric()` - Takes in a list of trace metrics and returns a
-  `ComputeMetricResult` Protobuf message
-* `status()` - Returns a `StatusResult` Protobuf message
-
-
-## Testing
-
-Trace processor is mainly tested in two ways:
-1. Unit tests of low-level building blocks
-2. "Diff" tests which parse traces and check the output of queries
-
-### Unit tests
-Unit testing trace processor is the same as in other parts of Perfetto and
-other C++ projects. However, unlike the rest of Perfetto, unit testing is
-relatively light in trace processor.
-
-We have discovered over time that unit tests are generally too brittle
-when dealing with code which parses traces leading to painful, mechanical
-changes being needed when refactorings happen.
-
-Because of this, we choose to focus on diff tests for most areas (e.g.
-parsing events, testing schema of tables, testing metrics etc.) and only
-use unit testing for the low-level building blocks on which the rest of
-trace processor is built.
-
-### Diff tests
-Diff tests are essentially integration tests for trace processor and the
-main way trace processor is tested.
-
-Each diff test takes as input a) a trace file b) a query file *or* a metric
-name. It runs `trace_processor_shell` to parse the trace and then executes
-the query/metric. The result is then compared to a 'golden' file and any
-difference is highlighted.
-
-All diff tests are organized under [test/trace_processor](/test/trace_processor)
-and are run by the script
-[`tools/diff_test_trace_processor.py`](/tools/diff_test_trace_processor.py).
-New tests can be added with the helper script
-[`tools/add_tp_diff_test.py`](/tools/add_tp_diff_test.py).
-
-NOTE: `trace_processor_shell` and associated proto descriptors needs to be
-built before running `tools/diff_test_trace_processor.py`. The easiest way
-to do this is to run `tools/ninja -C <out directory>` both initially and on
-every change to trace processor code or builtin metrics.
-
-#### Choosing where to add diff tests
-When adding a new test with `tools/add_tp_diff_test.py`, the user is
-prompted for a folder to add the new test to. Often this can be confusing
-as a test can fall into more than one category. This section is a guide
-to decide which folder to choose.
-
-Broadly, there are two categories which all folders fall into:
-1. __"Area" folders__ which encompass a "vertical" area of interest
-   e.g. startup/ contains Android app startup related tests or chrome/
-   contains all Chrome related tests.
-2. __"Feature" folders__ which encompass a particular feature of
-   trace processor e.g. process_tracking/ tests the lifetime tracking of
-   processes, span_join/ tests the span join operator.
-
-"Area" folders should be preferred for adding tests unless the test is
-applicable to more than one "area"; in this case, one of "feature" folders
-can be used instead.
-
-Here are some common scenarios in which new tests may be added and
-answers on where to add the test:
-
-__Scenario__: A new event is being parsed, the focus of the test is to ensure
-the event is being parsed correctly and the event is focused on a single
-vertical "Area".
-
-_Answer_: Add the test in one of the "Area" folders.
-
-__Scenario__: A new event is being parsed and the focus of the test is to ensure
-the event is being parsed correctly and the event is applicable to more than one
-vertical "Area".
-
-_Answer_: Add the test to the parsing/ folder.
-
-__Scenario__: A new metric is being added and the focus of the test is to
-ensure the metric is being correctly computed.
-
-_Answer_: Add the test in one of the "Area" folders.
-
-__Scenario__: A new dynamic table is being added and the focus of the test is to
-ensure the dynamic table is being correctly computed...
-
-_Answer_: Add the test to the dynamic/ folder
-
-__Scenario__: The interals of trace processor are being modified and the test
-is to ensure the trace processor is correctly filtering/sorting important
-built-in tables.
-
-_Answer_: Add the test to the tables/ folder.
-
-
 ## Appendix: table inheritance
 
 Concretely, the rules for inheritance between tables works are as follows:
diff --git a/docs/case-studies/memory.md b/docs/case-studies/memory.md
index ce23193..c2e8391 100644
--- a/docs/case-studies/memory.md
+++ b/docs/case-studies/memory.md
@@ -3,8 +3,6 @@
 ## Prerequisites
 
 * A host running macOS or Linux.
-* [ADB](https://developer.android.com/studio/command-line/adb) installed and
-  in PATH.
 * A device running Android 11+.
 
 If you are profiling your own app and are not running a userdebug build of
@@ -321,7 +319,7 @@
 code. The profile *will only show allocations done while it was running*, any
 allocations done before will not be shown.
 
-### {#capture-profile-native} Capturing the profile
+### Capturing the profile
 
 Use the `tools/heap_profile` script to profile a process. If you are having
 trouble make sure you are using the [latest version](
@@ -388,7 +386,7 @@
       troubleshooting see the [Data sources > Java heap profiler](
       /docs/data-sources/java-heap-profiler.md) page.
 
-### {#capture-profile-java} Capturing the profile
+### Capturing the profile
 We can get a snapshot of the graph of all the Java objects that constitute the
 Java heap. We use the `tools/java_heap_dump` script. If you are having trouble
 make sure you are using the [latest version](
diff --git a/docs/concepts/buffers.md b/docs/concepts/buffers.md
index 2a8012c..2764858 100644
--- a/docs/concepts/buffers.md
+++ b/docs/concepts/buffers.md
@@ -347,7 +347,7 @@
    [`TraceConfig.IncrementalStateConfig.clear_period_ms`][IncrStateConfig].
    This will cause the data sources that make use of incremental state to
    periodically drop the interning / process mapping tables and re-emit the
-   descriptors / strings on the next occurrence. This mitigates quite well the
+   descriptors / strings on the next occurence. This mitigates quite well the
    problem in the context of ring-buffer traces, as long as the
    `clear_period_ms` is one order of magnitude lower than the estimated length
    of trace data in the central trace buffer.
@@ -363,15 +363,15 @@
 Another common problem experienced in traces that involve multiple data sources
 is the non-synchronous nature of trace commits. As explained in the
 [Life of a trace packet](#life-of-a-trace-packet) section above, trace data is
-committed only when a full memory page of the shared memory buffer is filled (or
+commited only when a full memory page of the shared memory buffer is filled (or
 at when the tracing session ends). In most cases, if data sources produce events
 at a regular cadence, pages are filled quite quickly and events are committed
 in the central buffers within seconds.
 
 In some other cases, however, a data source can emit events only sporadically.
 Imagine the case of a data source that emits events when the display is turned
-on/off. Such an infrequent event might end up being staged in the shared memory
-buffer for very long times and can end up being committed in the trace buffer
+on/off. Such an infequent event might end up being staged in the shared memory
+buffer for very long times and can end up being commited in the trace buffer
 hours after it happened.
 
 Another scenario where this can happen is when using ftrace and when a
@@ -419,4 +419,4 @@
 [FtraceCpuStats]: /docs/reference/trace-packet-proto.autogen#FtraceCpuStats
 [FtraceEventBundle]: /docs/reference/trace-packet-proto.autogen#FtraceEventBundle
 [TracePacket]: /docs/reference/trace-packet-proto.autogen#TracePacket
-[BufferStats]: /docs/reference/trace-packet-proto.autogen#TraceStats.BufferStats
+[BufferStats]: /docs/reference/trace-packet-proto.autogen#TraceStats.BufferStats
\ No newline at end of file
diff --git a/docs/concepts/clock-sync.md b/docs/concepts/clock-sync.md
index 4afb1b7..95a200f 100644
--- a/docs/concepts/clock-sync.md
+++ b/docs/concepts/clock-sync.md
@@ -120,7 +120,7 @@
 
 * 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") | 0x80000000`
+* 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.
 
 ### {#clock_snapshot} The ClockSnapshot trace packet
diff --git a/docs/concepts/config.md b/docs/concepts/config.md
index 99f4cbc..1f8d37e 100644
--- a/docs/concepts/config.md
+++ b/docs/concepts/config.md
@@ -36,15 +36,12 @@
 And is used as follows:
 
 ```bash
-perfetto --txt -c config.pbtx -o trace_file.perfetto-trace
+perfetto --txt -c config.pbtx -o trace_file.pftrace
 ```
 
 TIP: Some more complete examples of trace configs can be found in the repo in
 [`/test/configs/`](/test/configs/).
 
-NOTE: If you are tracing on Android using adb and experiencing problems, see
-      [the Android section](#android) below.
-
 ## TraceConfig
 
 The TraceConfig is a protobuf message
@@ -199,7 +196,7 @@
 should be interpreted as a PBTX file:
 
 ```bash
-perfetto -c /path/to/config.pbtx --txt -o trace_file.perfetto-trace
+perfetto -c /path/to/config.pbtx --txt -o trace_file.pftrace
 ```
 
 NOTE: The `--txt` option has been introduced only in Android 10 (Q). Older
@@ -229,7 +226,7 @@
 and then passing it to perfetto as follows, without the `--txt` argument:
 
 ```bash
-perfetto -c config.bin -o trace_file.perfetto-trace
+perfetto -c config.bin -o trace_file.pftrace
 ```
 
 ## {#long-traces} Streaming long traces
@@ -362,10 +359,11 @@
 data_sources {
   config {
     name: "track_event"
+
+    # Enable the data source only on Chrome and Chrome canary.
+    producer_name_filter: "com.android.chrome"
+    producer_name_filter: "com.google.chrome.canary"
   }
-  # Enable the data source only on Chrome and Chrome canary.
-  producer_name_filter: "com.android.chrome"
-  producer_name_filter: "com.google.chrome.canary"
 }
 ```
 
@@ -418,18 +416,16 @@
 Start triggers allow activating a tracing session only after some significant
 event has happened. Passing a trace config that has `START_TRACING` trigger
 causes the tracing session to stay idle (i.e. not recording any data) until either
-the trigger is hit or the `trigger_timeout_ms` timeout is hit.
-
-`trace_duration_ms` and triggered traces can not be used at the same time.
+the trigger is hit or the `duration_ms` timeout is hit.
 
 Example config:
 ```protobuf
-# If no trigger is hit, the trace will end without having recorded any data
-# after 30s.
-trigger_timeout_ms: 30000
+// If no trigger is hit, the trace will end without having recorded any data
+// after 30s.
+duration_ms: 30000
 
-# If the "myapp_is_slow" is hit, the trace starts recording data and will be
-# stopped after 5s.
+// If the "myapp_is_slow" is hit, the trace starts recording data and will be
+// stopped after 5s.
 trigger_config {
   trigger_mode: START_TRACING
   triggers {
@@ -438,7 +434,7 @@
   }
 }
 
-# The rest of the config is as usual.
+// The rest of the config is as usual.
 buffers { ... }
 data_sources { ... }
 ```
@@ -458,10 +454,10 @@
 
 Example config:
 ```protobuf
-# If no trigger is hit, the trace will end after 30s.
-trigger_timeout_ms: 30000
+// If no trigger is hit, the trace will end after 30s.
+duration_ms: 30000
 
-# If the "missed_frame" is hit, the trace is stopped after 1s.
+// If the "missed_frame" is hit, the trace is stopped after 1s.
 trigger_config {
   trigger_mode: STOP_TRACING
   triggers {
@@ -470,29 +466,11 @@
   }
 }
 
-# The rest of the config is as usual.
+// The rest of the config is as usual.
 buffers { ... }
 data_sources { ... }
 ```
 
-## Android
-
-On Android, there are some caveats around using `adb shell`
-
-* Ctrl+C, which normally causes a graceful termination of the trace, is not
-  propagated by ADB when using `adb shell perfetto` but only when using an
-  interactive PTY-based session via `adb shell`.
-* On non-rooted devices before Android 12, the config can only be passed as
-  `cat config | adb shell perfetto -c -` (-: stdin) because of over-restrictive
-  SELinux rules. Since Android 12 `/data/misc/perfetto-configs` can be used for
-  storing configs.
-* On devices before Android 10, adb cannot directly pull
-  `/data/misc/perfetto-traces`. Use
-  `adb shell cat /data/misc/perfetto-traces/trace > trace` to work around.
-* When capturing longer traces, e.g. in the context of benchmarks or CI, use
-  `PID=$(perfetto --background)` and then `kill $PID` to stop.
-
-
 ## Other resources
 
 * [TraceConfig Reference](/docs/reference/trace-config-proto.autogen)
diff --git a/docs/contributing/build-instructions.md b/docs/contributing/build-instructions.md
index 0c12902..2bc82ae 100644
--- a/docs/contributing/build-instructions.md
+++ b/docs/contributing/build-instructions.md
@@ -3,8 +3,6 @@
 The source of truth for the Perfetto codebase lives in AOSP:
 https://android.googlesource.com/platform/external/perfetto/
 
-A read-only mirror is also available at https://github.com/google/perfetto .
-
 Perfetto can be built both from the Android tree (AOSP) and standalone.
 Standalone builds are meant only for local testing and are not shipped.
 Due to the reduced dependencies they are faster to iterate on and the
@@ -12,57 +10,51 @@
 
 ## Get the code
 
-**Standalone checkout**:
-
-```bash
-git clone https://android.googlesource.com/platform/external/perfetto/
+**Standalone checkout**:  
+```
+$ git clone https://android.googlesource.com/platform/external/perfetto/
 ```
 
-**Android tree**:
-
-Perfetto lives in [`external/perfetto` in the AOSP tree](https://cs.android.com/android/platform/superproject/+/master:external/perfetto/).
+**Android tree**:  
+Perfetto lives in `external/perfetto` in the AOSP tree.
 
 ## Prerequisites
 
-**Standalone checkout**:
-
+**Standalone checkout**:  
 All dependent libraries are self-hosted and pulled through:
-
-```bash
-tools/install-build-deps [--android] [--ui]
+```
+$ tools/install-build-deps [--android] [--ui]
 ```
 
-**Android tree**:
-
+**Android tree**:  
 See https://source.android.com/setup
 
+
 ## Building
 
-**Standalone checkout**:
-
+**Standalone checkout**:  
 If you are a chromium developer and have depot_tools installed you can avoid
 the `tools/` prefix below and just use gn/ninja from depot_tools.
 
 `$ tools/gn args out/android` to generate build files and enter in the editor:
 
-```python
+```
 target_os = "android"                 # Only when building for Android
-target_cpu = "arm" / "arm64" / "x64"
+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)
 
-```bash
-tools/ninja -C out/android
+```
+$ tools/ninja -C out/android
 ```
 
-**Android tree**
-
-`mmma external/perfetto`
+**Android tree**:  
+`$ mmma external/perfetto`
 or
-`m perfetto traced traced_probes`
+`$ m perfetto traced traced_probes`
 
 This will generate artifacts `out/target/product/XXX/system/`.
 Executables and shared libraries are stripped by default by the Android build
@@ -70,43 +62,26 @@
 
 ## UI development
 
-This command pulls the UI-related dependencies (notably, the NodeJS binary)
-and installs the `node_modules` in `ui/node_modules`:
+To build the UI (remember to run `tools/install-build-deps --ui` first):
 
-```bash
-tools/install-build-deps --ui
 ```
+$ tools/ninja -C out/android ui
 
-Build the UI:
-
-```bash
-# Will build into ./out/ui by default. Can be changed with --out path/
-# The final bundle will be available at ./ui/out/dist/.
-# The build script creates a symlink from ./ui/out to $OUT_PATH/ui/.
-ui/build
 ```
-
 Test your changes on a local server using:
 
-```bash
-# This will automatically build the UI. There is no need to manually run
-# ui/build before running ui/run-dev-server.
-ui/run-dev-server
 ```
-
-Navigate to http://localhost:10000/ to see the changes.
-
-The server supports live reloading of CSS and TS/JS contents. Whenever a ui
-source file is changed it, the script will automatically re-build it and show a
-prompt in the web page.
+$ ui/run-dev-server out/android
+```
+Navigate to `localhost:10000` to see the changes.
 
 ## IDE setup
 
 Use a following command in the checkout directory in order to generate the
 compilation database file:
 
-```bash
-tools/gn gen out/default --export-compile-commands
+```
+$ tools/ninja -C out/android -t compdb cc cxx > compile_commands.json
 ```
 
 After generating, it can be used in CLion (File -> Open -> Open As Project),
@@ -115,192 +90,80 @@
 
 ## Build files
 
-The source of truth of our build file is in the BUILD.gn files, which are based
-on [GN][gn-quickstart].
-The Android build file ([Android.bp](/Android.bp)) is autogenerated from the GN
-files through `tools/gen_android_bp`, which needs to be invoked whenever a
-change touches GN files or introduces new ones.
-
+The source of truth of our build file is in the BUILD.gn files, which are based on [GN][gn-quickstart].
+The Android build file ([Android.bp](/Android.bp)) is autogenerated from the GN files
+through `tools/gen_android_bp`, which needs to be invoked whenever a change
+touches GN files or introduces new ones.  
 A presubmit check checks that the Android.bp is consistent with GN files when
-submitting a CL through `git cl upload`.
-
-The generator has a list of root targets that will be translated into the
+submitting a CL through `git cl upload`.  
+The generator has a whitelist of root targets that will be translated into the
 Android.bp file. If you are adding a new target, add a new entry to the
-`default_targets` variable in [`tools/gen_android_bp`](/tools/gen_android_bp).
+`default_targets` variable inside [tools/gen\_android\_bp](/tools/gen_android_bp).
 
 ## Supported platforms
 
-**Linux desktop** (Debian Rodete)
+**Linux desktop** (Debian Rodete):
+  - Hermetic clang + libcxx toolchain (both following chromium's revisions)
+  - GCC-7 and libstdc++ 6
 
-- Hermetic clang + libcxx toolchain (both following chromium's revisions)
-- GCC-7 and libstdc++ 6
+**Android**:
+  - Android's NDK r15c (using NDK's libcxx)
+  - AOSP's in-tree clang (using in-tree libcxx)
 
-**Android**
-
-- Android's NDK r15c (using NDK's libcxx)
-- AOSP's in-tree clang (using in-tree libcxx)
-
-**Mac**
-
-- XCode 9 / clang (currently maintained best-effort).
-
-**Windows**
-
-Windows builds are not currently supported when using the standalone checkout
-and GN. Windows is supported only for a subset of the targets (mainly
-`trace_processor` and the in-process version of the
-[Tracing SDK](/docs/instrumentation/tracing-sdk.md)) in two ways:
-(1) when building through Bazel; (2) when building as part of Chromium.
+**Mac**:
+ - XCode 9 / clang (currently maintained best-effort).
 
 ## Build configurations
 
-TIP: `tools/build_all_configs.py` can be used to generate out/XXX folders for
-most of the supported configurations.
+TIP: `tools/build_all_configs.py` can be used to generate out/XXX folders for most of
+the supported configurations.
 
 The following [GN args][gn-quickstart] are supported:
 
-`target_os = "android" | "linux" | "mac"`:
-
+`target_os = "android" | "linux" | "mac"`:  
 Defaults to the current host, set "android" to build for Android.
 
-`target_cpu = "arm" | "arm64" | "x64"`
-
+`target_cpu = "arm" | "arm64" | "x86" | "x64"`:  
 Defaults to `"arm"` when `target_os` == `"android"`, `"x64"` when targeting the
 host. 32-bit host builds are not supported.
-Note: x64 here really means x86_64. This is to keep it consistent with
-Chromium's choice, which in turn follows Windows naming convention.
 
-`is_debug = true | false`
+`is_debug = true | false`:  
+Toggles Debug (default) / Release mode.
 
-Toggles Debug (default) / Release mode. This affects, among other things:
-(i) the `-g` compiler flag; (ii) setting/unsetting `-DNDEBUG`; (iii) turning
-on/off `DCHECK` and `DLOG`.
-Note that debug builds of Perfetto are sensibly slower than release versions. We
-strongly encourage using debug builds only for local development.
-
-`is_clang = true | false`
-
+`is_clang = true | false`:  
 Use Clang (default: true) or GCC (false).
 On Linux, by default it uses the self-hosted clang (see `is_hermetic_clang`).
 On Android, by default it uses clang from the NDK (in `buildtools/ndk`).
 On Mac, by default it uses the system version of clang (requires Xcode).
-See also the [custom toolchain](#custom-toolchain) section below.
 
-`is_hermetic_clang = true | false`
-
+`is_hermetic_clang = true | false`:  
 Use bundled toolchain from `buildtools/` rather than system-wide one.
 
-`cc = "gcc" / cxx = "g++"`
-
+`cc = "gcc" / cxx = "g++"`:  
 Uses a different compiler binary (default: autodetected depending on is_clang).
-See also the [custom toolchain](#custom-toolchain) section below.
 
-`cc_wrapper = "tool_name"`
-
+`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 considerably speed up repeat builds.
 
-`is_asan = true`
-
+`is_asan = true`:  
 Enables [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer)
 
-`is_lsan = true`
-
+`is_lsan = true`:  
 Enables [Leak Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer)
 (Linux/Mac only)
 
-`is_msan = true`
-
+`is_msan = true`:  
 Enables [Memory Sanitizer](https://github.com/google/sanitizers/wiki/MemorySanitizer)
 (Linux only)
 
-`is_tsan = true`
-
+`is_tsan = true`:  
 Enables [Thread Sanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
 (Linux/Mac only)
 
-`is_ubsan = true`
-
+`is_ubsan = true`:  
 Enables [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)
 
-### {#custom-toolchain} Using custom toolchains and CC / CXX / CFLAGS env vars
-
-When building Perfetto as part of some other build environment it might be
-necessary to switch off all the built-in toolchain-related path-guessing scripts
-and manually specify the path of the toolchains.
-
-```python
-# Disable the scripts that guess the path of the toolchain.
-is_system_compiler = true
-
-ar = "/path/to/ar"
-cc = "/path/to/gcc-like-compiler"
-cxx = "/path/to/g++-like-compiler"
-linker = ""  # This is passed to -fuse-ld=...
-```
-
-If you are using a build system that keeps the toolchain settings in
-environment variables, you can set:
-
-```python
-is_system_compiler = true
-ar="${AR}"
-cc="${CC}"
-cxx="${CXX}"
-```
-
-`is_system_compiler = true` can be used also for cross-compilation.
-In case of cross-compilation, the GN variables have the following semantic:
-`ar`, `cc`, `cxx`, `linker` refer to the _host_ toolchain (sometimes also called
-_build_ toolchain). This toolchain is used to build: (i) auxiliary tools
-(e.g. the `traceconv` conversion util) and (ii) executable artifacts that are
-used during the rest of the build process for the target (e.g., the `protoc`
-compiler or the `protozero_plugin` protoc compiler plugin).
-
-The cross-toolchain used to build the artifacts that run on the device is
-prefixed by `target_`: `target_ar`, `target_cc`, `target_cxx`, `target_linker`.
-
-```python
-# Cross compilation kicks in when at least one of these three variables is set
-# to a value != than the host defaults.
-
-target_cpu = "x86" | "x64" | "arm" | "arm64"
-target_os = "linux" | "android"
-target_triplet =  "arm-linux-gnueabi" | "x86_64-linux-gnu" | ...
-```
-
-When integrating with GNU Makefile cross-toolchains build environments, a
-typical mapping of the corresponding environment variables is:
-
-```python
-ar="${BUILD_AR}"
-cc="${BUILD_CC}"
-cxx="${BUILD_CXX}"
-target_ar="${AR}"
-target_cc="${CC}"
-target_cxx="${CXX}"
-```
-
-It is possible to extend the set of `CFLAGS` and `CXXFLAGS` through the
-`extra_xxxflags` GN variables as follows. The extra flags are always appended
-(hence, take precedence) to the set of flags that the GN build files generate.
-
-```python
-# These apply both to host and target toolchain.
-extra_cflags="${CFLAGS}"
-extra_cxxflags="${CXXFLAGS}"
-extra_ldflags="${LDFLAGS}"
-
-# These apply only to the host toolchain.
-extra_host_cflags="${BUILD_CFLAGS}"
-extra_host_cxxflags="${BUILD_CXXFLAGS}"
-extra_host_ldflags="${BUILD_LDFLAGS}"
-
-# These apply only to the target toolchain.
-extra_target_cflags="${CFLAGS}"
-extra_target_cxxflags="${CXXFLAGS} ${debug_flags}"
-extra_target_ldflags="${LDFLAGS}"
-```
 
 [gn-quickstart]: https://gn.googlesource.com/gn/+/master/docs/quick_start.md
diff --git a/docs/contributing/chrome-branches.md b/docs/contributing/chrome-branches.md
deleted file mode 100644
index 3530f5f..0000000
--- a/docs/contributing/chrome-branches.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Branching Perfetto for Chrome milestones
-
-Merging a (set of) Perfetto change(s) to a Chrome milestone release requires
-creation of a branch in the perfetto repo, cherry-picking of the change(s) to
-the branch, and updating the `DEPS` file in Chrome's milestone branch to point
-to the new perfetto branch's head.
-
-## Creating the perfetto branch {#branch}
-
-1.  Determine the branch name: **`chromium/XXXX`**, where `XXXX` is the branch
-    number of the milestone (see
-    [Chromium Dash](https://chromiumdash.appspot.com/branches)). Example for
-    M87: `chromium/4280`.
-
-1.  Check if the branch already exists: if yes, skip to
-    [cherry-picking](#all-tables). To check, you can search for it in
-    [Gerrit's branch page](https://android-review.googlesource.com/admin/repos/platform/external/perfetto,branches).
-
-1.  Look up the appropriate base revision for the branch. You should use the
-    revision that Chromium's `DEPS` of the milestone branch points to (search
-    for `perfetto` in the file). The `DEPS` file for branch XXXX is at:
-
-    `https://chromium.googlesource.com/chromium/src.git/+/refs/branch-heads/XXXX/DEPS`
-
-    Example for M87:
-    [`DEPS`](https://chromium.googlesource.com/chromium/src.git/+/refs/branch-heads/4280/DEPS)
-    (at time of writing) points to `f4cf78e052c9427d8b6c49faf39ddf2a2e236069`.
-
-1.  Create the branch - the easiest way to do this is via
-    [Gerrit's branch page](https://android-review.googlesource.com/admin/repos/platform/external/perfetto,branches).
-    The `NEW BRANCH` button on the top right opens a wizard - fill in the branch
-    name and base revision determined above. If this fails with a permission
-    issue, contact the [Discord chat](https://discord.gg/35ShE3A) or
-    [perfetto-dev](https://groups.google.com/forum/#!forum/perfetto-dev) mailing
-    list.
-
-## Cherry-picking the change(s) {#cherry-pick}
-
-1.  If there are no merge conflicts, cherry-picking via Gerrit will be easiest.
-    To attempt this, open your change in Gerrit and use the `Cherry pick` entry
-    in the overflow menu on the top right, providing the `chromium/XXXX` branch
-    name (see [above](#branch)).
-
-1.  Otherwise, merge the patch locally into a branch tracking
-    `origin/chromium/XXXX` and upload a Gerrit change as usual:
-
-    ```
-    $ git fetch origin
-    $ git checkout -tb cpick origin/chromium/XXXX
-    $ git cherry-pick -x <commit hash>    # Resolve conflicts manually.
-    $ tools/gen_all out/xxx               # If necessary.
-    $ git cl upload    # Remove "Change-Id:" lines from commit message.
-    ```
-
-1.  Send the patch for review and land it. Note the commit's revision hash.
-
-## Updating the DEPS file in Chromium
-
-1.  Create, send for review, and land a Chromium patch that edits the top-level
-    `DEPS` file on the Chromium's milestone branch. You can also combine this
-    step with cherry-picks of any chromium changes. For details, see
-    [Chromium's docs](https://www.chromium.org/developers/how-tos/drover). It
-    amounts to:
-
-    ```
-    $ gclient sync --with_branch_heads
-    $ git fetch
-    $ git checkout -tb perfetto_uprev refs/remotes/branch-heads/XXXX
-    $ ...    # Edit DEPS.
-    $ git cl upload
-    ```
diff --git a/docs/contributing/common-tasks.md b/docs/contributing/common-tasks.md
index d0724c9..40c1910 100644
--- a/docs/contributing/common-tasks.md
+++ b/docs/contributing/common-tasks.md
@@ -6,7 +6,7 @@
 
 1. Find the `format` file for your event. The location of the file depends where `tracefs` is mounted but can often be found at `/sys/kernel/debug/tracing/events/EVENT_GROUP/EVENT_NAME/format`.
 2. Copy the format file into the codebase at `src/traced/probes/ftrace/test/data/synthetic/events/EVENT_GROUP/EVENT_NAME/format`.
-3. Add the event to [tools/ftrace_proto_gen/event_list](/tools/ftrace_proto_gen/event_list).
+3. Add the event to [tools/ftrace_proto_gen/event_whitelist](/tools/ftrace_proto_gen/event_whitelist).
 4. Run `tools/run_ftrace_proto_gen`. This will update `protos/perfetto/trace/ftrace/ftrace_event.proto` and `protos/perfetto/trace/ftrace/GROUP_NAME.proto`.
 5. Run `tools/gen_all out/YOUR_BUILD_DIRECTORY`. This will update `src/traced/probes/ftrace/event_info.cc` and `protos/perfetto/trace/perfetto_trace.proto`.
 6. If special handling in `trace_processor` is desired update [src/trace_processor/importers/ftrace/ftrace_parser.cc](/src/trace_processor/importers/ftrace/ftrace_parser.cc) to parse the event.
@@ -23,10 +23,7 @@
 4. Add a new SQL file for the metric to [src/trace_processor/metrics](/src/trace_processor/metrics). The appropriate `BUILD.gn` file should be updated as well.
   * To learn how to write new metrics, see the [trace-based metrics documentation](/docs/analysis/metrics.md).
 5. Build all targets in your out directory with `tools/ninja -C out/YOUR_BUILD_DIRECTORY`.
-6. Add a new diff test for the metric. This can be done by adding files to
-the [test/trace_processor](/test/trace_processor) folder and modifying one
-of the index files listed in
-[/test/trace_processor/include_index](/test/trace_processor/include_index).
+6. Add a new diff test for the metric. This can be done by adding files to the [test/metrics](/test/metrics) folder and modifying the [index file](/test/metrics/index).
 7. Run the newly added test with `tools/diff_test_trace_processor.py <path to trace processor binary>`.
 8. Upload and land your change as normal.
 
@@ -39,8 +36,8 @@
 2. Register the table with the trace processor in the constructor for the [TraceProcessorImpl class](/src/trace_processor/trace_processor_impl.cc).
 3. If also implementing ingestion of events into the table:
   1. Modify the appropriate parser class in [src/trace_processor/importers](/src/trace_processor/importers) and add the code to add rows to the newly added table.
-  2. Add a new diff test for the added parsing code and table using
-  `tools/add_tp_diff_test.py`.
+  2. Add a new diff test for the added parsing code and table using `tools/add_tp_diff_test.sh`.
+    * Make sure to modify the [index file](/test/trace_processor/index) to correctly organize the test with other similar tests.
   3. Run the newly added test with `tools/diff_test_trace_processor.py <path to trace processor binary>`.
 4. Upload and land your change as normal.
 
@@ -61,14 +58,14 @@
 
 To extend a metric with annotations:
 
-1. Create a new table or view with the name `<metric name>_event`.
-  * For example, for the [`android_startup`]() metric, we create a view named `android_startup_event`.
-  * Note that the trailing `_event` suffix in the table name is important.
+1. Create a new table or view with the name `<metric name>_annotations`.
+  * For example, for the [`android_startup`]() metric, we create a view named `android_startup_annotations`.
+  * Note that the trailing `_annotations` suffix in the table name is important.
   * The schema required for this table is given below.
-2. List your metric in the `initialiseHelperViews` method of `trace_controller.ts`.
-3. Upload and land your change as normal.
 
-The schema of the `<metric name>_event` table/view is as follows:
+2. Upload and land your change as normal.
+
+The schema of the `<metric name>_annotations` table/view is as follows:
 
 | Name         | Type     | Presence                              | Meaning                                                      |
 | :----------- | -------- | ------------------------------------- | ------------------------------------------------------------ |
diff --git a/docs/contributing/embedding.md b/docs/contributing/embedding.md
index ad3ac88..a43fbed 100644
--- a/docs/contributing/embedding.md
+++ b/docs/contributing/embedding.md
@@ -72,7 +72,7 @@
 
 ### Creating derived events
 
-As creating derived events is tied to the metrics subsystem, the `ComputeMetrics` function in the trace processor API should be called with the appropriate metrics. This will create the `<metric_name>_event` table/view which can then be queried using the `ExectueQuery` function.
+As creating derived events is tied to the metrics subsystem, the `ComputeMetrics` function in the trace processor API should be called with the appropriate metrics. This will create the `<metric_name>_annotations` table/view which can then be queried using the `ExectueQuery` function.
 
 NOTE: At some point, there are plans to add an API which does not create the metrics proto but just executes the queries in the metric.
 
diff --git a/docs/contributing/sdk-releasing.md b/docs/contributing/sdk-releasing.md
index baccd05..d2e46d1 100644
--- a/docs/contributing/sdk-releasing.md
+++ b/docs/contributing/sdk-releasing.md
@@ -2,43 +2,42 @@
 
 This guide shows how to make a new Perfetto SDK release.
 
-Before snapshotting a release, check that no [release-blockers](http://b/savedsearches/5776355) are
-open.
-
-Check out the code:
+First, check out the code:
 
 ```bash
 git clone https://android.googlesource.com/platform/external/perfetto
 cd perfetto
 ```
 
-Next, decide the version number for the new release (vX.Y).
-The major version number (X) is incremented on every release (monthly).
-The minor version number is incremented only for minor changes / fixes on top of the monthly
-release (cherry-picks on the releases/vN.x branch). 
+Next, decide the version number for the new release (vX.Y). In general minor
+updates should increment the minor version number (Y) while larger, more
+significant behavioral changes should be reflected in the major version
+number (X).
 
 Continue with the appropriate section below.
 
 ## a) Creating a new major version
 
-Create a release branch for the new major version ("v16.x" here):
+Create a release branch for the new major version ("5.x" here) and merge in
+the code for the new release:
 
 ```bash
 git fetch origin
-git push origin origin/master:refs/heads/releases/v16.x
+git push origin origin/master:refs/heads/releases/v5.x
 git fetch origin
-git checkout -b releases/v16.x -t origin/releases/v16.x
+git checkout -b releases/v5.x -t origin/master
+git merge <sha1>
 ```
 
 Continue with [building the release](#building-and-tagging-the-release).
 
 ## b) Bumping the minor version
 
-Check out the existing release branch ("5.x" here) and merge in the desired
+Check out the existing release branch ("4.x" here) and merge in the desired
 revision for the new release, resolving any conflicts you may encounter.
 
 ```bash
-git checkout -b releases/v16.x -t origin/releases/v16.x
+git checkout -b releases/v4.x -t origin/releases/v4.x
 ```
 
 If you only want to introduce one or two patches in the new release, consider
@@ -92,13 +91,6 @@
    it ("vX.Y" being the new version).
 
 ```bash
-# This brings the branch up to date with the CL landed in the step above.
-git pull
-
-git status
-# Should print: Your branch is up to date with 'origin/releases/v16.x'.
-# Do NOT proceed if your branch has diverged from origin/releases/vX.X
-
 git tag -a -m "Perfetto vX.Y" vX.Y
 git push origin vX.Y
 ```
@@ -108,6 +100,4 @@
    - [docs/instrumentation/tracing-sdk.md](/docs/instrumentation/tracing-sdk.md)
    - [examples/sdk/README.md](/examples/sdk/README.md)
 
-6. Send an email with the CHANGELOG to perfetto-dev@ (internal) and perfetto-dev@googlegroups.com.
-
 Phew, you're done!
diff --git a/docs/contributing/testing.md b/docs/contributing/testing.md
index 98f0812..8baca32 100644
--- a/docs/contributing/testing.md
+++ b/docs/contributing/testing.md
@@ -93,37 +93,6 @@
 This is how standalone builds are tested. This is the only supported way to
 run integration tests on Linux and MacOS.
 
-Trace Processor diff tests
------------------
-Trace processor is mainly tested using so called "diff tests".
-
-For these tests, trace processor parses a known trace and executes a query
-file. The output of these queries is then compared (i.e. "diff"ed) against
-an expected output file and discrepencies are highlighted.
-
-Similar diff tests are also available when writing metrics - instead of a
-query file, the metric name is used and the expected output file contains
-the expected result of computing the metric.
-
-These tests (for both queries and metrics) can be run as follows:
-```bash
-tools/ninja -C <out directory>
-tools/diff_test_trace_processor.py <out directory>/trace_processor_shell
-```
-
-To add a new diff test (for query tests only), the `tools/add_tp_diff_test.py`
-script is useful. It will automatically create the query and expected output
-files and adds them both to the index. For metrics, this has to be done
-manually for now.
-
-TIP: Query diff tests are expected to only have a single query which produces
-output in the whole file (usually at the end). Calling
-`SELECT RUN_METRIC('metric file')` can trip up this check as this query
-generates some hidden output. To address this issue, if a query only has
-column is named `supress_query_output`, even if it has output, this will
-be ignored (for example,
-`SELECT RUN_METRIC('metric file') as surpress_query_output`)
-
 Android CTS tests
 -----------------
 CTS tests ensure that any vendors who modify Android remain compliant with the
diff --git a/docs/data-sources/atrace.md b/docs/data-sources/atrace.md
index 51e50f1..0df13c7 100644
--- a/docs/data-sources/atrace.md
+++ b/docs/data-sources/atrace.md
@@ -98,25 +98,19 @@
 ## TraceConfig
 
 ```protobuf
-buffers {
-  size_kb: 102400
-  fill_policy: RING_BUFFER
-}
-
 data_sources {
   config {
     name: "linux.ftrace"
     ftrace_config {
-      # Enables specific system events tags.
+      // Enables specific system events tags.
       atrace_categories: "am"
       atrace_categories: "pm"
 
-      # Enables events for a specific app.
+      // Enables events for a specific app.
       atrace_apps: "com.google.android.apps.docs"
 
-      # Enables all events for all apps.
+      // Enables all events for all apps.
       atrace_apps: "*"
     }
   }
-}
 ```
diff --git a/docs/data-sources/frametimeline.md b/docs/data-sources/frametimeline.md
deleted file mode 100644
index 6b711bf..0000000
--- a/docs/data-sources/frametimeline.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# Android Jank detection with FrameTimeline
-
-NOTE: **FrameTimeline requires Android 12(S) or higher**
-
-A frame is said to be janky if the time the frame was presented on screen does
-not match the predicted present time given by the scheduler.
-
-A jank can cause:
-* Unstable frame rate
-* Increased latency
-
-FrameTimeline is a module within SurfaceFlinger that detects janks and reports
-the source of the jank.
-[SurfaceViews](https://developer.android.com/reference/android/view/SurfaceView)
-are currently **not supported**, but will be, in future.
-
-## UI
-
-Two new tracks are added for every application that had at least one frame on
-screen.
-
-![](/docs/images/frametimeline/timeline_tracks.png)
-
-* Expected Timeline
-Each slice represents the time given to the app for rendering the
-frame. To avoid janks in the system, the app is expected to finish within this
-time frame.
-
-* Actual Timeline
-These slices represent the actual time an app took to complete the frame
-(including GPU work) and send it to SurfaceFlinger for composition. **Note: The
-actual frame start of apps is not yet known to FrameTimeline. Expected start
-time is used instead**. The end time of the slices here represent `max(gpu time,
-post time)`. **Post time** is the time the app's frame was posted to
-SurfaceFlinger.
-
-![](/docs/images/frametimeline/app-timelines.png)
-
-Similarly, SurfaceFlinger also gets these two new tracks representing the
-expected time it's supposed to finish within, and the actual time it took to
-finish compositing frames and presenting on-screen. Here, SurfaceFlinger's work
-represents everything underneath it in the display stack. This includes the
-Composer and the DisplayHAL. So, the slices represent SurfaceFlinger main
-thread's start to on-screen update.
-
-The names of the slices represent the token received from
-[choreographer](https://developer.android.com/reference/android/view/Choreographer).
-You can compare a slice in the actual timeline track to its corresponding slice
-in the expected timeline track to see how the app performed compared to the
-expectations. In addition, for debugging purposes, the token is added to the
-app's **doFrame** and **RenderThread** slices. For SurfaceFlinger, the same
-token is shown in **onMessageReceived**.
-
-![](/docs/images/frametimeline/app-vsyncid.png)
-
-![](/docs/images/frametimeline/sf-vsyncid.png)
-
-### Selecting an actual timeline slice
-
-![](/docs/images/frametimeline/selection.png)
-
-The selection details provide more information on what happened with the frame.
-These include:
-
-* **Present Type**
-
-Was the frame early, on time or late.
-* **On time finish**
-
-Did the application finish its work for the frame on time?
-* **Jank Type**
-
-Was there a jank observed with this frame? If yes, this shows what type of jank
-was observed. If not, the type would be **None**.
-* **Prediction type**
-
-Did the prediction expire by the time this frame was received by FrameTimeline?
-If yes, this will say **Expired Prediction**. If not, **Valid Prediction**.
-* **GPU Composition**
-
-Boolean that tells if the frame was composited by the GPU or not.
-* **Layer Name**
-
-Name of the Layer/Surface to which the frame was presented. Some processes
-update frames to multiple surfaces. Here, multiple slices with the same token
-will be shown in the Actual Timeline. Layer Name can be a good way to
-disambiguate between these slices.
-* **Is Buffer?**
-
-Boolean that tells if the frame corresponds to a buffer or an animation.
-
-### Flow events
-
-Selecting an actual timeline slice in the app also draws a line back to the
-corresponding SurfaceFlinger timeline slice.
-
-![](/docs/images/frametimeline/select-app-slice.png)
-
-Since SurfaceFlinger can composite frames from multiple layers into a single
-frame-on-screen (called a **DisplayFrame**), selecting a DisplayFrame draws
-arrows to all the frames that were composited together. This can span over
-multiple processes.
-
-![](/docs/images/frametimeline/select-sf-slice-1.png)
-![](/docs/images/frametimeline/select-sf-slice-2.png)
-
-### Color codes
-
-| Color | Image | Description    |
-| :---      | :---: | :---           |
-| Green | ![](/docs/images/frametimeline/green.png) | A good frame. No janks observed |
-| Light Green | ![](/docs/images/frametimeline/light-green.png) | High latency state. The framerate is smooth but frames are presented late, resulting in an increased input latency.|
-| Red | ![](/docs/images/frametimeline/red.png) | Janky frame. The process the slice belongs to, is the reason for the jank. |
-| Yellow | ![](/docs/images/frametimeline/yellow.png) | Used only by the apps. The frame is janky but app wasn't the reason, SurfaceFlinger caused the jank. |
-| Blue | ![](/docs/images/frametimeline/blue.png) | Dropped frame. Not related to jank. The frame was dropped by SurfaceFlinger, preferring an updated frame over this. |
-
-## Janks explained
-
-The jank types are defined in
-[JankInfo.h](http://cs/android/frameworks/native/libs/gui/include/gui/JankInfo.h?l=22).
-Since each app is written differently, there is no common way to go into the
-internals of the apps and specify what the reason for the jank was. Our goal is
-not to do this but rather, provide a quick way to tell if app was janky or if
-SurfaceFlinger was janky.
-
-### None
-
-All good. No jank with the frame. The ideal state that should be aimed for.
-
-### App janks
-
-* **AppDeadlineMissed**
-
-The app ran longer than expected causing a jank. The total time taken by the app
-frame is calculated by using the choreographer wake-up as the start time and
-max(gpu, post time) as the end time. Post time is the time the frame was sent to
-SurfaceFlinger. Since the GPU usually runs in parallel, it could be that the gpu
-finished later than the post time.
-
-* **BufferStuffing**
-
-This is more of a state than a jank. This happens if the app keeps sending new
-frames to SurfaceFlinger before the previous frame was even presented. The
-internal Buffer Queue is stuffed with buffers that are yet to be presented,
-hence the name, Buffer Stuffing. These extra buffers in the queue are presented
-only one after the other thus resulting in extra latency.
-This can also result in a stage where there are no more buffers for the app to
-use and it goes into a dequeue blocking wait.
-The actual duration of work performed by the app might still be within the
-deadline, but due to the stuffed nature, all the frames will be presented at
-least one vsync late no matter how quickly the app finishes its work.
-Frames will still be smooth in this state but there is an increased input
-latency associated with the late present.
-
-### SurfaceFlinger Janks
-
-There are two ways SurfaceFlinger can composite frames.
-* Device Composition - uses a dedicated hardware
-* GPU/Client composition - uses GPU to composite
-
-An important thing to note is that performing device composition happens as a
-blocking call on the main thread. However, GPU composition happens in parallel.
-SurfaceFlinger performs the necessary draw calls and then hands over the gpu
-fence to the display device. The display device then waits for the fence to be
-signaled, and then presents the frame.
-
-* **SurfaceFlingerCpuDeadlineMissed**
-
-SurfaceFlinger is expected to finish within the given deadline. If the main
-thread ran for longer than that, the jank is then
-SurfaceFlingerCpuDeadlineMissed. SurfaceFlinger’s CPU time is the time spent on
-the main thread. This includes the entire composition time if device composition
-was used. If GPU composition was used, this includes the time to write the draw
-calls and handing over the frame to the GPU.
-
-* **SurfaceFlingerGpuDeadlineMissed**
-
-The time taken by SurfaceFlinger’s main thread on the CPU + the GPU composition
-time together were longer than expected. Here, the CPU time would have still
-been within the deadline but since the work on the GPU wasn’t ready on time, the
-frame got pushed to the next vsync.
-
-* **DisplayHAL**
-
-DisplayHAL jank refers to the case where SurfaceFlinger finished its work and
-sent the frame down to the HAL on time, but the frame wasn’t presented on the
-vsync. It was presented on the next vsync. It could be that SurfaceFlinger did
-not give enough time for the HAL’s work or it could be that there was a genuine
-delay in the HAL’s work.
-
-* **PredictionError**
-
-SurfaceFlinger’s scheduler plans ahead the time to present the frames. However,
-this prediction sometimes drifts away from the actual hardware vsync time. For
-example, a frame might have predicted present time as 20ms. Due to a drift in
-estimation, the actual present time of the frame could be 23ms. This is called a
-Prediction Error in SurfaceFlinger’s scheduler. The scheduler corrects itself
-periodically, so this drift isn’t permanent. However, the frames that had a
-drift in prediction will still be classified as jank for tracking purposes.
-
-Isolated prediction errors are not usually perceived by the user as the
-scheduler is quick to adapt and fix the drift.
-
-### Unknown jank
-
-As the name suggests, the reason for the jank is unknown in this case. An
-example here would be that SurfaceFlinger or the App took longer than expected
-and missed the deadline but the frame was still presented early. The probability
-of such a jank happening is very low but not impossible.
-
-## SQL
-
-At the SQL level, frametimeline data is available in two tables
-* [`expected_frame_timeline_slice`](/docs/analysis/sql-tables.autogen#expected_frame_timeline_slice)
-* [`actual_frame_timeline_slice`](/docs/analysis/sql-tables.autogen#actual_frame_timeline_slice)
-
-```
-select ts, dur, surface_frame_token as app_token, display_frame_token as sf_token, process.name
-from expected_frame_timeline_slice left join process using(upid)
-```
-
-ts | dur | app_token | sf_token | name
----|-----|-----------|----------|-----
-60230453475 | 20500000 | 3135 | 3142 | com.google.android.apps.nexuslauncher
-60241677540 | 20500000 | 3137 | 3144 | com.google.android.apps.nexuslauncher
-60252895412 | 20500000 | 3139 | 3146 | com.google.android.apps.nexuslauncher
-60284614241 | 10500000 | 0 | 3144 | /system/bin/surfaceflinger
-60295858299 | 10500000 | 0 | 3146 | /system/bin/surfaceflinger
-60297798913 | 20500000 | 3147 | 3150 | com.android.systemui
-60307075728 | 10500000 | 0 | 3148 | /system/bin/surfaceflinger
-60318297746 | 10500000 | 0 | 3150 | /system/bin/surfaceflinger
-60320236468 | 20500000 | 3151 | 3154 | com.android.systemui
-60329511401 | 10500000 | 0 | 3152 | /system/bin/surfaceflinger
-60340732956 | 10500000 | 0 | 3154 | /system/bin/surfaceflinger
-60342673064 | 20500000 | 3155 | 3158 | com.android.systemui
-
-
-```
-select ts, dur, surface_frame_token as app_token, display_frame_token, jank_type, on_time_finish, present_type, layer_name, process.name
-from actual_frame_timeline_slice left join process using(upid)
-```
-
-ts | dur | app_token | sf_token | jank_type | on_time_finish | present_type | layer_name | name
----|-----|-----------|----------|-----------|----------------|--------------|------------|-----
-60230453475 | 26526379 | 3135 | 3142 | Buffer Stuffing | 1 | Late Present | TX - com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0 | com.google.android.apps.nexuslauncher
-60241677540 | 28235805 | 3137 | 3144 | Buffer Stuffing | 1 | Late Present | TX - com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0 | com.google.android.apps.nexuslauncher
-60252895412 | 2546525 | 3139 | 3142 | None | 1 | On-time Present | TX - NavigationBar0#0 | com.android.systemui
-60252895412 | 27945382 | 3139 | 3146 | Buffer Stuffing | 1 | Late Present | TX - com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0 | com.google.android.apps.nexuslauncher
-60284808190 | 10318230 | 0 | 3144 | None | 1 | On-time Present | [NULL] | /system/bin/surfaceflinger
-60296067722 | 10265574 | 0 | 3146 | None | 1 | On-time Present | [NULL] | /system/bin/surfaceflinger
-60297798913 | 5239227 | 3147 | 3150 | None | 1 | On-time Present | TX - NavigationBar0#0 | com.android.systemui
-60307246161 | 10301772 | 0 | 3148 | None | 1 | On-time Present | [NULL] | /system/bin/surfaceflinger
-60318497204 | 10281199 | 0 | 3150 | None | 1 | On-time Present | [NULL] | /system/bin/surfaceflinger
-60320236468 | 2747559 | 3151 | 3154 | None | 1 | On-time Present | TX - NavigationBar0#0 | com.android.systemui
-
-## TraceConfig
-
-Trace Protos:
-[FrameTimelineEvent](/docs/reference/trace-packet-proto.autogen#FrameTimelineEvent)
-
-Datasource:
-
-```protobuf
-data_sources {
-    config {
-        name: "android.surfaceflinger.frametimeline"
-    }
-}
-```
-
diff --git a/docs/data-sources/java-heap-profiler.md b/docs/data-sources/java-heap-profiler.md
index f03977e..5168d7d 100644
--- a/docs/data-sources/java-heap-profiler.md
+++ b/docs/data-sources/java-heap-profiler.md
@@ -53,18 +53,6 @@
 Note that this is **experimental** and the **API is subject to change**.
 From this we can see how much memory is being held by each type of object
 
-For that, we need to find the timestamp and upid of the graph.
-
-```sql
-select distinct graph_sample_ts, upid from heap_graph_object
-```
-
-graph_sample_ts     |        upid        |
---------------------|--------------------|
-     56785646801    |         1          |
-
-We can then use them to get the flamegraph data.
-
 ```sql
 select name, cumulative_size
        from experimental_flamegraph(56785646801, 1, 'graph')
diff --git a/docs/data-sources/native-heap-profiler.md b/docs/data-sources/native-heap-profiler.md
index cff52e2..02ec07c 100644
--- a/docs/data-sources/native-heap-profiler.md
+++ b/docs/data-sources/native-heap-profiler.md
@@ -56,7 +56,7 @@
 
 #### Using the tools/heap_profile script (recommended)
 
-You can use the `tools/heap_profile` script. If you are having trouble
+On Linux / MacOS, use the `tools/heap_profile` script. If you are having trouble
 make sure you are using the
 [latest version](
 https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile).
@@ -142,13 +142,9 @@
 ## Runtime profiling
 
 When a profiling session is started, all matching processes (by name or PID)
-are enumerated and are signalled to request profiling. Profiling isn't actually
-enabled until a few hundred milliseconds after the next allocation that is
-done by the application. If the application is idle when profiling is
-requested, and then does a burst of allocations, these may be missed.
-
-The resulting profile will contain all allocations done between when profiling
-is enabled, and the end of the profiling session.
+are enumerated and profiling is enabled. The resulting profile will contain
+all allocations done between the beginning and the end of the profiling
+session.
 
 The resulting [ProfilePacket] will have `from_startup` set to false in the
 corresponding `ProcessHeapSamples` message. This does not get surfaced in the
@@ -183,8 +179,8 @@
 Profiling requests for non-profileable/debuggable processes will result in an
 empty profile.
 
-On userdebug builds, all processes except for a small set of critical
-services can be profiled (to find the set of disallowed targets, look for
+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://cs.android.com/android/platform/superproject/+/master:system/sepolicy/private/heapprofd.te?q=never_profile_heap).
 This restriction can be lifted by disabling SELinux by running
@@ -237,7 +233,7 @@
 
 ## Symbolization
 
-NOTE: Symbolization is currently only available on Linux and MacOS.
+NOTE: Symbolization is currently only available on Linux
 
 ### Set up llvm-symbolizer
 
@@ -294,31 +290,6 @@
 4. $PERFETTO_BINARY_PATH/foo.so
 5. $PERFETTO_BINARY_PATH/.build-id/ab/cd1234.debug
 
-Alternatively, you can set the `PERFETTO_SYMBOLIZER_MODE` environment variable
-to `index`, and the symbolizer will recursively search the given directory for
-an ELF file with the given build id. This way, you will not have to worry
-about correct filenames.
-
-## Deobfuscation
-
-If your profile contains obfuscated Java methods (like `fsd.a`), you can
-provide a deobfuscation map to turn them back into human readable.
-To do so, use the `PERFETTO_PROGUARD_MAP` environment variable, using the
-format `packagename=filename[:packagename=filename...]`, e.g.
-`PERFETTO_PROGUARD_MAP=com.example.pkg1=foo.txt:com.example.pkg2=bar.txt`.
-All tools
-(traceconv, trace_processor_shell, the heap_profile script) support specifying
-the `PERFETTO_PROGUARD_MAP` as an environment variable.
-
-You can get a deobfuscation map for your trace using
-`tools/traceconv deobfuscate`. Then concatenate the resulting file to your
-trace to get a deobfuscated version of it.
-
-```
-PERFETTO_PROGUARD_MAP=com.example.pkg tools/traceconv deobfuscate ${TRACE} > deobfuscation_map
-cat ${TRACE} deobfuscation_map > deobfuscated_trace
-```
-
 ## Troubleshooting
 
 ### Buffer overrun
@@ -333,7 +304,7 @@
 ### Profile is empty
 
 Check whether your target process is eligible to be profiled by consulting
-[Target processes](#heapprofd-targets) above.
+[Target processes](#target-processes) above.
 
 Also check the [Known Issues](#known-issues).
 
@@ -387,81 +358,19 @@
 If this does not show one or more of the sections, change your build system
 to not strip them.
 
-## (non-Android) Linux support
-
-NOTE: Do not use this for production purposes.
-
-You can use a standalone library to profile memory allocations on Linux.
-First [build Perfetto](/docs/contributing/build-instructions.md). You only need
-to do this once.
-
-```
-tools/build_all_configs.py
-ninja -C out/linux_clang_release
-```
-
-Then, run traced
-
-```
-out/linux_clang_release/traced
-```
-
-Start the profile (e.g. targeting trace_processor_shell)
-
-```
-tools/heap_profile -n trace_processor_shell --print-config  | \
-out/linux_clang_release/perfetto \
-  -c - --txt \
-  -o ~/heapprofd-trace
-```
-
-Finally, run your target (e.g. trace_processor_shell) with LD_PRELOAD
-
-```
-LD_PRELOAD=out/linux_clang_release/libheapprofd_glibc_preload.so out/linux_clang_release/trace_processor_shell <trace>
-```
-
-Then, Ctrl-C the Perfetto invocation and upload ~/heapprofd-trace to the
-[Perfetto UI](https://ui.perfetto.dev).
-
 ## Known Issues
 
-### {#known-issues-android11} Android 11
+### Android 10
 
-* 32-bit programs cannot be targeted on 64-bit devices.
-* Setting `sampling_interval_bytes` to 0 crashes the target process.
-  This is an invalid config that should be rejected instead.
-* For startup profiles, some frame names might be missing. This will be
-  resolved in Android 12.
-* `Failed to send control socket byte.` is displayed in logcat at the end of
-  every profile. This is benign.
-* The object count may be incorrect in `dump_at_max` profiles.
-
-### {#known-issues-android10} Android 10
-* Function names in libraries with load bias might be incorrect. Use
-  [offline symbolization](#symbolization) to resolve this issue.
-* For startup profiles, some frame names might be missing. This will be
-  resolved in Android 12.
-* 32-bit programs cannot be targeted on 64-bit devices.
-* x86 / x86_64 platforms are not supported. This includes the Android
-_Cuttlefish_.
-  emulator.
 * On ARM32, the bottom-most frame is always `ERROR 2`. This is harmless and
   the callstacks are still complete.
+* x86 platforms are not supported. This includes 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.
-* Using `vfork(2)` or `clone(2)` with `CLONE_VM` and allocating / freeing
-  memory in the child process will prematurely end the profile.
-  `java.lang.Runtime.exec` does this, calling it will prematurely end
-  the profile. Note that this is in violation of the POSIX standard.
-* Setting `sampling_interval_bytes` to 0 crashes the target process.
-  This is an invalid config that should be rejected instead.
-* `Failed to send control socket byte.` is displayed in logcat at the end of
-  every profile. This is benign.
-* The object count may be incorrect in `dump_at_max` profiles.
 
 ## Heapprofd vs malloc_info() vs RSS
 
diff --git a/docs/data-sources/system-log.md b/docs/data-sources/system-log.md
index 9c713d9..73d30c9 100644
--- a/docs/data-sources/system-log.md
+++ b/docs/data-sources/system-log.md
@@ -35,6 +35,20 @@
 }
 ```
 
+A wildcard can be used to collect all events in a category:
+
+```protobuf
+data_sources {
+  config {
+    name: "linux.ftrace"
+    ftrace_config {
+      ftrace_events: "ftrace/print"
+      ftrace_events: "sched/*"
+    }
+  }
+}
+```
+
 The full configuration options for ftrace can be seen in [ftrace_config.proto](/protos/perfetto/config/ftrace/ftrace_config.proto).
 
 ## Android system logs
diff --git a/docs/design-docs/extensions.md b/docs/design-docs/extensions.md
deleted file mode 100644
index be8a466..0000000
--- a/docs/design-docs/extensions.md
+++ /dev/null
@@ -1,67 +0,0 @@
-Extensions: adding new types to traces
-======================================
-
-NOTE: **extensions are work-in-progress and are not ready to be used at the
-moment**
-
-Currently, it is not possible to add new types to traces while using Perfetto
-without modifying Perfetto proto message definitions upstream.
-
-This page describes ongoing work to use [protobuf
-extensions](https://developers.google.com/protocol-buffers/docs/overview#extensions)
-in order to make it possible to define new typed messages outside of the
-Perfetto repository.
-
-Protozero support
------------------
-
-Perfetto uses its own implementation of code generation for protocol buffer
-messages called [Protozero](/docs/design-docs/protozero.md), which is not a
-full-fledged protobuf implementation. Implementation of extensions is fairly
-limited, and all extensions are supposed to be nested inside a message that is
-used in order to provide the class name for generated code.
-
-For example,
-
-    message MyEvent {
-        extend TrackEvent {
-            optional string custom_string = 1000;
-        }
-    }
-
-Is going to generate a subclass of `TrackEvent` called `MyEvent`, that is going
-to have a new method to set `custom_string` in addition to all other protobuf
-fields defined in `TrackEvent`.
-
-Deserialization
----------------
-
-When analyzing traces, protos are not used directly and instead are parsed into
-database, which can be queried by SQL. In order to make it possible, Perfetto
-has to know field descriptors (the binary representation of the extended proto
-schema) of the extensions. Currently, the only way to do that is to add an
-[ExtensionDescriptor
-packet](reference/trace-packet-proto.autogen#ExtensionDescriptor). In the
-future, there is going to be a way to specify protobuf extensions at compile
-time in order to be able to avoid this overhead in every single trace.
-
-However, an ability to specify extension descriptors in the trace itself will
-still be useful in order to be able to use a pre-compiled trace processor in the
-UI when adding new typed messages during local development.
-
-Deserialization of protobuf extension are supported only for TrackEvent message
-at the moment, and is implemented in trace processor via ProtoToArgsUtils class.
-The extensions will appear in args table, similar to other trace event
-arguments.
-
-Testing extensions support inside Perfetto
-------------------------------------------
-
-Perfetto trace processor is mostly tested by integration tests, where input
-traces are specified most frequently in textproto format. Textproto format
-supports extensions, but the parser has to be aware of all the extensions used.
-In order to make it possible, all the extensions that are used in integration
-tests have to be specified in the `test_extensions.proto` file. Since this file
-is only used in the testing harness and is parsed by protoc, it does not have to
-adhere to the convention of all extensions being inside a wrapper message, which
-helps with making extension identifiers more concise.
diff --git a/docs/design-docs/heapprofd-design.md b/docs/design-docs/heapprofd-design.md
index fe5a8ef..1f11bf4 100644
--- a/docs/design-docs/heapprofd-design.md
+++ b/docs/design-docs/heapprofd-design.md
@@ -109,7 +109,7 @@
 
 Remote unwinding also enables us to use _global caching_ (`Elf::SetCachingEnabled(true)`) in libunwindstack. This prevents debug information being used by different processes to be loaded and decompressed multiple times.
 
-We add an `FDMaps` objects to parse maps from `/proc/self/maps` sent by the target process. We keep `FDMaps` object cached per process that is being profiled. This both saves the overhead of text-parsing `/proc/[pid]/maps` as well as keeps various objects needed for unwinding (e.g. decompressed minidebuginfo). In case an unwind fails with `ERROR_INVALID_MAP` we reparse the maps object. We will  do changes to libunwindstack to create a more general version of [`LocalUpdatableMaps`](https://cs.android.com/android/platform/superproject/+/master:system/unwinding/libunwindstack/Maps.cpp?q=symbol:LocalUpdatableMaps) that is also applicable for remote processes.
+We add an `FDMaps` objects to parse maps from `/proc/self/maps` sent by the target process. We keep `FDMaps` object cached per process that is being profiled. This both saves the overhead of text-parsing `/proc/[pid]/maps` as well as keeps various objects needed for unwinding (e.g. decompressed minidebuginfo). In case an unwind fails with `ERROR_INVALID_MAP` we reparse the maps object. We will  do changes to libunwindstack to create a more general version of [`LocalUpdatableMaps`](https://cs.android.com/android/platform/superproject/+/master:system/core/libunwindstack/Maps.cpp?q=symbol:LocalUpdatableMaps) that is also applicable for remote processes.
 
 
 #### Advantages of remote unwinding
@@ -216,9 +216,9 @@
 ### Stack Unwinding
 Stack unwinding is the process of determining the chain of return addresses from the raw bytes of the stack. These are the addresses we want to attribute the allocated memory to.
 
-The most efficient way of stack unwinding is using frame pointers. This is unreliable on Android as we do not control build parameters for vendor libraries or OEM builds and due to issues on ARM32. Thus, our stack unwinding relies on libunwindstack which uses DWARF information from the library ELF files to determine return addresses. This can significantly slower, with unwinding of a stack taking between 100μs and ~100 ms ([data from simpleperf](https://gist.github.com/fmayer/a3a5a352196f9037f34241f8fb09004d)).
+The most efficient way of stack unwinding is using frame pointers. This is unreliable on Android as we do not control build parameters for vendor libraries or OEM builds and due to issues on ARM32. Thus, our stack unwinding relies on libunwindstack which uses DWARF information from the library ELF files to determine return addresses. This can significantly slower, with unwinding of a stack taking between 100μs and ~100 ms ([data from simpleperf](https://gist.github.com/segfaulthunter/a3a5a352196f9037f34241f8fb09004d)).
 
-[libunwindstack](https://cs.android.com/android/platform/superproject/+/master:system/unwinding/libunwindstack/) is Android's replacement for [libunwind](https://www.nongnu.org/libunwind/). It has a modern C++ object-oriented API surface and support for Android specific features allowing it to unwind mixed native and Java applications using information emitted by ART depending on execution mode. It also supports symbolization for native code and all three execution modes or ART.
+[libunwindstack](https://cs.android.com/android/platform/superproject/+/master:system/core/libunwindstack/) is Android's replacement for [libunwind](https://www.nongnu.org/libunwind/). It has a modern C++ object-oriented API surface and support for Android specific features allowing it to unwind mixed native and Java applications using information emitted by ART depending on execution mode. It also supports symbolization for native code and all three execution modes or ART.
 
 ### Symbolization
 Symbolization is the process of determining function name and line number from a code address. For builds by Google, we can get symbolized binaries (i.e. binaries with an ELF section that can be used for symbolization) from go/ab or https://ci.android.com (e.g. https://ci.android.com/builds/submitted/6410994/aosp_cf_x86_phone-userdebug/latest/aosp_cf_x86_phone-symbols-6410994.zip).
diff --git a/docs/design-docs/heapprofd-sampling.md b/docs/design-docs/heapprofd-sampling.md
deleted file mode 100644
index 3ebfb3d..0000000
--- a/docs/design-docs/heapprofd-sampling.md
+++ /dev/null
@@ -1,179 +0,0 @@
-# heapprofd: Sampling for Memory Profiles
-
-_tomlewin, fmayer **·** 2021-04-14_  
-
-## Background
-
-A heap profiler associates memory allocations with the callstacks on which they
-happen ([example visualization]). It is prohibitively expensive to handle every
-allocation done by a program, so the [Android Heap Profiler] employs a sampling
-approach that handles a statistically meaningful subset of allocations. This
-document explores the statistical properties thereof.
-
-## Conceptual motivation
-Conceptually the sampling is implemented such that each byte has some
-probability p of being sampled. In theory we can think of each byte undergoing a
-Bernoulli trial. The reason we use a random sampling approach, as opposed to
-taking every nth byte, is that there may be regular allocation patterns in the
-code that may be missed by a correspondingly regular sampling.
-
-To scale the sampled bytes to the correct scale, we multiply by 1 / p, i.e. if
-we sample a byte with probability 10%, then each byte sampled represents 10
-bytes allocated.
-
-
-## Implementation
-
-In practice, the [algorithm] works as follows:
-
-1. We look at an allocation
-
-2. If the size of the allocation is large enough that there’s a greater than 99%
-   chance of it being sampled at least once, we return the size of the
-   allocation directly. This is a performance optimization.
-
-3. If the size of the allocation is smaller, then we compute the number of times
-   we would draw a sample if we sampled each byte with the given sampling rate:
-
-  * In practice we do this by keeping track of the arrival time of the next
-    sample. When an allocation happens, we subtract its size from the arrival
-    time of the next sample, and check whether we have brought it below zero. We
-    then repeatedly draw from the exponential distribution (which is the
-    interarrival time of Poisson) until the arrival time is brought back
-    above 0. The amount of times we had to draw from the exponential
-    distribution is the number of samples the allocation should count as.
-
-  * We multiply the number of samples we drew within the allocation by the
-    sampling rate to get an estimate of the size of the allocation
-
-We instead draw directly from the Poisson/binomial distribution to see how many
-samples we get for a given allocation size, but this is not as computationally
-efficient. This is because we don’t sample most of the allocations, due to their
-small size and our low sampling rate. This means it’s more efficient to use the
-exponential draw approach, as for a non-sample, we only need to decrement a
-counter. Sampling from the Poisson for every allocation (rather than drawing
-from exponential for every sample) is more expensive.
-
-## Theoretical performance
-
-If we sample at some rate 1 / p, then to set p reasonably we need to know what
-our probability of sampling an allocation of any size is, as well as our
-expected error when we sample it. If we set p = 1 then we sample everything and
-have no error. Reducing the sampling rate costs us coverage and accuracy.
-
-### Sampling probabilities
-
-We will sample an allocation with probability Exponential(sampling rate) <
-allocation size. This is equivalent to the probability that we do not fail to
-sample all bytes within the allocation if we sample bytes at our sampling rate.
-
-Because the exponential distribution is memoryless, we can add together
-allocations that are the same even if they occur apart for the purposes of
-probability. This means that if we have an allocation of 1MB and then another of
-1MB, the probability of us taking at least one sample is the same as the
-probability of us taking at least one sample of a contiguous 2MB allocation.
-
-We can see from the chart below that if we 16X our sampling rate from 32KiB to
-512KiB we still have a 95% chance of sampling anything above 1.5MiB. If we 64X
-it to 2048KiB we still have an 80% chance to sample anything above 3.5MiB.
-
-![](/docs/images/heapprofd-sampling/one-sample.png)
-
-### Expected errors
-We can also consider the expected error we’ll make at given allocation sizes and
-sampling rates. Like before it doesn’t matter where the allocation happens — if
-we have two allocations of the same type occurring at different times they have
-the same statistical properties as a single allocation with size equal to their
-sum. This is because the exponential distribution we use is memoryless.
-
-
-For expected error we report something like the [mean absolute percentage
-error]. This just means we see how wrong we might be in percent relative to the
-true allocation size, and then scale these results according to their
-probability of occurrence. This is an estimator that has some issues (i.e. it’s
-biased such that underestimates are more penalised) but it’s easy to reason
-about and it’s useful as a gauge of how wrong on average we might be with our
-estimates. I would recommend just reading this as analogous to a standard
-deviation.
-
-
-Charts below show both the expected error and the conditional expected error:
-the expected error assuming we have at least one sample within the allocation.
-There’s periodicity in both in line with the sampling rate used. The thing to
-take away is that, while the estimates are unbiased such that their expected
-value is equal to their real value, substantial errors are still possible.
-
-![](/docs/images/heapprofd-sampling/expected-error.png)
-
-Assuming that we take at least one sample of an allocation, what error might we
-expect? We can answer that using the following chart, which shows expected error
-conditional on at least one sample being taken. This is the expected error we
-can expect for the things that end up in our heap profile. It’s important to
-emphasise that this expected error methodology is not exact, and also that the
-underlying sampling remains unbiased — the expected value is the true value.
-This should be considered more as a measure akin to standard deviation.
-
-![](/docs/images/heapprofd-sampling/conditional-expected-error.png)
-
-## Performance Considerations
-### STL Distributions
-
-Benchmarking of the STL distributions on a Pixel 4 reinforces our approach of
-estimating the geometric distribution using an exponential distribution, as its
-performance is ~8x better ([full results]).
-
-
-Draw sample from exponential distribution with p = 1 / 32000:
-
-ARM64: 21.3ns (sd 0.066ns, negligibly small, smaller than a CPU cycle)
-
-ARM32: 33.2ns (sd 0.011ns, negligibly small, smaller than a CPU cycle)
-
-
-Draw sample from geometric distribution with p = 1 / 32000:
-
-ARM64: 169ns (sd 0.023ns, negligibly small, smaller than a CPU cycle) (7.93x)
-
-ARM32: 222ns (sd 0.118ns, negligibly small, smaller than a CPU cycle) (6.69x)
-
-## Appendix
-
-### Improvements made
-
-We previously (before Android 12) returned the size of the allocation accurately
-and immediately if the allocation size was greater than our sampling rate. This
-had several impacts.
-
-
-The most obvious impact is that with the old approach we would expect to sample
-an allocation equal in size to our sampling rate ~63% of the time, rather than
-100%. This means there is a discontinuity in coverage between an allocation a
-byte smaller than our sampling rate, and one a byte larger. This is still
-unbiased from a statistical perspective, but it’s important to note.
-
-
-Another unusual impact is that the sampling rate depends not only on the size of
-the memory being used, but also how it’s allocated. If our sampling rate were
-10KB, and we have an allocation that’s 10KB, we sample it with certainty. If
-instead that 10KB is split among two 5KB allocations, we sample it with
-probability 63%. Again this doesn’t bias our results, but it means that our
-measurements of memory where there are many small allocations might be noisier
-than ones where there are a few large allocations, even if total memory used is
-the same. If we didn’t return allocations greater than the sampling rate every
-time, then the memorylessness property of the exponential distribution would
-mean our method is insensitive to how the memory is split amongst allocations,
-which seems a desirable property.
-
-
-We altered the cutoff at which we simply returned the allocation size.
-Previously, as discussed, the cutoff was at the sampling rate, which led to a
-discontinuity. Now the cutoff is determined by the size at which we have a >99%
-chance of sampling an allocation at least once, given the sampling rate we’re
-using. This resolves the above issues.
-
-[algorithm]:
-  https://cs.android.com/android/platform/superproject/+/master:external/perfetto/src/profiling/memory/sampler.h
-[example visualization]: /docs/images/syssrv-apk-assets-two.png
-[Android Heap Profiler]: /docs/design-docs/heapprofd-design
-[mean absolute percentage error]: https://en.wikipedia.org/wiki/Mean_absolute_percentage_error
-[full results]: https://gist.github.com/fmayer/3aafcaf58f8db09714ba09aa4ac2b1ac
\ No newline at end of file
diff --git a/docs/design-docs/life-of-a-tracing-session.md b/docs/design-docs/life-of-a-tracing-session.md
index 79bdeb6..66690ec 100644
--- a/docs/design-docs/life-of-a-tracing-session.md
+++ b/docs/design-docs/life-of-a-tracing-session.md
@@ -51,7 +51,7 @@
     buffer.
 18. The service will check if the given chunk, identified by the tuple
     `{ProducerID (unspoofable), WriterID, ChunkID}` is still present in the
-    trace buffer and if so will proceed to patch it (% checks).
+    trace buffer and if so will proceed to patch it (% sanity checks).
 19. The consumer sends a [`FlushRequest`](/protos/perfetto/ipc/consumer_port.proto#52)
     to the service, asking it commit all data on flight in the trace buffers.
 20. The service, in turn, issues a
diff --git a/docs/design-docs/protozero.md b/docs/design-docs/protozero.md
index fa87fe2..61db880 100644
--- a/docs/design-docs/protozero.md
+++ b/docs/design-docs/protozero.md
@@ -269,7 +269,7 @@
 every 4KB-32KB (depending on the trace configuration).
 
 The assumption is that the likeliness that two threads will cross the chunk
-boundary and call `GetNewBuffer()` at the same time is extremely low and hence
+boundary and call `GetNewBuffer()` at the same time is extremely slow and hence
 the critical section is un-contended most of the times.
 
 ```mermaid
@@ -397,7 +397,7 @@
   void Append(T x) {
     // The memcpy will be elided by the compiler, which will emit just a
     // 64-bit aligned mov instruction.
-    memcpy(reinterpret_cast<void*>(ptr_), &x, sizeof(x));
+    memcpy(reinterpret_cast<T*>(ptr_), &x, sizeof(x));
     ptr_ += sizeof(x);
   }
 
@@ -407,7 +407,7 @@
   void set_field_uint64(uint64_t x) { Append(x); }
   void set_field_string(const char* str) { ptr_ = strcpy(ptr_, str); }
 
-  alignas(uint64_t) char storage_[sizeof(g_fake_input_simple) + 8];
+  char storage_[sizeof(g_fake_input_simple)];
   char* ptr_ = &storage_[0];
 };
 ```
diff --git a/docs/images/counter-events.png b/docs/images/counter-events.png
deleted file mode 100644
index e7a00e5..0000000
--- a/docs/images/counter-events.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/debug-slices-random.png b/docs/images/debug-slices-random.png
deleted file mode 100644
index 88c0eca..0000000
--- a/docs/images/debug-slices-random.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/example_pd_graph.png b/docs/images/example_pd_graph.png
deleted file mode 100644
index e8d55c2..0000000
--- a/docs/images/example_pd_graph.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/app-timelines.png b/docs/images/frametimeline/app-timelines.png
deleted file mode 100644
index 73e5ee2..0000000
--- a/docs/images/frametimeline/app-timelines.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/app-vsyncid.png b/docs/images/frametimeline/app-vsyncid.png
deleted file mode 100644
index dbefd02..0000000
--- a/docs/images/frametimeline/app-vsyncid.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/blue.png b/docs/images/frametimeline/blue.png
deleted file mode 100644
index 4bbad6f..0000000
--- a/docs/images/frametimeline/blue.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/green.png b/docs/images/frametimeline/green.png
deleted file mode 100644
index 3735c6d..0000000
--- a/docs/images/frametimeline/green.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/light-green.png b/docs/images/frametimeline/light-green.png
deleted file mode 100644
index c04ea6e..0000000
--- a/docs/images/frametimeline/light-green.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/red.png b/docs/images/frametimeline/red.png
deleted file mode 100644
index 29df82e..0000000
--- a/docs/images/frametimeline/red.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/select-app-slice.png b/docs/images/frametimeline/select-app-slice.png
deleted file mode 100644
index 990616c..0000000
--- a/docs/images/frametimeline/select-app-slice.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/select-sf-slice-1.png b/docs/images/frametimeline/select-sf-slice-1.png
deleted file mode 100644
index b034a34..0000000
--- a/docs/images/frametimeline/select-sf-slice-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/select-sf-slice-2.png b/docs/images/frametimeline/select-sf-slice-2.png
deleted file mode 100644
index 1685e9d..0000000
--- a/docs/images/frametimeline/select-sf-slice-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/selection.png b/docs/images/frametimeline/selection.png
deleted file mode 100644
index abb3759..0000000
--- a/docs/images/frametimeline/selection.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/sf-vsyncid.png b/docs/images/frametimeline/sf-vsyncid.png
deleted file mode 100644
index 752324e..0000000
--- a/docs/images/frametimeline/sf-vsyncid.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/timeline_tracks.png b/docs/images/frametimeline/timeline_tracks.png
deleted file mode 100644
index 7f4f173..0000000
--- a/docs/images/frametimeline/timeline_tracks.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/frametimeline/yellow.png b/docs/images/frametimeline/yellow.png
deleted file mode 100644
index 56930fb..0000000
--- a/docs/images/frametimeline/yellow.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/heapprofd-sampling/conditional-expected-error.png b/docs/images/heapprofd-sampling/conditional-expected-error.png
deleted file mode 100644
index cf92006..0000000
--- a/docs/images/heapprofd-sampling/conditional-expected-error.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/heapprofd-sampling/expected-error.png b/docs/images/heapprofd-sampling/expected-error.png
deleted file mode 100644
index ea6a7ac..0000000
--- a/docs/images/heapprofd-sampling/expected-error.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/heapprofd-sampling/one-sample.png b/docs/images/heapprofd-sampling/one-sample.png
deleted file mode 100644
index d179ff1..0000000
--- a/docs/images/heapprofd-sampling/one-sample.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/perfetto-stack.svg b/docs/images/perfetto-stack.svg
index aa5b986..7b7fead 100644
--- a/docs/images/perfetto-stack.svg
+++ b/docs/images/perfetto-stack.svg
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1652px" height="776px" viewBox="-0.5 -0.5 1652 776" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2020-05-22T22:41:34.812Z&quot; agent=&quot;5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36&quot; etag=&quot;QckB1rB-GYIfxBJ2Ru_L&quot; version=&quot;13.1.3&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;7NN0wUOKmaAmGsXKK3Xs&quot; name=&quot;Page-1&quot;&gt;7VxZc6rM1v41qfrOhVYzOVwSh8QcMdnR7Aw3XyG0iAGaF3Agv/6sZlKxUYyanXdXUkkFVo+sflb3muBKaNmrG091pwrRsXXFI311JbSveJ4XahL8o5QwpnCCJMQUwzP1hLYmDM0PnDRNGhpzU8f+VsWAECsw3W2iRhwHa8EWTfU8styuNiHW9qiuauAdwlBTrV3qs6kH04Ta5NG64BabxjQdmkdJia2mtROCP1V1stwi4VXQJU6QzPGRjElArqTONAjo48lXfBd+J7RG1SDEsLDqmn5VIzaQNR+qdCeqbVqUuUlj6FboXAktj5AgvrJXLWzRVUn5HY/dLSjNHtjDTlCmweB9pXj/9R4+FMu/kxZLUp/fVsS4l4VqzRNGPmKNeDpdPk/VYEVjlgRhyuiJaVktYhEvuhUmjcl4IlwJ137gkXecljjEgfrXlCXd3JML16plGg4QNJg59mhbV9VMx+jjCX0SlDRMQCbU4H6BvcCE1ZaTpgFx1+1G9KbNozVlo5eNuQqNRkdoAX2XdQk36TB4tUFKWHmDiY0DL4QqaWkKn1RgUkFYrtHXTOtMN4BXT4lqgiYj63u9eHCRrN8Rayk0dhbziq9ZQcIIKlWwolFB7Z85hd21l4Axvd9a6pRIG1f8aDEA6Ujg3VVUdd2oZiT/o8FgDZyTOuo5FdV1EwjS1Uw6Bq7EfW+Pl4jempxD7HJqBnjoxs++hP0PKk0DG3jb5uisNgCdwPZyWOZ3UVnXxoJI6ZY6xta1qr0bHpk7em54tgScAcn1HJKzjXEDyQILybWLIVliADm3qJRHbvmnzw4edZz2gPZyRcpxRdplCsdiCncxpvCHmQK9wHlL0XIA86rvxofwxFxhPScEgElRUycSKpKEXbbvXcXDSPxzTBUOMxXUAZdemnakgmSC2Kfi+kB8MzAJFUjYEAI48AvlmB6W0U+hMO+sSjSknFJRSoFrXQ1U2EXjW9gWF7BJXq9gffnWw+2AfwuvxfHzaq59IFO9fURamyz6gi7ooSQoobTQbG2hzOSl0mp+6LZm9m7f3LcXvTUWjGZvJhtKSw4H0V/PeLMtf9wGNvJTV795grq6+3b7SB6GvdX97bXYM6/J27PlqLe/oG1H1G4N82G2Wr6+PJLeDdDe0bLXvibK7JGHv57SfV1ic93v2G7O34a9Ra7N6r4lI33WJf3R3fPgRln2hyI3GKL5oP0UKEO06o+6vftnJejPnrheWwaanJTJK2jXG1iv6PVDjsqhLRpEbTqB8qLk6nZ4qGdE9Wa/oK+OQenaRydI7qHNa6A8GyH0OwPezAejJ9o+qtdrd8nAViiN8m0VjyXT+fHwRxTndXWw/9/l5orfkQj1hWH7Dfq+o32H2EbL/uixN3Bgjjad411tPJKDQcfgf8/0tM4K5iaqLRTqJgrV9h2vOG6gtBAqomVtTbo2y4UmvDkPVLOKfkF1CNQE+U10iU0hLW1s61mNnX24JjLOJvFCG0atUMfar/ak+j9VfLxUeYgMHbZOlBTEndESh3i2am2ULZPHpYUiipcAWTgANaSSqcH5lsD0oGI6erRItBCl40UloHA5/gTqpy2T/R4twSbY7jVrOLGIGuTr66bvWmryvKZjmUlBXtUbhn6AwUqqqTbdAZ2x725rdiyF74fTn+D0IV36R2k+xfwrrTRLF1Nlmn+J9deaesCRH+vva4Asfj/rj+MKkVwWXHwDwLWDrDZVmqE1mXuRZyvuc+x9vscD2EwE73DniNV533TmQO7Kju4R4Nj5AQ/4a7c67VZjH+o3KnNjCfOoUBo2oM43GKDNLKRzbMCpvy3FbX3X/5YZ7Zu4FT6B2ycfe/fjGTXD4OCngvpJWEoFe16y1GgSOV33ntFwwL+no3d1ovn0HwC7ksG6q7nziq9NsT63ov2TPyhx/AavExH9NKJaUoeTpfMjSmIgyjZ13WK7JI5HlLS9EwqMnZBnH+lHAwpuNzBVCmOl95IijMGYrke0K+r4KthJzoRml1gW9vxTYWxjm3hhRYPjMIi6O4xj4QfHuzhm7Yx/Dscno+sWqzQ2AFiGBTsDzBw1MBe4MoVuK2mnZbAm/mBtB2uiWKs2dj00/4JtU6ixVLBRaoIgGPs6+kV9c+ypdJpr9fGARRKTdXNxXv0w0wtRFH9GqRIR3ymqdj/M7p5NR6cx9v1TpMKxOcsiCTIdwOncBtzELkC+m9hqFV9/LyM79TPKjq5hXTu/BhsZa4WysxV5Zrs/T1Zp6wwFpMFSaT8THmGIUskwFNqxzmRHtUJgWou/ksumDUwmAi4MMH3GFt7NBTi8xLWrAxkD3W6zgc61vCi3vqyUAYG1vpdLGeBZpvYXR1q5/CHyDUKtXxlrzTB2Sqz1CDj+Qbb+RFu/b7R1KH8M279n/VFnrgzlZX/UM/qz90Ax5VCfdWh00lCG4gpoBqX12ndEGT3OKK3XhjITzaGPMIrWPivLuB9KQ0DrBYrjDu5b8mrAb0Zs19Fc3URcFgGd/eKgvUHp2kfHyKKmL69cFknNoqyU7gbAv+VriJIoLFqto6jd5/ssehzT4oiusuq14j567S5P68B9GmGOxgZ6bTz6ZSg3hXMOS8w5ZM+ZmP0PsdEXAD8fIkXsJYT9q4Oo57L+itVxGhl48AjoGD7x9irhx4cOz6xxH22ZqlSR8k0/UagxtUfTBz2oVPPnNEgnE4zGfEmluiM3aujzSnWR/nYWnUsUqvWcp5hrVBkuEYHjqxLDSm1w1VRP+wr1WmCpHp8wZS8d2U4iX1GQPe7jMkHvvAj+Nv05jP2B9+QMnOLU/KuYd3rGAN7vXvv0/tJpdFG3U7S/sHeI/VZh3q5j70Vbu4zAsPhEMLG74pl2n3xw9aIW32U9YQ/YmwC0CVR46h3t+zrt2L0dKf3sXL0bHn2swrLGx+ki2TwSr9XBI1U4ZzxB7rSuu3JZP5VcBxkpc6QyI62XPFLFfOS14Dxl+ny/+jTdfb/l6/0bUo5hf96/IZRIsD9fLnm6o57i38gW8jv7NwRWcuiPf+Pc/o0Q+kPD9mORryJk+yre2L4Km+2roHY6zaZ+DalPQF5SW35t0yvrzG2oF/lNhnE9mrWd+AKojyHL3O6PqC/BMAbvBlfgp/jY9CGo7eks8TkYSQZ4nDUe5v0Tr4ZyYwSKzfZRaOGGz+O53PMkGeWkP5qWeS5yf7POft/wqXycy99xhPB/z6Rxfjc3M3VlmLZLvGAjjL2rU52mPD14oDKM5xOQ5Uh7uh/EV37oH042+rSy0+22Wo1Cp3ZO2VE1rlnOf8BUds4a0EY1qVoTttDDTKCorZWeUw+Xs2X+MFMUI6BVxqqPqd+KzsXU9oCtQIE/LVIdoy5R4NeATAit4e+9uY0HPGXZIx1W5zcVtVPV+b8J4bULI/yIvI3hL2rq/TPH0ZyxY1DvRCFaT4PldSIU1BZEMDAs/ylA9P+xKpFVUAqL3A8WmViUGD6SC2Ox5KcSitPSS8NQ3J9kBPNamNoevJdVBTimD0chM3IgPlLiQDhJL1CxLjW4sk6Q8olu4oWRmnd61FjJwUxP3vHejpJwPD1QwIZj/P5NhdqJ5sTUdpGxnT95CZRcKKXry1FS+qUE/k+qjUwU9Jw0+LgLgGybQsHUw6p+9KF5IH9QMLPBKzbRcYnjVDxn8PPfuknVv3CTOkKlW59vuopt4hSfNWUhyz7enga9F9qaaO84OBqTGnE07AaRIhfjO8KeVQZ80g/4drJXvxh8JQ/NEh5a7Ogy/SDZmum66k+pBzVars2VK5XuUPTCJ16ZwctV7Iil168b1+3V5k2Y3jjAFtqkgqqI41JK1LBab4opYd06ukubbwMKptIYa4KoRvXSL7pxcUXVCzYJUT8P2DNhYehrrlF3UMnAQUYdZnm08Ye4Iv2gqHQ2t92UR+uppR9u4/YhMu54zxonvrZ4eofrYX3rw3J74wks+KY0D1vRiyRbk2VhOhnhgZjRZlfwFSYxrxEkDI1brSVjt6P86z/59yySdct3FIlY9tgn6KX1HxH7ZiLGSceJ2DcVCa7ZrAqfE4pas1atbx9PdSmlnCwY5TTxtbH/Tnm8wNEErUNvE53m4ho9yq3O/3d+dwaj/6tWq/854OYtaf6X1+nfK9GDlvGIiedMtvhbLEiJoUVJf1yLOvihyU8anbLr/vgdzmD4XdTvUPITjruviR2RvX3apveMx1Am+z62x1Z4GajUas12t1YSKlmmxjdwuYtlXg9nv2UoVDn+UnA55FxPNog2TWAlC/qGNoJlfhoec3SdA1tdClt00U+y/DXQYoZyLgmtRv1Zay1srONbS39c3tpj56VSDlnPxHv3KbYmE2tvyPEiqJInQQTpien5tJuF6Zv7XVj/RnQxcil3AFceXcyg9RnRBbfrj7PHRsD62/lC538=&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="0" y="75" width="900" height="700" fill="#f8fbf3" stroke="none" pointer-events="all"/><g fill="#388E3C" font-family="sans-serif" text-anchor="middle" font-size="36px"><text x="449.5" y="134.5">Record traces</text></g><rect x="600" y="150" width="300" height="600" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 601px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: sans-serif; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font face="sans-serif" style="font-size: 32px"><span style="font-size: 32px">In-app tracing</span></font></div></div></div></foreignObject><text x="750" y="189" fill="#7cb342" font-family="sans-serif" font-size="32px" text-anchor="middle">In-app tracing</text></switch></g><ellipse cx="450" cy="50" rx="50" ry="50" fill="#4caf50" stroke="none" pointer-events="all"/><image x="417.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMFYweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xOCA0djFoLTJWNGMwLS41NS0uNDUtMS0xLTFIOWMtLjU1IDAtMSAuNDUtMSAxdjFINlY0YzAtLjU1LS40NS0xLTEtMXMtMSAuNDUtMSAxdjE2YzAgLjU1LjQ1IDEgMSAxczEtLjQ1IDEtMXYtMWgydjFjMCAuNTUuNDUgMSAxIDFoNmMuNTUgMCAxLS40NSAxLTF2LTFoMnYxYzAgLjU1LjQ1IDEgMSAxczEtLjQ1IDEtMVY0YzAtLjU1LS40NS0xLTEtMXMtMSAuNDUtMSAxek04IDE3SDZ2LTJoMnYyem0wLTRINnYtMmgydjJ6bTAtNEg2VjdoMnYyem0xMCA4aC0ydi0yaDJ2MnptMC00aC0ydi0yaDJ2MnptMC00aC0yVjdoMnYyeiIvPjwvc3ZnPg==" preserveAspectRatio="none" transform="rotate(90,450,50)"/><rect x="0" y="150" width="300" height="500" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: sans-serif; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-family: sans-serif ; font-size: 32px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">System </span><span style="font-family: sans-serif ; font-size: 32px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">tracing</span></div></div></div></foreignObject><text x="150" y="189" fill="#7cb342" font-family="sans-serif" font-size="32px" text-anchor="middle">System tracing</text></switch></g><rect x="300" y="150" width="300" height="600" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 301px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: sans-serif; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font face="sans-serif" style="font-size: 32px"><span style="font-size: 32px">Chrome tracing</span></font></div></div></div></foreignObject><text x="450" y="189" fill="#7cb342" font-family="sans-serif" font-size="32px" text-anchor="middle">Chrome tracing</text></switch></g><rect x="25" y="225" width="250" height="300" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 522px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 28px">Data sources<br style="font-size: 28px" /></span><font style="font-size: 20px">Linux/Android</font></div></div></div></foreignObject><text x="150" y="522" fill="#1b5e20" font-family="sans-serif" font-size="28px" text-anchor="middle">Data sources...</text></switch></g><a target="_top" xlink:href="/docs/data-sources/cpu-scheduling"><rect x="50" y="250" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 275px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 25px">Linux ftrace</span></div></div></div></foreignObject><text x="150" y="283" fill="#1b5e20" font-family="sans-serif" font-size="25px" text-anchor="middle">Linux ftrace</text></switch></g></a><a target="_top" xlink:href="/docs/data-sources/memory-counters"><rect x="50" y="325" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 350px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 25px">/proc </font><span style="font-size: 25px">pollers</span></div></div></div></foreignObject><text x="150" y="358" fill="#1b5e20" font-family="sans-serif" font-size="25px" text-anchor="middle">/proc pollers</text></switch></g></a><a target="_top" xlink:href="/docs/data-sources/native-heap-profiler"><rect x="50" y="396.88" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 422px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 25px">Heap profilers</span></div></div></div></foreignObject><text x="150" y="429" fill="#1b5e20" font-family="sans-serif" font-size="25px" text-anchor="middle">Heap profilers</text></switch></g></a><a target="_top" xlink:href="/docs/instrumentation/tracing-sdk"><rect x="25" y="650" width="850" height="100" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 848px; height: 1px; padding-top: 700px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px">Tracing C++ Library<br /></font><div><font style="font-size: 20px">Android / Linux / MacOS / Windows</font></div></div></div></div></foreignObject><text x="450" y="710" fill="#1b5e20" font-family="sans-serif" font-size="32px" text-anchor="middle">Tracing C++ Library...</text></switch></g></a><rect x="925" y="75" width="350" height="700" fill="#fff3e0" stroke="none" pointer-events="all"/><g fill="#FF9800" font-family="sans-serif" text-anchor="middle" font-size="36px"><text x="1099.5" y="134.5">Analyze traces</text></g><ellipse cx="1100" cy="50" rx="50" ry="50" fill="#ff9800" stroke="none" pointer-events="all"/><image x="1067.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMFYweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xOSAzSDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJWNWMwLTEuMS0uOS0yLTItMnpNOCAxN2MtLjU1IDAtMS0uNDUtMS0xdi01YzAtLjU1LjQ1LTEgMS0xczEgLjQ1IDEgMXY1YzAgLjU1LS40NSAxLTEgMXptNCAwYy0uNTUgMC0xLS40NS0xLTFWOGMwLS41NS40NS0xIDEtMXMxIC40NSAxIDF2OGMwIC41NS0uNDUgMS0xIDF6bTQgMGMtLjU1IDAtMS0uNDUtMS0xdi0yYzAtLjU1LjQ1LTEgMS0xczEgLjQ1IDEgMXYyYzAgLjU1LS40NSAxLTEgMXoiLz48L3N2Zz4=" preserveAspectRatio="none"/><a target="_top" xlink:href="/docs/analysis/trace-processor"><rect x="943.75" y="168.75" width="312.5" height="581.25" fill="#ffe0b2" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 311px; height: 1px; padding-top: 196px; margin-left: 945px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: sans-serif; color: #EA8600; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 36px">Trace Processor<br /></span><span style="font-size: 20px">Android / Linux / MacOS / Win</span></div></div></div></foreignObject><text x="1100" y="228" fill="#EA8600" font-family="sans-serif" font-size="32px" text-anchor="middle">Trace Processor...</text></switch></g></a><rect x="1300" y="75" width="350" height="700" fill="#e8f0fe" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 348px; height: 1px; padding-top: 112px; margin-left: 1301px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 36px; font-family: sans-serif; color: #4285F4; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-align: right ; text-indent: 0px ; text-transform: none ; word-spacing: 0px">Visualize </font><span style="font-size: 36px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-align: right ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">traces</span></div></div></div></foreignObject><text x="1475" y="148" fill="#4285F4" font-family="sans-serif" font-size="36px" text-anchor="middle">Visualize traces</text></switch></g><a target="_top" xlink:href="/docs/#trace-visualization"><rect x="1325" y="168.75" width="300" height="581.25" fill="#aecbfa" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 196px; margin-left: 1326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #1A73E8; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px">Perfetto UI<br /></font><span style="font-size: 20px">HTML / JS</span></div></div></div></foreignObject><text x="1475" y="224" fill="#1A73E8" font-family="sans-serif" font-size="28px" text-anchor="middle">Perfetto UI...</text></switch></g></a><ellipse cx="1475" cy="50" rx="50" ry="50" fill="#4285f4" stroke="none" pointer-events="all"/><image x="1442.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0yMCA0SDRjLTEuMSAwLTIgLjktMiAydjEyYzAgMS4xLjkgMiAyIDJoMTZjMS4xIDAgMi0uOSAyLTJWNmMwLTEuMS0uOS0yLTItMnpNNSAxMmgyYy41NSAwIDEgLjQ1IDEgMXMtLjQ1IDEtMSAxSDVjLS41NSAwLTEtLjQ1LTEtMXMuNDUtMSAxLTF6bTggNkg1Yy0uNTUgMC0xLS40NS0xLTFzLjQ1LTEgMS0xaDhjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDF6bTYgMGgtMmMtLjU1IDAtMS0uNDUtMS0xcy40NS0xIDEtMWgyYy41NSAwIDEgLjQ1IDEgMXMtLjQ1IDEtMSAxem0wLTRoLThjLS41NSAwLTEtLjQ1LTEtMXMuNDUtMSAxLTFoOGMuNTUgMCAxIC40NSAxIDFzLS40NSAxLTEgMXoiLz48L3N2Zz4=" preserveAspectRatio="none"/><rect x="965.63" y="325" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 375px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Trace importers<br /><span style="font-size: 20px">Protobuf, JSON, systrace</span></div></div></div></foreignObject><text x="1100" y="383" fill="#ac1900" font-family="sans-serif" font-size="28px" text-anchor="middle">Trace importers...</text></switch></g><a target="_top" xlink:href="/docs/analysis/metrics"><rect x="965.63" y="625" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 675px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 28px">Trace-based metrics<br /></font><font style="font-size: 20px">JSON / Protobuf / CSV</font></div></div></div></foreignObject><text x="1100" y="683" fill="#ac1900" font-family="sans-serif" font-size="28px" text-anchor="middle">Trace-based metrics...</text></switch></g></a><a target="_top" xlink:href="/docs/analysis/sql-tables"><rect x="965.63" y="475" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 525px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">SQL query engine<br /><font style="font-size: 20px">Based on SQLite</font></div></div></div></foreignObject><text x="1100" y="533" fill="#ac1900" font-family="sans-serif" font-size="28px" text-anchor="middle">SQL query engine...</text></switch></g></a><rect x="325" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">Tracing service<br /><span style="font-size: 16px">Mojo</span><br /></font></div></div></div></foreignObject><text x="450" y="595" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">Tracing service...</text></switch></g><rect x="325" y="225" width="250" height="200" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 325px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">Chrome-specific<br />data-sources</font></div></div></div></foreignObject><text x="450" y="332" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">Chrome-specific...</text></switch></g><a target="_top" xlink:href="/docs/instrumentation/tracing-sdk#in-process-mode"><rect x="625" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 626px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">In-process<br />service thread</font></div></div></div></foreignObject><text x="750" y="595" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">In-process...</text></switch></g></a><a target="_top" xlink:href="/docs/concepts/service-model"><rect x="25" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Tracing daemon<br /><font style="font-size: 16px">UNIX socket</font></div></div></div></foreignObject><text x="150" y="595" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">Tracing daemon...</text></switch></g></a><path d="M 300 150 L 296.7 626.4" fill="none" stroke="#8bc34a" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 600 149.3 L 596.7 625.7" fill="none" stroke="#8bc34a" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><a target="_top" xlink:href="/docs/instrumentation/track-events"><rect x="325" y="450" width="550" height="75" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 548px; height: 1px; padding-top: 488px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>Track event library<br /><font style="font-size: 20px">TRACE_EVENT(...)</font><br /></font></div></div></div></foreignObject><text x="600" y="495" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">Track event library...</text></switch></g></a><rect x="625" y="225" width="250" height="200" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 325px; margin-left: 626px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: sans-serif; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">App-specific<br />data-sources</font></div></div></div></foreignObject><text x="750" y="332" fill="#1b5e20" font-family="sans-serif" font-size="24px" text-anchor="middle">App-specific...</text></switch></g><rect x="1350" y="325" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 377px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Trace Processor<br /><font style="font-size: 20px">Web Assembly</font></div></div></div></foreignObject><text x="1475" y="385" fill="#ffffff" font-family="sans-serif" font-size="28px" text-anchor="middle">Trace Processor...</text></switch></g><rect x="1350" y="475" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 527px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>ADB over WebUSB<br /></font><font style="font-size: 20px">For Android</font></div></div></div></foreignObject><text x="1475" y="535" fill="#ffffff" font-family="sans-serif" font-size="28px" text-anchor="middle">ADB over WebUSB...</text></switch></g><rect x="1350" y="625" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 677px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: sans-serif; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>Works offline<br /></font><font style="font-size: 20px">After first visit</font></div></div></div></foreignObject><text x="1475" y="685" fill="#ffffff" font-family="sans-serif" font-size="28px" text-anchor="middle">Works offline...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1652px" height="776px" viewBox="-0.5 -0.5 1652 776" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2020-05-22T22:41:34.812Z&quot; agent=&quot;5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36&quot; etag=&quot;QckB1rB-GYIfxBJ2Ru_L&quot; version=&quot;13.1.3&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;7NN0wUOKmaAmGsXKK3Xs&quot; name=&quot;Page-1&quot;&gt;7VxZc6rM1v41qfrOhVYzOVwSh8QcMdnR7Aw3XyG0iAGaF3Agv/6sZlKxUYyanXdXUkkFVo+sflb3muBKaNmrG091pwrRsXXFI311JbSveJ4XahL8o5QwpnCCJMQUwzP1hLYmDM0PnDRNGhpzU8f+VsWAECsw3W2iRhwHa8EWTfU8styuNiHW9qiuauAdwlBTrV3qs6kH04Ta5NG64BabxjQdmkdJia2mtROCP1V1stwi4VXQJU6QzPGRjElArqTONAjo48lXfBd+J7RG1SDEsLDqmn5VIzaQNR+qdCeqbVqUuUlj6FboXAktj5AgvrJXLWzRVUn5HY/dLSjNHtjDTlCmweB9pXj/9R4+FMu/kxZLUp/fVsS4l4VqzRNGPmKNeDpdPk/VYEVjlgRhyuiJaVktYhEvuhUmjcl4IlwJ137gkXecljjEgfrXlCXd3JML16plGg4QNJg59mhbV9VMx+jjCX0SlDRMQCbU4H6BvcCE1ZaTpgFx1+1G9KbNozVlo5eNuQqNRkdoAX2XdQk36TB4tUFKWHmDiY0DL4QqaWkKn1RgUkFYrtHXTOtMN4BXT4lqgiYj63u9eHCRrN8Rayk0dhbziq9ZQcIIKlWwolFB7Z85hd21l4Axvd9a6pRIG1f8aDEA6Ujg3VVUdd2oZiT/o8FgDZyTOuo5FdV1EwjS1Uw6Bq7EfW+Pl4jempxD7HJqBnjoxs++hP0PKk0DG3jb5uisNgCdwPZyWOZ3UVnXxoJI6ZY6xta1qr0bHpk7em54tgScAcn1HJKzjXEDyQILybWLIVliADm3qJRHbvmnzw4edZz2gPZyRcpxRdplCsdiCncxpvCHmQK9wHlL0XIA86rvxofwxFxhPScEgElRUycSKpKEXbbvXcXDSPxzTBUOMxXUAZdemnakgmSC2Kfi+kB8MzAJFUjYEAI48AvlmB6W0U+hMO+sSjSknFJRSoFrXQ1U2EXjW9gWF7BJXq9gffnWw+2AfwuvxfHzaq59IFO9fURamyz6gi7ooSQoobTQbG2hzOSl0mp+6LZm9m7f3LcXvTUWjGZvJhtKSw4H0V/PeLMtf9wGNvJTV795grq6+3b7SB6GvdX97bXYM6/J27PlqLe/oG1H1G4N82G2Wr6+PJLeDdDe0bLXvibK7JGHv57SfV1ic93v2G7O34a9Ra7N6r4lI33WJf3R3fPgRln2hyI3GKL5oP0UKEO06o+6vftnJejPnrheWwaanJTJK2jXG1iv6PVDjsqhLRpEbTqB8qLk6nZ4qGdE9Wa/oK+OQenaRydI7qHNa6A8GyH0OwPezAejJ9o+qtdrd8nAViiN8m0VjyXT+fHwRxTndXWw/9/l5orfkQj1hWH7Dfq+o32H2EbL/uixN3Bgjjad411tPJKDQcfgf8/0tM4K5iaqLRTqJgrV9h2vOG6gtBAqomVtTbo2y4UmvDkPVLOKfkF1CNQE+U10iU0hLW1s61mNnX24JjLOJvFCG0atUMfar/ak+j9VfLxUeYgMHbZOlBTEndESh3i2am2ULZPHpYUiipcAWTgANaSSqcH5lsD0oGI6erRItBCl40UloHA5/gTqpy2T/R4twSbY7jVrOLGIGuTr66bvWmryvKZjmUlBXtUbhn6AwUqqqTbdAZ2x725rdiyF74fTn+D0IV36R2k+xfwrrTRLF1Nlmn+J9deaesCRH+vva4Asfj/rj+MKkVwWXHwDwLWDrDZVmqE1mXuRZyvuc+x9vscD2EwE73DniNV533TmQO7Kju4R4Nj5AQ/4a7c67VZjH+o3KnNjCfOoUBo2oM43GKDNLKRzbMCpvy3FbX3X/5YZ7Zu4FT6B2ycfe/fjGTXD4OCngvpJWEoFe16y1GgSOV33ntFwwL+no3d1ovn0HwC7ksG6q7nziq9NsT63ov2TPyhx/AavExH9NKJaUoeTpfMjSmIgyjZ13WK7JI5HlLS9EwqMnZBnH+lHAwpuNzBVCmOl95IijMGYrke0K+r4KthJzoRml1gW9vxTYWxjm3hhRYPjMIi6O4xj4QfHuzhm7Yx/Dscno+sWqzQ2AFiGBTsDzBw1MBe4MoVuK2mnZbAm/mBtB2uiWKs2dj00/4JtU6ixVLBRaoIgGPs6+kV9c+ypdJpr9fGARRKTdXNxXv0w0wtRFH9GqRIR3ymqdj/M7p5NR6cx9v1TpMKxOcsiCTIdwOncBtzELkC+m9hqFV9/LyM79TPKjq5hXTu/BhsZa4WysxV5Zrs/T1Zp6wwFpMFSaT8THmGIUskwFNqxzmRHtUJgWou/ksumDUwmAi4MMH3GFt7NBTi8xLWrAxkD3W6zgc61vCi3vqyUAYG1vpdLGeBZpvYXR1q5/CHyDUKtXxlrzTB2Sqz1CDj+Qbb+RFu/b7R1KH8M279n/VFnrgzlZX/UM/qz90Ax5VCfdWh00lCG4gpoBqX12ndEGT3OKK3XhjITzaGPMIrWPivLuB9KQ0DrBYrjDu5b8mrAb0Zs19Fc3URcFgGd/eKgvUHp2kfHyKKmL69cFknNoqyU7gbAv+VriJIoLFqto6jd5/ssehzT4oiusuq14j567S5P68B9GmGOxgZ6bTz6ZSg3hXMOS8w5ZM+ZmP0PsdEXAD8fIkXsJYT9q4Oo57L+itVxGhl48AjoGD7x9irhx4cOz6xxH22ZqlSR8k0/UagxtUfTBz2oVPPnNEgnE4zGfEmluiM3aujzSnWR/nYWnUsUqvWcp5hrVBkuEYHjqxLDSm1w1VRP+wr1WmCpHp8wZS8d2U4iX1GQPe7jMkHvvAj+Nv05jP2B9+QMnOLU/KuYd3rGAN7vXvv0/tJpdFG3U7S/sHeI/VZh3q5j70Vbu4zAsPhEMLG74pl2n3xw9aIW32U9YQ/YmwC0CVR46h3t+zrt2L0dKf3sXL0bHn2swrLGx+ki2TwSr9XBI1U4ZzxB7rSuu3JZP5VcBxkpc6QyI62XPFLFfOS14Dxl+ny/+jTdfb/l6/0bUo5hf96/IZRIsD9fLnm6o57i38gW8jv7NwRWcuiPf+Pc/o0Q+kPD9mORryJk+yre2L4Km+2roHY6zaZ+DalPQF5SW35t0yvrzG2oF/lNhnE9mrWd+AKojyHL3O6PqC/BMAbvBlfgp/jY9CGo7eks8TkYSQZ4nDUe5v0Tr4ZyYwSKzfZRaOGGz+O53PMkGeWkP5qWeS5yf7POft/wqXycy99xhPB/z6Rxfjc3M3VlmLZLvGAjjL2rU52mPD14oDKM5xOQ5Uh7uh/EV37oH042+rSy0+22Wo1Cp3ZO2VE1rlnOf8BUds4a0EY1qVoTttDDTKCorZWeUw+Xs2X+MFMUI6BVxqqPqd+KzsXU9oCtQIE/LVIdoy5R4NeATAit4e+9uY0HPGXZIx1W5zcVtVPV+b8J4bULI/yIvI3hL2rq/TPH0ZyxY1DvRCFaT4PldSIU1BZEMDAs/ylA9P+xKpFVUAqL3A8WmViUGD6SC2Ox5KcSitPSS8NQ3J9kBPNamNoevJdVBTimD0chM3IgPlLiQDhJL1CxLjW4sk6Q8olu4oWRmnd61FjJwUxP3vHejpJwPD1QwIZj/P5NhdqJ5sTUdpGxnT95CZRcKKXry1FS+qUE/k+qjUwU9Jw0+LgLgGybQsHUw6p+9KF5IH9QMLPBKzbRcYnjVDxn8PPfuknVv3CTOkKlW59vuopt4hSfNWUhyz7enga9F9qaaO84OBqTGnE07AaRIhfjO8KeVQZ80g/4drJXvxh8JQ/NEh5a7Ogy/SDZmum66k+pBzVars2VK5XuUPTCJ16ZwctV7Iil168b1+3V5k2Y3jjAFtqkgqqI41JK1LBab4opYd06ukubbwMKptIYa4KoRvXSL7pxcUXVCzYJUT8P2DNhYehrrlF3UMnAQUYdZnm08Ye4Iv2gqHQ2t92UR+uppR9u4/YhMu54zxonvrZ4eofrYX3rw3J74wks+KY0D1vRiyRbk2VhOhnhgZjRZlfwFSYxrxEkDI1brSVjt6P86z/59yySdct3FIlY9tgn6KX1HxH7ZiLGSceJ2DcVCa7ZrAqfE4pas1atbx9PdSmlnCwY5TTxtbH/Tnm8wNEErUNvE53m4ho9yq3O/3d+dwaj/6tWq/854OYtaf6X1+nfK9GDlvGIiedMtvhbLEiJoUVJf1yLOvihyU8anbLr/vgdzmD4XdTvUPITjruviR2RvX3apveMx1Am+z62x1Z4GajUas12t1YSKlmmxjdwuYtlXg9nv2UoVDn+UnA55FxPNog2TWAlC/qGNoJlfhoec3SdA1tdClt00U+y/DXQYoZyLgmtRv1Zay1srONbS39c3tpj56VSDlnPxHv3KbYmE2tvyPEiqJInQQTpien5tJuF6Zv7XVj/RnQxcil3AFceXcyg9RnRBbfrj7PHRsD62/lC538=&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="0" y="75" width="900" height="700" fill="#f8fbf3" stroke="none" pointer-events="all"/><g fill="#388E3C" font-family="Roboto" text-anchor="middle" font-size="36px"><text x="449.5" y="134.5">Record traces</text></g><rect x="600" y="150" width="300" height="600" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 601px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: Roboto; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font face="roboto" style="font-size: 32px"><span style="font-size: 32px">In-app tracing</span></font></div></div></div></foreignObject><text x="750" y="189" fill="#7cb342" font-family="Roboto" font-size="32px" text-anchor="middle">In-app tracing</text></switch></g><ellipse cx="450" cy="50" rx="50" ry="50" fill="#4caf50" stroke="none" pointer-events="all"/><image x="417.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMFYweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xOCA0djFoLTJWNGMwLS41NS0uNDUtMS0xLTFIOWMtLjU1IDAtMSAuNDUtMSAxdjFINlY0YzAtLjU1LS40NS0xLTEtMXMtMSAuNDUtMSAxdjE2YzAgLjU1LjQ1IDEgMSAxczEtLjQ1IDEtMXYtMWgydjFjMCAuNTUuNDUgMSAxIDFoNmMuNTUgMCAxLS40NSAxLTF2LTFoMnYxYzAgLjU1LjQ1IDEgMSAxczEtLjQ1IDEtMVY0YzAtLjU1LS40NS0xLTEtMXMtMSAuNDUtMSAxek04IDE3SDZ2LTJoMnYyem0wLTRINnYtMmgydjJ6bTAtNEg2VjdoMnYyem0xMCA4aC0ydi0yaDJ2MnptMC00aC0ydi0yaDJ2MnptMC00aC0yVjdoMnYyeiIvPjwvc3ZnPg==" preserveAspectRatio="none" transform="rotate(90,450,50)"/><rect x="0" y="150" width="300" height="500" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: Roboto; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-family: &quot;roboto&quot; ; font-size: 32px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">System </span><span style="font-family: &quot;roboto&quot; ; font-size: 32px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">tracing</span></div></div></div></foreignObject><text x="150" y="189" fill="#7cb342" font-family="Roboto" font-size="32px" text-anchor="middle">System tracing</text></switch></g><rect x="300" y="150" width="300" height="600" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 157px; margin-left: 301px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: Roboto; color: #7cb342; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font face="roboto" style="font-size: 32px"><span style="font-size: 32px">Chrome tracing</span></font></div></div></div></foreignObject><text x="450" y="189" fill="#7cb342" font-family="Roboto" font-size="32px" text-anchor="middle">Chrome tracing</text></switch></g><rect x="25" y="225" width="250" height="300" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 522px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 28px">Data sources<br style="font-size: 28px" /></span><font style="font-size: 20px">Linux/Android</font></div></div></div></foreignObject><text x="150" y="522" fill="#1b5e20" font-family="Roboto" font-size="28px" text-anchor="middle">Data sources...</text></switch></g><a target="_top" xlink:href="/docs/data-sources/cpu-scheduling"><rect x="50" y="250" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 275px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 25px">Linux ftrace</span></div></div></div></foreignObject><text x="150" y="283" fill="#1b5e20" font-family="Roboto" font-size="25px" text-anchor="middle">Linux ftrace</text></switch></g></a><a target="_top" xlink:href="/docs/data-sources/memory-counters"><rect x="50" y="325" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 350px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 25px">/proc </font><span style="font-size: 25px">pollers</span></div></div></div></foreignObject><text x="150" y="358" fill="#1b5e20" font-family="Roboto" font-size="25px" text-anchor="middle">/proc pollers</text></switch></g></a><a target="_top" xlink:href="/docs/data-sources/native-heap-profiler"><rect x="50" y="396.88" width="200" height="50" fill="#c5e1a5" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 422px; margin-left: 51px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 25px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 25px">Heap profilers</span></div></div></div></foreignObject><text x="150" y="429" fill="#1b5e20" font-family="Roboto" font-size="25px" text-anchor="middle">Heap profilers</text></switch></g></a><a target="_top" xlink:href="/docs/instrumentation/tracing-sdk"><rect x="25" y="650" width="850" height="100" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 848px; height: 1px; padding-top: 700px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px">Tracing C++ Library<br /></font><div><font style="font-size: 20px">Android / Linux / MacOS / Windows</font></div></div></div></div></foreignObject><text x="450" y="710" fill="#1b5e20" font-family="Roboto" font-size="32px" text-anchor="middle">Tracing C++ Library...</text></switch></g></a><rect x="925" y="75" width="350" height="700" fill="#fff3e0" stroke="none" pointer-events="all"/><g fill="#FF9800" font-family="Roboto" text-anchor="middle" font-size="36px"><text x="1099.5" y="134.5">Analyze traces</text></g><ellipse cx="1100" cy="50" rx="50" ry="50" fill="#ff9800" stroke="none" pointer-events="all"/><image x="1067.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMFYweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xOSAzSDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJWNWMwLTEuMS0uOS0yLTItMnpNOCAxN2MtLjU1IDAtMS0uNDUtMS0xdi01YzAtLjU1LjQ1LTEgMS0xczEgLjQ1IDEgMXY1YzAgLjU1LS40NSAxLTEgMXptNCAwYy0uNTUgMC0xLS40NS0xLTFWOGMwLS41NS40NS0xIDEtMXMxIC40NSAxIDF2OGMwIC41NS0uNDUgMS0xIDF6bTQgMGMtLjU1IDAtMS0uNDUtMS0xdi0yYzAtLjU1LjQ1LTEgMS0xczEgLjQ1IDEgMXYyYzAgLjU1LS40NSAxLTEgMXoiLz48L3N2Zz4=" preserveAspectRatio="none"/><a target="_top" xlink:href="/docs/analysis/trace-processor"><rect x="943.75" y="168.75" width="312.5" height="581.25" fill="#ffe0b2" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 311px; height: 1px; padding-top: 196px; margin-left: 945px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 32px; font-family: Roboto; color: #EA8600; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><span style="font-size: 36px">Trace Processor<br /></span><span style="font-size: 20px">Android / Linux / MacOS / Win</span></div></div></div></foreignObject><text x="1100" y="228" fill="#EA8600" font-family="Roboto" font-size="32px" text-anchor="middle">Trace Processor...</text></switch></g></a><rect x="1300" y="75" width="350" height="700" fill="#e8f0fe" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 348px; height: 1px; padding-top: 112px; margin-left: 1301px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 36px; font-family: Roboto; color: #4285F4; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-align: right ; text-indent: 0px ; text-transform: none ; word-spacing: 0px">Visualize </font><span style="font-size: 36px ; font-style: normal ; font-weight: 400 ; letter-spacing: normal ; text-align: right ; text-indent: 0px ; text-transform: none ; word-spacing: 0px ; float: none ; display: inline">traces</span></div></div></div></foreignObject><text x="1475" y="148" fill="#4285F4" font-family="Roboto" font-size="36px" text-anchor="middle">Visualize traces</text></switch></g><a target="_top" xlink:href="/docs/#trace-visualization"><rect x="1325" y="168.75" width="300" height="581.25" fill="#aecbfa" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 196px; margin-left: 1326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #1A73E8; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 36px">Perfetto UI<br /></font><span style="font-size: 20px">HTML / JS</span></div></div></div></foreignObject><text x="1475" y="224" fill="#1A73E8" font-family="Roboto" font-size="28px" text-anchor="middle">Perfetto UI...</text></switch></g></a><ellipse cx="1475" cy="50" rx="50" ry="50" fill="#4285f4" stroke="none" pointer-events="all"/><image x="1442.5" y="17.5" width="64" height="64" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0yMCA0SDRjLTEuMSAwLTIgLjktMiAydjEyYzAgMS4xLjkgMiAyIDJoMTZjMS4xIDAgMi0uOSAyLTJWNmMwLTEuMS0uOS0yLTItMnpNNSAxMmgyYy41NSAwIDEgLjQ1IDEgMXMtLjQ1IDEtMSAxSDVjLS41NSAwLTEtLjQ1LTEtMXMuNDUtMSAxLTF6bTggNkg1Yy0uNTUgMC0xLS40NS0xLTFzLjQ1LTEgMS0xaDhjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDF6bTYgMGgtMmMtLjU1IDAtMS0uNDUtMS0xcy40NS0xIDEtMWgyYy41NSAwIDEgLjQ1IDEgMXMtLjQ1IDEtMSAxem0wLTRoLThjLS41NSAwLTEtLjQ1LTEtMXMuNDUtMSAxLTFoOGMuNTUgMCAxIC40NSAxIDFzLS40NSAxLTEgMXoiLz48L3N2Zz4=" preserveAspectRatio="none"/><rect x="965.63" y="325" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 375px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Trace importers<br /><span style="font-size: 20px">Protobuf, JSON, systrace</span></div></div></div></foreignObject><text x="1100" y="383" fill="#ac1900" font-family="Roboto" font-size="28px" text-anchor="middle">Trace importers...</text></switch></g><a target="_top" xlink:href="/docs/analysis/metrics"><rect x="965.63" y="625" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 675px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 28px">Trace-based metrics<br /></font><font style="font-size: 20px">JSON / Protobuf / CSV</font></div></div></div></foreignObject><text x="1100" y="683" fill="#ac1900" font-family="Roboto" font-size="28px" text-anchor="middle">Trace-based metrics...</text></switch></g></a><a target="_top" xlink:href="/docs/analysis/sql-tables"><rect x="965.63" y="475" width="268.75" height="100" fill="#ffcc80" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 267px; height: 1px; padding-top: 525px; margin-left: 967px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ac1900; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">SQL query engine<br /><font style="font-size: 20px">Based on SQLite</font></div></div></div></foreignObject><text x="1100" y="533" fill="#ac1900" font-family="Roboto" font-size="28px" text-anchor="middle">SQL query engine...</text></switch></g></a><rect x="325" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">Tracing service<br /><span style="font-size: 16px">Mojo</span><br /></font></div></div></div></foreignObject><text x="450" y="595" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">Tracing service...</text></switch></g><rect x="325" y="225" width="250" height="200" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 325px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">Chrome-specific<br />data-sources</font></div></div></div></foreignObject><text x="450" y="332" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">Chrome-specific...</text></switch></g><a target="_top" xlink:href="/docs/instrumentation/tracing-sdk#in-process-mode"><rect x="625" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 626px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">In-process<br />service thread</font></div></div></div></foreignObject><text x="750" y="595" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">In-process...</text></switch></g></a><a target="_top" xlink:href="/docs/concepts/service-model"><rect x="25" y="550" width="250" height="75" fill="#aed581" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 588px; margin-left: 26px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Tracing daemon<br /><font style="font-size: 16px">UNIX socket</font></div></div></div></foreignObject><text x="150" y="595" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">Tracing daemon...</text></switch></g></a><path d="M 300 150 L 296.7 626.4" fill="none" stroke="#8bc34a" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 600 149.3 L 596.7 625.7" fill="none" stroke="#8bc34a" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><a target="_top" xlink:href="/docs/instrumentation/track-events"><rect x="325" y="450" width="550" height="75" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 548px; height: 1px; padding-top: 488px; margin-left: 326px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>Track event library<br /><font style="font-size: 20px">TRACE_EVENT(...)</font><br /></font></div></div></div></foreignObject><text x="600" y="495" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">Track event library...</text></switch></g></a><rect x="625" y="225" width="250" height="200" fill="#dcedc8" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 325px; margin-left: 626px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Roboto; color: #1b5e20; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 24px">App-specific<br />data-sources</font></div></div></div></foreignObject><text x="750" y="332" fill="#1b5e20" font-family="Roboto" font-size="24px" text-anchor="middle">App-specific...</text></switch></g><rect x="1350" y="325" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 377px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Trace Processor<br /><font style="font-size: 20px">Web Assembly</font></div></div></div></foreignObject><text x="1475" y="385" fill="#ffffff" font-family="Roboto" font-size="28px" text-anchor="middle">Trace Processor...</text></switch></g><rect x="1350" y="475" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 527px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>ADB over WebUSB<br /></font><font style="font-size: 20px">For Android</font></div></div></div></foreignObject><text x="1475" y="535" fill="#ffffff" font-family="Roboto" font-size="28px" text-anchor="middle">ADB over WebUSB...</text></switch></g><rect x="1350" y="625" width="250" height="103.12" fill="#669df6" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 677px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 28px; font-family: Roboto; color: #ffffff; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font>Works offline<br /></font><font style="font-size: 20px">After first visit</font></div></div></div></foreignObject><text x="1475" y="685" fill="#ffffff" font-family="Roboto" font-size="28px" text-anchor="middle">Works offline...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
\ No newline at end of file
diff --git a/docs/images/rail-mode-debug-slices.png b/docs/images/rail-mode-debug-slices.png
deleted file mode 100644
index 608d9ac..0000000
--- a/docs/images/rail-mode-debug-slices.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/span-join.png b/docs/images/span-join.png
deleted file mode 100644
index b2cfd74..0000000
--- a/docs/images/span-join.png
+++ /dev/null
Binary files differ
diff --git a/docs/instrumentation/heapprofd-api.md b/docs/instrumentation/heapprofd-api.md
deleted file mode 100644
index 88f6dff..0000000
--- a/docs/instrumentation/heapprofd-api.md
+++ /dev/null
@@ -1,136 +0,0 @@
-# heapprofd Custom Allocator API - Early Access
-
-WARNING: The heapprofd Custom Allocator API is currently in **beta** stage.
-         Please file [bugs](https://github.com/google/perfetto/issues/new)
-         for any issues you encounter.
-
-NOTE: The heapprofd Custom Allocator API requires a device running Android
-      10 or newer.
-
-## Get SDK
-
-Before instrumenting your app, you need to get the heapprofd library and
-header.
-
-### Option 1: Prebuilts
-
-You can download the library as a binary from [Google Drive](
-https://drive.google.com/drive/folders/15RPlGgAHWRSk7KquBqlQ7fsCaXnNaa6r
-).
-Join our [Google Group](https://groups.google.com/forum/#!forum/perfetto-dev)
-to get access.
-
-### Option 2: Build yourself (on Linux)
-
-Alternatively, you can build the binaries yourself from AOSP.
-
-First, [check out Perfetto](https://perfetto.dev/docs/contributing/build-instructions):
-
-```
-$ git clone https://android.googlesource.com/platform/external/perfetto/
-```
-
-Then, change to the project directory, download and build additional
-dependencies, and then build the standalone library:
-
-```
-$ cd perfetto
-perfetto/ $ tools/install-build-deps --android
-perfetto/ $ tools/build_all_configs.py --android
-perfetto/ $ ninja -C out/android_release_incl_heapprofd_arm64 \
-libheapprofd_standalone_client.so
-```
-
-You will find the built library in
-`out/android_release_incl_heapprofd_arm64/libheapprofd_standalone_client.so`.
-The header for the API can be found in
-`src/profiling/memory/include/perfetto/heap_profile.h`. This library is built
-against SDK version 29, so will work on Android 10 or newer.
-
-WARNING: Only use the header from the checkout you used to build the library,
-         as the API is not stable yet.
-
-To make debugging in the future easier, make note of the revision at the time
-you built.
-
-```
-git rev-parse HEAD > perfetto-version.txt
-```
-Please include this in any bugs you file.
-
-## Instrument App
-
-Let's assume your application has a very simple custom allocator that looks
-like this:
-
-```
-void* my_malloc(size_t size) {
-  void* ptr = [code to somehow allocate get size bytes];
-  return ptr;
-}
-
-void my_free(void* ptr) {
-  [code to somehow free ptr]
-}
-```
-
-To find out where in a program these two functions get called, we instrument
-the allocator using this API:
-
-```
-#include "path/to/heap_profile.h"
-
-static uint32_t g_heap_id = AHeapProfile_registerHeap(
-  AHeapInfo_create("invalid.example"));
-void* my_malloc(size_t size) {
-  void* ptr = [code to somehow allocate get size bytes];
-  AHeapProfile_reportAllocation(g_heap_id, static_cast<uintptr_t>(ptr), size);
-  return ptr;
-}
-
-void my_free(void* ptr) {
-  AHeapProfile_reportFree(g_heap_id, static_cast<uintptr_t>(ptr));
-  [code to somehow free ptr]
-}
-```
-
-Don't forget to link `heapprofd_standalone_client.so` and including it in
-your app.
-
-## Profile your App
-
-Then, use the [heap_profile](
-https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile)
-script to get a profile to generate textpb of the config.
-To convert to a binary proto, you additionally need to download
-[`perfetto_trace.proto`](
-https://raw.githubusercontent.com/google/perfetto/master/protos/perfetto/trace/perfetto_trace.proto)
-and have recent version of the protoc compiler installed.
-[Learn how to install protoc](https://grpc.io/docs/protoc-installation).
-
-On Linux, you can start a profile using the following pipeline (substitue
-`$APP_NAME` for the name of your app and `$HEAP` for the name of the heap
-you registered using `AHeapProfile_registerHeap`):
-
-```
-heap_profile -n $APP_NAME --heaps $HEAP --print-config | \
- path/to/protoc --encode=perfetto.protos.TraceConfig perfetto_trace.proto | \
- adb shell perfetto -c - -o /data/misc/perfetto-traces/profile
-```
-
-On Windows, you will need [python 3.6](https://www.python.org/downloads/) or
-later. You can start a profile using the following pipeline from a command
-prompt (substitue`%APP_NAME%` for the name of your app and `%HEAP%` for
-the name of the heap you registered using `AHeapProfile_registerHeap`):
-
-```
-python /path/to/heap_profile -n %APP_NAME% --heaps %HEAP% --print-config | ^
- path/to/protoc --encode=perfetto.protos.TraceConfig perfetto_trace.proto | ^
- adb shell perfetto -c - -o /data/misc/perfetto-traces/profile
-```
-
-Play around with the app to make it cause custom allocations, then stop the
-profile using `adb shell killall perfetto`. Once it is done, pull the profile
-from `/data/misc/perfetto-traces/profile` using `adb pull`.
-
-Upload the profile to the [Perfetto UI](https://ui.perfetto.dev).
diff --git a/docs/instrumentation/interceptors.md b/docs/instrumentation/interceptors.md
deleted file mode 100644
index f61c469..0000000
--- a/docs/instrumentation/interceptors.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# Trace packet interceptors (Tracing SDK)
-
-A trace packet interceptor is used to redirect trace packets written by a
-data source into a custom backend instead of the normal Perfetto tracing
-service. For example, the console interceptor prints all trace packets to the
-console as they are generated. Another potential use is exporting trace data
-to another tracing service such as Android ATrace or Windows ETW.
-
-An interceptor is defined by subclassing the `perfetto::Interceptor` template:
-
-```C++
-class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
- public:
-  ~MyInterceptor() override = default;
-
-  // This function is called for each intercepted trace packet. |context|
-  // contains information about the trace packet as well as other state
-  // tracked by the interceptor (e.g., see ThreadLocalState).
-  //
-  // Intercepted trace data is provided in the form of serialized protobuf
-  // bytes, accessed through the |context.packet_data| field.
-  //
-  // Warning: this function can be called on any thread at any time. See
-  // below for how to safely access shared interceptor data from here.
-  static void OnTracePacket(InterceptorContext context) {
-    perfetto::protos::pbzero::TracePacket::Decoder packet(
-        context.packet_data.data, context.packet_data.size);
-    // ... Write |packet| to the desired destination ...
-  }
-};
-```
-
-An interceptor should be registered before any tracing sessions are started.
-Note that the interceptor also needs to be activated through the trace config
-shown below.
-
-```C++
-perfetto::InterceptorDescriptor desc;
-desc.set_name("my_interceptor");
-MyInterceptor::Register(desc);
-```
-
-Finally, an interceptor is enabled through the trace config like this:
-
-```C++
-perfetto::TraceConfig cfg;
-auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-ds_cfg->set_name("data_source_to_intercept");   // e.g. "track_event"
-ds_cfg->mutable_interceptor_config()->set_name("my_interceptor");
-```
-
-Once an interceptor is enabled, all data from the affected data sources is
-sent to the interceptor instead of the main tracing buffer.
-
-## Interceptor state
-
-Besides the serialized trace packet data, the `OnTracePacket` interceptor
-function can access three other types of state:
-
-1. **Global state:** this is no different from a normal static function, but
-   care must be taken because |OnTracePacket| can be called concurrently on
-   any thread at any time.
-
-2. **Per-data source instance state:** since the interceptor class is
-   automatically instantiated for each intercepted data source, its fields
-   can be used to store per-instance data such as the trace config. This data
-   can be maintained through the OnSetup/OnStart/OnStop callbacks:
-
-   ```C++
-   class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-    public:
-     void OnSetup(const SetupArgs& args) override {
-       enable_foo_ = args.config.interceptor_config().enable_foo();
-     }
-
-     bool enable_foo_{};
-   };
-   ```
-
-   In the interceptor function this data must be accessed through a scoped
-   lock for safety:
-
-   ```C++
-   class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-     ...
-     static void OnTracePacket(InterceptorContext context) {
-       auto my_interceptor = context.GetInterceptorLocked();
-       if (my_interceptor) {
-          // Access fields of MyInterceptor here.
-          if (my_interceptor->enable_foo_) { ... }
-       }
-       ...
-     }
-   };
-   ```
-
-   Since accessing this data involves holding a lock, it should be done
-   sparingly.
-
-3. **Per-thread/TraceWriter state:** many data sources use interning to avoid
-   repeating common data in the trace. Since the interning dictionaries are
-   typically kept individually for each TraceWriter sequence (i.e., per
-   thread), an interceptor can declare a data structure with lifetime
-   matching the TraceWriter:
-
-   ```C++
-   class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-    public:
-     struct ThreadLocalState
-         : public perfetto::InterceptorBase::ThreadLocalState {
-       ThreadLocalState(ThreadLocalStateArgs&) override = default;
-       ~ThreadLocalState() override = default;
-
-       std::map<size_t, std::string> event_names;
-     };
-   };
-   ```
-
-   This per-thread state can then be accessed and maintained in
-   `OnTracePacket` like this:
-
-   ```C++
-   class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-     ...
-     static void OnTracePacket(InterceptorContext context) {
-       // Updating interned data.
-       auto& tls = context.GetThreadLocalState();
-       if (parsed_packet.sequence_flags() & perfetto::protos::pbzero::
-               TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
-         tls.event_names.clear();
-       }
-       for (const auto& entry : parsed_packet.interned_data().event_names())
-         tls.event_names[entry.iid()] = entry.name();
-
-       // Looking up interned data.
-       if (parsed_packet.has_track_event()) {
-         size_t name_iid = parsed_packet.track_event().name_iid();
-         const std::string& event_name = tls.event_names[name_iid];
-       }
-       ...
-     }
-   };
-   ```
\ No newline at end of file
diff --git a/docs/instrumentation/tracing-sdk.md b/docs/instrumentation/tracing-sdk.md
index cc4e6c4..a072f65 100644
--- a/docs/instrumentation/tracing-sdk.md
+++ b/docs/instrumentation/tracing-sdk.md
@@ -30,7 +30,7 @@
 To start using the Client API, first check out the latest SDK release:
 
 ```bash
-git clone https://android.googlesource.com/platform/external/perfetto -b v14.0
+git clone https://android.googlesource.com/platform/external/perfetto -b v4.1
 ```
 
 The SDK consists of two files, `sdk/perfetto.h` and `sdk/perfetto.cc`. These are
@@ -92,7 +92,7 @@
 they take care of a number of subtleties (e.g., thread safety, flushing, string
 interning).
 Track events are time bounded events (e.g., slices, counter) based on simple
-`TRACE_EVENT` annotation tags in the codebase, like this:
+annotation tags in the codebase, like this:
 
 ```c++
 #include <perfetto.h>
@@ -161,7 +161,7 @@
 corresponding changes in [trace processor](/docs/analysis/trace-processor.md)
 to enable importing your data format.
 
-A custom data source is a subclass of `perfetto::DataSource`. Perfetto will
+A custom data source is a subclass of `perfetto::DataSource`. Perfetto with
 automatically create one instance of the class for each tracing session it is
 active in (usually just one).
 
@@ -367,7 +367,7 @@
 
 // Write the trace into a file.
 std::ofstream output;
-output.open("example.perfetto-trace", std::ios::out | std::ios::binary);
+output.open("example.pftrace", std::ios::out | std::ios::binary);
 output.write(&trace_data[0], trace_data.size());
 output.close();
 ```
@@ -377,7 +377,7 @@
 to close the file after tracing is done:
 
 ```C++
-int fd = open("example.perfetto-trace", O_RDWR | O_CREAT | O_TRUNC, 0600);
+int fd = open("example.pftrace", O_RDWR | O_CREAT | O_TRUNC, 0600);
 tracing_session->Setup(cfg, fd);
 tracing_session->StartBlocking();
 // ...
diff --git a/docs/instrumentation/track-events.md b/docs/instrumentation/track-events.md
index 6b31791..4ad67ae 100644
--- a/docs/instrumentation/track-events.md
+++ b/docs/instrumentation/track-events.md
@@ -15,8 +15,8 @@
 section of the Tracing SDK page for instructions on how to check out and
 build the SDK.
 
-TIP: The code from these examples is also available [in the
-repository](/examples/sdk/README.md).
+TIP: The code from this example is also available as a
+     [GitHub repository](https://github.com/skyostil/perfetto-sdk-example).
 
 There are a few main types of track events:
 
@@ -83,9 +83,8 @@
 #include "my_app_tracing_categories.h"
 
 void DrawPlayer() {
-  TRACE_EVENT("rendering", "DrawPlayer");  // Begin "DrawPlayer" slice.
+  TRACE_EVENT("rendering", "DrawPlayer");
   ...
-  // End "DrawPlayer" slice.
 }
 ```
 
@@ -93,32 +92,6 @@
 event will cover the time from when the `TRACE_EVENT` annotation is encountered
 to the end of the block (in the example above, until the function returns).
 
-For events that don't follow function scoping, use `TRACE_EVENT_BEGIN` and
-`TRACE_EVENT_END`:
-
-```C++
-void LoadGame() {
-  DisplayLoadingScreen();
-
-  TRACE_EVENT_BEGIN("io", "Loading");  // Begin "Loading" slice.
-  LoadCollectibles();
-  LoadVehicles();
-  LoadPlayers();
-  TRACE_EVENT_END("io");               // End "Loading" slice.
-
-  StartGame();
-}
-```
-
-Note that you don't need to give a name for `TRACE_EVENT_END`, since it
-automatically closes the most recent event that began on the same thread. In
-other words, all events on a given thread share the same stack. This means
-that it's not recommended to have a matching pair of `TRACE_EVENT_BEGIN` and
-`TRACE_EVENT_END` markers in separate functions, since an unrelated event
-might terminate the original event unexpectedly; for events that cross
-function boundaries it's usually best to emit them on a [separate
-track](#tracks).
-
 You can also supply (up to two) debug annotations together with the event.
 
 ```C++
@@ -126,10 +99,9 @@
 TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
 ```
 
-See [below](#track-event-arguments) for the other types of supported track
-event arguments. For more complex arguments, you can define [your own
-protobuf messages](/protos/perfetto/trace/track_event/track_event.proto) and
-emit them as a parameter for the event.
+For more complex arguments, you can define [your own protobuf
+messages](/protos/perfetto/trace/track_event/track_event.proto) and emit
+them as a parameter for the event.
 
 NOTE: Currently custom protobuf messages need to be added directly to the
       Perfetto repository under `protos/perfetto/trace`, and Perfetto itself
@@ -321,122 +293,6 @@
 
 ## Advanced topics
 
-### Track event arguments
-
-The following optional arguments can be passed to `TRACE_EVENT` to add extra
-information to events:
-
-```C++
-TRACE_EVENT("cat", "name"[, track][, timestamp]
-    (, "debug_name", debug_value |, TrackEvent::kFieldName, value)*
-    [, lambda]);
-```
-
-Some examples of valid combinations:
-
-1. A lambda for writing custom TrackEvent fields:
-
-   ```C++
-     TRACE_EVENT("category", "Name", [&](perfetto::EventContext ctx) {
-       ctx.event()->set_custom_value(...);
-     });
-   ```
-
-2. A timestamp and a lambda:
-
-   ```C++
-     TRACE_EVENT("category", "Name", time_in_nanoseconds,
-         [&](perfetto::EventContext ctx) {
-       ctx.event()->set_custom_value(...);
-     });
-   ```
-
-   |time_in_nanoseconds| should be an uint64_t by default. To support custom
-   timestamp types,
-   |perfetto::TraceTimestampTraits<MyTimestamp>::ConvertTimestampToTraceTimeNs|
-   should be defined. See |ConvertTimestampToTraceTimeNs| for more details.
-
-3. Arbitrary number of debug annotations:
-
-   ```C++
-     TRACE_EVENT("category", "Name", "arg", value);
-     TRACE_EVENT("category", "Name", "arg", value, "arg2", value2);
-     TRACE_EVENT("category", "Name", "arg", value, "arg2", value2,
-                 "arg3", value3);
-   ```
-
-   See |TracedValue| for recording custom types as debug annotations.
-
-4. Arbitrary number of TrackEvent fields (including extensions):
-
-  ```C++
-    TRACE_EVENT("category", "Name",
-                perfetto::protos::pbzero::TrackEvent::kFieldName, value);
-  ```
-
-5. Arbitrary combination of debug annotations and TrackEvent fields:
-
-  ```C++
-    TRACE_EVENT("category", "Name",
-                perfetto::protos::pbzero::TrackEvent::kFieldName, value1,
-                "arg", value2);
-  ```
-
-6. Arbitrary combination of debug annotations / TrackEvent fields and a lambda:
-
-   ```C++
-     TRACE_EVENT("category", "Name", "arg", value1,
-                 pbzero::TrackEvent::kFieldName, value2,
-                 [&](perfetto::EventContext ctx) {
-                     ctx.event()->set_custom_value(...);
-                 });
-   ```
-
-7. An overridden track:
-
-   ```C++
-     TRACE_EVENT("category", "Name", perfetto::Track(1234));
-   ```
-
-   See |Track| for other types of tracks which may be used.
-
-8. A track and a lambda:
-
-   ```C++
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 [&](perfetto::EventContext ctx) {
-                     ctx.event()->set_custom_value(...);
-                 });
-   ```
-
-9. A track and a timestamp:
-
-   ```C++
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 time_in_nanoseconds);
-   ```
-
-10. A track, a timestamp and a lambda:
-
-   ```C++
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 time_in_nanoseconds, [&](perfetto::EventContext ctx) {
-                     ctx.event()->set_custom_value(...);
-                 });
-   ```
-
-11. A track and any combination of debug annotions and TrackEvent fields:
-
-   ```C++
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 "arg", value);
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 "arg", value, "arg2", value2);
-     TRACE_EVENT("category", "Name", perfetto::Track(1234),
-                 "arg", value, "arg2", value2,
-                 pbzero::TrackEvent::kFieldName, value3);
-   ```
-
 ### Tracks
 
 Every track event is associated with a track, which specifies the timeline
@@ -509,54 +365,6 @@
 perfetto::TrackEvent::EraseTrackDescriptor(track);
 ```
 
-### Counters
-
-Time-varying numeric data can be recorded with the `TRACE_COUNTER` macro:
-
-```C++
-TRACE_COUNTER("category", "MyCounter", 1234.5);
-```
-
-This data is displayed as a counter track in the Perfetto UI:
-
-![A counter track shown in the Perfetto UI](
-  /docs/images/counter-events.png "A counter track shown in the Perfetto UI")
-
-Both integer and floating point counter values are supported. Counters can
-also be annotated with additional information such as units, for example, for
-tracking the rendering framerate in terms of frames per second or "fps":
-
-```C++
-TRACE_COUNTER("category", perfetto::CounterTrack("Framerate", "fps"), 120);
-```
-
-As another example, a memory counter that records bytes but accepts samples
-as kilobytes (to reduce trace binary size) can be defined like this:
-
-```C++
-perfetto::CounterTrack memory_track = perfetto::CounterTrack("Memory")
-    .set_unit("bytes")
-    .set_multiplier(1024);
-TRACE_COUNTER("category", memory_track, 4 /* = 4096 bytes */);
-```
-
-See
-[counter_descriptor.proto](
-/protos/perfetto/trace/track_event/counter_descriptor.proto) for the full set
-of attributes for a counter track.
-
-To record a counter value at a specific point in time (instead of the current
-time), you can pass in a custom timestamp:
-
-```C++
-// First record the current time and counter value.
-uint64_t timestamp = perfetto::TrackEvent::GetTraceTimeNs();
-int64_t value = 1234;
-
-// Later, emit a sample at that point in time.
-TRACE_COUNTER("category", "MyCounter", timestamp, value);
-```
-
 ### Interning
 
 Interning can be used to avoid repeating the same constant data (e.g., event
@@ -602,62 +410,4 @@
 Note that interned data is strongly typed, i.e., each class of interned data
 uses a separate namespace for identifiers.
 
-### Tracing session observers
-
-The session observer interface allows applications to be notified when track
-event tracing starts and stops:
-
-```C++
-class Observer : public perfetto::TrackEventSessionObserver {
-  public:
-  ~Observer() override = default;
-
-  void OnSetup(const perfetto::DataSourceBase::SetupArgs&) override {
-    // Called when tracing session is configured. Note tracing isn't active yet,
-    // so track events emitted here won't be recorded.
-  }
-
-  void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
-    // Called when a tracing session is started. It is possible to emit track
-    // events from this callback.
-  }
-
-  void OnStop(const perfetto::DataSourceBase::StopArgs&) override {
-    // Called when a tracing session is stopped. It is still possible to emit
-    // track events from this callback.
-  }
-};
-```
-
-Note that all methods of the interface are called on an internal Perfetto
-thread.
-
-For example, here's how to wait for any tracing session to start:
-
-```C++
-class Observer : public perfetto::TrackEventSessionObserver {
- public:
-  Observer() { perfetto::TrackEvent::AddSessionObserver(this); }
-  ~Observer() { perfetto::TrackEvent::RemoveSessionObserver(this); }
-
-  void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.notify_one();
-  }
-
-  void WaitForTracingStart() {
-    printf("Waiting for tracing to start...\n");
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [] { return perfetto::TrackEvent::IsEnabled(); });
-    printf("Tracing started\n");
-  }
-
-  std::mutex mutex;
-  std::condition_variable cv;
-};
-
-Observer observer;
-observer.WaitForTracingToStart();
-```
-
 [RAII]: https://en.cppreference.com/w/cpp/language/raii
diff --git a/docs/quickstart/android-tracing.md b/docs/quickstart/android-tracing.md
index 2c65d30..b48973c 100644
--- a/docs/quickstart/android-tracing.md
+++ b/docs/quickstart/android-tracing.md
@@ -1,114 +1,63 @@
 # Quickstart: Record traces on Android
 
-Perfetto allows you to collect system-wide performance traces from Android
+`perfetto` allows you to collect system-wide performance traces from Android
 devices from a variety of data sources (kernel scheduler via ftrace, userspace
 instrumentation via atrace and all other data sources listed in this site).
 
 ## Starting the tracing services
 
-Perfetto is based on [platform services](/docs/concepts/service-model.md)
-that are avilable since Android 9 (P) but are enabled by default only since
-Android 11 (R).
-On Android 9 (P) and 10 (Q) you need to do the following to ensure that the
-tracing services are enabled before getting started:
+Due to Perfetto's [service-based architecture](/docs/concepts/service-model.md)
+, the `traced` and `traced_probes` services need to be running to record traces.
+
+These services are shipped on Android system images by default since Android 9
+(Pie) but are not always enabled by default.
+On Android 9 (P) and 10 (Q) those services are enabled by default only on Pixel
+phones and must be manually enabled on other phones.
+Since Android 11 (R), perfetto services are enabled by default on most devices.
+
+To enable perfetto services run:
 
 ```bash
-# Needed only on Android 9 (P) and 10 (Q) on non-Pixel phones.
+# Will start both traced and traced_probes.
 adb shell setprop persist.traced.enable 1
 ```
 
 ## Recording a trace
 
-Command line tools (usage examples below in this page):
-
-* Using the [`tools/record_android_trace`](/tools/record_android_trace) helper script.
-* Using directly the `/system/bin/perfetto` command on device [[reference](/docs/reference/perfetto-cli.md)].
-
-UI tools:
+You can collect a trace in the following ways:
 
 * Through the record page in the [Perfetto UI](https://ui.perfetto.dev).
-* Using the on-device [System Tracing App](https://developer.android.com/topic/performance/tracing/on-device)
+* Using the `perfetto` command line interface [[reference](/docs/reference/perfetto-cli.md)].
 
-### Recording a trace through the Perfetto UI
+### Perfetto UI
 
-Navigate to [ui.perfetto.dev](https://ui.perfetto.dev/#!/record) and select
-**Record new trace** from the left menu.
-From this page, select and turn on the data sources you want to include in the
-trace. More detail about the different data sources can be found in the
+Navigate to ui.perfetto.dev and select **Record new trace**.
+
+From this page, select and turn on the data sources you want to include in the trace. More detail about the different data sources can be found in the
 _Data sources_ section of the docs.
 
 ![Record page of the Perfetto UI](/docs/images/record-trace.png)
 
 If you are unsure, start by turning on **Scheduling details** under the **CPU** tab.
 
-Ensure your device is connected and select **Add ADB device**. Once your device
-has successfully paired (you may need to allow USB debugging on the device), select the **Start Recording** button.
+Ensure your device is connected and select **Add ADB device**. Once your device has successfully paired (you may need to allow USB debugging on the device), select the **Start Recording** button.
 
-Allow time for the trace to be collected (10s by default) and then you should
-see the trace appear.
+Allow time for the trace to be collected (10s by default) and then you should see the trace appear.
 
 ![Perfetto UI with a trace loaded](/docs/images/trace-view.png)
 
 Your trace may look different depending on which data sources you enabled.
 
-### Recording a trace through the cmdline
+### Perfetto cmdline
 
-**Prerequisites**
+#### Short syntax
 
-For the cmdline based workflow you will need the `adb` (Android Debug Bridge)
-executable to be in your PATH. ADB binaries for Linux, Mac or Windows can be
-downloaded from https://developer.android.com/studio/releases/platform-tools .
-
-**Using the helper script**
-
-We suggest using the `tools/record_android_trace` script to record traces from
-the command line. It is the equivalent of running `adb shell perfetto` but it
-helps with getting the paths right, auto-pulling the trace once done and opening
-it on the browser.
-
-If you are already familiar with `systrace` or `atrace`, both cmdline tools
-support a systrace-equivalent syntax:
-
-On Linux and Mac:
+If you are already familiar with `systrace` or `atrace`, there is an equivalent syntax with `perfetto`:
 
 ```bash
-curl -O https://raw.githubusercontent.com/google/perfetto/master/tools/record_android_trace
-chmod u+x record_android_trace
-
-# See ./record_android_trace --help for more
-./record_android_trace -o trace_file.perfetto-trace -t 10s -b 32mb sched gfx wm
+adb shell perfetto -o mytrace.pftrace -t 20s sched freq idle am wm gfx view
 ```
 
-On Windows:
-
-```bash
-curl -O https://raw.githubusercontent.com/google/perfetto/master/tools/record_android_trace
-python3 record_android_trace -o trace_file.perfetto-trace -t 10s -b 32mb sched gfx wm
-```
-
-**Using the on-device /system/bin/perfetto command**
-
-Or, if you want to use directly the on-device binary do instead:
-
-```bash
-adb shell perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace -t 20s sched freq idle am wm gfx view
-```
-
-Caveats when using directly the `adb shell perfetto` workflow:
-
-* Ctrl+C, which normally causes a graceful termination of the trace, is not
-  propagated by ADB when using `adb shell perfetto` but only when using an
-  interactive PTY-based session via `adb shell`.
-* On non-rooted devices before Android 12, the config can only be passed as
-  `cat config | adb shell perfetto -c -` (-: stdin) because of over-restrictive
-  SELinux rules. Since Android 12 `/data/misc/perfetto-configs` can be used for
-  storing configs.
-* On devices before Android 10, adb cannot directly pull
-  `/data/misc/perfetto-traces`. Use
-  `adb shell cat /data/misc/perfetto-traces/trace > trace` to work around.
-* When capturing longer traces, e.g. in the context of benchmarks or CI, use
-  `PID=$(perfetto --background)` and then `kill $PID` to stop.
-
 #### Full trace config
 
 The short syntax allows to enable only a subset of the data sources; for full
@@ -127,7 +76,10 @@
 [_Trace configuration_ page](https://perfetto.dev/docs/concepts/config#pbtx-vs-binary-format).
 
 ```bash
-cat<<EOF>config.pbtx
+adb shell perfetto \
+  -c - --txt \
+  -o /data/misc/perfetto-traces/trace \
+<<EOF
 duration_ms: 10000
 
 buffers: {
@@ -167,36 +119,30 @@
         }
     }
 }
+
 EOF
-
-./record_android_trace -c config.pbtx -o trace_file.perfetto-trace 
 ```
 
-Or alternatively, when using directly the on-device command:
-
+In all other cases, first push the trace config file and then invoke perfetto:
 ```bash
-cat config.pbtx | adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace.perfetto-trace
+adb push config.txt /data/local/tmp/trace_config.txt
+adb shell 'perfetto --txt -c - -o /data/misc/perfetto-traces/trace < /data/local/tmp/trace_config.txt'
 ```
 
-Alternatively, first push the trace config file and then invoke perfetto:
+NOTE: because of strict SELinux rules, on versions of older than Android 11
+(R) passing directly the file path as `-c /data/local/tmp/config` might fail,
+hence the `-c -` + stdin piping above.
 
-```bash
-adb push config.pbtx /data/local/tmp/config.pbtx
-adb shell 'cat /data/local/tmp/config.pbtx | perfetto --txt -c - -o /data/misc/perfetto-traces/trace.perfetto-trace'
-```
-
-NOTE: because of strict SELinux rules, on non-rooted builds of Android, passing
-directly the file path as `-c /data/local/tmp/config` will fail, hence the
-`-c -` + stdin piping above. From Android 12 (S), `/data/misc/perfetto-configs/`
-can be used instead.
-
-Pull the file using `adb pull /data/misc/perfetto-traces/trace ~/trace.perfetto-trace`
-and open it in the [Perfetto UI](https://ui.perfetto.dev).
-
-NOTE: On devices before Android 10, adb cannot directly pull
-      `/data/misc/perfetto-traces`. Use
-       `adb shell cat /data/misc/perfetto-traces/trace > trace.perfetto-trace`
-       to work around.
+Pull the file using `adb pull /data/misc/perfetto-traces/trace ~/trace.pftrace`
+and upload to the [Perfetto UI](https://ui.perfetto.dev).
 
 The full reference for the `perfetto` cmdline interface can be found
 [here](/docs/reference/perfetto-cli.md).
+
+## On-device System Tracing app
+
+Since Android 9 (P) it's possible to collect a trace directly from the device
+using the System Tracing app, from Developer Settings.
+
+See https://developer.android.com/topic/performance/tracing/on-device for
+instructions.
diff --git a/docs/quickstart/heap-profiling.md b/docs/quickstart/heap-profiling.md
index 6f9692f..6e9bb26 100644
--- a/docs/quickstart/heap-profiling.md
+++ b/docs/quickstart/heap-profiling.md
@@ -2,7 +2,7 @@
 
 ## Prerequisites
 
-* [ADB](https://developer.android.com/studio/command-line/adb) installed.
+* A host running macOS or Linux.
 * A device running Android 10+.
 * A _Profileable_ or _Debuggable_ app. If you are running on a _"user"_ build of
   Android (as opposed to _"userdebug"_ or _"eng"_), your app needs to be marked
@@ -13,54 +13,20 @@
 
 ## Capture a heap profile
 
-### Linux / macOS
-Make sure adb is installed and in your PATH.
-
-```bash
-adb devices -l
-```
-
-If more than one device or emulator is reported you must select one upfront as follows:
-
-```bash
-export ANDROID_SERIAL=SER123456
-```
-
-Download the `tools/heap_profile` (if you don't have a perfetto checkout):
+Download the `tools/heap_profile` (if you don't have a perfetto checkout) and
+run it as follows:
 
 ```bash
 curl -LO https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile
 chmod +x heap_profile
-```
 
-Then start the profile:
-
-```bash
 ./heap_profile -n system_server
-```
 
-### Windows
+Profiling active. Press Ctrl+C to terminate.
+You may disconnect your device.
 
-Make sure that the downloaded adb.exe is in the PATH.
-
-```bash
-set PATH=%PATH%;%USERPROFILE%\Downloads\platform-tools
-
-adb devices -l
-```
-
-If more than one device or emulator is reported you must select one upfront as follows:
-
-```bash
-set ANDROID_SERIAL=SER123456
-```
-
-Download the
-[heap_profile](https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile)
-script. Then start the profile:
-
-```bash
-python /path/to/heap_profile -n system_server 
+Wrote profiles to /tmp/profile-1283e247-2170-4f92-8181-683763e17445 (symlink /tmp/heap_profile-latest)
+These can be viewed using pprof. Googlers: head to pprof/ and upload them.
 ```
 
 ## View profile
diff --git a/docs/quickstart/trace-analysis.md b/docs/quickstart/trace-analysis.md
index 7141394..427f68b 100644
--- a/docs/quickstart/trace-analysis.md
+++ b/docs/quickstart/trace-analysis.md
@@ -1,43 +1,32 @@
 # Quickstart: SQL-based analysis and trace-based metrics
 
-_This quickstart explains how to use `trace_processor` as well as its Python API to 
-programmatically query the trace contents through SQL and compute trace-based metrics._
+_This quickstart explains how to use `trace_processor` to programmatically query
+the trace contents through SQL and compute trace-based metrics._
 
-## Trace Processor
+## Get Trace Processor
 
 TraceProcessor is a multi-format trace importing and query engine based on
 SQLite. It comes both as a C++ library and as a standalone executable:
 `trace_processor_shell` (or just `trace_processor`).
 
-### Setup
-
 ```bash
 # Download prebuilts (Linux and Mac only)
 curl -LO https://get.perfetto.dev/trace_processor
 chmod +x ./trace_processor
 
 # Start the interactive shell
-./trace_processor trace.perfetto-trace
-
-# Start a local trace processor instance to replace wasm module in the UI
-./trace_processor trace.perfetto-trace --http
+./trace_processor trace.pftrace
 ```
 
-NOTE: In HTTP mode the trace will be loaded into the `trace_processor` and
-      the UI will connect and issue queries over TCP. This can allow
-      arbitrary sized traces to be loaded since there are no memory
-      constraints, unlike the WASM module. In addition, this can improve
-      performance in the UI as it issues SQL queries.
-
 See [Trace Processor docs](/docs/analysis/trace-processor.md) for the full
 TraceProcessor guide.
 
-### Sample queries
+## Sample queries
 
 For more exhaustive examples see the _SQL_ section of the various _Data sources_
 docs.
 
-#### Slices
+### Slices
 
 Slices are stackable events which have name and span some duration of time.
 
@@ -55,7 +44,7 @@
      ...
 ```
 
-#### Counters
+### Counters
 
 Counters are events with a value which changes over time.
 
@@ -74,7 +63,7 @@
 ...
 ```
 
-#### Scheduler slices
+### Scheduler slices
 
 Scheduler slices indicate which thread was scheduled on which CPU at which time.
 
@@ -92,12 +81,12 @@
 ...
 ```
 
-### Trace-based metrics
+## Trace-based metrics
 
 Trace Processor offers also a higher-level query interface that allows to run
 pre-baked queries, herein called "metrics". Metrics are generally curated by
 domain experts, often the same people who add the instrumentation points in the
-first place, and output structured JSON/Protobuf/text.
+first lace, and output structured JSON/Protobuf/text.
 Metrics allow to get a summarized view of the trace without having to type any
 SQL or having to load the trace in the UI.
 
@@ -106,7 +95,7 @@
 The corresponding SQL queries live in
 [/src/trace_processor/metrics](/src/trace_processor/metrics/).
 
-#### Run a single metric
+### Run a single metric
 
 Let's run the [`android_cpu`](/protos/perfetto/metrics/android/cpu_metric.proto)
 metric. This metrics computes the total CPU time and the total cycles
@@ -114,7 +103,7 @@
 trace, breaking it down by CPU (_core_) number.
 
 ```protobuf
-./trace_processor --run-metrics android_cpu trace.perfetto-trace
+./trace_processor --run-metrics android_cpu trace.pftrace
 
 android_cpu {
   process_info {
@@ -177,14 +166,14 @@
 }
 ```
 
-#### Running multiple metrics
+### Running multiple metrics
 
 Multiple metrics can be flagged using comma separators to the `--run-metrics`
 flag. This will output a text proto with the combined result of running both
 metrics.
 
 ```protobuf
-$ ./trace_processor --run-metrics android_mem,android_cpu trace.perfetto-trace
+$ ./trace_processor --run-metrics android_mem,android_cpu trace.pftrace
 
 android_mem {
   process_metrics {
@@ -238,7 +227,7 @@
 }
 ```
 
-#### JSON and binary output
+### JSON and binary output
 
 The trace processor also supports binary protobuf and JSON as alternative output
 formats. This is useful when the intended reader is an offline tool.
@@ -246,10 +235,10 @@
 Both single and multiple metrics are supported as with proto text output.
 
 ```
-./trace_processor --run-metrics android_mem --metrics-output=binary trace.perfetto-trace
+./trace_processor --run-metrics android_mem --metrics-output=binary trace.pftrace
 <binary protobuf output>
 
-./trace_processor --run-metrics android_mem,android_cpu --metrics-output=json trace.perfetto-trace
+./trace_processor --run-metrics android_mem,android_cpu --metrics-output=json trace.pftrace
 {
   "android_mem": {
     "process_metrics": [
@@ -315,105 +304,6 @@
 }
 ```
 
-## Python API
-
-The API can be run without requiring the `trace_processor` binary to be
-downloaded or installed.
-
-### Setup
-```
-$ pip install perfetto
-```
-NOTE: The API is only compatible with Python3.
-
-### Example functions
-See the Python API section of
-[Trace Processor (SQL)](/docs/analysis/trace-processor.md) to get
-more details on all available functions.
-
-#### Query
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-qr_it = tp.query('SELECT name FROM slice')
-for row in qr_it:
-  print(row.name)
-```
-**Output**
-```
-eglSwapBuffersWithDamageKHR
-onMessageReceived
-queueBuffer
-bufferLoad
-query
-...
-```
-#### Query as Pandas DataFrame
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-qr_it = tp.query('SELECT ts, name FROM slice')
-qr_df = qr_it.as_pandas_dataframe()
-print(qr_df.to_string())
-```
-**Output**
-```
-ts                   name
--------------------- ---------------------------
-     261187017446933 eglSwapBuffersWithDamageKHR
-     261187017518340 onMessageReceived
-     261187020825163 queueBuffer
-     261187021345235 bufferLoad
-     261187121345235 query
-     ...
-```
-#### Metric
-```python
-from perfetto.trace_processor import TraceProcessor
-tp = TraceProcessor(file_path='trace.perfetto-trace')
-
-cpu_metrics = tp.metric(['android_cpu'])
-print(cpu_metrics)
-```
-**Output**
-```
-metrics {
-  android_cpu {
-    process_info {
-      name: "/system/bin/init"
-      threads {
-        name: "init"
-        core {
-          id: 1
-          metrics {
-            mcycles: 1
-            runtime_ns: 570365
-            min_freq_khz: 1900800
-            max_freq_khz: 1900800
-            avg_freq_khz: 1902017
-          }
-        }
-        core {
-          id: 3
-          metrics {
-            mcycles: 0
-            runtime_ns: 366406
-            min_freq_khz: 1900800
-            max_freq_khz: 1900800
-            avg_freq_khz: 1902908
-          }
-        }
-        ...
-      }
-      ...
-    }
-    ...
-  }
-}
-```
-
 ## Next steps
 
 There are several options for exploring more of the trace analysis features
diff --git a/docs/reference/checkpoint-atoms.md b/docs/reference/checkpoint-atoms.md
deleted file mode 100644
index a00ebfd..0000000
--- a/docs/reference/checkpoint-atoms.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# Statsd Checkpoint Atoms
-## Tracing
-
-This diagram gives the atoms and the state transitions between when tracing/
-All atoms above log the UUID of the trace;
-`PERFETTO_TRACED_TRIGGER_STOP_TRACING` is special as it *also* logs the trigger
-name which caused trace finalization.
-
-NOTE: dotted lines indicate these transitions only happen in background
-configs; transitions with solid lines happen in both background and
-non-background cases.
-
-NOTE: for background traces, *either* start triggers or stop triggers are
-supported; both cannot happen for the same trace.
-
-```mermaid
-graph TD;
-    PERFETTO_CMD_TRACE_BEGIN-->PERFETTO_CMD_ON_CONNECT;
-    PERFETTO_CMD_BACKGROUND_TRACE_BEGIN-.->PERFETTO_CMD_ON_CONNECT
-    PERFETTO_CMD_ON_CONNECT-->PERFETTO_TRACED_ENABLE_TRACING
-    PERFETTO_TRACED_ENABLE_TRACING-->PERFETTO_TRACED_START_TRACING
-    PERFETTO_TRACED_ENABLE_TRACING-.->|start trigger background traces only|PERFETTO_TRACED_TRIGGER_START_TRACING
-    PERFETTO_TRACED_TRIGGER_START_TRACING-.->PERFETTO_TRACED_START_TRACING
-    PERFETTO_TRACED_START_TRACING-.->|stop trigger background traces only|PERFETTO_TRACED_TRIGGER_STOP_TRACING
-    PERFETTO_TRACED_TRIGGER_STOP_TRACING-.->PERFETTO_TRACED_DISABLE_TRACING
-    PERFETTO_TRACED_START_TRACING-->PERFETTO_TRACED_DISABLE_TRACING
-    PERFETTO_TRACED_DISABLE_TRACING-->PERFETTO_TRACED_NOTIFY_TRACING_DISABLED
-    PERFETTO_TRACED_NOTIFY_TRACING_DISABLED-->PERFETTO_CMD_ON_TRACING_DISABLED
-    PERFETTO_CMD_ON_TRACING_DISABLED-->PERFETTO_CMD_FINALIZE_TRACE_AND_EXIT
-    PERFETTO_CMD_FINALIZE_TRACE_AND_EXIT-->PERFETTO_CMD_UPLOAD_INCIDENT
-    PERFETTO_CMD_FINALIZE_TRACE_AND_EXIT-.->|only if no trigger happened|PERFETTO_CMD_NOT_UPLOADING_EMPTY_TRACE
-```
-
-## Triggers
-
-This diagram gives the atoms which can trigger finalization of a trace. 
-These atoms will not be reported individually but instead aggregated by trigger name
-and reported as a count.
-
-```mermaid
-graph TD;
-    PERFETTO_CMD_TRIGGER
-    PERFETTO_TRIGGER_PERFETTO_TRIGGER
-```
-
diff --git a/docs/reference/perfetto-cli.md b/docs/reference/perfetto-cli.md
index f0771d6..d101dee 100644
--- a/docs/reference/perfetto-cli.md
+++ b/docs/reference/perfetto-cli.md
@@ -37,7 +37,7 @@
 
 <pre class="none">
  adb shell perfetto [ --time <var>TIMESPEC</var> ] [ --buffer <var>SIZE</var> ] [ --size <var>SIZE</var> ]
-           [ <var>ATRACE_CAT</var> | <var>FTRACE_GROUP/FTRACE_NAME</var>]...
+           [ <var>ATRACE_CAT</var> | <var>FTRACE_GROUP/FTRACE_NAME</var> | <var>FTRACE_GROUP/*</var> ]...
 </pre>
 
 
@@ -57,6 +57,7 @@
 |--- |--- |
 |`ATRACE_CAT`|Specifies the atrace categories you want to record a trace for. For example, the following command traces Window Manager using atrace: `adb shell perfetto --out FILE wm`. To record other categories, see this [list of atrace categories](https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-q-preview-5/cmds/atrace/atrace.cpp#100).|
 |`FTRACE_GROUP/FTRACE_NAME`|Specifies the ftrace events you want to record a trace for. For example, the following command traces sched/sched_switch events: `adb shell perfetto --out FILE sched/sched_switch`|
+|`FTRACE_GROUP/*`|Record all events in group (e.g. sched/\*). Specifies the group of ftrace events you want to record a trace for. For example, the following command traces sched/\* events: `adb shell perfetto --out FILE 'sched/*'`|
 
 
 ## Normal mode
diff --git a/docs/run-dev-server b/docs/run-dev-server
deleted file mode 100755
index f5bc3c4..0000000
--- a/docs/run-dev-server
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 -eu
-CUR_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$CUR_DIR/../infra/perfetto.dev/run-dev-server
diff --git a/docs/toc.md b/docs/toc.md
index 15c1cae..03c2ad7 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -24,12 +24,10 @@
   * [Android system](#)
     * [Atrace instrumentation](data-sources/atrace.md)
     * [Android log (logcat)](data-sources/android-log.md)
-    * [Android Janks](data-sources/frametimeline.md)
 
 * [App Instrumentation](#)
   * [Tracing SDK](instrumentation/tracing-sdk.md)
   * [Track events](instrumentation/track-events.md)
-  * [Interceptors](instrumentation/interceptors.md)
 
 * [Trace analysis](#)
   * [Trace Processor (SQL)](analysis/trace-processor.md)
@@ -37,10 +35,6 @@
   * [SQL tables](analysis/sql-tables.autogen)
   * [Stats table](analysis/sql-stats.autogen)
 
-* [Trace visualization](#)
-  * [Perfetto UI](visualization/perfetto-ui.md)
-  * [Visualising large traces](visualization/large-traces.md)
-
 * [Core concepts](#)
   * [Trace configuration](concepts/config.md)
   * [Buffers and dataflow](concepts/buffers.md)
@@ -61,13 +55,11 @@
     * [Common tasks](contributing/common-tasks.md)
     * [Embedding Perfetto](contributing/embedding.md)
     * [Releasing the SDK](contributing/sdk-releasing.md)
-    * [Chrome branches](contributing/chrome-branches.md)
 
 * [Design documents](#)
     * [API and ABI surface](design-docs/api-and-abi.md)
     * [Heapprofd design](design-docs/heapprofd-design.md)
     * [Heapprofd wire protocol](design-docs/heapprofd-wire-protocol.md)
-    * [Heapprofd sampling](design-docs/heapprofd-sampling.md)
     * [Life of a tracing session](design-docs/life-of-a-tracing-session.md)
     * [Perfetto CI](design-docs/continuous-integration.md)
     * [ProtoZero](design-docs/protozero.md)
diff --git a/docs/visualization/large-traces.md b/docs/visualization/large-traces.md
deleted file mode 100644
index f4e40d5..0000000
--- a/docs/visualization/large-traces.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Visualising large traces
-
-Browsers often limit the amount of memory a site can use.
-This can cause problems when visualising large traces.
-
-## How to visualise large traces using the Perfetto UI
-
-Perfetto UI has support for a mode where the processing of the trace
-is offloaded to a 'server' instance of `trace_processor` running natively on your local machine.
-This server process can take full advantage of the RAM of your machine as well as running at full native (rather than WASM) performance.
-
-```
-curl -LO https://get.perfetto.dev/trace_processor
-chmod +x ./trace_processor
-trace_processor --httpd /path/to/trace.pftrace
-# Navigate to http://ui.perfetto.dev, it will prompt to use the HTTP+RPC interface
-```
-
-## How big is too big?
-
-The exact memory limit can vary by browser, architecture, and OS however 2gb is typical.
-This limit is a limit on the total memory used at runtime, not on the binary size of the trace.
-The `trace_processor` (and hence the UI) representation of a trace at runtime is normally larger than the binary size of that trace.
-This is because the representation is optimized for query performance rather than size.
-The exact inflation factor varies depending on the trace format but can be 2-4x for uncompressed proto traces.
-
-
diff --git a/docs/visualization/perfetto-ui.md b/docs/visualization/perfetto-ui.md
deleted file mode 100644
index 426f2dc..0000000
--- a/docs/visualization/perfetto-ui.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Perfetto UI
-
-[Perfetto UI](https://ui.perfetto.dev) enables you to view and analyze traces in
-the browser. It supports several different tracing formats, including the
-perfetto proto trace format and the legacy json trace format.
-
-## UI Tips and Tricks
-
-### Debug Slices
-
-Sometimes you may want to insert some fake slices into the timeline to help
-with your understanding of the data. You can do so by inserting rows into a
-magic `debug_slices` table.
-
-`debug_slices` table has five columns:
-
-* `id` (integer) [optional] If present, Perfetto UI will use it as slice id to
-  open the details panel when you click on the slices.
-* `name` (string) [optional] The displayed slice title.
-* `ts` (integer) [required] Start of the slice, in nanoseconds.
-* `dur` (integer) [required] Duration of the slice, in nanoseconds. Determines
-  slice width.
-* `depth` (integer) [optional] The row at which the slice is drawn. Depth 0 is
-  the first row.
-
-You can open the debug track by going to the "Sample queries" menu on the
-left, and clicking "Show Debug Track". A debug slice track will become pinned to
-the top and will initially be empty. After you insert slices in the
-`debug_slices` table, you can click the reload button on the track to refresh
-the information shown in that track.
-
-Here is a simple example with random slices to illustrate the use:
-
-```sql
-CREATE VIEW rand_slices AS SELECT * FROM SLICE
-  ORDER BY RANDOM() LIMIT 2000;
-
-INSERT INTO debug_slices(id, name, ts, dur, depth)
-  SELECT id, name, ts, dur, depth FROM RAND_SLICES;
-```
-
-After you click the reload button, you should see the slices in the debug track.
-
-![Example of debug slices](/docs/images/debug-slices-random.png)
-
-Once you're done, you can click the X button to hide the track, and you can
-clear the `debug_slices` table (`DELETE FROM debug_slices`) to clear the track.
-
-A more interesting example is seeing RAIL modes in chrome traces:
-
-```sql
-SELECT RUN_METRIC('chrome/rail_modes.sql');
-
--- Depth 0 is the unified RAIL Mode
-INSERT INTO debug_slices
-  SELECT NULL, rail_mode, ts, dur, 0 FROM combined_overall_rail_slices;
-
--- Depth 2+ are for each Renderer process with depth 1 left blank
-INSERT INTO debug_slices
-  SELECT NULL, short_name, ts, dur, depth + 1 FROM rail_mode_slices,
-    (SELECT track_id, row_number() OVER () AS depth FROM
-      (SELECT DISTINCT track_id FROM rail_mode_slices)) depth_map,
-    rail_modes
-  WHERE depth_map.track_id = rail_mode_slices.track_id
-    AND rail_mode=rail_modes.mode;
-```
-
-This produces a visualization like this:
-
-![RAIL modes in Debug Track](/docs/images/rail-mode-debug-slices.png)
-
-Note: There is no equivalent debug counters feature yet, but the feature request
-is tracked on [b/168886909](http://b/168886909)).
diff --git a/examples/sdk/CMakeLists.txt b/examples/sdk/CMakeLists.txt
index a2f74bd..fc13851 100644
--- a/examples/sdk/CMakeLists.txt
+++ b/examples/sdk/CMakeLists.txt
@@ -30,7 +30,6 @@
 add_executable(example_system_wide example_system_wide.cc
                trace_categories.cc)
 add_executable(example_custom_data_source example_custom_data_source.cc)
-add_executable(example_console example_console.cc trace_categories.cc)
 
 target_link_libraries(example perfetto
                       ${CMAKE_THREAD_LIBS_INIT})
@@ -38,34 +37,10 @@
                       ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries(example_custom_data_source perfetto
                       ${CMAKE_THREAD_LIBS_INIT})
-target_link_libraries(example_console perfetto
-                      ${CMAKE_THREAD_LIBS_INIT})
 
 # On Android we also need the logging library.
 if (ANDROID)
   target_link_libraries(example log)
   target_link_libraries(example_system_wide log)
   target_link_libraries(example_custom_data_source log)
-  target_link_libraries(example_console log)
-endif (ANDROID)
-
-if (WIN32)
-  # The perfetto library contains many symbols, so it needs the big object
-  # format.
-  target_compile_options(perfetto PRIVATE "/bigobj")
-  # Disable legacy features in windows.h.
-  add_definitions(-DWIN32_LEAN_AND_MEAN -DNOMINMAX)
-  # On Windows we should link to WinSock2.
-  target_link_libraries(example ws2_32)
-  target_link_libraries(example_system_wide ws2_32)
-  target_link_libraries(example_custom_data_source ws2_32)
-  target_link_libraries(example_console ws2_32)
-endif (WIN32)
-
-# Enable standards-compliant mode when using the Visual Studio compiler.
-if (MSVC)
-  target_compile_options(example PRIVATE "/permissive-")
-  target_compile_options(example_system_wide PRIVATE "/permissive-")
-  target_compile_options(example_custom_data_source PRIVATE "/permissive-")
-  target_compile_options(example_console PRIVATE "/permissive-")
-endif (MSVC)
\ No newline at end of file
+endif (ANDROID)
\ No newline at end of file
diff --git a/examples/sdk/README.md b/examples/sdk/README.md
index 3b8295f..bcd5180 100644
--- a/examples/sdk/README.md
+++ b/examples/sdk/README.md
@@ -15,7 +15,7 @@
 First, check out the latest Perfetto release:
 
 ```bash
-git clone https://android.googlesource.com/platform/external/perfetto -b v14.0
+git clone https://android.googlesource.com/platform/external/perfetto -b v4.1
 ```
 
 Then, build using CMake:
@@ -35,7 +35,7 @@
 build/example
 ```
 
-The program will create a trace file in `example.perfetto-trace`, which can be
+The program will create a trace file in `example.pftrace`, which can be
 directly opened in the [Perfetto UI](https://ui.perfetto.dev). The result
 should look like this:
 
@@ -75,18 +75,17 @@
          /data/local/tmp/
 adb shell "\
     cd /data/local/tmp; \
-    rm -f /data/misc/perfetto-traces/example_system_wide.perfetto-trace; \
+    rm -f /data/misc/perfetto-traces/example_system_wide.pftrace; \
     cat system_wide_trace_cfg.pbtxt | \
         perfetto --config - --txt --background \
-                 -o
-                 /data/misc/perfetto-traces/example_system_wide.perfetto-trace; \
+                 -o /data/misc/perfetto-traces/example_system_wide.pftrace; \
     ./example_system_wide"
 ```
 
 Finally, retrieve the resulting trace:
 
 ```bash
-adb pull /data/misc/perfetto-traces/example_system_wide.perfetto-trace
+adb pull /data/misc/perfetto-traces/example_system_wide.pftrace
 ```
 
 When opened in the Perfetto UI, the trace now shows additional contextual
@@ -110,12 +109,12 @@
 build/example_custom_data_source
 ```
 
-The program generates a trace file in `example_custom_data_source.perfetto-trace`,
+The program generates a trace file in `example_custom_data_source.pftrace`,
 which we can examine using Perfetto's `trace_to_text` tool to show the trace
 packet written by the custom data source:
 
 ```bash
-trace_to_text text example_custom_data_source.perfetto-trace
+trace_to_text text example_custom_data_source.pftrace
 ...
 packet {
   trusted_uid: 0
@@ -127,4 +126,4 @@
   }
 }
 ...
-```
+```
\ No newline at end of file
diff --git a/examples/sdk/example.cc b/examples/sdk/example.cc
index b282617..a1898d2 100644
--- a/examples/sdk/example.cc
+++ b/examples/sdk/example.cc
@@ -72,27 +72,15 @@
 }
 
 void DrawGame() {
-  // This is an example of an unscoped slice, which begins and ends at specific
-  // points (instead of at the end of the current block scope).
-  TRACE_EVENT_BEGIN("rendering", "DrawGame");
+  TRACE_EVENT("rendering", "DrawGame");
   DrawPlayer(1);
   DrawPlayer(2);
-  TRACE_EVENT_END("rendering");
-
-  // Record the rendering framerate as a counter sample.
-  TRACE_COUNTER("rendering", "Framerate", 120);
 }
 
 int main(int, const char**) {
   InitializePerfetto();
   auto tracing_session = StartTracing();
 
-  // Give a custom name for the traced process.
-  perfetto::ProcessTrack process_track = perfetto::ProcessTrack::Current();
-  perfetto::protos::gen::TrackDescriptor desc = process_track.Serialize();
-  desc.mutable_process()->set_process_name("Example");
-  perfetto::TrackEvent::SetTrackDescriptor(process_track, desc);
-
   // Simulate some work that emits trace events.
   DrawGame();
 
diff --git a/examples/sdk/example_console.cc b/examples/sdk/example_console.cc
deleted file mode 100644
index e7a9879..0000000
--- a/examples/sdk/example_console.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This example shows how to log trace events to the console using the console
-// interceptor.
-
-#include "trace_categories.h"
-
-#include <chrono>
-#include <thread>
-
-void InitializePerfetto() {
-  perfetto::TracingInitArgs args;
-  args.backends = perfetto::kInProcessBackend;
-  perfetto::Tracing::Initialize(args);
-  perfetto::TrackEvent::Register();
-  perfetto::ConsoleInterceptor::Register();
-}
-
-std::unique_ptr<perfetto::TracingSession> StartTracing() {
-  perfetto::TraceConfig cfg;
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-
-  // Enable the console interceptor.
-  ds_cfg->mutable_interceptor_config()->set_name("console");
-
-  auto tracing_session = perfetto::Tracing::NewTrace();
-  tracing_session->Setup(cfg);
-  tracing_session->StartBlocking();
-  return tracing_session;
-}
-
-void DrawPlayer(int player_number) {
-  TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
-  // Sleep to simulate a long computation.
-  std::this_thread::sleep_for(std::chrono::milliseconds(500));
-}
-
-void DrawGame() {
-  // This is an example of an unscoped slice, which begins and ends at specific
-  // points (instead of at the end of the current block scope).
-  TRACE_EVENT_BEGIN("rendering", "DrawGame");
-  DrawPlayer(1);
-  DrawPlayer(2);
-  TRACE_EVENT_END("rendering");
-}
-
-int main(int, const char**) {
-  InitializePerfetto();
-  auto tracing_session = StartTracing();
-
-  // Simulate some work that emits trace events.
-  DrawGame();
-
-  tracing_session->StopBlocking();
-  return 0;
-}
diff --git a/examples/sdk/example_system_wide.cc b/examples/sdk/example_system_wide.cc
index b7101de..f755d37 100644
--- a/examples/sdk/example_system_wide.cc
+++ b/examples/sdk/example_system_wide.cc
@@ -19,31 +19,9 @@
 #include "trace_categories.h"
 
 #include <chrono>
-#include <condition_variable>
 #include <fstream>
 #include <thread>
 
-class Observer : public perfetto::TrackEventSessionObserver {
- public:
-  Observer() { perfetto::TrackEvent::AddSessionObserver(this); }
-  ~Observer() { perfetto::TrackEvent::RemoveSessionObserver(this); }
-
-  void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.notify_one();
-  }
-
-  void WaitForTracingStart() {
-    PERFETTO_LOG("Waiting for tracing to start...");
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [] { return perfetto::TrackEvent::IsEnabled(); });
-    PERFETTO_LOG("Tracing started");
-  }
-
-  std::mutex mutex;
-  std::condition_variable cv;
-};
-
 void InitializePerfetto() {
   perfetto::TracingInitArgs args;
   // The backends determine where trace events are recorded. For this example we
@@ -55,6 +33,14 @@
   perfetto::TrackEvent::Register();
 }
 
+void WaitForTracingStart() {
+  PERFETTO_LOG("Waiting for tracing to start...");
+  while (!TRACE_EVENT_CATEGORY_ENABLED("rendering")) {
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+  }
+  PERFETTO_LOG("Tracing started");
+}
+
 void DrawPlayer(int player_number) {
   TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
   // Sleep to simulate a long computation.
@@ -69,9 +55,7 @@
 
 int main(int, const char**) {
   InitializePerfetto();
-
-  Observer observer;
-  observer.WaitForTracingStart();
+  WaitForTracingStart();
 
   // Simulate some work that emits trace events.
   // Note that we don't start and stop tracing here; for system-wide tracing
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 1f799ad..2041bbc 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -53,13 +53,18 @@
     perfetto_watchdog = "0"
   }
   if (enable_perfetto_tools) {
-    perfetto_local_symbolizer =
-        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || " +
-        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() ||" +
-        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN()"
+    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",
@@ -75,7 +80,7 @@
     "PERFETTO_VERSION_GEN=$enable_perfetto_version_gen",
     "PERFETTO_TP_PERCENTILE=$enable_perfetto_trace_processor_percentile",
     "PERFETTO_TP_LINENOISE=$enable_perfetto_trace_processor_linenoise",
-    "PERFETTO_TP_HTTPD=$enable_perfetto_trace_processor_httpd",
+    "PERFETTO_TP_HTTPD=$perfetto_tp_httpd",
     "PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
     "PERFETTO_LOCAL_SYMBOLIZER=$perfetto_local_symbolizer",
     "PERFETTO_ZLIB=$enable_perfetto_zlib",
@@ -95,7 +100,6 @@
 # All targets should depend on this target to inherit the right flags and
 # include directories.
 group("default_deps") {
-  visibility = [ "../*" ]  # Prevent chromium targets from depending on this (breaks component).
   public_configs = [ ":default_config" ]
   deps = [ ":gen_buildflags" ]
   if (perfetto_build_standalone) {
@@ -115,13 +119,9 @@
 # embedders that depend on perfetto (e.g. chrome). :public_config (see below) is
 # used for that.
 config("default_config") {
-  visibility = [ "../*" ]  # Prevent chromium targets from depending on this (breaks component).
   configs = [ ":public_config" ]
   defines = [ "PERFETTO_IMPLEMENTATION" ]
-  include_dirs = [
-    "..",
-    "../src/profiling/memory/include",
-  ]
+  include_dirs = [ ".." ]
 
   if (build_with_chromium && is_android) {
     # Included for __android_log_print
@@ -192,12 +192,10 @@
 
 # Full protobuf is just for host tools .No binary shipped on device should
 # depend on this.
-protobuf_full_deps_allowlist = [
+whitelisted_protobuf_full_deps = [
   "../src/ipc/protoc_plugin:*",
   "../src/protozero/protoc_plugin:*",
-  "../src/protozero/filtering:filter_util",
   "../src/trace_processor:trace_processor_shell",
-  "../src/protozero/filtering:filter_util",
   "../tools/*",
 ]
 
@@ -213,9 +211,10 @@
   libs = [ "protobuf" ]  # This will link against libprotobuf.so
 }
 
-# protoc compiler library, it's used for building protoc plugins.
+# 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 = protobuf_full_deps_allowlist
+  visibility = whitelisted_protobuf_full_deps
   if (current_toolchain == host_toolchain) {
     if (perfetto_use_system_protobuf) {
       public_configs = [
@@ -230,11 +229,13 @@
 }
 
 group("protobuf_full") {
-  visibility = protobuf_full_deps_allowlist
-  if (perfetto_use_system_protobuf) {
-    public_configs = [ ":system_protobuf" ]
-  } else {
-    public_deps = [ "${perfetto_protobuf_target_prefix}:protobuf_full" ]
+  visibility = whitelisted_protobuf_full_deps
+  if (current_toolchain == host_toolchain) {
+    if (perfetto_use_system_protobuf) {
+      public_configs = [ ":system_protobuf" ]
+    } else {
+      public_deps = [ "${perfetto_protobuf_target_prefix}:protobuf_full" ]
+    }
   }
 }
 
@@ -259,33 +260,19 @@
     "GOOGLE_PROTOBUF_NO_RTTI",
     "GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
   ]
-  cflags = []
-  if (is_clang || !is_win) {
-    cflags += [
-      "-Wno-unknown-warning-option",
-      "-Wno-deprecated",
-      "-Wno-undef",
-      "-Wno-zero-as-null-pointer-constant",
-    ]
-  }
-  if (is_clang && is_win) {
-    cflags += [
-      "-Wno-reserved-id-macro",
-      "-Wno-language-extension-token",
-      "-Wno-sign-conversion",
-      "-Wno-suggest-destructor-override",
-      "-Wno-undefined-reinterpret-cast",
-      "-Wno-inconsistent-missing-destructor-override",
-      "-Wno-unused-parameter",
-    ]
-  }
+  cflags = [
+    "-Wno-unknown-warning-option",
+    "-Wno-deprecated",
+    "-Wno-undef",
+    "-Wno-zero-as-null-pointer-constant",
+  ]
 
   if (!perfetto_use_system_protobuf) {
     cflags += [
       # Using -isystem instead of include_dirs (-I), so we don't need to
       # suppress warnings coming from libprotobuf headers. Doing so would mask
       # warnings in our own code.
-      perfetto_isystem_cflag,
+      "-isystem",
       rebase_path("../buildtools/protobuf/src", root_build_dir),
     ]
   }
@@ -365,16 +352,10 @@
   }
 }
 
-config("system_zlib_config") {
-  libs = [ "z" ]
-}
-
 # Zlib is used both by trace_processor and by perfetto_cmd.
 if (enable_perfetto_zlib) {
   group("zlib") {
-    if (perfetto_use_system_zlib) {
-      public_configs = [ "//gn:system_zlib_config" ]
-    } else if (perfetto_root_path == "//") {
+    if (perfetto_root_path == "//") {
       public_configs = [ "//buildtools:zlib_config" ]
       public_deps = [ "//buildtools:zlib" ]
     } else {
diff --git a/gn/gen_perfetto_version_header.gni b/gn/gen_perfetto_version_header.gni
deleted file mode 100644
index 17c879f..0000000
--- a/gn/gen_perfetto_version_header.gni
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This action generates a perfetto_version.gen.h which exposes some
-# PERFETTO_VERSION_xxx() macros that contains the git revision and release
-# number from the CHANGELOG.
-# This template is used only in two places: in //base (for C++ code) and in
-# //ui. This teamplate exists only to keep the logic consistent and avoid that
-# base's and ui's logic diverge.
-
-import("perfetto.gni")
-
-template("gen_perfetto_version_header") {
-  action(target_name) {
-    script = "${perfetto_root_path}tools/write_version_header.py"
-    changelog = "${perfetto_root_path}CHANGELOG"
-    inputs = [ changelog ]
-    outputs = []
-    args = []
-    if (perfetto_build_standalone && !is_perfetto_build_generator &&
-        perfetto_enable_git_rev_version_header) {
-      inputs += [ "${perfetto_root_path}.git/HEAD" ]
-    }
-
-    if (defined(invoker.cpp_out)) {
-      args += [
-        "--changelog",
-        rebase_path(changelog, root_build_dir),
-        "--cpp_out",
-        rebase_path(invoker.cpp_out, root_build_dir),
-      ]
-      outputs += [ invoker.cpp_out ]
-    }
-    if (defined(invoker.ts_out)) {
-      args += [
-        "--ts_out",
-        rebase_path(invoker.ts_out, root_build_dir),
-      ]
-      outputs += [ invoker.ts_out ]
-    }
-    if (!perfetto_enable_git_rev_version_header) {
-      args += [ "--no_git" ]
-    }
-  }
-}
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index c1ff723..42aa474 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -131,12 +131,7 @@
 }
 
 declare_args() {
-  # Enables build of platform-wide tracing services (traced, traced_probes)
-  # and executables (perfetto_cmd, trigger_perfetto).
-  # When disabled, only the client library and other auxiliary tools can be
-  # built (for Chromium and other GN embedders).
-  # Note that traced_probes is further conditioned by the GN variable
-  # enable_perfetto_traced_probes, in the declare_args() section below.
+  # Platform-wide tracing executables (traced, traced_probes, perfetto_cmd).
   enable_perfetto_platform_services =
       perfetto_build_standalone || perfetto_build_with_android
 
@@ -186,53 +181,31 @@
                               build_with_chromium || perfetto_build_with_android
 
   enable_perfetto_integration_tests =
-      (perfetto_build_standalone && !is_win) || perfetto_build_with_android
+      perfetto_build_standalone || perfetto_build_with_android
 
-  enable_perfetto_benchmarks = perfetto_build_standalone && !is_win
+  enable_perfetto_benchmarks = perfetto_build_standalone
 
   enable_perfetto_fuzzers =
       perfetto_build_standalone && defined(is_fuzzer) && is_fuzzer
 
-  # Enables the write_version_header.py tool that generates a .h that contains a
-  # macro with the current git revision and latest release version from
-  # CHANGELOG. If false base/version.h will return "unknown".
+  # 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 ||
-      perfetto_build_with_android
+      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.
-  # On Windows we default to monolithic executables, because pairing
-  # dllexport/import adds extra complexity for little benefit. Te only reason
-  # for monolithic_binaries=false is saving binary size, which matters mainly on
-  # Android. See also comments on PERFETTO_EXPORTED_ENTRYPOINT in compiler.h.
-  monolithic_binaries = is_win
+  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
-
-  # Installs a signal handler for the most common crash signals which unwinds
-  # the stack and prints the stack trace on stderr. Requires a dependency on
-  # libbacktrace when enabled.
-  enable_perfetto_stderr_crash_dump =
-      is_debug && perfetto_build_standalone && !is_wasm && !is_win
 }
 
 declare_args() {
-  perfetto_enable_git_rev_version_header = enable_perfetto_version_gen
-
-  # The traced_probes daemon is very Linux-specific, as it depends on ftrace and
-  # various /proc interfaces. There is no point making its code platform-neutral
-  # as it won't do anything useful on Windows.
-  # The only reason why we still build it on Mac OS is to be able to run the
-  # unittests there and making dev on mac less cumbersome. The traced_probes
-  # code happens to build cleanly and for now the mainteinance cost on Mac is
-  # extremely low.
-  enable_perfetto_traced_probes = enable_perfetto_platform_services && !is_win
-
   # Whether info-level logging is enabled.
   perfetto_verbose_logs_enabled =
       !build_with_chromium || perfetto_force_dlog == "on"
@@ -274,8 +247,7 @@
 
   # Allows to build the UI (TypeScript/ HTML / WASM)
   enable_perfetto_ui =
-      perfetto_build_standalone && enable_perfetto_trace_processor_sqlite &&
-      host_os != "win"
+      perfetto_build_standalone && enable_perfetto_trace_processor_sqlite
 
   # Skip buildtools dependency checks (needed for ChromeOS).
   skip_buildtools_check = false
@@ -283,15 +255,6 @@
   # Used by CrOS system builds. Uses the system version of protobuf
   # from /usr/include instead of the hermetic one.
   perfetto_use_system_protobuf = false
-
-  perfetto_use_system_zlib = false
-}
-
-if (is_win) {
-  # clang-cl
-  perfetto_isystem_cflag = "/I"
-} else {
-  perfetto_isystem_cflag = "-isystem"
 }
 
 # +---------------------------------------------------------------------------+
@@ -329,8 +292,3 @@
 
 assert(perfetto_force_dlog == "" || perfetto_force_dlog == "on" ||
        perfetto_force_dlog == "off")
-
-# If enable_perfetto_traced_probes is set, enable_perfetto_platform_services
-# must be set as well. Doesn't make sense to build traced_probes without the
-# rest. traced_probes integration tests depend on traced.
-assert(!enable_perfetto_traced_probes || enable_perfetto_platform_services)
diff --git a/gn/perfetto_benchmarks.gni b/gn/perfetto_benchmarks.gni
index e154064..46e067c 100644
--- a/gn/perfetto_benchmarks.gni
+++ b/gn/perfetto_benchmarks.gni
@@ -18,19 +18,13 @@
   "gn:default_deps",
   "src/base:benchmarks",
   "src/protozero:benchmarks",
-  "src/protozero/filtering:benchmarks",
   "src/trace_processor/sqlite:benchmarks",
   "src/trace_processor/containers:benchmarks",
   "src/trace_processor/tables:benchmarks",
-  "src/kallsyms:benchmarks",
+  "src/traced/probes/ftrace/kallsyms:benchmarks",
   "src/traced/probes/ftrace:benchmarks",
   "src/tracing/core:benchmarks",
   "src/tracing:benchmarks",
-  "src/trace_processor/rpc:benchmarks",
   "test:benchmark_main",
   "test:end_to_end_benchmarks",
 ]
-
-if (enable_perfetto_heapprofd) {
-  perfetto_benchmarks_targets += [ "src/profiling/memory:benchmarks" ]
-}
diff --git a/gn/perfetto_cc_proto_descriptor.gni b/gn/perfetto_cc_proto_descriptor.gni
deleted file mode 100644
index 852dc0b..0000000
--- a/gn/perfetto_cc_proto_descriptor.gni
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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")
-
-template("perfetto_cc_proto_descriptor") {
-  config("${target_name}_config") {
-    include_dirs = [ "${root_gen_dir}/${perfetto_root_path}" ]
-  }
-
-  action(target_name) {
-    generated_header = "${target_gen_dir}/${invoker.descriptor_name}.h"
-    descriptor_file_path =
-        get_label_info(invoker.descriptor_target, "target_gen_dir") +
-        "/${invoker.descriptor_name}"
-
-    script = "$perfetto_root_path/tools/gen_cc_proto_descriptor.py"
-    deps = [ invoker.descriptor_target ]
-    args = [
-      "--gen_dir",
-      rebase_path(root_gen_dir, root_build_dir),
-      "--cpp_out",
-      rebase_path(generated_header, root_build_dir),
-      rebase_path(descriptor_file_path, root_build_dir),
-    ]
-    inputs = [ descriptor_file_path ]
-    outputs = [ generated_header ]
-    public_configs = [ ":${target_name}_config" ]
-  }
-}
diff --git a/gn/perfetto_component.gni b/gn/perfetto_component.gni
deleted file mode 100644
index 3c40d5d..0000000
--- a/gn/perfetto_component.gni
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("perfetto.gni")
-
-# This template is used when generating build files via tools/gen_android_bp
-# and tools/gen_bazel. This is to solve the problem that other build systems
-# don't have a similar concept to GN's source_set and dependencies can only
-# happen between static libraries (or shared, but we don't use them).
-
-# In future this could be used for chromium component builds, where each
-# component becomes its own shared library (see b/159411946). This alone isn't
-# enough for that use case as it will require splitting also the various
-# export.h files.
-
-# TODO(primiano): we cannot split components as static libraries in Android
-# because heapprofd_client rebuilds base with
-# -DPERFETTO_ANDROID_ASYNC_SAFE_LOG. Once this is fixed re-enable the
-# ODRChecker in tools/gen_android_bp.
-
-# The condition below really means: "is Bazel generator".
-if (is_perfetto_build_generator && !perfetto_build_with_android) {
-  perfetto_component_type = "static_library"
-} else {
-  perfetto_component_type = "source_set"
-}
-
-template("perfetto_component") {
-  target(perfetto_component_type, target_name) {
-    forward_variables_from(invoker, "*")
-    if (perfetto_component_type == "static_library") {
-      # Mangle the name of the library putting the full path in it. In component
-      # builds we don't care about file names, as nobody depends from the
-      # outside on the internal component libraries.
-      # This is because library targets are stored in the root output folder
-      # (not in a subfolder that matches their path). This mangling avoid file
-      # avoid name clashes when the target is called "common" or similar, so we
-      # use src_ipc_common.a rather than common.a.
-      _name = get_label_info(target_name, "label_no_toolchain")
-      _name = string_replace(_name, "//", "")
-      _name = string_replace(_name, "/", "_")
-      _name = string_replace(_name, ":", "_")
-      output_name = _name
-      complete_static_lib = true
-    }
-  }
-}
diff --git a/gn/perfetto_fuzzers.gni b/gn/perfetto_fuzzers.gni
index 5874f8e..0a5dbfa 100644
--- a/gn/perfetto_fuzzers.gni
+++ b/gn/perfetto_fuzzers.gni
@@ -18,8 +18,6 @@
   "gn:default_deps",
   "src/ipc:buffered_frame_deserializer_fuzzer",
   "src/protozero:protozero_decoder_fuzzer",
-  "src/protozero/filtering:protozero_bytecode_parser_fuzzer",
-  "src/protozero/filtering:protozero_message_filter_fuzzer",
   "src/tracing/core:packet_stream_validator_fuzzer",
   "src/trace_processor:trace_processor_fuzzer",
   "src/traced/probes/ftrace:cpu_reader_fuzzer",
diff --git a/gn/perfetto_integrationtests.gni b/gn/perfetto_integrationtests.gni
index d1005fd..d2b0181 100644
--- a/gn/perfetto_integrationtests.gni
+++ b/gn/perfetto_integrationtests.gni
@@ -20,8 +20,7 @@
   "src/tracing/test:client_api_integrationtests",
 ]
 
-if (enable_perfetto_traced_probes) {
-  # enable_perfetto_traced_probes implies enable_perfetto_platform_services.
+if (enable_perfetto_platform_services) {
   perfetto_integrationtests_targets += [
     "src/traced/probes/ftrace:integrationtests",
     "test:end_to_end_integrationtests",
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index 1a2b482..aae3085 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -20,9 +20,7 @@
   "src/base:unittests",
   "src/protozero:unittests",
   "src/tracing/core:unittests",
-  "src/tracing:unittests",
   "src/profiling:unittests",
-  "src/profiling/symbolizer:unittests",
 ]
 
 if (enable_perfetto_ipc) {
@@ -51,16 +49,12 @@
 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/probes/ftrace/kallsyms:unittests",
     "src/traced/service:unittests",
   ]
-  if (enable_perfetto_traced_probes) {
-    perfetto_unittests_targets += [
-      "src/traced/probes:unittests",
-      "src/traced/probes/filesystem:unittests",
-      "src/traced/probes/ftrace:unittests",
-      "src/kallsyms:unittests",
-    ]
-  }
 }
 
 if (enable_perfetto_heapprofd || enable_perfetto_traced_perf) {
diff --git a/gn/proto_library.gni b/gn/proto_library.gni
index 03d6455..ca5370b 100644
--- a/gn/proto_library.gni
+++ b/gn/proto_library.gni
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("perfetto.gni")
-import("perfetto_component.gni")
 
 # This gni file defines rules for proto generation. There are various types of
 # proto targets that can be defined in our codebase:
@@ -52,13 +51,6 @@
     perfetto_protobuf_gni = "//third_party/protobuf/proto_library.gni"
   }
 }
-if (!defined(perfetto_protobuf_src_dir)) {
-  if (perfetto_root_path == "//") {
-    perfetto_protobuf_src_dir = "//buildtools/protobuf/src"
-  } else {
-    perfetto_protobuf_src_dir = "//third_party/protobuf/src"
-  }
-}
 import(perfetto_protobuf_gni)
 
 # Equivalent to proto_library (generation of .h/.cc from .proto files) but
@@ -85,16 +77,7 @@
       deps = []
     }
 
-    # omit_protozero_dep is intended to be used when protozero_library
-    # is used in Chrome (for generation of code for proto extensions)
-    # to avoid ODR violations in case of component builds. The embedder
-    # (Chrome) is then responsible for adding the appropriate transitive
-    # dependency on Protozero.
-    #
-    # TODO(b/173041866): use fine-grained components instead when available
-    if (!(defined(invoker.omit_protozero_dep) && invoker.omit_protozero_dep)) {
-      deps += [ perfetto_root_path + "src/protozero" ]
-    }
+    deps += [ perfetto_root_path + "src/protozero" ]
 
     forward_variables_from(invoker,
                            [
@@ -108,7 +91,6 @@
                              "visibility",
                              "generate_descriptor",
                              "propagate_imports_configs",
-                             "import_dirs",
                            ])
   }
 }
@@ -153,7 +135,6 @@
                              "visibility",
                              "generate_descriptor",
                              "propagate_imports_configs",
-                             "import_dirs",
                            ])
   }
 }
@@ -167,12 +148,10 @@
     generator_plugin_label =
         "$perfetto_root_path/src/ipc/protoc_plugin:ipc_plugin"
     generator_plugin_suffix = ".ipc"
-    deps = [ "$perfetto_root_path/gn:default_deps" ]
-    if (perfetto_component_type == "static_library") {
-      deps += [ "$perfetto_root_path/src/ipc:perfetto_ipc" ]
-    } else {
-      deps += [ "$perfetto_root_path/src/ipc:common" ]
-    }
+    deps = [
+      "$perfetto_root_path/gn:default_deps",
+      "$perfetto_root_path/src/ipc:common",
+    ]
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
@@ -188,7 +167,6 @@
                              "testonly",
                              "visibility",
                              "propagate_imports_configs",
-                             "import_dirs",
                            ])
   }
 }
@@ -202,7 +180,6 @@
       "zero",
       "lite",
       "cpp",
-      "source_set",
     ]
   }
 
@@ -213,17 +190,10 @@
     proto_path = perfetto_root_path
   }
 
-  if (defined(invoker.import_dirs)) {
-    import_dirs_ = invoker.import_dirs
-  } else {
-    import_dirs_ = []
-  }
-
   vars_to_forward = [
     "sources",
     "visibility",
     "testonly",
-    "exclude_imports",
   ]
   expansion_token = "@TYPE@"
 
@@ -250,7 +220,6 @@
         generator_plugin_options = "wrapper_namespace=pbzero"
         deps = deps_
         propagate_imports_configs = propagate_imports_configs_
-        import_dirs = import_dirs_
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "cpp") {
@@ -260,7 +229,6 @@
         generator_plugin_options = "wrapper_namespace=gen"
         deps = deps_
         propagate_imports_configs = propagate_imports_configs_
-        import_dirs = import_dirs_
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "ipc") {
@@ -271,7 +239,6 @@
         generator_plugin_options = "wrapper_namespace=gen"
         deps = deps_ + [ ":$cpp_target_name_" ]
         propagate_imports_configs = propagate_imports_configs_
-        import_dirs = import_dirs_
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "lite") {
@@ -282,7 +249,6 @@
         deps = deps_
         cc_generator_options = "lite=true:"
         propagate_imports_configs = propagate_imports_configs_
-        import_dirs = import_dirs_
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "descriptor") {
@@ -291,41 +257,13 @@
         proto_out_dir = proto_path
         generate_python = false
         generate_cc = false
-        generate_descriptor =
-            rebase_path(invoker.generate_descriptor, proto_path)
+        generate_descriptor = invoker.generate_descriptor
         deps = deps_
-        import_dirs = import_dirs_
         forward_variables_from(invoker, vars_to_forward)
       }
 
       # Not needed for descriptor proto_library target.
       not_needed([ "propagate_imports_configs_" ])
-    } else if (gen_type == "source_set") {
-      action(target_name_) {
-        out_path = "$target_gen_dir/" + target_name_
-        rebased_out_path =
-            rebase_path(target_gen_dir, root_build_dir) + "/" + target_name_
-
-        script = "$perfetto_root_path/tools/touch_file.py"
-        args = [
-          "--output",
-          rebased_out_path,
-        ]
-        outputs = [ out_path ]
-        deps = deps_
-
-        metadata = {
-          proto_library_sources = invoker.sources
-          import_dirs = import_dirs_
-        }
-        forward_variables_from(invoker, vars_to_forward)
-      }
-
-      # Not needed for source_set proto_library target.
-      not_needed([
-                   "propagate_imports_configs_",
-                   "proto_path",
-                 ])
     } else {
       assert(false, "Invalid 'proto_generators' value.")
     }
diff --git a/gn/standalone/.emscripten b/gn/standalone/.emscripten
deleted file mode 100644
index ac3a692..0000000
--- a/gn/standalone/.emscripten
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 is the init script that is passed to `emcc --em-config=.emscripten`
-# (Wasm toolchain). It sets vars to locate the various emsdk / llvm dirs.
-
-import os
-import sys
-from platform import system
-
-# We cannot use __file__ here.
-this_file = os.getenv('EM_CONFIG')
-if this_file is None:
-  sys.stderr.write('Could not find EM_CONFIG in .emscripten\n')
-  sys.exit(1)
-
-root_dir = os.path.dirname(os.path.dirname(os.path.dirname(this_file)))
-buildools_os = 'mac' if system().lower() == 'darwin' else 'linux64'
-node_path = os.path.join(root_dir, 'buildtools', buildools_os, 'nodejs')
-emsdk_path = os.path.join(root_dir, 'buildtools', buildools_os, 'emsdk')
-
-# Exported vars.
-NODE_JS = os.path.join(node_path, 'bin', 'node')
-LLVM_ROOT = os.path.join(emsdk_path, 'bin')
-BINARYEN_ROOT = emsdk_path
-EMSCRIPTEN_ROOT = os.path.join(emsdk_path, 'emscripten')
-COMPILER_ENGINE = NODE_JS
-JS_ENGINES = [NODE_JS]
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index af70070..f11bb5f 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -14,126 +14,72 @@
 
 import("//gn/perfetto_check_build_deps.gni")
 import("//gn/standalone/android.gni")
-import("//gn/standalone/libc++/libc++.gni")
 import("//gn/standalone/sanitizers/sanitizers.gni")
-import("//gn/standalone/toolchain/msvc.gni")
 import("//gn/standalone/wasm.gni")
 
 # These warnings have been introduced with the newest version of clang (only in
 # the hermetic build) and are enabled just with -Werror.
-hermetic_clang_suppressions = [ "-Wno-c99-designator" ]
-
-# We deal with three toolchains here:
-# 1. Clang, used in most cases.
-# 2. GCC, used in some Linux cases.
-# 3. MSVC, used in some Windows cases.
-# Clang vs gcc is typically not a problem: both support roughly the same
-# switches. -Wno-unknown-warning-option fixes the mismatching ones.
-# The situation on Windows is a bit trickier: clang-cl.exe really pretends to be
-# cl.exe (MSVC), so we should use MSVC-style switches (e.g. /W2). However,
-# clang-cl.exe still supports some -Wclang-style-switches for flags that don't
-# have a corresponding version in MSVC.
-#
-# In the rules below, the conditionals should be interpreted as follows:
-# is_win -> can be either clang-cl.exe or cl.exe (MSVC). Only MSVC-style
-#           switches (the common denominator) should be used.
-# is_clang -> could be clang-on-linux, clang-on-mac or clang-cl.exe.
+# TODO(primiano): we should look into Wimplicit-int-float-conversion. Seems
+# failing mostly in tests though.
+hermetic_clang_suppressions = [
+  "-Wno-c99-designator",
+  "-Wno-implicit-int-float-conversion",
+]
 
 config("extra_warnings") {
-  if (is_win) {
-    cflags = [
-      "/W2",
-      "/wd4244",  # conversion from 'float' to 'int', possible loss of data
-      "/wd4267",  # conversion from 'size_t' to 'int', possible loss of data
-    ]
-    if (is_clang) {
-      cflags += [
-        "-Wno-float-equal",
-        "-Wno-unused-macros",
-        "-Wno-old-style-cast",
-      ]
-    }
-  } else {
-    # Clang or Gcc. On linux, Android and Mac.
-    cflags = [
-      "-Wall",
-      "-Wextra",
-      "-Wpedantic",
-    ]
-  }
+  cflags = [
+    "-Wall",
+    "-Wextra",
+    "-Wpedantic",
+  ]
 
   # Disable variadic macro warning as we make extensive use of them in trace
   # processor and client API.
   if (is_clang) {
-    if (!is_fuzzer) {
-      # Disable Weverything on fuzzers to avoid breakages when new versions of
-      # clang are rolled into OSS-fuzz.
-      cflags += [ "-Weverything" ]
-    }
+    cflags += [ "-Wno-gnu-zero-variadic-macro-arguments" ]
+  }
+
+  # Disable Weverything on fuzzers to avoid breakages when new versions of clang
+  # are rolled into OSS-fuzz.
+  if (is_clang && !is_fuzzer) {
     cflags += [
+      "-Weverything",
       "-Wno-c++98-compat-pedantic",
       "-Wno-c++98-compat",
       "-Wno-disabled-macro-expansion",
-      "-Wno-documentation-unknown-command",
       "-Wno-gnu-include-next",
       "-Wno-gnu-statement-expression",
-      "-Wno-gnu-zero-variadic-macro-arguments",
       "-Wno-padded",
-      "-Wno-poison-system-directories",
       "-Wno-reserved-id-macro",
       "-Wno-unknown-sanitizers",
-      "-Wno-unknown-warning-option",
     ]
-  } else if (!is_clang && !is_win) {
-    # Use return std::move(...) for compatibility with old GCC compilers.
+  }
+
+  if (!is_clang) {
+    # Use return std::move(...) for compatibility with old compilers.
     cflags += [ "-Wno-redundant-move" ]
   }
 }
 
 config("no_exceptions") {
-  # Exceptions are disabled by default on Windows (Use /EHsc to enable them).
-  if (!is_win) {
-    cflags_cc = [ "-fno-exceptions" ]
-  }
+  cflags_cc = [ "-fno-exceptions" ]
 }
 
 config("no_rtti") {
-  if (is_win) {
-    cflags_cc = [ "/GR-" ]
-  } else {
-    cflags_cc = [ "-fno-rtti" ]
-  }
+  cflags_cc = [ "-fno-rtti" ]
 }
 
 config("c++11") {
-  # C++11 is the default on Windows.
-  if (!is_win) {
-    cflags_cc = [ "-std=c++11" ]
-  } else if (is_win && !is_clang) {
-    # Enable standards-conforming compiler behavior.
-    cflags_cc = [ "/permissive-" ]
-  }
+  cflags_cc = [ "-std=c++11" ]
 }
 
 # This is needed to compile libunwindstack.
 config("c++17") {
-  if (is_win) {
-    cflags_cc = [ "/std:c++17" ]
-  } else {
-    cflags_cc = [ "-std=c++17" ]
-  }
+  cflags_cc = [ "-std=c++17" ]
 }
 
 config("visibility_hidden") {
-  if (!is_win) {
-    cflags = [ "-fvisibility=hidden" ]
-  }
-}
-
-config("win32_lean_and_mean") {
-  if (is_win) {
-    defines = [ "WIN32_LEAN_AND_MEAN" ]
-  }
+  cflags = [ "-fvisibility=hidden" ]
 }
 
 config("default") {
@@ -142,58 +88,27 @@
   cflags_c = []
   cflags_cc = []
   defines = []
-  include_dirs = []
   ldflags = []
   libs = []
 
-  if ((is_android || is_linux) && !is_wasm) {
-    ldflags += [ "-Wl,--build-id" ]
-  }
+  cflags += [
+    "-fstrict-aliasing",
+    "-fstack-protector",
+    "-fPIC",
+    "-g",
+    "-Wformat",
+  ]
 
-  if (is_clang || !is_win) {  # Clang or GCC, but not MSVC.
-    cflags += [
-      "-fstrict-aliasing",
-      "-Wformat",
-    ]
-  }
-
-  if (is_win) {
-    cflags += [
-      "/bigobj",  # Some of our files are bigger than the regular limits.
-      "/Gy",  # Enable function-level linking.
-    ]
-    defines += [
-      "_CRT_NONSTDC_NO_WARNINGS",
-      "_CRT_SECURE_NO_DEPRECATE",
-      "_CRT_SECURE_NO_WARNINGS",  # Disables warnings on some POSIX-compat API.
-      "_SCL_SECURE_NO_DEPRECATE",
-      "NOMINMAX",
-    ]
-    if (!use_custom_libcxx) {
-      defines += [ "_HAS_EXCEPTIONS=0" ]  # Disables exceptions in MSVC STL.
-    }
-  } else if (!is_wasm) {  # !is_win
-    cflags += [
-      "-g",
-      "-fPIC",
-      "-fstack-protector-strong",
-    ]
-  }
-
-  # Treat warnings as errors, but give up on fuzzer builds.
   if (!is_fuzzer) {
-    if (is_win) {
-      cflags += [ "/WX" ]
-    } else {
-      cflags += [ "-Werror" ]
-    }
+    cflags += [ "-Werror" ]
   }
 
   if (is_clang) {
-    cflags += [ "-fcolor-diagnostics" ]
-    if (!is_win) {
-      cflags += [ "-fdiagnostics-show-template-tree" ]
-    }
+    cflags += [
+      # Color compiler output, see https://github.com/ninja-build/ninja/wiki/FAQ
+      "-fcolor-diagnostics",
+      "-fdiagnostics-show-template-tree",
+    ]
   }
 
   if (is_hermetic_clang && is_linux && !is_wasm) {
@@ -207,9 +122,6 @@
     ldflags += [ "-flto=full" ]
   }
 
-  # We support only x64 builds on Windows.
-  assert(!is_win || current_cpu == "x64")
-
   if (current_cpu == "arm") {
     cflags += [
       "-march=armv7-a",
@@ -238,24 +150,8 @@
     ]
   }
 
-  if (is_win && !is_clang) {
-    # When using MSVC we need to manually pass the include dirs. clang-cl.exe
-    # doesn't need them because it's smart enough to figure out the right path
-    # by querying the registry on its own.
-    include_dirs = win_msvc_inc_dirs  # Defined in msvc.gni.
-  }
-
   if (is_debug) {
-    if (is_win) {
-      cflags += [ "/Z7" ]
-      if (is_clang) {
-        # Required to see symbols in windbg when building with clang-cl.exe.
-        cflags += [ "-gcodeview-ghash" ]
-        ldflags = [ "/DEBUG:GHASH" ]
-      }
-    } else {
-      libs += [ "dl" ]
-    }
+    libs += [ "dl" ]
   }
 
   if (is_android) {
@@ -286,16 +182,13 @@
       "-Wl,--exclude-libs,libunwind.a",
       "-Wl,--exclude-libs,libgcc.a",
       "-Wl,--exclude-libs,libc++_static.a",
+      "-Wl,--build-id",
       "-Wl,--no-undefined",
       "-Wl,-z,noexecstack",
       "-Wl,-z,relro",
       "-Wl,-z,now",
       "-Wl,--warn-shared-textrel",
       "-Wl,--fatal-warnings",
-
-      # New NDKs need setting this to not give "unable to find library -lc++".
-      # See https://github.com/android/ndk/issues/951#issuecomment-501017894.
-      "-nostdlib++",
     ]
     lib_dirs = [
       "$android_ndk_root/sources/cxx-stl/llvm-libc++/libs/$android_app_abi",
@@ -314,49 +207,27 @@
 }
 
 config("debug_symbols") {
-  cflags = []
-  if (is_win) {
-    cflags = [ "/Od" ]
-  } else {
-    cflags = [ "-O0" ]
-  }
+  cflags = [ "-O0" ]
   if (is_android || is_linux) {
     cflags += [ "-funwind-tables" ]
   }
 }
 
 config("release") {
-  # Compiler flags for release builds.
-  if (is_win) {
-    cflags = [
-      "/O2",
-      "/Zc:inline",
-    ]
-  } else if (is_android) {
-    cflags = [ "-O2" ]
+  cflags = [
+    "-fdata-sections",
+    "-ffunction-sections",
+  ]
+  if (is_android) {
+    cflags += [ "-O2" ]
   } else if (is_fuzzer) {
-    cflags = [ "-O1" ]
+    cflags += [ "-O1" ]
   } else {
-    cflags = [ "-O3" ]
+    cflags += [ "-O3" ]
   }
-  if (!is_win) {
-    cflags += [
-      "-fdata-sections",
-      "-ffunction-sections",
-    ]
-  }
-
-  # Linker flags for release builds.
-  if (is_win) {
-    ldflags = [
-      "/OPT:REF",
-      "/OPT:ICF",
-      "/INCREMENTAL:NO",
-      "/FIXED:NO",
-    ]
-  } else if (is_mac) {
+  if (is_mac) {
     ldflags = [ "-dead_strip" ]
-  } else if (!is_win && !is_wasm) {
+  } else {
     ldflags = [
       "-Wl,--gc-sections",
       "-Wl,--icf=all",
@@ -377,9 +248,7 @@
 
   # Android will refuse to run executables if they aren't position independent.
   # Instead on Linux there isn't any need and they break ASan (goo.gl/paFR6K).
-  # The OSS-Fuzz provided AFL library is not PIC, so we we cannot use -fPIE
-  # for the fuzzer executables.
-  if ((is_android || is_linux) && !is_wasm && !is_fuzzer) {
+  if (is_android || is_linux) {
     asmflags = [ "-fPIE" ]
     cflags = [ "-fPIE" ]
     ldflags += [ "-pie" ]
@@ -390,7 +259,7 @@
   # supported only by Linux, not Android. But concretely we need this only when
   # use_custom_libcxx=true && custom_libcxx_is_static=false, which happens only
   # on Linux right now.
-  if (is_linux && !is_wasm) {
+  if (is_linux) {
     ldflags += [
       "-Wl,-rpath=\$ORIGIN/.",
       "-Wl,-rpath-link=.",
@@ -408,6 +277,22 @@
   }
 }
 
+config("gen_include_path") {
+  include_dirs = [ root_gen_dir ]
+}
+
+# This action generates a perfetto_version.gen.h which contains the git SHA1
+# of HEAD. The file can be included from C/C++ sources and exposes a
+# PERFETTO_GET_GIT_REVISION() macro that contains the git revision.
+action("gen_git_revision") {
+  script = "gen_git_revision.py"
+  generated_header = "${root_gen_dir}/perfetto_version.gen.h"
+  args = [ rebase_path(generated_header, root_build_dir) ]
+  inputs = []
+  outputs = [ generated_header ]
+  public_configs = [ ":gen_include_path" ]
+}
+
 # Checks that tools/install-build-deps has been run since it last changed.
 perfetto_check_build_deps("check_build_deps") {
   args = []
diff --git a/gn/standalone/BUILDCONFIG.gn b/gn/standalone/BUILDCONFIG.gn
index e080700..3668c0f 100644
--- a/gn/standalone/BUILDCONFIG.gn
+++ b/gn/standalone/BUILDCONFIG.gn
@@ -18,9 +18,9 @@
   is_system_compiler = false
   is_lto = false
 
-  # This is defined here because it's needed below for determining the value of
-  # |is_cross_compiling|.
-  target_triplet = ""
+  extra_cflags = ""
+  extra_cxxflags = ""
+  extra_ldflags = ""
 }
 
 # Platform detection
@@ -32,16 +32,13 @@
 }
 
 is_android = current_os == "android"
-is_chromeos = current_os == "chromeos"
 is_linux = current_os == "linux"
 is_linux_host = host_os == "linux"
 is_mac = current_os == "mac"
-is_mac_host = host_os == "mac"
-is_win = current_os == "win"
-is_win_host = host_os == "win"
 
 # Building with Windows/Fuchsia/nacl is currently only supported in the Chromium
 # tree so always set this to false.
+is_win = false
 is_fuchsia = false
 is_nacl = false
 
@@ -55,8 +52,7 @@
   current_cpu = target_cpu
 }
 
-is_cross_compiling =
-    target_cpu != host_cpu || target_os != host_os || target_triplet != ""
+is_cross_compiling = target_cpu != host_cpu || target_os != host_os
 
 default_configs = [
   "//gn/standalone:debug_symbols",
@@ -70,10 +66,6 @@
   "//gn/standalone/sanitizers:sanitizers_cflags",
 ]
 
-if (is_win) {
-  default_configs += [ "//gn/standalone:win32_lean_and_mean" ]
-}
-
 if (!is_debug) {
   default_configs -= [ "//gn/standalone:debug_symbols" ]
   default_configs += [ "//gn/standalone:release" ]
@@ -106,11 +98,7 @@
   configs += [ "//gn/standalone:android_liblog" ]
 }
 
-if (is_win) {
-  _default_toolchain = "//gn/standalone/toolchain:msvc"
-} else {
-  _default_toolchain = "//gn/standalone/toolchain:gcc_like"
-}
+_default_toolchain = "//gn/standalone/toolchain:gcc_like"
 set_default_toolchain(_default_toolchain)
 
 if (is_cross_compiling) {
diff --git a/gn/standalone/android.gni b/gn/standalone/android.gni
index ab9492e..d798b37 100644
--- a/gn/standalone/android.gni
+++ b/gn/standalone/android.gni
@@ -22,13 +22,13 @@
   } else if (host_os == "mac") {
     android_host = "darwin-x86_64"
   } else {
-    android_host = "UNSUPPORTED_ON_WINDOWS"
+    assert(false, "Need Android toolchain support for your build OS.")
   }
 }
 
 declare_args() {
   android_llvm_dir = "$android_ndk_root/toolchains/llvm/prebuilt/$android_host"
-  android_clangrt_dir = "$android_llvm_dir/lib64/clang/9.0.9/lib/linux"
+  android_clangrt_dir = "$android_llvm_dir/lib64/clang/6.0.2/lib/linux"
   android_compile_sysroot = "$android_ndk_root/sysroot/usr/include"
 
   if (current_cpu == "x86") {
diff --git a/gn/standalone/build_tool_wrapper.py b/gn/standalone/build_tool_wrapper.py
index f8f15ef..e1abe19 100644
--- a/gn/standalone/build_tool_wrapper.py
+++ b/gn/standalone/build_tool_wrapper.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/gn/standalone/cp.py b/gn/standalone/cp.py
deleted file mode 100644
index 8a3ef0d..0000000
--- a/gn/standalone/cp.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import shutil
-import sys
-
-
-def main():
-  src, dst = sys.argv[1:]
-
-  if os.path.exists(dst):
-    if os.path.isdir(dst):
-      shutil.rmtree(dst)
-    else:
-      os.remove(dst)
-
-  if os.path.isdir(src):
-    shutil.copytree(src, dst)
-  else:
-    shutil.copy2(src, dst)
-    #work around https://github.com/ninja-build/ninja/issues/1554
-    os.utime(dst, None)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/gn/standalone/fuzzer.gni b/gn/standalone/fuzzer.gni
index cac571a..0b3f332 100644
--- a/gn/standalone/fuzzer.gni
+++ b/gn/standalone/fuzzer.gni
@@ -15,9 +15,10 @@
 import("//gn/standalone/sanitizers/sanitizers.gni")
 
 template("perfetto_fuzzer_test") {
+  forward_variables_from(invoker, "*")
+
   if (is_fuzzer) {
     executable(target_name) {
-      forward_variables_from(invoker, "*")
       if (use_libfuzzer) {
         deps += [ "//gn:libfuzzer" ]
       } else {
@@ -26,7 +27,7 @@
     }
   } else {
     not_needed(invoker, "*")
-    group(target_name) {
+    source_set(target_name) {
     }
   }
 }  # template
diff --git a/gn/standalone/gen_git_revision.py b/gn/standalone/gen_git_revision.py
new file mode 100755
index 0000000..a45262a
--- /dev/null
+++ b/gn/standalone/gen_git_revision.py
@@ -0,0 +1,42 @@
+#!/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 os
+import subprocess
+import sys
+
+
+def main(argv):
+  if len(argv) != 2:
+    print('Usage: %s output_file.h' % argv[0])
+    return 1
+  script_dir = os.path.dirname(os.path.realpath(__file__))
+  revision = subprocess.check_output(
+      ['git', '-C', script_dir, 'rev-parse', 'HEAD']).strip()
+  new_contents = '#define PERFETTO_GET_GIT_REVISION() "%s"\n' % revision
+  out_file = argv[1]
+  old_contents = ''
+  if os.path.isfile(out_file):
+    with open(out_file) as f:
+      old_contents = f.read()
+  if old_contents == new_contents:
+    return 0
+  with open(out_file, 'w') as f:
+    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
new file mode 100755
index 0000000..038d070
--- /dev/null
+++ b/gn/standalone/glob.py
@@ -0,0 +1,80 @@
+#!/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.
+""" 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
+a bad idea, as it plays very badly with git leaving untracked files around. This
+script should be used only for cases where false positives won't affect the
+output of the build but just cause spurious re-runs (e.g. as input section of
+an "action" target).
+"""
+from __future__ import print_function
+import argparse
+import fnmatch
+import os
+import sys
+
+
+def make_parent_dirs(file_path):
+  directory = os.path.dirname(file_path)
+  if not os.path.exists(directory):
+    os.makedirs(directory)
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--filter', default=[], action='append')
+  parser.add_argument('--exclude', default=[], action='append')
+  parser.add_argument('--deps', default=None)
+  parser.add_argument('--output', default=None)
+  parser.add_argument('--root', required=True)
+  args = parser.parse_args()
+
+  if args.output:
+    make_parent_dirs(args.output)
+    fout = open(args.output, 'w')
+  else:
+    fout = sys.stdout
+
+  def writepath(path):
+    if args.deps:
+      path = '\t' + path
+    print(path, file=fout)
+
+  root = args.root
+  if not root.endswith('/'):
+    root += '/'
+  if not os.path.exists(root):
+    return 0
+
+  if args.deps:
+    print(args.deps + ':', file=fout)
+  for pardir, dirs, files in os.walk(root, topdown=True):
+    assert pardir.startswith(root)
+    relpar = pardir[len(root):]
+    dirs[:] = [d for d in dirs if os.path.join(relpar, d) not in args.exclude]
+    for fname in files:
+      fpath = os.path.join(pardir, fname)
+      match = len(args.filter) == 0
+      for filter in args.filter:
+        if fnmatch.fnmatch(fpath, filter):
+          match = True
+          break
+      if match:
+        writepath(fpath)
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/gn/standalone/proto_library.gni b/gn/standalone/proto_library.gni
index a0bac3c..95948a3 100644
--- a/gn/standalone/proto_library.gni
+++ b/gn/standalone/proto_library.gni
@@ -14,12 +14,6 @@
 
 import("../perfetto.gni")
 
-if (host_os == "win") {
-  _host_executable_suffix = ".exe"
-} else {
-  _host_executable_suffix = ""
-}
-
 template("proto_library") {
   assert(defined(invoker.sources))
   proto_sources = invoker.sources
@@ -39,11 +33,6 @@
   # generate_python = true.
   assert(defined(invoker.generate_python) && !invoker.generate_python)
 
-  import_dirs = []
-  if (defined(invoker.import_dirs)) {
-    import_dirs = invoker.import_dirs
-  }
-
   # If false will not generate the default .pb.{cc,h} files. Used for custom
   # codegen plugins.
   generate_cc = true
@@ -54,21 +43,12 @@
   generate_descriptor = ""
   if (defined(invoker.generate_descriptor)) {
     generate_descriptor = invoker.generate_descriptor
-
-    # Include imports to descriptor by default, but use exclude_imports to omit
-    # them if needed.
-    if (defined(invoker.exclude_imports)) {
-      exclude_imports = invoker.exclude_imports
-    } else {
-      exclude_imports = false
-    }
   }
 
   if (defined(invoker.generator_plugin_label)) {
     plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
-    plugin_path =
-        get_label_info(plugin_host_label, "root_out_dir") + "/" +
-        get_label_info(plugin_host_label, "name") + _host_executable_suffix
+    plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" +
+                  get_label_info(plugin_host_label, "name")
     generate_with_plugin = true
   } else if (defined(invoker.generator_plugin_script)) {
     plugin_path = invoker.generator_plugin_script
@@ -88,19 +68,19 @@
     }
   }
 
-  out_dir = "$root_gen_dir/" + proto_out_dir
-  rel_out_dir = rebase_path(out_dir, root_build_dir)
+  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_out_dir" ])
+    not_needed([ "rel_cc_out_dir" ])
   }
 
   protos = rebase_path(proto_sources, proto_in_dir)
   protogens = []
 
   if (generate_descriptor != "") {
-    protogens += [ "$out_dir/${generate_descriptor}" ]
+    protogens += [ "$target_gen_dir/" + generate_descriptor ]
   }
 
   foreach(proto, protos) {
@@ -115,13 +95,13 @@
 
     if (generate_cc) {
       protogens += [
-        "$out_dir/$proto_path.pb.h",
-        "$out_dir/$proto_path.pb.cc",
+        "$cc_out_dir/$proto_path.pb.h",
+        "$cc_out_dir/$proto_path.pb.cc",
       ]
     }
     if (generate_with_plugin) {
       foreach(suffix, generator_plugin_suffixes) {
-        protogens += [ "$out_dir/${proto_path}${suffix}" ]
+        protogens += [ "$cc_out_dir/${proto_path}${suffix}" ]
       }
     }
   }
@@ -135,7 +115,7 @@
   }
 
   config(config_name) {
-    include_dirs = [ out_dir ]
+    include_dirs = [ cc_out_dir ]
   }
 
   # The XXX_gen action that generates the .pb.{cc,h} files.
@@ -143,33 +123,28 @@
     if (generate_descriptor == "") {
       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"
+
     if (perfetto_use_system_protobuf) {
-      protoc_rebased_path = "protoc" + _host_executable_suffix  # from PATH
+      protoc_rebased_path = "protoc"  # from PATH
     } else {
       protoc_label = "//gn:protoc($host_toolchain)"
-      protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" +
-                    _host_executable_suffix
+      protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc"
       protoc_rebased_path = "./" + rebase_path(protoc_path, root_build_dir)
     }
-    script = "//gn/standalone/protoc.py"
     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.
       protoc_rebased_path,
       "--proto_path",
       rebase_path(proto_in_dir, root_build_dir),
     ]
-
-    foreach(path, import_dirs) {
-      args += [
-        "--proto_path",
-        rebase_path(path, root_build_dir),
-      ]
-    }
-
     if (generate_cc) {
       cc_generator_options_ = ""
       if (defined(invoker.cc_generator_options)) {
@@ -177,18 +152,15 @@
       }
       args += [
         "--cpp_out",
-        cc_generator_options_ + rel_out_dir,
+        cc_generator_options_ + rel_cc_out_dir,
       ]
     }
     if (generate_descriptor != "") {
-      depfile = "$root_gen_dir/$generate_descriptor.d"
-
-      if (!exclude_imports) {
-        args += [ "--include_imports" ]
-      }
+      depfile = "$target_gen_dir/$generate_descriptor.d"
       args += [
+        "--include_imports",
         "--descriptor_set_out",
-        rebase_path("$root_gen_dir/$generate_descriptor", root_build_dir),
+        rebase_path("$target_gen_dir/$generate_descriptor", root_build_dir),
         "--dependency_out",
         rebase_path(depfile, root_build_dir),
       ]
@@ -200,7 +172,7 @@
       if (defined(invoker.generator_plugin_options)) {
         plugin_out_args += invoker.generator_plugin_options
       }
-      plugin_out_args += ":$rel_out_dir"
+      plugin_out_args += ":$rel_cc_out_dir"
 
       args += [
         "--plugin=protoc-gen-plugin=$plugin_path_rebased",
diff --git a/gn/standalone/protoc.py b/gn/standalone/protoc.py
old mode 100644
new mode 100755
index 52e156e..723c35e
--- a/gn/standalone/protoc.py
+++ b/gn/standalone/protoc.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +23,6 @@
 import sys
 import subprocess
 import tempfile
-import uuid
 
 from codecs import open
 
@@ -35,19 +35,14 @@
   args, remaining = parser.parse_known_args()
 
   if args.dependency_out and args.descriptor_set_out:
-    tmp_path = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))
-    custom = [
-        '--descriptor_set_out', args.descriptor_set_out, '--dependency_out',
-        tmp_path
-    ]
-    try:
-      cmd = [args.protoc] + custom + remaining
-      subprocess.check_call(cmd)
-      with open(tmp_path, 'rb') as tmp_rd:
-        dependency_data = tmp_rd.read().decode('utf-8')
-    finally:
-      if os.path.exists(tmp_path):
-        os.unlink(tmp_path)
+    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 + ":")
diff --git a/gn/standalone/sanitizers/BUILD.gn b/gn/standalone/sanitizers/BUILD.gn
index d3374de..c015d3e 100644
--- a/gn/standalone/sanitizers/BUILD.gn
+++ b/gn/standalone/sanitizers/BUILD.gn
@@ -36,7 +36,11 @@
   cflags = []
   defines = []
   if (using_sanitizer) {
-    cflags += [ "-fno-omit-frame-pointer" ]
+    blacklist_path_ = rebase_path("blacklist.txt", root_build_dir)
+    cflags += [
+      "-fno-omit-frame-pointer",
+      "-fsanitize-blacklist=$blacklist_path_",
+    ]
   }
 
   if (is_asan) {
diff --git a/gn/standalone/sanitizers/blacklist.txt b/gn/standalone/sanitizers/blacklist.txt
new file mode 100644
index 0000000..e0e315b
--- /dev/null
+++ b/gn/standalone/sanitizers/blacklist.txt
@@ -0,0 +1 @@
+# The rules in this file are only applied at compile time.
diff --git a/gn/standalone/sanitizers/sanitizers.gni b/gn/standalone/sanitizers/sanitizers.gni
index 7116b7b..9b0ec00 100644
--- a/gn/standalone/sanitizers/sanitizers.gni
+++ b/gn/standalone/sanitizers/sanitizers.gni
@@ -16,18 +16,20 @@
 import("//gn/standalone/sanitizers/vars.gni")
 import("//gn/standalone/toolchain/llvm.gni")
 
-_sanitizer_lib_base_name = ""
-if (is_asan || is_tsan || is_ubsan) {
-  if (is_asan) {
-    _sanitizer_lib_base_name = "clang_rt.asan"
-  }
-  if (is_tsan) {
-    _sanitizer_lib_base_name = "clang_rt.tsan"
-  }
-  if (is_ubsan) {
-    _sanitizer_lib_base_name = "clang_rt.ubsan"
-    if (is_android || is_linux) {
-      _sanitizer_lib_base_name += "_standalone"
+declare_args() {
+  sanitizer_lib_base_name_ = ""
+  if (is_asan || is_tsan || is_ubsan) {
+    if (is_asan) {
+      sanitizer_lib_base_name_ = "clang_rt.asan"
+    }
+    if (is_tsan) {
+      sanitizer_lib_base_name_ = "clang_rt.tsan"
+    }
+    if (is_ubsan) {
+      sanitizer_lib_base_name_ = "clang_rt.ubsan"
+      if (is_android || is_linux) {
+        sanitizer_lib_base_name_ += "_standalone"
+      }
     }
   }
 }
@@ -36,20 +38,18 @@
   sanitizer_lib_dir = ""
   sanitizer_lib = ""
   sanitizer_lib_dir_is_static = false
-  if (_sanitizer_lib_base_name != "") {
+  if (sanitizer_lib_base_name_ != "") {
     if (is_mac) {
-      sanitizer_lib = "${_sanitizer_lib_base_name}_osx_dynamic"
+      sanitizer_lib = "${sanitizer_lib_base_name_}_osx_dynamic"
       sanitizer_lib_dir = mac_clangrt_dir
     }
     if (is_linux) {
-      sanitizer_lib = "lib${_sanitizer_lib_base_name}-x86_64.a"
+      sanitizer_lib = "lib${sanitizer_lib_base_name_}-x86_64.a"
       sanitizer_lib_dir_is_static = true
-
-      # sanitizer_lib_dir is unused on linux. All usages of sanitizer_lib_dir
-      # are gated by an if (!sanitizer_lib_dir_is_static).
+      sanitizer_lib_dir = linux_clangrt_dir
     }
     if (is_android) {
-      sanitizer_lib = "${_sanitizer_lib_base_name}-${android_llvm_arch}-android"
+      sanitizer_lib = "${sanitizer_lib_base_name_}-${android_llvm_arch}-android"
       sanitizer_lib_dir = android_clangrt_dir
     }
   }
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index f72c606..b10fa7c 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -16,7 +16,6 @@
 import("//gn/standalone/android.gni")
 import("//gn/standalone/wasm.gni")
 import("llvm.gni")
-import("msvc.gni")
 
 # This file is evaluated once, within the context of the default toolchain,
 # which is the target toolchain.
@@ -27,56 +26,36 @@
 
 declare_args() {
   cc_wrapper = ""
-
-  # These apply to both target and host toolchains.
-  extra_cflags = ""
-  extra_cxxflags = ""
-  extra_ldflags = ""
-
-  # These apply only to the target toolchain.
-  extra_target_cflags = ""
-  extra_target_cxxflags = ""
-  extra_target_ldflags = ""
-
-  # These apply only to the host toolchain.
-  extra_host_cflags = ""
-  extra_host_cxxflags = ""
-  extra_host_ldflags = ""
 }
 
 # 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 and CrOS ebuilds.
-
+#    This is used by OSSFuzz.
 declare_args() {
   sysroot = ""
   gcc_toolchain = ""
   ar = "ar"
-  linker = ""
-
   if (is_linux_host) {
     linker = "gold"
+  } else {
+    linker = ""
   }
 
-  if (is_clang) {
-    if (is_linux_host && !is_system_compiler) {
+  if (is_system_compiler) {
+    ar = "\$AR"
+    cc = "\$CC"
+    cxx = "\$CXX"
+  } else if (is_clang) {
+    if (is_linux_host) {
       cc = linux_clang_bin
       cxx = linux_clangxx_bin
       linker = linux_clang_linker
-    } else if (is_win_host && !is_system_compiler) {
-      cc = win_clang_bin
-      cxx = win_clangxx_bin
-      linker = win_clang_linker
     } else {
       cc = "clang"
       cxx = "clang++"
       linker = ""
     }
-  } else if (is_win) {  # MSVC
-    cc = "${win_msvc_bin_dir}\\cl.exe"
-    cxx = "${win_msvc_bin_dir}\\cl.exe"
-    linker = "${win_msvc_bin_dir}\\link.exe"
   } else {  # GCC
     cc = "gcc"
     cxx = "g++"
@@ -88,82 +67,60 @@
 declare_args() {
   target_sysroot = sysroot
   target_gcc_toolchain = ""
-
-  # |target_triplet| is the variable that the user can set via GN args. The user
-  # doesn't have to necessarily set it though. In most cases we can infer it
-  # by looking at target_os and target_cpu.
-  # |_target_triplet| is the final argument passed to the toolchain.
-  if (target_triplet != "") {
-    assert(is_cross_compiling)
-
-    # If the user provides the target_triplet in gn args, respect that.
-    # Otherwise guess it looking at the target os and cpu variables.
-    _target_triplet = target_triplet
-  } else if (!is_cross_compiling) {
-    _target_triplet = ""
+  if (!is_cross_compiling) {
+    target_triplet = ""
   } else if (target_os == "mac" && target_cpu == "x64") {
-    _target_triplet = "x86_64-apple-darwin"
+    target_triplet = "x86_64-apple-darwin"
   } else if (target_os == "mac" && target_cpu == "x86") {
-    _target_triplet = "i686-apple-darwin"
+    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 == "arm") {
-    _target_triplet = "arm-linux-gnueabi"
+    target_triplet = "aarch64-linux-gnu"
   } else if (target_os == "linux" && target_cpu == "x64") {
-    _target_triplet = "x86_64-linux-gnu"
+    target_triplet = "x86_64-linux-gnu"
   } else if (target_os == "linux" && target_cpu == "x86") {
-    _target_triplet = "i686-linux-gnu"
+    target_triplet = "i686-linux-gnu"
   } else if (target_os == "android" && target_cpu == "arm64") {
-    _target_triplet = "aarch64-linux-android"
+    target_triplet = "aarch64-linux-android"
   } else if (target_os == "android" && target_cpu == "arm") {
-    _target_triplet = "arm-linux-androideabi"
+    target_triplet = "arm-linux-androideabi"
   } else if (target_os == "android" && target_cpu == "x86") {
-    _target_triplet = "i686-linux-android"
+    target_triplet = "i686-linux-android"
   } else if (target_os == "android" && target_cpu == "x64") {
-    _target_triplet = "x86_64-linux-android"
+    target_triplet = "x86_64-linux-android"
   } else {
-    assert(
-        false,
-        "Cannot guess the target triplet from the target_os and target_cpu combination. Please set the target_triplet GN arg explicitly. See https://clang.llvm.org/docs/CrossCompilation.html#target-triple")
+    assert(false,
+           "Unsupported cross-compilation for ${target_os}-${target_cpu}")
   }
 }
 
 declare_args() {
-  if (is_linux || is_android) {
-    target_linker = "gold"
-  } else {
-    target_linker = ""
-  }
-
-  if (!is_cross_compiling || is_perfetto_build_generator ||
-      is_system_compiler) {
+  if (!is_cross_compiling || is_perfetto_build_generator) {
     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++"
-      target_linker = "$android_llvm_dir/bin/ld.lld"
     } else {
-      assert(_target_triplet != "",
+      assert(target_triplet != "",
              "target_triplet must be non-empty when cross-compiling")
       if (is_clang) {
-        if (is_linux_host) {
-          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 {
-          target_cc = "clang --target=${_target_triplet}"
-          target_cxx = "clang++ --target=${_target_triplet}"
-        }
+        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++"
+        target_ar = "${target_triplet}-ar"
+        target_cc = "${target_triplet}-gcc"
+        target_cxx = "${target_triplet}-g++"
       }
     }
   }
@@ -177,9 +134,6 @@
     lib_switch = "-l"
     lib_dir_switch = "-L"
     ld_arg = ""
-    external_cflags = ""
-    external_cxxflags = ""
-    external_ldflags = ""
     if (defined(invoker.linker) && invoker.linker != "") {
       _invoker_linker = invoker.linker
       ld_arg = "-fuse-ld=$_invoker_linker"
@@ -194,19 +148,10 @@
       _invoker_gcc_toolchain = invoker.gcc_toolchain
       ld_arg = "$ld_arg --gcc-toolchain=$_invoker_gcc_toolchain"
     }
-    if (defined(invoker.external_cflags)) {
-      external_cflags = invoker.external_cflags
-    }
-    if (defined(invoker.external_cxxflags)) {
-      external_cxxflags = invoker.external_cxxflags
-    }
-    if (defined(invoker.external_ldflags)) {
-      external_ldflags = invoker.external_ldflags
-    }
 
     tool("cc") {
       depfile = "{{output}}.d"
-      command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} ${external_cflags} -c {{source}} -o {{output}}"
+      command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} ${extra_cflags} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       outputs =
           [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
@@ -215,7 +160,7 @@
 
     tool("cxx") {
       depfile = "{{output}}.d"
-      command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}  ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}"
+      command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}  ${extra_cflags} ${extra_cxxflags} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       outputs =
           [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
@@ -255,7 +200,7 @@
         rpath = "-Wl,-install_name,@rpath/$soname"
       }
 
-      command = "$cc_wrapper $cxx $ld_arg -shared {{ldflags}} ${external_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
+      command = "$cc_wrapper $cxx $ld_arg -shared {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
       outputs = [ "{{root_out_dir}}/$soname" ]
       output_prefix = "lib"
       default_output_extension = ".so"
@@ -263,7 +208,7 @@
     }
 
     tool("link") {
-      command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${external_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
+      command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
       outputs =
           [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" ]
       description = "link {{output}}"
@@ -295,21 +240,6 @@
   linker = target_linker
   sysroot = target_sysroot
   gcc_toolchain = target_gcc_toolchain
-  external_cflags = string_join(" ",
-                                [
-                                  extra_cflags,
-                                  extra_target_cflags,
-                                ])
-  external_cxxflags = string_join(" ",
-                                  [
-                                    extra_cxxflags,
-                                    extra_target_cxxflags,
-                                  ])
-  external_ldflags = string_join(" ",
-                                 [
-                                   extra_ldflags,
-                                   extra_target_ldflags,
-                                 ])
 }
 
 gcc_like_toolchain("gcc_like_host") {
@@ -321,21 +251,6 @@
   linker = linker
   sysroot = sysroot
   gcc_toolchain = gcc_toolchain
-  external_cflags = string_join(" ",
-                                [
-                                  extra_cflags,
-                                  extra_host_cflags,
-                                ])
-  external_cxxflags = string_join(" ",
-                                  [
-                                    extra_cxxflags,
-                                    extra_host_cxxflags,
-                                  ])
-  external_ldflags = string_join(" ",
-                                 [
-                                   extra_ldflags,
-                                   extra_host_ldflags,
-                                 ])
 }
 
 gcc_like_toolchain("wasm") {
@@ -346,112 +261,3 @@
   cc = "$emsdk_dir/emscripten/emcc --em-config $em_config"
   cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config"
 }
-
-# This is used both for MSVC anc clang-cl. clang-cl cmdline interface pretends
-# to be MSVC's cl.exe.
-toolchain("msvc") {
-  lib_switch = ""
-  lib_dir_switch = "/LIBPATH:"
-
-  sys_lib_flags = "/LIBPATH:\"${win_sdk_lib_dir}\\ucrt\\x64\" "
-  sys_lib_flags += "/LIBPATH:\"${win_sdk_lib_dir}\\um\\x64\" "
-  sys_lib_flags += "/LIBPATH:\"${win_msvc_lib_dir}\" "
-
-  # Note: /showIncludes below is required for ninja, to build a complete
-  # dependency graph for headers. Removing it breaks incremental builds.
-
-  tool("cc") {
-    precompiled_header_type = "msvc"
-    pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
-    command = "$cc_wrapper $cc /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
-    depsformat = "msvc"
-    outputs =
-        [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj" ]
-    description = "compile {{source}}"
-  }
-
-  tool("cxx") {
-    precompiled_header_type = "msvc"
-    pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
-    command = "$cc_wrapper $cxx /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
-    depsformat = "msvc"
-    outputs =
-        [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj" ]
-    description = "compile {{source}}"
-  }
-
-  tool("alink") {
-    rspfile = "{{output}}.rsp"
-    command = "$linker /lib /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile"
-    outputs = [
-      # Ignore {{output_extension}} and always use .lib, there's no reason to
-      # allow targets to override this extension on Windows.
-      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
-    ]
-    default_output_extension = ".lib"
-    default_output_dir = "{{target_out_dir}}"
-
-    # inputs_newline works around a fixed per-line buffer size in the linker.
-    rspfile_content = "{{inputs_newline}}"
-    description = "link {{output}}"
-  }
-
-  tool("solink") {
-    dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
-    libname = "${dllname}.lib"
-    pdbname = "${dllname}.pdb"
-    rspfile = "${dllname}.rsp"
-
-    command = "$linker /nologo /IMPLIB:$libname ${sys_lib_flags} /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
-    outputs = [
-      dllname,
-      libname,
-      pdbname,
-    ]
-    default_output_extension = ".dll"
-    default_output_dir = "{{root_out_dir}}"
-
-    link_output = libname
-    depend_output = libname
-    runtime_outputs = [
-      dllname,
-      pdbname,
-    ]
-
-    # Since the above commands only updates the .lib file when it changes, ask
-    # Ninja to check if the timestamp actually changed to know if downstream
-    # dependencies should be recompiled.
-    restat = true
-
-    # inputs_newline works around a fixed per-line buffer size in the linker.
-    rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
-    description = "link {{output}}"
-  }
-
-  tool("link") {
-    exename = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
-    pdbname = "$exename.pdb"
-    rspfile = "$exename.rsp"
-
-    command =
-        "$linker /nologo /OUT:$exename ${sys_lib_flags} /PDB:$pdbname @$rspfile"
-    default_output_extension = ".exe"
-    default_output_dir = "{{root_out_dir}}"
-    outputs = [ exename ]
-
-    # inputs_newline works around a fixed per-line buffer size in the linker.
-    rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
-    description = "link {{output}}"
-  }
-
-  tool("stamp") {
-    command = "cmd /c type nul > \"{{output}}\""
-    description = "stamp {{output}}"
-  }
-
-  tool("copy") {
-    cp_py = rebase_path("../cp.py")
-    command = "cmd.exe /c python \"$cp_py\" {{source}} {{output}}"
-    description = "copy {{source}} {{output}}"
-  }
-}
diff --git a/gn/standalone/toolchain/linux_find_llvm.py b/gn/standalone/toolchain/linux_find_llvm.py
old mode 100755
new mode 100644
index 2ec716e..3a957fe
--- a/gn/standalone/toolchain/linux_find_llvm.py
+++ b/gn/standalone/toolchain/linux_find_llvm.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +19,7 @@
 
 def main():
   devnull = open(os.devnull, 'w')
-  for clang in ('clang', 'clang-3.8', 'clang-3.5', 'clang-8'):
+  for clang in ('clang', 'clang-3.8', 'clang-3.5'):
     if subprocess.call(['which', clang], stdout=devnull, stderr=devnull) != 0:
       continue
     res = subprocess.check_output([clang, '-print-search-dirs']).decode("utf-8")
diff --git a/gn/standalone/toolchain/llvm.gni b/gn/standalone/toolchain/llvm.gni
index e3fc350..dda60ab 100644
--- a/gn/standalone/toolchain/llvm.gni
+++ b/gn/standalone/toolchain/llvm.gni
@@ -15,47 +15,31 @@
 import("//gn/standalone/sanitizers/vars.gni")
 
 declare_args() {
-  is_hermetic_clang = is_clang && (is_linux_host || is_win_host)
+  is_hermetic_clang = is_clang && is_linux_host
 }
 
 assert(!is_hermetic_clang || is_clang, "is_hermetic_clang requires is_clang")
 
-if (is_linux_host) {
-  if (is_hermetic_clang) {
-    _hermetic_llvm_dir =
-        rebase_path("//buildtools/linux64/clang", root_build_dir)
-    linux_clang_bin = "$_hermetic_llvm_dir/bin/clang"
-    linux_clangxx_bin = "$_hermetic_llvm_dir/bin/clang++"
-    linux_clang_linker = "lld"
-  } else if (is_clang && !is_system_compiler) {
-    # Guess the path for the system clang.
-    # When is_system_compiler = true users neet to explicitly set cc / target_cc
-    # vars in the GN args."
-    _find_llvm_out = exec_script("linux_find_llvm.py", [], "list lines")
-    _linux_llvm_dir = _find_llvm_out[0]
-    linux_clang_bin = _find_llvm_out[1]
-    linux_clangxx_bin = _find_llvm_out[2]
-    linux_clang_linker = "gold"
-  }
-} else if (is_mac_host && is_clang && !is_system_compiler) {
-  _mac_toolchain_dirs = exec_script("mac_find_llvm.py", [], "list lines")
-
-  # _mac_toolchain_dirs[0] contains the mac toolchain dir.
-  mac_clangrt_dir = _mac_toolchain_dirs[1]
-} else if (is_win_host) {
-  if (is_hermetic_clang) {
-    # Use the toolchain pulled by //tools/install-build-deps. This tracks
-    # chromium's llvm dist.
-    _llvm_win_path = rebase_path("//buildtools/win/clang/bin", root_build_dir)
-    win_clang_bin = "${_llvm_win_path}\clang-cl.exe"
-    win_clangxx_bin = "${_llvm_win_path}\clang-cl.exe"
-    win_clang_linker = "${_llvm_win_path}\lld-link.exe"
-  } else {
-    # Assume clang-cl.exe / lld-link.exe are on the PATH. The user can always
-    # ovveride them by setting cc/cxx/linker GN variables.
-    # See //gn/standalone/toolchain/BUILD.gn.
-    win_clang_bin = "clang-cl.exe"
-    win_clangxx_bin = "clang-cl.exe"
-    win_clang_linker = "lld-link.exe"
+declare_args() {
+  if (is_linux_host) {
+    if (is_hermetic_clang) {
+      _hermetic_llvm_dir = rebase_path("//buildtools/clang", root_build_dir)
+      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"
+    } else if (is_clang) {
+      # Guess the path for the system clang.
+      find_llvm_out = exec_script("linux_find_llvm.py", [], "list lines")
+      linux_llvm_dir = find_llvm_out[0]
+      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")
+    mac_toolchain_dir = mac_toolchain_dirs_[0]
+    mac_clangrt_dir = mac_toolchain_dirs_[1]
   }
 }
diff --git a/gn/standalone/toolchain/mac_find_llvm.py b/gn/standalone/toolchain/mac_find_llvm.py
index 43e46b0..3511f29 100644
--- a/gn/standalone/toolchain/mac_find_llvm.py
+++ b/gn/standalone/toolchain/mac_find_llvm.py
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import glob
 import os
 import subprocess
@@ -26,14 +24,14 @@
                          stderr=subprocess.STDOUT)
   out, err = job.communicate()
   if job.returncode != 0:
-    print(out, file=sys.stderr)
-    print(err, file=sys.stderr)
+    print >> sys.stderr, out
+    print >> sys.stderr, err
     return job.returncode
   sdk_dir = os.path.dirname(os.path.dirname(out.rstrip()))
-  print(sdk_dir)
+  print sdk_dir
   clang_dir = glob.glob(
-      os.path.join(sdk_dir.decode(), 'lib', 'clang', '*', 'lib', 'darwin'))
-  print(clang_dir[0] if clang_dir else 'CLANG_DIR_NOT_FOUND')
+      os.path.join(sdk_dir, 'lib', 'clang', '*', 'lib', 'darwin'))
+  print clang_dir[0] if clang_dir else 'CLANG_DIR_NOT_FOUND'
 
 
 if __name__ == '__main__':
diff --git a/gn/standalone/toolchain/msvc.gni b/gn/standalone/toolchain/msvc.gni
deleted file mode 100644
index 34c0a50..0000000
--- a/gn/standalone/toolchain/msvc.gni
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# We should never get in here by accident from the Chromium tree.
-assert(!defined(build_with_chromium) || !build_with_chromium)
-
-if (is_win_host) {
-  _find_msvc_out = exec_script("win_find_msvc.py", [], "list lines")
-
-  # The output looks like this (without the line number "N:" part):
-  # 1: C:\Program Files (x86)\Windows Kits\10
-  # 2: 10.0.19041.0
-  # 3: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333
-  _win_sdk_base = _find_msvc_out[0]
-  _win_sdk_ver = _find_msvc_out[1]
-  _win_msvc_base = _find_msvc_out[2]
-
-  # TODO(primiano): look into how to integrate this with the toolchain pulled by
-  # depot tools. Also improve error reporting telling the user what to do.
-  # For now this requires both:
-  # 1. Build Tools for Visual Studio 2019
-  #    https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
-  # 2. Windows 10 SDK:
-  #    https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/
-
-  # These variables are required both for clang-cl.exe and MSVC (cl.exe).
-  win_sdk_lib_dir = _win_sdk_base + "\\Lib\\" + _win_sdk_ver
-  win_msvc_lib_dir = _win_msvc_base + "\\lib\\x64"
-
-  # These variables are only required when building with MSVC.
-  # Clang is clever enough to figure out the right include path by querying the
-  # registry and detect the Windows SDK path (it still needs the /LIBPATH
-  # though, hence the _lib_dir above).
-  win_msvc_bin_dir = _win_msvc_base + "\\bin\\Hostx64\\x64"
-  win_msvc_inc_dirs = [
-    _win_msvc_base + "\\include",
-    _win_sdk_base + "\\Include\\" + _win_sdk_ver + "\\ucrt",
-    _win_sdk_base + "\\Include\\" + _win_sdk_ver + "\\um",
-    _win_sdk_base + "\\Include\\" + _win_sdk_ver + "\\shared",
-  ]
-} else {
-  win_sdk_lib_dir = ""
-  win_msvc_lib_dir = ""
-  win_msvc_bin_dir = ""
-  win_msvc_inc_dirs = []
-}
diff --git a/gn/standalone/toolchain/win_find_msvc.py b/gn/standalone/toolchain/win_find_msvc.py
deleted file mode 100644
index 41b3476..0000000
--- a/gn/standalone/toolchain/win_find_msvc.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-# 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.
-"""
-Finds and prints MSVC and Windows SDK paths.
-
-It outpus:
-Line 1: the base path of the Windows SDK.
-Line 2: the most recent version of the Windows SDK.
-Line 3: the path of the most recent MSVC.
-
-Example:
-C:\Program Files (x86)\Windows Kits\10
-10.0.19041.0
-C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333
-"""
-
-import os
-import subprocess
-import sys
-
-
-def ver_to_tuple(ver_str):
-  """Turns '10.1.2' into [10,1,2] so it can be compared using > """
-  parts = [int(x) for x in ver_str.split('.')]
-  assert (len(parts) == 4)
-  return parts
-
-
-def find_max_subdir(base_dir, filter=lambda x: True):
-  """Finds the max subdirectory in base_dir by comparing semantic versions."""
-  max_ver = None
-  for ver in os.listdir(base_dir) if os.path.exists(base_dir) else []:
-    cur = os.path.join(base_dir, ver)
-    if not filter(cur):
-      continue
-    if max_ver is None or ver_to_tuple(ver) > ver_to_tuple(max_ver):
-      max_ver = ver
-  return max_ver
-
-
-def main():
-  out = [
-      '',
-      '',
-      '',
-  ]
-  winsdk_base = 'C:\\Program Files (x86)\\Windows Kits\\10'
-  if os.path.exists(winsdk_base):
-    out[0] = winsdk_base
-    lib_base = winsdk_base + '\\Lib'
-    filt = lambda x: os.path.exists(os.path.join(x, 'ucrt', 'x64', 'ucrt.lib'))
-    out[1] = find_max_subdir(lib_base, filt)
-
-  for version in ['BuildTools', 'Community']:
-    msvc_base = ('C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\'
-                 '{}\\VC\\Tools\\MSVC').format(version)
-    if os.path.exists(msvc_base):
-      filt = lambda x: os.path.exists(
-          os.path.join(x, 'lib', 'x64', 'libcmt.lib'))
-      max_msvc = find_max_subdir(msvc_base, filt)
-      if max_msvc is not None:
-        out[2] = os.path.join(msvc_base, max_msvc)
-      break
-
-  # Don't error in case of failure, GN scripts are supposed to deal with
-  # failures and allow the user to override the dirs.
-
-  print('\n'.join(out))
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/gn/standalone/wasm.gni b/gn/standalone/wasm.gni
index bcf952b..bfa46ec 100644
--- a/gn/standalone/wasm.gni
+++ b/gn/standalone/wasm.gni
@@ -14,13 +14,18 @@
 
 import("../wasm_vars.gni")
 
-# Used by //gn/standalone/toolchain/BUILD.gn .
-em_config = rebase_path(".emscripten", "")
-if (is_mac_host) {
-  emsdk_dir = rebase_path("//buildtools/mac/emsdk", "")
-} else {
-  emsdk_dir = rebase_path("//buildtools/linux64/emsdk", "")
-}
+emsdk_dir = rebase_path("//buildtools/emsdk", "")
+nodejs_dir = rebase_path("//buildtools/nodejs", "")
+
+# This variable is used by the //gn/standalone/toolchain/BUILD.gn.
+em_config = "EMSCRIPTEN_ROOT='$emsdk_dir/emscripten';"
+em_config += "LLVM_ROOT='$emsdk_dir/llvm';"
+em_config += "BINARYEN_ROOT='$emsdk_dir/llvm/binaryen';"
+em_config += "EMSCRIPTEN_NATIVE_OPTIMIZER='$emsdk_dir/llvm/optimizer';"
+em_config += "NODE_JS='$nodejs_dir/bin/node';"
+em_config += "COMPILER_ENGINE=NODE_JS;"
+em_config += "JS_ENGINES=[NODE_JS];"
+em_config = "\"$em_config\""
 
 # Defines a WASM library target.
 # Args:
@@ -34,8 +39,8 @@
   # If the name is foo the target_name must be foo_wasm.
   assert(invoker.name + "_wasm" == target_name)
   _lib_name = invoker.name
+
   if (is_wasm) {
-    _exports = "['ccall', 'callMain', 'addFunction', 'FS']"
     _target_ldflags = [
       "-s",
       "WASM=1",
@@ -44,15 +49,19 @@
       "-s",
       "NO_DYNAMIC_EXECUTION=1",
       "-s",
-      "INITIAL_MEMORY=33554432",
+      "TOTAL_MEMORY=33554432",
       "-s",
       "ALLOW_MEMORY_GROWTH=1",
       "-s",
-      "ALLOW_TABLE_GROWTH=1",
+      "RESERVED_FUNCTION_POINTERS=32",
       "-s",
-      "WASM_ASYNC_COMPILATION=0",
+      "BINARYEN_METHOD='native-wasm'",
       "-s",
-      "EXTRA_EXPORTED_RUNTIME_METHODS=" + _exports,
+      "BINARYEN_TRAP_MODE='clamp'",
+      "-s",
+      "EXPORT_FUNCTION_TABLES=1",
+      "-s",
+      "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap', 'addFunction', 'FS']",
 
       # This forces the MEMFS filesystem library to always use typed arrays
       # instead of building strings/arrays when appending to a file. This allows
@@ -68,27 +77,11 @@
       # JS that overrides the same global variable (var Module = ...)
       "-s",
       "EXPORT_NAME=${target_name}",
-
-      "-lworkerfs.js",  # For FS.filesystems.WORKERFS
     ]
     if (is_debug) {
-      _target_ldflags += [
-        "-s",
-        "ASSERTIONS=2",
-        "-s",
-        "SAFE_HEAP=1",
-        "-s",
-        "STACK_OVERFLOW_CHECK=1",
-        "-g4",
-        "-O0",
-      ]
+      _target_ldflags += [ "-g4" ]
     } else {
-      _target_ldflags += [
-        "-s",
-        "ASSERTIONS=1",
-        "-g2",  # Required for getting C++ symbol names.
-        "-O3",
-      ]
+      _target_ldflags += [ "-O3" ]
     }
 
     if (defined(invoker.js_library)) {
diff --git a/gn/standalone/wasm_typescript_declaration.d.ts b/gn/standalone/wasm_typescript_declaration.d.ts
index 67b0c9b..9fa3538 100644
--- a/gn/standalone/wasm_typescript_declaration.d.ts
+++ b/gn/standalone/wasm_typescript_declaration.d.ts
@@ -63,6 +63,6 @@
     print(s: string): void;
     printErr(s: string): void;
     onRuntimeInitialized(): void;
-    onAbort?(): void;
+    onAbort(): void;
   }
 }
diff --git a/gn/standalone/write_ui_dist_file_map.py b/gn/standalone/write_ui_dist_file_map.py
new file mode 100644
index 0000000..999bea5
--- /dev/null
+++ b/gn/standalone/write_ui_dist_file_map.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+""" Writes a TypeScript dict that contains SHA256s of the passed files.
+
+The output looks like this:
+{
+  hex_digest: '6c761701c5840483833ffb0bd70ae155b2b3c70e8f667c7bd1f6abc98095930',
+  files: {
+    'frontend_bundle.js': 'sha256-2IVKK/3mEMlDdXNADyK03L1cANKbBpU+xue+vnLOcyo=',
+    'index.html': 'sha256-ZRS1+Xh/dFZeWZi/dz8QMWg/8PYQHNdazsNX2oX8s70=',
+    ...
+  }
+}
+"""
+
+from __future__ import print_function
+
+import argparse
+import base64
+import hashlib
+import os
+import sys
+
+from base64 import b64encode
+
+
+def hash_file(file_path):
+  hasher = hashlib.sha256()
+  with open(file_path, 'rb') as f:
+    for chunk in iter(lambda: f.read(32768), b''):
+      hasher.update(chunk)
+    return file_path, hasher.digest()
+
+
+def hash_list_hex(args):
+  hasher = hashlib.sha256()
+  for arg in args:
+    hasher.update(arg)
+  return hasher.hexdigest()
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--out', help='Path of the output file')
+  parser.add_argument(
+      '--strip', help='Strips the leading path in the generated file list')
+  parser.add_argument('file_list', nargs=argparse.REMAINDER)
+  args = parser.parse_args()
+
+  # Compute the hash of each file.
+  digests = dict(map(hash_file, args.file_list))
+
+  contents = '// __generated_by %s\n' % __file__
+  contents += 'export const UI_DIST_MAP = {\n'
+  contents += '  files: {\n'
+  strip = args.strip + ('' if args.strip[-1] == os.path.sep else os.path.sep)
+  for fname, digest in digests.items():
+    if not fname.startswith(strip):
+      raise Exception('%s must start with %s (--strip arg)' % (fname, strip))
+    fname = fname[len(strip):]
+    # We use b64 instead of hexdigest() because it's handy for handling fetch()
+    # subresource integrity.
+    contents += '    \'%s\': \'sha256-%s\',\n' % (fname, b64encode(digest))
+  contents += '  },\n'
+
+  # Compute the hash of the all resources' hashes.
+  contents += '  hex_digest: \'%s\',\n' % hash_list_hex(digests.values())
+  contents += '};\n'
+
+  with open(args.out + '.tmp', 'w') as fout:
+    fout.write(contents)
+  os.rename(args.out + '.tmp', args.out)
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/gn/write_buildflag_header.py b/gn/write_buildflag_header.py
index 617ab7d..702c70f 100644
--- a/gn/write_buildflag_header.py
+++ b/gn/write_buildflag_header.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -67,7 +67,7 @@
   guard = '%s_' % args.out.upper()
   guard = guard.replace('/', '_').replace('\\', '_').replace('.', '_')
   lines = []
-  lines.append('// Generated by %s' % os.path.basename(__file__))
+  lines.append('// Generated by %s' % __file__)
   lines.append('')
   lines.append('// fix_include_guards: off')
   lines.append('#ifndef %s' % guard)
diff --git a/heapprofd.rc b/heapprofd.rc
index bf313b1..dd96325 100644
--- a/heapprofd.rc
+++ b/heapprofd.rc
@@ -25,21 +25,6 @@
     # permission is userdebug_or_eng only.
     capabilities KILL DAC_READ_SEARCH
 
-# Allow to start a second heapprofd. We can use that one to profile the
-# primary one. See src/memory/profiling/README.md.
-service heapprofd_secondary /system/bin/heapprofd
-    disabled
-    oneshot
-    socket heapprofd stream 0666 root root
-    user nobody
-    group nobody readproc
-    # By default, this  daemon is idle. When profiling an app, we should unwind
-    # as fast as possible in the interest of the app being profiled.
-    writepid /dev/cpuset/foreground/tasks
-    # DAC_READ_SEARCH is denied by SELinux on user builds because the SELinux
-    # permission is userdebug_or_eng only.
-    capabilities KILL DAC_READ_SEARCH
-
 on property:persist.heapprofd.enable=1
     start heapprofd
 
diff --git a/include/README.md b/include/README.md
index 3be92c4..6edb3ca 100644
--- a/include/README.md
+++ b/include/README.md
@@ -103,7 +103,7 @@
   });
 ```
 
-The passed lambda will be called only if tracing is enabled and the data source
+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/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 031d7b0..85819b7 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -21,11 +21,8 @@
     "export.h",
     "flat_set.h",
     "logging.h",
-    "platform_handle.h",
     "proc_utils.h",
-    "status.h",
     "task_runner.h",
-    "template_util.h",
     "thread_utils.h",
     "time.h",
   ]
diff --git a/include/perfetto/base/build_config.h b/include/perfetto/base/build_config.h
index bd3623f..047d897 100644
--- a/include/perfetto/base/build_config.h
+++ b/include/perfetto/base/build_config.h
@@ -26,17 +26,16 @@
 
 #if defined(__ANDROID__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #elif defined(__APPLE__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 1
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
@@ -45,62 +44,53 @@
 // Include TARGET_OS_IPHONE when on __APPLE__ systems.
 #include <TargetConditionals.h>
 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 1
-#else
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 1
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #endif
 #elif defined(__linux__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 1
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #elif defined(_WIN32)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 1
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #elif defined(__EMSCRIPTEN__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 1
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #elif defined(__Fuchsia__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 1
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #elif defined(__native_client__)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
 #else
 #error OS not supported (see build_config.h)
 #endif
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
index f0179c6..d6b9b3b 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// Generated by write_buildflag_header.py
+// Generated by ../../gn/write_buildflag_header.py
 
 // fix_include_guards: off
 #ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
@@ -31,12 +31,12 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() ||PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
 
 // clang-format on
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 6745b3f..4bf677e 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-// Generated by write_buildflag_header.py
+// Generated by ../../gn/write_buildflag_header.py
 
 // fix_include_guards: off
 #ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
@@ -31,12 +31,12 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (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_JSON() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() ||PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
 
 // clang-format on
diff --git a/include/perfetto/base/compiler.h b/include/perfetto/base/compiler.h
index b060810..8b4ccda 100644
--- a/include/perfetto/base/compiler.h
+++ b/include/perfetto/base/compiler.h
@@ -17,26 +17,10 @@
 #ifndef INCLUDE_PERFETTO_BASE_COMPILER_H_
 #define INCLUDE_PERFETTO_BASE_COMPILER_H_
 
-#include <stddef.h>
 #include <type_traits>
 
-#include "perfetto/base/build_config.h"
-
-// __has_attribute is supported only by clang and recent versions of GCC.
-// Add a layer to wrap the __has_attribute macro.
-#if defined(__has_attribute)
-#define PERFETTO_HAS_ATTRIBUTE(x) __has_attribute(x)
-#else
-#define PERFETTO_HAS_ATTRIBUTE(x) 0
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
 #define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
 #define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
-#else
-#define PERFETTO_LIKELY(_x) (_x)
-#define PERFETTO_UNLIKELY(_x) (_x)
-#endif
 
 #if defined(__GNUC__) || defined(__clang__)
 #define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
@@ -55,12 +39,6 @@
 #endif
 
 #if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_NORETURN __attribute__((__noreturn__))
-#else
-#define PERFETTO_NORETURN __declspec(noreturn)
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
 #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
 #elif defined(_MSC_VER)
 #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
@@ -76,77 +54,6 @@
 #define PERFETTO_PRINTF_FORMAT(x, y)
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_IOS)
-// TODO(b/158814068): For iOS builds, thread_local is only supported since iOS
-// 8. We'd have to use pthread for thread local data instead here. For now, just
-// define it to nothing since we don't support running perfetto or the client
-// lib on iOS right now.
-#define PERFETTO_THREAD_LOCAL
-#else
-#define PERFETTO_THREAD_LOCAL thread_local
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_POPCOUNT(x) __builtin_popcountll(x)
-#else
-#include <intrin.h>
-#define PERFETTO_POPCOUNT(x) __popcnt64(x)
-#endif
-
-#if defined(__clang__)
-#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
-extern "C" void __asan_poison_memory_region(void const volatile*, size_t);
-extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t);
-#define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
-#define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s))
-#else
-#define PERFETTO_ASAN_POISON(addr, size)
-#define PERFETTO_ASAN_UNPOISON(addr, size)
-#endif  // __has_feature(address_sanitizer)
-#else
-#define PERFETTO_ASAN_POISON(addr, size)
-#define PERFETTO_ASAN_UNPOISON(addr, size)
-#endif  // __clang__
-
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_IS_LITTLE_ENDIAN() __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#else
-// Assume all MSVC targets are little endian.
-#define PERFETTO_IS_LITTLE_ENDIAN() 1
-#endif
-
-// This is used for exporting xxxMain() symbols (e.g., PerfettoCmdMain,
-// ProbesMain) from libperfetto.so when the GN arg monolithic_binaries = false.
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_EXPORT_ENTRYPOINT __attribute__((visibility("default")))
-#else
-// TODO(primiano): on Windows this should be a pair of dllexport/dllimport. But
-// that requires a -DXXX_IMPLEMENTATION depending on whether we are on the
-// impl-site or call-site. Right now it's not worth the trouble as we
-// force-export the xxxMain() symbols only on Android, where we pack all the
-// code for N binaries into one .so to save binary size. On Windows we support
-// only monolithic binaries, as they are easier to deal with.
-#define PERFETTO_EXPORT_ENTRYPOINT
-#endif
-
-// Disables thread safety analysis for functions where the compiler can't
-// accurate figure out which locks are being held.
-#if defined(__clang__)
-#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS \
-  __attribute__((no_thread_safety_analysis))
-#else
-#define PERFETTO_NO_THREAD_SAFETY_ANALYSIS
-#endif
-
-// Avoid calling the exit-time destructor on an object with static lifetime.
-#if PERFETTO_HAS_ATTRIBUTE(no_destroy)
-#define PERFETTO_HAS_NO_DESTROY() 1
-#define PERFETTO_NO_DESTROY __attribute__((no_destroy))
-#else
-#define PERFETTO_HAS_NO_DESTROY() 0
-#define PERFETTO_NO_DESTROY
-#endif
-
 namespace perfetto {
 namespace base {
 
diff --git a/include/perfetto/base/flat_set.h b/include/perfetto/base/flat_set.h
index 9390537..068ad3c 100644
--- a/include/perfetto/base/flat_set.h
+++ b/include/perfetto/base/flat_set.h
@@ -48,7 +48,7 @@
 
   FlatSet() = default;
 
-  // Mainly for tests. Deliberately not marked as "explicit".
+  // Mainly for tests. Deliberately not marked as "expicit".
   FlatSet(std::initializer_list<T> initial) : entries_(initial) {
     std::sort(entries_.begin(), entries_.end());
     entries_.erase(std::unique(entries_.begin(), entries_.end()),
diff --git a/include/perfetto/base/logging.h b/include/perfetto/base/logging.h
index 8641a1c..aeebf0b 100644
--- a/include/perfetto/base/logging.h
+++ b/include/perfetto/base/logging.h
@@ -24,10 +24,8 @@
 #include "perfetto/base/compiler.h"
 #include "perfetto/base/export.h"
 
-#if defined(__GNUC__) || defined(__clang__)
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
 #pragma GCC system_header
-#endif
 
 // TODO(primiano): move this to base/build_config.h, turn into
 // PERFETTO_BUILDFLAG(DCHECK_IS_ON) and update call sites to use that instead.
@@ -80,19 +78,6 @@
 
 enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
 
-struct LogMessageCallbackArgs {
-  LogLev level;
-  int line;
-  const char* filename;
-  const char* message;
-};
-
-using LogMessageCallback = void (*)(LogMessageCallbackArgs);
-
-// This is not thread safe and must be called before using tracing from other
-// threads.
-PERFETTO_EXPORT void SetLogMessageCallback(LogMessageCallback callback);
-
 PERFETTO_EXPORT void LogMessage(LogLev,
                                 const char* fname,
                                 int line,
@@ -106,27 +91,17 @@
                           "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \
                           __LINE__, ##__VA_ARGS__);                           \
   } while (0)
-#elif defined(PERFETTO_DISABLE_LOG)
-#define PERFETTO_XLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
-#else
+#else  // defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
 #define PERFETTO_XLOG(level, fmt, ...)                                      \
   ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \
                                __LINE__, fmt, ##__VA_ARGS__)
-#endif
+#endif  // defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
 
-#if defined(_MSC_VER)
-#define PERFETTO_IMMEDIATE_CRASH() \
-  do {                             \
-    __debugbreak();                \
-    __assume(0);                   \
-  } while (0)
-#else
 #define PERFETTO_IMMEDIATE_CRASH() \
   do {                             \
     __builtin_trap();              \
     __builtin_unreachable();       \
   } while (0)
-#endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
 #define PERFETTO_LOG(fmt, ...) \
@@ -145,34 +120,16 @@
     PERFETTO_IMMEDIATE_CRASH();        \
   } while (0)
 
-#if defined(__GNUC__) || defined(__clang__)
 #define PERFETTO_PLOG(x, ...) \
   PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
-#else
-// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
-#define PERFETTO_PLOG PERFETTO_ELOG
-#endif
-
-#define PERFETTO_CHECK(x)                            \
-  do {                                               \
-    if (PERFETTO_UNLIKELY(!(x))) {                   \
-      PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
-      PERFETTO_IMMEDIATE_CRASH();                    \
-    }                                                \
-  } while (0)
 
 #if PERFETTO_DLOG_IS_ON()
 
 #define PERFETTO_DLOG(fmt, ...) \
   PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__)
 
-#if defined(__GNUC__) || defined(__clang__)
 #define PERFETTO_DPLOG(x, ...) \
   PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
-#else
-// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
-#define PERFETTO_DPLOG PERFETTO_DLOG
-#endif
 
 #else  // PERFETTO_DLOG_IS_ON()
 
@@ -183,8 +140,22 @@
 
 #if PERFETTO_DCHECK_IS_ON()
 
-#define PERFETTO_DCHECK(x) PERFETTO_CHECK(x)
-#define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__)
+#define PERFETTO_DCHECK(x)                           \
+  do {                                               \
+    if (PERFETTO_UNLIKELY(!(x))) {                   \
+      PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
+      PERFETTO_IMMEDIATE_CRASH();                    \
+    }                                                \
+  } while (0)
+
+#define PERFETTO_CHECK(x) PERFETTO_DCHECK(x)
+
+#define PERFETTO_DFATAL(fmt, ...)      \
+  do {                                 \
+    PERFETTO_PLOG(fmt, ##__VA_ARGS__); \
+    PERFETTO_IMMEDIATE_CRASH();        \
+  } while (0)
+
 #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__)
 
 #else  // PERFETTO_DCHECK_IS_ON()
@@ -193,6 +164,14 @@
   do {                     \
   } while (false && (x))
 
+#define PERFETTO_CHECK(x)                            \
+  do {                                               \
+    if (PERFETTO_UNLIKELY(!(x))) {                   \
+      PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
+      PERFETTO_IMMEDIATE_CRASH();                    \
+    }                                                \
+  } while (0)
+
 #define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__)
 #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__)
 
diff --git a/include/perfetto/base/platform_handle.h b/include/perfetto/base/platform_handle.h
deleted file mode 100644
index 879fa85..0000000
--- a/include/perfetto/base/platform_handle.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
-#define INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
-
-#include "perfetto/base/build_config.h"
-
-namespace perfetto {
-namespace base {
-
-// PlatformHandle should be used only for types that are HANDLE(s) in Windows.
-// It should NOT be used to blanket-replace "int fd" in the codebase.
-// Windows has two types of "handles", which, in UNIX-land, both map to int:
-// 1. File handles returned by the posix-compatibility API like _open().
-//    These are just int(s) and should stay such, because all the posix-like API
-//    in Windows.h take an int, not a HANDLE.
-// 2. Handles returned by old-school WINAPI like CreateFile, CreateEvent etc.
-//    These are proper HANDLE(s). PlatformHandle should be used here.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// Windows.h typedefs HANDLE to void*. We use void* here to avoid leaking
-// Windows.h through our headers.
-using PlatformHandle = void*;
-
-// On Windows both nullptr and 0xffff... (INVALID_HANDLE_VALUE) are invalid.
-struct PlatformHandleChecker {
-  static inline bool IsValid(PlatformHandle h) {
-    return h && h != reinterpret_cast<PlatformHandle>(-1);
-  }
-};
-#else
-using PlatformHandle = int;
-struct PlatformHandleChecker {
-  static inline bool IsValid(PlatformHandle h) { return h >= 0; }
-};
-#endif
-
-// The definition of this lives in base/file_utils.cc (to avoid creating an
-// extra build edge for a one liner). This is really an alias for close() (UNIX)
-// CloseHandle() (Windows). THe indirection layer is just to avoid leaking
-// system headers like Windows.h through perfetto headers.
-// Thre return value is always UNIX-style: 0 on success, -1 on failure.
-int ClosePlatformHandle(PlatformHandle);
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_BASE_PLATFORM_HANDLE_H_
diff --git a/include/perfetto/base/status.h b/include/perfetto/base/status.h
deleted file mode 100644
index c48d86a..0000000
--- a/include/perfetto/base/status.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 INCLUDE_PERFETTO_BASE_STATUS_H_
-#define INCLUDE_PERFETTO_BASE_STATUS_H_
-
-#include <string>
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace base {
-
-// 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 msg) : ok_(false), message_(std::move(msg)) {
-    PERFETTO_CHECK(!message_.empty());
-  }
-
-  // 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_; }
-
-  // When ok() is false this returns the error message. Returns the empty string
-  // otherwise.
-  const std::string& message() const { return message_; }
-  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();
-}
-
-PERFETTO_PRINTF_FORMAT(1, 2) Status ErrStatus(const char* format, ...);
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_BASE_STATUS_H_
diff --git a/include/perfetto/base/task_runner.h b/include/perfetto/base/task_runner.h
index 4f64bf8..040aab2 100644
--- a/include/perfetto/base/task_runner.h
+++ b/include/perfetto/base/task_runner.h
@@ -22,7 +22,6 @@
 #include <functional>
 
 #include "perfetto/base/export.h"
-#include "perfetto/base/platform_handle.h"
 
 namespace perfetto {
 namespace base {
@@ -50,19 +49,18 @@
   // called from any thread.
   virtual void PostDelayedTask(std::function<void()>, uint32_t delay_ms) = 0;
 
-  // Schedule a task to run when the handle becomes readable. The same handle
-  // can only be monitored by one function. Note that this function only needs
-  // to be implemented on platforms where the built-in ipc framework is used.
-  // Can be called from any thread.
+  // Schedule a task to run when |fd| becomes readable. The same |fd| can only
+  // be monitored by one function. Note that this function only needs to be
+  // implemented on platforms where the built-in ipc framework is used. Can be
+  // called from any thread.
   // TODO(skyostil): Refactor this out of the shared interface.
-  virtual void AddFileDescriptorWatch(PlatformHandle,
-                                      std::function<void()>) = 0;
+  virtual void AddFileDescriptorWatch(int fd, std::function<void()>) = 0;
 
-  // Remove a previously scheduled watch for the handle. If this is run on the
-  // target thread of this TaskRunner, guarantees that the task registered to
-  // this handle will not be executed after this function call.
-  // Can be called from any thread.
-  virtual void RemoveFileDescriptorWatch(PlatformHandle) = 0;
+  // Remove a previously scheduled watch for |fd|. If this is run on the target
+  // thread of this TaskRunner, guarantees that the task registered to this fd
+  // will not be executed after this function call. Can be called from any
+  // thread.
+  virtual void RemoveFileDescriptorWatch(int fd) = 0;
 
   // Checks if the current thread is the same thread where the TaskRunner's task
   // run. This allows single threaded task runners (like the ones used in
diff --git a/include/perfetto/base/template_util.h b/include/perfetto/base/template_util.h
deleted file mode 100644
index 4a5359c..0000000
--- a/include/perfetto/base/template_util.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TEMPLATE_UTIL_H_
-#define INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
-
-#include <cstddef>
-#include <type_traits>
-
-namespace perfetto {
-namespace base {
-
-// Helper to express preferences in an overload set. If more than one overload
-// is available for a given set of parameters the overload with the higher
-// priority will be chosen.
-template <size_t I>
-struct priority_tag : priority_tag<I - 1> {};
-
-template <>
-struct priority_tag<0> {};
-
-// enable_if_t is an implementation of std::enable_if_t from C++14.
-//
-// Specification:
-// https://en.cppreference.com/w/cpp/types/enable_if
-template <bool B, class T = void>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-// decay_t is an implementation of std::decay_t from C++14.
-//
-// Specification:
-// https://en.cppreference.com/w/cpp/types/decay
-template <class T>
-using decay_t = typename std::decay<T>::type;
-
-// remove_cvref is an implementation of std::remove_cvref from
-// C++20.
-//
-// Specification:
-// https://en.cppreference.com/w/cpp/types/remove_cvref
-
-template <class T>
-struct remove_cvref {
-  using type = typename std::remove_cv<typename std::remove_cv<
-      typename std::remove_reference<T>::type>::type>::type;
-};
-template <class T>
-using remove_cvref_t = typename remove_cvref<T>::type;
-
-// Check if a given type is a specialization of a given template:
-// is_specialization<T, std::vector>::value.
-
-template <typename Type, template <typename...> class Template>
-struct is_specialization : std::false_type {};
-
-template <template <typename...> class Ref, typename... Args>
-struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_
diff --git a/include/perfetto/base/thread_utils.h b/include/perfetto/base/thread_utils.h
index 48a6508..39f2f1b 100644
--- a/include/perfetto/base/thread_utils.h
+++ b/include/perfetto/base/thread_utils.h
@@ -54,7 +54,7 @@
 inline PlatformThreadId GetThreadId() {
   return zx_thread_self();
 }
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 using PlatformThreadId = uint64_t;
 inline PlatformThreadId GetThreadId() {
   uint64_t tid;
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
index de966f5..0ee6042 100644
--- a/include/perfetto/base/time.h
+++ b/include/perfetto/base/time.h
@@ -20,12 +20,11 @@
 #include <time.h>
 
 #include <chrono>
-#include <string>
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #include <mach/mach_init.h>
 #include <mach/mach_port.h>
 #include <mach/mach_time.h>
@@ -59,7 +58,7 @@
   return GetWallTimeNs();
 }
 
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 
 inline TimeNanos GetWallTimeNs() {
   auto init_time_factor = []() -> uint64_t {
@@ -180,8 +179,6 @@
   return ts;
 }
 
-std::string GetTimeFmt(const std::string& fmt);
-
 }  // namespace base
 }  // namespace perfetto
 
diff --git a/include/perfetto/ext/base/BUILD.gn b/include/perfetto/ext/base/BUILD.gn
index ec8cca8..e2d29b5 100644
--- a/include/perfetto/ext/base/BUILD.gn
+++ b/include/perfetto/ext/base/BUILD.gn
@@ -18,19 +18,15 @@
   sources = [
     "circular_queue.h",
     "container_annotations.h",
-    "ctrl_c_handler.h",
-    "endian.h",
     "event_fd.h",
     "file_utils.h",
-    "getopt.h",
-    "getopt_compat.h",
     "hash.h",
+    "lookup_set.h",
     "metatrace.h",
     "metatrace_events.h",
     "no_destructor.h",
     "optional.h",
     "paged_memory.h",
-    "periodic_task.h",
     "pipe.h",
     "scoped_file.h",
     "small_set.h",
@@ -47,7 +43,6 @@
     "unix_task_runner.h",
     "utils.h",
     "uuid.h",
-    "version.h",
     "waitable_event.h",
     "watchdog.h",
     "watchdog_noop.h",
diff --git a/include/perfetto/ext/base/circular_queue.h b/include/perfetto/ext/base/circular_queue.h
index 8d1f1b7..de7db0e 100644
--- a/include/perfetto/ext/base/circular_queue.h
+++ b/include/perfetto/ext/base/circular_queue.h
@@ -67,22 +67,26 @@
       ignore_result(generation);
     }
 
-    Iterator(const Iterator&) noexcept = default;
-    Iterator& operator=(const Iterator&) noexcept = default;
-    Iterator(Iterator&&) noexcept = default;
-    Iterator& operator=(Iterator&&) noexcept = default;
-
-    T* operator->() const {
+    T* operator->() {
 #if PERFETTO_DCHECK_IS_ON()
       PERFETTO_DCHECK(generation_ == queue_->generation());
 #endif
       return queue_->Get(pos_);
     }
 
-    T& operator*() const { return *(operator->()); }
+    const T* operator->() const {
+      return const_cast<CircularQueue<T>::Iterator*>(this)->operator->();
+    }
+
+    T& operator*() { return *(operator->()); }
+    const T& operator*() const { return *(operator->()); }
 
     value_type& operator[](difference_type i) { return *(*this + i); }
 
+    const value_type& operator[](difference_type i) const {
+      return const_cast<CircularQueue<T>::Iterator&>(*this)[i];
+    }
+
     Iterator& operator++() {
       Add(1);
       return *this;
@@ -190,7 +194,7 @@
       PERFETTO_DCHECK(empty());
       return;
     }
-    clear();  // Invoke destructors on all alive entries.
+    erase_front(size());  // Invoke destructors on all alive entries.
     PERFETTO_DCHECK(empty());
     free(entries_);
   }
@@ -214,8 +218,6 @@
 
   void pop_front() { erase_front(1); }
 
-  void clear() { erase_front(size()); }
-
   T& at(size_t idx) {
     PERFETTO_DCHECK(idx < size());
     return *Get(begin_ + idx);
diff --git a/include/perfetto/ext/base/ctrl_c_handler.h b/include/perfetto/ext/base/ctrl_c_handler.h
deleted file mode 100644
index 6c7b34c..0000000
--- a/include/perfetto/ext/base/ctrl_c_handler.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_CTRL_C_HANDLER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_
-
-namespace perfetto {
-namespace base {
-
-// On Linux/Android/Mac: installs SIGINT + SIGTERM signal handlers.
-// On Windows: installs a SetConsoleCtrlHandler() handler.
-// The passed handler must be async safe.
-using CtrlCHandlerFunction = void (*)();
-void InstallCtrCHandler(CtrlCHandlerFunction);
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_
diff --git a/include/perfetto/ext/base/endian.h b/include/perfetto/ext/base/endian.h
deleted file mode 100644
index b18979f..0000000
--- a/include/perfetto/ext/base/endian.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_ENDIAN_H_
-#define INCLUDE_PERFETTO_EXT_BASE_ENDIAN_H_
-
-#include <stdint.h>
-#include <stdlib.h>  // For MSVC
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-
-#if !PERFETTO_IS_LITTLE_ENDIAN()
-#error "endian.h supports only little-endian archs"
-#endif
-
-namespace perfetto {
-namespace base {
-
-#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
-inline uint16_t HostToBE16(uint16_t x) {
-  return _byteswap_ushort(x);
-}
-inline uint32_t HostToBE32(uint32_t x) {
-  return _byteswap_ulong(x);
-}
-inline uint64_t HostToBE64(uint64_t x) {
-  return _byteswap_uint64(x);
-}
-#else
-inline uint16_t HostToBE16(uint16_t x) {
-  return __builtin_bswap16(x);
-}
-inline uint32_t HostToBE32(uint32_t x) {
-  return __builtin_bswap32(x);
-}
-inline uint64_t HostToBE64(uint64_t x) {
-  return __builtin_bswap64(x);
-}
-#endif
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_ENDIAN_H_
diff --git a/include/perfetto/ext/base/event_fd.h b/include/perfetto/ext/base/event_fd.h
index e4bd6e9..9e1715b 100644
--- a/include/perfetto/ext/base/event_fd.h
+++ b/include/perfetto/ext/base/event_fd.h
@@ -18,9 +18,15 @@
 #define INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/platform_handle.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 {
 
@@ -35,7 +41,7 @@
   EventFd& operator=(EventFd&&) = default;
 
   // The non-blocking file descriptor that can be polled to wait for the event.
-  PlatformHandle fd() const { return event_handle_.get(); }
+  int fd() const { return fd_.get(); }
 
   // Can be called from any thread.
   void Notify();
@@ -47,12 +53,9 @@
  private:
   // The eventfd, when eventfd is supported, otherwise this is the read end of
   // the pipe for fallback mode.
-  ScopedPlatformHandle event_handle_;
+  ScopedFile fd_;
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) &&   \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // On Mac and other non-Linux UNIX platforms a pipe-based fallback is used.
+#if !PERFETTO_USE_EVENTFD()
   // The write end of the wakeup pipe.
   ScopedFile write_fd_;
 #endif
diff --git a/include/perfetto/ext/base/file_utils.h b/include/perfetto/ext/base/file_utils.h
index bf33d70..9ff03b1 100644
--- a/include/perfetto/ext/base/file_utils.h
+++ b/include/perfetto/ext/base/file_utils.h
@@ -17,36 +17,19 @@
 #ifndef INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
 #define INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
 
-#include <fcntl.h>  // For mode_t & O_RDONLY/RDWR. Exists also on Windows.
 #include <stddef.h>
 
 #include <string>
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/export.h"
-#include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 namespace base {
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using FileOpenMode = int;
-#else
-using FileOpenMode = mode_t;
-#endif
-
-constexpr FileOpenMode kFileModeInvalid = static_cast<FileOpenMode>(-1);
-
-bool ReadPlatformHandle(PlatformHandle, std::string* out);
 bool ReadFileDescriptor(int fd, std::string* out);
 bool ReadFileStream(FILE* f, std::string* out);
 bool ReadFile(const std::string& path, std::string* out);
 
-// A wrapper around read(2). It deals with Linux vs Windows includes. It also
-// deals with handling EINTR. Has the same semantics of UNIX's read(2).
-ssize_t Read(int fd, void* dst, size_t dst_size);
-
 // Call write until all data is written or an error is detected.
 //
 // man 2 write:
@@ -56,28 +39,8 @@
 //   succeeds, and returns the number of bytes written.
 ssize_t WriteAll(int fd, const void* buf, size_t count);
 
-ssize_t WriteAllHandle(PlatformHandle, const void* buf, size_t count);
-
-ScopedFile OpenFile(const std::string& path,
-                    int flags,
-                    FileOpenMode = kFileModeInvalid);
-
-// This is an alias for close(). It's to avoid leaking Windows.h in headers.
-// Exported because ScopedFile is used in the /include/ext API by Chromium
-// component builds.
-int PERFETTO_EXPORT CloseFile(int fd);
-
 bool FlushFile(int fd);
 
-// Returns true if mkdir succeeds, false if it fails (see errno in that case).
-bool Mkdir(const std::string& path);
-
-// Calls rmdir() on UNIX, _rmdir() on Windows.
-bool Rmdir(const std::string& path);
-
-// Wrapper around access(path, F_OK).
-bool FileExists(const std::string& path);
-
 }  // namespace base
 }  // namespace perfetto
 
diff --git a/include/perfetto/ext/base/getopt.h b/include/perfetto/ext/base/getopt.h
deleted file mode 100644
index 77c1490..0000000
--- a/include/perfetto/ext/base/getopt.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_GETOPT_H_
-#define INCLUDE_PERFETTO_EXT_BASE_GETOPT_H_
-
-// This is the header that should be included in all places that need getopt.h.
-// This either routes on the sysroot getopt.h, for OSes that have one (all but
-// Windows) or routes on the home-brewed getopt_compat.h.
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include "perfetto/ext/base/getopt_compat.h"
-
-// getopt_compat.h puts everything in a nested namespace, to allow
-// getopt_compat_unittest.cc to use both <getopt.h> and "getopt_compat.h"
-// without collisions.
-
-// Here we expose them into the root namespace, because we want offer a drop-in
-// replacement to the various main.cc, which can't know about the nested
-// namespace.
-using ::perfetto::base::getopt_compat::optarg;
-using ::perfetto::base::getopt_compat::optind;
-using ::perfetto::base::getopt_compat::option;
-constexpr auto getopt = ::perfetto::base::getopt_compat::getopt;
-constexpr auto getopt_long = ::perfetto::base::getopt_compat::getopt_long;
-constexpr auto no_argument = ::perfetto::base::getopt_compat::no_argument;
-constexpr auto required_argument =
-    ::perfetto::base::getopt_compat::required_argument;
-
-#else
-#include <getopt.h>
-#endif
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_GETOPT_H_
diff --git a/include/perfetto/ext/base/getopt_compat.h b/include/perfetto/ext/base/getopt_compat.h
deleted file mode 100644
index d1f5436..0000000
--- a/include/perfetto/ext/base/getopt_compat.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_GETOPT_COMPAT_H_
-#define INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_
-
-#include <cstddef>  // For std::nullptr_t
-
-// No translation units other than base/getopt.h and getopt_compat_unittest.cc
-// should directly include this file. Use base/getopt.h instead.
-
-namespace perfetto {
-namespace base {
-namespace getopt_compat {
-
-// A tiny getopt() replacement for Windows, which doesn't have <getopt.h>.
-// This implementation is based on the subset of features that we use in the
-// Perfetto codebase. It doesn't even try to deal with the full surface of GNU's
-// getopt().
-// Limitations:
-// - getopt_long_only() is not supported.
-// - optional_argument is not supported. That is extremely subtle and caused us
-//   problems in the past with GNU's getopt.
-// - It does not reorder non-option arguments. It behaves like MacOS getopt, or
-//   GNU's when POSIXLY_CORRECT=1.
-// - Doesn't expose optopt or opterr.
-// - option.flag and longindex are not supported and must be nullptr.
-
-enum {
-  no_argument = 0,
-  required_argument = 1,
-};
-
-struct option {
-  const char* name;
-  int has_arg;
-  std::nullptr_t flag;  // Only nullptr is supported.
-  int val;
-};
-
-extern char* optarg;
-extern int optind;
-
-int getopt_long(int argc,
-                char** argv,
-                const char* shortopts,
-                const option* longopts,
-                std::nullptr_t /*longindex is not supported*/);
-
-int getopt(int argc, char** argv, const char* shortopts);
-
-}  // namespace getopt_compat
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_
diff --git a/include/perfetto/ext/base/hash.h b/include/perfetto/ext/base/hash.h
index 6ec9fbe..87b1a54 100644
--- a/include/perfetto/ext/base/hash.h
+++ b/include/perfetto/ext/base/hash.h
@@ -34,9 +34,8 @@
   Hash() {}
 
   // Hashes a numeric value.
-  template <
-      typename T,
-      typename std::enable_if<std::is_arithmetic<T>::value, bool>::type = true>
+  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));
   }
diff --git a/include/perfetto/ext/base/lookup_set.h b/include/perfetto/ext/base/lookup_set.h
new file mode 100644
index 0000000..2e31a52
--- /dev/null
+++ b/include/perfetto/ext/base/lookup_set.h
@@ -0,0 +1,68 @@
+/*
+ * 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); }
+
+  void Clear() { set_.clear(); }
+
+  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
index 59b8b3f..f5eb057 100644
--- a/include/perfetto/ext/base/metatrace.h
+++ b/include/perfetto/ext/base/metatrace.h
@@ -26,6 +26,7 @@
 #include "perfetto/base/thread_utils.h"
 #include "perfetto/base/time.h"
 #include "perfetto/ext/base/metatrace_events.h"
+#include "perfetto/ext/base/thread_annotations.h"
 #include "perfetto/ext/base/utils.h"
 
 // A facility to trace execution of the perfetto codebase itself.
@@ -88,7 +89,10 @@
 // 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);
-  return PERFETTO_UNLIKELY((enabled_tags & tag) != 0);
+  if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
+    return false;
+  else
+    return true;
 }
 
 // Holds the data for a metatrace event or counter.
@@ -139,7 +143,7 @@
     // 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.
+    int32_t counter_value;  // If type == counter.
   };
 };
 
diff --git a/include/perfetto/ext/base/optional.h b/include/perfetto/ext/base/optional.h
index f9ef9ff..b093510 100644
--- a/include/perfetto/ext/base/optional.h
+++ b/include/perfetto/ext/base/optional.h
@@ -888,11 +888,15 @@
 }  // namespace base
 }  // namespace perfetto
 
+namespace std {
+
 template <class T>
-struct std::hash<perfetto::base::Optional<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
index 0afd6b8..f0ed568 100644
--- a/include/perfetto/ext/base/paged_memory.h
+++ b/include/perfetto/ext/base/paged_memory.h
@@ -56,8 +56,9 @@
   };
 
   // Allocates |size| bytes using mmap(MAP_ANONYMOUS). The returned memory is
-  // guaranteed to be page-aligned and guaranteed to be zeroed.
-  // For |flags|, see the AllocationFlags enum above.
+  // 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.
@@ -87,10 +88,6 @@
   PagedMemory& operator=(const PagedMemory&) = default;
 
   char* p_ = nullptr;
-
-  // The size originally passed to Allocate(). The actual virtual memory
-  // reservation will be larger due to: (i) guard pages; (ii) rounding up to
-  // the system page size.
   size_t size_ = 0;
 
 #if TRACK_COMMITTED_SIZE()
diff --git a/include/perfetto/ext/base/periodic_task.h b/include/perfetto/ext/base/periodic_task.h
deleted file mode 100644
index b948322..0000000
--- a/include/perfetto/ext/base/periodic_task.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_PERIODIC_TASK_H_
-#define INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
-
-#include <functional>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/weak_ptr.h"
-
-namespace perfetto {
-namespace base {
-
-class TaskRunner;
-
-// A periodic task utility class. It wraps the logic necessary to do periodic
-// tasks using a TaskRunner, taking care of subtleties like ensuring that
-// outstanding tasks are cancelled after reset/dtor.
-// Tasks are aligned on wall time, this is to ensure that when using multiple
-// periodic tasks, they happen at the same time, minimizing wakeups.
-// On Linux/Android it also supports suspend-aware mode (via timerfd). On other
-// operating systems it falls back to PostDelayedTask, which is not
-// suspend-aware.
-// TODO(primiano): this should probably become a periodic timer scheduler, so we
-// can use one FD for everything rather than one FD per task. For now we take
-// the hit of a FD-per-task to keep this low-risk.
-class PeriodicTask {
- public:
-  explicit PeriodicTask(base::TaskRunner*);
-  ~PeriodicTask();  // Calls Reset().
-
-  struct Args {
-    uint32_t period_ms = 0;
-    std::function<void()> task = nullptr;
-    bool start_first_task_immediately = false;
-    bool use_suspend_aware_timer = false;
-  };
-
-  void Start(Args);
-
-  // Safe to be called multiple times, even without calling Start():
-  void Reset();
-
-  // No copy or move. WeakPtr-wrapped pointers to |this| are posted on the
-  // task runner, this class is not easily movable.
-  PeriodicTask(const PeriodicTask&) = delete;
-  PeriodicTask& operator=(const PeriodicTask&) = delete;
-  PeriodicTask(PeriodicTask&&) = delete;
-  PeriodicTask& operator=(PeriodicTask&&) = delete;
-
-  base::PlatformHandle timer_fd_for_testing() { return *timer_fd_; }
-
- private:
-  static void RunTaskAndPostNext(base::WeakPtr<PeriodicTask>,
-                                 uint32_t generation);
-  void PostNextTask();
-  void ResetTimerFd();
-
-  base::TaskRunner* const task_runner_;
-  Args args_;
-  uint32_t generation_ = 0;
-  base::ScopedPlatformHandle timer_fd_;
-
-  PERFETTO_THREAD_CHECKER(thread_checker_)
-  base::WeakPtrFactory<PeriodicTask> weak_ptr_factory_;  // Keep last.
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
diff --git a/include/perfetto/ext/base/pipe.h b/include/perfetto/ext/base/pipe.h
index 840296d..ba22729 100644
--- a/include/perfetto/ext/base/pipe.h
+++ b/include/perfetto/ext/base/pipe.h
@@ -17,7 +17,6 @@
 #ifndef INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
 #define INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
 
-#include "perfetto/base/platform_handle.h"
 #include "perfetto/ext/base/scoped_file.h"
 
 namespace perfetto {
@@ -27,11 +26,9 @@
  public:
   enum Flags {
     kBothBlock = 0,
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
     kBothNonBlock,
     kRdNonBlock,
     kWrNonBlock,
-#endif
   };
 
   static Pipe Create(Flags = kBothBlock);
@@ -40,8 +37,8 @@
   Pipe(Pipe&&) noexcept;
   Pipe& operator=(Pipe&&);
 
-  ScopedPlatformHandle rd;
-  ScopedPlatformHandle wr;
+  ScopedFile rd;
+  ScopedFile wr;
 };
 
 }  // namespace base
diff --git a/include/perfetto/ext/base/scoped_file.h b/include/perfetto/ext/base/scoped_file.h
index 5a99de6..24c8970 100644
--- a/include/perfetto/ext/base/scoped_file.h
+++ b/include/perfetto/ext/base/scoped_file.h
@@ -19,43 +19,34 @@
 
 #include "perfetto/base/build_config.h"
 
+#include <fcntl.h>
 #include <stdio.h>
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <dirent.h>  // For DIR* / opendir().
+#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/export.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/base/platform_handle.h"
 
 namespace perfetto {
 namespace base {
 
-namespace internal {
-// Used for the most common cases of ScopedResource where there is only one
-// invalid value.
-template <typename T, T InvalidValue>
-struct DefaultValidityChecker {
-  static bool IsValid(T t) { return t != InvalidValue; }
-};
-}  // namespace internal
+constexpr mode_t kInvalidMode = static_cast<mode_t>(-1);
 
 // RAII classes for auto-releasing fds and dirs.
-// if T is a pointer type, InvalidValue must be nullptr. Doing otherwise
-// causes weird unexpected behaviors (See https://godbolt.org/z/5nGMW4).
 template <typename T,
           int (*CloseFunction)(T),
           T InvalidValue,
-          bool CheckClose = true,
-          class Checker = internal::DefaultValidityChecker<T, InvalidValue>>
-class PERFETTO_EXPORT ScopedResource {
+          bool CheckClose = true>
+class ScopedResource {
  public:
-  using ValidityChecker = Checker;
-  static constexpr T kInvalid = InvalidValue;
-
   explicit ScopedResource(T t = InvalidValue) : t_(t) {}
   ScopedResource(ScopedResource&& other) noexcept {
     t_ = other.t_;
@@ -68,9 +59,9 @@
   }
   T get() const { return t_; }
   T operator*() const { return t_; }
-  explicit operator bool() const { return Checker::IsValid(t_); }
+  explicit operator bool() const { return t_ != InvalidValue; }
   void reset(T r = InvalidValue) {
-    if (Checker::IsValid(t_)) {
+    if (t_ != InvalidValue) {
       int res = CloseFunction(t_);
       if (CheckClose)
         PERFETTO_CHECK(res == 0);
@@ -87,35 +78,30 @@
  private:
   ScopedResource(const ScopedResource&) = delete;
   ScopedResource& operator=(const ScopedResource&) = delete;
+
   T t_;
 };
 
-// Declared in file_utils.h. Forward declared to avoid #include cycles.
-int PERFETTO_EXPORT CloseFile(int fd);
-
-// Use this for file resources obtained via open() and similar APIs.
-using ScopedFile = ScopedResource<int, CloseFile, -1>;
-using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>;
-
-// Use this for resources that are HANDLE on Windows. See comments in
-// platform_handle.h
+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)
-using ScopedPlatformHandle = ScopedResource<PlatformHandle,
-                                            ClosePlatformHandle,
-                                            /*InvalidValue=*/nullptr,
-                                            /*CheckClose=*/true,
-                                            PlatformHandleChecker>;
+  // Always use O_BINARY on Windows, to avoid silly EOL translations.
+  ScopedFile fd(open(path.c_str(), flags | O_BINARY, mode));
 #else
-// On non-windows systems we alias ScopedPlatformHandle to ScopedFile because
-// they are really the same. This is to allow assignments between the two in
-// Linux-specific code paths that predate ScopedPlatformHandle.
-static_assert(std::is_same<int, PlatformHandle>::value, "");
-using ScopedPlatformHandle = ScopedFile;
-
-// DIR* does not exist on Windows.
+  // 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
 
diff --git a/include/perfetto/ext/base/string_utils.h b/include/perfetto/ext/base/string_utils.h
index bd4f1f6..df2de4b 100644
--- a/include/perfetto/ext/base/string_utils.h
+++ b/include/perfetto/ext/base/string_utils.h
@@ -29,8 +29,6 @@
 namespace perfetto {
 namespace base {
 
-std::string QuoteAndEscapeControlCodes(const std::string& raw);
-
 inline char Lowercase(char c) {
   return ('A' <= c && c <= 'Z') ? static_cast<char>(c - ('A' - 'a')) : c;
 }
@@ -64,11 +62,9 @@
   return (*s && !*endptr) ? base::make_optional(value) : base::nullopt;
 }
 
-double StrToD(const char* nptr, char** endptr);
-
 inline Optional<double> CStringToDouble(const char* s) {
   char* endptr = nullptr;
-  double value = StrToD(s, &endptr);
+  double value = strtod(s, &endptr);
   Optional<double> result(base::nullopt);
   if (*s != '\0' && *endptr == '\0')
     result = value;
@@ -98,7 +94,6 @@
 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);
-bool Contains(const std::string& haystack, char 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,
@@ -117,13 +112,6 @@
   return ToHex(s.c_str(), s.size());
 }
 std::string IntToHexString(uint32_t number);
-std::string Uint64ToHexString(uint64_t number);
-std::string Uint64ToHexStringNoPrefix(uint64_t number);
-std::string ReplaceAll(std::string str,
-                       const std::string& to_replace,
-                       const std::string& replacement);
-std::string TrimLeading(const std::string& str);
-std::string Base64Encode(const void* raw, size_t size);
 
 }  // namespace base
 }  // namespace perfetto
diff --git a/include/perfetto/ext/base/string_view.h b/include/perfetto/ext/base/string_view.h
index dce2fdc..cd8ef61 100644
--- a/include/perfetto/ext/base/string_view.h
+++ b/include/perfetto/ext/base/string_view.h
@@ -168,11 +168,15 @@
 }  // namespace base
 }  // namespace perfetto
 
+namespace std {
+
 template <>
-struct std::hash<::perfetto::base::StringView> {
+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
index cee3198..428b17e 100644
--- a/include/perfetto/ext/base/string_writer.h
+++ b/include/perfetto/ext/base/string_writer.h
@@ -71,13 +71,7 @@
   template <char padchar, uint64_t padding>
   void AppendPaddedInt(int64_t sign_value) {
     const bool negate = std::signbit(static_cast<double>(sign_value));
-    uint64_t absolute_value;
-    if (sign_value == std::numeric_limits<int64_t>::min()) {
-      absolute_value =
-          static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1;
-    } else {
-      absolute_value = static_cast<uint64_t>(std::abs(sign_value));
-    }
+    uint64_t absolute_value = static_cast<uint64_t>(std::abs(sign_value));
     AppendPaddedInt<padchar, padding>(absolute_value, negate);
   }
 
@@ -160,9 +154,7 @@
 
     if (padding > 0) {
       size_t num_digits = kSizeNeeded - 1 - idx;
-      // std::max() needed to work around GCC not being able to tell that
-      // padding > 0.
-      for (size_t i = num_digits; i < std::max(uint64_t{1u}, padding); i++) {
+      for (size_t i = num_digits; i < padding; i++) {
         data[idx--] = padchar;
       }
     }
diff --git a/include/perfetto/ext/base/subprocess.h b/include/perfetto/ext/base/subprocess.h
index 77b2dfd..2733152 100644
--- a/include/perfetto/ext/base/subprocess.h
+++ b/include/perfetto/ext/base/subprocess.h
@@ -17,19 +17,27 @@
 #ifndef INCLUDE_PERFETTO_EXT_BASE_SUBPROCESS_H_
 #define INCLUDE_PERFETTO_EXT_BASE_SUBPROCESS_H_
 
-#include <condition_variable>
+#include "perfetto/base/build_config.h"
+
+// This is a #if as opposite to a GN condition, because GN conditions aren't propagated when
+// translating to Bazel or other build systems, as they get resolved at translation time. Without
+// this, the Bazel build breaks on Windows.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+#define PERFETTO_HAS_SUBPROCESS() 1
+#else
+#define PERFETTO_HAS_SUBPROCESS() 0
+#endif
+
 #include <functional>
 #include <initializer_list>
-#include <mutex>
 #include <string>
 #include <thread>
 #include <vector>
 
-#include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/base/platform_handle.h"
 #include "perfetto/base/proc_utils.h"
-#include "perfetto/ext/base/event_fd.h"
 #include "perfetto/ext/base/pipe.h"
 #include "perfetto/ext/base/scoped_file.h"
 
@@ -43,7 +51,7 @@
 //    This happens when |args.exec_cmd| is not empty.
 //    This is safe to use even in a multi-threaded environment.
 // 2) fork(): for spawning a process and running a function.
-//    This happens when |args.posix_entrypoint_for_testing| is not empty.
+//    This happens when |args.entrypoint_for_testing| is not empty.
 //    This is intended only for tests as it is extremely subtle.
 //    This mode must be used with extreme care. Before the entrypoint is
 //    invoked all file descriptors other than stdin/out/err and the ones
@@ -94,22 +102,21 @@
 //     p.Start();
 //     p.Wait();
 // )
-// EXPECT_EQ(p.status(), base::Subprocess::kTerminated);
+// EXPECT_EQ(p.status(), base::Subprocess::kExited);
 // EXPECT_EQ(p.returncode(), 0);
 class Subprocess {
  public:
   enum Status {
     kNotStarted = 0,  // Before calling Start() or Call().
     kRunning,         // After calling Start(), before Wait().
-    kTerminated,      // The subprocess terminated, either successfully or not.
-                      // This includes crashes or other signals on UNIX.
+    kExited,          // The subprocess exited (either succesully or not).
+    kKilledBySignal,  // The subprocess has been killed by a signal.
   };
 
   enum OutputMode {
     kInherit = 0,  // Inherit's the caller process stdout/stderr.
     kDevNull,      // dup() onto /dev/null
-    kBuffer,       // dup() onto a pipe and move it into the output() buffer.
-    kFd,           // dup() onto the passed args.fd.
+    kBuffer        // dup() onto a pipe and move it into the output() buffer.
   };
 
   // Input arguments for configuring the subprocess behavior.
@@ -120,20 +127,19 @@
     // If non-empty this will cause an exec() when Start()/Call() are called.
     std::vector<std::string> exec_cmd;
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
     // If non-empty, it changes the argv[0] argument passed to exec. If
     // unset, argv[0] == exec_cmd[0]. This is to handle cases like:
     // exec_cmd = {"/proc/self/exec"}, argv0: "my_custom_test_override".
-    std::string posix_argv0_override_for_testing;
+    std::string argv0_override;
 
     // If non-empty this will be invoked on the fork()-ed child process, after
     // stdin/out/err has been redirected and all other file descriptor are
-    // closed. It is valid to specify both |exec_cmd| AND
-    // |posix_entrypoint_for_testing|. In this case the latter will be invoked
-    // just before the exec() call, but after having closed all fds % stdin/o/e.
+    // closed.
+    // It is valid to specify both |exec_cmd| AND |entrypoint_for_testing|.
+    // In this case |entrypoint_for_testing| will be invoked just before the
+    // exec() call, but after having closed all fds % stdin/out/err.
     // This is for synchronization barriers in tests.
-    std::function<void()> posix_entrypoint_for_testing;
-#endif
+    std::function<void()> entrypoint_for_testing;
 
     // If non-empty, replaces the environment passed to exec().
     std::vector<std::string> env;
@@ -147,24 +153,10 @@
     OutputMode stdout_mode = kInherit;
     OutputMode stderr_mode = kInherit;
 
-    base::ScopedPlatformHandle out_fd;
-
     // Returns " ".join(exec_cmd), quoting arguments.
     std::string GetCmdString() const;
   };
 
-  struct ResourceUsage {
-    uint32_t cpu_utime_ms = 0;
-    uint32_t cpu_stime_ms = 0;
-    uint32_t max_rss_kb = 0;
-    uint32_t min_page_faults = 0;
-    uint32_t maj_page_faults = 0;
-    uint32_t vol_ctx_switch = 0;
-    uint32_t invol_ctx_switch = 0;
-
-    uint32_t cpu_time_ms() const { return cpu_utime_ms + cpu_stime_ms; }
-  };
-
   explicit Subprocess(std::initializer_list<std::string> exec_cmd = {});
   Subprocess(Subprocess&&) noexcept;
   Subprocess& operator=(Subprocess&&);
@@ -191,74 +183,37 @@
 
   Status Poll();
 
-  // Sends a signal (SIGKILL if not specified) and wait for process termination.
-  void KillAndWaitForTermination(int sig_num = 0);
+  // Sends a SIGKILL and wait to see the process termination.
+  void KillAndWaitForTermination();
 
-  PlatformProcessId pid() const { return s_->pid; }
-
-  // The accessors below are updated only after a call to Poll(), Wait() or
-  // KillAndWaitForTermination().
-  // In most cases you want to call Poll() rather than these accessors.
-
-  Status status() const { return s_->status; }
-  int returncode() const { return s_->returncode; }
-  bool timed_out() const { return s_->timed_out; }
+  PlatformProcessId pid() const { return pid_; }
+  Status status() const { return status_; }
+  int returncode() const { return returncode_; }
 
   // This contains both stdout and stderr (if the corresponding _mode ==
   // kBuffer). It's non-const so the caller can std::move() it.
-  std::string& output() { return s_->output; }
-  const std::string& output() const { return s_->output; }
-
-  const ResourceUsage& posix_rusage() const { return *s_->rusage; }
+  std::string& output() { return output_; }
 
   Args args;
 
  private:
-  // The signal/exit code used when killing the process in case of a timeout.
-  static const int kTimeoutSignal;
-
   Subprocess(const Subprocess&) = delete;
   Subprocess& operator=(const Subprocess&) = delete;
-
-  // This is to deal robustly with the move operators, without having to
-  // manually maintain member-wise move instructions.
-  struct MovableState {
-    base::Pipe stdin_pipe;
-    base::Pipe stdouterr_pipe;
-    PlatformProcessId pid;
-    Status status = kNotStarted;
-    int returncode = -1;
-    std::string output;  // Stdin+stderr. Only when kBuffer.
-    std::unique_ptr<ResourceUsage> rusage{new ResourceUsage()};
-    bool timed_out = false;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    std::thread stdouterr_thread;
-    std::thread stdin_thread;
-    ScopedPlatformHandle win_proc_handle;
-    ScopedPlatformHandle win_thread_handle;
-
-    base::EventFd stdouterr_done_event;
-    std::mutex mutex;  // Protects locked_outerr_buf and the two pipes.
-    std::string locked_outerr_buf;
-#else
-    base::Pipe exit_status_pipe;
-    size_t input_written = 0;
-    std::thread waitpid_thread;
-#endif
-  };
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  static void StdinThread(MovableState*, std::string input);
-  static void StdoutErrThread(MovableState*);
-#else
   void TryPushStdin();
   void TryReadStdoutAndErr();
   void TryReadExitStatus();
   void KillAtMostOnce();
   bool PollInternal(int poll_timeout_ms);
-#endif
 
-  std::unique_ptr<MovableState> s_;
+  base::Pipe stdin_pipe_;
+  base::Pipe stdouterr_pipe_;
+  base::Pipe exit_status_pipe_;
+  PlatformProcessId pid_;
+  size_t input_written_ = 0;
+  Status status_ = kNotStarted;
+  int returncode_ = -1;
+  std::string output_;  // Stdin+stderr. Only when kBuffer.
+  std::thread waitpid_thread_;
 };
 
 }  // namespace base
diff --git a/include/perfetto/ext/base/temp_file.h b/include/perfetto/ext/base/temp_file.h
index 3598868..da7e1bf 100644
--- a/include/perfetto/ext/base/temp_file.h
+++ b/include/perfetto/ext/base/temp_file.h
@@ -24,8 +24,6 @@
 namespace perfetto {
 namespace base {
 
-std::string GetSysTempDir();
-
 class TempFile {
  public:
   static TempFile CreateUnlinked();
diff --git a/include/perfetto/ext/base/thread_task_runner.h b/include/perfetto/ext/base/thread_task_runner.h
index 5f5947e..6579fa5 100644
--- a/include/perfetto/ext/base/thread_task_runner.h
+++ b/include/perfetto/ext/base/thread_task_runner.h
@@ -32,7 +32,7 @@
 // * the UnixTaskRunner will be constructed and destructed on the task thread.
 // * the task thread will live for the lifetime of the UnixTaskRunner.
 //
-class PERFETTO_EXPORT ThreadTaskRunner : public TaskRunner {
+class ThreadTaskRunner {
  public:
   static ThreadTaskRunner CreateAndStart(const std::string& name = "") {
     return ThreadTaskRunner(name);
@@ -43,7 +43,7 @@
 
   ThreadTaskRunner(ThreadTaskRunner&&) noexcept;
   ThreadTaskRunner& operator=(ThreadTaskRunner&&);
-  ~ThreadTaskRunner() override;
+  ~ThreadTaskRunner();
 
   // Executes the given function on the task runner thread and blocks the caller
   // thread until the function has run.
@@ -62,14 +62,6 @@
   // should be handled exclusively by this class' destructor.
   UnixTaskRunner* get() const { return task_runner_; }
 
-  // TaskRunner implementation.
-  // These methods just proxy to the underlying task_runner_.
-  void PostTask(std::function<void()>) override;
-  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(PlatformHandle, std::function<void()>) override;
-  void RemoveFileDescriptorWatch(PlatformHandle) override;
-  bool RunsTasksOnCurrentThread() const override;
-
  private:
   explicit ThreadTaskRunner(const std::string& name);
   void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
diff --git a/include/perfetto/ext/base/thread_utils.h b/include/perfetto/ext/base/thread_utils.h
index 2e9c4e5..7869e77 100644
--- a/include/perfetto/ext/base/thread_utils.h
+++ b/include/perfetto/ext/base/thread_utils.h
@@ -23,16 +23,12 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #include <pthread.h>
 #include <string.h>
 #include <algorithm>
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/prctl.h>
-#endif
-
 // Internal implementation utils that aren't as widely useful/supported as
 // base/thread_utils.h.
 
@@ -41,7 +37,7 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 // Sets the "comm" of the calling thread to the first 15 chars of the given
 // string.
 inline bool MaybeSetThreadName(const std::string& name) {
@@ -49,33 +45,14 @@
   size_t sz = std::min(name.size(), static_cast<size_t>(15));
   strncpy(buf, name.c_str(), sz);
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   return pthread_setname_np(buf) == 0;
 #else
   return pthread_setname_np(pthread_self(), buf) == 0;
 #endif
 }
-
-inline bool GetThreadName(std::string& out_result) {
-  char buf[16] = {};
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  if (prctl(PR_GET_NAME, buf) != 0)
-    return false;
 #else
-  if (pthread_getname_np(pthread_self(), buf, sizeof(buf)) != 0)
-    return false;
-#endif
-  out_result = std::string(buf);
-  return true;
-}
-
-#else
-inline bool MaybeSetThreadName(const std::string&) {
-  return false;
-}
-inline bool GetThreadName(std::string&) {
-  return false;
-}
+inline void MaybeSetThreadName(const std::string&) {}
 #endif
 
 }  // namespace base
diff --git a/include/perfetto/ext/base/unix_socket.h b/include/perfetto/ext/base/unix_socket.h
index 0d679e5..df0cad8 100644
--- a/include/perfetto/ext/base/unix_socket.h
+++ b/include/perfetto/ext/base/unix_socket.h
@@ -23,8 +23,6 @@
 #include <memory>
 #include <string>
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/export.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/utils.h"
@@ -35,73 +33,33 @@
 namespace perfetto {
 namespace base {
 
-// Define the SocketHandle and ScopedSocketHandle types.
-// On POSIX OSes, a SocketHandle is really just an int (a file descriptor).
-// On Windows, sockets are have their own type (SOCKET) which is neither a
-// HANDLE nor an int. However Windows SOCKET(s) can have a event HANDLE attached
-// to them (which in Perfetto is a PlatformHandle), and that can be used in
-// WaitForMultipleObjects, hence in base::TaskRunner.AddFileDescriptorWatch().
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// uintptr_t really reads as SOCKET here (Windows headers typedef to that).
-// As usual we don't just use SOCKET here to avoid leaking Windows.h includes
-// in our headers.
-using SocketHandle = uintptr_t;  // SOCKET
-int CloseSocket(SocketHandle);   // A wrapper around ::closesocket().
-using ScopedSocketHandle =
-    ScopedResource<SocketHandle, CloseSocket, static_cast<SocketHandle>(-1)>;
-#else
-using SocketHandle = int;
-using ScopedSocketHandle = ScopedFile;
-#endif
-
 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, kInet6 };
+enum class SockFamily { kUnix = 200, kInet };
 
-// Controls the getsockopt(SO_PEERCRED) behavior, which allows to obtain the
-// peer credentials.
-enum class SockPeerCredMode {
-  // Obtain the peer credentials immediatley after connection and cache them.
-  kReadOnConnect = 0,
-
-  // Don't read peer credentials at all. Calls to peer_uid()/peer_pid() will
-  // hit a DCHECK and return kInvalidUid/Pid in release builds.
-  kIgnore = 1,
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  kDefault = kIgnore,
-#else
-  kDefault = kReadOnConnect,
-#endif
-};
-
-// UnixSocketRaw is a basic wrapper around sockets. It exposes wrapper
+// 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 which depends
-// on base::TaskRunner.
+// 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);
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   // Crates a pair of connected sockets.
-  static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePairPosix(SockFamily,
-                                                                 SockType);
-#endif
+  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(ScopedSocketHandle, SockFamily, SockType);
+  UnixSocketRaw(ScopedFile, SockFamily, SockType);
 
   ~UnixSocketRaw() = default;
   UnixSocketRaw(UnixSocketRaw&&) noexcept = default;
@@ -114,50 +72,33 @@
   bool SetRxTimeout(uint32_t timeout_ms);
   void Shutdown();
   void SetBlocking(bool);
-  void DcheckIsBlocking(bool expected) const;  // No-op on release and Win.
+  bool IsBlocking() const;
   void RetainOnExec();
   SockType type() const { return type_; }
   SockFamily family() const { return family_; }
-  SocketHandle fd() const { return *fd_; }
+  int fd() const { return *fd_; }
   explicit operator bool() const { return !!fd_; }
 
-  // This is the handle that passed to TaskRunner.AddFileDescriptorWatch().
-  // On UNIX this is just the socket FD. On Windows, we need to create a
-  // dedicated event object.
-  PlatformHandle watch_handle() const {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    return *event_handle_;
-#else
-    return *fd_;
-#endif
-  }
+  ScopedFile ReleaseFd() { return std::move(fd_); }
 
-  ScopedSocketHandle ReleaseFd() { return std::move(fd_); }
-
-  // |send_fds| and |num_fds| are ignored on Windows.
   ssize_t Send(const void* msg,
                size_t len,
                const int* send_fds = nullptr,
                size_t num_fds = 0);
 
-  // |fd_vec| and |max_files| are ignored on Windows.
+  // 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);
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // UNIX-specific helpers to deal with SCM_RIGHTS.
-
-  // 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 SendMsgAllPosix(struct msghdr* msg);
-
   // Exposed for testing only.
   // Update msghdr so subsequent sendmsg will send data that remains after n
   // bytes have already been sent.
-  static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg);
-#endif
+  static void ShiftMsgHdr(size_t n, struct msghdr* msg);
 
  private:
   UnixSocketRaw(SockFamily, SockType);
@@ -165,10 +106,7 @@
   UnixSocketRaw(const UnixSocketRaw&) = delete;
   UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
 
-  ScopedSocketHandle fd_;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  ScopedPlatformHandle event_handle_;
-#endif
+  ScopedFile fd_;
   SockFamily family_ = SockFamily::kUnix;
   SockType type_ = SockType::kStream;
 };
@@ -212,7 +150,7 @@
 //                             | (failure or Shutdown())
 //                             V
 //                       OnDisconnect()
-class PERFETTO_EXPORT UnixSocket {
+class UnixSocket {
  public:
   class EventListener {
    public:
@@ -247,10 +185,9 @@
   // |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").
-  // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000").
-  // Returns nullptr if the socket creation or bind fails. If listening fails,
-  // (e.g. if another socket with the same name is already listening) the
-  // returned socket will have is_listening() == false.
+  // 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*,
@@ -259,7 +196,7 @@
 
   // 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(ScopedSocketHandle,
+  static std::unique_ptr<UnixSocket> Listen(ScopedFile,
                                             EventListener*,
                                             TaskRunner*,
                                             SockFamily,
@@ -268,22 +205,18 @@
   // 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,
-      SockPeerCredMode = SockPeerCredMode::kDefault);
+  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(
-      ScopedSocketHandle,
-      EventListener*,
-      TaskRunner*,
-      SockFamily,
-      SockType,
-      SockPeerCredMode = SockPeerCredMode::kDefault);
+  static std::unique_ptr<UnixSocket> AdoptConnected(ScopedFile,
+                                                    EventListener*,
+                                                    TaskRunner*,
+                                                    SockFamily,
+                                                    SockType);
 
   UnixSocket(const UnixSocket&) = delete;
   UnixSocket& operator=(const UnixSocket&) = delete;
@@ -301,12 +234,6 @@
   // be reused with Listen() or Connect().
   void Shutdown(bool notify);
 
-  void SetTxTimeout(uint32_t timeout_ms) {
-    PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms));
-  }
-  void SetRxTimeout(uint32_t timeout_ms) {
-    PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms));
-  }
   // 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
@@ -345,19 +272,17 @@
 
   bool is_connected() const { return state_ == State::kConnected; }
   bool is_listening() const { return state_ == State::kListening; }
-  SocketHandle fd() const { return sock_raw_.fd(); }
+  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.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  uid_t peer_uid_posix(bool skip_check_for_testing = false) const {
-    PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) ||
-                    skip_check_for_testing);
-
+  uid_t peer_uid() const {
+    PERFETTO_DCHECK(!is_listening() && peer_uid_ != kInvalidUid);
+    ignore_result(kInvalidPid);  // Silence warnings in amalgamated builds.
     return peer_uid_;
   }
-#endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -366,9 +291,8 @@
   // retains the pid of the last peer.
   //
   // This is only available on Linux / Android.
-  pid_t peer_pid_linux(bool skip_check_for_testing = false) const {
-    PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) ||
-                    skip_check_for_testing);
+  pid_t peer_pid() const {
+    PERFETTO_DCHECK(!is_listening() && peer_pid_ != kInvalidPid);
     return peer_pid_;
   }
 #endif
@@ -377,36 +301,25 @@
   UnixSocketRaw ReleaseSocket();
 
  private:
+  UnixSocket(EventListener*, TaskRunner*, SockFamily, SockType);
   UnixSocket(EventListener*,
              TaskRunner*,
-             SockFamily,
-             SockType,
-             SockPeerCredMode);
-  UnixSocket(EventListener*,
-             TaskRunner*,
-             ScopedSocketHandle,
+             ScopedFile,
              State,
              SockFamily,
-             SockType,
-             SockPeerCredMode);
+             SockType);
 
   // Called once by the corresponding public static factory methods.
   void DoConnect(const std::string& socket_name);
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  void ReadPeerCredentialsPosix();
-#endif
+  void ReadPeerCredentials();
 
   void OnEvent();
   void NotifyConnectionState(bool success);
 
   UnixSocketRaw sock_raw_;
   State state_ = State::kDisconnected;
-  SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault;
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+  int last_error_ = 0;
   uid_t peer_uid_ = kInvalidUid;
-#endif
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
   pid_t peer_pid_ = kInvalidPid;
diff --git a/include/perfetto/ext/base/unix_task_runner.h b/include/perfetto/ext/base/unix_task_runner.h
index 8d1ab6d..386c01f 100644
--- a/include/perfetto/ext/base/unix_task_runner.h
+++ b/include/perfetto/ext/base/unix_task_runner.h
@@ -25,16 +25,13 @@
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/thread_checker.h"
 
+#include <poll.h>
 #include <chrono>
 #include <deque>
 #include <map>
 #include <mutex>
 #include <vector>
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <poll.h>
-#endif
-
 namespace perfetto {
 namespace base {
 
@@ -53,8 +50,6 @@
 //
 // TODO(rsavitski): consider adding a thread-check in the destructor, after
 // auditing existing usages.
-// TODO(primiano): rename this to TaskRunnerImpl. The "Unix" part is misleading
-// now as it supports also Windows.
 class UnixTaskRunner : public TaskRunner {
  public:
   UnixTaskRunner();
@@ -72,8 +67,8 @@
   // TaskRunner implementation:
   void PostTask(std::function<void()>) override;
   void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(PlatformHandle, std::function<void()>) override;
-  void RemoveFileDescriptorWatch(PlatformHandle) 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
@@ -83,23 +78,22 @@
 
  private:
   void WakeUp();
+
   void UpdateWatchTasksLocked();
+
   int GetDelayMsToNextTaskLocked() const;
   void RunImmediateAndDelayedTask();
-  void PostFileDescriptorWatches(uint64_t windows_wait_result);
-  void RunFileDescriptorWatch(PlatformHandle);
+  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_;
 
-// The array of fds/handles passed to poll(2) / WaitForMultipleObjects().
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  std::vector<PlatformHandle> poll_fds_;
-#else
   std::vector<struct pollfd> poll_fds_;
-#endif
 
   // --- Begin lock-protected members ---
 
@@ -111,17 +105,10 @@
 
   struct WatchTask {
     std::function<void()> callback;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    // On UNIX systems we make the FD number negative in |poll_fds_| to avoid
-    // polling it again until the queued task runs. On Windows we can't do that.
-    // Instead we keep track of its state here.
-    bool pending = false;
-#else
     size_t poll_fd_index;  // Index into |poll_fds_|.
-#endif
   };
 
-  std::map<PlatformHandle, WatchTask> watch_tasks_;
+  std::map<int, WatchTask> watch_tasks_;
   bool watch_tasks_changed_ = false;
 
   // --- End lock-protected members ---
diff --git a/include/perfetto/ext/base/utils.h b/include/perfetto/ext/base/utils.h
index af39b37..aadded6 100644
--- a/include/perfetto/ext/base/utils.h
+++ b/include/perfetto/ext/base/utils.h
@@ -22,19 +22,11 @@
 
 #include <errno.h>
 #include <stddef.h>
-#include <stdint.h>
 #include <stdlib.h>
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <sys/types.h>
+#endif
 
-#include <atomic>
-#include <string>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// Even if Windows has errno.h, the all syscall-restart behavior does not apply.
-// Trying to handle EINTR can cause more harm than good if errno is left stale.
-// Chromium does the same.
-#define PERFETTO_EINTR(x) (x)
-#else
 #define PERFETTO_EINTR(x)                                   \
   ([&] {                                                    \
     decltype(x) eintr_wrapper_result;                       \
@@ -43,15 +35,11 @@
     } while (eintr_wrapper_result == -1 && errno == EINTR); \
     return eintr_wrapper_result;                            \
   }())
-#endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using uid_t = unsigned int;
-#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
-using pid_t = unsigned int;
-#endif
+// TODO(brucedawson) - create a ::perfetto::base::IOSize to replace this.
 #if defined(_WIN64)
-using ssize_t = int64_t;
+using ssize_t = __int64;
 #else
 using ssize_t = long;
 #endif
@@ -60,21 +48,13 @@
 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
 
-// Do not add new usages of kPageSize, consider using GetSysPageSize() below.
-// TODO(primiano): over time the semantic of kPageSize became too ambiguous.
-// Strictly speaking, this constant is incorrect on some new devices where the
-// page size can be 16K (e.g., crbug.com/1116576). Unfortunately too much code
-// ended up depending on kPageSize for purposes that are not strictly related
-// with the kernel's mm subsystem.
 constexpr size_t kPageSize = 4096;
 
-// Returns the system's page size. Use this when dealing with mmap, madvise and
-// similar mm-related syscalls.
-uint32_t GetSysPageSize();
-
 template <typename T>
 constexpr size_t ArraySize(const T& array) {
   return sizeof(array) / sizeof(array[0]);
@@ -91,9 +71,8 @@
 
 template <typename T>
 constexpr T AssumeLittleEndian(T value) {
-#if !PERFETTO_IS_LITTLE_ENDIAN()
-  static_assert(false, "Unimplemented on big-endian archs");
-#endif
+  static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
+                "Unimplemented on big-endian archs");
   return value;
 }
 
@@ -108,22 +87,6 @@
   return err == EAGAIN || err == EWOULDBLOCK;
 }
 
-// setenv(2)-equivalent. Deals with Windows vs Posix discrepancies.
-void SetEnv(const std::string& key, const std::string& value);
-
-// Calls mallopt(M_PURGE, 0) on Android. Does nothing on other platforms.
-// This forces the allocator to release freed memory. This is used to work
-// around various Scudo inefficiencies. See b/170217718.
-void MaybeReleaseAllocatorMemToOS();
-
-// geteuid() on POSIX OSes, returns 0 on Windows (See comment in utils.cc).
-uid_t GetCurrentUserId();
-
-// Forks the process.
-// Parent: prints the PID of the child and exit(0).
-// Child: redirects stdio onto /dev/null and chdirs into .
-void Daemonize();
-
 }  // namespace base
 }  // namespace perfetto
 
diff --git a/include/perfetto/ext/base/version.h b/include/perfetto/ext/base/version.h
deleted file mode 100644
index 212424a..0000000
--- a/include/perfetto/ext/base/version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
-#define INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
-
-namespace perfetto {
-namespace base {
-
-// The returned pointer is a static string is safe to pass around.
-const char* GetVersionString();
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_VERSION_H_
diff --git a/include/perfetto/ext/base/watchdog_posix.h b/include/perfetto/ext/base/watchdog_posix.h
index 3c673c3..9a6e1dd 100644
--- a/include/perfetto/ext/base/watchdog_posix.h
+++ b/include/perfetto/ext/base/watchdog_posix.h
@@ -17,7 +17,6 @@
 #ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_POSIX_H_
 #define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_POSIX_H_
 
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/thread_checker.h"
 
 #include <atomic>
@@ -55,7 +54,7 @@
     Timer(const Timer&) = delete;
     Timer& operator=(const Timer&) = delete;
 
-    Optional<timer_t> timerid_;
+    timer_t timerid_ = nullptr;
   };
   virtual ~Watchdog();
 
diff --git a/include/perfetto/ext/ipc/basic_types.h b/include/perfetto/ext/ipc/basic_types.h
index 3931f05..7d99c26 100644
--- a/include/perfetto/ext/ipc/basic_types.h
+++ b/include/perfetto/ext/ipc/basic_types.h
@@ -21,7 +21,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/cpp_message_obj.h"
 
 namespace perfetto {
@@ -33,16 +32,6 @@
 using ClientID = uint64_t;
 using RequestID = uint64_t;
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// AF_UNIX on Windows is supported only on Windows 10 from build 17063.
-// Also it doesn't bring major advantages compared to a TCP socket.
-// See go/perfetto-win .
-constexpr bool kUseTCPSocket = true;
-#else
-// On Android, Linux, Mac use a AF_UNIX socket.
-constexpr bool kUseTCPSocket = false;
-#endif
-
 // 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;
diff --git a/include/perfetto/ext/ipc/client.h b/include/perfetto/ext/ipc/client.h
index d04ac85..72c3e73 100644
--- a/include/perfetto/ext/ipc/client.h
+++ b/include/perfetto/ext/ipc/client.h
@@ -21,7 +21,6 @@
 #include <memory>
 
 #include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/weak_ptr.h"
 #include "perfetto/ext/ipc/basic_types.h"
 
@@ -45,26 +44,8 @@
 // });
 class Client {
  public:
-  // struct ConnArgs is used for creating a client in 2 connection modes:
-  // 1. Connect using a socket name with the option to retry the connection on
-  //    connection failure.
-  // 2. Adopt a connected socket.
-  struct ConnArgs {
-    ConnArgs(const char* sock_name, bool sock_retry)
-        : socket_name(sock_name), retry(sock_retry) {}
-    explicit ConnArgs(base::ScopedSocketHandle sock_fd)
-        : socket_fd(std::move(sock_fd)) {}
-
-    // Disallow copy. Only supports move.
-    ConnArgs(const ConnArgs& other) = delete;
-    ConnArgs(ConnArgs&& other) = default;
-
-    base::ScopedSocketHandle socket_fd;
-    const char* socket_name = nullptr;
-    bool retry = false;  // Only for connecting with |socket_name|.
-  };
-
-  static std::unique_ptr<Client> CreateInstance(ConnArgs, base::TaskRunner*);
+  static std::unique_ptr<Client> CreateInstance(const char* socket_name,
+                                                base::TaskRunner*);
   virtual ~Client();
 
   virtual void BindService(base::WeakPtr<ServiceProxy>) = 0;
diff --git a/include/perfetto/ext/ipc/client_info.h b/include/perfetto/ext/ipc/client_info.h
index 6988d18..0b43f9a 100644
--- a/include/perfetto/ext/ipc/client_info.h
+++ b/include/perfetto/ext/ipc/client_info.h
@@ -17,8 +17,9 @@
 #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/base/utils.h"
 #include "perfetto/ext/ipc/basic_types.h"
 
 namespace perfetto {
diff --git a/include/perfetto/ext/ipc/host.h b/include/perfetto/ext/ipc/host.h
index a9b5824..bbf3657 100644
--- a/include/perfetto/ext/ipc/host.h
+++ b/include/perfetto/ext/ipc/host.h
@@ -20,7 +20,6 @@
 #include <memory>
 
 #include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/ipc/basic_types.h"
 
 namespace perfetto {
@@ -46,7 +45,7 @@
 
   // 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::ScopedSocketHandle,
+  static std::unique_ptr<Host> CreateInstance(base::ScopedFile socket_fd,
                                               base::TaskRunner*);
 
   virtual ~Host();
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/BUILD.gn b/include/perfetto/ext/trace_processor/importers/memory_tracker/BUILD.gn
deleted file mode 100644
index 7d093f4..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../../../../gn/perfetto.gni")
-
-source_set("memory_tracker") {
-  deps = [ "../../../../../../gn:default_deps" ]
-  public_deps = [
-    "../../../../base",
-    "../../../base",
-  ]
-  sources = [
-    "graph.h",
-    "graph_processor.h",
-    "memory_allocator_node_id.h",
-    "memory_graph_edge.h",
-    "raw_memory_graph_node.h",
-    "raw_process_memory_node.h",
-  ]
-}
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h
deleted file mode 100644
index d8a9d87..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_H_
-
-#include <sys/types.h>
-
-#include <forward_list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/proc_utils.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-const base::PlatformProcessId kNullProcessId = 0;
-
-// Contains processed node graphs for each process and in the global space.
-// This class is also the arena which owns the nodes of the graph.
-class PERFETTO_EXPORT GlobalNodeGraph {
- public:
-  class Node;
-  class Edge;
-  class PreOrderIterator;
-  class PostOrderIterator;
-
-  // Graph of nodes either associated with a process or with
-  // the shared space.
-  class PERFETTO_EXPORT Process {
-   public:
-    Process(base::PlatformProcessId pid, GlobalNodeGraph* global_graph);
-    ~Process();
-
-    // Creates a node in the node graph which is associated with the
-    // given |id|, |path| and |weak|ness and returns it.
-    GlobalNodeGraph::Node* CreateNode(MemoryAllocatorNodeId id,
-                                      const std::string& path,
-                                      bool weak);
-
-    // Returns the node in the graph at the given |path| or nullptr
-    // if no such node exists in the provided |graph|.
-    GlobalNodeGraph::Node* FindNode(const std::string& path);
-
-    base::PlatformProcessId pid() const { return pid_; }
-    GlobalNodeGraph* global_graph() const { return global_graph_; }
-    GlobalNodeGraph::Node* root() const { return root_; }
-
-   private:
-    base::PlatformProcessId pid_;
-    GlobalNodeGraph* global_graph_;
-    GlobalNodeGraph::Node* root_;
-    Process(const Process&) = delete;
-    Process& operator=(const Process&) = delete;
-  };
-
-  // A single node in the graph of allocator nodes associated with a
-  // certain path and containing the entries for this path.
-  class PERFETTO_EXPORT Node {
-   public:
-    // Auxilary data (a scalar number or a string) about this node each
-    // associated with a key.
-    struct PERFETTO_EXPORT Entry {
-      enum Type {
-        kUInt64,
-        kString,
-      };
-
-      // The units of the entry if the entry is a scalar. The scalar
-      // refers to either a number of objects or a size in bytes.
-      enum ScalarUnits {
-        kObjects,
-        kBytes,
-      };
-
-      // Creates the entry with the appropriate type.
-      Entry(ScalarUnits units, uint64_t value);
-      explicit Entry(const std::string& value);
-
-      const Type type;
-      const ScalarUnits units;
-
-      // The value of the entry if this entry has a string type.
-      const std::string value_string;
-
-      // The value of the entry if this entry has a integer type.
-      const uint64_t value_uint64;
-    };
-
-    explicit Node(GlobalNodeGraph::Process* node_graph, Node* parent);
-    ~Node();
-
-    // Gets the direct child of a node for the given |subpath|.
-    Node* GetChild(const std::string& name) const;
-
-    // Inserts the given |node| as a child of the current node
-    // with the given |subpath| as the key.
-    void InsertChild(const std::string& name, Node* node);
-
-    // Creates a child for this node with the given |name| as the key.
-    Node* CreateChild(const std::string& name);
-
-    // Checks if the current node is a descendent (i.e. exists as a child,
-    // child of a child, etc.) of the given node |possible_parent|.
-    bool IsDescendentOf(const Node& possible_parent) const;
-
-    // Adds an entry for this node node with the given |name|, |units| and
-    // type.
-    void AddEntry(const std::string& name,
-                  Entry::ScalarUnits units,
-                  uint64_t value);
-    void AddEntry(const std::string& name, const std::string& value);
-
-    // Adds an edge which indicates that this node is owned by
-    // another node.
-    void AddOwnedByEdge(Edge* edge);
-
-    // Sets the edge indicates that this node owns another node.
-    void SetOwnsEdge(Edge* edge);
-
-    bool is_weak() const { return weak_; }
-    void set_weak(bool weak) { weak_ = weak; }
-    bool is_explicit() const { return explicit_; }
-    void set_explicit(bool explicit_node) { explicit_ = explicit_node; }
-    uint64_t not_owned_sub_size() const { return not_owned_sub_size_; }
-    void add_not_owned_sub_size(uint64_t addition) {
-      not_owned_sub_size_ += addition;
-    }
-    uint64_t not_owning_sub_size() const { return not_owning_sub_size_; }
-    void add_not_owning_sub_size(uint64_t addition) {
-      not_owning_sub_size_ += addition;
-    }
-    double owned_coefficient() const { return owned_coefficient_; }
-    void set_owned_coefficient(double owned_coefficient) {
-      owned_coefficient_ = owned_coefficient;
-    }
-    double owning_coefficient() const { return owning_coefficient_; }
-    void set_owning_coefficient(double owning_coefficient) {
-      owning_coefficient_ = owning_coefficient;
-    }
-    double cumulative_owned_coefficient() const {
-      return cumulative_owned_coefficient_;
-    }
-    void set_cumulative_owned_coefficient(double cumulative_owned_coefficient) {
-      cumulative_owned_coefficient_ = cumulative_owned_coefficient;
-    }
-    double cumulative_owning_coefficient() const {
-      return cumulative_owning_coefficient_;
-    }
-    void set_cumulative_owning_coefficient(
-        double cumulative_owning_coefficient) {
-      cumulative_owning_coefficient_ = cumulative_owning_coefficient;
-    }
-    MemoryAllocatorNodeId id() const { return id_; }
-    void set_id(MemoryAllocatorNodeId id) { id_ = id; }
-    GlobalNodeGraph::Edge* owns_edge() const { return owns_edge_; }
-    std::map<std::string, Node*>* children() { return &children_; }
-    const std::map<std::string, Node*>& const_children() const {
-      return children_;
-    }
-    std::vector<GlobalNodeGraph::Edge*>* owned_by_edges() {
-      return &owned_by_edges_;
-    }
-    const Node* parent() const { return parent_; }
-    const GlobalNodeGraph::Process* node_graph() const { return node_graph_; }
-    std::map<std::string, Entry>* entries() { return &entries_; }
-    const std::map<std::string, Entry>& const_entries() const {
-      return entries_;
-    }
-
-   private:
-    GlobalNodeGraph::Process* node_graph_;
-    Node* const parent_;
-    MemoryAllocatorNodeId id_;
-    std::map<std::string, Entry> entries_;
-    std::map<std::string, Node*> children_;
-    bool explicit_ = false;
-    bool weak_ = false;
-    uint64_t not_owning_sub_size_ = 0;
-    uint64_t not_owned_sub_size_ = 0;
-    double owned_coefficient_ = 1;
-    double owning_coefficient_ = 1;
-    double cumulative_owned_coefficient_ = 1;
-    double cumulative_owning_coefficient_ = 1;
-
-    GlobalNodeGraph::Edge* owns_edge_;
-    std::vector<GlobalNodeGraph::Edge*> owned_by_edges_;
-
-    Node(const Node&) = delete;
-    Node& operator=(const Node&) = delete;
-  };
-
-  // An edge in the node graph which indicates ownership between the
-  // source and target nodes.
-  class PERFETTO_EXPORT Edge {
-   public:
-    Edge(GlobalNodeGraph::Node* source,
-         GlobalNodeGraph::Node* target,
-         int priority);
-
-    GlobalNodeGraph::Node* source() const { return source_; }
-    GlobalNodeGraph::Node* target() const { return target_; }
-    int priority() const { return priority_; }
-
-   private:
-    GlobalNodeGraph::Node* const source_;
-    GlobalNodeGraph::Node* const target_;
-    const int priority_;
-  };
-
-  // An iterator-esque class which yields nodes in a depth-first pre order.
-  class PERFETTO_EXPORT PreOrderIterator {
-   public:
-    explicit PreOrderIterator(std::vector<Node*>&& root_nodes);
-    PreOrderIterator(PreOrderIterator&& other);
-    ~PreOrderIterator();
-
-    // Yields the next node in the DFS post-order traversal.
-    Node* next();
-
-   private:
-    std::vector<Node*> to_visit_;
-    std::set<const Node*> visited_;
-  };
-
-  // An iterator-esque class which yields nodes in a depth-first post order.
-  class PERFETTO_EXPORT PostOrderIterator {
-   public:
-    explicit PostOrderIterator(std::vector<Node*>&& root_nodes);
-    PostOrderIterator(PostOrderIterator&& other);
-    ~PostOrderIterator();
-
-    // Yields the next node in the DFS post-order traversal.
-    Node* next();
-
-   private:
-    std::vector<Node*> to_visit_;
-    std::set<Node*> visited_;
-    std::vector<Node*> path_;
-  };
-
-  using ProcessNodeGraphMap =
-      std::map<base::PlatformProcessId,
-               std::unique_ptr<GlobalNodeGraph::Process>>;
-  using IdNodeMap = std::map<MemoryAllocatorNodeId, Node*>;
-
-  GlobalNodeGraph();
-  ~GlobalNodeGraph();
-
-  // Creates a container for all the node graphs for the process given
-  // by the given |process_id|.
-  GlobalNodeGraph::Process* CreateGraphForProcess(
-      base::PlatformProcessId process_id);
-
-  // Adds an edge in the node graph with the given source and target nodes
-  // and edge priority.
-  void AddNodeOwnershipEdge(Node* owner, Node* owned, int priority);
-
-  // Returns an iterator which yields nodes in the nodes in this graph in
-  // pre-order. That is, children and owners of nodes are returned after the
-  // node itself.
-  PreOrderIterator VisitInDepthFirstPreOrder();
-
-  // Returns an iterator which yields nodes in the nodes in this graph in
-  // post-order. That is, children and owners of nodes are returned before the
-  // node itself.
-  PostOrderIterator VisitInDepthFirstPostOrder();
-
-  const IdNodeMap& nodes_by_id() const { return nodes_by_id_; }
-  GlobalNodeGraph::Process* shared_memory_graph() const {
-    return shared_memory_graph_.get();
-  }
-  const ProcessNodeGraphMap& process_node_graphs() const {
-    return process_node_graphs_;
-  }
-  const std::forward_list<Edge>& edges() const { return all_edges_; }
-
- private:
-  // Creates a node in the arena which is associated with the given
-  // |process_graph| and for the given |parent|.
-  Node* CreateNode(GlobalNodeGraph::Process* process_graph,
-                   GlobalNodeGraph::Node* parent);
-
-  std::forward_list<Node> all_nodes_;
-  std::forward_list<Edge> all_edges_;
-  IdNodeMap nodes_by_id_;
-  std::unique_ptr<GlobalNodeGraph::Process> shared_memory_graph_;
-  ProcessNodeGraphMap process_node_graphs_;
-  GlobalNodeGraph(const GlobalNodeGraph&) = delete;
-  GlobalNodeGraph& operator=(const GlobalNodeGraph&) = delete;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_H_
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h
deleted file mode 100644
index c9fea6b..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_PROCESSOR_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_PROCESSOR_H_
-
-#include <sys/types.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-
-#include "perfetto/base/proc_utils.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class PERFETTO_EXPORT GraphProcessor {
- public:
-  // This map does not own the pointers inside.
-  using RawMemoryNodeMap =
-      std::map<base::PlatformProcessId, std::unique_ptr<RawProcessMemoryNode>>;
-
-  static std::unique_ptr<GlobalNodeGraph> CreateMemoryGraph(
-      const RawMemoryNodeMap& process_nodes);
-
-  static void RemoveWeakNodesFromGraph(GlobalNodeGraph* global_graph);
-
-  static void AddOverheadsAndPropagateEntries(GlobalNodeGraph* global_graph);
-
-  static void CalculateSizesForGraph(GlobalNodeGraph* global_graph);
-
-  static std::map<base::PlatformProcessId, uint64_t>
-  ComputeSharedFootprintFromGraph(const GlobalNodeGraph& global_graph);
-
- private:
-  friend class GraphProcessorTest;
-
-  static void CollectAllocatorNodes(const RawProcessMemoryNode& source,
-                                    GlobalNodeGraph* global_graph,
-                                    GlobalNodeGraph::Process* process_graph);
-
-  static void AddEdges(const RawProcessMemoryNode& source,
-                       GlobalNodeGraph* global_graph);
-
-  static void MarkImplicitWeakParentsRecursively(GlobalNodeGraph::Node* node);
-
-  static void MarkWeakOwnersAndChildrenRecursively(
-      GlobalNodeGraph::Node* node,
-      std::set<const GlobalNodeGraph::Node*>* nodes);
-
-  static void RemoveWeakNodesRecursively(GlobalNodeGraph::Node* parent);
-
-  static void AssignTracingOverhead(const std::string& allocator,
-                                    GlobalNodeGraph* global_graph,
-                                    GlobalNodeGraph::Process* process);
-
-  static GlobalNodeGraph::Node::Entry AggregateNumericWithNameForNode(
-      GlobalNodeGraph::Node* node,
-      const std::string& name);
-
-  static void AggregateNumericsRecursively(GlobalNodeGraph::Node* node);
-
-  static void PropagateNumericsAndDiagnosticsRecursively(
-      GlobalNodeGraph::Node* node);
-
-  static base::Optional<uint64_t> AggregateSizeForDescendantNode(
-      GlobalNodeGraph::Node* root,
-      GlobalNodeGraph::Node* descendant);
-
-  static void CalculateSizeForNode(GlobalNodeGraph::Node* node);
-
-  /**
-   * Calculate not-owned and not-owning sub-sizes of a memory allocator node
-   * from its children's (sub-)sizes.
-   *
-   * Not-owned sub-size refers to the aggregated memory of all children which
-   * is not owned by other MADs. Conversely, not-owning sub-size is the
-   * aggregated memory of all children which do not own another MAD. The
-   * diagram below illustrates these two concepts:
-   *
-   *     ROOT 1                         ROOT 2
-   *     size: 4                        size: 5
-   *     not-owned sub-size: 4          not-owned sub-size: 1 (!)
-   *     not-owning sub-size: 0 (!)     not-owning sub-size: 5
-   *
-   *      ^                              ^
-   *      |                              |
-   *
-   *     PARENT 1   ===== owns =====>   PARENT 2
-   *     size: 4                        size: 5
-   *     not-owned sub-size: 4          not-owned sub-size: 5
-   *     not-owning sub-size: 4         not-owning sub-size: 5
-   *
-   *      ^                              ^
-   *      |                              |
-   *
-   *     CHILD 1                        CHILD 2
-   *     size [given]: 4                size [given]: 5
-   *     not-owned sub-size: 4          not-owned sub-size: 5
-   *     not-owning sub-size: 4         not-owning sub-size: 5
-   *
-   * This method assumes that (1) the size of the node, its children, and its
-   * owners [see calculateSizes()] and (2) the not-owned and not-owning
-   * sub-sizes of both the children and owners of the node have already been
-   * calculated [depth-first post-order traversal].
-   */
-  static void CalculateNodeSubSizes(GlobalNodeGraph::Node* node);
-
-  /**
-   * Calculate owned and owning coefficients of a memory allocator node and
-   * its owners.
-   *
-   * The owning coefficient refers to the proportion of a node's not-owning
-   * sub-size which is attributed to the node (only relevant to owning MADs).
-   * Conversely, the owned coefficient is the proportion of a node's
-   * not-owned sub-size, which is attributed to it (only relevant to owned
-   * MADs).
-   *
-   * The not-owned size of the owned node is split among its owners in the
-   * order of the ownership importance as demonstrated by the following
-   * example:
-   *
-   *                                          memory allocator nodes
-   *                                   OWNED  OWNER1  OWNER2  OWNER3 OWNER4
-   *       not-owned sub-size [given]     10       -       -       - -
-   *      not-owning sub-size [given]      -       6       7       5 8
-   *               importance [given]      -       2       2       1 0
-   *    attributed not-owned sub-size      2       -       -       - -
-   *   attributed not-owning sub-size      -       3       4       0 1
-   *                owned coefficient   2/10       -       -       - -
-   *               owning coefficient      -     3/6     4/7     0/5 1/8
-   *
-   * Explanation: Firstly, 6 bytes are split equally among OWNER1 and OWNER2
-   * (highest importance). OWNER2 owns one more byte, so its attributed
-   * not-owning sub-size is 6/2 + 1 = 4 bytes. OWNER3 is attributed no size
-   * because it is smaller than the owners with higher priority. However,
-   * OWNER4 is larger, so it's attributed the difference 8 - 7 = 1 byte.
-   * Finally, 2 bytes remain unattributed and are hence kept in the OWNED
-   * node as attributed not-owned sub-size. The coefficients are then
-   * directly calculated as fractions of the sub-sizes and corresponding
-   * attributed sub-sizes.
-   *
-   * Note that we always assume that all ownerships of a node overlap (e.g.
-   * OWNER3 is subsumed by both OWNER1 and OWNER2). Hence, the table could
-   * be alternatively represented as follows:
-   *
-   *                                 owned memory range
-   *              0   1   2    3    4    5    6        7        8   9  10
-   *   Priority 2 |  OWNER1 + OWNER2 (split)  | OWNER2 |
-   *   Priority 1 | (already attributed) |
-   *   Priority 0 | - - -  (already attributed)  - - - | OWNER4 |
-   *    Remainder | - - - - - (already attributed) - - - - - -  | OWNED |
-   *
-   * This method assumes that (1) the size of the node [see calculateSizes()]
-   * and (2) the not-owned size of the node and not-owning sub-sizes of its
-   * owners [see the first step of calculateEffectiveSizes()] have already
-   * been calculated. Note that the method doesn't make any assumptions about
-   * the order in which nodes are visited.
-   */
-  static void CalculateNodeOwnershipCoefficient(GlobalNodeGraph::Node* node);
-
-  /**
-   * Calculate cumulative owned and owning coefficients of a memory allocator
-   * node from its (non-cumulative) owned and owning coefficients and the
-   * cumulative coefficients of its parent and/or owned node.
-   *
-   * The cumulative coefficients represent the total effect of all
-   * (non-strict) ancestor ownerships on a memory allocator node. The
-   * cumulative owned coefficient of a MAD can be calculated simply as:
-   *
-   *   cumulativeOwnedC(M) = ownedC(M) * cumulativeOwnedC(parent(M))
-   *
-   * This reflects the assumption that if a parent of a child MAD is
-   * (partially) owned, then the parent's owner also indirectly owns (a part
-   * of) the child MAD.
-   *
-   * The cumulative owning coefficient of a MAD depends on whether the MAD
-   * owns another node:
-   *
-   *                           [if M doesn't own another MAD]
-   *                         / cumulativeOwningC(parent(M))
-   *   cumulativeOwningC(M) =
-   *                         \ [if M owns another MAD]
-   *                           owningC(M) * cumulativeOwningC(owned(M))
-   *
-   * The reasoning behind the first case is similar to the one for cumulative
-   * owned coefficient above. The only difference is that we don't need to
-   * include the node's (non-cumulative) owning coefficient because it is
-   * implicitly 1.
-   *
-   * The formula for the second case is derived as follows: Since the MAD
-   * owns another node, its memory is not included in its parent's not-owning
-   * sub-size and hence shouldn't be affected by the parent's corresponding
-   * cumulative coefficient. Instead, the MAD indirectly owns everything
-   * owned by its owned node (and so it should be affected by the
-   * corresponding coefficient).
-   *
-   * Note that undefined coefficients (and coefficients of non-existent
-   * nodes) are implicitly assumed to be 1.
-   *
-   * This method assumes that (1) the size of the node [see calculateSizes()],
-   * (2) the (non-cumulative) owned and owning coefficients of the node [see
-   * the second step of calculateEffectiveSizes()], and (3) the cumulative
-   * coefficients of the node's parent and owned MADs (if present)
-   * [depth-first pre-order traversal] have already been calculated.
-   */
-  static void CalculateNodeCumulativeOwnershipCoefficient(
-      GlobalNodeGraph::Node* node);
-
-  /**
-   * Calculate the effective size of a memory allocator node.
-   *
-   * In order to simplify the (already complex) calculation, we use the fact
-   * that effective size is cumulative (unlike regular size), i.e. the
-   * effective size of a non-leaf node is equal to the sum of effective sizes
-   * of its children. The effective size of a leaf MAD is calculated as:
-   *
-   *   effectiveSize(M) = size(M) * cumulativeOwningC(M) * cumulativeOwnedC(M)
-   *
-   * This method assumes that (1) the size of the node and its children [see
-   * calculateSizes()] and (2) the cumulative owning and owned coefficients
-   * of the node (if it's a leaf node) [see the third step of
-   * calculateEffectiveSizes()] or the effective sizes of its children (if
-   * it's a non-leaf node) [depth-first post-order traversal] have already
-   * been calculated.
-   */
-  static void CalculateNodeEffectiveSize(GlobalNodeGraph::Node* node);
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_GRAPH_PROCESSOR_H_
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h
deleted file mode 100644
index f4899d5..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_ALLOCATOR_NODE_ID_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_ALLOCATOR_NODE_ID_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "perfetto/base/export.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class PERFETTO_EXPORT MemoryAllocatorNodeId {
- public:
-  MemoryAllocatorNodeId();
-  explicit MemoryAllocatorNodeId(uint64_t id);
-
-  uint64_t ToUint64() const { return id_; }
-
-  // Returns a (hex-encoded) string representation of the id.
-  std::string ToString() const;
-
-  bool empty() const { return id_ == 0u; }
-
-  bool operator==(const MemoryAllocatorNodeId& other) const {
-    return id_ == other.id_;
-  }
-
-  bool operator!=(const MemoryAllocatorNodeId& other) const {
-    return !(*this == other);
-  }
-
-  bool operator<(const MemoryAllocatorNodeId& other) const {
-    return id_ < other.id_;
-  }
-
- private:
-  uint64_t id_;
-
-  // Deliberately copy-able.
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_ALLOCATOR_NODE_ID_H_
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h
deleted file mode 100644
index 6f7d4fe..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_GRAPH_EDGE_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_GRAPH_EDGE_H_
-
-#include <stdint.h>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class PERFETTO_EXPORT MemoryGraphEdge {
- public:
-  MemoryGraphEdge(MemoryAllocatorNodeId s,
-                  MemoryAllocatorNodeId t,
-                  int i,
-                  bool o)
-      : source(s), target(t), importance(i), overridable(o) {}
-
-  MemoryGraphEdge& operator=(const MemoryGraphEdge& edge) {
-    source = edge.source;
-    target = edge.target;
-    importance = edge.importance;
-    overridable = edge.overridable;
-    return *this;
-  }
-
-  MemoryAllocatorNodeId source;
-  MemoryAllocatorNodeId target;
-  int importance;
-  bool overridable;
-
-  // Deliberately copy-able.
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_MEMORY_GRAPH_EDGE_H_
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h
deleted file mode 100644
index e865afe..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_MEMORY_GRAPH_NODE_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_MEMORY_GRAPH_NODE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Describes the level of detail of the memory graph.
-enum class LevelOfDetail : uint32_t {
-  kFirst,
-
-  // For background tracing mode. The node time is quick, and typically just the
-  // totals are expected. Suballocations need not be specified. Node name must
-  // contain only pre-defined strings and string arguments cannot be added.
-  kBackground = kFirst,
-
-  // For the levels below, MemoryNodeProvider instances must guarantee that the
-  // total size reported in the root node is consistent. Only the granularity of
-  // the child MemoryAllocatorNode(s) differs with the levels.
-
-  // Few entries, typically a fixed number, per node.
-  kLight,
-
-  // Unrestricted amount of entries per node.
-  kDetailed,
-
-  kLast = kDetailed
-};
-
-// Data model for user-land memory nodes.
-class PERFETTO_EXPORT RawMemoryGraphNode {
- public:
-  enum Flags {
-    kDefault = 0,
-
-    // A node marked weak will be discarded if there is no ownership edge exists
-    // from a non-weak node.
-    kWeak = 1 << 0,
-  };
-
-  // In the UI table each MemoryAllocatorNode becomes
-  // a row and each Entry generates a column (if it doesn't already
-  // exist).
-  struct PERFETTO_EXPORT MemoryNodeEntry {
-    enum EntryType {
-      kUint64,
-      kString,
-    };
-
-    MemoryNodeEntry(const std::string& name,
-                    const std::string& units,
-                    uint64_t value);
-    MemoryNodeEntry(const std::string& name,
-                    const std::string& units,
-                    const std::string& value);
-
-    bool operator==(const MemoryNodeEntry& rhs) const;
-
-    std::string name;
-    std::string units;
-
-    EntryType entry_type;
-
-    uint64_t value_uint64;
-    std::string value_string;
-  };
-
-  RawMemoryGraphNode(const std::string& absolute_name,
-                     LevelOfDetail level,
-                     MemoryAllocatorNodeId id);
-
-  RawMemoryGraphNode(
-      const std::string& absolute_name,
-      LevelOfDetail level,
-      MemoryAllocatorNodeId id,
-      std::vector<RawMemoryGraphNode::MemoryNodeEntry>&& entries);
-
-  // Standard attribute |name|s for the AddScalar and AddString() methods.
-  static const char kNameSize[];         // To represent allocated space.
-  static const char kNameObjectCount[];  // To represent number of objects.
-
-  // Standard attribute |unit|s for the AddScalar and AddString() methods.
-  static const char kUnitsBytes[];    // Unit name to represent bytes.
-  static const char kUnitsObjects[];  // Unit name to represent #objects.
-
-  // Constants used only internally and by tests.
-  static const char kTypeScalar[];  // Type name for scalar attributes.
-  static const char kTypeString[];  // Type name for string attributes.
-
-  // |id| is an optional global node identifier, unique across all processes
-  // within the scope of a global node.
-  // Subsequent MemoryAllocatorNode(s) with the same |absolute_name| are
-  // expected to have the same id.
-  MemoryAllocatorNodeId id() const { return id_; }
-
-  // Absolute name, unique within the scope of an entire ProcessMemoryNode.
-  const std::string& absolute_name() const { return absolute_name_; }
-
-  const std::vector<MemoryNodeEntry>& entries() const { return entries_; }
-
-  LevelOfDetail level_of_detail() const { return level_of_detail_; }
-
-  // Use enum Flags to set values.
-  void set_flags(int flags) { flags_ |= flags; }
-  void clear_flags(int flags) { flags_ &= ~flags; }
-  int flags() const { return flags_; }
-
- private:
-  std::string absolute_name_;
-  LevelOfDetail level_of_detail_;
-  std::vector<MemoryNodeEntry> entries_;
-  MemoryAllocatorNodeId id_;
-
-  // A node marked weak will be discarded by TraceViewer.
-  int flags_;  // See enum Flags.
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_MEMORY_GRAPH_NODE_H_
diff --git a/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h b/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h
deleted file mode 100644
index 66b4e89..0000000
--- a/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_PROCESS_MEMORY_NODE_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_PROCESS_MEMORY_NODE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h"
-#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// ProcessMemoryNode is as a strongly typed container which holds the nodes
-// produced by the MemoryNodeProvider(s) for a specific process.
-class PERFETTO_EXPORT RawProcessMemoryNode {
- public:
-  // Maps allocator nodes absolute names (allocator_name/heap/subheap) to
-  // MemoryAllocatorNode instances.
-  using MemoryNodesMap =
-      std::map<std::string, std::unique_ptr<RawMemoryGraphNode>>;
-
-  // Stores allocator node edges indexed by source allocator node GUID.
-  using AllocatorNodeEdgesMap =
-      std::map<MemoryAllocatorNodeId, std::unique_ptr<MemoryGraphEdge>>;
-
-  explicit RawProcessMemoryNode(
-      LevelOfDetail level_of_detail,
-      AllocatorNodeEdgesMap&& edges_map = AllocatorNodeEdgesMap{},
-      MemoryNodesMap&& nodes_map = MemoryNodesMap{});
-  RawProcessMemoryNode(RawProcessMemoryNode&&);
-  ~RawProcessMemoryNode();
-  RawProcessMemoryNode& operator=(RawProcessMemoryNode&&);
-
-  // Looks up a MemoryAllocatorNode given its allocator and heap names, or
-  // nullptr if not found.
-  RawMemoryGraphNode* GetAllocatorNode(const std::string& absolute_name) const;
-
-  // Returns the map of the MemoryAllocatorNodes added to this node.
-  const MemoryNodesMap& allocator_nodes() const { return allocator_nodes_; }
-
-  const AllocatorNodeEdgesMap& allocator_nodes_edges() const {
-    return allocator_nodes_edges_;
-  }
-
-  const LevelOfDetail& level_of_detail() const { return level_of_detail_; }
-
- private:
-  LevelOfDetail level_of_detail_;
-
-  // Keeps track of relationships between MemoryAllocatorNode(s).
-  AllocatorNodeEdgesMap allocator_nodes_edges_;
-
-  // Level of detail of the current node.
-  MemoryNodesMap allocator_nodes_;
-
-  // This class is uncopyable and unassignable.
-  RawProcessMemoryNode(const RawProcessMemoryNode&) = delete;
-  RawProcessMemoryNode& operator=(const RawProcessMemoryNode&) = delete;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_IMPORTERS_MEMORY_TRACKER_RAW_PROCESS_MEMORY_NODE_H_
diff --git a/include/perfetto/ext/traced/data_source_types.h b/include/perfetto/ext/traced/data_source_types.h
index a91b490..eef7be0 100644
--- a/include/perfetto/ext/traced/data_source_types.h
+++ b/include/perfetto/ext/traced/data_source_types.h
@@ -19,6 +19,7 @@
 
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 #include <set>
 #include <string>
 
diff --git a/include/perfetto/ext/traced/sys_stats_counters.h b/include/perfetto/ext/traced/sys_stats_counters.h
index fa846d6..f4ba962 100644
--- a/include/perfetto/ext/traced/sys_stats_counters.h
+++ b/include/perfetto/ext/traced/sys_stats_counters.h
@@ -208,57 +208,6 @@
     {"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},
-    {"allocstall_dma", protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_DMA},
-    {"allocstall_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_MOVABLE},
-    {"allocstall_normal",
-     protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL_NORMAL},
-    {"compact_daemon_free_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_FREE_SCANNED},
-    {"compact_daemon_migrate_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED},
-    {"nr_fastrpc", protos::pbzero::VmstatCounters::VMSTAT_NR_FASTRPC},
-    {"nr_indirectly_reclaimable",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_INDIRECTLY_RECLAIMABLE},
-    {"nr_ion_heap_pool",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ION_HEAP_POOL},
-    {"nr_kernel_misc_reclaimable",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_KERNEL_MISC_RECLAIMABLE},
-    {"nr_shadow_call_stack_bytes",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_SHADOW_CALL_STACK_BYTES},
-    {"nr_shmem_hugepages",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM_HUGEPAGES},
-    {"nr_shmem_pmdmapped",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM_PMDMAPPED},
-    {"nr_unreclaimable_pages",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_UNRECLAIMABLE_PAGES},
-    {"nr_zone_active_anon",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_ACTIVE_ANON},
-    {"nr_zone_active_file",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_ACTIVE_FILE},
-    {"nr_zone_inactive_anon",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_INACTIVE_ANON},
-    {"nr_zone_inactive_file",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_INACTIVE_FILE},
-    {"nr_zone_unevictable",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_UNEVICTABLE},
-    {"nr_zone_write_pending",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ZONE_WRITE_PENDING},
-    {"oom_kill", protos::pbzero::VmstatCounters::VMSTAT_OOM_KILL},
-    {"pglazyfree", protos::pbzero::VmstatCounters::VMSTAT_PGLAZYFREE},
-    {"pglazyfreed", protos::pbzero::VmstatCounters::VMSTAT_PGLAZYFREED},
-    {"pgrefill", protos::pbzero::VmstatCounters::VMSTAT_PGREFILL},
-    {"pgscan_direct", protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT},
-    {"pgscan_kswapd", protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD},
-    {"pgskip_dma", protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_DMA},
-    {"pgskip_movable", protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_MOVABLE},
-    {"pgskip_normal", protos::pbzero::VmstatCounters::VMSTAT_PGSKIP_NORMAL},
-    {"pgsteal_direct", protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT},
-    {"pgsteal_kswapd", protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD},
-    {"swap_ra_hit", protos::pbzero::VmstatCounters::VMSTAT_SWAP_RA_HIT},
-    {"swap_ra", protos::pbzero::VmstatCounters::VMSTAT_SWAP_RA},
-    {"workingset_restore",
-     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_RESTORE},
 };
 
 // Returns a lookup table of meminfo counter names addressable by counter id.
diff --git a/include/perfetto/ext/tracing/core/consumer.h b/include/perfetto/ext/tracing/core/consumer.h
index fce7c65..0cbd158 100644
--- a/include/perfetto/ext/tracing/core/consumer.h
+++ b/include/perfetto/ext/tracing/core/consumer.h
@@ -47,9 +47,8 @@
   // - 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. In this case |error|
-  //   is non-empty.
-  virtual void OnTracingDisabled(const std::string& error) = 0;
+  // - 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
diff --git a/include/perfetto/ext/tracing/core/shared_memory.h b/include/perfetto/ext/tracing/core/shared_memory.h
index b1bcbcb..11d078a 100644
--- a/include/perfetto/ext/tracing/core/shared_memory.h
+++ b/include/perfetto/ext/tracing/core/shared_memory.h
@@ -22,7 +22,6 @@
 #include <memory>
 
 #include "perfetto/base/export.h"
-#include "perfetto/base/platform_handle.h"
 
 namespace perfetto {
 
@@ -47,6 +46,7 @@
 
   virtual void* start() const = 0;
   virtual size_t size() const = 0;
+  virtual int fd() const = 0;
 };
 
 }  // namespace perfetto
diff --git a/include/perfetto/ext/tracing/core/shared_memory_abi.h b/include/perfetto/ext/tracing/core/shared_memory_abi.h
index 567a295..9d17850 100644
--- a/include/perfetto/ext/tracing/core/shared_memory_abi.h
+++ b/include/perfetto/ext/tracing/core/shared_memory_abi.h
@@ -143,8 +143,6 @@
 
 class SharedMemoryABI {
  public:
-  static constexpr size_t kMinPageSize = 4 * 1024;
-
   // This is due to Chunk::size being 16 bits.
   static constexpr size_t kMaxPageSize = 64 * 1024;
 
@@ -415,7 +413,7 @@
     }
 
     // Flags are cleared by TryAcquireChunk(), by passing the new header for
-    // the chunk, or through ClearNeedsPatchingFlag.
+    // the chunk.
     void SetFlag(ChunkHeader::Flags flag) {
       ChunkHeader* chunk_header = header();
       auto packets = chunk_header->packets.load(std::memory_order_relaxed);
@@ -423,18 +421,6 @@
       chunk_header->packets.store(packets, std::memory_order_release);
     }
 
-    // This flag can only be cleared by the producer while it is still holding
-    // on to the chunk - i.e. while the chunk is still in state
-    // ChunkState::kChunkBeingWritten and hasn't been transitioned to
-    // ChunkState::kChunkComplete. This is ok, because the service is oblivious
-    // to the needs patching flag before the chunk is released as complete.
-    void ClearNeedsPatchingFlag() {
-      ChunkHeader* chunk_header = header();
-      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
-      packets.flags &= ~ChunkHeader::kChunkNeedsPatching;
-      chunk_header->packets.store(packets, std::memory_order_release);
-    }
-
    private:
     friend class SharedMemoryABI;
     Chunk(uint8_t* begin, uint16_t size, uint8_t chunk_idx);
@@ -529,9 +515,7 @@
     return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingRead, nullptr);
   }
 
-  // The caller must have successfully TryAcquireAllChunksForReading() or it
-  // needs to guarantee that the chunk is already in the kChunkBeingWritten
-  // state.
+  // The caller must have successfully TryAcquireAllChunksForReading().
   Chunk GetChunkUnchecked(size_t page_idx,
                           uint32_t page_layout,
                           size_t chunk_idx);
diff --git a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
index 8d371a3..69849bb 100644
--- a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
+++ b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
@@ -113,61 +113,6 @@
   // committed in the shared memory buffer. Should only be called while bound.
   virtual void NotifyFlushComplete(FlushRequestID) = 0;
 
-  // Sets the duration during which commits are batched. Args:
-  // |batch_commits_duration_ms|: The length of the period, during which commits
-  // by all trace writers are accumulated, before being sent to the service.
-  // When the period ends, all accumulated commits are flushed. On the first
-  // commit after the last flush, another delayed flush is scheduled to run in
-  // |batch_commits_duration_ms|. If an immediate flush occurs (via
-  // FlushPendingCommitDataRequests()) during a batching period, any
-  // accumulated commits up to that point will be sent to the service
-  // immediately. And when the batching period ends, the commits that occurred
-  // after the immediate flush will also be sent to the service.
-  //
-  // If the duration has already been set to a non-zero value before this method
-  // is called, and there is already a scheduled flush with the previously-set
-  // duration, the new duration will take effect after the scheduled flush
-  // occurs.
-  //
-  // If |batch_commits_duration_ms| is non-zero, batched data that hasn't been
-  // sent could be lost at the end of a tracing session. To avoid this,
-  // producers should make sure that FlushPendingCommitDataRequests is called
-  // after the last TraceWriter write and before the service has stopped
-  // listening for commits from the tracing session's data sources (i.e.
-  // data sources should stop asynchronously, see
-  // DataSourceDescriptor.will_notify_on_stop=true).
-  virtual void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms) = 0;
-
-  // Called to enable direct producer-side patching of chunks that have not yet
-  // been committed to the service. The return value indicates whether direct
-  // patching was successfully enabled. It will be true if
-  // SharedMemoryArbiter::SetDirectSMBPatchingSupportedByService has been called
-  // and false otherwise.
-  virtual bool EnableDirectSMBPatching() = 0;
-
-  // When the producer and service live in separate processes, this method
-  // should be called if the producer receives an
-  // InitializeConnectionResponse.direct_smb_patching_supported set to true by
-  // the service (see producer_port.proto) .
-  //
-  // In the in-process case, the service will always support direct SMB patching
-  // and this method should always be called.
-  virtual void SetDirectSMBPatchingSupportedByService() = 0;
-
-  // Forces an immediate commit of the completed packets, without waiting for
-  // the next task or for a batching period to end. Should only be called while
-  // bound.
-  virtual void FlushPendingCommitDataRequests(
-      std::function<void()> callback = {}) = 0;
-
-  // Attempts to shut down this arbiter. This function prevents new trace
-  // writers from being created for this this arbiter, but if there are any
-  // existing trace writers, the shutdown cannot proceed and this funtion
-  // returns false. The caller should not delete the arbiter before all of its
-  // associated trace writers have been destroyed and this function returns
-  // true.
-  virtual bool TryShutdown() = 0;
-
   // Create a bound arbiter instance. Args:
   // |SharedMemory|: the shared memory buffer to use.
   // |page_size|: a multiple of 4KB that defines the granularity of tracing
diff --git a/include/perfetto/ext/tracing/core/slice.h b/include/perfetto/ext/tracing/core/slice.h
index 063043b..4ce66fd 100644
--- a/include/perfetto/ext/tracing/core/slice.h
+++ b/include/perfetto/ext/tracing/core/slice.h
@@ -44,14 +44,6 @@
     return slice;
   }
 
-  static Slice TakeOwnership(std::unique_ptr<uint8_t[]> buf, size_t size) {
-    Slice slice;
-    slice.own_data_ = std::move(buf);
-    slice.start = &slice.own_data_[0];
-    slice.size = size;
-    return slice;
-  }
-
   uint8_t* own_data() {
     PERFETTO_DCHECK(own_data_);
     return own_data_.get();
diff --git a/include/perfetto/ext/tracing/core/trace_writer.h b/include/perfetto/ext/tracing/core/trace_writer.h
index 1921371..6baaad9 100644
--- a/include/perfetto/ext/tracing/core/trace_writer.h
+++ b/include/perfetto/ext/tracing/core/trace_writer.h
@@ -59,10 +59,6 @@
   // 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.
-  // The returned packet handle is always valid, but note that, when using
-  // BufferExhaustedPolicy::kDrop and the SMB is exhausted, it may be assigned
-  // a garbage chunk and any trace data written into it will be lost. For more
-  // details on buffer size choices: https://perfetto.dev/docs/concepts/buffers.
   TracePacketHandle NewTracePacket() override = 0;
 
   // Commits the data pending for the current chunk into the shared memory
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index 9636cdf..3a72e90 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -41,9 +41,6 @@
 class SharedMemoryArbiter;
 class TraceWriter;
 
-// Exposed for testing.
-std::string GetBugreportPath();
-
 // 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.
 
@@ -225,20 +222,6 @@
   using QueryCapabilitiesCallback =
       std::function<void(const TracingServiceCapabilities&)>;
   virtual void QueryCapabilities(QueryCapabilitiesCallback) = 0;
-
-  // If any tracing session with TraceConfig.bugreport_score > 0 is running,
-  // this will pick the highest-score one, stop it and save it into a fixed
-  // path (See kBugreportTracePath).
-  // The callback is invoked when the file has been saved, in case of success,
-  // or whenever an error occurs.
-  // Args:
-  // - success: if true, an eligible trace was found and saved into file.
-  //            If false, either there was no eligible trace running or
-  //            something else failed (See |msg|).
-  // - msg: human readable diagnostic messages to debug failures.
-  using SaveTraceForBugreportCallback =
-      std::function<void(bool /*success*/, const std::string& /*msg*/)>;
-  virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0;
 };  // class ConsumerEndpoint.
 
 // The public API of the tracing Service business logic.
@@ -326,8 +309,7 @@
       ProducerSMBScrapingMode smb_scraping_mode =
           ProducerSMBScrapingMode::kDefault,
       size_t shared_memory_page_size_hint_bytes = 0,
-      std::unique_ptr<SharedMemory> shm = nullptr,
-      const std::string& sdk_version = {}) = 0;
+      std::unique_ptr<SharedMemory> shm = nullptr) = 0;
 
   // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
   // essentially a 1:1 channel between one Consumer and the Service.
diff --git a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
index da496b9..5469ded 100644
--- a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
+++ b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
@@ -21,7 +21,6 @@
 #include <string>
 
 #include "perfetto/base/export.h"
-#include "perfetto/ext/ipc/client.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"
@@ -37,16 +36,6 @@
 //   src/tracing/ipc/producer/producer_ipc_client_impl.cc
 class PERFETTO_EXPORT ProducerIPCClient {
  public:
-  enum class ConnectionFlags {
-    // Fails immediately with OnConnect(false) if the service connection cannot
-    // be established.
-    kDefault = 0,
-
-    // Keeps retrying with exponential backoff indefinitely. The caller will
-    // never see an OnConnect(false).
-    kRetryIfUnreachable = 1,
-  };
-
   // 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
@@ -62,8 +51,6 @@
   // until the client is destroyed.
   //
   // TODO(eseckler): Support adoption failure more gracefully.
-  // TODO(primiano): move all the existing use cases to the Connect(ConnArgs)
-  // below. Also move the functionality of ConnectionFlags into ConnArgs.
   static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
       const char* service_sock_name,
       Producer*,
@@ -74,21 +61,6 @@
       size_t shared_memory_size_hint_bytes = 0,
       size_t shared_memory_page_size_hint_bytes = 0,
       std::unique_ptr<SharedMemory> shm = nullptr,
-      std::unique_ptr<SharedMemoryArbiter> shm_arbiter = nullptr,
-      ConnectionFlags = ConnectionFlags::kDefault);
-
-  // Overload of Connect() to support adopting a connected socket using
-  // ipc::Client::ConnArgs.
-  static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
-      ipc::Client::ConnArgs,
-      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,
-      std::unique_ptr<SharedMemory> shm = nullptr,
       std::unique_ptr<SharedMemoryArbiter> shm_arbiter = nullptr);
 
  protected:
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
index 567851d..ed3deb9 100644
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
@@ -21,7 +21,6 @@
 
 #include "perfetto/base/export.h"
 #include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 
 namespace perfetto {
@@ -49,8 +48,8 @@
   // 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::ScopedSocketHandle producer_socket_fd,
-                     base::ScopedSocketHandle consumer_socket_fd) = 0;
+  virtual bool Start(base::ScopedFile producer_socket_fd,
+                     base::ScopedFile consumer_socket_fd) = 0;
 
   virtual TracingService* service() const = 0;
 
diff --git a/include/perfetto/profiling/BUILD.gn b/include/perfetto/profiling/BUILD.gn
index e7f9ddf..17dc5db 100644
--- a/include/perfetto/profiling/BUILD.gn
+++ b/include/perfetto/profiling/BUILD.gn
@@ -19,3 +19,7 @@
 source_set("normalize") {
   sources = [ "normalize.h" ]
 }
+
+source_set("deobfuscator") {
+  sources = [ "deobfuscator.h" ]
+}
diff --git a/include/perfetto/profiling/deobfuscator.h b/include/perfetto/profiling/deobfuscator.h
new file mode 100644
index 0000000..a6f467a
--- /dev/null
+++ b/include/perfetto/profiling/deobfuscator.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DEOBFUSCATOR_H_
+#define INCLUDE_PERFETTO_PROFILING_DEOBFUSCATOR_H_
+
+#include <map>
+#include <string>
+
+namespace perfetto {
+namespace profiling {
+
+struct ObfuscatedClass {
+  ObfuscatedClass(std::string d) : deobfuscated_name(std::move(d)) {}
+  ObfuscatedClass(std::string d, std::map<std::string, std::string> f)
+      : deobfuscated_name(std::move(d)), deobfuscated_fields(std::move(f)) {}
+
+  std::string deobfuscated_name;
+  std::map<std::string, std::string> deobfuscated_fields;
+};
+
+class ProguardParser {
+ public:
+  // A return value of false means this line failed to parse. This leaves the
+  // parser in an undefined state and it should no longer be used.
+  bool AddLine(std::string line);
+
+  std::map<std::string, ObfuscatedClass> ConsumeMapping() {
+    return std::move(mapping_);
+  }
+
+ private:
+  std::map<std::string, ObfuscatedClass> mapping_;
+  ObfuscatedClass* current_class_ = nullptr;
+};
+
+}  // namespace profiling
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_PROFILING_DEOBFUSCATOR_H_
diff --git a/include/perfetto/profiling/parse_smaps.h b/include/perfetto/profiling/parse_smaps.h
index e6c260c..47d11c9 100644
--- a/include/perfetto/profiling/parse_smaps.h
+++ b/include/perfetto/profiling/parse_smaps.h
@@ -25,7 +25,6 @@
 
 #include <errno.h>
 #include <stdio.h>
-#include <string.h>
 #include <unistd.h>
 
 #include <inttypes.h>
diff --git a/include/perfetto/profiling/pprof_builder.h b/include/perfetto/profiling/pprof_builder.h
index df18c5a..7e26f51 100644
--- a/include/perfetto/profiling/pprof_builder.h
+++ b/include/perfetto/profiling/pprof_builder.h
@@ -17,6 +17,7 @@
 #ifndef INCLUDE_PERFETTO_PROFILING_PPROF_BUILDER_H_
 #define INCLUDE_PERFETTO_PROFILING_PPROF_BUILDER_H_
 
+#include <iostream>
 #include <string>
 #include <vector>
 
@@ -32,34 +33,25 @@
 
 namespace trace_to_text {
 
-enum class ProfileType {
-  kHeapProfile,
-  kPerfProfile,
-};
-
 struct SerializedProfile {
-  ProfileType profile_type;
   uint64_t pid;
   std::string serialized;
-  // non-empty if profile_type == kHeapProfile
-  std::string heap_name;
 };
 
-enum class ConversionMode { kHeapProfile, kPerfProfile };
-
-enum class ConversionFlags : uint64_t {
-  kNone = 0,
-  // Suffix frame names with additional information. Current annotations are
-  // specific to apps running within the Android runtime, and include
-  // information such as whether the given frame was interpreted / executed
-  // under JIT / etc.
-  kAnnotateFrames = 1
-};
-
-bool TraceToPprof(trace_processor::TraceProcessor* tp,
+bool TraceToPprof(trace_processor::TraceProcessor*,
                   std::vector<SerializedProfile>* output,
-                  ConversionMode mode = ConversionMode::kHeapProfile,
-                  uint64_t flags = 0,
+                  profiling::Symbolizer* symbolizer,
+                  uint64_t pid = 0,
+                  const std::vector<uint64_t>& timestamps = {});
+
+bool TraceToPprof(std::istream* input,
+                  std::vector<SerializedProfile>* output,
+                  profiling::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 = {});
 
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index c99f7fd..ee0f77a 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -19,14 +19,11 @@
     "copyable_ptr.h",
     "cpp_message_obj.h",
     "field.h",
-    "field_writer.h",
     "message.h",
-    "message_arena.h",
     "message_handle.h",
     "packed_repeated_fields.h",
     "proto_decoder.h",
     "proto_utils.h",
-    "root_message.h",
     "scattered_heap_buffer.h",
     "scattered_stream_null_delegate.h",
     "scattered_stream_writer.h",
diff --git a/include/perfetto/protozero/field_writer.h b/include/perfetto/protozero/field_writer.h
deleted file mode 100644
index e8d76d7..0000000
--- a/include/perfetto/protozero/field_writer.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/message.h"
-#include "perfetto/protozero/proto_utils.h"
-
-#ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
-#define INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
-
-namespace protozero {
-namespace internal {
-
-template <proto_utils::ProtoSchemaType proto_schema_type>
-struct FieldWriter {
-  static_assert(proto_schema_type != proto_utils::ProtoSchemaType::kMessage,
-                "FieldWriter can't be used with nested messages");
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kDouble> {
-  inline static void Append(Message& message, uint32_t field_id, double value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kFloat> {
-  inline static void Append(Message& message, uint32_t field_id, float value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kBool> {
-  inline static void Append(Message& message, uint32_t field_id, bool value) {
-    message.AppendTinyVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kInt32> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int32_t value) {
-    message.AppendVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kInt64> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int64_t value) {
-    message.AppendVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kUint32> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            uint32_t value) {
-    message.AppendVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kUint64> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            uint64_t value) {
-    message.AppendVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kSint32> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int32_t value) {
-    message.AppendSignedVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kSint64> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int64_t value) {
-    message.AppendSignedVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kFixed32> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            uint32_t value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kFixed64> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            uint64_t value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed32> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int32_t value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kSfixed64> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            int64_t value) {
-    message.AppendFixed(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kEnum> {
-  template <typename EnumType>
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            EnumType value) {
-    message.AppendVarInt(field_id, value);
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kString> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            const char* data,
-                            size_t size) {
-    message.AppendBytes(field_id, data, size);
-  }
-
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            const std::string& value) {
-    message.AppendBytes(field_id, value.data(), value.size());
-  }
-};
-
-template <>
-struct FieldWriter<proto_utils::ProtoSchemaType::kBytes> {
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            const uint8_t* data,
-                            size_t size) {
-    message.AppendBytes(field_id, data, size);
-  }
-
-  inline static void Append(Message& message,
-                            uint32_t field_id,
-                            const std::string& value) {
-    message.AppendBytes(field_id, value.data(), value.size());
-  }
-};
-
-}  // namespace internal
-}  // namespace protozero
-
-#endif  // INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
diff --git a/include/perfetto/protozero/message.h b/include/perfetto/protozero/message.h
index 6a44ecc..b53dcda 100644
--- a/include/perfetto/protozero/message.h
+++ b/include/perfetto/protozero/message.h
@@ -38,28 +38,30 @@
 
 namespace protozero {
 
-class MessageArena;
 class MessageHandleBase;
 
 // Base class extended by the proto C++ stubs generated by the ProtoZero
 // compiler. This class provides the minimal runtime required to support
 // append-only operations and is designed for performance. None of the methods
-// require any dynamic memory allocation, unless more than 16 nested messages
-// are created via BeginNestedMessage() calls.
+// require any dynamic memory allocation.
 class PERFETTO_EXPORT Message {
  public:
   friend class MessageHandleBase;
 
-  // The ctor is deliberately a no-op to avoid forwarding args from all
-  // subclasses. The real initialization is performed by Reset().
-  // Nested messages are allocated via placement new by MessageArena and
-  // implictly destroyed when the RootMessage's arena goes away. This is
-  // fine as long as all the fields are PODs, which is checked by the
-  // static_assert()s in the Reset() method.
+  // 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;
+
+  // Ctor and Dtor of Message are never called, with the exeception
+  // of root (non-nested) messages. Nested messages are allocated via placement
+  // new in the |nested_messages_arena_| and implictly destroyed when the arena
+  // of the root message goes away. This is fine as long as all the fields are
+  // PODs, which is checked by the static_assert in the ctor (see the Reset()
+  // method in the .cc file).
   Message() = default;
 
   // Clears up the state, allowing the message to be reused as a fresh one.
-  void Reset(ScatteredStreamWriter*, MessageArena*);
+  void Reset(ScatteredStreamWriter*);
 
   // Commits all the changes to the buffer (backfills the size field of this and
   // all nested messages) and seals the message. Returns the size of the message
@@ -154,9 +156,10 @@
                               ContiguousMemoryRange* ranges,
                               size_t num_ranges);
 
-  // Begins a nested message. The returned object is owned by the MessageArena
-  // of the root message. The nested message ends either when Finalize() is
-  // called or when any other Append* method is called in the parent class.
+  // Begins a nested message, using the static storage provided by the parent
+  // class (see comment in |nested_messages_arena_|). The nested message ends
+  // either when Finalize() is called or when any other Append* method is called
+  // in the parent class.
   // The template argument T is supposed to be a stub class auto generated from
   // a .proto, hence a subclass of Message.
   template <class T>
@@ -167,13 +170,12 @@
                   "T must be a subclass of Message");
     static_assert(sizeof(T) == sizeof(Message),
                   "Message subclasses cannot introduce extra state.");
-    return static_cast<T*>(BeginNestedMessageInternal(field_id));
+    T* message = reinterpret_cast<T*>(nested_messages_arena_);
+    BeginNestedMessageInternal(field_id, message);
+    return message;
   }
 
-  // Gives read-only access to the underlying stream_writer. This is used only
-  // by few internals to query the state of the underlying buffer. It is almost
-  // always a bad idea to poke at the stream_writer() internals.
-  const ScatteredStreamWriter* stream_writer() const { return stream_writer_; }
+  ScatteredStreamWriter* stream_writer_for_testing() { return stream_writer_; }
 
   // Appends some raw bytes to the message. The use-case for this is preserving
   // unknown fields in the decode -> re-encode path of xxx.gen.cc classes
@@ -189,7 +191,7 @@
   Message(const Message&) = delete;
   Message& operator=(const Message&) = delete;
 
-  Message* BeginNestedMessageInternal(uint32_t field_id);
+  void BeginNestedMessageInternal(uint32_t field_id, Message*);
 
   // Called by Finalize and Append* methods.
   void EndNestedMessage();
@@ -208,22 +210,6 @@
   // The stream writer interface used for the serialization.
   ScatteredStreamWriter* stream_writer_;
 
-  // The storage used to allocate nested Message objects.
-  // This is owned by RootMessage<T>.
-  MessageArena* arena_;
-
-  // Pointer to the last child message created through BeginNestedMessage(), if
-  // any, nullptr otherwise. There is no need to keep track of more than one
-  // message per nesting level as the proto-zero API contract mandates that
-  // nested fields can be filled only in a stacked fashion. In other words,
-  // nested messages are finalized and sealed when any other field is set in the
-  // parent message (or the parent message itself is finalized) and cannot be
-  // accessed anymore afterwards.
-  Message* nested_message_;
-
-  // [optional] Pointer to a non-aligned pre-reserved var-int slot of
-  // kMessageLengthFieldSize bytes. When set, the Finalize() method will write
-  // the size of proto-encoded message in the pointed memory region.
   uint8_t* size_field_;
 
   // Keeps track of the size of the current message.
@@ -236,6 +222,10 @@
   // attempts of writing to a message which has been Finalize()-d.
   bool finalized_;
 
+  // Used to detect attemps to create messages with a nesting level >
+  // kMaxNestingDepth. |nesting_depth_| == 0 for root (non-nested) messages.
+  uint8_t nesting_depth_;
+
 #if PERFETTO_DCHECK_IS_ON()
   // Current generation of message. Incremented on Reset.
   // Used to detect stale handles.
@@ -243,6 +233,28 @@
 
   MessageHandleBase* handle_;
 #endif
+
+  // Pointer to the last child message created through BeginNestedMessage(), if
+  // any, nullptr otherwise. There is no need to keep track of more than one
+  // message per nesting level as the proto-zero API contract mandates that
+  // nested fields can be filled only in a stacked fashion. In other words,
+  // nested messages are finalized and sealed when any other field is set in the
+  // parent message (or the parent message itself is finalized) and cannot be
+  // accessed anymore afterwards.
+  // TODO(primiano): optimization: I think that nested_message_, when non-null.
+  // will always be @ (this) + offsetof(nested_messages_arena_).
+  Message* nested_message_;
+
+  // The root message owns the storage for all its nested messages, up to a max
+  // of kMaxNestingDepth levels (see the .cc file). Note that the boundaries of
+  // the arena are meaningful only for the root message.
+  // Unfortunately we cannot put the sizeof() math here because we cannot sizeof
+  // the current class in a header. However the .cc file has a static_assert
+  // that guarantees that (see the Reset() method in the .cc file).
+  alignas(sizeof(void*)) uint8_t nested_messages_arena_[512];
+
+  // DO NOT add any fields below |nested_messages_arena_|. The memory layout of
+  // nested messages would overflow the storage allocated by the root message.
 };
 
 }  // namespace protozero
diff --git a/include/perfetto/protozero/message_arena.h b/include/perfetto/protozero/message_arena.h
deleted file mode 100644
index 4905dae..0000000
--- a/include/perfetto/protozero/message_arena.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
-#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
-
-#include <stdint.h>
-
-#include <list>
-#include <type_traits>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/message.h"
-
-namespace protozero {
-
-class Message;
-
-// Object allocator for fixed-sized protozero::Message objects.
-// It's a simple bump-pointer allocator which leverages the stack-alike
-// usage pattern of protozero nested messages. It avoids hitting the system
-// allocator in most cases, by reusing the same block, and falls back on
-// allocating new blocks only when using deeply nested messages (which are
-// extremely rare).
-// This is used by RootMessage<T> to handle the storage for root-level messages.
-class PERFETTO_EXPORT MessageArena {
- public:
-  MessageArena();
-  ~MessageArena();
-
-  // Strictly no copies or moves as this is used to hand out pointers.
-  MessageArena(const MessageArena&) = delete;
-  MessageArena& operator=(const MessageArena&) = delete;
-  MessageArena(MessageArena&&) = delete;
-  MessageArena& operator=(MessageArena&&) = delete;
-
-  // Allocates a new Message object.
-  Message* NewMessage();
-
-  // Deletes the last message allocated. The |msg| argument is used only for
-  // DCHECKs, it MUST be the pointer obtained by the last NewMessage() call.
-  void DeleteLastMessage(Message* msg) {
-    PERFETTO_DCHECK(!blocks_.empty() && blocks_.back().entries > 0);
-    PERFETTO_DCHECK(&blocks_.back().storage[blocks_.back().entries - 1] ==
-                    static_cast<void*>(msg));
-    DeleteLastMessageInternal();
-  }
-
-  // Resets the state of the arena, clearing up all but one block. This is used
-  // to avoid leaking outstanding unfinished sub-messages while recycling the
-  // RootMessage object (this is extremely rare due to the RAII scoped handles
-  // but could happen if some client does some overly clever std::move() trick).
-  void Reset() {
-    PERFETTO_DCHECK(!blocks_.empty());
-    blocks_.resize(1);
-    auto& block = blocks_.back();
-    block.entries = 0;
-    PERFETTO_ASAN_POISON(block.storage, sizeof(block.storage));
-  }
-
- private:
-  void DeleteLastMessageInternal();
-
-  struct Block {
-    static constexpr size_t kCapacity = 16;
-
-    Block() { PERFETTO_ASAN_POISON(storage, sizeof(storage)); }
-
-    std::aligned_storage<sizeof(Message), alignof(Message)>::type
-        storage[kCapacity];
-    uint32_t entries = 0;  // # Message entries used (<= kCapacity).
-  };
-
-  // blocks are used to hand out pointers and must not be moved. Hence why
-  // std::list rather than std::vector.
-  std::list<Block> blocks_;
-};
-
-}  // namespace protozero
-
-#endif  // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_ARENA_H_
diff --git a/include/perfetto/protozero/proto_utils.h b/include/perfetto/protozero/proto_utils.h
index 6b195cb..d8f0592 100644
--- a/include/perfetto/protozero/proto_utils.h
+++ b/include/perfetto/protozero/proto_utils.h
@@ -162,10 +162,9 @@
 template <typename T>
 inline typename std::make_signed<T>::type ZigZagDecode(T value) {
   using UnsignedType = typename std::make_unsigned<T>::type;
-  using SignedType = typename std::make_signed<T>::type;
   auto u_value = static_cast<UnsignedType>(value);
-  auto mask = static_cast<UnsignedType>(-static_cast<SignedType>(u_value & 1));
-  return static_cast<SignedType>((u_value >> 1) ^ mask);
+  return static_cast<typename std::make_signed<T>::type>(
+      ((u_value >> 1) ^ -(u_value & 1)));
 }
 
 template <typename T>
@@ -201,20 +200,12 @@
 // used to backfill fixed-size reservations for the length field using a
 // non-canonical varint encoding (e.g. \x81\x80\x80\x00 instead of \x01).
 // See https://github.com/google/protobuf/issues/1530.
-// This is used mainly in two cases:
-// 1) At trace writing time, when starting a nested messages. The size of a
-//    nested message is not known until all its field have been written.
-//    |kMessageLengthFieldSize| bytes are reserved to encode the size field and
-//    backfilled at the end.
-// 2) When rewriting a message at trace filtering time, in protozero/filtering.
-//    At that point we know only the upper bound of the length (a filtered
-//    message is <= the original one) and we backfill after the message has been
-//    filtered.
-inline void WriteRedundantVarInt(uint32_t value,
-                                 uint8_t* buf,
-                                 size_t size = kMessageLengthFieldSize) {
-  for (size_t i = 0; i < size; ++i) {
-    const uint8_t msb = (i < size - 1) ? 0x80 : 0;
+// In particular, this is used for nested messages. The size of a nested message
+// is not known until all its field have been written. |kMessageLengthFieldSize|
+// bytes are reserved to encode the size field and backfilled at the end.
+inline void WriteRedundantVarInt(uint32_t value, uint8_t* buf) {
+  for (size_t i = 0; i < kMessageLengthFieldSize; ++i) {
+    const uint8_t msb = (i < kMessageLengthFieldSize - 1) ? 0x80 : 0;
     buf[i] = static_cast<uint8_t>(value) | msb;
     value >>= 7;
   }
@@ -252,53 +243,6 @@
   return start;
 }
 
-enum class RepetitionType {
-  kNotRepeated,
-  kRepeatedPacked,
-  kRepeatedNotPacked,
-};
-
-// Provide a common base struct for all templated FieldMetadata types to allow
-// simple checks if a given type is a FieldMetadata or not.
-struct FieldMetadataBase {
-  constexpr FieldMetadataBase() = default;
-};
-
-template <uint32_t field_id,
-          RepetitionType repetition_type,
-          ProtoSchemaType proto_schema_type,
-          typename CppFieldType,
-          typename MessageType>
-struct FieldMetadata : public FieldMetadataBase {
-  constexpr FieldMetadata() = default;
-
-  static constexpr int kFieldId = field_id;
-  // Whether this field is repeated, packed (repeated [packed-true]) or not
-  // (optional).
-  static constexpr RepetitionType kRepetitionType = repetition_type;
-  // Proto type of this field (e.g. int64, fixed32 or nested message).
-  static constexpr ProtoSchemaType kProtoFieldType = proto_schema_type;
-  // C++ type of this field (for nested messages - C++ protozero class).
-  using cpp_field_type = CppFieldType;
-  // Protozero message which this field belongs to.
-  using message_type = MessageType;
-};
-
-namespace internal {
-
-// Ideally we would create variables of FieldMetadata<...> type directly,
-// but before C++17's support for constexpr inline variables arrive, we have to
-// actually use pointers to inline functions instead to avoid having to define
-// symbols in *.pbzero.cc files.
-//
-// Note: protozero bindings will generate Message::kFieldName variable and which
-// can then be passed to TRACE_EVENT macro for inline writing of typed messages.
-// The fact that the former can be passed to the latter is a part of the stable
-// API, while the particular type is not and users should not rely on it.
-template <typename T>
-using FieldMetadataHelper = T (*)(void);
-
-}  // namespace internal
 }  // namespace proto_utils
 }  // namespace protozero
 
diff --git a/include/perfetto/protozero/root_message.h b/include/perfetto/protozero/root_message.h
deleted file mode 100644
index 40e2328..0000000
--- a/include/perfetto/protozero/root_message.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
-#define INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
-
-#include "perfetto/protozero/message.h"
-#include "perfetto/protozero/message_arena.h"
-
-namespace protozero {
-
-// Helper class to hand out messages using the default MessageArena.
-// Usage:
-// RootMessage<perfetto::protos::zero::MyMessage> msg;
-// msg.Reset(stream_writer);
-// msg.set_foo(...);
-// auto* nested = msg.set_nested();
-template <typename T = Message>
-class RootMessage : public T {
- public:
-  RootMessage() { T::Reset(nullptr, &root_arena_); }
-
-  // Disallow copy and move.
-  RootMessage(const RootMessage&) = delete;
-  RootMessage& operator=(const RootMessage&) = delete;
-  RootMessage(RootMessage&&) = delete;
-  RootMessage& operator=(RootMessage&&) = delete;
-
-  void Reset(ScatteredStreamWriter* writer) {
-    root_arena_.Reset();
-    Message::Reset(writer, &root_arena_);
-  }
-
- private:
-  MessageArena root_arena_;
-};
-
-}  // namespace protozero
-
-#endif  // INCLUDE_PERFETTO_PROTOZERO_ROOT_MESSAGE_H_
diff --git a/include/perfetto/protozero/scattered_heap_buffer.h b/include/perfetto/protozero/scattered_heap_buffer.h
index d62612e..bc6a0d2 100644
--- a/include/perfetto/protozero/scattered_heap_buffer.h
+++ b/include/perfetto/protozero/scattered_heap_buffer.h
@@ -23,7 +23,6 @@
 
 #include "perfetto/base/export.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/protozero/root_message.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
 
 namespace protozero {
@@ -72,10 +71,6 @@
   // protozero::ScatteredStreamWriter::Delegate implementation.
   protozero::ContiguousMemoryRange GetNewBuffer() override;
 
-  // Return the slices backing this buffer, adjusted for the number of bytes the
-  // writer has written.
-  const std::vector<Slice>& GetSlices();
-
   // Stitch all the slices into a single contiguous buffer.
   std::vector<uint8_t> StitchSlices();
 
@@ -83,8 +78,6 @@
   // outlive it.
   std::vector<protozero::ContiguousMemoryRange> GetRanges();
 
-  // Note that size of the last slice isn't updated to reflect the number of
-  // bytes written by the trace writer.
   const std::vector<Slice>& slices() const { return slices_; }
 
   void set_writer(protozero::ScatteredStreamWriter* writer) {
@@ -162,11 +155,6 @@
     return shb_.GetRanges();
   }
 
-  const std::vector<ScatteredHeapBuffer::Slice>& GetSlices() {
-    msg_.Finalize();
-    return shb_.GetSlices();
-  }
-
   void Reset() {
     shb_.Reset();
     writer_.Reset(protozero::ContiguousMemoryRange{});
@@ -177,7 +165,7 @@
  private:
   ScatteredHeapBuffer shb_;
   ScatteredStreamWriter writer_;
-  RootMessage<T> msg_;
+  T msg_;
 };
 
 }  // namespace protozero
diff --git a/include/perfetto/protozero/static_buffer.h b/include/perfetto/protozero/static_buffer.h
index 3d7ec3d..6f5924f 100644
--- a/include/perfetto/protozero/static_buffer.h
+++ b/include/perfetto/protozero/static_buffer.h
@@ -22,7 +22,6 @@
 #include <vector>
 
 #include "perfetto/base/export.h"
-#include "perfetto/protozero/root_message.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
 
 namespace protozero {
@@ -80,7 +79,7 @@
  private:
   StaticBufferDelegate delegate_;
   ScatteredStreamWriter writer_;
-  RootMessage<T> msg_;
+  T msg_;
 };
 
 // Helper function to create stack-based protozero messages in one line.
diff --git a/include/perfetto/test/BUILD.gn b/include/perfetto/test/BUILD.gn
deleted file mode 100644
index 9f4ef43..0000000
--- a/include/perfetto/test/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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("test_support") {
-  testonly = true
-
-  public_deps = [ "../tracing:tracing" ]
-
-  sources = [ "traced_value_test_support.h" ]
-}
diff --git a/include/perfetto/test/traced_value_test_support.h b/include/perfetto/test/traced_value_test_support.h
deleted file mode 100644
index 4fa0e2d..0000000
--- a/include/perfetto/test/traced_value_test_support.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TEST_TRACED_VALUE_TEST_SUPPORT_H_
-#define INCLUDE_PERFETTO_TEST_TRACED_VALUE_TEST_SUPPORT_H_
-
-#include "perfetto/base/export.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/traced_value.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-
-namespace perfetto {
-
-namespace internal {
-PERFETTO_EXPORT std::string DebugAnnotationToString(
-    const std::string& proto_message);
-}  // namespace internal
-
-// Leverage TracedValue support for the given value to convert it to a JSON-like
-// representation. Note: this should be _only_ for testing TracedValue
-// conversion and providing extra information for human consumption (e.g. when
-// the test fails).
-// Please do not rely on this to compare the object values in
-// tests and implement explicit comparison operators for the objects you want to
-// test as the stability of this representation is not guaranteed.
-template <typename T>
-std::string TracedValueToString(T&& value) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  WriteIntoTracedValue(internal::CreateTracedValueFromProto(message.get()),
-                       std::forward<T>(value));
-  return internal::DebugAnnotationToString(message.SerializeAsString());
-}
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TEST_TRACED_VALUE_TEST_SUPPORT_H_
diff --git a/include/perfetto/trace_processor/BUILD.gn b/include/perfetto/trace_processor/BUILD.gn
index ed1f3a9..8db2a2f 100644
--- a/include/perfetto/trace_processor/BUILD.gn
+++ b/include/perfetto/trace_processor/BUILD.gn
@@ -14,7 +14,6 @@
 
 source_set("trace_processor") {
   sources = [
-    "iterator.h",
     "read_trace.h",
     "trace_processor.h",
   ]
@@ -34,5 +33,4 @@
     "basic_types.h",
     "status.h",
   ]
-  public_deps = [ "../base" ]
 }
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index 2b38b6d..cc41758 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -34,63 +34,11 @@
 // simpler (e.g. use arrays instead of vectors).
 constexpr size_t kMaxCpus = 128;
 
-// Enum which encodes how trace processor should try to sort the ingested data.
-enum class SortingMode {
-  // This option allows trace processor to use built-in heuristics about how to
-  // sort the data. Generally, this option is correct for most embedders as
-  // trace processor reads information from the trace (e.g. TraceConfig) to make
-  // the best decision.
-  //
-  // The exact heuristics are implementation details but will ensure that all
-  // relevant tables are sorted by timestamp.
-  //
-  // This is the default mode.
-  kDefaultHeuristics = 0,
-
-  // This option forces trace processor to wait for all trace packets to be
-  // passed to it before doing a full sort of all the packets. This causes any
-  // heuristics trace processor would normally use to ingest partially sorted
-  // data to be skipped.
-  kForceFullSort = 1,
-
-  // This option forces trace processor to use the |flush_period_ms| specified
-  // in the TraceConfig to perform a windowed sort of the data. The window size
-  // is not guaranteed to be exactly |flush_period_ms| but will be of the same
-  // order of magnitude; the exact value is an implementation detail and should
-  // not be relied upon.
-  //
-  // If a |flush_period_ms| is not specified in the TraceConfig, this mode will
-  // act the same as |SortingMode::kDefaultHeuristics|.
-  kForceFlushPeriodWindowedSort = 2
-};
-
-// Enum which encodes which event (if any) should be used to drop ftrace data
-// from before this timestamp of that event.
-enum class DropFtraceDataBefore {
-  // Drops ftrace data before timestmap specified by the
-  // TracingServiceEvent::tracing_started packet. If this packet is not in the
-  // trace, no data is dropped.
-  // Note: this event was introduced in S+ so no data will be dropped on R-
-  // traces.
-  // This is the default approach.
-  kTracingStarted = 0,
-
-  // Retains all ftrace data regardless of timestamp and other events.
-  kNoDrop = 1,
-
-  // Drops ftrace data before timestmap specified by the
-  // TracingServiceEvent::all_data_sources_started. If this packet is not in the
-  // trace, no data is dropped.
-  // This option can be used in cases where R- traces are being considered and
-  // |kTracingStart| cannot be used because the event was not present.
-  kAllDataSourcesStarted = 2,
-};
-
 // Struct for configuring a TraceProcessor instance (see trace_processor.h).
 struct PERFETTO_EXPORT Config {
-  // Indicates the sortinng mode that trace processor should use on the passed
-  // trace packets. See the enum documentation for more details.
-  SortingMode sorting_mode = SortingMode::kDefaultHeuristics;
+  // 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;
 
   // When set to false, this option makes the trace processor not include ftrace
   // events in the raw table; this makes converting events back to the systrace
@@ -101,11 +49,6 @@
   // this flag is false and all other events which parse into the raw table are
   // unaffected by this flag.
   bool ingest_ftrace_in_raw_table = true;
-
-  // Indicates the event which should be used as a marker to drop ftrace data in
-  // the trace before that event. See the ennu documenetation for more details.
-  DropFtraceDataBefore drop_ftrace_data_before =
-      DropFtraceDataBefore::kTracingStarted;
 };
 
 // Represents a dynamically typed value returned by SQL.
@@ -142,14 +85,6 @@
     return value;
   }
 
-  static SqlValue Bytes(const void* v, size_t size) {
-    SqlValue value;
-    value.bytes_value = v;
-    value.bytes_count = size;
-    value.type = Type::kBytes;
-    return value;
-  }
-
   double AsDouble() const {
     PERFETTO_CHECK(type == kDouble);
     return double_value;
diff --git a/include/perfetto/trace_processor/iterator.h b/include/perfetto/trace_processor/iterator.h
deleted file mode 100644
index c3373f3..0000000
--- a/include/perfetto/trace_processor/iterator.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_ITERATOR_H_
-#define INCLUDE_PERFETTO_TRACE_PROCESSOR_ITERATOR_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 {
-
-class IteratorImpl;
-
-// Iterator returning SQL rows satisfied by a query.
-class PERFETTO_EXPORT Iterator {
- public:
-  explicit Iterator(std::unique_ptr<IteratorImpl>);
-  ~Iterator();
-
-  Iterator(Iterator&) noexcept = delete;
-  Iterator& operator=(Iterator&) = delete;
-
-  Iterator(Iterator&&) noexcept;
-  Iterator& operator=(Iterator&&);
-
-  // 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
-  // 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
-  // true. |col| must be less than the number returned by |ColumnCount()|.
-  SqlValue Get(uint32_t col);
-
-  // Returns the name of the column at index |col|. Can be called even before
-  // calling |Next()|.
-  std::string GetColumnName(uint32_t col);
-
-  // Returns the number of columns in this iterator's query. Can be called
-  // even before calling |Next()|.
-  uint32_t ColumnCount();
-
-  // Returns the status of the iterator.
-  util::Status Status();
-
- private:
-  friend class QueryResultSerializer;
-
-  // This is to allow QueryResultSerializer, which is very perf sensitive, to
-  // access direct the impl_ and avoid one extra function call for each cell.
-  template <typename T = IteratorImpl>
-  std::unique_ptr<T> take_impl() {
-    return std::move(iterator_);
-  }
-
-  // A PIMPL pattern is used to avoid leaking the dependencies on sqlite3.h and
-  // other internal classes.
-  std::unique_ptr<IteratorImpl> iterator_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACE_PROCESSOR_ITERATOR_H_
diff --git a/include/perfetto/trace_processor/status.h b/include/perfetto/trace_processor/status.h
index 6ee417e..ee7271a 100644
--- a/include/perfetto/trace_processor/status.h
+++ b/include/perfetto/trace_processor/status.h
@@ -17,20 +17,67 @@
 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_STATUS_H_
 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_STATUS_H_
 
-#include "perfetto/base/status.h"
+#include <stdarg.h>
+#include <string>
 
-// Once upon a time Status used to live in perfetto::trace_processor. At some
-// point it has been moved up to base. This forwarding header stayed here
-// because of out-of-repo users.
+#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 {
 
-using Status = ::perfetto::base::Status;
+// 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)) {}
 
-constexpr auto OkStatus = ::perfetto::base::OkStatus;
-constexpr auto ErrStatus = ::perfetto::base::ErrStatus;
+  // 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
diff --git a/include/perfetto/trace_processor/trace_processor.h b/include/perfetto/trace_processor/trace_processor.h
index c949695..920c3fa 100644
--- a/include/perfetto/trace_processor/trace_processor.h
+++ b/include/perfetto/trace_processor/trace_processor.h
@@ -23,7 +23,6 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/export.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/iterator.h"
 #include "perfetto/trace_processor/status.h"
 #include "perfetto/trace_processor/trace_processor_storage.h"
 
@@ -34,9 +33,45 @@
 // traces. See TraceProcessorStorage for parsing of trace files.
 class PERFETTO_EXPORT TraceProcessor : public TraceProcessorStorage {
  public:
-  // For legacy API clients. Iterator used to be a nested class here. Many API
-  // clients depends on it at this point.
-  using Iterator = ::perfetto::trace_processor::Iterator;
+  class IteratorImpl;
+
+  // Iterator returning SQL rows satisfied by a query.
+  class Iterator {
+   public:
+    Iterator(std::unique_ptr<IteratorImpl> iterator);
+    ~Iterator();
+
+    Iterator(Iterator&) noexcept = delete;
+    Iterator& operator=(Iterator&) = delete;
+
+    Iterator(Iterator&&) noexcept;
+    Iterator& operator=(Iterator&&);
+
+    // 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
+    // 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
+    // kHasNext. |col| must be less than the number returned by |ColumnCount()|.
+    SqlValue Get(uint32_t col);
+
+    // Returns the name of the column at index |col|. Can be called even before
+    // calling |Next()|.
+    std::string GetColumnName(uint32_t col);
+
+    // Returns the number of columns in this iterator's query. Can be called
+    // even before calling |Next()|.
+    uint32_t ColumnCount();
+
+    // Returns the status of the iterator.
+    util::Status Status();
+
+   private:
+    std::unique_ptr<IteratorImpl> iterator_;
+  };
 
   // Creates a new instance of TraceProcessor.
   static std::unique_ptr<TraceProcessor> CreateInstance(const Config&);
@@ -65,19 +100,6 @@
       const std::vector<std::string>& metric_names,
       std::vector<uint8_t>* metrics_proto) = 0;
 
-  enum MetricResultFormat {
-    kProtoText = 0,
-    kJson = 1,
-  };
-
-  // Computes metrics as the ComputeMetric function above, but instead of
-  // producing proto encoded bytes, the output argument |metrics_string| is
-  // filled with the metric formatted in the requested |format|.
-  virtual util::Status ComputeMetricText(
-      const std::vector<std::string>& metric_names,
-      MetricResultFormat format,
-      std::string* metrics_string) = 0;
-
   // Interrupts the current query. Typically used by Ctrl-C handler.
   virtual void InterruptQuery() = 0;
 
@@ -105,12 +127,6 @@
   // read.
   virtual util::Status DisableAndReadMetatrace(
       std::vector<uint8_t>* trace_proto) = 0;
-
-  // Gets all the currently loaded proto descriptors used in metric computation.
-  // This includes all compiled-in binary descriptors, and all proto descriptors
-  // loaded by trace processor shell at runtime. The message is encoded as
-  // DescriptorSet, defined in perfetto/trace_processor/trace_processor.proto.
-  virtual std::vector<uint8_t> GetMetricDescriptors() = 0;
 };
 
 // When set, logs SQLite actions on the console.
diff --git a/include/perfetto/tracing.h b/include/perfetto/tracing.h
index c542741..fca7c70 100644
--- a/include/perfetto/tracing.h
+++ b/include/perfetto/tracing.h
@@ -24,18 +24,15 @@
 // concern (e.g. chromium), which migh prefer sticking to strict IWYU.
 
 #include "perfetto/tracing/buffer_exhausted_policy.h"
-#include "perfetto/tracing/console_interceptor.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/interceptor.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"
 #include "perfetto/tracing/track_event_legacy.h"
-#include "perfetto/tracing/track_event_state_tracker.h"
 
 #endif  // INCLUDE_PERFETTO_TRACING_H_
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
index b7a91d0..b81e9f7 100644
--- a/include/perfetto/tracing/BUILD.gn
+++ b/include/perfetto/tracing/BUILD.gn
@@ -27,43 +27,28 @@
   ]
 
   sources = [
-    "backend_type.h",
     "buffer_exhausted_policy.h",
-    "console_interceptor.h",
     "data_source.h",
     "debug_annotation.h",
     "event_context.h",
-    "interceptor.h",
     "internal/basic_types.h",
-    "internal/checked_scope.h",
-    "internal/compile_time_hash.h",
     "internal/data_source_internal.h",
     "internal/in_process_tracing_backend.h",
-    "internal/interceptor_trace_writer.h",
     "internal/system_tracing_backend.h",
-    "internal/tracing_backend_fake.h",
     "internal/tracing_muxer.h",
     "internal/tracing_tls.h",
     "internal/track_event_data_source.h",
     "internal/track_event_internal.h",
-    "internal/track_event_interned_fields.h",
     "internal/track_event_macros.h",
-    "internal/write_track_event_args.h",
     "locked_handle.h",
     "platform.h",
-    "string_helpers.h",
     "trace_writer_base.h",
-    "traced_proto.h",
-    "traced_value.h",
-    "traced_value_forward.h",
     "tracing.h",
     "tracing_backend.h",
-    "tracing_policy.h",
     "track.h",
     "track_event.h",
     "track_event_category_registry.h",
     "track_event_interned_data_index.h",
     "track_event_legacy.h",
-    "track_event_state_tracker.h",
   ]
 }
diff --git a/include/perfetto/tracing/backend_type.h b/include/perfetto/tracing/backend_type.h
deleted file mode 100644
index e242650..0000000
--- a/include/perfetto/tracing/backend_type.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_BACKEND_TYPE_H_
-#define INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
-
-#include <stdint.h>
-
-namespace perfetto {
-
-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,
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_
diff --git a/include/perfetto/tracing/console_interceptor.h b/include/perfetto/tracing/console_interceptor.h
deleted file mode 100644
index 98c8879..0000000
--- a/include/perfetto/tracing/console_interceptor.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
-#define INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/tracing/interceptor.h"
-#include "perfetto/tracing/track_event_state_tracker.h"
-
-#include <stdarg.h>
-
-#include <functional>
-#include <map>
-#include <vector>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_PRINTF_ATTR \
-  __attribute__((format(printf, /*format_index=*/2, /*first_to_check=*/3)))
-#else
-#define PERFETTO_PRINTF_ATTR
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && !defined(STDOUT_FILENO)
-#define STDOUT_FILENO 1
-#define STDERR_FILENO 2
-#endif
-
-namespace perfetto {
-namespace protos {
-namespace pbzero {
-class DebugAnnotation_Decoder;
-class TracePacket_Decoder;
-class TrackEvent_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-struct ConsoleColor;
-
-class PERFETTO_EXPORT ConsoleInterceptor
-    : public Interceptor<ConsoleInterceptor> {
- public:
-  ~ConsoleInterceptor() override;
-
-  static void Register();
-  static void OnTracePacket(InterceptorContext context);
-
-  static void SetOutputFdForTesting(int fd);
-
-  void OnSetup(const SetupArgs&) override;
-  void OnStart(const StartArgs&) override;
-  void OnStop(const StopArgs&) override;
-
-  struct ThreadLocalState : public InterceptorBase::ThreadLocalState {
-    ThreadLocalState(ThreadLocalStateArgs&);
-    ~ThreadLocalState() override;
-
-    // Destination file. Assumed to stay valid until the program ends (i.e., is
-    // stderr or stdout).
-    int fd{};
-    bool use_colors{};
-
-    // Messages up to this length are buffered and written atomically. If a
-    // message is longer, it will be printed with multiple writes.
-    std::array<char, 1024> message_buffer{};
-    size_t buffer_pos{};
-
-    // We only support a single trace writer sequence per thread, so the
-    // sequence state is stored in TLS.
-    TrackEventStateTracker::SequenceState sequence_state;
-    uint64_t start_time_ns{};
-  };
-
- private:
-  class Delegate;
-
-  // Appends a formatted message to |message_buffer_| or directly to the output
-  // file if the buffer is full.
-  static void Printf(InterceptorContext& context,
-                     const char* format,
-                     ...) PERFETTO_PRINTF_ATTR;
-  static void Flush(InterceptorContext& context);
-  static void SetColor(InterceptorContext& context, const ConsoleColor&);
-  static void SetColor(InterceptorContext& context, const char*);
-
-  static void PrintDebugAnnotations(InterceptorContext&,
-                                    const protos::pbzero::TrackEvent_Decoder&,
-                                    const ConsoleColor& slice_color,
-                                    const ConsoleColor& highlight_color);
-  static void PrintDebugAnnotationName(
-      InterceptorContext&,
-      const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);
-  static void PrintDebugAnnotationValue(
-      InterceptorContext&,
-      const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation);
-
-  int fd_ = STDOUT_FILENO;
-  bool use_colors_ = true;
-
-  TrackEventStateTracker::SessionState session_state_;
-  uint64_t start_time_ns_{};
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index c4c6681..7780406 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -31,7 +31,6 @@
 #include <memory>
 #include <mutex>
 
-#include "perfetto/base/build_config.h"
 #include "perfetto/base/compiler.h"
 #include "perfetto/base/export.h"
 #include "perfetto/protozero/message.h"
@@ -173,12 +172,7 @@
         ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;
 
     TraceContext(TraceContext&&) noexcept = default;
-    ~TraceContext() {
-      // If the data source is being intercepted, flush the trace writer after
-      // each trace point to make sure the interceptor sees the data right away.
-      if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted))
-        Flush();
-    }
+    ~TraceContext() = default;
 
     TracePacketHandle NewTracePacket() {
       return tls_inst_->trace_writer->NewTracePacket();
@@ -224,13 +218,6 @@
     }
 
     typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
-      // Recreate incremental state data if it has been reset by the service.
-      if (tls_inst_->incremental_state_generation !=
-          static_state_.incremental_state_generation.load(
-              std::memory_order_relaxed)) {
-        tls_inst_->incremental_state.reset();
-        CreateIncrementalState(tls_inst_);
-      }
       return reinterpret_cast<typename DataSourceTraits::IncrementalStateType*>(
           tls_inst_->incremental_state.get());
     }
@@ -270,9 +257,7 @@
   // 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,
-                            typename Traits::TracePointData trace_point_data =
-                                {}) PERFETTO_ALWAYS_INLINE {
+  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
@@ -282,8 +267,8 @@
     // - |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(trace_point_data)
-                             ->load(std::memory_order_relaxed);
+    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).
@@ -298,19 +283,11 @@
   // CallIfEnabled().
   // |tracing_fn| will be called to record trace data as in Trace().
   //
-  // |trace_point_data| is an optional parameter given to |Traits::
-  // GetActiveInstances| to make it possible to use custom storage for
-  // the data source enabled state. This is, for example, used by TrackEvent to
-  // implement per-tracing category enabled states.
-  //
   // 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,
-      typename Traits::TracePointData trace_point_data = {}) {
+  static void TraceWithInstances(uint32_t instances, Lambda tracing_fn) {
     PERFETTO_DCHECK(instances);
     constexpr auto kMaxDataSourceInstances = internal::kMaxDataSourceInstances;
 
@@ -319,11 +296,6 @@
     if (PERFETTO_UNLIKELY(!tls_state_))
       tls_state_ = GetOrCreateDataSourceTLS(&static_state_);
 
-    // Avoid re-entering the trace point recursively.
-    if (PERFETTO_UNLIKELY(tls_state_->root_tls->is_in_trace_point))
-      return;
-    internal::ScopedReentrancyAnnotator scoped_annotator(*tls_state_->root_tls);
-
     // 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
@@ -382,21 +354,19 @@
         // 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(trace_point_data)
-                        ->load(std::memory_order_acquire);
+        instances =
+            Traits::GetActiveInstances()->load(std::memory_order_acquire);
         instance_state = static_state_.TryGetCached(instances, i);
         if (!instance_state || !instance_state->trace_lambda_enabled)
-          continue;
+          return;
         tls_inst.backend_id = instance_state->backend_id;
-        tls_inst.backend_connection_id = instance_state->backend_connection_id;
         tls_inst.buffer_id = instance_state->buffer_id;
-        tls_inst.data_source_instance_id =
-            instance_state->data_source_instance_id;
-        tls_inst.is_intercepted = instance_state->interceptor_id != 0;
         tls_inst.trace_writer = tracing_impl->CreateTraceWriter(
-            &static_state_, i, instance_state,
-            DataSourceType::kBufferExhaustedPolicy);
-        CreateIncrementalState(&tls_inst);
+            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.
@@ -415,21 +385,18 @@
   // Can return false to signal failure if attemping to register more than
   // kMaxDataSources (32) data sources types or if tracing hasn't been
   // initialized.
-  // The optional |constructor_args| will be passed to the data source when it
-  // is constructed.
-  template <class... Args>
-  static bool Register(const DataSourceDescriptor& descriptor,
-                       const Args&... constructor_args) {
+  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 = [constructor_args...]() {
-      return std::unique_ptr<DataSourceBase>(
-          new DataSourceType(constructor_args...));
+    auto factory = [] {
+      return std::unique_ptr<DataSourceBase>(new DataSourceType());
     };
     auto* tracing_impl = internal::TracingMuxer::Get();
+    if (!tracing_impl)
+      return false;
     return tracing_impl->RegisterDataSource(descriptor, factory,
                                             &static_state_);
   }
@@ -444,13 +411,7 @@
     //
     // DANGER: when doing this, the data source must use the appropriate memory
     // fences when changing the state of the bitmap.
-    //
-    // |TraceWithInstances| may be optionally given an additional parameter for
-    // looking up the enable flags. That parameter is passed as |TracePointData|
-    // to |GetActiveInstances|. This is, for example, used by TrackEvent to
-    // implement per-category enabled states.
-    struct TracePointData {};
-    static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
+    static constexpr std::atomic<uint32_t>* GetActiveInstances() {
       return &static_state_.valid_instances;
     }
   };
@@ -459,37 +420,23 @@
   // storage. Note: The second parameter here is used to specialize the case
   // where there is no incremental state type.
   template <typename T>
-  static void CreateIncrementalStateImpl(
+  static void CreateIncrementalState(
       internal::DataSourceInstanceThreadLocalState* tls_inst,
       const T*) {
     PERFETTO_DCHECK(!tls_inst->incremental_state);
-    tls_inst->incremental_state_generation =
-        static_state_.incremental_state_generation.load(
-            std::memory_order_relaxed);
     tls_inst->incremental_state =
         internal::DataSourceInstanceThreadLocalState::IncrementalStatePointer(
             reinterpret_cast<void*>(new T()),
             [](void* p) { delete reinterpret_cast<T*>(p); });
   }
-
-  static void CreateIncrementalStateImpl(
+  static void CreateIncrementalState(
       internal::DataSourceInstanceThreadLocalState*,
       const void*) {}
 
-  static void CreateIncrementalState(
-      internal::DataSourceInstanceThreadLocalState* tls_inst) {
-    CreateIncrementalStateImpl(
-        tls_inst,
-        static_cast<typename DataSourceTraits::IncrementalStateType*>(nullptr));
-  }
-
   // 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) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_IOS)
-    PERFETTO_FATAL("Data source TLS not supported on iOS, see b/158814068");
-#endif
     auto* tracing_impl = internal::TracingMuxer::Get();
     internal::TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS();
     internal::DataSourceThreadLocalState* ds_tls =
@@ -512,16 +459,13 @@
   // 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 PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState* tls_state_;
+  static thread_local internal::DataSourceThreadLocalState* tls_state_;
 };
 
-// static
 template <typename T, typename D>
 internal::DataSourceStaticState DataSource<T, D>::static_state_;
-// static
 template <typename T, typename D>
-PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState*
-    DataSource<T, D>::tls_state_;
+thread_local internal::DataSourceThreadLocalState* DataSource<T, D>::tls_state_;
 
 }  // namespace perfetto
 
@@ -538,35 +482,19 @@
   PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \
       perfetto::DataSource<__VA_ARGS__>::static_state_;               \
   template <>                                                         \
-  PERFETTO_COMPONENT_EXPORT PERFETTO_THREAD_LOCAL                     \
-      perfetto::internal::DataSourceThreadLocalState*                 \
+  PERFETTO_COMPONENT_EXPORT thread_local perfetto::internal::         \
+      DataSourceThreadLocalState*                                     \
           perfetto::DataSource<__VA_ARGS__>::tls_state_
 
-// MSVC has a bug where explicit template member specialization declarations
-// can't have thread_local as the storage class specifier. The generated code
-// seems correct without the specifier, so drop it until the bug gets fixed.
-// See https://developercommunity2.visualstudio.com/t/Unable-to-specialize-
-// static-thread_local/1302689.
-#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
-#define PERFETTO_TEMPLATE_THREAD_LOCAL
-#else
-#define PERFETTO_TEMPLATE_THREAD_LOCAL PERFETTO_THREAD_LOCAL
-#endif
-
 // This macro must be used once for each data source in one source file to
 // allocate static storage for the data source's static state.
-//
-// Note: if MSVC fails with a C2086 (redefinition) error here, use the
-// permissive- flag to enable standards-compliant mode. See
-// https://developercommunity.visualstudio.com/content/problem/319447/
-// explicit-specialization-of-static-data-member-inco.html.
 #define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...)               \
   template <>                                                         \
   PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \
       perfetto::DataSource<__VA_ARGS__>::static_state_{};             \
   template <>                                                         \
-  PERFETTO_COMPONENT_EXPORT PERFETTO_TEMPLATE_THREAD_LOCAL            \
-      perfetto::internal::DataSourceThreadLocalState*                 \
+  PERFETTO_COMPONENT_EXPORT 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/debug_annotation.h b/include/perfetto/tracing/debug_annotation.h
index 86494cf..2b479fe 100644
--- a/include/perfetto/tracing/debug_annotation.h
+++ b/include/perfetto/tracing/debug_annotation.h
@@ -18,7 +18,6 @@
 #define INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
 
 #include "perfetto/base/export.h"
-#include "perfetto/tracing/traced_value_forward.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 
 #include <stdint.h>
@@ -55,10 +54,86 @@
 
   // Called to write the contents of the debug annotation into the trace.
   virtual void Add(protos::pbzero::DebugAnnotation*) const = 0;
-
-  void WriteIntoTracedValue(TracedValue context) const;
 };
 
+namespace internal {
+// Overloads for all the supported built in debug annotation types. Numeric
+// types are handled with templates to avoid problems with overloading
+// platform-specific types (e.g., size_t).
+void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
+                                          const char*);
+void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
+                                          const std::string&);
+void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
+                                          const void*);
+void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
+                                          const DebugAnnotation&);
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<std::is_floating_point<T>::value>::type* =
+        nullptr) {
+  annotation->set_double_value(static_cast<double>(value));
+}
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<std::is_integral<T>::value &&
+                            !std::is_same<T, bool>::value &&
+                            std::is_signed<T>::value>::type* = nullptr) {
+  annotation->set_int_value(value);
+}
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<
+        std::is_enum<T>::value &&
+        std::is_signed<typename safe_underlying_type<T>::type>::value>::type* =
+        nullptr) {
+  annotation->set_int_value(value);
+}
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<std::is_enum<T>::value &&
+                            std::is_unsigned<typename safe_underlying_type<
+                                T>::type>::value>::type* = nullptr) {
+  annotation->set_uint_value(value);
+}
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<std::is_integral<T>::value &&
+                            !std::is_same<T, bool>::value &&
+                            std::is_unsigned<T>::value>::type* = nullptr) {
+  annotation->set_uint_value(value);
+}
+
+template <typename T>
+void WriteDebugAnnotation(
+    protos::pbzero::DebugAnnotation* annotation,
+    T value,
+    typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr) {
+  annotation->set_bool_value(value);
+}
+
+template <typename T>
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+                          const std::unique_ptr<T>& value) {
+  WriteDebugAnnotation(annotation, *value);
+}
+
+}  // namespace internal
 }  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
diff --git a/include/perfetto/tracing/event_context.h b/include/perfetto/tracing/event_context.h
index 21cb788..fe9c4bb 100644
--- a/include/perfetto/tracing/event_context.h
+++ b/include/perfetto/tracing/event_context.h
@@ -19,7 +19,6 @@
 
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/tracing/internal/track_event_internal.h"
-#include "perfetto/tracing/traced_proto.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
@@ -42,38 +41,12 @@
 
   // For Chromium during the transition phase to the client library.
   // TODO(eseckler): Remove once Chromium has switched to client lib entirely.
-  explicit EventContext(
-      protos::pbzero::TrackEvent* event,
-      internal::TrackEventIncrementalState* incremental_state = nullptr)
-      : event_(event), incremental_state_(incremental_state) {}
+  explicit EventContext(protos::pbzero::TrackEvent* event)
+      : event_(event), incremental_state_(nullptr) {}
 
   ~EventContext();
 
-  // Get a TrackEvent message to write typed arguments to.
-  //
-  // event() is a template method to allow callers to specify a subclass of
-  // TrackEvent instead. Those subclasses correspond to TrackEvent message with
-  // application-specific extensions. More information in
-  // design-docs/extensions.md.
-  template <typename EventType = protos::pbzero::TrackEvent>
-  EventType* event() const {
-    // As the method does downcasting, we check that a target subclass does
-    // not add new fields.
-    static_assert(
-        sizeof(EventType) == sizeof(protos::pbzero::TrackEvent),
-        "Event type must be binary-compatible with protos::pbzero::TrackEvent");
-    return static_cast<EventType*>(event_);
-  }
-
-  // Convert a raw pointer to protozero message to TracedProto which captures
-  // the reference to this EventContext.
-  template <typename MessageType>
-  TracedProto<MessageType> Wrap(MessageType* message) {
-    static_assert(std::is_base_of<protozero::Message, MessageType>::value,
-                  "TracedProto can be used only with protozero messages");
-
-    return TracedProto<MessageType>(message, *this);
-  }
+  protos::pbzero::TrackEvent* event() const { return event_; }
 
  private:
   template <typename, size_t, typename, typename>
diff --git a/include/perfetto/tracing/interceptor.h b/include/perfetto/tracing/interceptor.h
deleted file mode 100644
index 643b5a4..0000000
--- a/include/perfetto/tracing/interceptor.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
-#define INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
-
-// An interceptor is used to redirect trace packets written by a data source
-// into a custom backend instead of the normal Perfetto tracing service. For
-// example, the console interceptor prints all trace packets to the console as
-// they are generated. Another potential use is exporting trace data to another
-// tracing service such as Android ATrace or Windows ETW.
-//
-// An interceptor is defined by subclassing the perfetto::Interceptor template:
-//
-// class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-//  public:
-//   ~MyInterceptor() override = default;
-//
-//   // This function is called for each intercepted trace packet. |context|
-//   // contains information about the trace packet as well as other state
-//   // tracked by the interceptor (e.g., see ThreadLocalState).
-//   //
-//   // Intercepted trace data is provided in the form of serialized protobuf
-//   // bytes, accessed through the |context.packet_data| field.
-//   //
-//   // Warning: this function can be called on any thread at any time. See
-//   // below for how to safely access shared interceptor data from here.
-//   static void OnTracePacket(InterceptorContext context) {
-//     perfetto::protos::pbzero::TracePacket::Decoder packet(
-//         context.packet_data.data, context.packet_data.size);
-//     // ... Write |packet| to the desired destination ...
-//   }
-// };
-//
-// An interceptor should be registered before any tracing sessions are started.
-// Note that the interceptor also needs to be activated through the trace config
-// as shown below.
-//
-//   perfetto::InterceptorDescriptor desc;
-//   desc.set_name("my_interceptor");
-//   MyInterceptor::Register(desc);
-//
-// Finally, an interceptor is enabled through the trace config like this:
-//
-//   perfetto::TraceConfig cfg;
-//   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-//   ds_cfg->set_name("data_source_to_intercept");   // e.g. "track_event"
-//   ds_cfg->mutable_interceptor_config()->set_name("my_interceptor");
-//
-// Once an interceptor is enabled, all data from the affected data sources is
-// sent to the interceptor instead of the main tracing buffer.
-//
-// Interceptor state
-// =================
-//
-// Besides the serialized trace packet data, the |OnTracePacket| interceptor
-// function can access three other types of state:
-//
-// 1. Global state: this is no different from a normal static function, but care
-//    must be taken because |OnTracePacket| can be called concurrently on any
-//    thread at any time.
-//
-// 2. Per-data source instance state: since the interceptor class is
-//    automatically instantiated for each intercepted data source, its fields
-//    can be used to store per-instance data such as the trace config. This data
-//    can be maintained through the OnSetup/OnStart/OnStop callbacks:
-//
-//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-//     public:
-//      void OnSetup(const SetupArgs& args) override {
-//        enable_foo_ = args.config.interceptor_config().enable_foo();
-//      }
-//
-//      bool enable_foo_{};
-//    };
-//
-//    In the interceptor function this data must be accessed through a scoped
-//    lock for safety:
-//
-//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-//      ...
-//      static void OnTracePacket(InterceptorContext context) {
-//        auto my_interceptor = context.GetInterceptorLocked();
-//        if (my_interceptor) {
-//           // Access fields of MyInterceptor here.
-//           if (my_interceptor->enable_foo_) { ... }
-//        }
-//        ...
-//      }
-//    };
-//
-//    Since accessing this data involves holding a lock, it should be done
-//    sparingly.
-//
-// 3. Per-thread/TraceWriter state: many data sources use interning to avoid
-//    repeating common data in the trace. Since the interning dictionaries are
-//    typically kept individually for each TraceWriter sequence (i.e., per
-//    thread), an interceptor can declare a data structure with lifetime
-//    matching the TraceWriter:
-//
-//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-//     public:
-//      struct ThreadLocalState
-//          : public perfetto::InterceptorBase::ThreadLocalState {
-//        ThreadLocalState(ThreadLocalStateArgs&) override = default;
-//        ~ThreadLocalState() override = default;
-//
-//        std::map<size_t, std::string> event_names;
-//      };
-//    };
-//
-//    This per-thread state can then be accessed and maintained in
-//    |OnTracePacket| like this:
-//
-//    class MyInterceptor : public perfetto::Interceptor<MyInterceptor> {
-//      ...
-//      static void OnTracePacket(InterceptorContext context) {
-//        // Updating interned data.
-//        auto& tls = context.GetThreadLocalState();
-//        if (parsed_packet.sequence_flags() & perfetto::protos::pbzero::
-//                TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
-//          tls.event_names.clear();
-//        }
-//        for (const auto& entry : parsed_packet.interned_data().event_names())
-//          tls.event_names[entry.iid()] = entry.name();
-//
-//        // Looking up interned data.
-//        if (parsed_packet.has_track_event()) {
-//          size_t name_iid = parsed_packet.track_event().name_iid();
-//          const std::string& event_name = tls.event_names[name_iid];
-//        }
-//        ...
-//      }
-//    };
-//
-
-#include <functional>
-
-#include "perfetto/protozero/field.h"
-#include "perfetto/tracing/core/forward_decls.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/internal/data_source_internal.h"
-#include "perfetto/tracing/locked_handle.h"
-
-namespace {
-class MockTracingMuxer;
-}
-
-namespace perfetto {
-namespace protos {
-namespace gen {
-class DataSourceConfig;
-class InterceptorDescriptor;
-}  // namespace gen
-}  // namespace protos
-
-using protos::gen::InterceptorDescriptor;
-
-namespace internal {
-class InterceptorTraceWriter;
-class TracingMuxer;
-class TracingMuxerFake;
-class TracingMuxerImpl;
-}  // namespace internal
-
-// A virtual base class for interceptors. Users should derive from the templated
-// subclass below instead of this one.
-class PERFETTO_EXPORT InterceptorBase {
- public:
-  virtual ~InterceptorBase();
-
-  // A virtual base class for thread-local state needed by the interceptor.
-  // To define your own state, subclass this with the same name in the
-  // interceptor class. A reference to the state can then be looked up through
-  // context.GetThreadLocalState() in the trace packet interceptor function.
-  class ThreadLocalState {
-   public:
-    virtual ~ThreadLocalState();
-  };
-
-  struct SetupArgs {
-    const DataSourceConfig& config;
-  };
-  struct StartArgs {};
-  struct StopArgs {};
-
-  // Called when an intercepted data source is set up. Both the interceptor's
-  // and the data source's configuration is available in
-  // |SetupArgs|. Called on an internal Perfetto service thread, but not
-  // concurrently.
-  virtual void OnSetup(const SetupArgs&) {}
-
-  // Called when an intercepted data source starts. Called on an internal
-  // Perfetto service thread, but not concurrently.
-  virtual void OnStart(const StartArgs&) {}
-
-  // Called when an intercepted data source stops. Called on an internal
-  // Perfetto service thread, but not concurrently.
-  virtual void OnStop(const StopArgs&) {}
-
- private:
-  friend class internal::InterceptorTraceWriter;
-  friend class internal::TracingMuxer;
-  friend class internal::TracingMuxerFake;
-  friend class internal::TracingMuxerImpl;
-  friend MockTracingMuxer;
-  template <class T>
-  friend class Interceptor;
-
-  // Data passed from DataSource::Trace() into the interceptor.
-  struct TracePacketCallbackArgs {
-    internal::DataSourceStaticState* static_state;
-    uint32_t instance_index;
-    protozero::ConstBytes packet_data;
-    ThreadLocalState* tls;
-  };
-
-  // These callback functions are defined as stateless to avoid accidentally
-  // introducing cross-thread data races.
-  using TLSFactory = std::unique_ptr<ThreadLocalState> (*)(
-      internal::DataSourceStaticState*,
-      uint32_t data_source_instance_index);
-  using TracePacketCallback = void (*)(TracePacketCallbackArgs);
-
-  static void RegisterImpl(
-      const InterceptorDescriptor& descriptor,
-      std::function<std::unique_ptr<InterceptorBase>()> factory,
-      InterceptorBase::TLSFactory tls_factory,
-      InterceptorBase::TracePacketCallback on_trace_packet);
-};
-
-// Templated interceptor instantiation. See above for usage.
-template <class InterceptorType>
-class PERFETTO_EXPORT Interceptor : public InterceptorBase {
- public:
-  // A context object provided to the ThreadLocalState constructor. Provides
-  // access to the per-instance interceptor object.
-  class ThreadLocalStateArgs {
-   public:
-    ~ThreadLocalStateArgs() = default;
-
-    // Return a locked reference to the interceptor session. The session object
-    // will remain valid as long as the returned handle is in scope.
-    LockedHandle<InterceptorType> GetInterceptorLocked() {
-      auto* internal_state = static_state_->TryGet(data_source_instance_index_);
-      if (!internal_state)
-        return LockedHandle<InterceptorType>();
-      return LockedHandle<InterceptorType>(
-          &internal_state->lock,
-          static_cast<InterceptorType*>(internal_state->interceptor.get()));
-    }
-
-   private:
-    friend class Interceptor<InterceptorType>;
-    friend class InterceptorContext;
-    friend class TracingMuxerImpl;
-
-    ThreadLocalStateArgs(internal::DataSourceStaticState* static_state,
-                         uint32_t data_source_instance_index)
-        : static_state_(static_state),
-          data_source_instance_index_(data_source_instance_index) {}
-
-    internal::DataSourceStaticState* const static_state_;
-    const uint32_t data_source_instance_index_;
-  };
-
-  // A context object provided to each call into |OnTracePacket|. Contains the
-  // intercepted serialized trace packet data.
-  class InterceptorContext {
-   public:
-    InterceptorContext(InterceptorContext&&) noexcept = default;
-    ~InterceptorContext() = default;
-
-    // Return a locked reference to the interceptor session. The session object
-    // will remain valid as long as the returned handle is in scope.
-    LockedHandle<InterceptorType> GetInterceptorLocked() {
-      return tls_args_.GetInterceptorLocked();
-    }
-
-    // Return the thread-local state for this interceptor. See
-    // InterceptorBase::ThreadLocalState.
-    typename InterceptorType::ThreadLocalState& GetThreadLocalState() {
-      return static_cast<typename InterceptorType::ThreadLocalState&>(*tls_);
-    }
-
-    // A buffer containing the serialized TracePacket protocol buffer message.
-    // This memory is only valid during the call to OnTracePacket.
-    protozero::ConstBytes packet_data;
-
-   private:
-    friend class Interceptor<InterceptorType>;
-    InterceptorContext(TracePacketCallbackArgs args)
-        : packet_data(args.packet_data),
-          tls_args_(args.static_state, args.instance_index),
-          tls_(args.tls) {}
-    InterceptorContext(const InterceptorContext&) = delete;
-    InterceptorContext& operator=(const InterceptorContext&) = delete;
-
-    ThreadLocalStateArgs tls_args_;
-    InterceptorBase::ThreadLocalState* const tls_;
-  };
-
-  // Register the interceptor for use in tracing sessions.
-  // The optional |constructor_args| will be passed to the interceptor when it
-  // is constructed.
-  template <class... Args>
-  static void Register(const InterceptorDescriptor& descriptor,
-                       const Args&... constructor_args) {
-    auto factory = [constructor_args...]() {
-      return std::unique_ptr<InterceptorBase>(
-          new InterceptorType(constructor_args...));
-    };
-    auto tls_factory = [](internal::DataSourceStaticState* static_state,
-                          uint32_t data_source_instance_index) {
-      // Don't bother allocating TLS state unless the interceptor is actually
-      // using it.
-      if (std::is_same<typename InterceptorType::ThreadLocalState,
-                       InterceptorBase::ThreadLocalState>::value) {
-        return std::unique_ptr<InterceptorBase::ThreadLocalState>(nullptr);
-      }
-      ThreadLocalStateArgs args(static_state, data_source_instance_index);
-      return std::unique_ptr<InterceptorBase::ThreadLocalState>(
-          new typename InterceptorType::ThreadLocalState(args));
-    };
-    auto on_trace_packet = [](TracePacketCallbackArgs args) {
-      InterceptorType::OnTracePacket(InterceptorContext(std::move(args)));
-    };
-    RegisterImpl(descriptor, std::move(factory), std::move(tls_factory),
-                 std::move(on_trace_packet));
-  }
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_
diff --git a/include/perfetto/tracing/internal/checked_scope.h b/include/perfetto/tracing/internal/checked_scope.h
deleted file mode 100644
index 29dfcd8..0000000
--- a/include/perfetto/tracing/internal/checked_scope.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_CHECKED_SCOPE_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_CHECKED_SCOPE_H_
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace internal {
-
-#if PERFETTO_DCHECK_IS_ON()
-
-// Checker to ensure that despite multiple scopes being present, only the active
-// one is being accessed. Rules:
-// - Only an active scope can create inner scopes. When this happens, it stops
-// being active and the inner scope becomes active instead.
-// - Only an active scope can be destroyed. When this happens, its parent scope
-// becomes active.
-class PERFETTO_EXPORT CheckedScope {
- public:
-  explicit CheckedScope(CheckedScope* parent_scope);
-  ~CheckedScope();
-  CheckedScope(CheckedScope&&);
-  CheckedScope& operator=(CheckedScope&&);
-  CheckedScope(const CheckedScope&) = delete;
-  CheckedScope& operator=(const CheckedScope&) = delete;
-
-  void Reset();
-
-  CheckedScope* parent_scope() const { return parent_scope_; }
-  bool is_active() const { return is_active_; }
-
- private:
-  void set_is_active(bool is_active) { is_active_ = is_active; }
-
-  bool is_active_ = true;
-  CheckedScope* parent_scope_;
-
-  bool deleted_ = false;
-};
-
-#else
-
-// Dummy for cases when DCHECK is not enabled. Methods are marked constexpr to
-// ensure that the compiler can inline and optimise them away.
-class CheckedScope {
- public:
-  inline explicit CheckedScope(CheckedScope*) {}
-  inline ~CheckedScope() {}
-
-  inline void Reset() {}
-
-  inline CheckedScope* parent_scope() const { return nullptr; }
-  inline bool is_active() const { return true; }
-};
-
-#endif  // PERFETTO_DCHECK_IS_ON()
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_CHECKED_SCOPE_H_
diff --git a/include/perfetto/tracing/internal/compile_time_hash.h b/include/perfetto/tracing/internal/compile_time_hash.h
deleted file mode 100644
index da6b081..0000000
--- a/include/perfetto/tracing/internal/compile_time_hash.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_COMPILE_TIME_HASH_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_COMPILE_TIME_HASH_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace perfetto {
-namespace internal {
-
-// A helper class which computes a 64-bit hash of the input data at compile
-// time. 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 CompileTimeHash {
- public:
-  // Creates an empty hash object
-  constexpr inline CompileTimeHash() {}
-
-  // Hashes a byte array.
-  constexpr inline CompileTimeHash Update(const char* data, size_t size) const {
-    return CompileTimeHash(HashRecursively(kFnv1a64OffsetBasis, data, size));
-  }
-
-  constexpr inline uint64_t digest() const { return result_; }
-
- private:
-  constexpr inline CompileTimeHash(uint64_t result) : result_(result) {}
-
-  static constexpr inline uint64_t HashRecursively(uint64_t value,
-                                                   const char* data,
-                                                   size_t size) {
-    return !size ? value
-                 : HashRecursively(
-                       (value ^ static_cast<uint8_t>(*data)) * kFnv1a64Prime,
-                       data + 1, size - 1);
-  }
-
-  static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
-  static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
-
-  uint64_t result_ = kFnv1a64OffsetBasis;
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_COMPILE_TIME_HASH_H_
diff --git a/include/perfetto/tracing/internal/data_source_internal.h b/include/perfetto/tracing/internal/data_source_internal.h
index cb052c6..8e06ee4 100644
--- a/include/perfetto/tracing/internal/data_source_internal.h
+++ b/include/perfetto/tracing/internal/data_source_internal.h
@@ -34,7 +34,6 @@
 namespace perfetto {
 
 class DataSourceBase;
-class InterceptorBase;
 class TraceWriterBase;
 
 namespace internal {
@@ -70,11 +69,6 @@
   // source.
   TracingBackendId backend_id = 0;
 
-  // Each backend may connect to the tracing service multiple times if a
-  // disconnection occurs. This counter is used to uniquely identify each
-  // connection so that trace writers don't get reused across connections.
-  uint32_t backend_connection_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.
@@ -86,23 +80,13 @@
   // event).
   uint64_t config_hash = 0;
 
-  // If this data source is being intercepted (see Interceptor), this field
-  // contains the non-zero id of a registered interceptor which should receive
-  // trace packets for this session. Note: interceptor id 1 refers to the first
-  // element of TracingMuxerImpl::interceptors_ with successive numbers using
-  // the following slots.
-  uint32_t interceptor_id = 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.
-  // This lock is also used to protect access to a possible interceptor for this
-  // data source session.
   std::recursive_mutex lock;
   std::unique_ptr<DataSourceBase> data_source;
-  std::unique_ptr<InterceptorBase> interceptor;
 };
 
 // This is to allow lazy-initialization and avoid static initializers and
@@ -122,10 +106,6 @@
   std::atomic<uint32_t> valid_instances{};
   std::array<DataSourceStateStorage, kMaxDataSourceInstances> instances{};
 
-  // Incremented whenever incremental state should be reset for any instance of
-  // this data source.
-  std::atomic<uint32_t> incremental_state_generation{};
-
   // Can be used with a cached |valid_instances| bitmap.
   DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) {
     return cached_bitmap & (1 << n)
@@ -151,21 +131,13 @@
     trace_writer.reset();
     incremental_state.reset();
     backend_id = 0;
-    backend_connection_id = 0;
     buffer_id = 0;
-    data_source_instance_id = 0;
-    incremental_state_generation = 0;
-    is_intercepted = false;
   }
 
   std::unique_ptr<TraceWriterBase> trace_writer;
   IncrementalStatePointer incremental_state = {nullptr, [](void*) {}};
-  uint32_t incremental_state_generation;
   TracingBackendId backend_id;
-  uint32_t backend_connection_id;
   BufferId buffer_id;
-  uint64_t data_source_instance_id;
-  bool is_intercepted;
 };
 
 // Per-DataSource-type thread-local state.
diff --git a/include/perfetto/tracing/internal/interceptor_trace_writer.h b/include/perfetto/tracing/internal/interceptor_trace_writer.h
deleted file mode 100644
index 5dd28cd..0000000
--- a/include/perfetto/tracing/internal/interceptor_trace_writer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
-
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/interceptor.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/trace_writer_base.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace internal {
-
-// A heap-backed trace writer used to reroute trace packets to an interceptor.
-class InterceptorTraceWriter : public TraceWriterBase {
- public:
-  InterceptorTraceWriter(std::unique_ptr<InterceptorBase::ThreadLocalState> tls,
-                         InterceptorBase::TracePacketCallback packet_callback,
-                         DataSourceStaticState* static_state,
-                         uint32_t instance_index);
-  ~InterceptorTraceWriter() override;
-
-  // TraceWriterBase implementation.
-  protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket()
-      override;
-  void Flush(std::function<void()> callback = {}) override;
-  uint64_t written() const override;
-
- private:
-  std::unique_ptr<InterceptorBase::ThreadLocalState> tls_;
-  InterceptorBase::TracePacketCallback packet_callback_;
-
-  protozero::HeapBuffered<protos::pbzero::TracePacket> cur_packet_;
-  uint64_t bytes_written_ = 0;
-
-  // Static state of the data source we are intercepting.
-  DataSourceStaticState* const static_state_;
-
-  // Index of the data source tracing session which we are intercepting
-  // (0...kMaxDataSourceInstances - 1). Used to look up this interceptor's
-  // session state (i.e., the Interceptor class instance) in the
-  // DataSourceStaticState::instances array.
-  const uint32_t instance_index_;
-
-  const uint32_t sequence_id_;
-
-  static std::atomic<uint32_t> next_sequence_id_;
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_INTERCEPTOR_TRACE_WRITER_H_
diff --git a/include/perfetto/tracing/internal/tracing_backend_fake.h b/include/perfetto/tracing/internal/tracing_backend_fake.h
deleted file mode 100644
index 92c8ea1..0000000
--- a/include/perfetto/tracing/internal/tracing_backend_fake.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_BACKEND_FAKE_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_BACKEND_FAKE_H_
-
-#include "perfetto/base/export.h"
-#include "perfetto/tracing/tracing_backend.h"
-
-namespace perfetto {
-namespace internal {
-
-// A built-in implementation of TracingBackend that fails any attempt to create
-// a tracing session.
-class PERFETTO_EXPORT TracingBackendFake : public TracingBackend {
- public:
-  static TracingBackend* GetInstance();
-
-  // TracingBackend implementation.
-  std::unique_ptr<ProducerEndpoint> ConnectProducer(
-      const ConnectProducerArgs&) override;
-  std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
-      const ConnectConsumerArgs&) override;
-
- private:
-  TracingBackendFake();
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_BACKEND_FAKE_H_
diff --git a/include/perfetto/tracing/internal/tracing_muxer.h b/include/perfetto/tracing/internal/tracing_muxer.h
index a0b464c..4363ca5 100644
--- a/include/perfetto/tracing/internal/tracing_muxer.h
+++ b/include/perfetto/tracing/internal/tracing_muxer.h
@@ -22,7 +22,6 @@
 
 #include "perfetto/base/export.h"
 #include "perfetto/tracing/core/forward_decls.h"
-#include "perfetto/tracing/interceptor.h"
 #include "perfetto/tracing/internal/basic_types.h"
 #include "perfetto/tracing/internal/tracing_tls.h"
 #include "perfetto/tracing/platform.h"
@@ -69,8 +68,6 @@
   // 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(
-      DataSourceStaticState*,
-      uint32_t data_source_instance_index,
       DataSourceState*,
       BufferExhaustedPolicy buffer_exhausted_policy) = 0;
 
@@ -78,12 +75,6 @@
 
   uint32_t generation(std::memory_order ord) { return generation_.load(ord); }
 
-  using InterceptorFactory = std::function<std::unique_ptr<InterceptorBase>()>;
-  virtual void RegisterInterceptor(const InterceptorDescriptor&,
-                                   InterceptorFactory,
-                                   InterceptorBase::TLSFactory,
-                                   InterceptorBase::TracePacketCallback) = 0;
-
  protected:
   explicit TracingMuxer(Platform* platform) : platform_(platform) {}
 
diff --git a/include/perfetto/tracing/internal/tracing_tls.h b/include/perfetto/tracing/internal/tracing_tls.h
index 68515a4..67f0637 100644
--- a/include/perfetto/tracing/internal/tracing_tls.h
+++ b/include/perfetto/tracing/internal/tracing_tls.h
@@ -74,11 +74,6 @@
   // thread-local TraceWriter(s) is issued.
   uint32_t generation = 0;
 
-  // This flag is true while this thread is inside a trace point for any data
-  // source or in other delicate parts of the tracing machinery during which we
-  // should not try to trace. Used to prevent unexpected re-entrancy.
-  bool is_in_trace_point = false;
-
   // By default all data source instances have independent thread-local state
   // (see above).
   std::array<DataSourceThreadLocalState, kMaxDataSources> data_sources_tls{};
@@ -89,17 +84,6 @@
   DataSourceThreadLocalState track_event_tls{};
 };
 
-struct ScopedReentrancyAnnotator {
-  ScopedReentrancyAnnotator(TracingTLS& root_tls) : root_tls_(root_tls) {
-    PERFETTO_DCHECK(!root_tls_.is_in_trace_point);
-    root_tls_.is_in_trace_point = true;
-  }
-  ~ScopedReentrancyAnnotator() { root_tls_.is_in_trace_point = false; }
-
- private:
-  TracingTLS& root_tls_;
-};
-
 }  // namespace internal
 }  // namespace perfetto
 
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 12a5a85..bbae795 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -18,13 +18,11 @@
 #define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
 
 #include "perfetto/base/compiler.h"
-#include "perfetto/base/template_util.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/data_source.h"
 #include "perfetto/tracing/event_context.h"
 #include "perfetto/tracing/internal/track_event_internal.h"
-#include "perfetto/tracing/internal/write_track_event_args.h"
 #include "perfetto/tracing/track.h"
 #include "perfetto/tracing/track_event_category_registry.h"
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
@@ -34,101 +32,36 @@
 #include <type_traits>
 
 namespace perfetto {
-
-struct TraceTimestamp {
-  protos::pbzero::BuiltinClock clock_id;
-  uint64_t nanoseconds;
-};
-
-// This template provides a way to convert an abstract timestamp into the trace
-// clock timebase in nanoseconds. By specialising this template and defining
-// static ConvertTimestampToTraceTimeNs function in it the user can register
-// additional timestamp types. The return value should specify the clock used by
-// the timestamp as well as its value in nanoseconds.
-//
-// The users should see the specialisation for uint64_t below as an example.
-// Note that the specialisation should be defined in perfetto namespace.
-template <typename T>
-struct TraceTimestampTraits;
-
-// A pass-through implementation for raw uint64_t nanosecond timestamps.
-template <>
-struct TraceTimestampTraits<uint64_t> {
-  static inline TraceTimestamp ConvertTimestampToTraceTimeNs(
-      const uint64_t& timestamp) {
-    return {internal::TrackEventInternal::GetClockId(), timestamp};
-  }
-};
-
 namespace internal {
 namespace {
 
-// Checks if |T| is a valid track.
+// A template helper for determining whether a type can be used as a track event
+// lambda, i.e., it has the signature "void(EventContext)". This is achieved by
+// checking that we can pass an EventContext value (the inner declval) into a T
+// instance (the outer declval). If this is a valid expression, the result
+// evaluates to sizeof(0), i.e., true.
+// TODO(skyostil): Replace this with std::is_convertible<std::function<...>>
+// once we have C++14.
 template <typename T>
-static constexpr bool IsValidTrack() {
-  return std::is_convertible<T, Track>::value;
-}
-
-// Checks if |T| is a valid non-counter track.
-template <typename T>
-static constexpr bool IsValidNormalTrack() {
-  return std::is_convertible<T, Track>::value &&
-         !std::is_convertible<T, CounterTrack>::value;
-}
-
-// Because the user can use arbitrary timestamp types, we can't compare against
-// any known base type here. Instead, we check that a track or a trace lambda
-// isn't being interpreted as a timestamp.
-template <typename T,
-          typename CanBeConvertedToNsCheck = decltype(
-              ::perfetto::TraceTimestampTraits<typename base::remove_cvref_t<
-                  T>>::ConvertTimestampToTraceTimeNs(std::declval<T>())),
-          typename NotTrackCheck =
-              typename std::enable_if<!IsValidNormalTrack<T>()>::type,
-          typename NotLambdaCheck =
-              typename std::enable_if<!IsValidTraceLambda<T>()>::type>
-static constexpr bool IsValidTimestamp() {
+static constexpr bool IsValidTraceLambdaImpl(
+    typename std::enable_if<static_cast<bool>(
+        sizeof(std::declval<T>()(std::declval<EventContext>()), 0))>::type* =
+        nullptr) {
   return true;
 }
 
+template <typename T>
+static constexpr bool IsValidTraceLambdaImpl(...) {
+  return false;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambda() {
+  return IsValidTraceLambdaImpl<T>(nullptr);
+}
+
 }  // namespace
 
-// Traits for dynamic categories.
-template <typename CategoryType>
-struct CategoryTraits {
-  static constexpr bool kIsDynamic = true;
-  static constexpr const Category* GetStaticCategory(
-      const TrackEventCategoryRegistry*,
-      const CategoryType&) {
-    return nullptr;
-  }
-  static size_t GetStaticIndex(const CategoryType&) {
-    PERFETTO_DCHECK(false);  // Not reached.
-    return TrackEventCategoryRegistry::kDynamicCategoryIndex;
-  }
-  static DynamicCategory GetDynamicCategory(const CategoryType& category) {
-    return DynamicCategory{category};
-  }
-};
-
-// Traits for static categories.
-template <>
-struct CategoryTraits<size_t> {
-  static constexpr bool kIsDynamic = false;
-  static const Category* GetStaticCategory(
-      const TrackEventCategoryRegistry* registry,
-      size_t category_index) {
-    return registry->GetCategory(category_index);
-  }
-  static constexpr size_t GetStaticIndex(size_t category_index) {
-    return category_index;
-  }
-  static DynamicCategory GetDynamicCategory(size_t) {
-    PERFETTO_DCHECK(false);  // Not reached.
-    return DynamicCategory();
-  }
-};
-
 struct TrackEventDataSourceTraits : public perfetto::DefaultDataSourceTraits {
   using IncrementalStateType = TrackEventIncrementalState;
 
@@ -140,6 +73,16 @@
   }
 };
 
+// A helper that ensures movable debug annotations are passed by value to
+// minimize binary size at the call site, while allowing non-movable and
+// non-copiable arguments to be passed by reference.
+// TODO(skyostil): Remove this with C++17.
+template <typename T>
+struct DebugAnnotationArg {
+  using type = typename std::
+      conditional<std::is_move_constructible<T>::value, T, T&&>::type;
+};
+
 // A generic track event data source which is instantiated once per track event
 // category namespace.
 template <typename DataSourceType, const TrackEventCategoryRegistry* Registry>
@@ -148,49 +91,29 @@
   using Base = DataSource<DataSourceType, TrackEventDataSourceTraits>;
 
  public:
-  // Add or remove a session observer for this track event data source. The
-  // observer will be notified about started and stopped tracing sessions.
-  // Returns |true| if the observer was succesfully added (i.e., the maximum
-  // number of observers wasn't exceeded).
-  static bool AddSessionObserver(TrackEventSessionObserver* observer) {
-    return TrackEventInternal::AddSessionObserver(observer);
-  }
-
-  static void RemoveSessionObserver(TrackEventSessionObserver* observer) {
-    TrackEventInternal::RemoveSessionObserver(observer);
-  }
-
   // DataSource implementation.
   void OnSetup(const DataSourceBase::SetupArgs& args) override {
     auto config_raw = args.config->track_event_config_raw();
     bool ok = config_.ParseFromArray(config_raw.data(), config_raw.size());
     PERFETTO_DCHECK(ok);
-    TrackEventInternal::EnableTracing(*Registry, config_, args);
+    TrackEventInternal::EnableTracing(*Registry, config_,
+                                      args.internal_instance_index);
   }
 
-  void OnStart(const DataSourceBase::StartArgs& args) override {
-    TrackEventInternal::OnStart(args);
-  }
+  void OnStart(const DataSourceBase::StartArgs&) override {}
 
   void OnStop(const DataSourceBase::StopArgs& args) override {
-    TrackEventInternal::DisableTracing(*Registry, args);
+    TrackEventInternal::DisableTracing(*Registry, args.internal_instance_index);
   }
 
   static void Flush() {
     Base::template Trace([](typename Base::TraceContext ctx) { ctx.Flush(); });
   }
 
-  // Determine if *any* tracing category is enabled.
-  static bool IsEnabled() {
-    bool enabled = false;
-    Base::template CallIfEnabled(
-        [&](uint32_t /*instances*/) { enabled = true; });
-    return enabled;
-  }
-
   // Determine if tracing for the given static category is enabled.
-  static bool IsCategoryEnabled(size_t category_index) {
-    return Registry->GetCategoryState(category_index)
+  template <size_t CategoryIndex>
+  static bool IsCategoryEnabled() {
+    return Registry->GetCategoryState(CategoryIndex)
         ->load(std::memory_order_relaxed);
   }
 
@@ -208,134 +131,285 @@
   // 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 <typename Callback>
-  static void CallIfCategoryEnabled(size_t category_index,
-                                    Callback callback) PERFETTO_ALWAYS_INLINE {
-    Base::template CallIfEnabled<CategoryTracePointTraits>(
-        [&callback](uint32_t instances) { callback(instances); },
-        {category_index});
+  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 onto this thread's default track. Outlined to avoid
   // bloating code (mostly stack depth) at the actual trace point.
   //
-  // The following combination of parameters is supported (in the given order):
-  // - Zero or one track,
-  // - Zero or one custom timestamp,
-  // - Arbitrary number of debug annotations.
-  // - Zero or one lambda.
+  // To minimize call overhead at each trace point, we provide the following
+  // trace point argument variants:
+  //
+  // - None
+  // - Lambda
+  // - Lambda + timestamp
+  // - One debug annotation
+  // - Two debug annotations
+  // - Track
+  // - Track + Lambda
+  // - Track + timestamp
+  // - Track + Lambda + timestamp
+  // - Track + one debug annotation
+  // - Track + two debug annotations
 
-  // Trace point which does not take a track or timestamp.
-  template <typename CategoryType, typename... Arguments>
+  // Trace point which takes no arguments.
+  template <size_t CategoryIndex, typename CategoryType>
   static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
+                               const CategoryType& dynamic_category,
                                const char* event_name,
-                               perfetto::protos::pbzero::TrackEvent::Type type,
-                               Arguments&&... args) PERFETTO_NO_INLINE {
-    TraceForCategoryImpl(instances, category, event_name, type,
-                         TrackEventInternal::kDefaultTrack,
-                         TrackEventInternal::GetTimeNs(),
-                         std::forward<Arguments>(args)...);
+                               perfetto::protos::pbzero::TrackEvent::Type type)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type);
   }
 
-  // Trace point which takes a track, but not timestamp.
-  // NOTE: Here track should be captured using universal reference (TrackType&&)
-  // instead of const TrackType& to ensure that the proper overload is selected
-  // (otherwise the compiler will fail to disambiguate between adding const& and
-  // parsing track as a part of Arguments...).
-  template <typename TrackType,
+  // Trace point which takes a lambda function argument.
+  template <size_t CategoryIndex,
             typename CategoryType,
-            typename... Arguments,
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               ArgumentFunction arg_function)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(
+        instances, dynamic_category, event_name, type, Track(),
+        TrackEventInternal::GetTimeNs(), std::move(arg_function));
+  }
+
+  // Trace point which takes a lambda function argument and an overridden
+  // timestamp. |timestamp| must be in nanoseconds in the trace clock timebase.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               uint64_t timestamp,
+                               ArgumentFunction arg_function)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type, Track(), timestamp,
+                                        std::move(arg_function));
+  }
+
+  // This variant of the inner trace point takes a Track argument which can be
+  // used to emit events on a non-default track.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
             typename TrackTypeCheck = typename std::enable_if<
                 std::is_convertible<TrackType, Track>::value>::type>
   static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
+                               const CategoryType& dynamic_category,
                                const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
-                               TrackType&& track,
-                               Arguments&&... args) PERFETTO_NO_INLINE {
-    TraceForCategoryImpl(
-        instances, category, event_name, type, std::forward<TrackType>(track),
-        TrackEventInternal::GetTimeNs(), std::forward<Arguments>(args)...);
+                               const TrackType& track) PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type, track);
   }
 
-  // Trace point which takes a timestamp, but not track.
-  template <typename CategoryType,
-            typename TimestampType = uint64_t,
-            typename... Arguments,
-            typename TimestampTypeCheck = typename std::enable_if<
-                IsValidTimestamp<TimestampType>()>::type>
-  static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
-                               const char* event_name,
-                               perfetto::protos::pbzero::TrackEvent::Type type,
-                               TimestampType&& timestamp,
-                               Arguments&&... args) PERFETTO_NO_INLINE {
-    TraceForCategoryImpl(instances, category, event_name, type,
-                         TrackEventInternal::kDefaultTrack,
-                         std::forward<TimestampType>(timestamp),
-                         std::forward<Arguments>(args)...);
-  }
-
-  // Trace point which takes a timestamp and a track.
-  template <typename TrackType,
+  // Trace point with a track and a lambda function.
+  template <size_t CategoryIndex,
+            typename TrackType,
             typename CategoryType,
-            typename TimestampType = uint64_t,
-            typename... Arguments,
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type,
             typename TrackTypeCheck = typename std::enable_if<
-                std::is_convertible<TrackType, Track>::value>::type,
-            typename TimestampTypeCheck = typename std::enable_if<
-                IsValidTimestamp<TimestampType>()>::type>
+                std::is_convertible<TrackType, Track>::value>::type>
   static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
+                               const CategoryType& dynamic_category,
                                const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
-                               TrackType&& track,
-                               TimestampType&& timestamp,
-                               Arguments&&... args) PERFETTO_NO_INLINE {
-    TraceForCategoryImpl(instances, category, event_name, type,
-                         std::forward<TrackType>(track),
-                         std::forward<TimestampType>(timestamp),
-                         std::forward<Arguments>(args)...);
+                               const TrackType& track,
+                               ArgumentFunction arg_function)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(
+        instances, dynamic_category, event_name, type, track,
+        TrackEventInternal::GetTimeNs(), std::move(arg_function));
   }
 
-  // Trace point with with a counter sample.
-  template <typename CategoryType, typename ValueType>
+  // Trace point with a track and overridden timestamp.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
+            typename TrackTypeCheck = typename std::enable_if<
+                std::is_convertible<TrackType, Track>::value>::type>
   static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
-                               const char*,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
-                               CounterTrack track,
-                               ValueType value) PERFETTO_ALWAYS_INLINE {
-    PERFETTO_DCHECK(type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER);
-    TraceForCategory(instances, category, /*name=*/nullptr, type, track,
-                     TrackEventInternal::GetTimeNs(), value);
+                               const TrackType& track,
+                               uint64_t timestamp) PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type, track, timestamp);
   }
 
-  // Trace point with with a timestamp and a counter sample.
-  template <typename CategoryType,
-            typename TimestampType = uint64_t,
-            typename TimestampTypeCheck = typename std::enable_if<
-                IsValidTimestamp<TimestampType>()>::type,
-            typename ValueType>
+  // Trace point with a track, a lambda function and an overridden timestamp.
+  // |timestamp| must be in nanoseconds in the trace clock timebase.
+  template <size_t CategoryIndex,
+            typename TrackType,
+            typename CategoryType,
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type>
   static void TraceForCategory(uint32_t instances,
-                               const CategoryType& category,
-                               const char*,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
-                               CounterTrack track,
-                               TimestampType timestamp,
-                               ValueType value) PERFETTO_ALWAYS_INLINE {
-    PERFETTO_DCHECK(type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER);
-    TraceForCategoryImpl(
-        instances, category, /*name=*/nullptr, type, track, timestamp,
-        [&](EventContext event_ctx) {
-          if (std::is_integral<ValueType>::value) {
-            event_ctx.event()->set_counter_value(static_cast<int64_t>(value));
-          } else {
-            event_ctx.event()->set_double_counter_value(
-                static_cast<double>(value));
-          }
+                               const TrackType& track,
+                               uint64_t timestamp,
+                               ArgumentFunction arg_function)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type, track, timestamp,
+                                        std::move(arg_function));
+  }
+
+  // Trace point with one debug annotation.
+  //
+  // This type of trace point is implemented with an inner helper function which
+  // ensures |arg_value| is only passed by reference when required (i.e., with a
+  // custom DebugAnnotation type). This avoids the binary and runtime overhead
+  // of unnecessarily passing all types debug annotations by reference.
+  //
+  // Note that for this to work well, the _outer_ function (this function) has
+  // to be inlined at the call site while the _inner_ function
+  // (TraceForCategoryWithDebugAnnotations) is still outlined to minimize
+  // overall binary size.
+  template <size_t CategoryIndex, typename CategoryType, typename ArgType>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               const char* arg_name,
+                               ArgType&& arg_value) PERFETTO_ALWAYS_INLINE {
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, CategoryType, Track,
+                                         ArgType>(
+        instances, dynamic_category, event_name, type, Track(), arg_name,
+        std::forward<ArgType>(arg_value));
+  }
+
+  // A one argument trace point which takes an explicit track.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
+            typename ArgType>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               const TrackType& track,
+                               const char* arg_name,
+                               ArgType&& arg_value) PERFETTO_ALWAYS_INLINE {
+    PERFETTO_DCHECK(track);
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, CategoryType, TrackType,
+                                         ArgType>(
+        instances, dynamic_category, event_name, type, track, arg_name,
+        std::forward<ArgType>(arg_value));
+  }
+
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
+            typename ArgType>
+  static void TraceForCategoryWithDebugAnnotations(
+      uint32_t instances,
+      const CategoryType& dynamic_category,
+      const char* event_name,
+      perfetto::protos::pbzero::TrackEvent::Type type,
+      const TrackType& track,
+      const char* arg_name,
+      typename internal::DebugAnnotationArg<ArgType>::type arg_value)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(
+        instances, dynamic_category, event_name, type, track,
+        TrackEventInternal::GetTimeNs(), [&](EventContext event_ctx) {
+          TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
+                                                 arg_value);
+        });
+  }
+
+  // Trace point with two debug annotations. Note that we only support up to two
+  // direct debug annotations. For more complicated arguments, you should
+  // define your own argument type in track_event.proto and use a lambda to fill
+  // it in your trace point.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename ArgType,
+            typename ArgType2>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               const char* arg_name,
+                               ArgType&& arg_value,
+                               const char* arg_name2,
+                               ArgType2&& arg_value2) PERFETTO_ALWAYS_INLINE {
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, CategoryType, Track,
+                                         ArgType, ArgType2>(
+        instances, dynamic_category, event_name, type, Track(), arg_name,
+        std::forward<ArgType>(arg_value), arg_name2,
+        std::forward<ArgType2>(arg_value2));
+  }
+
+  // A two argument trace point which takes an explicit track.
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
+            typename ArgType,
+            typename ArgType2>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               const TrackType& track,
+                               const char* arg_name,
+                               ArgType&& arg_value,
+                               const char* arg_name2,
+                               ArgType2&& arg_value2) PERFETTO_ALWAYS_INLINE {
+    PERFETTO_DCHECK(track);
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, CategoryType, TrackType,
+                                         ArgType, ArgType2>(
+        instances, dynamic_category, event_name, type, track, arg_name,
+        std::forward<ArgType>(arg_value), arg_name2,
+        std::forward<ArgType2>(arg_value2));
+  }
+
+  template <size_t CategoryIndex,
+            typename CategoryType,
+            typename TrackType,
+            typename ArgType,
+            typename ArgType2>
+  static void TraceForCategoryWithDebugAnnotations(
+      uint32_t instances,
+      const CategoryType& dynamic_category,
+      const char* event_name,
+      perfetto::protos::pbzero::TrackEvent::Type type,
+      TrackType track,
+      const char* arg_name,
+      typename internal::DebugAnnotationArg<ArgType>::type arg_value,
+      const char* arg_name2,
+      typename internal::DebugAnnotationArg<ArgType2>::type arg_value2)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(
+        instances, dynamic_category, event_name, type, track,
+        TrackEventInternal::GetTimeNs(), [&](EventContext event_ctx) {
+          TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
+                                                 arg_value);
+          TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name2,
+                                                 arg_value2);
         });
   }
 
@@ -398,108 +472,84 @@
  private:
   // Each category has its own enabled/disabled state, stored in the category
   // registry.
+  template <size_t CategoryIndex>
   struct CategoryTracePointTraits {
-    // Each trace point with a static category has an associated category index.
-    struct TracePointData {
-      size_t category_index;
-    };
-    // Called to get the enabled state bitmap of a given category.
-    // |data| is the trace point data structure given to
-    // DataSource::TraceWithInstances.
-    static constexpr std::atomic<uint8_t>* GetActiveInstances(
-        TracePointData data) {
-      return Registry->GetCategoryState(data.category_index);
+    static constexpr std::atomic<uint8_t>* GetActiveInstances() {
+      static_assert(
+          CategoryIndex != TrackEventCategoryRegistry::kInvalidCategoryIndex,
+          "Invalid category index");
+      return Registry->GetCategoryState(CategoryIndex);
     }
   };
 
-  template <typename CategoryType,
+  // TODO(skyostil): Make |CategoryIndex| a regular parameter to reuse trace
+  // point code across different categories.
+  template <size_t CategoryIndex,
+            typename CategoryType,
             typename TrackType = Track,
-            typename TimestampType = uint64_t,
-            typename TimestampTypeCheck = typename std::enable_if<
-                IsValidTimestamp<TimestampType>()>::type,
-            typename TrackTypeCheck =
-                typename std::enable_if<IsValidTrack<TrackType>()>::type,
-            typename... Arguments>
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type,
+            typename TrackTypeCheck = typename std::enable_if<
+                std::is_convertible<TrackType, Track>::value>::type>
   static void TraceForCategoryImpl(
       uint32_t instances,
-      const CategoryType& category,
+      const CategoryType& dynamic_category,
       const char* event_name,
       perfetto::protos::pbzero::TrackEvent::Type type,
-      const TrackType& track,
-      const TimestampType& timestamp,
-      Arguments&&... args) PERFETTO_ALWAYS_INLINE {
-    using CatTraits = CategoryTraits<CategoryType>;
-    const Category* static_category =
-        CatTraits::GetStaticCategory(Registry, category);
-    TraceWithInstances(
-        instances, category, [&](typename Base::TraceContext ctx) {
+      const TrackType& track = Track(),
+      uint64_t timestamp = TrackEventInternal::GetTimeNs(),
+      ArgumentFunction arg_function = [](EventContext) {
+      }) PERFETTO_ALWAYS_INLINE {
+    TraceWithInstances<CategoryIndex>(
+        instances, [&](typename Base::TraceContext ctx) {
           // If this category is dynamic, first check whether it's enabled.
-          if (CatTraits::kIsDynamic &&
-              !IsDynamicCategoryEnabled(
-                  &ctx, CatTraits::GetDynamicCategory(category))) {
+          constexpr bool kIsDynamic =
+              CategoryIndex ==
+              TrackEventCategoryRegistry::kDynamicCategoryIndex;
+          if (kIsDynamic && !IsDynamicCategoryEnabled(
+                                &ctx, DynamicCategory{dynamic_category})) {
             return;
           }
 
-          // TODO(skyostil): Support additional clock ids.
-          TraceTimestamp trace_timestamp = ::perfetto::TraceTimestampTraits<
-              TimestampType>::ConvertTimestampToTraceTimeNs(timestamp);
-          PERFETTO_DCHECK(trace_timestamp.clock_id ==
-                          TrackEventInternal::GetClockId());
-
-          // Make sure incremental state is valid.
-          TraceWriterBase* trace_writer = ctx.tls_inst_->trace_writer.get();
-          TrackEventIncrementalState* incr_state = ctx.GetIncrementalState();
-          if (incr_state->was_cleared) {
-            incr_state->was_cleared = false;
-            TrackEventInternal::ResetIncrementalState(
-                trace_writer, trace_timestamp.nanoseconds);
-          }
-
-          // Write the track descriptor before any event on the track.
-          if (track) {
-            TrackEventInternal::WriteTrackDescriptorIfNeeded(
-                track, trace_writer, incr_state);
-          }
-
-          // Write the event itself.
           {
+            // TODO(skyostil): Intern categories at compile time.
+            const Category* static_category =
+                kIsDynamic ? nullptr : Registry->GetCategory(CategoryIndex);
             auto event_ctx = TrackEventInternal::WriteEvent(
-                trace_writer, incr_state, static_category, event_name, type,
-                trace_timestamp.nanoseconds);
-            // Write dynamic categories (except for events that don't require
-            // categories). For counter events, the counter name (and optional
-            // category) is stored as part of the track descriptor instead being
-            // recorded with individual events.
-            if (CatTraits::kIsDynamic &&
-                type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
-                type != protos::pbzero::TrackEvent::TYPE_COUNTER) {
-              DynamicCategory dynamic_category =
-                  CatTraits::GetDynamicCategory(category);
-              Category cat = Category::FromDynamicCategory(dynamic_category);
-              cat.ForEachGroupMember(
+                ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+                static_category, event_name, type, timestamp);
+            if (kIsDynamic) {
+              Category category{
+                  Category::FromDynamicCategory(dynamic_category)};
+              category.ForEachGroupMember(
                   [&](const char* member_name, size_t name_size) {
                     event_ctx.event()->add_categories(member_name, name_size);
                     return true;
                   });
             }
-            if (&track != &TrackEventInternal::kDefaultTrack)
+            if (track)
               event_ctx.event()->set_track_uuid(track.uuid);
-            WriteTrackEventArgs(std::move(event_ctx),
-                                std::forward<Arguments>(args)...);
+            arg_function(std::move(event_ctx));
           }  // event_ctx
+
+          if (track) {
+            TrackEventInternal::WriteTrackDescriptorIfNeeded(
+                track, ctx.tls_inst_->trace_writer.get(),
+                ctx.GetIncrementalState());
+          }
         });
   }
 
-  template <typename CategoryType, typename Lambda>
+  template <size_t CategoryIndex, typename Lambda>
   static void TraceWithInstances(uint32_t instances,
-                                 const CategoryType& category,
                                  Lambda lambda) PERFETTO_ALWAYS_INLINE {
-    using CatTraits = CategoryTraits<CategoryType>;
-    if (CatTraits::kIsDynamic) {
+    if (CategoryIndex == TrackEventCategoryRegistry::kDynamicCategoryIndex) {
       Base::template TraceWithInstances(instances, std::move(lambda));
     } else {
-      Base::template TraceWithInstances<CategoryTracePointTraits>(
-          instances, std::move(lambda), {CatTraits::GetStaticIndex(category)});
+      Base::template TraceWithInstances<
+          CategoryTracePointTraits<CategoryIndex>>(instances,
+                                                   std::move(lambda));
     }
   }
 
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index d293039..6de74ef 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -20,10 +20,8 @@
 #include "perfetto/base/flat_set.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/tracing/core/forward_decls.h"
-#include "perfetto/tracing/data_source.h"
 #include "perfetto/tracing/debug_annotation.h"
 #include "perfetto/tracing/trace_writer_base.h"
-#include "perfetto/tracing/traced_value.h"
 #include "perfetto/tracing/track.h"
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
@@ -33,7 +31,6 @@
 
 namespace perfetto {
 class EventContext;
-class TrackEventSessionObserver;
 struct Category;
 namespace protos {
 namespace gen {
@@ -44,34 +41,15 @@
 }  // namespace pbzero
 }  // namespace protos
 
-// A callback interface for observing track event tracing sessions starting and
-// stopping. See TrackEvent::{Add,Remove}SessionObserver. Note that all methods
-// will be called on an internal Perfetto thread.
-class PERFETTO_EXPORT TrackEventSessionObserver {
- public:
-  virtual ~TrackEventSessionObserver();
-  // Called when a track event tracing session is configured. Note tracing isn't
-  // active yet, so track events emitted here won't be recorded. See
-  // DataSourceBase::OnSetup.
-  virtual void OnSetup(const DataSourceBase::SetupArgs&);
-  // Called when a track event tracing session is started. It is possible to
-  // emit track events from this callback.
-  virtual void OnStart(const DataSourceBase::StartArgs&);
-  // Called when a track event tracing session is stopped. It is still possible
-  // to emit track events from this callback.
-  virtual void OnStop(const DataSourceBase::StopArgs&);
-};
-
 namespace internal {
 class TrackEventCategoryRegistry;
 
-class PERFETTO_EXPORT BaseTrackEventInternedDataIndex {
+class BaseTrackEventInternedDataIndex {
  public:
   virtual ~BaseTrackEventInternedDataIndex();
 
 #if PERFETTO_DCHECK_IS_ON()
   const char* type_id_ = nullptr;
-  const void* add_function_ptr_ = nullptr;
 #endif  // PERFETTO_DCHECK_IS_ON()
 };
 
@@ -120,15 +98,11 @@
       const TrackEventCategoryRegistry&,
       bool (*register_data_source)(const DataSourceDescriptor&));
 
-  static bool AddSessionObserver(TrackEventSessionObserver*);
-  static void RemoveSessionObserver(TrackEventSessionObserver*);
-
   static void EnableTracing(const TrackEventCategoryRegistry& registry,
                             const protos::gen::TrackEventConfig& config,
-                            const DataSourceBase::SetupArgs&);
-  static void OnStart(const DataSourceBase::StartArgs&);
+                            uint32_t instance_index);
   static void DisableTracing(const TrackEventCategoryRegistry& registry,
-                             const DataSourceBase::StopArgs&);
+                             uint32_t instance_index);
   static bool IsCategoryEnabled(const TrackEventCategoryRegistry& registry,
                                 const protos::gen::TrackEventConfig& config,
                                 const Category& category);
@@ -141,15 +115,12 @@
       perfetto::protos::pbzero::TrackEvent::Type,
       uint64_t timestamp = GetTimeNs());
 
-  static void ResetIncrementalState(TraceWriterBase*, uint64_t timestamp);
-
   template <typename T>
   static void AddDebugAnnotation(perfetto::EventContext* event_ctx,
                                  const char* name,
                                  T&& value) {
     auto annotation = AddDebugAnnotation(event_ctx, name);
-    WriteIntoTracedValue(internal::CreateTracedValueFromProto(annotation),
-                         std::forward<T>(value));
+    WriteDebugAnnotation(annotation, value);
   }
 
   // If the given track hasn't been seen by the trace writer yet, write a
@@ -179,7 +150,7 @@
 
   // Get the clock used by GetTimeNs().
   static constexpr protos::pbzero::BuiltinClock GetClockId() {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
     return protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
 #else
@@ -187,12 +158,8 @@
 #endif
   }
 
-  static int GetSessionCount();
-
-  // Represents the default track for the calling thread.
-  static const Track kDefaultTrack;
-
  private:
+  static void ResetIncrementalState(TraceWriterBase*, uint64_t timestamp);
   static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
       TraceWriterBase*,
       uint64_t timestamp,
@@ -201,8 +168,6 @@
   static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
       perfetto::EventContext*,
       const char* name);
-
-  static std::atomic<int> session_count_;
 };
 
 }  // namespace internal
diff --git a/include/perfetto/tracing/internal/track_event_interned_fields.h b/include/perfetto/tracing/internal/track_event_interned_fields.h
deleted file mode 100644
index 81bfd98..0000000
--- a/include/perfetto/tracing/internal/track_event_interned_fields.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/export.h"
-#include "perfetto/tracing/track_event_interned_data_index.h"
-
-#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
-
-namespace perfetto {
-namespace internal {
-
-// These helpers are exposed here to allow Chromium-without-client library
-// to share the interning buffers with Perfetto internals (e.g.
-// perfetto::TracedValue implementation).
-
-struct PERFETTO_EXPORT InternedEventCategory
-    : public TrackEventInternedDataIndex<
-          InternedEventCategory,
-          perfetto::protos::pbzero::InternedData::kEventCategoriesFieldNumber,
-          const char*,
-          SmallInternedDataTraits> {
-  ~InternedEventCategory() override;
-
-  static void Add(protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value,
-                  size_t length);
-};
-
-struct PERFETTO_EXPORT InternedEventName
-    : public TrackEventInternedDataIndex<
-          InternedEventName,
-          perfetto::protos::pbzero::InternedData::kEventNamesFieldNumber,
-          const char*,
-          SmallInternedDataTraits> {
-  ~InternedEventName() override;
-
-  static void Add(protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value);
-};
-
-struct PERFETTO_EXPORT InternedDebugAnnotationName
-    : public TrackEventInternedDataIndex<
-          InternedDebugAnnotationName,
-          perfetto::protos::pbzero::InternedData::
-              kDebugAnnotationNamesFieldNumber,
-          const char*,
-          SmallInternedDataTraits> {
-  ~InternedDebugAnnotationName() override;
-
-  static void Add(protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value);
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNED_FIELDS_H_
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index 0c7ffb7..b5b6303 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -26,9 +26,7 @@
 #include "perfetto/tracing/track_event_category_registry.h"
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
 
 // Defines data structures for backing a category registry.
 //
@@ -46,8 +44,7 @@
   constexpr size_t kCategoryCount =                                           \
       sizeof(kCategories) / sizeof(kCategories[0]);                           \
   /* The per-instance enable/disable state per category */                    \
-  PERFETTO_COMPONENT_EXPORT extern std::atomic<uint8_t>                       \
-      g_category_state_storage[kCategoryCount];                               \
+  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: */                                \
   /**/                                                                        \
@@ -71,15 +68,14 @@
   }  // namespace internal
 
 // In a .cc file, declares storage for each category's runtime state.
-#define PERFETTO_INTERNAL_CATEGORY_STORAGE()             \
-  namespace internal {                                   \
-  PERFETTO_COMPONENT_EXPORT std::atomic<uint8_t>         \
-      g_category_state_storage[kCategoryCount];          \
-  PERFETTO_COMPONENT_EXPORT const ::perfetto::internal:: \
-      TrackEventCategoryRegistry kCategoryRegistry(      \
-          kCategoryCount,                                \
-          &kCategories[0],                               \
-          &g_category_state_storage[0]);                 \
+#define PERFETTO_INTERNAL_CATEGORY_STORAGE()                     \
+  namespace internal {                                           \
+  std::atomic<uint8_t> g_category_state_storage[kCategoryCount]; \
+  PERFETTO_COMPONENT_EXPORT 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.
@@ -104,31 +100,26 @@
 
 // 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, ...)                           \
-  do {                                                                         \
-    namespace tns = ::PERFETTO_TRACK_EVENT_NAMESPACE;                          \
-    /* Compute the category index outside the lambda to work around a */       \
-    /* GCC 7 bug */                                                            \
-    static constexpr auto PERFETTO_UID(                                        \
-        kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_) =               \
-        PERFETTO_GET_CATEGORY_INDEX(category);                                 \
-    if (tns::internal::IsDynamicCategory(category)) {                          \
-      tns::TrackEvent::CallIfEnabled(                                          \
-          [&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {         \
-            tns::TrackEvent::TraceForCategory(instances, category,             \
-                                              ##__VA_ARGS__);                  \
-          });                                                                  \
-    } else {                                                                   \
-      tns::TrackEvent::CallIfCategoryEnabled(                                  \
-          PERFETTO_UID(kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_), \
-          [&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {         \
-            tns::TrackEvent::TraceForCategory(                                 \
-                instances,                                                     \
-                PERFETTO_UID(                                                  \
-                    kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_),    \
-                ##__VA_ARGS__);                                                \
-          });                                                                  \
-    }                                                                          \
+#define PERFETTO_INTERNAL_TRACK_EVENT(category, ...)                      \
+  do {                                                                    \
+    namespace tns = ::PERFETTO_TRACK_EVENT_NAMESPACE;                     \
+    /* Compute the category index outside the lambda to work around a */  \
+    /* GCC 7 bug */                                                       \
+    constexpr auto PERFETTO_UID(kCatIndex) =                              \
+        PERFETTO_GET_CATEGORY_INDEX(category);                            \
+    if (tns::internal::IsDynamicCategory(category)) {                     \
+      tns::TrackEvent::CallIfEnabled([&](uint32_t instances) {            \
+        tns::TrackEvent::TraceForCategory<PERFETTO_UID(kCatIndex)>(       \
+            instances, category, ##__VA_ARGS__);                          \
+      });                                                                 \
+    } else {                                                              \
+      tns::TrackEvent::CallIfCategoryEnabled<PERFETTO_UID(kCatIndex)>(    \
+          [&](uint32_t instances) {                                       \
+            /* TODO(skyostil): Get rid of the category name parameter. */ \
+            tns::TrackEvent::TraceForCategory<PERFETTO_UID(kCatIndex)>(   \
+                instances, nullptr, ##__VA_ARGS__);                       \
+          });                                                             \
+    }                                                                     \
   } while (false)
 
 #define PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ...)             \
@@ -155,7 +146,7 @@
   (::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory(category)   \
        ? ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::                      \
              IsDynamicCategoryEnabled(::perfetto::DynamicCategory(category)) \
-       : ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsCategoryEnabled(    \
-             PERFETTO_GET_CATEGORY_INDEX(category)))
+       : ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsCategoryEnabled<    \
+             PERFETTO_GET_CATEGORY_INDEX(category)>())
 
 #endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
diff --git a/include/perfetto/tracing/internal/write_track_event_args.h b/include/perfetto/tracing/internal/write_track_event_args.h
deleted file mode 100644
index 2f84878..0000000
--- a/include/perfetto/tracing/internal/write_track_event_args.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_WRITE_TRACK_EVENT_ARGS_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/tracing/event_context.h"
-#include "perfetto/tracing/traced_proto.h"
-
-namespace perfetto {
-namespace internal {
-
-// Helper function handling filling provided |EventContext| from the provided
-// arguments, which include:
-// - Lambda functions,
-// - Debug annotations.
-//
-// TRACE_EVENT parameters which do not translate to directly writing something
-// into TrackEvent proto (like tracks and timestamps are _not_ covered by this
-// function).
-template <typename... Args, typename TypeCheck = void>
-void WriteTrackEventArgs(EventContext event_context, Args&&... args);
-
-// No arguments means that we don't have to write anything.
-template <>
-PERFETTO_ALWAYS_INLINE inline void WriteTrackEventArgs(EventContext) {}
-
-namespace {
-
-// A template helper for determining whether a type can be used as a track event
-// lambda, i.e., it has the signature "void(EventContext)". This is achieved by
-// checking that we can pass an EventContext value (the inner declval) into a T
-// instance (the outer declval). If this is a valid expression, the result
-// evaluates to sizeof(0), i.e., true.
-// TODO(skyostil): Replace this with std::is_convertible<std::function<...>>
-// once we have C++14.
-template <typename T>
-static constexpr bool IsValidTraceLambdaImpl(
-    typename std::enable_if<static_cast<bool>(
-        sizeof(std::declval<T>()(std::declval<EventContext>()), 0))>::type* =
-        nullptr) {
-  return true;
-}
-
-template <typename T>
-static constexpr bool IsValidTraceLambdaImpl(...) {
-  return false;
-}
-
-template <typename T>
-static constexpr bool IsValidTraceLambda() {
-  return IsValidTraceLambdaImpl<T>(nullptr);
-}
-
-}  // namespace
-
-// Write a lambda.
-// TODO(altimin): At the moment lambda takes EventContext, which is
-// non-copyable, so only one lambda is supported and it has to be the last
-// argument.
-template <typename ArgumentFunction,
-          typename ArgFunctionCheck = typename std::enable_if<
-              IsValidTraceLambda<ArgumentFunction>()>::type>
-PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
-                                                ArgumentFunction arg_function) {
-  arg_function(std::move(event_ctx));
-}
-
-// Write one debug annotation and recursively write the rest of the arguments.
-template <typename ArgValue, typename... Args>
-PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(EventContext event_ctx,
-                                                const char* arg_name,
-                                                ArgValue&& arg_value,
-                                                Args&&... args) {
-  TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
-                                         std::forward<ArgValue>(arg_value));
-  WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
-}
-
-// Write one typed message and recursively write the rest of the arguments.
-template <typename FieldMetadataType,
-          typename ArgValue,
-          typename... Args,
-          typename Check = base::enable_if_t<
-              std::is_base_of<protozero::proto_utils::FieldMetadataBase,
-                              FieldMetadataType>::value>>
-PERFETTO_ALWAYS_INLINE void WriteTrackEventArgs(
-    EventContext event_ctx,
-    protozero::proto_utils::internal::FieldMetadataHelper<FieldMetadataType>
-        field_name,
-    ArgValue&& arg_value,
-    Args&&... args) {
-  static_assert(
-      std::is_base_of<protos::pbzero::TrackEvent,
-                      typename FieldMetadataType::message_type>::value,
-      "Only fields of TrackEvent (and TrackEvent's extensions) can "
-      "be passed to TRACE_EVENT");
-  WriteIntoTracedProto(
-      event_ctx.Wrap(
-          event_ctx.event<typename FieldMetadataType::message_type>()),
-      field_name, std::forward<ArgValue>(arg_value));
-  WriteTrackEventArgs(std::move(event_ctx), std::forward<Args>(args)...);
-}
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
diff --git a/include/perfetto/tracing/platform.h b/include/perfetto/tracing/platform.h
index ecd74d9..662e73d 100644
--- a/include/perfetto/tracing/platform.h
+++ b/include/perfetto/tracing/platform.h
@@ -22,7 +22,6 @@
 
 #include <functional>
 #include <memory>
-#include <string>
 
 #include "perfetto/base/export.h"
 
diff --git a/include/perfetto/tracing/string_helpers.h b/include/perfetto/tracing/string_helpers.h
deleted file mode 100644
index 8511d1a..0000000
--- a/include/perfetto/tracing/string_helpers.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_STRING_HELPERS_H_
-#define INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
-
-#include "perfetto/base/export.h"
-
-#include <cstddef>
-#include <string>
-
-namespace perfetto {
-
-// A wrapper for marking strings that can't be determined to be static at build
-// time, but are in fact static.
-class PERFETTO_EXPORT StaticString {
- public:
-  // Implicit constructor for string literals.
-  template <size_t N>
-  constexpr StaticString(const char (&str)[N]) : value(str) {}
-
-  // Implicit constructor for null strings.
-  constexpr StaticString(std::nullptr_t) : value(nullptr) {}
-
-  constexpr explicit StaticString(const char* str) : value(str) {}
-
-  const char* value;
-};
-
-namespace internal {
-
-// Ensure that |string| is a static constant string.
-//
-// If you get a compiler failure here, you are most likely trying to use
-// TRACE_EVENT with a dynamic event name. There are two ways to fix this:
-//
-// 1) If the event name is actually dynamic (e.g., std::string), write it into
-//    the event manually:
-//
-//      TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
-//        ctx.event()->set_name(dynamic_name);
-//      });
-//
-// 2) If the name is static, but the pointer is computed at runtime, wrap it
-//    with perfetto::StaticString:
-//
-//      TRACE_EVENT("category", perfetto::StaticString{name});
-//
-//    DANGER: Using perfetto::StaticString with strings whose contents change
-//            dynamically can cause silent trace data corruption.
-//
-constexpr const char* GetStaticString(StaticString string) {
-  return string.value;
-}
-
-}  // namespace internal
-
-// A explicit wrapper for marking strings as dynamic to ensure that perfetto
-// doesn't try to cache the pointer value.
-class PERFETTO_EXPORT DynamicString {
- public:
-  explicit DynamicString(const std::string& str)
-      : value(str.data()), length(str.length()) {}
-  explicit DynamicString(const char* str) : value(str), length(strlen(str)) {}
-  DynamicString(const char* str, size_t len) : value(str), length(len) {}
-
-  const char* value;
-  size_t length;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
diff --git a/include/perfetto/tracing/traced_proto.h b/include/perfetto/tracing/traced_proto.h
deleted file mode 100644
index 44e4fb2..0000000
--- a/include/perfetto/tracing/traced_proto.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TRACED_PROTO_H_
-#define INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
-
-#include "perfetto/base/template_util.h"
-#include "perfetto/protozero/field_writer.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace perfetto {
-class EventContext;
-
-// A Wrapper around a protozero message to allow C++ classes to specify how it
-// should be serialised into the trace:
-//
-// class Foo {
-//  public:
-//   void WriteIntoTrace(perfetto::TracedProto<pbzero::Foo> message) {
-//     message->set_int_field(int_field_);
-//   }
-// };
-//
-// This class also exposes EventContext, e.g. to enable data interning.
-//
-// NOTE: the functionality below is not ready yet.
-// TODO(altimin): Make the interop below possible.
-// TracedProto also provides a seamless integration with writing untyped
-// values via TracedValue / TracedDictionary / TracedArray:
-//
-// - TracedValue can be converted to a TracedProto, either by calling
-//   TracedValue::WriteProto<T>() or implicitly.
-// - If a proto message has a repeating DebugAnnotation debug_annotations
-//   field, it can be filled using the TracedDictionary obtained from
-//   TracedProto::WriteDebugAnnotations.
-template <typename MessageType>
-class TracedProto {
- public:
-  TracedProto(const TracedProto&) = delete;
-  TracedProto& operator=(const TracedProto&) = delete;
-  TracedProto& operator=(TracedProto&&) = delete;
-  TracedProto(TracedProto&&) = default;
-  ~TracedProto() = default;
-
-  MessageType* operator->() const { return message_; }
-
-  MessageType* message() { return message_; }
-
-  EventContext& context() const { return context_; }
-
- private:
-  friend class EventContext;
-
-  TracedProto(MessageType* message, EventContext& context)
-      : message_(message), context_(context) {}
-
-  MessageType* const message_;
-  EventContext& context_;
-};
-
-namespace internal {
-
-// TypedProtoWriter takes the protozero message (TracedProto<MessageType>),
-// field description (FieldMetadata) and value and writes the given value
-// into the given field of the given protozero message.
-//
-// This is primarily used for inline writing of typed messages:
-// TRACE_EVENT(..., pbzero::Message:kField, value);
-//
-// Ideally we would use a function here and not a struct, but passing template
-// arguments directly to the function (e.g. foo<void>()) isn't supported until
-// C++20, so we have to use a helper struct here.
-template <typename FieldMetadata>
-struct TypedProtoWriter {
- private:
-  using ProtoSchemaType = protozero::proto_utils::ProtoSchemaType;
-  using RepetitionType = protozero::proto_utils::RepetitionType;
-
-  static_assert(FieldMetadata::kRepetitionType !=
-                    RepetitionType::kRepeatedPacked,
-                "writing packed fields isn't supported yet");
-
- public:
-  // Implementation note: typename Check=void is used to ensure that SFINAE
-  // kicks in and the methods which do not match FieldMetadata do not fail
-  // to compile. std::is_same<Check,void> prevents early evaluation of the
-  // first enable_if_t argument.
-
-  // Simple non-repeated field.
-  template <typename Proto, typename ValueType, typename Check = void>
-  static typename base::enable_if_t<
-      FieldMetadata::kProtoFieldType != ProtoSchemaType::kMessage &&
-      FieldMetadata::kRepetitionType == RepetitionType::kNotRepeated &&
-      std::is_same<Check, void>::value>
-  Write(TracedProto<Proto> context, ValueType&& value) {
-    protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
-        *context.message(), FieldMetadata::kFieldId, value);
-  }
-
-  // Simple repeated non-packed field.
-  template <typename Proto, typename ValueType, typename Check = void>
-  static typename base::enable_if_t<
-      FieldMetadata::kProtoFieldType != ProtoSchemaType::kMessage &&
-      FieldMetadata::kRepetitionType == RepetitionType::kRepeatedNotPacked &&
-      std::is_same<Check, void>::value>
-  Write(TracedProto<Proto> context, ValueType&& value) {
-    for (auto&& item : value) {
-      protozero::internal::FieldWriter<FieldMetadata::kProtoFieldType>::Append(
-          *context.message(), FieldMetadata::kFieldId, item);
-    }
-  }
-
-  // Nested non-repeated field.
-  template <typename Proto, typename ValueType, typename Check = void>
-  static typename base::enable_if_t<
-      FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage &&
-      FieldMetadata::kRepetitionType == RepetitionType::kNotRepeated &&
-      std::is_same<Check, void>::value>
-  Write(TracedProto<Proto> context, ValueType&& value) {
-    // TODO(altimin): support TraceFormatTraits here.
-    value.WriteIntoTrace(
-        context.context().Wrap(context.message()
-                                   ->template BeginNestedMessage<
-                                       typename FieldMetadata::cpp_field_type>(
-                                       FieldMetadata::kFieldId)));
-  }
-
-  // Nested repeated non-packed field.
-  template <typename Proto, typename ValueType, typename Check = void>
-  static typename base::enable_if_t<
-      FieldMetadata::kProtoFieldType == ProtoSchemaType::kMessage &&
-      FieldMetadata::kRepetitionType == RepetitionType::kRepeatedNotPacked &&
-      std::is_same<Check, void>::value>
-  Write(TracedProto<Proto> context, ValueType&& value) {
-    // TODO(altimin): support TraceFormatTraits here.
-    for (auto&& item : value) {
-      item.WriteIntoTrace(context.context().Wrap(
-          context.message()
-              ->template BeginNestedMessage<
-                  typename FieldMetadata::cpp_field_type>(
-                  FieldMetadata::kFieldId)));
-    }
-  }
-};
-
-}  // namespace internal
-
-template <typename MessageType, typename FieldMetadataType, typename ValueType>
-void WriteIntoTracedProto(
-    TracedProto<MessageType> message,
-    protozero::proto_utils::internal::FieldMetadataHelper<FieldMetadataType>,
-    ValueType&& value) {
-  static_assert(
-      std::is_base_of<protozero::proto_utils::FieldMetadataBase,
-                      FieldMetadataType>::value,
-      "Field name should be a protozero::internal::FieldMetadata<...>");
-  static_assert(
-      std::is_base_of<MessageType,
-                      typename FieldMetadataType::message_type>::value,
-      "Field's parent type should match the context.");
-
-  internal::TypedProtoWriter<FieldMetadataType>::Write(
-      std::move(message), std::forward<ValueType>(value));
-}
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
diff --git a/include/perfetto/tracing/traced_value.h b/include/perfetto/tracing/traced_value.h
deleted file mode 100644
index b1a14d3..0000000
--- a/include/perfetto/tracing/traced_value.h
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TRACED_VALUE_H_
-#define INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/export.h"
-#include "perfetto/base/template_util.h"
-#include "perfetto/tracing/internal/checked_scope.h"
-#include "perfetto/tracing/string_helpers.h"
-#include "perfetto/tracing/traced_value_forward.h"
-
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class DebugAnnotation;
-}
-}  // namespace protos
-
-class DebugAnnotation;
-
-// These classes provide a JSON-inspired way to write structed data into traces.
-//
-// Each TracedValue can be consumed exactly once to write a value into a trace
-// using one of the Write* methods.
-//
-// Write* methods fall into two categories:
-// - Primitive types (int, string, bool, double, etc): they just write the
-//   provided value, consuming the TracedValue in the process.
-// - Complex types (arrays and dicts): they consume the TracedValue and
-//   return a corresponding scoped object (TracedArray or TracedDictionary).
-//   This scope then can be used to write multiple items into the container:
-//   TracedArray::AppendItem and TracedDictionary::AddItem return a new
-//   TracedValue which then can be used to write an element of the
-//   dictionary or array.
-//
-// To define how a custom class should be written into the trace, users should
-// define one of the two following functions:
-// - Foo::WriteIntoTrace(TracedValue) const
-//   (preferred for code which depends on perfetto directly)
-// - perfetto::TraceFormatTraits<T>::WriteIntoTrace(
-//       TracedValue, const T&);
-//   (should be used if T is defined in a library which doesn't know anything
-//   about tracing).
-//
-//
-// After definiting a conversion method, the object can be used directly as a
-// TRACE_EVENT argument:
-//
-// Foo foo;
-// TRACE_EVENT("cat", "Event", "arg", foo);
-//
-// Examples:
-//
-// TRACE_EVENT("cat", "event", "params", [&](perfetto::TracedValue context)
-// {
-//   auto dict = std::move(context).WriteDictionary();
-//   dict->Add("param1", param1);
-//   dict->Add("param2", param2);
-//   ...
-//   dict->Add("paramN", paramN);
-//
-//   {
-//     auto inner_array = dict->AddArray("inner");
-//     inner_array->Append(value1);
-//     inner_array->Append(value2);
-//   }
-// });
-//
-// template <typename T>
-// TraceFormatTraits<std::optional<T>>::WriteIntoTrace(
-//    TracedValue context, const std::optional<T>& value) {
-//  if (!value) {
-//    std::move(context).WritePointer(nullptr);
-//    return;
-//  }
-//  perfetto::WriteIntoTrace(std::move(context), *value);
-// }
-//
-// template <typename T>
-// TraceFormatTraits<std::vector<T>>::WriteIntoTrace(
-//    TracedValue context, const std::array<T>& value) {
-//  auto array = std::move(context).WriteArray();
-//  for (const auto& item: value) {
-//    array_scope.Append(item);
-//  }
-// }
-//
-// class Foo {
-//   void WriteIntoTrace(TracedValue context) const {
-//     auto dict = std::move(context).WriteDictionary();
-//     dict->Set("key", 42);
-//     dict->Set("foo", "bar");
-//     dict->Set("member", member_);
-//   }
-// }
-namespace internal {
-PERFETTO_EXPORT TracedValue
-CreateTracedValueFromProto(protos::pbzero::DebugAnnotation*);
-}
-
-class PERFETTO_EXPORT TracedValue {
- public:
-  TracedValue(const TracedValue&) = delete;
-  TracedValue& operator=(const TracedValue&) = delete;
-  TracedValue& operator=(TracedValue&&) = delete;
-  TracedValue(TracedValue&&) = default;
-  ~TracedValue() = default;
-
-  // TracedValue represents a context into which a single value can be written
-  // (either by writing it directly for primitive types, or by creating a
-  // TracedArray or TracedDictionary for the complex types). This is enforced
-  // by allowing Write* methods to be called only on rvalue references.
-
-  void WriteInt64(int64_t value) &&;
-  void WriteUInt64(uint64_t value) &&;
-  void WriteDouble(double value) &&;
-  void WriteBoolean(bool value) &&;
-  void WriteString(const char*) &&;
-  void WriteString(const char*, size_t len) &&;
-  void WriteString(const std::string&) &&;
-  void WritePointer(const void* value) &&;
-
-  // Rules for writing nested dictionaries and arrays:
-  // - Only one scope (TracedArray, TracedDictionary or TracedValue) can be
-  // active at the same time. It's only allowed to call methods on the active
-  // scope.
-  // - When a scope creates a nested scope, the new scope becomes active.
-  // - When a scope is destroyed, it's parent scope becomes active again.
-  //
-  // Typically users will have to create a scope only at the beginning of a
-  // conversion function and this scope should be destroyed at the end of it.
-  // TracedArray::Append and TracedDictionary::Add create, write and complete
-  // inner scopes automatically.
-
-  // Scope which allows multiple values to be appended.
-  TracedArray WriteArray() && PERFETTO_WARN_UNUSED_RESULT;
-
-  // Scope which allows multiple key-value pairs to be added.
-  TracedDictionary WriteDictionary() && PERFETTO_WARN_UNUSED_RESULT;
-
- private:
-  friend class TracedArray;
-  friend class TracedDictionary;
-  friend TracedValue internal::CreateTracedValueFromProto(
-      protos::pbzero::DebugAnnotation*);
-
-  static TracedValue CreateFromProto(protos::pbzero::DebugAnnotation*);
-
-  inline explicit TracedValue(protos::pbzero::DebugAnnotation* context,
-                              internal::CheckedScope* parent_scope)
-      : context_(context), checked_scope_(parent_scope) {}
-
-  // Temporary support for perfetto::DebugAnnotation C++ class before it's going
-  // to be replaced by TracedValue.
-  // TODO(altimin): Convert v8 to use TracedValue directly and delete it.
-  friend class DebugAnnotation;
-
-  protos::pbzero::DebugAnnotation* const context_ = nullptr;
-
-  internal::CheckedScope checked_scope_;
-};
-
-class PERFETTO_EXPORT TracedArray {
- public:
-  TracedArray(const TracedArray&) = delete;
-  TracedArray& operator=(const TracedArray&) = delete;
-  TracedArray& operator=(TracedArray&&) = delete;
-  TracedArray(TracedArray&&) = default;
-  ~TracedArray() = default;
-
-  TracedValue AppendItem();
-
-  template <typename T>
-  void Append(T&& value) {
-    WriteIntoTracedValue(AppendItem(), std::forward<T>(value));
-  }
-
-  TracedDictionary AppendDictionary() PERFETTO_WARN_UNUSED_RESULT;
-  TracedArray AppendArray();
-
- private:
-  friend class TracedValue;
-
-  inline explicit TracedArray(protos::pbzero::DebugAnnotation* context,
-                              internal::CheckedScope* parent_scope)
-      : context_(context), checked_scope_(parent_scope) {}
-
-  protos::pbzero::DebugAnnotation* context_;
-
-  internal::CheckedScope checked_scope_;
-};
-
-class PERFETTO_EXPORT TracedDictionary {
- public:
-  TracedDictionary(const TracedDictionary&) = delete;
-  TracedDictionary& operator=(const TracedDictionary&) = delete;
-  TracedDictionary& operator=(TracedDictionary&&) = delete;
-  TracedDictionary(TracedDictionary&&) = default;
-  ~TracedDictionary() = default;
-
-  // There are two paths for writing dictionary keys: fast path for writing
-  // compile-time const, whose pointer is remains valid during the entire
-  // runtime of the program and the slow path for dynamic strings, which need to
-  // be copied.
-  // In the most common case, a string literal can be passed to `Add`/`AddItem`.
-  // In other cases, either StaticString or DynamicString declarations are
-  // needed.
-
-  TracedValue AddItem(StaticString key);
-  TracedValue AddItem(DynamicString key);
-
-  template <typename T>
-  void Add(StaticString key, T&& value) {
-    WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
-  }
-
-  template <typename T>
-  void Add(DynamicString key, T&& value) {
-    WriteIntoTracedValue(AddItem(key), std::forward<T>(value));
-  }
-
-  TracedDictionary AddDictionary(StaticString key);
-  TracedDictionary AddDictionary(DynamicString key);
-  TracedArray AddArray(StaticString key);
-  TracedArray AddArray(DynamicString key);
-
- private:
-  friend class TracedValue;
-
-  inline explicit TracedDictionary(protos::pbzero::DebugAnnotation* context,
-                                   internal::CheckedScope* parent_scope)
-      : context_(context), checked_scope_(parent_scope) {}
-
-  protos::pbzero::DebugAnnotation* context_;
-
-  internal::CheckedScope checked_scope_;
-};
-
-namespace internal {
-
-// SFINAE helpers for finding a right overload to convert a given class to
-// trace-friendly form, ordered from most to least preferred.
-
-constexpr int kMaxWriteImplPriority = 4;
-
-// If T has WriteIntoTracedValue member function, call it.
-template <typename T>
-decltype(std::declval<T>().WriteIntoTracedValue(std::declval<TracedValue>()),
-         void())
-WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
-  value.WriteIntoTracedValue(std::move(context));
-}
-
-// If T has WriteIntoTrace member function, call it.
-template <typename T>
-decltype(std::declval<T>().WriteIntoTrace(std::declval<TracedValue>()), void())
-WriteImpl(base::priority_tag<4>, TracedValue context, T&& value) {
-  value.WriteIntoTrace(std::move(context));
-}
-
-// If perfetto::TraceFormatTraits<T>::WriteIntoTracedValue(TracedValue, const
-// T&) is available, use it.
-template <typename T>
-decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
-             std::declval<TracedValue>(),
-             std::declval<T>()),
-         void())
-WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
-  TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTracedValue(
-      std::move(context), std::forward<T>(value));
-}
-
-// If perfetto::TraceFormatTraits<T>::WriteIntoTrace(TracedValue, const T&)
-// is available, use it.
-template <typename T>
-decltype(TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
-             std::declval<TracedValue>(),
-             std::declval<T>()),
-         void())
-WriteImpl(base::priority_tag<3>, TracedValue context, T&& value) {
-  TraceFormatTraits<base::remove_cvref_t<T>>::WriteIntoTrace(
-      std::move(context), std::forward<T>(value));
-}
-
-// If T has operator(), which takes TracedValue, use it.
-// Very useful for lambda resolutions.
-template <typename T>
-decltype(std::declval<T>()(std::declval<TracedValue>()), void())
-WriteImpl(base::priority_tag<2>, TracedValue context, T&& value) {
-  std::forward<T>(value)(std::move(context));
-}
-
-// If T is a container and its elements have tracing support, use it.
-//
-// Note: a reference to T should be passed to std::begin, otherwise
-// for non-reference types const T& will be passed to std::begin, losing
-// support for non-const WriteIntoTracedValue methods.
-template <typename T>
-typename check_traced_value_support<
-    decltype(*std::begin(std::declval<T&>()))>::type
-WriteImpl(base::priority_tag<1>, TracedValue context, T&& value) {
-  auto array = std::move(context).WriteArray();
-  for (auto&& item : value) {
-    array.Append(item);
-  }
-}
-
-// std::underlying_type can't be used with non-enum types, so we need this
-// indirection.
-template <typename T, bool = std::is_enum<T>::value>
-struct safe_underlying_type {
-  using type = typename std::underlying_type<T>::type;
-};
-
-template <typename T>
-struct safe_underlying_type<T, false> {
-  using type = T;
-};
-
-template <typename T>
-struct is_incomplete_type {
-  static constexpr bool value = sizeof(T) != 0;
-};
-
-// sizeof is not available for const char[], but it's still not considered to be
-// an incomplete type for our purposes as the size can be determined at runtime
-// due to strings being null-terminated.
-template <>
-struct is_incomplete_type<const char[]> {
-  static constexpr bool value = true;
-};
-
-}  // namespace internal
-
-// Helper template to determine if a given type can be passed to
-// perfetto::WriteIntoTracedValue. These templates will fail to resolve if the
-// class does not have it support, so they are useful in SFINAE and in producing
-// helpful compiler results.
-template <typename T, class Result = void>
-using check_traced_value_support_t = decltype(
-    internal::WriteImpl(
-        std::declval<base::priority_tag<internal::kMaxWriteImplPriority>>(),
-        std::declval<TracedValue>(),
-        std::declval<T>()),
-    std::declval<Result>());
-
-// check_traced_value_support<T, V>::type is defined (and equal to V) iff T
-// supports being passed to WriteIntoTracedValue. See the comment in
-// traced_value_forward.h for more details.
-template <typename T, class Result>
-struct check_traced_value_support<T,
-                                  Result,
-                                  check_traced_value_support_t<T, Result>> {
-  static_assert(
-      internal::is_incomplete_type<T>::value,
-      "perfetto::TracedValue should not be used with incomplete types");
-
-  static constexpr bool value = true;
-  using type = Result;
-};
-
-namespace internal {
-
-// Helper class to check if a given type can be passed to
-// perfetto::WriteIntoTracedValue. This template will always resolve (with
-// |value| being set to either true or false depending on presence of the
-// support, so this macro is useful in the situation when you want to e.g. OR
-// the result with some other conditions.
-//
-// In this case, compiler will not give you the full deduction chain, so, for
-// example, use check_traced_value_support for writing positive static_asserts
-// and has_traced_value_support for writing negative.
-template <typename T>
-class has_traced_value_support {
-  using Yes = char[1];
-  using No = char[2];
-
-  template <typename V>
-  static Yes& check_support(check_traced_value_support_t<V, int>);
-  template <typename V>
-  static No& check_support(...);
-
- public:
-  static constexpr bool value = sizeof(Yes) == sizeof(check_support<T>(0));
-};
-
-}  // namespace internal
-
-template <typename T>
-void WriteIntoTracedValue(TracedValue context, T&& value) {
-  // TODO(altimin): Add a URL to documentation and a list of common failure
-  // patterns.
-  static_assert(
-      internal::has_traced_value_support<T>::value,
-      "The provided type (passed to TRACE_EVENT argument / TracedArray::Append "
-      "/ TracedDictionary::Add) does not support being written in a trace "
-      "format. Please see the comment in traced_value.h for more details.");
-
-  // Should be kept in sync with check_traced_value_support_t!
-  internal::WriteImpl(base::priority_tag<internal::kMaxWriteImplPriority>(),
-                      std::move(context), std::forward<T>(value));
-}
-
-// Helpers to write a given value into TracedValue even if the given type
-// doesn't support conversion (in which case the provided fallback should be
-// used). Useful for automatically generating conversions for autogenerated
-// code, but otherwise shouldn't be used as non-autogenerated code is expected
-// to define WriteIntoTracedValue convertor.
-// See WriteWithFallback test in traced_value_unittest.cc for a concrete
-// example.
-template <typename T>
-typename std::enable_if<internal::has_traced_value_support<T>::value>::type
-WriteIntoTracedValueWithFallback(TracedValue context,
-                                 T&& value,
-                                 const std::string&) {
-  WriteIntoTracedValue(std::move(context), std::forward<T>(value));
-}
-
-template <typename T>
-typename std::enable_if<!internal::has_traced_value_support<T>::value>::type
-WriteIntoTracedValueWithFallback(TracedValue context,
-                                 T&&,
-                                 const std::string& fallback) {
-  std::move(context).WriteString(fallback);
-}
-
-// TraceFormatTraits implementations for primitive types.
-
-// Specialisation for signed integer types (note: it excludes enums, which have
-// their own explicit specialisation).
-template <typename T>
-struct TraceFormatTraits<
-    T,
-    typename std::enable_if<std::is_integral<T>::value &&
-                            !std::is_same<T, bool>::value &&
-                            std::is_signed<T>::value>::type> {
-  inline static void WriteIntoTrace(TracedValue context, T value) {
-    std::move(context).WriteInt64(value);
-  }
-};
-
-// Specialisation for unsigned integer types (note: it excludes enums, which
-// have their own explicit specialisation).
-template <typename T>
-struct TraceFormatTraits<
-    T,
-    typename std::enable_if<std::is_integral<T>::value &&
-                            !std::is_same<T, bool>::value &&
-                            std::is_unsigned<T>::value>::type> {
-  inline static void WriteIntoTrace(TracedValue context, T value) {
-    std::move(context).WriteUInt64(value);
-  }
-};
-
-// Specialisation for bools.
-template <>
-struct TraceFormatTraits<bool> {
-  inline static void WriteIntoTrace(TracedValue context, bool value) {
-    std::move(context).WriteBoolean(value);
-  }
-};
-
-// Specialisation for floating point values.
-template <typename T>
-struct TraceFormatTraits<
-    T,
-    typename std::enable_if<std::is_floating_point<T>::value>::type> {
-  inline static void WriteIntoTrace(TracedValue context, T value) {
-    std::move(context).WriteDouble(static_cast<double>(value));
-  }
-};
-
-// Specialisation for signed enums.
-template <typename T>
-struct TraceFormatTraits<
-    T,
-    typename std::enable_if<
-        std::is_enum<T>::value &&
-        std::is_signed<
-            typename internal::safe_underlying_type<T>::type>::value>::type> {
-  inline static void WriteIntoTrace(TracedValue context, T value) {
-    std::move(context).WriteInt64(static_cast<int64_t>(value));
-  }
-};
-
-// Specialisation for unsigned enums.
-template <typename T>
-struct TraceFormatTraits<
-    T,
-    typename std::enable_if<
-        std::is_enum<T>::value &&
-        std::is_unsigned<
-            typename internal::safe_underlying_type<T>::type>::value>::type> {
-  inline static void WriteIntoTrace(TracedValue context, T value) {
-    std::move(context).WriteUInt64(static_cast<uint64_t>(value));
-  }
-};
-
-// Specialisations for C-style strings.
-template <>
-struct TraceFormatTraits<const char*> {
-  inline static void WriteIntoTrace(TracedValue context, const char* value) {
-    std::move(context).WriteString(value);
-  }
-};
-
-template <>
-struct TraceFormatTraits<char[]> {
-  inline static void WriteIntoTrace(TracedValue context, const char value[]) {
-    std::move(context).WriteString(value);
-  }
-};
-
-template <size_t N>
-struct TraceFormatTraits<char[N]> {
-  inline static void WriteIntoTrace(TracedValue context, const char value[N]) {
-    std::move(context).WriteString(value);
-  }
-};
-
-// Specialisation for C++ strings.
-template <>
-struct TraceFormatTraits<std::string> {
-  inline static void WriteIntoTrace(TracedValue context,
-                                    const std::string& value) {
-    std::move(context).WriteString(value);
-  }
-};
-
-// Specialisation for (const) void*, which writes the pointer value.
-template <>
-struct TraceFormatTraits<void*> {
-  inline static void WriteIntoTrace(TracedValue context, void* value) {
-    std::move(context).WritePointer(value);
-  }
-};
-
-template <>
-struct TraceFormatTraits<const void*> {
-  inline static void WriteIntoTrace(TracedValue context, const void* value) {
-    std::move(context).WritePointer(value);
-  }
-};
-
-// Specialisation for std::unique_ptr<>, which writes either nullptr or the
-// object it points to.
-template <typename T>
-struct TraceFormatTraits<std::unique_ptr<T>, check_traced_value_support_t<T>> {
-  inline static void WriteIntoTrace(TracedValue context,
-                                    const std::unique_ptr<T>& value) {
-    ::perfetto::WriteIntoTracedValue(std::move(context), value.get());
-  }
-};
-
-// Specialisation for raw pointer, which writes either nullptr or the object it
-// points to.
-template <typename T>
-struct TraceFormatTraits<T*, check_traced_value_support_t<T>> {
-  inline static void WriteIntoTrace(TracedValue context, T* value) {
-    if (!value) {
-      std::move(context).WritePointer(nullptr);
-      return;
-    }
-    ::perfetto::WriteIntoTracedValue(std::move(context), *value);
-  }
-};
-
-// Specialisation for nullptr.
-template <>
-struct TraceFormatTraits<std::nullptr_t> {
-  inline static void WriteIntoTrace(TracedValue context, std::nullptr_t) {
-    std::move(context).WritePointer(nullptr);
-  }
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
diff --git a/include/perfetto/tracing/traced_value_forward.h b/include/perfetto/tracing/traced_value_forward.h
deleted file mode 100644
index 7a91712..0000000
--- a/include/perfetto/tracing/traced_value_forward.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TRACED_VALUE_FORWARD_H_
-#define INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
-
-namespace perfetto {
-
-class TracedValue;
-class TracedArray;
-class TracedDictionary;
-
-template <typename T>
-void WriteIntoTracedValue(TracedValue context, T&& value);
-
-template <typename T, class = void>
-struct TraceFormatTraits;
-
-// Write support checker to allow it to be used when matching.
-//
-// Intended to be used for types like smart pointers, who should support
-// AsTracedValueInto only iff their inner type supports being written into
-// a TracedValue.
-//
-// template <typename T>
-// class SmartPtr {
-//   ...
-//
-//   typename check_traced_value_support<T, void>::value
-//   AsTracedValueInto(perfetto::TracedValue context) const {
-//      WriteIntoTracedValue(std::move(context), *ptr_);
-//   }
-// };
-template <typename T, typename ResultType = void, class = void>
-struct check_traced_value_support;
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
diff --git a/include/perfetto/tracing/tracing.h b/include/perfetto/tracing/tracing.h
index 8a688f2..76a42a3 100644
--- a/include/perfetto/tracing/tracing.h
+++ b/include/perfetto/tracing/tracing.h
@@ -28,11 +28,9 @@
 #include "perfetto/base/compiler.h"
 #include "perfetto/base/export.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/tracing/backend_type.h"
 #include "perfetto/tracing/core/forward_decls.h"
 #include "perfetto/tracing/internal/in_process_tracing_backend.h"
 #include "perfetto/tracing/internal/system_tracing_backend.h"
-#include "perfetto/tracing/tracing_policy.h"
 
 namespace perfetto {
 
@@ -44,31 +42,26 @@
 class Platform;
 class TracingSession;  // Declared below.
 
-struct TracingError {
-  enum ErrorCode : uint32_t {
-    // Peer disconnection.
-    kDisconnected = 1,
+enum BackendType : uint32_t {
+  kUnspecifiedBackend = 0,
 
-    // The Start() method failed. This is typically because errors in the passed
-    // TraceConfig. More details are available in |message|.
-    kTracingFailed = 2,
-  };
+  // 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,
 
-  ErrorCode code;
-  std::string message;
+  // Connects to the system tracing service (e.g. on Linux/Android/Mac uses a
+  // named UNIX socket).
+  kSystemBackend = 1 << 1,
 
-  TracingError(ErrorCode cd, std::string msg)
-      : code(cd), message(std::move(msg)) {
-    PERFETTO_CHECK(!message.empty());
-  }
+  // 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,
 };
 
-using LogLev = ::perfetto::base::LogLev;
-using LogMessageCallbackArgs = ::perfetto::base::LogMessageCallbackArgs;
-using LogMessageCallback = ::perfetto::base::LogMessageCallback;
-
 struct TracingInitArgs {
-  uint32_t backends = 0;                     // One or more BackendTypes.
+  uint32_t backends = 0;                     // One or more BackendFlags.
   TracingBackend* custom_backend = nullptr;  // [Optional].
 
   // [Optional] Platform implementation. It allows the embedder to take control
@@ -90,31 +83,6 @@
   // Must be one of [4, 8, 16, 32].
   uint32_t shmem_page_size_hint_kb = 0;
 
-  // [Optional] The length of the period during which shared-memory-buffer
-  // chunks that have been filled with data are accumulated (batched) on the
-  // producer side, before the service is notified of them over an out-of-band
-  // IPC call. If, while this period lasts, the shared memory buffer gets too
-  // full, the IPC call will be sent immediately. The value of this parameter is
-  // a trade-off between IPC traffic overhead and the ability to sustain bursts
-  // of trace writes. The higher the value, the more chunks will be batched and
-  // the less buffer space will be available to hide the latency of the service,
-  // and vice versa. For more details, see the SetBatchCommitsDuration method in
-  // shared_memory_arbiter.h.
-  //
-  // Note: With the default value of 0ms, batching still happens but with a zero
-  // delay, i.e. commits will be sent to the service at the next opportunity.
-  uint32_t shmem_batch_commits_duration_ms = 0;
-
-  // [Optional] If set, the policy object is notified when certain SDK events
-  // occur and may apply policy decisions, such as denying connections. The
-  // embedder is responsible for ensuring the object remains alive for the
-  // lifetime of the process.
-  TracingPolicy* tracing_policy = nullptr;
-
-  // [Optional] If set, log messages generated by perfetto are passed to this
-  // callback instead of being logged directly.
-  LogMessageCallback log_message_callback = nullptr;
-
  protected:
   friend class Tracing;
   friend class internal::TracingMuxerImpl;
@@ -167,9 +135,6 @@
     InitializeInternal(args_copy);
   }
 
-  // Checks if tracing has been initialized by calling |Initialize|.
-  static bool IsInitialized();
-
   // 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
@@ -194,8 +159,7 @@
   // TODO(primiano): add an error callback.
   virtual void Setup(const TraceConfig&, int fd = -1) = 0;
 
-  // Enable tracing asynchronously. Use SetOnStartCallback() to get a
-  // notification when the session has fully started.
+  // Enable tracing asynchronously.
   virtual void Start() = 0;
 
   // Enable tracing and block until tracing has started. Note that if data
@@ -206,46 +170,6 @@
   // started.
   virtual void StartBlocking() = 0;
 
-  // This callback will be invoked when all data sources have acknowledged that
-  // tracing has started. This callback will be invoked on an internal perfetto
-  // thread.
-  virtual void SetOnStartCallback(std::function<void()>) = 0;
-
-  // This callback can be used to get a notification when some error occured
-  // (e.g., peer disconnection). Error type will be passed as an argument. This
-  // callback will be invoked on an internal perfetto thread.
-  virtual void SetOnErrorCallback(std::function<void(TracingError)>) = 0;
-
-  // Issues a flush request, asking all data sources to ack the request, within
-  // the specified timeout. A "flush" is a fence to ensure visibility of data in
-  // the async tracing pipeline. It guarantees that all data written before the
-  // Flush() call will be visible in the trace buffer and hence by the
-  // ReadTrace() / ReadTraceBlocking() methods.
-  // Args:
-  //  callback: will be invoked on an internal perfetto thread when all data
-  //    sources have acked, or the timeout is reached. The bool argument
-  //    will be true if all data sources acked within the timeout, false if
-  //    the timeout was hit or some other error occurred (e.g. the tracing
-  //    session wasn't started or ended).
-  //  timeout_ms: how much time the service will wait for data source acks. If
-  //    0, the global timeout specified in the TraceConfig (flush_timeout_ms)
-  //    will be used. If flush_timeout_ms is also unspecified, a default value
-  //    of 5s will be used.
-  // Known issues:
-  //    Because flushing is still based on service-side scraping, the very last
-  //    trace packet for each data source thread will not be visible. Fixing
-  //    this requires either propagating the Flush() to the data sources or
-  //    changing the order of atomic operations in the service (b/162206162).
-  //    Until then, a workaround is to make sure to call
-  //    DataSource::Trace([](TraceContext ctx) { ctx.Flush(); }) just before
-  //    stopping, on each thread where DataSource::Trace has been previously
-  //    called.
-  virtual void Flush(std::function<void(bool)>, uint32_t timeout_ms = 0) = 0;
-
-  // Blocking version of Flush(). Waits until all data sources have acked and
-  // returns the success/failure status.
-  bool FlushBlocking(uint32_t timeout_ms = 0);
-
   // Disable tracing asynchronously.
   // Use SetOnStopCallback() to get a notification when the tracing session is
   // fully stopped and all data sources have acked.
@@ -260,12 +184,6 @@
   // This callback will be invoked on an internal perfetto thread.
   virtual void SetOnStopCallback(std::function<void()>) = 0;
 
-  // Changes the TraceConfig for an active tracing session. The session must
-  // have been configured and started before. Note that the tracing service
-  // only supports changing a subset of TraceConfig fields,
-  // see ConsumerEndpoint::ChangeTraceConfig().
-  virtual void ChangeTraceConfig(const TraceConfig&) = 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
@@ -283,13 +201,8 @@
 
   // 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. If this is called before the end of the trace (i.e. before
-  // Stop() / StopBlocking()), in almost all cases you need to call
-  // Flush() / FlushBlocking() before Read(). This is to guarantee that tracing
-  // data in-flight in the data sources is committed into the tracing buffers
-  // before reading them.
-  // Reading the trace data is a destructive operation w.r.t. contents of the
-  // trace buffer and is not idempotent.
+  // 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 false.
   using ReadTraceCallback = std::function<void(ReadTraceCallbackArgs)>;
@@ -299,53 +212,6 @@
   // the trace contents are read. This is slow and inefficient (involves more
   // copies) and is mainly intended for testing.
   std::vector<char> ReadTraceBlocking();
-
-  // Struct passed as an argument to the callback for GetTraceStats(). Contains
-  // statistics about the tracing session.
-  struct GetTraceStatsCallbackArgs {
-    // Whether or not querying statistics succeeded.
-    bool success = false;
-    // Serialized TraceStats protobuf message. To decode:
-    //
-    //   perfetto::protos::gen::TraceStats trace_stats;
-    //   trace_stats.ParseFromArray(args.trace_stats_data.data(),
-    //                              args.trace_stats_data.size());
-    //
-    std::vector<uint8_t> trace_stats_data;
-  };
-
-  // Requests a snapshot of statistical data for this tracing session. Only one
-  // query may be active at a time. This callback will be invoked on an internal
-  // perfetto thread.
-  using GetTraceStatsCallback = std::function<void(GetTraceStatsCallbackArgs)>;
-  virtual void GetTraceStats(GetTraceStatsCallback) = 0;
-
-  // Synchronous version of GetTraceStats() for convenience.
-  GetTraceStatsCallbackArgs GetTraceStatsBlocking();
-
-  // Struct passed as an argument to the callback for QueryServiceState().
-  // Contains information about registered data sources.
-  struct QueryServiceStateCallbackArgs {
-    // Whether or not getting the service state succeeded.
-    bool success = false;
-    // Serialized TracingServiceState protobuf message. To decode:
-    //
-    //   perfetto::protos::gen::TracingServiceState state;
-    //   state.ParseFromArray(args.service_state_data.data(),
-    //                        args.service_state_data.size());
-    //
-    std::vector<uint8_t> service_state_data;
-  };
-
-  // Requests a snapshot of the tracing service state for this session. Only one
-  // request per session may be active at a time. This callback will be invoked
-  // on an internal perfetto thread.
-  using QueryServiceStateCallback =
-      std::function<void(QueryServiceStateCallbackArgs)>;
-  virtual void QueryServiceState(QueryServiceStateCallback) = 0;
-
-  // Synchronous version of QueryServiceState() for convenience.
-  QueryServiceStateCallbackArgs QueryServiceStateBlocking();
 };
 
 }  // namespace perfetto
diff --git a/include/perfetto/tracing/tracing_policy.h b/include/perfetto/tracing/tracing_policy.h
deleted file mode 100644
index bd93666..0000000
--- a/include/perfetto/tracing/tracing_policy.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_POLICY_H_
-#define INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
-
-#include <functional>
-
-#include "perfetto/base/export.h"
-#include "perfetto/tracing/backend_type.h"
-
-namespace perfetto {
-
-// Applies policy decisions, such as allowing or denying connections, when
-// certain tracing SDK events occur. All methods are called on an internal
-// perfetto thread.
-class PERFETTO_EXPORT TracingPolicy {
- public:
-  virtual ~TracingPolicy();
-
-  // Called when the current process attempts to connect a new consumer to the
-  // backend of |backend_type| to check if the connection should be allowed. Its
-  // implementation should execute |result_callback| with the result of the
-  // check (synchronuosly or asynchronously on any thread). If the result is
-  // false, the consumer connection is aborted. Chrome uses this to restrict
-  // creating (system) tracing sessions based on an enterprise policy.
-  struct ShouldAllowConsumerSessionArgs {
-    BackendType backend_type;
-    std::function<void(bool /*allow*/)> result_callback;
-  };
-  virtual void ShouldAllowConsumerSession(
-      const ShouldAllowConsumerSessionArgs&) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_
diff --git a/include/perfetto/tracing/track.h b/include/perfetto/tracing/track.h
index 0ff225d..0a4697b 100644
--- a/include/perfetto/tracing/track.h
+++ b/include/perfetto/tracing/track.h
@@ -22,9 +22,7 @@
 #include "perfetto/base/thread_utils.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/internal/compile_time_hash.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
 #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
 
@@ -87,7 +85,7 @@
   // To minimize the chances for accidental id collisions across processes, the
   // track's effective uuid is generated by xorring |id| with a random,
   // per-process cookie.
-  explicit constexpr Track(uint64_t id, Track parent = MakeProcessTrack())
+  explicit Track(uint64_t id, Track parent = MakeProcessTrack())
       : uuid(id ^ parent.uuid), parent_uuid(parent.uuid) {}
 
   explicit operator bool() const { return uuid; }
@@ -100,21 +98,7 @@
   // accidental clashes with track identifiers emitted by other producers.
   static Track Global(uint64_t id) { return Track(id, Track()); }
 
-  // Construct a track using |ptr| as identifier.
-  static Track FromPointer(const void* ptr, Track parent = MakeProcessTrack()) {
-    // Using pointers as global TrackIds isn't supported as pointers are
-    // per-proccess and the same pointer value can be used in different
-    // processes.
-    PERFETTO_DCHECK(parent.uuid != Track().uuid);
-
-    return Track(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)),
-                 parent);
-  }
-
  protected:
-  constexpr Track(uint64_t uuid_, uint64_t parent_uuid_)
-      : uuid(uuid_), parent_uuid(parent_uuid_) {}
-
   static Track MakeThreadTrack(base::PlatformThreadId tid) {
     // If tid were 0 here (which is an invalid tid), we would create a thread
     // track with a uuid that conflicts with the corresponding ProcessTrack.
@@ -124,12 +108,6 @@
 
   static Track MakeProcessTrack() { return Track(process_uuid, Track()); }
 
-  static constexpr inline uint64_t CompileTimeHash(const char* string) {
-    return internal::CompileTimeHash()
-        .Update(string, static_cast<size_t>(base::StrEnd(string) - string))
-        .digest();
-  }
-
  private:
   friend class internal::TrackRegistry;
   static uint64_t process_uuid;
@@ -173,110 +151,6 @@
         tid(tid_) {}
 };
 
-// A track for recording counter values with the TRACE_COUNTER macro. Counter
-// tracks can optionally be given units and other metadata. See
-// /protos/perfetto/trace/track_event/counter_descriptor.proto for details.
-class CounterTrack : public Track {
-  // A random value mixed into counter track uuids to avoid collisions with
-  // other types of tracks.
-  static constexpr uint64_t kCounterMagic = 0xb1a4a67d7970839eul;
-
- public:
-  using Unit = perfetto::protos::pbzero::CounterDescriptor::Unit;
-
-  // |name| must be a string with static lifetime.
-  constexpr explicit CounterTrack(const char* name,
-                                  Track parent = MakeProcessTrack())
-      : Track(CompileTimeHash(name) ^ kCounterMagic, parent),
-        name_(name),
-        category_(nullptr) {}
-
-  // |unit_name| is a free-form description of the unit used by this counter. It
-  // must have static lifetime.
-  constexpr CounterTrack(const char* name,
-                         const char* unit_name,
-                         Track parent = MakeProcessTrack())
-      : Track(CompileTimeHash(name) ^ kCounterMagic, parent),
-        name_(name),
-        category_(nullptr),
-        unit_name_(unit_name) {}
-
-  constexpr CounterTrack(const char* name,
-                         Unit unit,
-                         Track parent = MakeProcessTrack())
-      : Track(CompileTimeHash(name) ^ kCounterMagic, parent),
-        name_(name),
-        category_(nullptr),
-        unit_(unit) {}
-
-  static constexpr CounterTrack Global(const char* name,
-                                       const char* unit_name) {
-    return CounterTrack(name, unit_name, Track());
-  }
-
-  static constexpr CounterTrack Global(const char* name, Unit unit) {
-    return CounterTrack(name, unit, Track());
-  }
-
-  static constexpr CounterTrack Global(const char* name) {
-    return Global(name, nullptr);
-  }
-
-  constexpr CounterTrack set_unit(Unit unit) const {
-    return CounterTrack(uuid, parent_uuid, name_, category_, unit, unit_name_,
-                        unit_multiplier_, is_incremental_);
-  }
-
-  constexpr CounterTrack set_unit_name(const char* unit_name) const {
-    return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name,
-                        unit_multiplier_, is_incremental_);
-  }
-
-  constexpr CounterTrack set_unit_multiplier(int64_t unit_multiplier) const {
-    return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
-                        unit_multiplier, is_incremental_);
-  }
-
-  constexpr CounterTrack set_category(const char* category) const {
-    return CounterTrack(uuid, parent_uuid, name_, category, unit_, unit_name_,
-                        unit_multiplier_, is_incremental_);
-  }
-
-  void Serialize(protos::pbzero::TrackDescriptor*) const;
-  protos::gen::TrackDescriptor Serialize() const;
-
- private:
-  constexpr CounterTrack(uint64_t uuid_,
-                         uint64_t parent_uuid_,
-                         const char* name,
-                         const char* category,
-                         Unit unit,
-                         const char* unit_name,
-                         int64_t unit_multiplier,
-                         bool is_incremental)
-      : Track(uuid_, parent_uuid_),
-        name_(name),
-        category_(category),
-        unit_(unit),
-        unit_name_(unit_name),
-        unit_multiplier_(unit_multiplier),
-        is_incremental_(is_incremental) {}
-
-  // TODO(skyostil): Expose incremental counters once we decide how to manage
-  // their incremental state.
-  constexpr CounterTrack set_is_incremental(bool is_incremental = true) const {
-    return CounterTrack(uuid, parent_uuid, name_, category_, unit_, unit_name_,
-                        unit_multiplier_, is_incremental);
-  }
-
-  const char* const name_;
-  const char* const category_;
-  Unit unit_ = perfetto::protos::pbzero::CounterDescriptor::UNIT_UNSPECIFIED;
-  const char* const unit_name_ = nullptr;
-  int64_t unit_multiplier_ = 1;
-  bool is_incremental_ = false;
-};
-
 namespace internal {
 
 // Keeps a map of uuids to serialized track descriptors and provides a
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 7e226f0..8eebf76 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -21,7 +21,6 @@
 #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/string_helpers.h"
 #include "perfetto/tracing/track.h"
 #include "perfetto/tracing/track_event_category_registry.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
@@ -152,6 +151,32 @@
 }  // namespace internal
 }  // namespace PERFETTO_TRACK_EVENT_NAMESPACE
 
+namespace perfetto {
+
+// A wrapper for marking strings that can't be determined to be static at build
+// time, but are in fact static.
+class PERFETTO_EXPORT StaticString final {
+ public:
+  const char* value;
+
+  operator const char*() const { return value; }
+};
+
+namespace internal {
+
+template <typename T = void>
+constexpr bool IsStaticString(const char*) {
+  return true;
+}
+
+template <typename T = void>
+constexpr bool IsStaticString(...) {
+  return false;
+}
+
+}  // namespace internal
+}  // namespace perfetto
+
 // Normally all categories are defined statically at build-time (see
 // PERFETTO_DEFINE_CATEGORIES). However, some categories are only used for
 // testing, and we shouldn't publish them to the tracing service or include them
@@ -193,9 +218,36 @@
       perfetto::internal::TrackEventDataSourceTraits)
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
+
+// Ensure that |string| is a static constant string.
+//
+// If you get a compiler failure here, you are most likely trying to use
+// TRACE_EVENT with a dynamic event name. There are two ways to fix this:
+//
+// 1) If the event name is actually dynamic (e.g., std::string), write it into
+//    the event manually:
+//
+//      TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
+//        ctx.event()->set_name(dynamic_name);
+//      });
+//
+// 2) If the name is static, but the pointer is computed at runtime, wrap it
+//    with perfetto::StaticString:
+//
+//      TRACE_EVENT("category", perfetto::StaticString{name});
+//
+//    DANGER: Using perfetto::StaticString with strings whose contents change
+//            dynamically can cause silent trace data corruption.
+//
+#define PERFETTO_GET_STATIC_STRING(string)                                 \
+  [&]() {                                                                  \
+    static_assert(                                                         \
+        std::is_same<decltype(string), ::perfetto::StaticString>::value || \
+            ::perfetto::internal::IsStaticString(string),                  \
+        "String must be static");                                          \
+    return static_cast<const char*>(string);                               \
+  }()
 
 // Begin a slice under |category| with the title |name|. Both strings must be
 // static constants. The track event is only recorded if |category| is enabled
@@ -212,93 +264,15 @@
 //    ctx.event()->set_name(dynamic_name);
 //  });
 //
-// The following optional arguments can be passed to `TRACE_EVENT` to add extra
-// information to events:
-//
-// TRACE_EVENT("cat", "name"[, track][, timestamp]
-//                          [, "debug_name1", debug_value1]
-//                          [, "debug_name2", debug_value2]
-//                          ...
-//                          [, "debug_nameN", debug_valueN]
-//                          [, lambda]);
-//
-// Some examples of valid combinations:
-//
-// 1. A lambda for writing custom TrackEvent fields:
-//
-//   TRACE_EVENT("category", "Name", [&](perfetto::EventContext ctx) {
-//     ctx.event()->set_custom_value(...);
-//   });
-//
-// 2. A timestamp and a lambda:
-//
-//   TRACE_EVENT("category", "Name", time_in_nanoseconds,
-//       [&](perfetto::EventContext ctx) {
-//     ctx.event()->set_custom_value(...);
-//   });
-//
-//   |time_in_nanoseconds| should be an uint64_t by default. To support custom
-//   timestamp types,
-//   |perfetto::TraceTimestampTraits<T>::ConvertTimestampToTraceTimeNs|
-//   should be defined. See |ConvertTimestampToTraceTimeNs| for more details.
-//
-// 3. Arbitrary number of debug annotations:
-//
-//   TRACE_EVENT("category", "Name", "arg", value);
-//   TRACE_EVENT("category", "Name", "arg", value, "arg2", value2);
-//   TRACE_EVENT("category", "Name", "arg", value, "arg2", value2,
-//                                   "arg3", value3);
-//
-//   See |TracedValue| for recording custom types as debug annotations.
-//
-// 4. Arbitrary number of debug annotations and a lambda:
-//
-//   TRACE_EVENT("category", "Name", "arg", value,
-//       [&](perfetto::EventContext ctx) {
-//     ctx.event()->set_custom_value(...);
-//   });
-//
-// 5. An overridden track:
-//
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234));
-//
-//   See |Track| for other types of tracks which may be used.
-//
-// 6. A track and a lambda:
-//
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234),
-//       [&](perfetto::EventContext ctx) {
-//     ctx.event()->set_custom_value(...);
-//   });
-//
-// 7. A track and a timestamp:
-//
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234),
-//       time_in_nanoseconds);
-//
-// 8. A track, a timestamp and a lambda:
-//
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234),
-//       time_in_nanoseconds, [&](perfetto::EventContext ctx) {
-//     ctx.event()->set_custom_value(...);
-//   });
-//
-// 9. A track and an arbitrary number of debug annotions:
-//
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234),
-//               "arg", value);
-//   TRACE_EVENT("category", "Name", perfetto::Track(1234),
-//               "arg", value, "arg2", value2);
-//
-#define TRACE_EVENT_BEGIN(category, name, ...)               \
-  PERFETTO_INTERNAL_TRACK_EVENT(                             \
-      category, ::perfetto::internal::GetStaticString(name), \
+#define TRACE_EVENT_BEGIN(category, name, ...)    \
+  PERFETTO_INTERNAL_TRACK_EVENT(                  \
+      category, PERFETTO_GET_STATIC_STRING(name), \
       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
 
 // End a slice under |category|.
 #define TRACE_EVENT_END(category, ...) \
   PERFETTO_INTERNAL_TRACK_EVENT(       \
-      category, /*name=*/nullptr,      \
+      category, nullptr,               \
       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
 
 // Begin a slice which gets automatically closed when going out of scope.
@@ -306,9 +280,9 @@
   PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
 
 // Emit a slice which has zero duration.
-#define TRACE_EVENT_INSTANT(category, name, ...)             \
-  PERFETTO_INTERNAL_TRACK_EVENT(                             \
-      category, ::perfetto::internal::GetStaticString(name), \
+#define TRACE_EVENT_INSTANT(category, name, ...)  \
+  PERFETTO_INTERNAL_TRACK_EVENT(                  \
+      category, PERFETTO_GET_STATIC_STRING(name), \
       ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
 
 // Efficiently determine if the given static or dynamic trace category or
@@ -316,49 +290,7 @@
 #define TRACE_EVENT_CATEGORY_ENABLED(category) \
   PERFETTO_INTERNAL_CATEGORY_ENABLED(category)
 
-// Time-varying numeric data can be recorded with the TRACE_COUNTER macro:
-//
-//   TRACE_COUNTER("cat", counter_track[, timestamp], value);
-//
-// For example, to record a single value for a counter called "MyCounter":
-//
-//   TRACE_COUNTER("category", "MyCounter", 1234.5);
-//
-// This data is displayed as a counter track in the Perfetto UI.
-//
-// Both integer and floating point counter values are supported. Counters can
-// also be annotated with additional information such as units, for example, for
-// tracking the rendering framerate in terms of frames per second or "fps":
-//
-//   TRACE_COUNTER("category", perfetto::CounterTrack("Framerate", "fps"), 120);
-//
-// As another example, a memory counter that records bytes but accepts samples
-// as kilobytes (to reduce trace binary size) can be defined like this:
-//
-//   perfetto::CounterTrack memory_track = perfetto::CounterTrack("Memory")
-//       .set_unit("bytes")
-//       .set_multiplier(1024);
-//   TRACE_COUNTER("category", memory_track, 4 /* = 4096 bytes */);
-//
-// See /protos/perfetto/trace/track_event/counter_descriptor.proto
-// for the full set of attributes for a counter track.
-//
-// To record a counter value at a specific point in time (instead of the current
-// time), you can pass in a custom timestamp:
-//
-//   // First record the current time and counter value.
-//   uint64_t timestamp = perfetto::TrackEvent::GetTraceTimeNs();
-//   int64_t value = 1234;
-//
-//   // Later, emit a sample at that point in time.
-//   TRACE_COUNTER("category", "MyCounter", timestamp, value);
-//
-#define TRACE_COUNTER(category, track, ...)                 \
-  PERFETTO_INTERNAL_TRACK_EVENT(                            \
-      category, /*name=*/nullptr,                           \
-      ::perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER, \
-      ::perfetto::CounterTrack(track), ##__VA_ARGS__)
-
 // TODO(skyostil): Add flow 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
index 8b9d8f5..e51c4d6 100644
--- a/include/perfetto/tracing/track_event_category_registry.h
+++ b/include/perfetto/tracing/track_event_category_registry.h
@@ -207,10 +207,7 @@
   size_t category_count() const { return category_count_; }
 
   // Returns a category based on its index.
-  const Category* GetCategory(size_t index) const {
-    PERFETTO_DCHECK(index < category_count_);
-    return &categories_[index];
-  }
+  const Category* GetCategory(size_t index) const;
 
   // Turn tracing on or off for the given category in a track event data source
   // instance.
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
index 1afcdd0..cce2665 100644
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ b/include/perfetto/tracing/track_event_interned_data_index.h
@@ -208,21 +208,6 @@
               "%s. New type: %s.",
               entry.second->type_id_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
         }
-        // If an interned data index is defined in an anonymous namespace, we
-        // can end up with multiple copies of it in the same program. Because
-        // they will all share a memory address through TLS, this can lead to
-        // subtle data corruption if all the copies aren't exactly identical.
-        // Try to detect this by checking if the Add() function address remains
-        // constant.
-        if (reinterpret_cast<void*>(&InternedDataType::Add) !=
-            entry.second->add_function_ptr_) {
-          PERFETTO_FATAL(
-              "Inconsistent interned data index. Maybe the index was defined "
-              "in an anonymous namespace in a header or copied to multiple "
-              "files? Duplicate index definitions can lead to memory "
-              "corruption! Type id: %s",
-              entry.second->type_id_);
-        }
 #endif  // PERFETTO_DCHECK_IS_ON()
         return reinterpret_cast<InternedDataType*>(entry.second.get());
       }
@@ -234,8 +219,6 @@
         entry.second.reset(new InternedDataType());
 #if PERFETTO_DCHECK_IS_ON()
         entry.second->type_id_ = PERFETTO_DEBUG_FUNCTION_IDENTIFIER();
-        entry.second->add_function_ptr_ =
-            reinterpret_cast<void*>(&InternedDataType::Add);
 #endif  // PERFETTO_DCHECK_IS_ON()
         return reinterpret_cast<InternedDataType*>(entry.second.get());
       }
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index cd86510..394f431 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -32,9 +32,7 @@
 #endif
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
 
 // ----------------------------------------------------------------------------
 // Constants.
@@ -146,7 +144,6 @@
 static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
 static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
 static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
-static constexpr uint8_t TRACE_VALUE_TYPE_PROTO = 9;
 
 // Enum reflecting the scope of an INSTANT event. Must fit within
 // TRACE_EVENT_FLAG_SCOPE_MASK.
@@ -177,14 +174,25 @@
 //   #define TRACE_TIME_TICKS_NOW() ...
 //   #define TRACE_TIME_NOW() ...
 
-// User-provided function to convert an abstract thread id into a thread track.
+// User-provided function to convert an abstract thread id into either a track
+// uuid or a pid/tid override. Return true if the conversion succeeded.
 template <typename T>
-ThreadTrack ConvertThreadId(const T&);
+bool ConvertThreadId(const T&,
+                     uint64_t* track_uuid_out,
+                     int32_t* pid_override_out,
+                     int32_t* tid_override_out);
+
+// User-provided function to convert an abstract timestamp into the trace clock
+// timebase in nanoseconds.
+template <typename T>
+uint64_t ConvertTimestampToTraceTimeNs(const T&);
 
 // Built-in implementation for events referring to the current thread.
 template <>
-ThreadTrack PERFETTO_EXPORT
-ConvertThreadId(const PerfettoLegacyCurrentThreadId&);
+bool PERFETTO_EXPORT ConvertThreadId(const PerfettoLegacyCurrentThreadId&,
+                                     uint64_t*,
+                                     int32_t*,
+                                     int32_t*);
 
 }  // namespace legacy
 
@@ -250,7 +258,7 @@
     uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
   };
 
-  explicit LegacyTraceId(const void* raw_id)
+  LegacyTraceId(const void* raw_id)
       : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
     id_flags_ = legacy::kTraceEventFlagHasLocalId;
   }
@@ -326,6 +334,7 @@
                                uint32_t flags,
                                Args&&... args) PERFETTO_NO_INLINE {
     AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+    SetTrackIfNeeded(&ctx, flags);
     if (NeedLegacyFlags(phase, flags)) {
       auto legacy_event = ctx.event()->set_legacy_event();
       SetLegacyFlags(legacy_event, phase, flags);
@@ -345,28 +354,38 @@
     // 1. If we have an id, we need to write {unscoped,local,global}_id and/or
     //    bind_id.
     // 2. If we have a thread id, we need to write track_uuid() or
-    //    {pid,tid}_override if the id represents another process.  The
-    //    conversion from |thread_id| happens in embedder code since the type is
-    //    embedder-specified.
+    //    {pid,tid}_override. This happens in embedder code since the thread id
+    //    is embedder-specified.
     // 3. If we have a timestamp, we need to write a different timestamp in the
     //    trace packet itself and make sure TrackEvent won't write one
     //    internally. This is already done at the call site.
     //
     flags |= id.id_flags();
     AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
-    if (NeedLegacyFlags(phase, flags)) {
+    int32_t pid_override = 0;
+    int32_t tid_override = 0;
+    uint64_t track_uuid = 0;
+    if (legacy::ConvertThreadId(thread_id, &track_uuid, &pid_override,
+                                &tid_override) &&
+        track_uuid) {
+      if (track_uuid != ThreadTrack::Current().uuid)
+        ctx.event()->set_track_uuid(track_uuid);
+    } else if (pid_override || tid_override) {
+      // Explicitly clear the track so the overrides below take effect.
+      ctx.event()->set_track_uuid(0);
+    } else {
+      // No pid/tid/track overrides => obey the flags instead.
+      SetTrackIfNeeded(&ctx, flags);
+    }
+    if (NeedLegacyFlags(phase, flags) || pid_override || tid_override) {
       auto legacy_event = ctx.event()->set_legacy_event();
       SetLegacyFlags(legacy_event, phase, flags);
       if (id.id_flags())
         id.Write(legacy_event, flags);
-      if (flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) {
-        // The thread identifier actually represents a process id. Let's set an
-        // override for it.
-        int32_t pid_override =
-            static_cast<int32_t>(legacy::ConvertThreadId(thread_id).tid);
+      if (pid_override)
         legacy_event->set_pid_override(pid_override);
-        legacy_event->set_tid_override(-1);
-      }
+      if (tid_override)
+        legacy_event->set_tid_override(tid_override);
     }
   }
 
@@ -393,19 +412,37 @@
   }
 
  private:
+  static void SetTrackIfNeeded(EventContext* ctx, uint32_t flags) {
+    // Note: This avoids the need to set LegacyEvent::instant_event_scope.
+    auto scope = flags & TRACE_EVENT_FLAG_SCOPE_MASK;
+    switch (scope) {
+      case TRACE_EVENT_SCOPE_GLOBAL:
+        ctx->event()->set_track_uuid(0);
+        break;
+      case TRACE_EVENT_SCOPE_PROCESS:
+        ctx->event()->set_track_uuid(ProcessTrack::Current().uuid);
+        break;
+      default:
+      case TRACE_EVENT_SCOPE_THREAD:
+        // Thread scope is already the default.
+        break;
+    }
+  }
+
   static bool NeedLegacyFlags(char phase, uint32_t flags) {
     if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
       return true;
     // TODO(skyostil): Implement/deprecate:
     // - TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
     // - TRACE_EVENT_FLAG_HAS_CONTEXT_ID
+    // - TRACE_EVENT_FLAG_HAS_PROCESS_ID
     // - TRACE_EVENT_FLAG_TYPED_PROTO_ARGS
     // - TRACE_EVENT_FLAG_JAVA_STRING_LITERALS
     return flags &
            (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
             TRACE_EVENT_FLAG_HAS_GLOBAL_ID | TRACE_EVENT_FLAG_ASYNC_TTS |
             TRACE_EVENT_FLAG_BIND_TO_ENCLOSING | TRACE_EVENT_FLAG_FLOW_IN |
-            TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
+            TRACE_EVENT_FLAG_FLOW_OUT);
   }
 
   static void SetLegacyFlags(
@@ -440,125 +477,71 @@
 
 // Implementations for the INTERNAL_* adapter macros used by the trace points
 // below.
-#define PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(phase, category, name, track, \
-                                                ...)                          \
-  PERFETTO_INTERNAL_TRACK_EVENT(                                              \
-      category,                                                               \
-      ::perfetto::internal::GetStaticString(::perfetto::StaticString{name}),  \
-      ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track,      \
-      ##__VA_ARGS__);
-
-// The main entrypoint for writing unscoped legacy events.  This macro
-// determines the right track to write the event on based on |flags| and
-// |thread_id|.
-#define PERFETTO_INTERNAL_LEGACY_EVENT(phase, category, name, flags,         \
-                                       thread_id, ...)                       \
-  [&]() {                                                                    \
-    constexpr auto& kDefaultTrack =                                          \
-        ::perfetto::internal::TrackEventInternal::kDefaultTrack;             \
-    /* First check the scope for instant events. */                          \
-    if ((phase) == TRACE_EVENT_PHASE_INSTANT) {                              \
-      /* Note: Avoids the need to set LegacyEvent::instant_event_scope. */   \
-      auto scope = (flags)&TRACE_EVENT_FLAG_SCOPE_MASK;                      \
-      switch (scope) {                                                       \
-        case TRACE_EVENT_SCOPE_GLOBAL:                                       \
-          PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(                           \
-              phase, category, name, ::perfetto::Track::Global(0),           \
-              ##__VA_ARGS__);                                                \
-          return;                                                            \
-        case TRACE_EVENT_SCOPE_PROCESS:                                      \
-          PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(                           \
-              phase, category, name, ::perfetto::ProcessTrack::Current(),    \
-              ##__VA_ARGS__);                                                \
-          return;                                                            \
-        default:                                                             \
-        case TRACE_EVENT_SCOPE_THREAD:                                       \
-          /* Fallthrough. */                                                 \
-          break;                                                             \
-      }                                                                      \
-    }                                                                        \
-    /* If an event targets the current thread or another process, write      \
-     * it on the current thread's track. The process override case is        \
-     * handled through |pid_override| in WriteLegacyEvent. */                \
-    if (std::is_same<                                                        \
-            decltype(thread_id),                                             \
-            ::perfetto::legacy::PerfettoLegacyCurrentThreadId>::value ||     \
-        ((flags)&TRACE_EVENT_FLAG_HAS_PROCESS_ID)) {                         \
-      PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(phase, category, name,         \
-                                              kDefaultTrack, ##__VA_ARGS__); \
-    } else {                                                                 \
-      PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(                               \
-          phase, category, name,                                             \
-          ::perfetto::legacy::ConvertThreadId(thread_id), ##__VA_ARGS__);    \
-    }                                                                        \
-  }()
-
-#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...)        \
-  PERFETTO_INTERNAL_LEGACY_EVENT(                                          \
-      phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId,  \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
-        using ::perfetto::internal::TrackEventLegacy;                      \
-        TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags,   \
-                                           ##__VA_ARGS__);                 \
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...)      \
+  PERFETTO_INTERNAL_TRACK_EVENT(                                         \
+      category, ::perfetto::StaticString{name},                          \
+      ::perfetto::internal::TrackEventLegacy::PhaseToType(phase),        \
+      [&](perfetto::EventContext ctx) {                                  \
+        using ::perfetto::internal::TrackEventLegacy;                    \
+        TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags, \
+                                           ##__VA_ARGS__);               \
       })
 
-// PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
-// uses TRACE_EVENT_BEGIN/END internally, which already have this call.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...)               \
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...)        \
+  PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                             \
+      category, ::perfetto::StaticString{name},                     \
+      [&](perfetto::EventContext ctx) {                             \
+        using ::perfetto::internal::TrackEventLegacy;               \
+        TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__); \
+      })
+
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id, \
+                                                  flags, ...)              \
   PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                                    \
       category, ::perfetto::StaticString{name},                            \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
+      [&](perfetto::EventContext ctx) {                                    \
         using ::perfetto::internal::TrackEventLegacy;                      \
-        TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__);        \
+        ::perfetto::internal::LegacyTraceId trace_id{bind_id};             \
+        TrackEventLegacy::WriteLegacyEventWithIdAndTid(                    \
+            std::move(ctx), TRACE_EVENT_PHASE_BEGIN, flags, trace_id,      \
+            TRACE_EVENT_API_CURRENT_THREAD_ID, ##__VA_ARGS__);             \
       })
 
-// PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
-// uses TRACE_EVENT_BEGIN/END internally, which already have this call.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id,   \
-                                                  flags, ...)                \
-  PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                                      \
-      category, ::perfetto::StaticString{name},                              \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {   \
-        using ::perfetto::internal::TrackEventLegacy;                        \
-        ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){bind_id}; \
-        TrackEventLegacy::WriteLegacyEventWithIdAndTid(                      \
-            std::move(ctx), TRACE_EVENT_PHASE_BEGIN, flags,                  \
-            PERFETTO_UID(trace_id), TRACE_EVENT_API_CURRENT_THREAD_ID,       \
-            ##__VA_ARGS__);                                                  \
+#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name,   \
+                                                timestamp, flags, ...)   \
+  PERFETTO_INTERNAL_TRACK_EVENT(                                         \
+      category, ::perfetto::StaticString{name},                          \
+      ::perfetto::internal::TrackEventLegacy::PhaseToType(phase),        \
+      ::perfetto::legacy::ConvertTimestampToTraceTimeNs(timestamp),      \
+      [&](perfetto::EventContext ctx) {                                  \
+        using ::perfetto::internal::TrackEventLegacy;                    \
+        TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags, \
+                                           ##__VA_ARGS__);               \
       })
 
-#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name,     \
-                                                timestamp, flags, ...)     \
-  PERFETTO_INTERNAL_LEGACY_EVENT(                                          \
-      phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId,  \
-      timestamp,                                                           \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
-        using ::perfetto::internal::TrackEventLegacy;                      \
-        TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags,   \
-                                           ##__VA_ARGS__);                 \
-      })
-
-#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                  \
-    phase, category, name, id, thread_id, timestamp, flags, ...)             \
-  PERFETTO_INTERNAL_LEGACY_EVENT(                                            \
-      phase, category, name, flags, thread_id, timestamp,                    \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {   \
-        using ::perfetto::internal::TrackEventLegacy;                        \
-        ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){id};      \
-        TrackEventLegacy::WriteLegacyEventWithIdAndTid(                      \
-            std::move(ctx), phase, flags, PERFETTO_UID(trace_id), thread_id, \
-            ##__VA_ARGS__);                                                  \
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                    \
+    phase, category, name, id, thread_id, timestamp, flags, ...)               \
+  PERFETTO_INTERNAL_TRACK_EVENT(                                               \
+      category, ::perfetto::StaticString{name},                                \
+      ::perfetto::internal::TrackEventLegacy::PhaseToType(phase),              \
+      ::perfetto::legacy::ConvertTimestampToTraceTimeNs(timestamp),            \
+      [&](perfetto::EventContext ctx) {                                        \
+        using ::perfetto::internal::TrackEventLegacy;                          \
+        ::perfetto::internal::LegacyTraceId trace_id{id};                      \
+        TrackEventLegacy::WriteLegacyEventWithIdAndTid(                        \
+            std::move(ctx), phase, flags, trace_id, thread_id, ##__VA_ARGS__); \
       })
 
 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
                                          ...)                              \
-  PERFETTO_INTERNAL_LEGACY_EVENT(                                          \
-      phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId,  \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
+  PERFETTO_INTERNAL_TRACK_EVENT(                                           \
+      category, ::perfetto::StaticString{name},                            \
+      ::perfetto::internal::TrackEventLegacy::PhaseToType(phase),          \
+      [&](perfetto::EventContext ctx) {                                    \
         using ::perfetto::internal::TrackEventLegacy;                      \
-        ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){id};    \
+        ::perfetto::internal::LegacyTraceId trace_id{id};                  \
         TrackEventLegacy::WriteLegacyEventWithIdAndTid(                    \
-            std::move(ctx), phase, flags, PERFETTO_UID(trace_id),          \
+            std::move(ctx), phase, flags, trace_id,                        \
             TRACE_EVENT_API_CURRENT_THREAD_ID, ##__VA_ARGS__);             \
       })
 
@@ -1004,12 +987,6 @@
   INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                            \
       TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id,        \
       TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
-#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(                  \
-    category_group, name, id, timestamp, arg1_name, arg1_val)              \
-  INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                      \
-      TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id,    \
-      TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
-      arg1_name, arg1_val)
 
 // Async end events.
 #define TRACE_EVENT_NESTABLE_ASYNC_END0(category_group, name, id)        \
@@ -1095,13 +1072,101 @@
   INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                 \
       TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
       TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY)
-#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP2(                    \
-    category_group, name, id, timestamp, arg1_name, arg1_val, arg2_name,   \
-    arg2_val)                                                              \
-  INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                      \
-      TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id,      \
-      TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
-      arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Legacy flow events.
+#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id)        \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+                                   category_group, name, id,     \
+                                   TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN,               \
+                                   category_group, name, id,                   \
+                                   TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \
+                                arg2_name, arg2_val)                           \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                            \
+      TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id,                  \
+      TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id)   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+                                   category_group, name, id,     \
+                                   TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \
+                                     arg1_val)                            \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN,          \
+                                   category_group, name, id,              \
+                                   TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \
+                                     arg1_val, arg2_name, arg2_val)       \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                       \
+      TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id,             \
+      TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Legacy flow step events.
+#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step)  \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+                                   category_group, name, id,    \
+                                   TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, arg1_name, \
+                               arg1_val)                                  \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                       \
+      TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id,              \
+      TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP,     \
+                                   category_group, name, id,        \
+                                   TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, arg1_name, \
+                                    arg1_val)                                  \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                            \
+      TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id,                   \
+      TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val)
+
+// Legacy flow end events.
+#define TRACE_EVENT_FLOW_END0(category_group, name, id)                        \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0(category_group, name, id)      \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id,                                   \
+                                   TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
+#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val)   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+                                   arg1_val)
+#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val,   \
+                              arg2_name, arg2_val)                             \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+                                   arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id)                   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name,        \
+                                   arg1_val)                                   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \
+                                   arg1_val)
+#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name,        \
+                                   arg1_val, arg2_name, arg2_val)              \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+                                   name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \
+                                   arg1_val, arg2_name, arg2_val)
+
+// Special strongly typed trace events.
+// TODO(skyostil): Migrate these to regular track event trace points.
+#define TRACE_TASK_EXECUTION(run_function, task) \
+  if (false) {                                   \
+    base::ignore_result(run_function);           \
+    base::ignore_result(task);                   \
+  }
+
+#define TRACE_LOG_MESSAGE(file, message, line) \
+  if (false) {                                 \
+    base::ignore_result(file);                 \
+    base::ignore_result(message);              \
+    base::ignore_result(line);                 \
+  }
 
 // Metadata events.
 #define TRACE_EVENT_METADATA1(category_group, name, arg1_name, arg1_val) \
@@ -1151,11 +1216,6 @@
                                    category_group, name, context,   \
                                    TRACE_EVENT_FLAG_NONE)
 
-// TODO(skyostil): Implement binary-efficient trace events.
-#define TRACE_EVENT_BINARY_EFFICIENT0 TRACE_EVENT0
-#define TRACE_EVENT_BINARY_EFFICIENT1 TRACE_EVENT1
-#define TRACE_EVENT_BINARY_EFFICIENT2 TRACE_EVENT2
-
 // Macro to efficiently determine if a given category group is enabled.
 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category, ret) \
   do {                                                    \
@@ -1163,18 +1223,10 @@
   } while (0)
 
 // Macro to efficiently determine, through polling, if a new trace has begun.
-#define TRACE_EVENT_IS_NEW_TRACE(ret)                                \
-  do {                                                               \
-    static int PERFETTO_UID(prev) = -1;                              \
-    int PERFETTO_UID(curr) =                                         \
-        ::perfetto::internal::TrackEventInternal::GetSessionCount(); \
-    if (::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::IsEnabled() && \
-        (PERFETTO_UID(prev) != PERFETTO_UID(curr))) {                \
-      *(ret) = true;                                                 \
-      PERFETTO_UID(prev) = PERFETTO_UID(curr);                       \
-    } else {                                                         \
-      *(ret) = false;                                                \
-    }                                                                \
+// TODO(skyostil): Implement.
+#define TRACE_EVENT_IS_NEW_TRACE(ret) \
+  do {                                \
+    *ret = false;                     \
   } while (0)
 
 // ----------------------------------------------------------------------------
@@ -1203,30 +1255,17 @@
 // non-zero indicates at least one tracing session for this category is active.
 // Note that callers should not make any assumptions at what each bit represents
 // in the status byte. Does not support dynamic categories.
-#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category)                \
-  reinterpret_cast<const uint8_t*>(                                         \
-      [&] {                                                                 \
-        static_assert(                                                      \
-            !std::is_same<::perfetto::DynamicCategory,                      \
-                          decltype(category)>::value,                       \
-            "Enabled flag pointers are not supported for dynamic trace "    \
-            "categories.");                                                 \
-      },                                                                    \
-      PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry  \
-          .GetCategoryState(                                                \
-              ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
-                  .Find(category, /*is_dynamic=*/false)))
-
-// Given a pointer returned by TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED,
-// yields a pointer to the name of the corresponding category group.
-#define TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(category_enabled_ptr)       \
-  ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry    \
-      .GetCategory(                                                         \
-          category_enabled_ptr -                                            \
-          reinterpret_cast<const uint8_t*>(                                 \
-              ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry \
-                  .GetCategoryState(0u)))                                   \
-      ->name
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category)                 \
+  reinterpret_cast<const uint8_t*>(                                          \
+      [&] {                                                                  \
+        static_assert(                                                       \
+            !::PERFETTO_TRACK_EVENT_NAMESPACE::internal::IsDynamicCategory(  \
+                category),                                                   \
+            "Enabled flag pointers are not supported for dynamic trace "     \
+            "categories.");                                                  \
+      },                                                                     \
+      ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry \
+          .GetCategoryState(PERFETTO_GET_CATEGORY_INDEX(category)))
 
 #endif  // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
 
diff --git a/include/perfetto/tracing/track_event_state_tracker.h b/include/perfetto/tracing/track_event_state_tracker.h
deleted file mode 100644
index 7b2437e..0000000
--- a/include/perfetto/tracing/track_event_state_tracker.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
-
-#include "perfetto/base/export.h"
-
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-#include <map>
-#include <string>
-#include <vector>
-
-namespace perfetto {
-namespace protos {
-namespace pbzero {
-class TracePacket_Decoder;
-class TrackEvent;
-class TrackEvent_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-// A helper for keeping track of incremental state when intercepting track
-// events.
-class PERFETTO_EXPORT TrackEventStateTracker {
- public:
-  ~TrackEventStateTracker();
-
-  struct StackFrame {
-    uint64_t timestamp{};
-
-    // Only one of |name| and |name_iid| will be set.
-    std::string name;
-    uint64_t name_iid{};
-    uint64_t name_hash{};
-
-    // Only one of |category| and |category_iid| will be set.
-    std::string category;
-    uint64_t category_iid{};
-  };
-
-  struct Track {
-    uint64_t uuid{};
-    uint32_t index{};  // Ordinal number for the track in the tracing session.
-
-    std::string name;
-    int64_t pid{};
-    int64_t tid{};
-
-    // Opaque user data associated with the track.
-    std::vector<uint8_t> user_data;
-
-    // Stack of opened slices on this track.
-    std::vector<StackFrame> stack;
-  };
-
-  // State for a single trace writer sequence (typically a single thread).
-  struct SequenceState {
-    // Trace packet sequence defaults.
-    Track track;
-
-    // Interned state.
-#if PERFETTO_DCHECK_IS_ON()
-    uint32_t sequence_id{};
-#endif
-    std::map<uint64_t /*iid*/, std::string> event_names;
-    std::map<uint64_t /*iid*/, std::string> event_categories;
-    std::map<uint64_t /*iid*/, std::string> debug_annotation_names;
-  };
-
-  // State for the entire tracing session. Shared by all trace writer sequences
-  // participating in the session.
-  struct SessionState {
-    // Non-thread-bound tracks.
-    std::map<uint64_t /*uuid*/, Track> tracks;
-  };
-
-  // Represents a single decoded track event (without arguments).
-  struct ParsedTrackEvent {
-    explicit ParsedTrackEvent(
-        const perfetto::protos::pbzero::TrackEvent::Decoder&);
-
-    // Underlying event.
-    const perfetto::protos::pbzero::TrackEvent::Decoder& track_event;
-
-    // Event metadata.
-    uint64_t timestamp_ns{};
-    uint64_t duration_ns{};
-
-    size_t stack_depth{};
-
-    protozero::ConstChars category{};
-    protozero::ConstChars name{};
-    uint64_t name_hash{};
-  };
-
-  // Interface used by the tracker to access tracing session and sequence state
-  // and to report parsed track events.
-  class Delegate {
-   public:
-    virtual ~Delegate();
-
-    // Called to retrieve the session-global state shared by all sequences. The
-    // returned pointer must remain valid (locked) throughout the call to
-    // |ProcessTracePacket|.
-    virtual SessionState* GetSessionState() = 0;
-
-    // Called when the metadata (e.g., name) for a track changes. |Track| can be
-    // modified by the callback to attach user data.
-    virtual void OnTrackUpdated(Track&) = 0;
-
-    // If the packet given to |ProcessTracePacket| contains a track event, this
-    // method is called to report the properties of that event. Note that memory
-    // pointers in |TrackEvent| will only be valid during this call.
-    virtual void OnTrackEvent(const Track&, const ParsedTrackEvent&) = 0;
-  };
-
-  // Process a single trace packet, reporting any contained track event back via
-  // the delegate interface. |SequenceState| must correspond to the sequence
-  // that was used to write the packet.
-  static void ProcessTracePacket(Delegate&,
-                                 SequenceState&,
-                                 const protos::pbzero::TracePacket_Decoder&);
-
- private:
-  static void UpdateIncrementalState(
-      Delegate&,
-      SequenceState&,
-      const protos::pbzero::TracePacket_Decoder&);
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_
diff --git a/infra/ci/Makefile b/infra/ci/Makefile
index d4a3e16..39764eb 100644
--- a/infra/ci/Makefile
+++ b/infra/ci/Makefile
@@ -77,12 +77,11 @@
 		--maintenance-policy=MIGRATE \
 		--service-account=gce-ci-worker@perfetto-ci.iam.gserviceaccount.com \
 		--scopes=${GCE_SCOPES} \
-		--image=cos-85-13310-1209-10 \
+		--image=cos-stable-75-12105-77-0 \
 		--image-project=cos-cloud \
-		--boot-disk-size=100GB \
+		--boot-disk-size=200GB \
 		--boot-disk-type=pd-ssd \
-		--boot-disk-device-name=ci-worker-template \
-		--local-ssd=interface=NVME
+		--boot-disk-device-name=ci-worker-template
 	touch $@
 
 .PHONY: deploy-controller
@@ -93,32 +92,33 @@
 deploy-frontend:
 	make -C frontend deploy
 
-.PHONY: restart-workers
-restart-workers: stop-workers start-workers
-
-define start-workers-for-zone
-gcloud compute --project=${PROJECT} \
-	instance-groups managed create ${GCE_GROUP_NAME}-$1 \
-	--zone=$1 \
-	--base-instance-name=ci-$1 \
-	--template=ci-worker-template \
-	--size=${NUM_VMS}
-
-endef
-
-.PHONY: start-workers
-start-workers: .deps/gce-template
-	$(foreach zone,$(GCE_ZONES),$(call start-workers-for-zone,$(zone)))
-
-define stop-workers-for-zone
-gcloud compute --quiet --project=${PROJECT} \
-	instance-groups managed delete ${GCE_GROUP_NAME}-$1 --zone=$1 || true
-
-endef
-
 .PHONY: stop-workers
 stop-workers:
-	$(foreach zone,$(GCE_ZONES),$(call stop-workers-for-zone,$(zone)))
+	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 "${NUM_VMS}" \
+		--max-num-replicas "${NUM_VMS}" \
+		--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.
@@ -128,14 +128,14 @@
 	gcloud compute --quiet \
 		--project ${PROJECT} \
 		instances delete ${GCE_VM_NAME} \
-		--zone us-central1-f
+		--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 us-central1-f \
+		--zone ${ZONE} \
 		--source-instance-template=${GCE_TEMPLATE}
 
 # Debugging client to make OAuth2 authenticated requests manually.
diff --git a/infra/ci/config.py b/infra/ci/config.py
index be325ab..8b35141 100755
--- a/infra/ci/config.py
+++ b/infra/ci/config.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,6 +32,7 @@
 
 # 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'
@@ -40,18 +41,17 @@
 CI_SITE = 'https://ci.perfetto.dev'
 GCS_ARTIFACTS = 'perfetto-ci-artifacts'
 
-JOB_TIMEOUT_SEC = 45 * 60
+JOB_TIMEOUT_SEC = 60 * 30
 CL_TIMEOUT_SEC = 60 * 60 * 3
 LOGS_TTL_DAYS = 15
 TRUSTED_EMAILS = '^.*@google.com$'
 
-GCE_ZONES = 'us-central1-b us-east1-b us-west1-b'
 GCE_VM_NAME = 'ci-worker'
-GCE_VM_TYPE = 'c2-standard-8'
+GCE_VM_TYPE = 'e2-standard-16'
 GCE_TEMPLATE = 'ci-worker-template'
 GCE_GROUP_NAME = 'ci'
-NUM_VMS = 3
-NUM_WORKERS_PER_VM = 2
+NUM_VMS = 6
+NUM_WORKERS_PER_VM = 5
 
 GCE_SCOPES = [
     'https://www.googleapis.com/auth/cloud-platform',
@@ -110,6 +110,10 @@
         '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',
@@ -145,7 +149,6 @@
 
   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' %
-          os.path.basename(__file__))
+    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/frontend/Makefile b/infra/ci/frontend/Makefile
index 400b5eb..14431aa 100644
--- a/infra/ci/frontend/Makefile
+++ b/infra/ci/frontend/Makefile
@@ -36,26 +36,26 @@
 static/config.js: ../config.py
 	../config.py js > $@
 
-static/third_party/xterm-4.11.0.min.css:
-	curl -Sso $@ https://unpkg.com/xterm@4.11.0/css/xterm.css
-	echo "4cee0ccb82803888905fefc8641f0613c0a9081b  $@" | ${SHASUM} -c || rm $@
+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-4.11.0.min.js:
-	curl -Sso $@ https://unpkg.com/xterm@4.11.0/lib/xterm.js
-	echo "470644a5cd3e2a443a422c6ecddc85b37a85f329  $@" | ${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-0.8.0-addon-search.min.js:
-	curl -Sso $@ https://unpkg.com/xterm-addon-search@0.8.0/lib/xterm-addon-search.js
-	echo "1eae1371cc07677c38f9d01eae4d6a3b996388f8  $@" | ${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-0.5.0-addon-fit.min.js:
-	curl -Sso $@ https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js
-	echo "4c8942910554242336443126e349ac1e3897a64e  $@" | ${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/mithril-1.1.6.min.js static/third_party/xterm-4.11.0.min.css static/third_party/xterm-4.11.0.min.js static/third_party/xterm-0.8.0-addon-search.min.js static/third_party/xterm-0.5.0-addon-fit.min.js
+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/frontend.py b/infra/ci/frontend/frontend.py
index c6697cd..ff16ad7 100644
--- a/infra/ci/frontend/frontend.py
+++ b/infra/ci/frontend/frontend.py
@@ -61,12 +61,8 @@
     url = 'https://%s/changes/?q=project:%s+' % (GERRIT_HOST, GERRIT_PROJECT)
     url += self.request.query_string
     result = urlfetch.fetch(url)
-    self.response.headers['Content-Type'] = 'text/plain'
     self.response.status_int = result.status_code
-    if (result.status_code == 200):
-      self.response.write(result.content[4:])  # 4: -> Strip Gerrit XSSI chars.
-    else:
-      self.response.write('HTTP error %s' % result.status_code)
+    self.response.write(result.content[4:])  # 4: -> Strip Gerrit XSSI chars.
 
 
 app = webapp2.WSGIApplication([
diff --git a/infra/ci/frontend/static/index.html b/infra/ci/frontend/static/index.html
index f1995bc..7c67790 100644
--- a/infra/ci/frontend/static/index.html
+++ b/infra/ci/frontend/static/index.html
@@ -21,7 +21,7 @@
     <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-4.11.0.min.css">
+    <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>
@@ -31,9 +31,9 @@
 
 <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-4.11.0.min.js"></script>
-<script src="/static/third_party/xterm-0.5.0-addon-fit.min.js"></script>
-<script src="/static/third_party/xterm-0.8.0-addon-search.min.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>
diff --git a/infra/ci/frontend/static/script.js b/infra/ci/frontend/static/script.js
index 1520485..4a537c6 100644
--- a/infra/ci/frontend/static/script.js
+++ b/infra/ci/frontend/static/script.js
@@ -26,13 +26,22 @@
   { 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' },
 ];
 
-const STATS_LINK =
-    'https://app.google.stackdriver.com/dashboards/5008687313278081798?project=perfetto-ci';
+// 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.
@@ -92,11 +101,11 @@
 };
 
 let term = undefined;
-let fitAddon = undefined;
-let searchAddon = undefined;
 
 function main() {
   firebase.initializeApp({ databaseURL: cfg.DB_ROOT });
+  Terminal.applyAddon(fit);
+  Terminal.applyAddon(search);
 
   m.route(document.body, '/cls', {
     '/cls': CLsPageRenderer,
@@ -104,6 +113,7 @@
     '/logs/:jobId': LogsPageRenderer,
     '/jobs': JobsPageRenderer,
     '/jobs/:jobId': JobsPageRenderer,
+    '/stats/:period': StatsPageRenderer,
   });
 
   setInterval(fetchGerritCLs, 15000);
@@ -118,27 +128,21 @@
 function renderHeader() {
   const active = id => m.route.get().startsWith(`/${id}`) ? '.active' : '';
   const logUrl = 'https://goto.google.com/perfetto-ci-logs-';
-  const docsUrl =
-      'https://perfetto.dev/docs/design-docs/continuous-integration';
-  return m(
-      'header', m('a[href=/#!/cls]', 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_LINK}][target=_blank]`, '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')),
-              ),
-          ));
+  const docsUrl = 'https://docs.perfetto.dev/#/continuous-integration';
+  return m('header',
+    m('a[href=/#!/cls]', 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 = {
@@ -193,16 +197,16 @@
                 m('td[rowspan=4]', 'Status'),
                 m('td[rowspan=4]', 'Owner'),
                 m('td[rowspan=4]', 'Updated'),
-                m('td[colspan=11]', 'Bots'),
+                m('td[colspan=12]', 'Bots'),
               ),
               m('tr',
-                m('td[colspan=9]', 'linux'),
+                m('td[colspan=10]', 'linux'),
                 m('td[colspan=2]', 'android'),
               ),
               m('tr',
                 m('td', 'gcc7'),
                 m('td[colspan=7]', 'clang'),
-                m('td[colspan=1]', 'ui'),
+                m('td[colspan=2]', 'ui'),
                 m('td[colspan=2]', 'clang-arm'),
               ),
               m('tr#cls_header',
@@ -367,33 +371,19 @@
 }
 
 const TermRenderer = {
-  oncreate: function(vnode) {
+  oncreate: function (vnode) {
     console.log('Creating terminal object');
-    fitAddon = new FitAddon.FitAddon();
-    searchAddon = new SearchAddon.SearchAddon();
-    term = new Terminal({
-      rows: 6,
-      fontFamily: 'monospace',
-      fontSize: 12,
-      scrollback: 100000,
-      disableStdin: true,
-    });
-    term.loadAddon(fitAddon);
-    term.loadAddon(searchAddon);
+    term = new Terminal({ rows: 6, fontSize: 12, scrollback: 100000 });
     term.open(vnode.dom);
-    fitAddon.fit();
-    if (vnode.attrs.focused)
-      term.focus();
+    term.fit();
+    if (vnode.attrs.focused) term.focus();
   },
-  onremove: function(vnode) {
-    term.dispose();
-    fitAddon.dispose();
-    searchAddon.dispose();
+  onremove: function (vnode) {
+    term.destroy();
   },
-  onupdate: function(vnode) {
-    fitAddon.fit();
+  onupdate: function (vnode) {
     if (state.termClear) {
-      term.clear();
+      term.clear()
       state.termClear = false;
     }
     for (const line of state.termLines) {
@@ -401,7 +391,7 @@
     }
     state.termLines = [];
   },
-  view: function() {
+  view: function () {
     return m('.term-container',
       {
         onkeydown: (e) => {
@@ -415,9 +405,9 @@
         onkeydown: (e) => {
           if (e.key !== 'Enter') return;
           if (e.shiftKey) {
-            searchAddon.findNext(e.target.value);
+            term.findNext(e.target.value);
           } else {
-            searchAddon.findPrevious(e.target.value);
+            term.findPrevious(e.target.value);
           }
           e.stopPropagation();
           e.preventDefault();
@@ -544,6 +534,28 @@
   }
 };
 
+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).
 // -----------------------------------------------------------------------------
@@ -565,12 +577,13 @@
   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;
   }
 
-  const json = (await response.text());
+  json = (await response.text());
   const cls = [];
   for (const e of JSON.parse(json)) {
     const revHash = Object.keys(e.revisions)[0];
diff --git a/infra/ci/frontend/static/style.css b/infra/ci/frontend/static/style.css
index 93a2503..5ce48b2 100644
--- a/infra/ci/frontend/static/style.css
+++ b/infra/ci/frontend/static/style.css
@@ -4,6 +4,7 @@
 
 html {
     font-size: 13px;
+    font-weight: 300;
     padding: 0;
     margin: 0;
     height: 100%;
@@ -194,12 +195,12 @@
 
 .main-table tbody td:first-child {
     padding-left: 20px;
-    max-width: 55vw;
 }
 
 .main-table thead {
     color: #111;
     font-size: 14px;
+    font-weight: 300;
 }
 
 .main-table thead tr:nth-child(n+3) td {
@@ -295,7 +296,7 @@
     height: 25px;
     line-height: 25px;
     font-size: 13px;
-    -webkit-font-smoothing: antialiased;
+    font-weight: 300;
 }
 
 .main-table tbody tr.nested td:first-child, .main-table tbody tr.nested a {
diff --git a/infra/ci/sandbox/Dockerfile b/infra/ci/sandbox/Dockerfile
index 6f14c90..04e22a3 100644
--- a/infra/ci/sandbox/Dockerfile
+++ b/infra/ci/sandbox/Dockerfile
@@ -16,38 +16,30 @@
 # image is used by the Kokoro continuous integration jobs, but is also suitable
 # for local development.
 
-FROM debian:buster
+FROM debian:latest
 
 RUN set -ex; \
     export DEBIAN_FRONTEND=noninteractive; \
-    echo deb http://deb.debian.org/debian buster-backports main > \
-            /etc/apt/sources.list.d/backports.list; \
+    echo deb http://deb.debian.org/debian testing main > \
+             /etc/apt/sources.list.d/testing.list; \
     apt-get update; \
-    apt-get -y install python3 python3-pip git curl sudo lz4 tar ccache tini \
-                       libpulse0 libgl1 libxml2 libc6-dev-i386 libtinfo5 \
-                       gnupg2 pkg-config zip g++ zlib1g-dev unzip \
-                       python3-distutils clang-8 gcc-7 g++-7; \
-    update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1; \
-    gcc-7 --version; \
-    g++-7 --version; \
-    clang-8 --version; \
-    clang++-8 --version; \
-    pip3 install --quiet protobuf pandas; \
-    groupadd -g 1337 perfetto; \
-    useradd -d /ci/ramdisk -u 1337 -g perfetto perfetto; \
-    apt-get -y autoremove; \
-    rm -rf /var/lib/apt/lists/* /usr/share/man/* /usr/share/doc/*;
-
-RUN set -ex; \
-    curl -LO https://github.com/bazelbuild/bazel/releases/download/2.2.0/bazel-2.2.0-installer-linux-x86_64.sh; \
+    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;
+    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
-RUN chmod -R a+rx /ci/
 
 VOLUME [ "/ci/cache", "/ci/ramdisk", "/ci/artifacts" ]
 ENTRYPOINT [ "tini", "-g", "--" ]
diff --git a/infra/ci/sandbox/init.sh b/infra/ci/sandbox/init.sh
index 2816fea..68e4118 100644
--- a/infra/ci/sandbox/init.sh
+++ b/infra/ci/sandbox/init.sh
@@ -19,5 +19,4 @@
 chmod 777 /ci/cache /ci/artifacts
 chown perfetto.perfetto /ci/ramdisk
 cd /ci/ramdisk
-ls -A1 | xargs rm -rf
 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
index 49a63ec..d16554e 100755
--- a/infra/ci/sandbox/testrunner.sh
+++ b/infra/ci/sandbox/testrunner.sh
@@ -30,12 +30,11 @@
 
 # Print env vars for debugging. They contain GN args and entrypoint.
 date
-hostname
 env
 
 mkdir src && cd src
 
-if [[ -f "$PERFETTO_TEST_GIT_REF" ]]; then
+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
@@ -74,15 +73,16 @@
 export CCACHE_COMPILERCHECK=string:$(shasum tools/install-build-deps)
 export CCACHE_UMASK=000
 export CCACHE_DEPEND=1
-export CCACHE_MAXSIZE=32G
+export CCACHE_MAXSIZE=8G
 export CCACHE_DIR=/ci/cache/ccache
 export CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime
-export CCACHE_NOCOMPRESS=1
+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=""
+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).
@@ -92,8 +92,8 @@
 # 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=/ci/cache/buildtools-$(hostname -s).tar.lz4
+  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
+  git check-ignore buildtools/* | xargs tar c | lz4 -z - $TMPFILE
+  mv -f $TMPFILE $PREBUILTS_ARCHIVE
 fi
diff --git a/infra/ci/worker/Dockerfile b/infra/ci/worker/Dockerfile
index 6dc57d6..8b1788a 100644
--- a/infra/ci/worker/Dockerfile
+++ b/infra/ci/worker/Dockerfile
@@ -15,8 +15,8 @@
 # docker:stable is an Alpine-based distro.
 FROM docker:stable
 
-RUN apk update && apk add python3 py-pip sudo tini
-RUN pip3 install oauth2client httplib2
+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.
@@ -34,8 +34,8 @@
 RUN set -e; \
     echo 'root ALL=(ALL) ALL' /etc/sudoers; \
     echo 'perfetto ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers; \
-    addgroup -S --gid 1337 perfetto; \
-    adduser -S --uid 1337 -h /home/perfetto perfetto perfetto; \
+    addgroup -S perfetto; \
+    adduser -S -h /home/perfetto perfetto perfetto; \
     chown perfetto.perfetto -R /home/perfetto; \
     chmod -R 755 /home/perfetto;
 
@@ -43,4 +43,4 @@
 WORKDIR /home/perfetto
 
 ENTRYPOINT [ "tini", "--" ]
-CMD [ "python3", "/home/perfetto/worker.py" ]
+CMD [ "python2", "/home/perfetto/worker.py" ]
diff --git a/infra/ci/worker/artifacts_uploader.py b/infra/ci/worker/artifacts_uploader.py
index d2c5f25..2a44633 100644
--- a/infra/ci/worker/artifacts_uploader.py
+++ b/infra/ci/worker/artifacts_uploader.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python2
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -76,7 +76,7 @@
     res = upload_one_file(fpath)
     if res >= 0:
       return res
-    logging.warning('Upload of %s failed, retrying in %s seconds', fpath, retry)
+    logging.warn('Upload of %s failed, retrying in %s seconds', fpath, retry)
     time.sleep(retry)
 
 
@@ -116,11 +116,6 @@
     logging.error('Directory not found: %s', dirpath)
     return 1
 
-  # Make all artifacts readable by our user. Some of them are extracted as
-  # rw-rw--- and owned by a diffrent user (whatever the "sandbox" docker
-  # container uid ends up mapping to).
-  subprocess.call(['sudo', 'chown', '-R', str(os.geteuid()), dirpath])
-
   total_size = 0
   uploads = 0
   failures = 0
diff --git a/infra/ci/worker/gce-startup-script.sh b/infra/ci/worker/gce-startup-script.sh
index 7672c42..2e384b8 100644
--- a/infra/ci/worker/gce-startup-script.sh
+++ b/infra/ci/worker/gce-startup-script.sh
@@ -19,25 +19,16 @@
 URL='http://metadata.google.internal/computeMetadata/v1/instance/attributes/num-workers'
 NUM_WORKERS=$(curl --silent --fail -H'Metadata-Flavor:Google' $URL || echo 1)
 
-for SSD in /dev/nvme0n*; do
-mkswap $SSD
-swapon -p -1 $SSD
-done
-
 # This is used by the sandbox containers, NOT needed by the workers.
-# Rationale for size=100G: by default tmpfs mount are set to RAM/2, which makes
-# the CI depend too much on the underlying VM. Here and below, we pick an
-# arbitrary fixed size (we use local scratch NVME as a swap device).
 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,size=100G
+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/disks/artifacts
+export ARTIFACTS_DIR=/mnt/stateful_partition/artifacts
 rm -rf $ARTIFACTS_DIR
-mkdir -p $ARTIFACTS_DIR
-mount -t tmpfs tmpfs $ARTIFACTS_DIR -o mode=777,size=100G
+mkdir -m 777 -p $ARTIFACTS_DIR
 
 # Pull the latest images from the registry.
 docker pull eu.gcr.io/perfetto-ci/worker
@@ -57,15 +48,6 @@
 # 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
-
-# We manually mount a tmpfs mount ourselves because Docker doesn't allow to
-# both override tmpfs-size AND "-o exec" (see also
-# https://github.com/moby/moby/issues/32131)
-SANDBOX_TMP=/mnt/disks/sandbox-$i-tmp
-rm -rf $SANDBOX_TMP
-mkdir -p $SANDBOX_TMP
-mount -t tmpfs tmpfs $SANDBOX_TMP -o mode=777,size=100G
-
 docker rm -f worker-$i 2>/dev/null || true
 docker run -d \
   -v /var/run/docker.sock:/var/run/docker.sock \
@@ -73,7 +55,6 @@
   --env SHARED_WORKER_CACHE="$SHARED_WORKER_CACHE" \
   --env SANDBOX_NETWORK_ARGS="$SANDBOX_NETWORK_ARGS" \
   --env ARTIFACTS_DIR="$ARTIFACTS_DIR" \
-  --env SANDBOX_TMP="$SANDBOX_TMP" \
   --env WORKER_HOST="$(hostname)" \
   --name worker-$i \
   --hostname worker-$i \
diff --git a/infra/ci/worker/perf_metrics_uploader.py b/infra/ci/worker/perf_metrics_uploader.py
index 37c22db..dcc9c83 100755
--- a/infra/ci/worker/perf_metrics_uploader.py
+++ b/infra/ci/worker/perf_metrics_uploader.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,8 +53,7 @@
 
 def sha1(obj):
   hasher = hashlib.sha1()
-  hasher.update(
-      json.dumps(obj, sort_keys=True, separators=(',', ':')).encode('utf-8'))
+  hasher.update(json.dumps(obj, sort_keys=True, separators=(',', ':')))
   return hasher.hexdigest()
 
 
diff --git a/infra/ci/worker/run_job.py b/infra/ci/worker/run_job.py
index 4706120..ad3f833 100755
--- a/infra/ci/worker/run_job.py
+++ b/infra/ci/worker/run_job.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python2
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +21,7 @@
 import logging
 import json
 import os
-import queue
+import Queue
 import signal
 import socket
 import shutil
@@ -48,7 +48,7 @@
       buf = os.read(fd.fileno(), 1024)
       if not buf:
         break
-      res += buf.decode()
+      res += buf
     except OSError:
       break
   return res
@@ -73,7 +73,7 @@
 def main(argv):
   init_logging()
   if len(argv) != 2:
-    print('Usage: %s job_id' % argv[0])
+    print 'Usage: %s job_id' % argv[0]
     return 1
 
   job_id = argv[1]
@@ -85,14 +85,14 @@
   # Remove stale jobs, if any.
   subprocess.call(['sudo', 'docker', 'rm', '-f', container])
 
-  q = queue.Queue()
+  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.warning('Job runner got signal %s, terminating job %s', sig, job_id)
+    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.
 
@@ -104,23 +104,15 @@
   # SYS_PTRACE is required for gtest death tests and LSan.
   cmd = [
       'sudo', 'docker', 'run', '--name', container, '--hostname', container,
-      '--cap-add', 'SYS_PTRACE', '--rm', '--env',
-      'PERFETTO_TEST_JOB=%s' % job_id, '--tmpfs', '/tmp:exec'
+      '--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]
 
-  # We use the tmpfs mount created by gce-startup-script.sh, if present. The
-  # problem is that Docker doesn't allow to both override the tmpfs-size and
-  # prevent the "-o noexec". In turn the default tmpfs-size depends on the host
-  # phisical memory size.
-  if os.getenv('SANDBOX_TMP'):
-    cmd += ['-v', '%s:/ci/ramdisk' % os.getenv('SANDBOX_TMP')]
-  else:
-    cmd += ['--tmpfs', '/ci/ramdisk:exec']
-
   # 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.
diff --git a/infra/ci/worker/worker.py b/infra/ci/worker/worker.py
index d08b8fc..764b0e5 100755
--- a/infra/ci/worker/worker.py
+++ b/infra/ci/worker/worker.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python2
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -77,16 +77,6 @@
   if not jobs:
     return
 
-  # Work out the worker number from the hostname. We try to distribute the load
-  # (via the time.sleep below) so that we fill first all the worker-1 of each
-  # vm, then worker-2 and so on. This is designed so that if there is only one
-  # CL (hence N jobs) in the queue, each VM gets only one job, maximizing the
-  # cpu efficiency of each VM.
-  try:
-    worker_num = int(socket.gethostname().split('-')[-1])
-  except ValueError:
-    worker_num = 1
-
   # Transactionally acquire a job. Deal with races (two workers trying to
   # acquire the same job).
   job = None
@@ -96,7 +86,7 @@
     if job is not None:
       break
     logging.info('Raced while trying to acquire job %s, retrying', job_id)
-    time.sleep(worker_num * 2 + random.random())
+    time.sleep(int(random.random() * 3))
   if job is None:
     logging.error('Failed to acquire a job')
     return
@@ -116,7 +106,7 @@
   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'].items()})
+  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
@@ -162,7 +152,7 @@
 
 
 def sig_handler(_, __):
-  logging.warning('Interrupted by signal, exiting worker')
+  logging.warn('Interrupted by signal, exiting worker')
   sigterm.set()
 
 
@@ -183,16 +173,12 @@
       logging.error('Exception in worker loop:\n%s', traceback.format_exc())
     if sigterm.is_set():
       break
-
-    # Synchronize sleeping with the wall clock. This is so all VMs wake up at
-    # the same time. See comment on distributing load above in this file.
-    poll_time_sec = 5
-    time.sleep(poll_time_sec - (time.time() % poll_time_sec))
+    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.warning('Exiting the worker loop, got signal: %s', sigterm.is_set())
+  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'))
diff --git a/infra/config/README.md b/infra/config/README.md
deleted file mode 100644
index b99be64..0000000
--- a/infra/config/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-This folder contains the recipes.cfg file which is needed for our
-integration with LUCI. Unfortunately, the infra/config prefix for
-this file is hardcoded into LUCI infrastructure so we cannot move
-this to infra/luci folder where the other LUCI code lives.
\ No newline at end of file
diff --git a/infra/config/recipes.cfg b/infra/config/recipes.cfg
deleted file mode 100644
index 5743902..0000000
--- a/infra/config/recipes.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "api_version": 2,
-  "deps": {
-    "recipe_engine": {
-      "branch": "refs/heads/master",
-      "revision": "2030661a4ff2a6b64b0651f2c44aabed8c71223f",
-      "url": "https://chromium.googlesource.com/infra/luci/recipes-py"
-    }
-  },
-  "project_id": "perfetto",
-  "recipes_path": "infra/luci",
-  "repo_name": "perfetto"
-}
diff --git a/infra/luci/README.recipes.md b/infra/luci/README.recipes.md
deleted file mode 100644
index 8d601e9..0000000
--- a/infra/luci/README.recipes.md
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--- AUTOGENERATED BY `./recipes.py test train` -->
-# Repo documentation for [perfetto]()
-## Table of Contents
-
-**[Recipes](#Recipes)**
-  * [perfetto](#recipes-perfetto) &mdash; Recipe for building Perfetto.
-## Recipes
-
-### *recipes* / [perfetto](/infra/luci/recipes/perfetto.py)
-
-[DEPS](/infra/luci/recipes/perfetto.py#18): [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/file][recipe_engine/recipe_modules/file], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/step][recipe_engine/recipe_modules/step]
-
-Recipe for building Perfetto.
-
-&mdash; **def [RunSteps](/infra/luci/recipes/perfetto.py#39)(api, repository):**
-
-[recipe_engine/recipe_modules/buildbucket]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-buildbucket
-[recipe_engine/recipe_modules/context]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-context
-[recipe_engine/recipe_modules/file]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-file
-[recipe_engine/recipe_modules/path]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-path
-[recipe_engine/recipe_modules/platform]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-platform
-[recipe_engine/recipe_modules/properties]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-properties
-[recipe_engine/recipe_modules/step]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/2030661a4ff2a6b64b0651f2c44aabed8c71223f/README.recipes.md#recipe_modules-step
diff --git a/infra/luci/recipes.py b/infra/luci/recipes.py
deleted file mode 100644
index 32e497c..0000000
--- a/infra/luci/recipes.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/bin/sh
-# Copyright 2019 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-# We want to run python in unbuffered mode; however shebangs on linux grab the
-# entire rest of the shebang line as a single argument, leading to errors like:
-#
-#   /usr/bin/env: 'python -u': No such file or directory
-#
-# This little shell hack is a triple-quoted noop in python, but in sh it
-# evaluates to re-exec'ing this script in unbuffered mode.
-# pylint: disable=pointless-string-statement
-''''exec python -u -- "$0" ${1+"$@"} # '''
-# vi: syntax=python
-"""Bootstrap script to clone and forward to the recipe engine tool.
-
-*******************
-** DO NOT MODIFY **
-*******************
-
-This is a copy of https://chromium.googlesource.com/infra/luci/recipes-py/+/master/recipes.py.
-To fix bugs, fix in the googlesource repo then run the autoroller.
-"""
-
-# pylint: disable=wrong-import-position
-import argparse
-import errno
-import json
-import logging
-import os
-import subprocess
-import sys
-
-from collections import namedtuple
-
-try:
-  import urllib.parse as urlparse
-except ImportError:
-  import urlparse
-
-# The dependency entry for the recipe_engine in the client repo's recipes.cfg
-#
-# url (str) - the url to the engine repo we want to use.
-# revision (str) - the git revision for the engine to get.
-# branch (str) - the branch to fetch for the engine as an absolute ref (e.g.
-#   refs/heads/master)
-EngineDep = namedtuple('EngineDep', 'url revision branch')
-
-
-class MalformedRecipesCfg(Exception):
-
-  def __init__(self, msg, path):
-    full_message = 'malformed recipes.cfg: %s: %r' % (msg, path)
-    super(MalformedRecipesCfg, self).__init__(full_message)
-
-
-def parse(repo_root, recipes_cfg_path):
-  """Parse is a lightweight a recipes.cfg file parser.
-
-  Args:
-    repo_root (str) - native path to the root of the repo we're trying to run
-      recipes for.
-    recipes_cfg_path (str) - native path to the recipes.cfg file to process.
-
-  Returns (as tuple):
-    engine_dep (EngineDep|None): The recipe_engine dependency, or None, if the
-      current repo IS the recipe_engine.
-    recipes_path (str) - native path to where the recipes live inside of the
-      current repo (i.e. the folder containing `recipes/` and/or
-      `recipe_modules`)
-  """
-  with open(recipes_cfg_path, 'rU') as fh:
-    pb = json.load(fh)
-
-  try:
-    if pb['api_version'] != 2:
-      raise MalformedRecipesCfg('unknown version %d' % pb['api_version'],
-                                recipes_cfg_path)
-
-    # If we're running ./recipes.py from the recipe_engine repo itself, then
-    # return None to signal that there's no EngineDep.
-    repo_name = pb.get('repo_name')
-    if not repo_name:
-      repo_name = pb['project_id']
-    if repo_name == 'recipe_engine':
-      return None, pb.get('recipes_path', '')
-
-    engine = pb['deps']['recipe_engine']
-
-    if 'url' not in engine:
-      raise MalformedRecipesCfg(
-          'Required field "url" in dependency "recipe_engine" not found',
-          recipes_cfg_path)
-
-    engine.setdefault('revision', '')
-    engine.setdefault('branch', 'refs/heads/master')
-    recipes_path = pb.get('recipes_path', '')
-
-    # TODO(iannucci): only support absolute refs
-    if not engine['branch'].startswith('refs/'):
-      engine['branch'] = 'refs/heads/' + engine['branch']
-
-    recipes_path = os.path.join(repo_root,
-                                recipes_path.replace('/', os.path.sep))
-    return EngineDep(**engine), recipes_path
-  except KeyError as ex:
-    raise MalformedRecipesCfg(ex.message, recipes_cfg_path)
-
-
-IS_WIN = sys.platform.startswith(('win', 'cygwin'))
-
-_BAT = '.bat' if IS_WIN else ''
-GIT = 'git' + _BAT
-VPYTHON = 'vpython' + _BAT
-CIPD = 'cipd' + _BAT
-REQUIRED_BINARIES = {GIT, VPYTHON, CIPD}
-
-
-def _is_executable(path):
-  return os.path.isfile(path) and os.access(path, os.X_OK)
-
-
-# TODO: Use shutil.which once we switch to Python3.
-def _is_on_path(basename):
-  for path in os.environ['PATH'].split(os.pathsep):
-    full_path = os.path.join(path, basename)
-    if _is_executable(full_path):
-      return True
-  return False
-
-
-def _subprocess_call(argv, **kwargs):
-  logging.info('Running %r', argv)
-  return subprocess.call(argv, **kwargs)
-
-
-def _git_check_call(argv, **kwargs):
-  argv = [GIT] + argv
-  logging.info('Running %r', argv)
-  subprocess.check_call(argv, **kwargs)
-
-
-def _git_output(argv, **kwargs):
-  argv = [GIT] + argv
-  logging.info('Running %r', argv)
-  return subprocess.check_output(argv, **kwargs)
-
-
-def parse_args(argv):
-  """This extracts a subset of the arguments that this bootstrap script cares
-  about. Currently this consists of:
-    * an override for the recipe engine in the form of `-O recipe_engine=/path`
-    * the --package option.
-  """
-  PREFIX = 'recipe_engine='
-
-  p = argparse.ArgumentParser(add_help=False)
-  p.add_argument('-O', '--project-override', action='append')
-  p.add_argument('--package', type=os.path.abspath)
-  args, _ = p.parse_known_args(argv)
-  for override in args.project_override or ():
-    if override.startswith(PREFIX):
-      return override[len(PREFIX):], args.package
-  return None, args.package
-
-
-def checkout_engine(engine_path, repo_root, recipes_cfg_path):
-  dep, recipes_path = parse(repo_root, recipes_cfg_path)
-  if dep is None:
-    # we're running from the engine repo already!
-    return os.path.join(repo_root, recipes_path)
-
-  url = dep.url
-
-  if not engine_path and url.startswith('file://'):
-    engine_path = urlparse.urlparse(url).path
-
-  if not engine_path:
-    revision = dep.revision
-    branch = dep.branch
-
-    # Ensure that we have the recipe engine cloned.
-    engine_path = os.path.join(recipes_path, '.recipe_deps', 'recipe_engine')
-
-    with open(os.devnull, 'w') as NUL:
-      # Note: this logic mirrors the logic in recipe_engine/fetch.py
-      _git_check_call(['init', engine_path], stdout=NUL)
-
-      try:
-        _git_check_call(['rev-parse', '--verify',
-                         '%s^{commit}' % revision],
-                        cwd=engine_path,
-                        stdout=NUL,
-                        stderr=NUL)
-      except subprocess.CalledProcessError:
-        _git_check_call(['fetch', url, branch],
-                        cwd=engine_path,
-                        stdout=NUL,
-                        stderr=NUL)
-
-    try:
-      _git_check_call(['diff', '--quiet', revision], cwd=engine_path)
-    except subprocess.CalledProcessError:
-      index_lock = os.path.join(engine_path, '.git', 'index.lock')
-      try:
-        os.remove(index_lock)
-      except OSError as exc:
-        if exc.errno != errno.ENOENT:
-          logging.warn('failed to remove %r, reset will fail: %s', index_lock,
-                       exc)
-      _git_check_call(['reset', '-q', '--hard', revision], cwd=engine_path)
-
-    # If the engine has refactored/moved modules we need to clean all .pyc files
-    # or things will get squirrely.
-    _git_check_call(['clean', '-qxf'], cwd=engine_path)
-
-  return engine_path
-
-
-def main():
-  for required_binary in REQUIRED_BINARIES:
-    if not _is_on_path(required_binary):
-      return 'Required binary is not found on PATH: %s' % required_binary
-
-  if '--verbose' in sys.argv:
-    logging.getLogger().setLevel(logging.INFO)
-
-  args = sys.argv[1:]
-  engine_override, recipes_cfg_path = parse_args(args)
-
-  if recipes_cfg_path:
-    # calculate repo_root from recipes_cfg_path
-    repo_root = os.path.dirname(
-        os.path.dirname(os.path.dirname(recipes_cfg_path)))
-  else:
-    # find repo_root with git and calculate recipes_cfg_path
-    repo_root = (
-        _git_output(['rev-parse', '--show-toplevel'],
-                    cwd=os.path.abspath(os.path.dirname(__file__))).strip())
-    repo_root = os.path.abspath(repo_root).decode()
-    recipes_cfg_path = os.path.join(repo_root, 'infra', 'config', 'recipes.cfg')
-    args = ['--package', recipes_cfg_path] + args
-
-  engine_path = checkout_engine(engine_override, repo_root, recipes_cfg_path)
-
-  argv = (
-      [VPYTHON, '-u',
-       os.path.join(engine_path, 'recipe_engine', 'main.py')] + args)
-
-  if IS_WIN:
-    # No real 'exec' on windows; set these signals to ignore so that they
-    # propagate to our children but we still wait for the child process to quit.
-    signal.signal(signal.SIGBREAK, signal.SIG_IGN)
-    signal.signal(signal.SIGINT, signal.SIG_IGN)
-    signal.signal(signal.SIGTERM, signal.SIG_IGN)
-    return _subprocess_call(argv)
-  else:
-    os.execvp(argv[0], argv)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/infra/luci/recipes/perfetto.expected/ci_linux.json b/infra/luci/recipes/perfetto.expected/ci_linux.json
deleted file mode 100644
index eebe765..0000000
--- a/infra/luci/recipes/perfetto.expected/ci_linux.json
+++ /dev/null
@@ -1,96 +0,0 @@
-[
-  {
-    "cmd": [],
-    "name": "git"
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/builder/perfetto"
-    ],
-    "infra_step": true,
-    "name": "git.ensure source dir",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "git",
-      "init",
-      "[CACHE]/builder/perfetto"
-    ],
-    "infra_step": true,
-    "name": "git.init",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "git",
-      "fetch",
-      "--tags",
-      "https://android.googlesource.com/platform/external/perfetto",
-      "2d72510e447ab60a9728aeea2362d8be2cbd7789"
-    ],
-    "cwd": "[CACHE]/builder/perfetto",
-    "infra_step": true,
-    "name": "git.fetch",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "git",
-      "checkout",
-      "FETCH_HEAD"
-    ],
-    "cwd": "[CACHE]/builder/perfetto",
-    "infra_step": true,
-    "name": "git.checkout",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "tools/install-build-deps",
-      "--ui",
-      "--android"
-    ],
-    "cwd": "[CACHE]/builder/perfetto",
-    "infra_step": true,
-    "name": "build-deps"
-  },
-  {
-    "cmd": [
-      "tools/gn",
-      "gen",
-      "out/dist",
-      "--args=is_debug=false"
-    ],
-    "cwd": "[CACHE]/builder/perfetto",
-    "name": "gn gen"
-  },
-  {
-    "cmd": [
-      "tools/ninja",
-      "-C",
-      "out/dist"
-    ],
-    "cwd": "[CACHE]/builder/perfetto",
-    "name": "ninja"
-  },
-  {
-    "name": "$result"
-  }
-]
\ No newline at end of file
diff --git a/infra/luci/recipes/perfetto.py b/infra/luci/recipes/perfetto.py
deleted file mode 100644
index e4552d8..0000000
--- a/infra/luci/recipes/perfetto.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Recipe for building Perfetto."""
-
-from recipe_engine.recipe_api import Property
-
-DEPS = [
-    'recipe_engine/buildbucket',
-    'recipe_engine/context',
-    'recipe_engine/file',
-    'recipe_engine/path',
-    'recipe_engine/platform',
-    'recipe_engine/properties',
-    'recipe_engine/step',
-]
-
-PROPERTIES = {
-    'repository':
-        Property(
-            kind=str,
-            default='https://android.googlesource.com/platform/external/perfetto'
-        ),
-}
-
-ARTIFACTS = ['trace_processor_shell']
-
-
-def RunSteps(api, repository):
-  builder_cache_dir = api.path['cache'].join('builder')
-  src_dir = builder_cache_dir.join('perfetto')
-
-  # Fetch the Perfetto repo.
-  with api.step.nest('git'), api.context(infra_steps=True):
-    api.file.ensure_directory('ensure source dir', src_dir)
-    api.step('init', ['git', 'init', src_dir])
-    with api.context(cwd=src_dir):
-      build_input = api.buildbucket.build_input
-      ref = (
-          build_input.gitiles_commit.id
-          if build_input.gitiles_commit else 'refs/heads/master')
-      # Fetch tags so `git describe` works.
-      api.step('fetch', ['git', 'fetch', '--tags', repository, ref])
-      api.step('checkout', ['git', 'checkout', 'FETCH_HEAD'])
-
-  # Pull all deps here.
-  # There should be no need for internet access for building Perfetto beyond
-  # this point.
-  with api.context(cwd=src_dir, infra_steps=True):
-    api.step('build-deps', ['tools/install-build-deps', '--ui', '--android'])
-
-  # Buld Perfetto.
-  with api.context(cwd=src_dir):
-    api.step('gn gen', ['tools/gn', 'gen', 'out/dist', '--args=is_debug=false'])
-    api.step('ninja', ['tools/ninja', '-C', 'out/dist'])
-
-
-def GenTests(api):
-  for platform in ('linux',):
-    yield (api.test('ci_' + platform) + api.platform.name(platform) +
-           api.buildbucket.ci_build(
-               project='perfetto',
-               git_repo='android.googlesource.com/platform/external/perfetto',
-           ))
diff --git a/infra/oss-fuzz/build_fuzzers b/infra/oss-fuzz/build_fuzzers
index 7f1fe48..57018b5 100755
--- a/infra/oss-fuzz/build_fuzzers
+++ b/infra/oss-fuzz/build_fuzzers
@@ -6,19 +6,12 @@
 
 mkdir -p $WORK/build
 
-# sanitize=vptr needs RTTI, which we do not compile with.
-CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr"
-
 GN_ARGS="is_clang=true is_debug=false is_fuzzer=true use_libfuzzer=false \
-link_fuzzer=\"-lFuzzingEngine\" is_hermetic_clang=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 cc=\"$CC\" cxx=\"$CXX\" linker=\"gold\""
-
-if [ "$SANITIZER" = "address" ]; then
-  GN_ARGS="$GN_ARGS is_asan=true";
-fi;
+is_system_compiler=true"
 
 OUTDIR=$WORK/build
 $SRC/perfetto/tools/gn gen "$OUTDIR" --args="${GN_ARGS}" --check
@@ -28,7 +21,3 @@
 mkdir -p $OUT/src/traced/probes/ftrace/test/data
 cp -a $SRC/perfetto/src/traced/probes/ftrace/test/data/synthetic \
   $OUT/src/traced/probes/ftrace/test/data
-
-if [ "$SANITIZER" = "undefined" ]; then
-  rm $OUT/trace_processor_fuzzer
-fi;
diff --git a/infra/perfetto-get.appspot.com/main.py b/infra/perfetto-get.appspot.com/main.py
index e4b14a8..71e2b12 100644
--- a/infra/perfetto-get.appspot.com/main.py
+++ b/infra/perfetto-get.appspot.com/main.py
@@ -37,7 +37,6 @@
 class GitilesMirrorHandler(webapp2.RequestHandler):
 
   def get(self, resource):
-    self.response.headers['Content-Type'] = 'text/plain'
     resource = resource.lower()
     if resource not in RESOURCES:
       self.error(404)
@@ -56,6 +55,7 @@
         return
       contents = base64.b64decode(result.content)
       memcache.set(url, contents, time=3600)  # 1h
+    self.response.headers['Content-Type'] = 'text/plain'
     self.response.headers['Content-Disposition'] = \
         'attachment; filename="%s"' % resource
     self.response.write(contents)
@@ -63,6 +63,6 @@
 
 app = webapp2.WSGIApplication([
     ('/', RedirectHandler),
-    ('/([a-zA-Z0-9_.-]+)', GitilesMirrorHandler),
+    ('/(.*)', GitilesMirrorHandler),
 ],
                               debug=True)
diff --git a/infra/perfetto.dev/.clang-format b/infra/perfetto.dev/.clang-format
deleted file mode 100644
index 265b562..0000000
--- a/infra/perfetto.dev/.clang-format
+++ /dev/null
@@ -1,5 +0,0 @@
-Language:         JavaScript
-BasedOnStyle:     Google
-ColumnLimit:      80
-BinPackArguments: false
-JavaScriptWrapImports: true
\ No newline at end of file
diff --git a/infra/perfetto.dev/.gcloudignore b/infra/perfetto.dev/.gcloudignore
new file mode 100644
index 0000000..2382779
--- /dev/null
+++ b/infra/perfetto.dev/.gcloudignore
@@ -0,0 +1,12 @@
+.firebase/
+.firebaserc
+.gcloudignore
+.git
+.gitignore
+BUILD.gn
+deploy
+firebase-debug.log
+node_modules/
+package-lock.json
+package.json
+run-dev-server
\ No newline at end of file
diff --git a/infra/perfetto.dev/BUILD.gn b/infra/perfetto.dev/BUILD.gn
new file mode 100644
index 0000000..ddab3db
--- /dev/null
+++ b/infra/perfetto.dev/BUILD.gn
@@ -0,0 +1,350 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../gn/perfetto.gni")
+
+# Prevent that this file is accidentally included in embedder builds.
+assert(enable_perfetto_ui)
+
+dist_dir = "$root_build_dir/site"
+gen_dir = "$target_out_dir/gen"
+nodejs_root = "../buildtools/nodejs"
+nodejs_bin = rebase_path("$nodejs_root/bin", root_build_dir)
+
+# +----------------------------------------------------------------------------+
+# | The outer "ui" target to just ninja -C out/xxx ui                          |
+# +----------------------------------------------------------------------------+
+
+group("site") {
+  deps = [
+    ":assets_dist",
+    ":index_dist",
+    ":markdown",
+    ":scss",
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Runs NodeJS using the hermetic node toolchain.                             |
+# +----------------------------------------------------------------------------+
+template("node_bin") {
+  action(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "inputs",
+                             "outputs",
+                             "depfile",
+                           ])
+    deps = [ ":node_modules" ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+    script = "../../gn/standalone/build_tool_wrapper.py"
+    _node_cmd = invoker.node_cmd
+    args = []
+    if (defined(invoker.suppress_stdout) && invoker.suppress_stdout) {
+      args += [ "--suppress_stdout" ]
+    }
+    if (defined(invoker.suppress_stderr) && invoker.suppress_stderr) {
+      args += [ "--suppress_stderr" ]
+    }
+    args += [
+              "--path=$nodejs_bin",
+              "node",
+              rebase_path("node_modules/.bin/$_node_cmd", root_build_dir),
+            ] + invoker.args
+  }
+}
+
+# +----------------------------------------------------------------------------+
+# | Installs the node modules secified in package.json                         |
+# +----------------------------------------------------------------------------+
+action("node_modules") {
+  script = "../../gn/standalone/build_tool_wrapper.py"
+  stamp_file = "$dist_dir/.$target_name.stamp"
+  cur_dir = rebase_path(".", root_build_dir)
+  args = [
+    "--stamp",
+    rebase_path(stamp_file, root_build_dir),
+    "--chdir=$cur_dir",
+    "--path=$nodejs_bin",
+    "npm",
+    "install",
+  ]
+  inputs = [
+    "package.json",
+    "package-lock.json",
+  ]
+  outputs = [ stamp_file ]
+}
+
+copy("assets_dist") {
+  sources = [
+    "node_modules/highlight.js/styles/tomorrow-night.css",
+    "node_modules/mermaid/dist/mermaid.min.js",
+    "src/assets/analysis.png",
+    "src/assets/app_tracing.png",
+    "src/assets/brand.png",
+    "src/assets/favicon.png",
+    "src/assets/home.png",
+    "src/assets/script.js",
+    "src/assets/sprite.png",
+    "src/assets/sys_profiling.png",
+    "src/assets/ui.png",
+  ]
+  outputs = [ "$dist_dir/assets/{{source_file_part}}" ]
+}
+
+node_bin("scss") {
+  inputs = [ "src/assets/style.scss" ]
+  outputs = [ "$dist_dir/assets/style.css" ]
+  node_cmd = "node-sass"
+  args = [
+    "--quiet",
+    rebase_path(inputs[0], root_build_dir),
+    rebase_path(outputs[0], root_build_dir),
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Markdown generation                                                        |
+# +----------------------------------------------------------------------------+
+
+html_templates = [
+  "src/template_header.html",
+  "src/template_footer.html",
+  "src/template_index.html",
+  "src/template_markdown.html",
+]
+
+# Renderers a markdown file into a HTML.
+# Args:
+#  markdown:        [in]  The source markdown file.
+#  html_template:   [in]  HTML template (optional).
+#  out_html:        [out] The generated HTML.
+template("md_to_html") {
+  action(target_name) {
+    js_src = "src/markdown_render.js"
+    script = "../../gn/standalone/build_tool_wrapper.py"
+    outputs = [ invoker.out_html ]
+    inputs = [ js_src ] + html_templates
+    args = [
+      "--path=$nodejs_bin",
+      "node",
+      rebase_path(js_src, root_build_dir),
+      "--odir",
+      rebase_path(dist_dir, root_build_dir),
+      "-o",
+      rebase_path(outputs[0], root_build_dir),
+    ]
+    if (defined(invoker.html_template)) {
+      args += [
+        "-t",
+        invoker.html_template,
+      ]
+      inputs += [ invoker.html_template ]
+    }
+    if (defined(invoker.markdown)) {
+      args += [
+        "-i",
+        rebase_path(invoker.markdown, root_build_dir),
+      ]
+      inputs += [ invoker.markdown ]
+    }
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
+  }
+}
+
+# Generates a .md file from a .proto.
+# Args:
+#  proto_src: [in]
+#  proto_root_type: [in]
+#  markdown_out: [in]
+template("gen_proto_reference_md") {
+  action(target_name) {
+    js_src = "src/gen_proto_reference.js"
+    script = "../../gn/standalone/build_tool_wrapper.py"
+    inputs = [
+      invoker.proto_src,
+      js_src,
+    ]
+    outputs = [ invoker.markdown_out ]
+    args = [
+      "--path=$nodejs_bin",
+      "node",
+      rebase_path(js_src, root_build_dir),
+      "-o",
+      rebase_path(invoker.markdown_out, root_build_dir),
+      "-i",
+      rebase_path(invoker.proto_src, root_build_dir),
+      "-p",
+      invoker.proto_root_type,
+    ]
+  }
+}
+
+# +----------------------------------------------------------------------------+
+# | /reference/ auto-generated docs                                            |
+# +----------------------------------------------------------------------------+
+
+# Generates a .html from a proto (proto -> md -> html).
+template("gen_proto_reference_html") {
+  intermediate_md = "$target_out_dir/$target_name.md"
+  gen_proto_reference_md("${target_name}_md") {
+    proto_src = invoker.proto_src
+    proto_root_type = invoker.proto_root_type
+    markdown_out = intermediate_md
+  }
+  md_to_html(target_name) {
+    deps = [
+      ":${target_name}_md",
+      ":navmap",
+    ]
+    markdown = intermediate_md
+    out_html = invoker.out_html
+    html_template = rebase_path("src/template_markdown.html", root_build_dir)
+  }
+}
+
+gen_proto_reference_html("trace_config_reference") {
+  proto_src = "../../protos/perfetto/config/trace_config.proto"
+  proto_root_type = "perfetto.protos.TraceConfig"
+  out_html = "$dist_dir/docs/reference/trace-config-proto"
+}
+
+gen_proto_reference_html("trace_packet_reference") {
+  proto_src = "../../protos/perfetto/trace/trace_packet.proto"
+  proto_root_type = "perfetto.protos.TracePacket"
+  out_html = "$dist_dir/docs/reference/trace-packet-proto"
+}
+
+# Generates the HTML for the sidebar.
+md_to_html("navmap") {
+  markdown = "../../docs/toc.md"
+  out_html = "$dist_dir/docs/_nav.html"
+}
+
+# Generates the root index.html.
+md_to_html("index_dist") {
+  html_template = rebase_path("src/template_index.html", root_build_dir)
+  out_html = "$dist_dir/index.html"
+}
+
+tp_tables_list = "$target_out_dir/tables.deps"
+exec_script("../../gn/standalone/glob.py",
+            [
+              "--root=" + rebase_path("../../src/trace_processor/tables",
+                                      root_build_dir),
+              "--filter=*.h",
+              "--output=" + rebase_path(tp_tables_list),
+            ])
+
+action("sql_tables_reference_md") {
+  js_src = "src/gen_sql_tables_reference.js"
+  script = "../../gn/standalone/build_tool_wrapper.py"
+  tp_table_hdrs = read_file(tp_tables_list, "list lines")
+  inputs = tp_table_hdrs + [ js_src ]
+  outputs = [ "$target_out_dir/sql-tables.autogen" ]
+  args = [
+    "--path=$nodejs_bin",
+    "node",
+    rebase_path(js_src, root_build_dir),
+    "-o",
+    rebase_path(outputs[0], root_build_dir),
+  ]
+  foreach(table_hdr, tp_table_hdrs) {
+    args += [
+      "-i",
+      table_hdr,
+    ]
+  }
+}
+
+md_to_html("sql_tables_reference") {
+  deps = [
+    ":navmap",
+    ":sql_tables_reference_md",
+  ]
+  markdown = "$target_out_dir/sql-tables.autogen"
+  out_html = "$dist_dir/docs/analysis/sql-tables"
+  html_template = rebase_path("src/template_markdown.html", root_build_dir)
+}
+
+action("stats_reference_md") {
+  js_src = "src/gen_stats_reference.js"
+  script = "../../gn/standalone/build_tool_wrapper.py"
+  input = "../../src/trace_processor/storage/stats.h"
+  inputs = [
+    input,
+    js_src,
+  ]
+  outputs = [ "$target_out_dir/sql-stats.autogen" ]
+  args = [
+    "--path=$nodejs_bin",
+    "node",
+    rebase_path(js_src, root_build_dir),
+    "-o",
+    rebase_path(outputs[0], root_build_dir),
+    "-i",
+    "../../src/trace_processor/storage/stats.h",
+  ]
+}
+
+md_to_html("stats_reference") {
+  deps = [
+    ":navmap",
+    ":stats_reference_md",
+  ]
+  markdown = "$target_out_dir/sql-stats.autogen"
+  out_html = "$dist_dir/docs/analysis/sql-stats"
+  html_template = rebase_path("src/template_markdown.html", root_build_dir)
+}
+
+# Generates a HTML file for each //docs/**/*.md.
+md_file_list = "$target_out_dir/docs.deps"
+exec_script("../../gn/standalone/glob.py",
+            [
+              "--root=" + rebase_path("../../docs", root_build_dir),
+              "--filter=*.md",
+              "--output=" + rebase_path(md_file_list),
+            ],
+            "",
+            [ "../../docs/toc.md" ])
+all_md_targets = []
+foreach(source, read_file(md_file_list, "list lines")) {
+  target_name = "gen_$source"
+  all_md_targets += [ ":$target_name" ]
+  md_to_html(target_name) {
+    deps = [ ":navmap" ]
+    base_name = string_replace(rebase_path(source, "../../docs"), ".md", "")
+    if (base_name == "README") {
+      base_name = "index.html"
+    }
+    markdown = source
+    out_html = "$dist_dir/docs/$base_name"
+    html_template = rebase_path("src/template_markdown.html", root_build_dir)
+  }
+}
+
+group("markdown") {
+  deps = all_md_targets
+  deps += [
+    ":sql_tables_reference",
+    ":stats_reference",
+    ":trace_config_reference",
+    ":trace_packet_reference",
+  ]
+}
diff --git a/infra/perfetto.dev/app.yaml b/infra/perfetto.dev/app.yaml
new file mode 100644
index 0000000..d20e18f
--- /dev/null
+++ b/infra/perfetto.dev/app.yaml
@@ -0,0 +1,45 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+runtime: python37
+default_expiration: "5m"
+handlers:
+- url: /$
+  static_files: dist/index.html
+  upload: dist/index.html
+  secure: always
+  redirect_http_response_code: 301
+- url: /docs/?$
+  static_files: dist/docs/index.html
+  upload: dist/docs/index.html
+  mime_type: text/html
+  secure: always
+  redirect_http_response_code: 301
+- url: /docs/(.*\.svg)$
+  static_files: dist/docs/\1
+  mime_type: image/svg+xml
+  upload: dist/docs/.*\.svg$
+- url: /docs/(.*/[A-Za-z0-9-_]+)$
+  static_files: dist/docs/\1
+  mime_type: text/html
+  upload: dist/docs/.*/[A-Za-z0-9-_]+$
+  secure: always
+  redirect_http_response_code: 301
+- url: /assets/
+  static_dir: dist/assets
+  expiration: 60m
+- url: /
+  static_dir: dist/
+  secure: always
+  redirect_http_response_code: 301
diff --git a/infra/perfetto.dev/appengine/.gcloudignore b/infra/perfetto.dev/appengine/.gcloudignore
deleted file mode 100644
index d671c50..0000000
--- a/infra/perfetto.dev/appengine/.gcloudignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.gcloudignore
-.gitignore
-deploy
\ No newline at end of file
diff --git a/infra/perfetto.dev/appengine/README.md b/infra/perfetto.dev/appengine/README.md
deleted file mode 100644
index 3c2348a..0000000
--- a/infra/perfetto.dev/appengine/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# www.perfetto.dev Cloud scripts
-
-The docs site follows the same architecture of ui.perfetto.dev.
-See [go/perfetto-ui-autopush](http://go/perfetto-ui-autopush) for docs.
-
-## /appengine : GAE <> GCS proxy
-
-The Google AppEngine instance that responds to www.perfetto.dev.
-It simply passes through the requests to the bucket gs://perfetto.dev .
-This should NOT be re-deployed when uploading new docs, as the actual
-artifacts live in GCS.
-
-We are using AppEngine for historical reasons, at some point this should
-be migrated to a Type 7 Google Cloud Load Balancer, which supports
-direct backing by a GCS bucket.
diff --git a/infra/perfetto.dev/appengine/app.yaml b/infra/perfetto.dev/appengine/app.yaml
deleted file mode 100644
index 1f4e65c..0000000
--- a/infra/perfetto.dev/appengine/app.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-runtime: python38
-instance_class: B1
-basic_scaling:
-  max_instances: 4
-  idle_timeout: 10m
diff --git a/infra/perfetto.dev/appengine/deploy b/infra/perfetto.dev/appengine/deploy
deleted file mode 100755
index 7cafa17..0000000
--- a/infra/perfetto.dev/appengine/deploy
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 script deploys the AppEngine instance that acts as a proxy for the GCS
-# bucket gs://perfetto.dev. This does NOT need to be re-deployed when docs
-# change. See go/perfetto-ui-autopush for details.
-
-set -eu
-
-readonly CUR_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-
-cd $CUR_DIR
-
-VERSION=testing
-PROMOTE=--no-promote
-
-while [[ $# -gt 0 ]]; do
-  key="$1"
-  case $key in
-      --prod)
-      VERSION=prod
-      PROMOTE=--promote
-      shift
-      ;;
-      *)
-      echo "Usage: $0 [--prod]"
-      echo "    --prod      Deploy prod version"
-      echo "    -h|--help   Display this message"
-      exit 0
-      shift
-      ;;
-  esac
-done
-
-set -x
-gcloud app deploy app.yaml --project perfetto-site \
-    -v $VERSION $PROMOTE --stop-previous-version
diff --git a/infra/perfetto.dev/appengine/main.py b/infra/perfetto.dev/appengine/main.py
deleted file mode 100644
index 6baa0d3..0000000
--- a/infra/perfetto.dev/appengine/main.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 flask
-import os
-
-from google.cloud import storage
-
-BUCKET_NAME = 'perfetto.dev'
-
-app = flask.Flask(__name__)
-bucket = None
-is_local_testing_instance = False
-
-
-@app.route('/_ah/<path:path>')
-def ignore_app_engine_lifecycle(path):
-  return flask.abort(404)
-
-
-@app.route('/docs')
-def docs_redirect():
-  return flask.redirect('/docs/', code=301)
-
-
-# Serve the requests from the GCS bucket.
-@app.route('/', methods=['GET'])
-@app.route('/<path:path>', methods=['GET'])
-def main(path=''):
-  # Force redirect HTTP -> HTTPS.
-  if not flask.request.is_secure and not is_local_testing_instance:
-    https_url = flask.request.url.replace('http://', 'https://', 1)
-    return flask.redirect(https_url, code=301)
-  if flask.request.host == 'www.perfetto.dev':
-    return flask.redirect(
-        flask.request.url.replace('www.perfetto.dev', 'perfetto.dev'))
-  if flask.request.host == 'docs.perfetto.dev':
-    return flask.redirect('https://perfetto.dev/docs/')
-
-  path = '/' + path
-  path += 'index.html' if path.endswith('/') else ''
-  global bucket
-  if bucket is None:
-    bucket = storage.Client().get_bucket(BUCKET_NAME)
-  blob = bucket.get_blob(path[1:])
-  if blob is None:
-    return flask.abort(404)
-  data = blob.download_as_bytes()
-  resp = flask.Response(data)
-  resp.headers['Content-Type'] = blob.content_type
-  resp.headers['Content-Length'] = len(data)
-  resp.headers['Content-Encoding'] = blob.content_encoding
-  if os.path.splitext(path)[1] in ('.png', '.svg'):
-    resp.headers['Cache-Control'] = 'public, max-age=86400'  # 1 Day
-  else:
-    resp.headers['Cache-Control'] = 'public, max-age=600'  # 10 min
-  return resp
-
-
-def get_credentials_for_local_testing():
-  from google_auth_oauthlib import flow
-  flow = flow.InstalledAppFlow.from_client_config(
-      client_config={
-          'installed': {
-              # These aren't secret. Copied from gsutil's apitools sources.
-              'client_id': '1042881264118.apps.googleusercontent.com',
-              'client_secret': 'x_Tw5K8nnjoRAqULM9PFAC2b',
-              'redirect_uris': ['urn:ietf:wg:oauth:2.0:oob'],
-              'auth_uri': 'https://accounts.google.com/o/oauth2/auth',
-              'token_uri': 'https://accounts.google.com/o/oauth2/token'
-          }
-      },
-      scopes=['https://www.googleapis.com/auth/devstorage.read_only'])
-  creds = flow.run_console()
-  return creds
-
-
-if __name__ == '__main__':
-  # This is used when running locally only.
-  creds = get_credentials_for_local_testing()
-  storage_client = storage.Client(project='perfetto-site', credentials=creds)
-  bucket = storage_client.bucket(BUCKET_NAME)
-  is_local_testing_instance = True
-  app.run(host='127.0.0.1', port=8082, debug=False)
diff --git a/infra/perfetto.dev/appengine/requirements.txt b/infra/perfetto.dev/appengine/requirements.txt
deleted file mode 100644
index 9dc4af3..0000000
--- a/infra/perfetto.dev/appengine/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Flask==1.1.2
-google-cloud-storage
diff --git a/infra/perfetto.dev/build b/infra/perfetto.dev/build
deleted file mode 100755
index 59a1c35..0000000
--- a/infra/perfetto.dev/build
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 -eu
-
-# cd into the //infra/perfetto.dev dir, so this works uniformely when invoked by
-# other paths. the cd is required for npm install.
-cd -P ${BASH_SOURCE[0]%/*}
-
-# Ensure that `npm install` has been called and is current. Note that the set of
-# packages that the docs website requires is != the UI ones.
-if ! test node_modules/.stamp -nt package-lock.json; then
-  ../../tools/npm install
-  touch node_modules/.stamp
-fi
-
-../../tools/node ./build.js "$@"
diff --git a/infra/perfetto.dev/build.js b/infra/perfetto.dev/build.js
deleted file mode 100644
index 1fc657c..0000000
--- a/infra/perfetto.dev/build.js
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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';
-
-// This script builds the perfetto.dev docs website.
-
-const argparse = require('argparse');
-const child_process = require('child_process');
-const fs = require('fs');
-const http = require('http');
-const path = require('path');
-const fswatch = require('node-watch');  // Like fs.watch(), but works on Linux.
-const pjoin = path.join;
-
-const ROOT_DIR = path.dirname(path.dirname(__dirname));  // The repo root.
-
-const cfg = {
-  watch: false,
-  verbose: false,
-  startHttpServer: false,
-
-  outDir: pjoin(ROOT_DIR, 'out/perfetto.dev'),
-};
-
-const RULES = [
-  {r: /infra\/perfetto.dev\/src\/assets\/((.*)\.png)/, f: copyAssets},
-  {r: /infra\/perfetto.dev\/src\/assets\/((.*)\.js)/, f: copyAssets},
-  {r: /infra\/perfetto.dev\/node_modules\/.*\/(.*\.css|.*\.js)/, f: copyAssets},
-  {r: /infra\/perfetto.dev\/src\/assets\/.+\.scss/, f: compileScss},
-  {
-    r: /protos\/perfetto\/config\/trace_config\.proto/,
-    f: s => genProtoReference(s, 'perfetto.protos.TraceConfig')
-  },
-  {
-    r: /protos\/perfetto\/trace\/trace_packet\.proto/,
-    f: s => genProtoReference(s, 'perfetto.protos.TracePacket')
-  },
-  {r: /src\/trace_processor\/storage\/stats\.h/, f: genSqlStatsReference},
-  {r: /src\/trace_processor\/tables\/.*\.h/, f: s => sqlTables.add(s)},
-  {r: /docs\/toc[.]md/, f: genNav},
-  {r: /docs\/.*[.]md/, f: renderDoc},
-];
-
-let sqlTables = new Set();
-let tasks = [];
-let tasksTot = 0, tasksRan = 0;
-let tStart = Date.now();
-
-function main() {
-  const parser = new argparse.ArgumentParser();
-  parser.add_argument('--out', {help: 'Output directory'});
-  parser.add_argument('--watch', '-w', {action: 'store_true'});
-  parser.add_argument('--serve', '-s', {action: 'store_true'});
-  parser.add_argument('--verbose', '-v', {action: 'store_true'});
-
-  const args = parser.parse_args();
-  cfg.outDir = path.resolve(ensureDir(args.out || cfg.outDir, /*clean=*/ true));
-  cfg.watch = !!args.watch;
-  cfg.verbose = !!args.verbose;
-  cfg.startHttpServer = args.serve;
-
-  // Check that deps are current before starting.
-  const installBuildDeps = pjoin(ROOT_DIR, 'tools/install-build-deps');
-
-  // --filter=nodejs is to match what cloud_build_entrypoint.sh passes to
-  // install-build-deps. It doesn't bother installing the full toolchains
-  // because, unlike the Perfetto UI, it doesn't need Wasm.
-  const depsArgs = ['--check-only=/dev/null', '--ui', '--filter=nodejs'];
-  exec(installBuildDeps, depsArgs);
-
-  console.log('Entering', cfg.outDir);
-  process.chdir(cfg.outDir);
-
-  scanDir('infra/perfetto.dev/src/assets');
-  scanFile(
-      'infra/perfetto.dev/node_modules/highlight.js/styles/tomorrow-night.css');
-  scanFile('infra/perfetto.dev/node_modules/mermaid/dist/mermaid.min.js');
-  scanFile('docs/toc.md');
-  genIndex();
-  scanFile('src/trace_processor/storage/stats.h');
-  scanDir('src/trace_processor/tables');
-  scanDir('protos');
-  genSqlTableReference();
-  scanDir('docs');
-  if (args.serve) {
-    addTask(startServer);
-  }
-}
-
-// -----------
-// Build rules
-// -----------
-
-function copyAssets(src, dst) {
-  addTask(cp, [src, pjoin(cfg.outDir, 'assets', dst)]);
-}
-
-function compileScss() {
-  const src = pjoin(__dirname, 'src/assets/style.scss');
-  const dst = pjoin(cfg.outDir, 'assets/style.css');
-  // In watch mode, don't exit(1) if scss fails. It can easily happen by
-  // having a typo in the css. It will still print an errror.
-  const noErrCheck = !!cfg.watch;
-  addTask(
-      execNode,
-      ['node_modules/.bin/node-sass', ['--quiet', src, dst], {noErrCheck}]);
-}
-
-function md2html(src, dst, template) {
-  const script = pjoin(__dirname, 'src/markdown_render.js');
-  const args = ['-i', src, '--odir', cfg.outDir, '-o', dst];
-  ensureDir(path.dirname(dst));
-  if (template) args.push('-t', pjoin(__dirname, 'src', template));
-  execNode(script, args);
-}
-
-function proto2md(src, dst, protoRootType) {
-  const script = pjoin(__dirname, 'src/gen_proto_reference.js');
-  const args = ['-i', src, '-p', protoRootType, '-o', dst];
-  ensureDir(path.dirname(dst));
-  execNode(script, args);
-}
-
-function genNav(src) {
-  const dst = pjoin(cfg.outDir, 'docs', '_nav.html');
-  addTask(md2html, [src, dst]);
-}
-
-function genIndex() {
-  const dst = pjoin(cfg.outDir, 'index.html');
-  addTask(md2html, ['/dev/null', dst, 'template_index.html']);
-}
-
-function renderDoc(src) {
-  let dstRel = path.relative(ROOT_DIR, src);
-  dstRel = dstRel.replace('.md', '').replace(/\bREADME$/, 'index.html');
-  const dst = pjoin(cfg.outDir, dstRel);
-  addTask(md2html, [src, dst, 'template_markdown.html']);
-}
-
-function genProtoReference(src, protoRootType) {
-  const fname = path.basename(src);
-  const dstFname = fname.replace(/[._]/g, '-');
-  const dstHtml = pjoin(cfg.outDir, 'docs/reference', dstFname);
-  const dstMd = dstHtml + '.md';
-  addTask(proto2md, [src, dstMd, protoRootType]);
-  addTask(md2html, [dstMd, dstHtml, 'template_markdown.html']);
-  addTask(exec, ['rm', [dstMd]]);
-}
-
-function genSqlStatsReference(src) {
-  const dstDir = ensureDir(pjoin(cfg.outDir, 'docs/analysis'));
-  const dstHtml = pjoin(dstDir, 'sql-stats');
-  const dstMd = dstHtml + '.md';
-  const script = pjoin(__dirname, 'src/gen_stats_reference.js');
-  const args = ['-i', src, '-o', dstMd];
-  addTask(execNode, [script, args]);
-  addTask(md2html, [dstMd, dstHtml, 'template_markdown.html']);
-  addTask(exec, ['rm', [dstMd]]);
-}
-
-function genSqlTableReference() {
-  const dstDir = ensureDir(pjoin(cfg.outDir, 'docs/analysis'));
-  const dstHtml = pjoin(dstDir, 'sql-tables');
-  const dstMd = dstHtml + '.md';
-  const script = pjoin(__dirname, 'src/gen_sql_tables_reference.js');
-  const args = ['-o', dstMd];
-  sqlTables.forEach(f => args.push('-i', f));
-  addTask(execNode, [script, args]);
-  addTask(md2html, [dstMd, dstHtml, 'template_markdown.html']);
-  addTask(exec, ['rm', [dstMd]]);
-}
-
-function startServer() {
-  const port = 8082;
-  console.log(`Starting HTTP server on http://localhost:${port}`)
-  http.createServer(function(req, res) {
-        console.debug(req.method, req.url);
-        let uri = req.url.split('?', 1)[0];
-        uri += uri.endsWith('/') ? 'index.html' : '';
-
-        const absPath = path.normalize(path.join(cfg.outDir, uri));
-        fs.readFile(absPath, function(err, data) {
-          if (err) {
-            res.writeHead(404);
-            res.end(JSON.stringify(err));
-            return;
-          }
-          const mimeMap = {
-            'css': 'text/css',
-            'svg': 'image/svg+xml',
-            'js': 'application/javascript',
-          };
-          const contentType = mimeMap[uri.split('.').pop()] || 'text/html';
-          const head = {
-            'Content-Type': contentType,
-            'Content-Length': data.length,
-            'Cache-Control': 'no-cache',
-          };
-          res.writeHead(200, head);
-          res.end(data);
-        });
-      })
-      .listen(port);
-}
-
-
-// -----------------------
-// Task chaining functions
-// -----------------------
-
-function addTask(func, args) {
-  const task = new Task(func, args);
-  for (const t of tasks) {
-    if (t.identity === task.identity) {
-      return;
-    }
-  }
-  tasks.push(task);
-  setTimeout(runTasks, 0);
-}
-
-function runTasks() {
-  const snapTasks = tasks.splice(0);  // snap = std::move(tasks).
-  tasksTot += snapTasks.length;
-  for (const task of snapTasks) {
-    const DIM = '\u001b[2m';
-    const BRT = '\u001b[37m';
-    const RST = '\u001b[0m';
-    const ms = (new Date(Date.now() - tStart)).toISOString().slice(17, -1);
-    const ts = `[${DIM}${ms}${RST}]`;
-    const descr = task.description.substr(0, 80);
-    console.log(`${ts} ${BRT}${++tasksRan}/${tasksTot}${RST}\t${descr}`);
-    task.func.apply(/*this=*/ undefined, task.args);
-  }
-}
-
-// Executes the first rule in RULES that match the given |absPath|.
-function scanFile(file) {
-  const absPath = path.isAbsolute(file) ? file : pjoin(ROOT_DIR, file);
-  console.assert(fs.existsSync(absPath));
-  const normPath = path.relative(ROOT_DIR, absPath);
-  for (const rule of RULES) {
-    const match = rule.r.exec(normPath);
-    if (!match || match[0] !== normPath) continue;
-    const captureGroup = match.length > 1 ? match[1] : undefined;
-    rule.f(absPath, captureGroup);
-    return;
-  }
-}
-
-// Walks the passed |dir| recursively and, for each file, invokes the matching
-// RULES. If --watch is used, it also installs a fswatch() and re-triggers the
-// matching RULES on each file change.
-function scanDir(dir, regex) {
-  const filterFn = regex ? absPath => regex.test(absPath) : () => true;
-  const absDir = path.isAbsolute(dir) ? dir : pjoin(ROOT_DIR, dir);
-  // Add a fs watch if in watch mode.
-  if (cfg.watch) {
-    fswatch(absDir, {recursive: true}, (_eventType, filePath) => {
-      if (!filterFn(filePath)) return;
-      if (cfg.verbose) {
-        console.log('File change detected', _eventType, filePath);
-      }
-      if (fs.existsSync(filePath)) {
-        scanFile(filePath, filterFn);
-      }
-    });
-  }
-  walk(absDir, f => {
-    if (filterFn(f)) scanFile(f);
-  });
-}
-
-function exec(cmd, args, opts) {
-  opts = opts || {};
-  opts.stdout = opts.stdout || 'inherit';
-  if (cfg.verbose) console.log(`${cmd} ${args.join(' ')}\n`);
-  const spwOpts = {cwd: cfg.outDir, stdio: ['ignore', opts.stdout, 'inherit']};
-  const checkExitCode = (code, signal) => {
-    if (signal === 'SIGINT' || signal === 'SIGTERM') return;
-    if (code !== 0 && !opts.noErrCheck) {
-      console.error(`${cmd} ${args.join(' ')} failed with code ${code}`);
-      process.exit(1);
-    }
-  };
-  const spawnRes = child_process.spawnSync(cmd, args, spwOpts);
-  checkExitCode(spawnRes.status, spawnRes.signal);
-  return spawnRes;
-}
-
-function execNode(script, args, opts) {
-  const modPath = path.isAbsolute(script) ? script : pjoin(__dirname, script);
-  const nodeBin = pjoin(ROOT_DIR, 'tools/node');
-  args = [modPath].concat(args || []);
-  return exec(nodeBin, args, opts);
-}
-
-// ------------------------------------------
-// File system & subprocess utility functions
-// ------------------------------------------
-
-class Task {
-  constructor(func, args) {
-    this.func = func;
-    this.args = args || [];
-    // |identity| is used to dedupe identical tasks in the queue.
-    this.identity = JSON.stringify([this.func.name, this.args]);
-  }
-
-  get description() {
-    const ret = this.func.name.startsWith('exec') ? [] : [this.func.name];
-    const flattenedArgs = [].concat.apply([], this.args);
-    for (const arg of flattenedArgs) {
-      const argStr = `${arg}`;
-      if (argStr.startsWith('/')) {
-        ret.push(path.relative(cfg.outDir, arg));
-      } else {
-        ret.push(argStr);
-      }
-    }
-    return ret.join(' ');
-  }
-}
-
-function walk(dir, callback, skipRegex) {
-  for (const child of fs.readdirSync(dir)) {
-    const childPath = pjoin(dir, child);
-    const stat = fs.lstatSync(childPath);
-    if (skipRegex !== undefined && skipRegex.test(child)) continue;
-    if (stat.isDirectory()) {
-      walk(childPath, callback, skipRegex);
-    } else if (!stat.isSymbolicLink()) {
-      callback(childPath);
-    }
-  }
-}
-
-function ensureDir(dirPath, clean) {
-  const exists = fs.existsSync(dirPath);
-  if (exists && clean) {
-    if (cfg.verbose) console.log('rm', dirPath);
-    fs.rmSync(dirPath, {recursive: true});
-  }
-  if (!exists || clean) fs.mkdirSync(dirPath, {recursive: true});
-  return dirPath;
-}
-
-function cp(src, dst) {
-  ensureDir(path.dirname(dst));
-  if (cfg.verbose) {
-    console.log(
-        'cp', path.relative(ROOT_DIR, src), '->', path.relative(ROOT_DIR, dst));
-  }
-  fs.copyFileSync(src, dst);
-}
-
-main();
diff --git a/infra/perfetto.dev/cloud_build_entrypoint.sh b/infra/perfetto.dev/cloud_build_entrypoint.sh
deleted file mode 100755
index 4497867..0000000
--- a/infra/perfetto.dev/cloud_build_entrypoint.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 -exu
-
-# This script will be run in /workspace after the Cloud Build environment has
-# pulled the GitHub repo in shallow mode. We want to build off the official
-# AOSP repo, not the GitHub mirror though, hence why the clone below.
-# GitHub is used only as a trigger. This is because Google Cloud Build doesn't
-# support yet triggering from Gerrit.
-# See go/perfetto-ui-autopush for more details.
-
-# The cd is really a safeguard against people running this script on their
-# workstation and hitting the rm -rf.
-cd /workspace/
-ls -A1 | xargs rm -rf
-UPSTREAM="https://android.googlesource.com/platform/external/perfetto.git"
-git clone --depth 1 $UPSTREAM upstream
-
-cd upstream/
-git rev-parse HEAD
-
-# Install only NodeJS, no need to install the other toolchains.
-tools/install-build-deps --ui --filter=nodejs
-
-# The deploy script takes care of building by invoking ./build internally.
-infra/perfetto.dev/deploy
diff --git a/infra/perfetto.dev/cloudbuild.yaml b/infra/perfetto.dev/cloudbuild.yaml
deleted file mode 100644
index f8e0889..0000000
--- a/infra/perfetto.dev/cloudbuild.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-# See go/perfetto-ui-autopush for docs on how this works end-to-end.
-# Reuse the same Docker container of the UI autopusher.
-steps:
-- name: gcr.io/perfetto-ui/perfetto-ui-builder
-  args:
-  - 'infra/perfetto.dev/cloud_build_entrypoint.sh'
-# Timeout: 15 min (last measured time in Feb 2021: 2 min)
-timeout: 900s
diff --git a/infra/perfetto.dev/deploy b/infra/perfetto.dev/deploy
index 825f9e7..0b8336b 100755
--- a/infra/perfetto.dev/deploy
+++ b/infra/perfetto.dev/deploy
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
+# 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.
@@ -13,61 +13,68 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This script builds the perfetto.dev docs website (via ./build) and pushes the
-# contents to the gs://perfetto.dev GCS bucket. It doesn't re-deploy the
-# AppEngine instance, as that doesn't depend on the contents (use
-# ./appengine/deploy for that).
-# This is ran by the Cloud Build infrastructure (./cloudbuild.yaml) whenever a
-# docs/ change is detected. See go/perfetto-ui-autopush for more details.
+set -e
 
-set -eux
-
-# The directory that contains this script (//infra/perfetto.dev)
 readonly CUR_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-
-# The repo root.
 readonly ROOT_DIR=$(dirname $(dirname "$CUR_DIR"))
+readonly NODE_DIR="$ROOT_DIR/buildtools/nodejs/bin"
+readonly WRAPPER="$ROOT_DIR/gn/standalone/build_tool_wrapper.py"
 
-# The directory that will contain the static website artifacts.
-readonly OUT_DIR="$ROOT_DIR/out/perfetto.dev"
+cd $CUR_DIR
 
-# Build first.
-"$CUR_DIR/build"
+function echo_and_do {
+  echo $@
+  $@
+}
 
-# The markdown docs are rendered into extension-less HTML files to make the URLs
-# look nice (e.g., /docs/tracing rather than /docs/tracing.html). By default
-# gsutil infers the mime-type from the extension, falling back to octet/stream
-# for extension-less fiels. octect/stream causes the browser to download the
-# file rather than parsing it as a web page.
-# We set use_magicfile = True here, which causes gsutil to infer the MIME type
-# by invoking `file -b --mime /path/to/file`.
-# Unfortunately, that solves the HTML MIME problem but adds another one: the
-# standard `file` util doesn't deal with .css files and marks them as text/plain
-# causing the browser to ignore the CSS.
-# Here what we do is replacing the standard `file` util with a custom made one
-# (mime_util/file) which sets the right MIME types we want. We do this by
-# prepending our script to the PATH.
-export PATH="$CUR_DIR/mime_util:$PATH"
-export BOTO_CONFIG=/tmp/boto
-cat << EOF > $BOTO_CONFIG
-[GSUtil]
-use_magicfile = True
+function npm {
+  echo_and_do python "$WRAPPER" --path $NODE_DIR npm $@
+}
 
-EOF
+CLEAN_OUT_DIR=true
+DEPLOY_PROD=false
+DEPLOY_STAGING=false
 
-# Basic checks before uploading. Test both the existence and the mime type.
-[ "$(file $OUT_DIR/index.html)" == "text/html" ]
-[ "$(file $OUT_DIR/assets/style.css)" == "text/css" ]
-[ "$(file $OUT_DIR/assets/home.png)" == "image/png" ]
-[ "$(file $OUT_DIR/docs/images/perfetto-stack.svg)" == "image/svg+xml" ]
-[ "$(file $OUT_DIR/docs/images/perfetto-stack.svg)" == "image/svg+xml" ]
-[ "$(file $OUT_DIR/docs/analysis/sql-tables)" == "text/html" ]
+while [[ $# -gt 0 ]]; do
+  key="$1"
+  case $key in
+      --no-clean)
+      CLEAN_OUT_DIR=false
+      shift
+      ;;
+      --prod)
+      DEPLOY_PROD=true
+      shift
+      ;;
+      --staging)
+      DEPLOY_STAGING=true
+      shift
+      ;;
+      -h|--help)
+      echo "Usage: $0 [--no-clean] [--prod] [--staging]"
+      echo "    --no-clean  Don't remove the out directory"
+      echo "    --prod      Deploy prod version (implies --release)"
+      echo "    --staging   Deploy staging version"
+      echo "    -h|--help   Display this message"
+      exit 0
+      shift
+      ;;
+  esac
+done
 
-# -j: apply 'Content-Encoding: gzip' compression to passed extensions.
-# -d: mirror also deletetions.
-# -c: compare checksums, not mtimes.
-# -r: recursive.
-# The trailing slash appended to $OUT_DIR is to prevent that gsutil creates a
-# nested sub-directory inside gs://perfetto.dev/.
-gsutil -m rsync -j html,js,css,svg -d -c -r \
-  "$OUT_DIR/" gs://perfetto.dev/
+if [ "$CLEAN_OUT_DIR" = true ]; then
+  npm run clean
+fi
+
+npm run build
+
+if [ "$DEPLOY_PROD" = true ]; then
+  echo_and_do gcloud app deploy app.yaml --project perfetto-site \
+      -v prod --promote --stop-previous-version
+elif [ "$DEPLOY_STAGING" = true ]; then
+  echo_and_do gcloud app deploy app.yaml --project perfetto-site \
+      -v staging --no-promote --stop-previous-version
+else
+  echo_and_do gcloud app deploy app.yaml --project perfetto-site \
+      -v $USER --no-promote --stop-previous-version
+fi
diff --git a/infra/perfetto.dev/dispatch.yaml b/infra/perfetto.dev/dispatch.yaml
new file mode 100644
index 0000000..8315963
--- /dev/null
+++ b/infra/perfetto.dev/dispatch.yaml
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dispatch:
+- url: "docs.perfetto.dev/*"
+  service: redirect
+- url: "www.perfetto.dev/*"
+  service: redirect
+- url: "*/*"
+  service: default
diff --git a/infra/perfetto.dev/dist b/infra/perfetto.dev/dist
new file mode 120000
index 0000000..eac3128
--- /dev/null
+++ b/infra/perfetto.dev/dist
@@ -0,0 +1 @@
+../../out/perfetto.dev/site
\ No newline at end of file
diff --git a/infra/perfetto.dev/main.py b/infra/perfetto.dev/main.py
new file mode 100644
index 0000000..610b746
--- /dev/null
+++ b/infra/perfetto.dev/main.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Deliberately empty. The site is fully static and doesn't need any server-side
+# component. This is only to keep dev_appserver.py happy.
\ No newline at end of file
diff --git a/infra/perfetto.dev/mime_util/file b/infra/perfetto.dev/mime_util/file
deleted file mode 100755
index ba687ec..0000000
--- a/infra/perfetto.dev/mime_util/file
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-import os
-
-def main():
-  # Typically the target file argument is the last arg. gsutil invokes:
-  # `file -b --mime /path/to/file`. Rathter than depending on it, just pick
-  # the right-most argument which points to a valid file.
-  fname = None
-  for arg in reversed(sys.argv[1:]):
-    if os.path.exists(arg):
-      fname = arg
-      break
-  if fname is None:
-    raise 'File not found in ' + ' '.join(sys.argv)
-
-  ext = os.path.splitext(fname)[1].lower()
-  ext_map = {
-    '.html': 'text/html',
-    '.css': 'text/css',
-    '.js': 'text/javascript',
-    '.jpg': 'image/jpeg',
-    '.png': 'image/png',
-    '.svg': 'image/svg+xml',
-  }
-  print(ext_map.get(ext, 'text/html'))
-  return 0
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/infra/perfetto.dev/package-lock.json b/infra/perfetto.dev/package-lock.json
index b722b8c..9f6302e 100644
--- a/infra/perfetto.dev/package-lock.json
+++ b/infra/perfetto.dev/package-lock.json
@@ -4,6 +4,12 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@blakeembrey/deque": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@blakeembrey/deque/-/deque-1.0.5.tgz",
+      "integrity": "sha512-6xnwtvp9DY1EINIKdTfvfeAtCYw4OqBZJhtiqkT3ivjnEfa25VQ3TsKvaFfKm8MyGIEfE95qLe+bNEt3nB0Ylg==",
+      "dev": true
+    },
     "@braintree/sanitize-url": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz",
@@ -73,6 +79,12 @@
       "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
       "dev": true
     },
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
+    },
     "@types/long": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
@@ -80,9 +92,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "13.13.41",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.41.tgz",
-      "integrity": "sha512-qLT9IvHiXJfdrje9VmsLzun7cQ65obsBTmtU3EOnCSLFOoSHx1hpiRHoBnpdbyFqnzqdUUIv81JcEJQCB8un9g==",
+      "version": "13.13.1",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.1.tgz",
+      "integrity": "sha512-uysqysLJ+As9jqI5yqjwP3QJrhOcUwBjHUlUxPxjbplwKoILvXVsmYWEhfmAQlrPfbRZmhJB007o4L9sKqtHqQ==",
       "dev": true
     },
     "abbrev": {
@@ -92,9 +104,9 @@
       "dev": true
     },
     "ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "version": "6.11.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
+      "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
       "dev": true,
       "requires": {
         "fast-deep-equal": "^3.1.1",
@@ -124,6 +136,16 @@
         "color-convert": "^1.9.0"
       }
     },
+    "anymatch": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
     "aproba": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -140,18 +162,18 @@
         "readable-stream": "^2.0.6"
       }
     },
-    "argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
     "array-find-index": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
       "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
       "dev": true
     },
+    "arrify": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+      "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+      "dev": true
+    },
     "asn1": {
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -167,12 +189,6 @@
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
       "dev": true
     },
-    "async": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
-      "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
-      "dev": true
-    },
     "async-foreach": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
@@ -198,9 +214,9 @@
       "dev": true
     },
     "aws4": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
-      "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
+      "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==",
       "dev": true
     },
     "balanced-match": {
@@ -218,6 +234,21 @@
         "tweetnacl": "^0.14.3"
       }
     },
+    "binary-extensions": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+      "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
+      "dev": true
+    },
+    "block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.0"
+      }
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -228,6 +259,15 @@
         "concat-map": "0.0.1"
       }
     },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
     "buffer-from": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -273,13 +313,34 @@
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
         "supports-color": "^5.3.0"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
       }
     },
-    "chownr": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
-      "dev": true
+    "chokidar": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
+      "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==",
+      "dev": true,
+      "requires": {
+        "anymatch": "~3.1.1",
+        "braces": "~3.0.2",
+        "fsevents": "~2.1.2",
+        "glob-parent": "~5.1.0",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.3.0"
+      }
     },
     "clean-css": {
       "version": "4.2.3",
@@ -287,51 +348,24 @@
       "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
       "requires": {
         "source-map": "~0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+        }
       }
     },
     "cliui": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+      "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
       "dev": true,
       "requires": {
-        "string-width": "^3.1.0",
-        "strip-ansi": "^5.2.0",
-        "wrap-ansi": "^5.1.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-          "dev": true
-        },
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wrap-ansi": "^2.0.0"
       }
     },
     "code-point-at": {
@@ -365,9 +399,9 @@
       }
     },
     "commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
+      "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0="
     },
     "concat-map": {
       "version": "0.0.1",
@@ -375,6 +409,23 @@
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
+    "concurrently": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-3.6.1.tgz",
+      "integrity": "sha512-/+ugz+gwFSEfTGUxn0KHkY+19XPRTXR8+7oUK/HxgiN1n7FjeJmkrbSiXAJfyQ0zORgJYPaenmymwon51YXH9Q==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.1",
+        "commander": "2.6.0",
+        "date-fns": "^1.23.0",
+        "lodash": "^4.5.1",
+        "read-pkg": "^3.0.0",
+        "rx": "2.3.24",
+        "spawn-command": "^0.0.2-1",
+        "supports-color": "^3.2.3",
+        "tree-kill": "^1.1.0"
+      }
+    },
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -388,14 +439,21 @@
       "dev": true
     },
     "cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+      "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
       "dev": true,
       "requires": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
+        "lru-cache": "^4.0.1",
+        "which": "^1.2.9"
+      }
+    },
+    "crypto-random-string": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-3.2.0.tgz",
+      "integrity": "sha512-8vPu5bsKaq2uKRy3OL7h1Oo7RayAWB8sYexLKAqvCXVib8SxgbmoF1IN4QMKjBv8uI8mp5gPPMbiRah25GMrVQ==",
+      "requires": {
+        "type-fest": "^0.8.1"
       }
     },
     "css-b64-images": {
@@ -461,9 +519,9 @@
       "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
     },
     "d3-brush": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz",
-      "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==",
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.5.tgz",
+      "integrity": "sha512-rEaJ5gHlgLxXugWjIkolTA0OyMvw8UWU1imYXy1v642XyyswmI1ybKOv05Ft+ewq+TFmdliD3VuK0pRp1VT/5A==",
       "requires": {
         "d3-dispatch": "1",
         "d3-drag": "1",
@@ -524,14 +582,14 @@
       }
     },
     "d3-ease": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
-      "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz",
+      "integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ=="
     },
     "d3-fetch": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz",
-      "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz",
+      "integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==",
       "requires": {
         "d3-dsv": "1"
       }
@@ -548,14 +606,14 @@
       }
     },
     "d3-format": {
-      "version": "1.4.5",
-      "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
-      "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.4.tgz",
+      "integrity": "sha512-TWks25e7t8/cqctxCmxpUuzZN11QxIA7YrMbram94zMQ0PXjE4LVIMe/f6a4+xxL8HQ3OsAFULOINQi1pE62Aw=="
     },
     "d3-geo": {
-      "version": "1.12.1",
-      "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
-      "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==",
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.0.tgz",
+      "integrity": "sha512-NalZVW+6/SpbKcnl+BCO67m8gX+nGeJdo6oGL9H6BRUGUL1e+AtPcP4vE4TwCQ/gl8y5KE7QvBzrLn+HsKIl+w==",
       "requires": {
         "d3-array": "1"
       }
@@ -616,9 +674,9 @@
       }
     },
     "d3-selection": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
-      "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.1.tgz",
+      "integrity": "sha512-BTIbRjv/m5rcVTfBs4AMBLKs4x8XaaLkwm28KWu9S2vKNqXkXt2AH2Qf0sdPZHjFxcWg/YL53zcqAz+3g4/7PA=="
     },
     "d3-shape": {
       "version": "1.3.7",
@@ -634,9 +692,9 @@
       "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
     },
     "d3-time-format": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
-      "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz",
+      "integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==",
       "requires": {
         "d3-time": "1"
       }
@@ -705,12 +763,18 @@
         "assert-plus": "^1.0.0"
       }
     },
+    "date-fns": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+      "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+      "dev": true
+    },
     "debug": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
-      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "requires": {
-        "ms": "2.1.2"
+        "ms": "^2.1.1"
       }
     },
     "decamelize": {
@@ -742,32 +806,15 @@
       }
     },
     "ejs": {
-      "version": "3.1.6",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
-      "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
-      "dev": true,
-      "requires": {
-        "jake": "^10.6.1"
-      }
-    },
-    "emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz",
+      "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==",
       "dev": true
     },
-    "entity-decode": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/entity-decode/-/entity-decode-2.0.2.tgz",
-      "integrity": "sha512-5CCY/3ci4MC1m2jlumNjWd7VBFt4VfFnmSqSNmVcXq4gxM3Vmarxtt+SvmBnzwLS669MWdVuXboNVj1qN2esVg==",
-      "requires": {
-        "he": "^1.1.1"
-      }
-    },
-    "env-paths": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
-      "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
       "dev": true
     },
     "error-ex": {
@@ -785,6 +832,11 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "escaper": {
+      "version": "2.5.3",
+      "resolved": "https://registry.npmjs.org/escaper/-/escaper-2.5.3.tgz",
+      "integrity": "sha512-QGb9sFxBVpbzMggrKTX0ry1oiI4CSDAl9vIL702hzl1jGW8VZs7qfqTRX7WDOjoNDoEVGcEtu1ZOQgReSfT2kQ=="
+    },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -798,9 +850,9 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+      "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
       "dev": true
     },
     "fast-json-stable-stringify": {
@@ -809,13 +861,13 @@
       "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
       "dev": true
     },
-    "filelist": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
-      "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
       "dev": true,
       "requires": {
-        "minimatch": "^3.0.4"
+        "to-regex-range": "^5.0.1"
       }
     },
     "find-up": {
@@ -846,24 +898,15 @@
       }
     },
     "fs-extra": {
-      "version": "9.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
-      "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
+      "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
       "dev": true,
       "requires": {
         "at-least-node": "^1.0.0",
         "graceful-fs": "^4.2.0",
         "jsonfile": "^6.0.1",
-        "universalify": "^2.0.0"
-      }
-    },
-    "fs-minipass": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-      "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
-      "dev": true,
-      "requires": {
-        "minipass": "^3.0.0"
+        "universalify": "^1.0.0"
       }
     },
     "fs.realpath": {
@@ -872,11 +915,24 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
-    "function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "dev": true
+    "fsevents": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+      "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+      "dev": true,
+      "optional": true
+    },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      }
     },
     "gauge": {
       "version": "2.7.4",
@@ -904,9 +960,9 @@
       }
     },
     "get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+      "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
       "dev": true
     },
     "get-stdin": {
@@ -938,10 +994,19 @@
         "path-is-absolute": "^1.0.0"
       }
     },
+    "glob-parent": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+      "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
     "globule": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
-      "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.0.tgz",
+      "integrity": "sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg==",
       "dev": true,
       "requires": {
         "glob": "~7.1.1",
@@ -950,9 +1015,9 @@
       }
     },
     "graceful-fs": {
-      "version": "4.2.6",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
-      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
       "dev": true
     },
     "graphlib": {
@@ -970,24 +1035,15 @@
       "dev": true
     },
     "har-validator": {
-      "version": "5.1.5",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
-      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
       "dev": true,
       "requires": {
-        "ajv": "^6.12.3",
+        "ajv": "^6.5.5",
         "har-schema": "^2.0.0"
       }
     },
-    "has": {
-      "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"
-      }
-    },
     "has-ansi": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@@ -1015,15 +1071,15 @@
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
     },
     "highlight.js": {
-      "version": "10.6.0",
-      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.6.0.tgz",
-      "integrity": "sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ==",
+      "version": "9.18.1",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
+      "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==",
       "dev": true
     },
     "hosted-git-info": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-      "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
+      "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
       "dev": true
     },
     "html-minifier": {
@@ -1038,6 +1094,13 @@
         "param-case": "^2.1.1",
         "relateurl": "^0.2.7",
         "uglify-js": "^3.5.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        }
       }
     },
     "http-signature": {
@@ -1059,6 +1122,18 @@
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
+    "ignore": {
+      "version": "5.1.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
+      "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
+      "dev": true
+    },
+    "in-publish": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
+      "dev": true
+    },
     "indent-string": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
@@ -1084,21 +1159,33 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
+    "invert-kv": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+      "dev": true
+    },
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "dev": true
     },
-    "is-core-module": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
-      "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
       "dev": true,
       "requires": {
-        "has": "^1.0.3"
+        "binary-extensions": "^2.0.0"
       }
     },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
     "is-finite": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
@@ -1114,6 +1201,26 @@
         "number-is-nan": "^1.0.0"
       }
     },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true
+    },
+    "is-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+      "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk="
+    },
     "is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -1144,22 +1251,10 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
       "dev": true
     },
-    "jake": {
-      "version": "10.8.2",
-      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
-      "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
-      "dev": true,
-      "requires": {
-        "async": "0.9.x",
-        "chalk": "^2.4.2",
-        "filelist": "^1.0.1",
-        "minimatch": "^3.0.4"
-      }
-    },
     "js-base64": {
-      "version": "2.6.4",
-      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
-      "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==",
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
+      "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
       "dev": true
     },
     "jsbn": {
@@ -1168,6 +1263,12 @@
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
       "dev": true
     },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
     "json-schema": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@@ -1187,13 +1288,13 @@
       "dev": true
     },
     "jsonfile": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
-      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+      "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.6",
-        "universalify": "^2.0.0"
+        "universalify": "^1.0.0"
       }
     },
     "jsprim": {
@@ -1208,46 +1309,40 @@
         "verror": "1.10.0"
       }
     },
-    "khroma": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.2.0.tgz",
-      "integrity": "sha512-DlKk5y243dujy8fOH02aRnnewLfiHJV0s8aXaVrCohgBf3s7fEAn6gc6LLQ21agODlFZS8ufrn+juu70uCA9Tw=="
+    "lcid": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+      "dev": true,
+      "requires": {
+        "invert-kv": "^1.0.0"
+      }
     },
     "load-json-file": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
-        "parse-json": "^2.2.0",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0",
-        "strip-bom": "^2.0.0"
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
       }
     },
     "locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
       "dev": true,
       "requires": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
-      },
-      "dependencies": {
-        "path-exists": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
-          "dev": true
-        }
+        "p-locate": "^4.1.0"
       }
     },
     "lodash": {
-      "version": "4.17.20",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
     },
     "long": {
       "version": "4.0.0",
@@ -1271,12 +1366,13 @@
       "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
     },
     "lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
       "dev": true,
       "requires": {
-        "yallist": "^4.0.0"
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
       }
     },
     "map-obj": {
@@ -1286,9 +1382,9 @@
       "dev": true
     },
     "marked": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
-      "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.0.tgz",
+      "integrity": "sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ==",
       "dev": true
     },
     "meow": {
@@ -1310,36 +1406,36 @@
       }
     },
     "mermaid": {
-      "version": "8.9.0",
-      "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.9.0.tgz",
-      "integrity": "sha512-J582tyE1vkdNu4BGgfwXnFo4Mu6jpuc4uK96mIenavaak9kr4T5gaMmYCo/7edwq/vTBkx/soZ5LcJo5WXZ1BQ==",
+      "version": "8.5.0",
+      "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.5.0.tgz",
+      "integrity": "sha512-fZf4GAzkqWuSwo5L+BmzaBwWPudHkxL3M/t1RmS9Dvc2mcnv6hdhMaeC7poARpHaSGwkpb74LL81qXj+vAsVBg==",
       "requires": {
         "@braintree/sanitize-url": "^3.1.0",
+        "crypto-random-string": "^3.0.1",
         "d3": "^5.7.0",
         "dagre": "^0.8.4",
         "dagre-d3": "^0.6.4",
-        "entity-decode": "^2.0.2",
         "graphlib": "^2.1.7",
         "he": "^1.2.0",
-        "khroma": "^1.1.0",
+        "lodash": "^4.17.11",
         "minify": "^4.1.1",
         "moment-mini": "^2.22.1",
-        "stylis": "^3.5.2"
+        "scope-css": "^1.2.1"
       }
     },
     "mime-db": {
-      "version": "1.45.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
-      "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
+      "version": "1.43.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+      "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.28",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
-      "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
+      "version": "2.1.26",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+      "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
       "dev": true,
       "requires": {
-        "mime-db": "1.45.0"
+        "mime-db": "1.43.0"
       }
     },
     "minify": {
@@ -1366,37 +1462,26 @@
       }
     },
     "minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+      "version": "1.2.0",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
       "dev": true
     },
-    "minipass": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
-      "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
-      "dev": true,
-      "requires": {
-        "yallist": "^4.0.0"
-      }
-    },
-    "minizlib": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
-      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
-      "dev": true,
-      "requires": {
-        "minipass": "^3.0.0",
-        "yallist": "^4.0.0"
-      }
-    },
     "mkdirp": {
-      "version": "0.5.5",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "dev": true,
       "requires": {
-        "minimist": "^1.2.5"
+        "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+          "dev": true
+        }
       }
     },
     "moment-mini": {
@@ -1410,9 +1495,15 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
     "nan": {
-      "version": "2.14.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
-      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
       "dev": true
     },
     "no-case": {
@@ -1424,54 +1515,54 @@
       }
     },
     "node-gyp": {
-      "version": "7.1.2",
-      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz",
-      "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==",
+      "version": "3.8.0",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+      "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
       "dev": true,
       "requires": {
-        "env-paths": "^2.2.0",
-        "glob": "^7.1.4",
-        "graceful-fs": "^4.2.3",
-        "nopt": "^5.0.0",
-        "npmlog": "^4.1.2",
-        "request": "^2.88.2",
-        "rimraf": "^3.0.2",
-        "semver": "^7.3.2",
-        "tar": "^6.0.2",
-        "which": "^2.0.2"
+        "fstream": "^1.0.0",
+        "glob": "^7.0.3",
+        "graceful-fs": "^4.1.2",
+        "mkdirp": "^0.5.0",
+        "nopt": "2 || 3",
+        "npmlog": "0 || 1 || 2 || 3 || 4",
+        "osenv": "0",
+        "request": "^2.87.0",
+        "rimraf": "2",
+        "semver": "~5.3.0",
+        "tar": "^2.0.0",
+        "which": "1"
       },
       "dependencies": {
         "semver": {
-          "version": "7.3.4",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
-          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
-          "dev": true,
-          "requires": {
-            "lru-cache": "^6.0.0"
-          }
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+          "dev": true
         }
       }
     },
     "node-sass": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-5.0.0.tgz",
-      "integrity": "sha512-opNgmlu83ZCF792U281Ry7tak9IbVC+AKnXGovcQ8LG8wFaJv6cLnRlc6DIHlmNxWEexB5bZxi9SZ9JyUuOYjw==",
+      "version": "4.13.1",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz",
+      "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==",
       "dev": true,
       "requires": {
         "async-foreach": "^0.1.3",
         "chalk": "^1.1.1",
-        "cross-spawn": "^7.0.3",
+        "cross-spawn": "^3.0.0",
         "gaze": "^1.0.0",
         "get-stdin": "^4.0.1",
         "glob": "^7.0.3",
+        "in-publish": "^2.0.0",
         "lodash": "^4.17.15",
         "meow": "^3.7.0",
         "mkdirp": "^0.5.1",
         "nan": "^2.13.2",
-        "node-gyp": "^7.1.0",
+        "node-gyp": "^3.8.0",
         "npmlog": "^4.0.0",
         "request": "^2.88.0",
-        "sass-graph": "2.2.5",
+        "sass-graph": "^2.2.4",
         "stdout-stream": "^1.4.0",
         "true-case-path": "^1.0.2"
       },
@@ -1503,16 +1594,10 @@
         }
       }
     },
-    "node-watch": {
-      "version": "0.7.1",
-      "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz",
-      "integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==",
-      "dev": true
-    },
     "nopt": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
-      "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
       "dev": true,
       "requires": {
         "abbrev": "1"
@@ -1530,6 +1615,12 @@
         "validate-npm-package-license": "^3.0.1"
       }
     },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true
+    },
     "npmlog": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
@@ -1569,22 +1660,99 @@
         "wrappy": "1"
       }
     },
+    "onchange": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/onchange/-/onchange-6.1.0.tgz",
+      "integrity": "sha512-T0wvi3yzNd+Lut2ymJp2e6fTiob0TLrXnjqGaiK9MAFB8MYo/k/ZClx6ps7YhTtQ88dDm+hDHmtJXP1nJT5WNA==",
+      "dev": true,
+      "requires": {
+        "@blakeembrey/deque": "^1.0.3",
+        "arrify": "^2.0.0",
+        "chokidar": "^3.0.0",
+        "cross-spawn": "^6.0.0",
+        "ignore": "^5.1.4",
+        "minimist": "^1.2.0",
+        "supports-color": "^7.0.0",
+        "tree-kill": "^1.2.0"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
+          "requires": {
+            "nice-try": "^1.0.4",
+            "path-key": "^2.0.1",
+            "semver": "^5.5.0",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-locale": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+      "dev": true,
+      "requires": {
+        "lcid": "^1.0.0"
+      }
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
     "p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+      "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
       "dev": true,
       "requires": {
         "p-try": "^2.0.0"
       }
     },
     "p-locate": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
       "dev": true,
       "requires": {
-        "p-limit": "^2.0.0"
+        "p-limit": "^2.2.0"
       }
     },
     "p-try": {
@@ -1602,12 +1770,13 @@
       }
     },
     "parse-json": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
       "dev": true,
       "requires": {
-        "error-ex": "^1.2.0"
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
       }
     },
     "path-exists": {
@@ -1626,9 +1795,9 @@
       "dev": true
     },
     "path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
       "dev": true
     },
     "path-parse": {
@@ -1638,14 +1807,12 @@
       "dev": true
     },
     "path-type": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^4.1.2",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0"
+        "pify": "^3.0.0"
       }
     },
     "performance-now": {
@@ -1654,10 +1821,16 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
       "dev": true
     },
+    "picomatch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz",
+      "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==",
+      "dev": true
+    },
     "pify": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
       "dev": true
     },
     "pinkie": {
@@ -1682,9 +1855,9 @@
       "dev": true
     },
     "protobufjs": {
-      "version": "6.10.2",
-      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.2.tgz",
-      "integrity": "sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==",
+      "version": "6.9.0",
+      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz",
+      "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==",
       "dev": true,
       "requires": {
         "@protobufjs/aspromise": "^1.1.2",
@@ -1702,10 +1875,16 @@
         "long": "^4.0.0"
       }
     },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
     "psl": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
-      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
+      "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==",
       "dev": true
     },
     "punycode": {
@@ -1714,21 +1893,15 @@
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
       "dev": true
     },
-    "qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
-      "dev": true
-    },
     "read-pkg": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+      "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
       "dev": true,
       "requires": {
-        "load-json-file": "^1.0.0",
+        "load-json-file": "^4.0.0",
         "normalize-package-data": "^2.3.2",
-        "path-type": "^1.0.0"
+        "path-type": "^3.0.0"
       }
     },
     "read-pkg-up": {
@@ -1739,6 +1912,67 @@
       "requires": {
         "find-up": "^1.0.0",
         "read-pkg": "^1.0.0"
+      },
+      "dependencies": {
+        "load-json-file": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+          "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "parse-json": "^2.2.0",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0",
+            "strip-bom": "^2.0.0"
+          }
+        },
+        "parse-json": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+          "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.2.0"
+          }
+        },
+        "path-type": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+          "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "read-pkg": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+          "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+          "dev": true,
+          "requires": {
+            "load-json-file": "^1.0.0",
+            "normalize-package-data": "^2.3.2",
+            "path-type": "^1.0.0"
+          }
+        },
+        "strip-bom": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+          "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+          "dev": true,
+          "requires": {
+            "is-utf8": "^0.2.0"
+          }
+        }
       }
     },
     "readable-stream": {
@@ -1756,6 +1990,15 @@
         "util-deprecate": "~1.0.1"
       }
     },
+    "readdirp": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
+      "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==",
+      "dev": true,
+      "requires": {
+        "picomatch": "^2.0.7"
+      }
+    },
     "redent": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -1781,9 +2024,9 @@
       }
     },
     "request": {
-      "version": "2.88.2",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
-      "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
       "dev": true,
       "requires": {
         "aws-sign2": "~0.7.0",
@@ -1793,7 +2036,7 @@
         "extend": "~3.0.2",
         "forever-agent": "~0.6.1",
         "form-data": "~2.3.2",
-        "har-validator": "~5.1.3",
+        "har-validator": "~5.1.0",
         "http-signature": "~1.2.0",
         "is-typedarray": "~1.0.0",
         "isstream": "~0.1.2",
@@ -1803,9 +2046,17 @@
         "performance-now": "^2.1.0",
         "qs": "~6.5.2",
         "safe-buffer": "^5.1.2",
-        "tough-cookie": "~2.5.0",
+        "tough-cookie": "~2.4.3",
         "tunnel-agent": "^0.6.0",
         "uuid": "^3.3.2"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+          "dev": true
+        }
       }
     },
     "require-directory": {
@@ -1815,25 +2066,24 @@
       "dev": true
     },
     "require-main-filename": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
       "dev": true
     },
     "resolve": {
-      "version": "1.20.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz",
+      "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==",
       "dev": true,
       "requires": {
-        "is-core-module": "^2.2.0",
         "path-parse": "^1.0.6"
       }
     },
     "rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
       "dev": true,
       "requires": {
         "glob": "^7.1.3"
@@ -1844,6 +2094,12 @@
       "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
       "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
     },
+    "rx": {
+      "version": "2.3.24",
+      "resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz",
+      "integrity": "sha1-FPlQpCF9fjXapxu8vljv9o6ksrc=",
+      "dev": true
+    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -1856,15 +2112,63 @@
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "sass-graph": {
-      "version": "2.2.5",
-      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz",
-      "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==",
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+      "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
       "dev": true,
       "requires": {
         "glob": "^7.0.0",
         "lodash": "^4.0.0",
         "scss-tokenizer": "^0.2.3",
-        "yargs": "^13.3.2"
+        "yargs": "^7.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+          "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^3.0.0",
+            "cliui": "^3.2.0",
+            "decamelize": "^1.1.1",
+            "get-caller-file": "^1.0.1",
+            "os-locale": "^1.4.0",
+            "read-pkg-up": "^1.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^1.0.1",
+            "set-blocking": "^2.0.0",
+            "string-width": "^1.0.2",
+            "which-module": "^1.0.0",
+            "y18n": "^3.2.1",
+            "yargs-parser": "^5.0.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+          "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^3.0.0"
+          }
+        }
+      }
+    },
+    "scope-css": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/scope-css/-/scope-css-1.2.1.tgz",
+      "integrity": "sha512-UjLRmyEYaDNiOS673xlVkZFlVCtckJR/dKgr434VMm7Lb+AOOqXKdAcY7PpGlJYErjXXJzKN7HWo4uRPiZZG0Q==",
+      "requires": {
+        "escaper": "^2.5.3",
+        "slugify": "^1.3.1",
+        "strip-css-comments": "^3.0.0"
       }
     },
     "scss-tokenizer": {
@@ -1875,17 +2179,6 @@
       "requires": {
         "js-base64": "^2.1.8",
         "source-map": "^0.4.2"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
-          "dev": true,
-          "requires": {
-            "amdefine": ">=0.0.4"
-          }
-        }
       }
     },
     "semver": {
@@ -1901,30 +2194,39 @@
       "dev": true
     },
     "shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
       "dev": true,
       "requires": {
-        "shebang-regex": "^3.0.0"
+        "shebang-regex": "^1.0.0"
       }
     },
     "shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
       "dev": true
     },
     "signal-exit": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
-      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
       "dev": true
     },
+    "slugify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.0.tgz",
+      "integrity": "sha512-FtLNsMGBSRB/0JOE2A0fxlqjI6fJsgHGS13iTuVT28kViI4JjUiNqp/vyis0ZXYcMnpR3fzGNkv+6vRlI2GwdQ=="
+    },
     "source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+      "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+      "dev": true,
+      "requires": {
+        "amdefine": ">=0.0.4"
+      }
     },
     "source-map-support": {
       "version": "0.5.19",
@@ -1933,12 +2235,25 @@
       "requires": {
         "buffer-from": "^1.0.0",
         "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+        }
       }
     },
+    "spawn-command": {
+      "version": "0.0.2-1",
+      "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
+      "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=",
+      "dev": true
+    },
     "spdx-correct": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
-      "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
       "dev": true,
       "requires": {
         "spdx-expression-parse": "^3.0.0",
@@ -1946,15 +2261,15 @@
       }
     },
     "spdx-exceptions": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
       "dev": true
     },
     "spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
       "dev": true,
       "requires": {
         "spdx-exceptions": "^2.1.0",
@@ -1962,9 +2277,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
-      "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
       "dev": true
     },
     "sshpk": {
@@ -2015,7 +2330,7 @@
     },
     "strip-ansi": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
       "dev": true,
       "requires": {
@@ -2023,12 +2338,17 @@
       }
     },
     "strip-bom": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
-      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
-      "dev": true,
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-css-comments": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-css-comments/-/strip-css-comments-3.0.0.tgz",
+      "integrity": "sha1-elYl7/iisibPiUehElTaluE9rok=",
       "requires": {
-        "is-utf8": "^0.2.0"
+        "is-regexp": "^1.0.0"
       }
     },
     "strip-indent": {
@@ -2040,62 +2360,89 @@
         "get-stdin": "^4.0.1"
       }
     },
-    "stylis": {
-      "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
-      "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
-    },
     "supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+      "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
       "dev": true,
       "requires": {
-        "has-flag": "^3.0.0"
-      }
-    },
-    "tar": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-      "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
-      "dev": true,
-      "requires": {
-        "chownr": "^2.0.0",
-        "fs-minipass": "^2.0.0",
-        "minipass": "^3.0.0",
-        "minizlib": "^2.1.1",
-        "mkdirp": "^1.0.3",
-        "yallist": "^4.0.0"
+        "has-flag": "^1.0.0"
       },
       "dependencies": {
-        "mkdirp": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+        "has-flag": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
           "dev": true
         }
       }
     },
+    "tar": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+      "dev": true,
+      "requires": {
+        "block-stream": "*",
+        "fstream": "^1.0.12",
+        "inherits": "2"
+      }
+    },
     "terser": {
-      "version": "4.8.0",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
-      "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
+      "version": "4.6.13",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz",
+      "integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==",
       "requires": {
         "commander": "^2.20.0",
         "source-map": "~0.6.1",
         "source-map-support": "~0.5.12"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+        }
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "requires": {
+        "is-number": "^7.0.0"
       }
     },
     "tough-cookie": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
-      "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
       "dev": true,
       "requires": {
-        "psl": "^1.1.28",
-        "punycode": "^2.1.1"
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
       }
     },
+    "tree-kill": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+      "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+      "dev": true
+    },
     "trim-newlines": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
@@ -2136,15 +2483,30 @@
       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
       "dev": true
     },
+    "type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
+    },
     "uglify-js": {
-      "version": "3.12.7",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz",
-      "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q=="
+      "version": "3.9.2",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.2.tgz",
+      "integrity": "sha512-zGVwKslUAD/EeqOrD1nQaBmXIHl1Vw371we8cvS8I6mYK9rmgX5tv8AAeJdfsQ3Kk5mGax2SVV/AizxdNGhl7Q==",
+      "requires": {
+        "commander": "~2.20.3"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        }
+      }
     },
     "universalify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
-      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+      "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
       "dev": true
     },
     "upper-case": {
@@ -2153,9 +2515,9 @@
       "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
     },
     "uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
       "dev": true,
       "requires": {
         "punycode": "^2.1.0"
@@ -2195,18 +2557,18 @@
       }
     },
     "which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
       "dev": true,
       "requires": {
         "isexe": "^2.0.0"
       }
     },
     "which-module": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+      "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
       "dev": true
     },
     "wide-align": {
@@ -2219,48 +2581,13 @@
       }
     },
     "wrap-ansi": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {
-        "ansi-styles": "^3.2.0",
-        "string-width": "^3.0.0",
-        "strip-ansi": "^5.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-          "dev": true
-        },
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-          "dev": true,
-          "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1"
       }
     },
     "wrappy": {
@@ -2270,82 +2597,161 @@
       "dev": true
     },
     "y18n": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
-      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+      "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
       "dev": true
     },
     "yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
       "dev": true
     },
     "yargs": {
-      "version": "13.3.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz",
+      "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==",
       "dev": true,
       "requires": {
-        "cliui": "^5.0.0",
-        "find-up": "^3.0.0",
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
         "get-caller-file": "^2.0.1",
         "require-directory": "^2.1.1",
         "require-main-filename": "^2.0.0",
         "set-blocking": "^2.0.0",
-        "string-width": "^3.0.0",
+        "string-width": "^4.2.0",
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
-        "yargs-parser": "^13.1.2"
+        "yargs-parser": "^16.1.0"
       },
       "dependencies": {
         "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "cliui": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+          "dev": true,
+          "requires": {
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.0",
+            "wrap-ansi": "^6.2.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
         "find-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
           "dev": true,
           "requires": {
-            "locate-path": "^3.0.0"
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
           }
         },
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+          "dev": true
+        },
         "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
+        "require-main-filename": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
           "dev": true
         },
         "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
           }
         },
         "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
           "dev": true,
           "requires": {
-            "ansi-regex": "^4.1.0"
+            "ansi-regex": "^5.0.0"
           }
+        },
+        "which-module": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+          "dev": true
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+          "dev": true
         }
       }
     },
     "yargs-parser": {
-      "version": "13.1.2",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+      "version": "16.1.0",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz",
+      "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==",
       "dev": true,
       "requires": {
         "camelcase": "^5.0.0",
diff --git a/infra/perfetto.dev/package.json b/infra/perfetto.dev/package.json
index dbf62d1..791be22 100644
--- a/infra/perfetto.dev/package.json
+++ b/infra/perfetto.dev/package.json
@@ -10,13 +10,22 @@
     "mermaid": "^8.5.0"
   },
   "devDependencies": {
-    "argparse": "^2.0.1",
+    "concurrently": "^3.5.0",
     "ejs": "^3.0.1",
     "fs-extra": "^9.0.0",
-    "highlight.js": "^10.1.2",
+    "highlight.js": "^9.18.1",
     "marked": "^0.8.0",
-    "node-sass": "^5.0.0",
-    "node-watch": "^0.7.1",
-    "protobufjs": "^6.9.0"
+    "node-sass": "^4.13.1",
+    "onchange": "^6.1.0",
+    "protobufjs": "^6.9.0",
+    "yargs": "^15.1.0"
+  },
+  "scripts": {
+    "clean": "../../tools/gn clean ../../out/perfetto.dev",
+    "setup": "ln -fns ../../out/perfetto.dev/site dist",
+    "serve": "npm run setup; dev_appserver.py .",
+    "build": "npm run setup; ../../tools/gn gen --args='' ../../out/perfetto.dev; ../../tools/ninja -C ../../out/perfetto.dev infra/perfetto.dev:node_modules; ../../tools/ninja -C ../../out/perfetto.dev site",
+    "watch": "onchange -v '../../docs/**' '**' '../../src/trace_processor/tables/**' '../../src/trace_processor/storage/stats.h' '../../protos/**' -e 'dist' -e 'dist/**' -- npm run build",
+    "start": "npm run build; concurrently \"npm run serve\" \"npm run watch\""
   }
 }
diff --git a/infra/perfetto.dev/redirect/.gcloudignore b/infra/perfetto.dev/redirect/.gcloudignore
new file mode 100644
index 0000000..dba30e9
--- /dev/null
+++ b/infra/perfetto.dev/redirect/.gcloudignore
@@ -0,0 +1,13 @@
+__pycache__/
+.firebase/
+.firebaserc
+.gcloudignore
+.git
+.gitignore
+BUILD.gn
+deploy
+firebase-debug.log
+node_modules/
+package-lock.json
+package.json
+run-dev-server
diff --git a/infra/perfetto.dev/redirect/app.yaml b/infra/perfetto.dev/redirect/app.yaml
new file mode 100644
index 0000000..ecd8a58
--- /dev/null
+++ b/infra/perfetto.dev/redirect/app.yaml
@@ -0,0 +1,20 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+runtime: python37
+service: redirect
+handlers:
+- url: /.*
+  script: auto
+
diff --git a/infra/perfetto.dev/redirect/main.py b/infra/perfetto.dev/redirect/main.py
new file mode 100644
index 0000000..2b72cd3
--- /dev/null
+++ b/infra/perfetto.dev/redirect/main.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from flask import Flask, redirect
+
+app = Flask(__name__)
+
+
+@app.route('/', defaults={'path': ''})
+@app.route('/<path:path>')
+def main(path):
+  return redirect('https://perfetto.dev/' + path)
+
+
+if __name__ == '__main__':
+  app.run(host='127.0.0.1', port=8080, debug=True)
diff --git a/infra/perfetto.dev/redirect/requirements.txt b/infra/perfetto.dev/redirect/requirements.txt
new file mode 100644
index 0000000..46a48dd
--- /dev/null
+++ b/infra/perfetto.dev/redirect/requirements.txt
@@ -0,0 +1 @@
+Flask==1.1.2
diff --git a/infra/perfetto.dev/run-dev-server b/infra/perfetto.dev/run-dev-server
index 6a213ad..0915cc4 100755
--- a/infra/perfetto.dev/run-dev-server
+++ b/infra/perfetto.dev/run-dev-server
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
+# Copyright (C) 2020 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,6 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -eu
-CUR_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$CUR_DIR/build --serve --watch
+set -e
+
+readonly CUR_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
+readonly ROOT_DIR=$(dirname $(dirname "$CUR_DIR"))
+readonly NODE_DIR="$ROOT_DIR/buildtools/nodejs/bin"
+readonly WRAPPER="$ROOT_DIR/gn/standalone/build_tool_wrapper.py"
+
+cd "$CUR_DIR"
+exec python "$WRAPPER" --path $NODE_DIR npm run start
diff --git a/infra/perfetto.dev/src/assets/style.scss b/infra/perfetto.dev/src/assets/style.scss
index 0d0bbbe..e141890 100644
--- a/infra/perfetto.dev/src/assets/style.scss
+++ b/infra/perfetto.dev/src/assets/style.scss
@@ -683,9 +683,6 @@
             tr {
                 height: 20px;
             }
-            tr:target {
-                background-color: #ecba2a;
-            }
             thead {
                 text-align: left;
                 background-color: #e8eaed;
diff --git a/infra/perfetto.dev/src/gen_proto_reference.js b/infra/perfetto.dev/src/gen_proto_reference.js
index c3d0481..044929e 100644
--- a/infra/perfetto.dev/src/gen_proto_reference.js
+++ b/infra/perfetto.dev/src/gen_proto_reference.js
@@ -26,30 +26,13 @@
 
 const visited = {};
 
-// This function is used to escape:
-// - The message-level comment, which becomes a full paragraph.
-// - The per-field comments, rendered as as table.
-function escapeCommentCommon(comment) {
-  comment = comment || '';
 
-  // Remove Next id: NN lines.
-  comment = comment.replace(/(\n)?^\s*next.*\bid:.*$/img, '');
-
-  // Hide our little dirty secrets.
-  comment = comment.replace(/(\n)?^\s*TODO\(\w+\):.*$/img, '');
-
-  // Turn |variable| references into `variable`.
-  comment = comment.replace(/[|](\w+?)[|]/g, '`$1`');
-  return comment;
-}
-
-// This is used to escape only the per-field comments.
 // Removes \n due to 80col wrapping and preserves only end-of-sentence line
 // breaks.
 function singleLineComment(comment) {
-  comment = escapeCommentCommon(comment);
+  comment = comment || '';
   comment = comment.trim();
-  comment = comment.replace(/([.:?!])\n/g, '$1<br>');
+  comment = comment.replace(/\.\n/g, '<br>');
   comment = comment.replace(/\n/g, ' ');
   return comment;
 }
@@ -79,8 +62,7 @@
   md += '\n';
   const fileName = path.basename(pType.filename);
   const relPath = path.relative(PROJECT_ROOT, pType.filename);
-
-  md += escapeCommentCommon(pType.comment);
+  md += `${(pType.comment || '').replace(/(\n)?^\s*next.*\bid:.*$/img, '')}`;
   md += `\n\nDefined in [${fileName}](/${relPath})\n\n`;
 
   const subTypes = [];
diff --git a/infra/perfetto.dev/src/gen_sql_tables_reference.js b/infra/perfetto.dev/src/gen_sql_tables_reference.js
index f92acfc..b1ced89 100644
--- a/infra/perfetto.dev/src/gen_sql_tables_reference.js
+++ b/infra/perfetto.dev/src/gen_sql_tables_reference.js
@@ -17,6 +17,7 @@
 'use strict';
 
 const fs = require('fs');
+const path = require('path');
 const argv = require('yargs').argv
 
 // Removes \n due to 80col wrapping and preserves only end-of-sentence line
diff --git a/infra/perfetto.dev/src/gen_stats_reference.js b/infra/perfetto.dev/src/gen_stats_reference.js
index def5a01..0f7228e 100644
--- a/infra/perfetto.dev/src/gen_stats_reference.js
+++ b/infra/perfetto.dev/src/gen_stats_reference.js
@@ -17,6 +17,7 @@
 'use strict';
 
 const fs = require('fs');
+const path = require('path');
 const argv = require('yargs').argv
 
 // Removes \n due to 80col wrapping and preserves only end-of-sentence line
@@ -65,14 +66,13 @@
 
 function tableToMarkdown(table) {
   let md = `# Trace Processor Stats\n\n`;
-  md += `<table><thead><tr><td>Name</td><td>Cardinality</td><td>Type</td>
-  <td>Scope</td><td>Description</td></tr></thead>\n`;
+  md += 'Name | Cardinality | Type | Scope | Description |\n';
+  md += '---- | ----------- | ---- | ----- | ----------- |\n';
   for (const col of table) {
-    md += `<tr id="${col.name}"><td>${col.name}</td>
-    <td>${col.cardinality}</td><td>${col.type}</td><td>${col.scope}</td>
-    <td>${singleLineComment(col.comment)} </td></tr>\n`
+    md += `${col.name} | ${col.cardinality} | ${col.type} | ${col.scope} | ${
+        singleLineComment(col.comment)} |\n`
   }
-  md += '</table>\n\n';
+  md += '\n\n';
   return md;
 }
 
diff --git a/infra/perfetto.dev/src/markdown_render.js b/infra/perfetto.dev/src/markdown_render.js
index 8fe5cc9..ebb34d8 100644
--- a/infra/perfetto.dev/src/markdown_render.js
+++ b/infra/perfetto.dev/src/markdown_render.js
@@ -23,6 +23,7 @@
     'https://cs.android.com/android/platform/superproject/+/master:external/perfetto';
 
 const ROOT_DIR = path.dirname(path.dirname(path.dirname(__dirname)));
+const DOCS_DIR = path.join(ROOT_DIR, 'docs');
 
 let outDir = '';
 let curMdFile = '';
@@ -199,7 +200,7 @@
     const templateData = {
       markdown: markdownHtml,
       title: title ? `${title} - Perfetto Tracing Docs` : fallbackTitle,
-      fileName: '/' + path.relative(outDir, outFile),
+      fileName: '/' + outFile.split('/').slice(1).join('/'),
     };
     if (fs.existsSync(navFilePath)) {
       templateData['nav'] = fs.readFileSync(navFilePath, 'utf8');
diff --git a/infra/ui.perfetto.dev/README.md b/infra/ui.perfetto.dev/README.md
deleted file mode 100644
index 6006a7f..0000000
--- a/infra/ui.perfetto.dev/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# ui.perfetto.dev Cloud scripts
-
-See [go/perfetto-ui-autopush](http://go/perfetto-ui-autopush) for docs on how
-this works end-to-end.
-
-## /appengine : GAE <> GCS proxy
-
-The Google AppEngine instance that responds to ui.perfetto.dev.
-It simply passes through the requests to the bucket gs://ui.perfetto.dev .
-This should NOT be re-deployed when uploading a new version of the ui,
-as the actual UI artifacts live in GCS.
-
-We are using AppEngine for historical reasons, at some point this should
-be migrated to a Type 7 Google Cloud Load Balancer, which supports
-direct backing by a GCS bucket. The only blocker for that is figuring out
-a seamless migration strategy for the SSL certificate.
-
-## /builder : Docker container for Google Cloud Build
-
-Contains the Dockerfile to generate the container image which is used by
-Google Cloud Build when auto-triggering new ui builds.
-Cloud Build invokes the equivalent of:
-
-```bash
-docker run gcr.io/perfetto-ui/perfetto-ui-builder \
-    ui/release/builder_entrypoint.sh
-```
-
-NOTE: the `builder_entrypoint.sh` script is not bundled in the docker container
-and is taken from the HEAD if the checked out repo.
-
-To update the container:
-
-```bash
-cd infra/ui.perfetto.dev/builder
-docker build -t gcr.io/perfetto-ui/perfetto-ui-builder .
-docker push gcr.io/perfetto-ui/perfetto-ui-builder .
-```
diff --git a/infra/ui.perfetto.dev/appengine/.gcloudignore b/infra/ui.perfetto.dev/appengine/.gcloudignore
deleted file mode 100644
index cc91f41..0000000
--- a/infra/ui.perfetto.dev/appengine/.gcloudignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.gcloudignore
-.git
-.gitignore
-__pycache__/
-/setup.cfg
-deploy
diff --git a/infra/ui.perfetto.dev/appengine/app.yaml b/infra/ui.perfetto.dev/appengine/app.yaml
deleted file mode 100644
index 1f4e65c..0000000
--- a/infra/ui.perfetto.dev/appengine/app.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-runtime: python38
-instance_class: B1
-basic_scaling:
-  max_instances: 4
-  idle_timeout: 10m
diff --git a/infra/ui.perfetto.dev/appengine/deploy b/infra/ui.perfetto.dev/appengine/deploy
deleted file mode 100755
index 694d329..0000000
--- a/infra/ui.perfetto.dev/appengine/deploy
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 -exu
-
-cd -P ${BASH_SOURCE[0]%/*}
-
-VERSION=staging
-PROMOTE=--no-promote
-while [[ $# -gt 0 ]]; do
-  key="$1"
-  case $key in
-      --prod)
-      VERSION=prod
-      PROMOTE=--promote
-      shift
-      ;;
-      *)
-      echo "Usage: $0 [--prod]"
-      echo "    --prod      Deploy prod version"
-      echo "    -h|--help   Display this message"
-      exit 0
-      shift
-      ;;
-  esac
-done
-
-gcloud app deploy app.yaml --project perfetto-ui \
-    -v $VERSION $PROMOTE --stop-previous-version
diff --git a/infra/ui.perfetto.dev/appengine/index.yaml b/infra/ui.perfetto.dev/appengine/index.yaml
deleted file mode 100644
index 6536212..0000000
--- a/infra/ui.perfetto.dev/appengine/index.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-indexes:
-# AUTOGENERATED
diff --git a/infra/ui.perfetto.dev/appengine/main.py b/infra/ui.perfetto.dev/appengine/main.py
deleted file mode 100644
index 0fac701..0000000
--- a/infra/ui.perfetto.dev/appengine/main.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 flask
-import requests
-
-BUCKET_NAME = 'ui.perfetto.dev'
-
-REQ_HEADERS = [
-    'Accept',
-    'Accept-Encoding',
-    'Cache-Control',
-]
-
-RESP_HEADERS = [
-    'Content-Type',
-    'Content-Encoding',
-    'Content-Length',
-    'Cache-Control',
-    'Date',
-    'Expires',
-]
-
-app = flask.Flask(__name__)
-
-
-# Redirect v1.2.3 to v.1.2.3/
-@app.route('/v<int:x>.<int:y>.<int:z>')
-def version_redirect(x, y, z):
-  return flask.redirect('/v%d.%d.%d/' % (x, y, z), code=302)
-
-
-# Serve the requests from the GCS bucket.
-@app.route('/', methods=['GET'])
-@app.route('/<path:path>', methods=['GET'])
-def main(path=''):
-  path = '/' + path
-  path += 'index.html' if path.endswith('/') else ''
-  req_headers = {}
-  for key in set(flask.request.headers.keys()).intersection(REQ_HEADERS):
-    req_headers[key] = flask.request.headers.get(key)
-  url = 'https://commondatastorage.googleapis.com/' + BUCKET_NAME + path
-  req = requests.get(url, headers=req_headers)
-  if (req.status_code != 200):
-    return flask.abort(req.status_code)
-  resp = flask.Response(req.content)
-  for key in set(req.headers.keys()).intersection(RESP_HEADERS):
-    resp.headers[key] = req.headers.get(key)
-  return resp
-
-
-if __name__ == '__main__':
-  # This is used when running locally only.
-  app.run(host='127.0.0.1', port=10000, debug=True)
diff --git a/infra/ui.perfetto.dev/appengine/requirements.txt b/infra/ui.perfetto.dev/appengine/requirements.txt
deleted file mode 100644
index 1faca3d..0000000
--- a/infra/ui.perfetto.dev/appengine/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Flask==1.1.2
-requests
diff --git a/infra/ui.perfetto.dev/builder/Dockerfile b/infra/ui.perfetto.dev/builder/Dockerfile
deleted file mode 100644
index 07944c1..0000000
--- a/infra/ui.perfetto.dev/builder/Dockerfile
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# The image that builds the Perfetto UI and deploys to GCS.
-# See go/perfetto-ui-autopush for docs on how this works end-to-end.
-
-FROM debian:buster-slim
-
-ENV PATH=/builder/google-cloud-sdk/bin/:$PATH
-RUN set -ex; \
-    export DEBIAN_FRONTEND=noninteractive; \
-    apt-get update; \
-    apt-get -y install python3 python3-distutils python3-pip git curl tar tini \
-            pkg-config zip libc-dev libgcc-8-dev; \
-    update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1; \
-    pip3 install --quiet protobuf crcmod; \
-    mkdir -p /builder && \
-    curl -s -o - https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz | tar -zx -C /builder; \
-    /builder/google-cloud-sdk/install.sh \
-        --usage-reporting=false \
-        --bash-completion=false \
-        --disable-installation-options \
-        --override-components gcloud gsutil; \
-    git config --system credential.helper gcloud.sh; \
-    useradd -d /home/perfetto perfetto; \
-    apt-get -y autoremove; \
-    rm -rf /var/lib/apt/lists/* /usr/share/man/* /usr/share/doc/*;
-
-ENTRYPOINT [ "tini", "-g", "--" ]
diff --git a/infra/ui.perfetto.dev/cloudbuild.yaml b/infra/ui.perfetto.dev/cloudbuild.yaml
deleted file mode 100644
index 6cfca1b..0000000
--- a/infra/ui.perfetto.dev/cloudbuild.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-# See go/perfetto-ui-autopush for docs on how this works end-to-end.
-steps:
-- name: gcr.io/$PROJECT_ID/perfetto-ui-builder
-  args:
-  - 'ui/release/builder_entrypoint.sh'
-# Timeout = 30 min (last measured time in Feb 2021: 12 min)
-timeout: 1800s
-options:
-  machineType: E2_HIGHCPU_32
diff --git a/meson.build b/meson.build
deleted file mode 100644
index 13d603b..0000000
--- a/meson.build
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 meson project only supports the Perfetto SDK
-# available from release branches.
-# https://perfetto.dev/docs/instrumentation/tracing-sdk
-
-project(
-    'perfetto',
-    ['c','cpp'],
-    default_options: ['c_std=c99', 'cpp_std=c++11']
-)
-
-fs = import('fs')
-
-if not fs.is_dir('sdk')
-    error('sdk dir not found, please checkout a release tag, e.g. v14.0')
-endif
-
-dep_threads = dependency('threads')
-
-lib_perfetto = static_library(
-    'perfetto',
-    sources: 'sdk/perfetto.cc',
-    dependencies: dep_threads,
-)
-
-inc_perfetto = include_directories('sdk')
-
-dep_perfetto = declare_dependency(
-    link_with: lib_perfetto,
-    include_directories: inc_perfetto,
-)
diff --git a/perfetto.rc b/perfetto.rc
index e8762fb..a33bd03 100644
--- a/perfetto.rc
+++ b/perfetto.rc
@@ -25,8 +25,8 @@
     class late_start
     disabled
     user nobody
-    # Despite the "log" group below, traced_probes is allowed to read log
-    # only on userdebug/eng via selinux (see traced_probes.te).
+    # Despite the "log" group below, traced_probes is whitelisted for log read
+    # access only on userdebug/eng via selinux (see traced_probes.te).
     group nobody readproc log
     writepid /dev/cpuset/system-background/tasks
     # Clean up procfs configuration even if traced_probes crashes
@@ -50,18 +50,12 @@
 on property:persist.traced.enable=1
     # Trace files need to be:
     # - Written by either uid:shell or uid:statsd.
-    # - Read by shell and incidentd.
+    # - Read by shell and dropbox (dropbox is part of system_server).
+    # When written to dropbox, they are persistet in the perfetto-traces folder
+    # only for the time it takes to make a dropbox call, and unlinked
+    # immediately in any case.
     mkdir /data/misc/perfetto-traces 0773 root shell
 
-    # Traces in this directory are only accessed by dumpstate (read+unlink) and
-    # by the bug reporting UI (ls+getattr).
-    mkdir /data/misc/perfetto-traces/bugreport 0773 root shell
-
-    # This directory allows shell to save configs file in a place where the
-    # perfetto cmdline client can read then. /data/local/tmp/ isn't safe because
-    # too many other domains can write into that. See b/170404111.
-    mkdir /data/misc/perfetto-configs 0775 root shell
-
     start traced
     start traced_probes
 
@@ -72,21 +66,3 @@
 # Reset the Perfetto guard rail state on boot:
 on post-fs-data
     rm /data/misc/perfetto-traces/.guardraildata
-
-#############################################################################
-#  mm_events - Arms a perfetto trace config that is triggered
-#              on memory pressure (kmem_activity trigger)
-#############################################################################
-
-service mm_events /system/bin/mm_events
-    class late_start
-    disabled
-    oneshot
-    user nobody
-    group nobody
-
-on property:persist.mm_events.enabled=true && property:persist.traced.enable=1
-    restart mm_events   # Restart to reset backoff interval
-
-on property:persist.mm_events.enabled=false
-    stop mm_events
diff --git a/protos/perfetto/common/BUILD.gn b/protos/perfetto/common/BUILD.gn
index 1af189d..90dde62 100644
--- a/protos/perfetto/common/BUILD.gn
+++ b/protos/perfetto/common/BUILD.gn
@@ -19,16 +19,13 @@
 # a C++ counterpart in tracing/core (i.e. are used also for the non-IPC cases).
 perfetto_proto_library("@TYPE@") {
   sources = [
-    "android_energy_consumer_descriptor.proto",
     "android_log_constants.proto",
     "builtin_clock.proto",
     "commit_data_request.proto",
     "data_source_descriptor.proto",
     "descriptor.proto",
     "gpu_counter_descriptor.proto",
-    "interceptor_descriptor.proto",
     "observable_events.proto",
-    "perf_events.proto",
     "sys_stats_counters.proto",
     "trace_stats.proto",
     "tracing_service_capabilities.proto",
diff --git a/protos/perfetto/common/android_energy_consumer_descriptor.proto b/protos/perfetto/common/android_energy_consumer_descriptor.proto
deleted file mode 100644
index 3e72cc0..0000000
--- a/protos/perfetto/common/android_energy_consumer_descriptor.proto
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-// Energy consumer based on aidl class:
-// android.hardware.power.stats.EnergyConsumer.
-message AndroidEnergyConsumer {
-  // Unique ID of this energy consumer.  Matches the ID in a
-  // AndroidEnergyEstimationBreakdown.
-  optional int32 energy_consumer_id = 1;
-
-  // For a group of energy consumers of the same logical type, sorting by
-  // ordinal gives their physical order. Ordinals must be consecutive integers
-  // starting from 0.
-  optional int32 ordinal = 2;
-
-  // Type of this energy consumer.
-  optional string type = 3;
-
-  // Unique name of this energy consumer. Vendor/device specific. Opaque to
-  // framework.
-  optional string name = 4;
-}
-
-message AndroidEnergyConsumerDescriptor {
-  repeated AndroidEnergyConsumer energy_consumers = 1;
-}
diff --git a/protos/perfetto/common/android_log_constants.proto b/protos/perfetto/common/android_log_constants.proto
index d041b87..47e42d1 100644
--- a/protos/perfetto/common/android_log_constants.proto
+++ b/protos/perfetto/common/android_log_constants.proto
@@ -20,9 +20,7 @@
 
 // Values from NDK's android/log.h.
 enum AndroidLogId {
-  // MAIN.
-  LID_DEFAULT = 0;
-
+  LID_DEFAULT = 0;  // MAIN.
   LID_RADIO = 1;
   LID_EVENTS = 2;
   LID_SYSTEM = 3;
@@ -34,10 +32,7 @@
 
 enum AndroidLogPriority {
   PRIO_UNSPECIFIED = 0;
-
-  // _DEFAULT, but should never be seen in logs.
-  PRIO_UNUSED = 1;
-
+  PRIO_UNUSED = 1;  // _DEFAULT, but should never be seen in logs.
   PRIO_VERBOSE = 2;
   PRIO_DEBUG = 3;
   PRIO_INFO = 4;
diff --git a/protos/perfetto/common/data_source_descriptor.proto b/protos/perfetto/common/data_source_descriptor.proto
index d35c641..725c2f2 100644
--- a/protos/perfetto/common/data_source_descriptor.proto
+++ b/protos/perfetto/common/data_source_descriptor.proto
@@ -25,8 +25,7 @@
 // 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 {
-  // e.g., "linux.ftrace", "chromium.tracing"
-  optional string name = 1;
+  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
diff --git a/protos/perfetto/common/descriptor.proto b/protos/perfetto/common/descriptor.proto
index 7ee05e3..95f6fc0 100644
--- a/protos/perfetto/common/descriptor.proto
+++ b/protos/perfetto/common/descriptor.proto
@@ -19,6 +19,7 @@
 
 package perfetto.protos;
 
+
 // The protocol compiler can output a FileDescriptorSet containing the .proto
 // files it parses.
 message FileDescriptorSet {
@@ -27,10 +28,8 @@
 
 // Describes a complete .proto file.
 message FileDescriptorProto {
-  // file name, relative to root of source tree
-  optional string name = 1;
-  // e.g. "foo", "foo.bar", etc.
-  optional string package = 2;
+  optional string name = 1;     // file name, relative to root of source tree
+  optional string package = 2;  // e.g. "foo", "foo.bar", etc.
 
   // Names of files imported by this file.
   repeated string dependency = 3;
@@ -71,10 +70,8 @@
   // fields or extension ranges in the same message. Reserved ranges may
   // not overlap.
   message ReservedRange {
-    // Inclusive.
-    optional int32 start = 1;
-    // Exclusive.
-    optional int32 end = 2;
+    optional int32 start = 1;  // Inclusive.
+    optional int32 end = 2;    // Exclusive.
   }
   repeated ReservedRange reserved_range = 9;
   // Reserved field names, which may not be used by fields in the same message.
@@ -105,8 +102,7 @@
     // implementations should still be able to parse the group wire format and
     // treat group fields as unknown fields.
     TYPE_GROUP = 10;
-    // Length-delimited aggregate.
-    TYPE_MESSAGE = 11;
+    TYPE_MESSAGE = 11;  // Length-delimited aggregate.
 
     // New in version 2.
     TYPE_BYTES = 12;
@@ -114,10 +110,8 @@
     TYPE_ENUM = 14;
     TYPE_SFIXED32 = 15;
     TYPE_SFIXED64 = 16;
-    // Uses ZigZag encoding.
-    TYPE_SINT32 = 17;
-    // Uses ZigZag encoding.
-    TYPE_SINT64 = 18;
+    TYPE_SINT32 = 17;  // Uses ZigZag encoding.
+    TYPE_SINT64 = 18;  // Uses ZigZag encoding.
   };
 
   enum Label {
diff --git a/protos/perfetto/common/gpu_counter_descriptor.proto b/protos/perfetto/common/gpu_counter_descriptor.proto
index 9591054..d15b146 100644
--- a/protos/perfetto/common/gpu_counter_descriptor.proto
+++ b/protos/perfetto/common/gpu_counter_descriptor.proto
@@ -30,8 +30,7 @@
     VERTICES = 2;
     FRAGMENTS = 3;
     PRIMITIVES = 4;
-    // Includes counters relating to caching and bandwidth.
-    MEMORY = 5;
+    MEMORY = 5;  // Includes counters relating to caching and bandwidth.
     COMPUTE = 6;
   }
 
@@ -39,8 +38,7 @@
     optional uint32 counter_id = 1;
     optional string name = 2;
     optional string description = 3;
-    // MeasureUnit unit (deprecated)
-    reserved 4;
+    reserved 4;  // MeasureUnit unit (deprecated)
     oneof peak_value {
       int64 int_peak_value = 5;
       double double_peak_value = 6;
diff --git a/protos/perfetto/common/interceptor_descriptor.proto b/protos/perfetto/common/interceptor_descriptor.proto
deleted file mode 100644
index e5f7a00..0000000
--- a/protos/perfetto/common/interceptor_descriptor.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Used to configure the properties of a data source interceptor.
-message InterceptorDescriptor {
-  // e.g., "console", "etw"
-  optional string name = 1;
-}
diff --git a/protos/perfetto/common/perf_events.proto b/protos/perfetto/common/perf_events.proto
deleted file mode 100644
index 77f3a1e..0000000
--- a/protos/perfetto/common/perf_events.proto
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-message PerfEvents {
-  // What event to sample on, and how often. Commented from the perspective of
-  // its use in |PerfEventConfig|.
-  message Timebase {
-    // How often the per-cpu sampling will occur. Not guaranteed to be honored
-    // as the kernel can throttle the sampling rate if it's too high.
-    // If unset, an implementation-defined default is used.
-    oneof interval {
-      // Per-cpu sampling frequency in Hz, as requested from the kernel. Not the
-      // same as 1/period.
-      // Details: the actual sampling will still be based on a period, but the
-      // kernel will dynamically adjust it based on the observed event rate, to
-      // approximate this frequency. Works best with steady-rate events like
-      // timers.
-      uint64 frequency = 2;
-
-      // Per-cpu sampling will occur every |period| counts of |event|.
-      // Prefer |frequency| by default, as it's easier to oversample with a
-      // fixed period.
-      uint64 period = 1;
-    }
-
-    // Counting event to use as a timebase for the sampling.
-    // If unset, implies the CPU timer (SW_CPU_CLOCK) as the event,
-    // which is what you usually want.
-    // See common/perf_events.proto for the definitions.
-    oneof event {
-      Counter counter = 4;
-      Tracepoint tracepoint = 3;
-    }
-  }
-
-  enum Counter {
-    UNKNOWN_COUNTER = 0;
-    // software:
-    SW_CPU_CLOCK = 1;
-    SW_PAGE_FAULTS = 2;
-    // hardware:
-    HW_CPU_CYCLES = 10;
-    HW_INSTRUCTIONS = 11;
-  }
-
-  message Tracepoint {
-    // Group and name for the tracepoint, acceptable forms:
-    // * "sched/sched_switch"
-    // * "sched:sched_switch"
-    optional string name = 1;
-
-    // Optional field-level filter for the tracepoint. Only events matching this
-    // filter will be counted (and therefore contribute to the sampling period).
-    // Example: "prev_pid >= 42 && next_pid == 0".
-    // For full syntax, see kernel documentation on "Event filtering":
-    // https://www.kernel.org/doc/Documentation/trace/events.txt
-    optional string filter = 2;
-  }
-}
diff --git a/protos/perfetto/common/sys_stats_counters.proto b/protos/perfetto/common/sys_stats_counters.proto
index 1605a73..837656b 100644
--- a/protos/perfetto/common/sys_stats_counters.proto
+++ b/protos/perfetto/common/sys_stats_counters.proto
@@ -157,37 +157,4 @@
   VMSTAT_NR_ZSPAGES = 93;
   VMSTAT_NR_ION_HEAP = 94;
   VMSTAT_NR_GPU_HEAP = 95;
-  VMSTAT_ALLOCSTALL_DMA = 96;
-  VMSTAT_ALLOCSTALL_MOVABLE = 97;
-  VMSTAT_ALLOCSTALL_NORMAL = 98;
-  VMSTAT_COMPACT_DAEMON_FREE_SCANNED = 99;
-  VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED = 100;
-  VMSTAT_NR_FASTRPC = 101;
-  VMSTAT_NR_INDIRECTLY_RECLAIMABLE = 102;
-  VMSTAT_NR_ION_HEAP_POOL = 103;
-  VMSTAT_NR_KERNEL_MISC_RECLAIMABLE = 104;
-  VMSTAT_NR_SHADOW_CALL_STACK_BYTES = 105;
-  VMSTAT_NR_SHMEM_HUGEPAGES = 106;
-  VMSTAT_NR_SHMEM_PMDMAPPED = 107;
-  VMSTAT_NR_UNRECLAIMABLE_PAGES = 108;
-  VMSTAT_NR_ZONE_ACTIVE_ANON = 109;
-  VMSTAT_NR_ZONE_ACTIVE_FILE = 110;
-  VMSTAT_NR_ZONE_INACTIVE_ANON = 111;
-  VMSTAT_NR_ZONE_INACTIVE_FILE = 112;
-  VMSTAT_NR_ZONE_UNEVICTABLE = 113;
-  VMSTAT_NR_ZONE_WRITE_PENDING = 114;
-  VMSTAT_OOM_KILL = 115;
-  VMSTAT_PGLAZYFREE = 116;
-  VMSTAT_PGLAZYFREED = 117;
-  VMSTAT_PGREFILL = 118;
-  VMSTAT_PGSCAN_DIRECT = 119;
-  VMSTAT_PGSCAN_KSWAPD = 120;
-  VMSTAT_PGSKIP_DMA = 121;
-  VMSTAT_PGSKIP_MOVABLE = 122;
-  VMSTAT_PGSKIP_NORMAL = 123;
-  VMSTAT_PGSTEAL_DIRECT = 124;
-  VMSTAT_PGSTEAL_KSWAPD = 125;
-  VMSTAT_SWAP_RA = 126;
-  VMSTAT_SWAP_RA_HIT = 127;
-  VMSTAT_WORKINGSET_RESTORE = 128;
 }
\ No newline at end of file
diff --git a/protos/perfetto/common/trace_stats.proto b/protos/perfetto/common/trace_stats.proto
index c6a9fbf..e925ad4 100644
--- a/protos/perfetto/common/trace_stats.proto
+++ b/protos/perfetto/common/trace_stats.proto
@@ -158,13 +158,4 @@
   // Packets that failed validation of the TrustedPacket. If this is > 0, there
   // is a bug in the producer.
   optional uint64 invalid_packets = 10;
-
-  // This is set only when the TraceConfig specifies a TraceFilter.
-  message FilterStats {
-    optional uint64 input_packets = 1;
-    optional uint64 input_bytes = 2;
-    optional uint64 output_bytes = 3;
-    optional uint64 errors = 4;
-  }
-  optional FilterStats filter_stats = 11;
 }
diff --git a/protos/perfetto/common/tracing_service_state.proto b/protos/perfetto/common/tracing_service_state.proto
index 1ef4c56..dd475ab 100644
--- a/protos/perfetto/common/tracing_service_state.proto
+++ b/protos/perfetto/common/tracing_service_state.proto
@@ -26,20 +26,9 @@
 message TracingServiceState {
   // Describes a producer process.
   message Producer {
-    // Unique ID of the producer (monotonic counter).
-    optional int32 id = 1;
-
-    // Typically matches the process name.
-    optional string name = 2;
-
-    // Unix uid of the remote process.
-    optional int32 uid = 3;
-
-    // The version of the client library used by the producer.
-    // This is a human readable string with and its format varies depending on
-    // the build system and the repo (standalone vs AOSP).
-    // This is intended for human debugging only.
-    optional string sdk_version = 4;
+    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
@@ -63,10 +52,4 @@
 
   // Number of tracing sessions in the started state. Always <= num_sessions.
   optional int32 num_sessions_started = 4;
-
-  // The version of traced (the same returned by `traced --version`).
-  // This is a human readable string with and its format varies depending on
-  // the build system and the repo (standalone vs AOSP).
-  // This is intended for human debugging only.
-  optional string tracing_service_version = 5;
 }
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index de9c1f5..8a4a3b8 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -19,13 +19,14 @@
 # data_source_config.proto.
 
 perfetto_proto_library("@TYPE@") {
+  # Chromium shouldn't ignore the "android/" folder.
+  set_sources_assignment_filter([])
   deps = [
     "../common:@TYPE@",
     "android:@TYPE@",
     "ftrace:@TYPE@",
     "gpu:@TYPE@",
     "inode_file:@TYPE@",
-    "interceptors:@TYPE@",
     "power:@TYPE@",
     "process_stats:@TYPE@",
     "profiling:@TYPE@",
@@ -36,8 +37,6 @@
   sources = [
     "chrome/chrome_config.proto",
     "data_source_config.proto",
-    "interceptor_config.proto",
-    "stress_test_config.proto",
     "test_config.proto",
     "trace_config.proto",
   ]
@@ -49,16 +48,3 @@
   proto_generators = [ "lite" ]
   sources = [ "perfetto_config.proto" ]
 }
-
-perfetto_proto_library("descriptor") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "config.descriptor"
-  deps = [ ":source_set" ]
-  sources = [ "trace_config.proto" ]
-}
-
-perfetto_proto_library("perfetto_config_descriptor") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "perfetto_config.descriptor"
-  sources = [ "perfetto_config.proto" ]
-}
diff --git a/protos/perfetto/config/android/android_log_config.proto b/protos/perfetto/config/android/android_log_config.proto
index 57ae316..ff4c400 100644
--- a/protos/perfetto/config/android/android_log_config.proto
+++ b/protos/perfetto/config/android/android_log_config.proto
@@ -22,8 +22,7 @@
 message AndroidLogConfig {
   repeated AndroidLogId log_ids = 1;
 
-  // Was |poll_ms|, deprecated.
-  reserved 2;
+  reserved 2;  // Was |poll_ms|, deprecated.
 
   // If set ignores all log messages whose prio is < the given value.
   optional AndroidLogPriority min_prio = 3;
diff --git a/protos/perfetto/config/chrome/chrome_config.proto b/protos/perfetto/config/chrome/chrome_config.proto
index aa9333b..aa24c38 100644
--- a/protos/perfetto/config/chrome/chrome_config.proto
+++ b/protos/perfetto/config/chrome/chrome_config.proto
@@ -24,25 +24,4 @@
   // When enabled, the data source should only fill in fields in the output that
   // are not potentially privacy sensitive.
   optional bool privacy_filtering_enabled = 2;
-
-  // Instead of emitting binary protobuf, convert the trace data to the legacy
-  // JSON format. Note that the trace data will still be returned as a series of
-  // TracePackets, but the embedded data will be JSON instead of serialized
-  // protobuf.
-  optional bool convert_to_legacy_json = 3;
-
-  // Priority of the tracing session client. A higher priority session may
-  // preempt a lower priority one in configurations where concurrent sessions
-  // aren't supported.
-  enum ClientPriority {
-    UNKNOWN = 0;
-    BACKGROUND = 1;
-    USER_INITIATED = 2;
-  }
-  optional ClientPriority client_priority = 4;
-
-  // Applicable only when using legacy JSON format.
-  // If |json_agent_label_filter| is not empty, only data pertaining to
-  // the specified tracing agent label (e.g. "traceEvents") will be returned.
-  optional string json_agent_label_filter = 5;
 }
diff --git a/protos/perfetto/config/data_source_config.proto b/protos/perfetto/config/data_source_config.proto
index 22b18e3..5f99d5a 100644
--- a/protos/perfetto/config/data_source_config.proto
+++ b/protos/perfetto/config/data_source_config.proto
@@ -26,7 +26,6 @@
 import "protos/perfetto/config/gpu/gpu_counter_config.proto";
 import "protos/perfetto/config/gpu/vulkan_memory_config.proto";
 import "protos/perfetto/config/inode_file/inode_file_config.proto";
-import "protos/perfetto/config/interceptor_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";
@@ -37,16 +36,7 @@
 import "protos/perfetto/config/track_event/track_event_config.proto";
 
 // The configuration that is passed to each data source when starting tracing.
-// Next id: 116
 message DataSourceConfig {
-  enum SessionInitiator {
-    SESSION_INITIATOR_UNSPECIFIED = 0;
-    // This trace was initiated from a trusted system app has DUMP and
-    // USAGE_STATS permission. This system app is expected to not expose the
-    // trace to the user of the device.
-    // This is determined by checking the UID initiating the trace.
-    SESSION_INITIATOR_TRUSTED_SYSTEM = 1;
-  };
   // Data source unique name, e.g., "linux.ftrace". This must match
   // the name passed by the data source when it registers (see
   // RegisterDataSource()).
@@ -73,16 +63,11 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional bool enable_extra_guardrails = 6;
 
-  // Set by the service to indicate which user initiated this trace.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional SessionInitiator session_initiator = 8;
-
   // Set by the service to indicate which tracing session the data source
   // belongs to. The intended use case for this is checking if two data sources,
   // one of which produces metadata for the other one, belong to the same trace
   // session and hence should be linked together.
   // This field was introduced in Aug 2018 after Android P.
-  // DO NOT SET in consumer as this will be overridden by the service.
   optional uint64 tracing_session_id = 4;
 
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
@@ -131,16 +116,6 @@
   // C++ class for it so it can pass around plain C++ objets.
   optional ChromeConfig chrome_config = 101;
 
-  // If an interceptor is specified here, packets for this data source will be
-  // rerouted to the interceptor instead of the main trace buffer. This can be
-  // used, for example, to write trace data into ETW or for logging trace points
-  // to the console.
-  //
-  // Note that interceptors are only supported by data sources registered
-  // through the Perfetto SDK API. Data sources that don't use that API (e.g.,
-  // traced_probes) may not support interception.
-  optional InterceptorConfig interceptor_config = 115;
-
   // 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
   // is part of the platform (i.e. traced service) is supposed to *not* truncate
@@ -153,6 +128,5 @@
   // This field is only used for testing.
   optional TestConfig for_testing = 1001;
 
-  // Was |for_testing|. Caused more problems then found.
-  reserved 268435455;
+  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
 }
diff --git a/protos/perfetto/config/ftrace/ftrace_config.proto b/protos/perfetto/config/ftrace/ftrace_config.proto
index 070b481..3b78baa 100644
--- a/protos/perfetto/config/ftrace/ftrace_config.proto
+++ b/protos/perfetto/config/ftrace/ftrace_config.proto
@@ -35,17 +35,4 @@
     optional bool enabled = 1;
   }
   optional CompactSchedConfig compact_sched = 12;
-
-  // Enables symbol name resolution against /proc/kallsyms.
-  // It requires that either traced_probes is running as root or that
-  // kptr_restrict has been manually lowered.
-  // It does not disclose KASLR, symbol addresses are mangled.
-  optional bool symbolize_ksyms = 13;
-
-  // By default the kernel symbolizer is lazily initialized on a deferred task
-  // to reduce ftrace's time-to-start-recording. Unfortunately that makes
-  // ksyms integration tests hard. This flag forces the kernel symbolizer to be
-  // initialized synchronously on the data source start and hence avoiding
-  // timing races in tests.
-  optional bool initialize_ksyms_synchronously_for_testing = 14;
 }
diff --git a/protos/perfetto/config/interceptor_config.proto b/protos/perfetto/config/interceptor_config.proto
deleted file mode 100644
index 7ecc13b..0000000
--- a/protos/perfetto/config/interceptor_config.proto
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-import "protos/perfetto/config/interceptors/console_config.proto";
-
-// Configuration for trace packet interception. Used for diverting trace data to
-// non-Perfetto sources (e.g., logging to the console, ETW) when using the
-// Perfetto SDK.
-message InterceptorConfig {
-  // Matches the name given to RegisterInterceptor().
-  optional string name = 1;
-
-  optional ConsoleConfig console_config = 100 [lazy = true];
-}
diff --git a/protos/perfetto/config/interceptors/BUILD.gn b/protos/perfetto/config/interceptors/BUILD.gn
deleted file mode 100644
index 2330b10..0000000
--- a/protos/perfetto/config/interceptors/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../../gn/perfetto.gni")
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  deps = [ "../../common:@TYPE@" ]
-  sources = [ "console_config.proto" ]
-}
diff --git a/protos/perfetto/config/interceptors/console_config.proto b/protos/perfetto/config/interceptors/console_config.proto
deleted file mode 100644
index 7f0189f..0000000
--- a/protos/perfetto/config/interceptors/console_config.proto
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-package perfetto.protos;
-
-message ConsoleConfig {
-  enum Output {
-    OUTPUT_UNSPECIFIED = 0;
-    OUTPUT_STDOUT = 1;
-    OUTPUT_STDERR = 2;
-  }
-  optional Output output = 1;
-  optional bool enable_colors = 2;
-}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 756c8a6..c6cb90c 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -25,8 +25,7 @@
     VERTICES = 2;
     FRAGMENTS = 3;
     PRIMITIVES = 4;
-    // Includes counters relating to caching and bandwidth.
-    MEMORY = 5;
+    MEMORY = 5;  // Includes counters relating to caching and bandwidth.
     COMPUTE = 6;
   }
 
@@ -34,8 +33,7 @@
     optional uint32 counter_id = 1;
     optional string name = 2;
     optional string description = 3;
-    // MeasureUnit unit (deprecated)
-    reserved 4;
+    reserved 4;  // MeasureUnit unit (deprecated)
     oneof peak_value {
       int64 int_peak_value = 5;
       double double_peak_value = 6;
@@ -155,8 +153,7 @@
 // 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 {
-  // e.g., "linux.ftrace", "chromium.tracing"
-  optional string name = 1;
+  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
@@ -189,20 +186,9 @@
 message TracingServiceState {
   // Describes a producer process.
   message Producer {
-    // Unique ID of the producer (monotonic counter).
-    optional int32 id = 1;
-
-    // Typically matches the process name.
-    optional string name = 2;
-
-    // Unix uid of the remote process.
-    optional int32 uid = 3;
-
-    // The version of the client library used by the producer.
-    // This is a human readable string with and its format varies depending on
-    // the build system and the repo (standalone vs AOSP).
-    // This is intended for human debugging only.
-    optional string sdk_version = 4;
+    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
@@ -226,12 +212,6 @@
 
   // Number of tracing sessions in the started state. Always <= num_sessions.
   optional int32 num_sessions_started = 4;
-
-  // The version of traced (the same returned by `traced --version`).
-  // This is a human readable string with and its format varies depending on
-  // the build system and the repo (standalone vs AOSP).
-  // This is intended for human debugging only.
-  optional string tracing_service_version = 5;
 }
 
 // End of protos/perfetto/common/tracing_service_state.proto
@@ -257,9 +237,7 @@
 
 // Values from NDK's android/log.h.
 enum AndroidLogId {
-  // MAIN.
-  LID_DEFAULT = 0;
-
+  LID_DEFAULT = 0;  // MAIN.
   LID_RADIO = 1;
   LID_EVENTS = 2;
   LID_SYSTEM = 3;
@@ -271,10 +249,7 @@
 
 enum AndroidLogPriority {
   PRIO_UNSPECIFIED = 0;
-
-  // _DEFAULT, but should never be seen in logs.
-  PRIO_UNUSED = 1;
-
+  PRIO_UNUSED = 1;  // _DEFAULT, but should never be seen in logs.
   PRIO_VERBOSE = 2;
   PRIO_DEBUG = 3;
   PRIO_INFO = 4;
@@ -290,8 +265,7 @@
 message AndroidLogConfig {
   repeated AndroidLogId log_ids = 1;
 
-  // Was |poll_ms|, deprecated.
-  reserved 2;
+  reserved 2;  // Was |poll_ms|, deprecated.
 
   // If set ignores all log messages whose prio is < the given value.
   optional AndroidLogPriority min_prio = 3;
@@ -335,27 +309,6 @@
   // When enabled, the data source should only fill in fields in the output that
   // are not potentially privacy sensitive.
   optional bool privacy_filtering_enabled = 2;
-
-  // Instead of emitting binary protobuf, convert the trace data to the legacy
-  // JSON format. Note that the trace data will still be returned as a series of
-  // TracePackets, but the embedded data will be JSON instead of serialized
-  // protobuf.
-  optional bool convert_to_legacy_json = 3;
-
-  // Priority of the tracing session client. A higher priority session may
-  // preempt a lower priority one in configurations where concurrent sessions
-  // aren't supported.
-  enum ClientPriority {
-    UNKNOWN = 0;
-    BACKGROUND = 1;
-    USER_INITIATED = 2;
-  }
-  optional ClientPriority client_priority = 4;
-
-  // Applicable only when using legacy JSON format.
-  // If |json_agent_label_filter| is not empty, only data pertaining to
-  // the specified tracing agent label (e.g. "traceEvents") will be returned.
-  optional string json_agent_label_filter = 5;
 }
 
 // End of protos/perfetto/config/chrome/chrome_config.proto
@@ -379,19 +332,6 @@
     optional bool enabled = 1;
   }
   optional CompactSchedConfig compact_sched = 12;
-
-  // Enables symbol name resolution against /proc/kallsyms.
-  // It requires that either traced_probes is running as root or that
-  // kptr_restrict has been manually lowered.
-  // It does not disclose KASLR, symbol addresses are mangled.
-  optional bool symbolize_ksyms = 13;
-
-  // By default the kernel symbolizer is lazily initialized on a deferred task
-  // to reduce ftrace's time-to-start-recording. Unfortunately that makes
-  // ksyms integration tests hard. This flag forces the kernel symbolizer to be
-  // initialized synchronously on the data source start and hence avoiding
-  // timing races in tests.
-  optional bool initialize_ksyms_synchronously_for_testing = 14;
 }
 
 // End of protos/perfetto/config/ftrace/ftrace_config.proto
@@ -458,61 +398,21 @@
 
 // End of protos/perfetto/config/inode_file/inode_file_config.proto
 
-// Begin of protos/perfetto/config/interceptors/console_config.proto
-
-message ConsoleConfig {
-  enum Output {
-    OUTPUT_UNSPECIFIED = 0;
-    OUTPUT_STDOUT = 1;
-    OUTPUT_STDERR = 2;
-  }
-  optional Output output = 1;
-  optional bool enable_colors = 2;
-}
-
-// End of protos/perfetto/config/interceptors/console_config.proto
-
-// Begin of protos/perfetto/config/interceptor_config.proto
-
-// Configuration for trace packet interception. Used for diverting trace data to
-// non-Perfetto sources (e.g., logging to the console, ETW) when using the
-// Perfetto SDK.
-message InterceptorConfig {
-  // Matches the name given to RegisterInterceptor().
-  optional string name = 1;
-
-  optional ConsoleConfig console_config = 100 [lazy = true];
-}
-
-// End of protos/perfetto/config/interceptor_config.proto
-
 // Begin of protos/perfetto/config/power/android_power_config.proto
 
 message AndroidPowerConfig {
   enum BatteryCounters {
     BATTERY_COUNTER_UNSPECIFIED = 0;
-
-    // Coulomb counter.
-    BATTERY_COUNTER_CHARGE = 1;
-
-    // Charge (%).
-    BATTERY_COUNTER_CAPACITY_PERCENT = 2;
-
-    // Instantaneous current.
-    BATTERY_COUNTER_CURRENT = 3;
-
-    // Avg current.
-    BATTERY_COUNTER_CURRENT_AVG = 4;
+    BATTERY_COUNTER_CHARGE = 1;            // Coulomb counter.
+    BATTERY_COUNTER_CAPACITY_PERCENT = 2;  // Charge (%).
+    BATTERY_COUNTER_CURRENT = 3;           // Instantaneous current.
+    BATTERY_COUNTER_CURRENT_AVG = 4;       // Avg current.
   }
   optional uint32 battery_poll_ms = 1;
   repeated BatteryCounters battery_counters = 2;
 
   // Where available enables per-power-rail measurements.
   optional bool collect_power_rails = 3;
-
-  // Provides a breakdown of energy estimation for various subsystem (e.g. GPU).
-  // Available from Android S.
-  optional bool collect_energy_estimation_breakdown = 4;
 }
 
 // End of protos/perfetto/config/power/android_power_config.proto
@@ -571,7 +471,7 @@
 // Begin of protos/perfetto/config/profiling/heapprofd_config.proto
 
 // Configuration for go/heapprofd.
-// Next id: 27
+// Next id: 19
 message HeapprofdConfig {
   message ContinuousDumpConfig {
     // ms to wait before first dump.
@@ -580,33 +480,13 @@
     optional uint32 dump_interval_ms = 6;
   }
 
-  // Sampling rate for all heaps not specified via heap_sampling_intervals.
-  //
-  // These are:
-  // * All heaps if heap_sampling_intervals is empty.
-  // * Those profiled due to all_heaps and not named in heaps if
-  //   heap_sampling_intervals is not empty.
-  // * The implicit libc.malloc heap if heaps is empty.
-  //
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
   //
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#sampling-interval
-  // for more details.
-  //
-  // BUGS
-  // Before Android 12, setting this to 0 would crash the target process.
+  // See https://docs.perfetto.dev/#/heapprofd?id=sampling-interval for more
+  // details.
   optional uint64 sampling_interval_bytes = 1;
 
-  // If less than the given numbers of bytes are left free in the shared
-  // memory buffer, increase sampling interval by a factor of two.
-  // Adaptive sampling is disabled when set to 0.
-  optional uint64 adaptive_sampling_shmem_threshold = 24;
-  // Stop doubling the sampling_interval once the sampling interval has reached
-  // this value.
-  optional uint64 adaptive_sampling_max_sampling_interval_bytes = 25;
-
   // E.g. surfaceflinger, com.android.phone
   // This input is normalized in the following way: if it contains slashes,
   // everything up to the last slash is discarded. If it contains "@",
@@ -619,47 +499,9 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 4;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 26;
-
-  // Which heaps to sample, e.g. "libc.malloc". If left empty, only samples
-  // "malloc".
-  //
-  // Introduced in Android 12.
-  repeated string heaps = 20;
-
-  // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
-  // combination with all_heaps;
-  //
-  // Introduced in Android 12.
-  repeated string exclude_heaps = 27;
-
-  optional bool stream_allocations = 23;
-
-  // If given, needs to be the same length as heaps and gives the sampling
-  // interval for the respective entry in heaps.
-  //
-  // Otherwise, sampling_interval_bytes is used.
-  //
-  // It is recommended to set sampling_interval_bytes to a reasonable default
-  // value when using this, as a value of 0 for sampling_interval_bytes will
-  // crash the target process before Android 12.
-  //
-  // Introduced in Android 12.
-  repeated uint64 heap_sampling_intervals = 22;
-
-  // Sample all heaps registered by target process. Introduced in Android 12.
-  optional bool all_heaps = 21;
-
   // Profile all processes eligible for profiling on the system.
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#heapprofd-targets
-  // for which processes are eligible.
+  // See https://docs.perfetto.dev/#/heapprofd?id=target-processes for which
+  // processes are eligible.
   //
   // On unmodified userdebug builds, this will lead to system crashes. Zygote
   // will crash when trying to launch a new process as it will have an
@@ -722,8 +564,17 @@
   // Introduced in Android 11.
   optional bool no_running = 11;
 
-  // deprecated idle_allocations.
-  reserved 12;
+  // 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
@@ -773,14 +624,6 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 2;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 7;
-
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 3;
 
@@ -794,107 +637,24 @@
   // * start with /data/app
   // * contain "extracted in memory from Y", where Y matches any of the above
   optional bool dump_smaps = 5;
-
-  // Exclude objects of the following types from the profile. This can be
-  // useful if lots of uninteresting objects, e.g. "sun.misc.Cleaner".
-  repeated string ignored_types = 6;
 }
 
 // End of protos/perfetto/config/profiling/java_hprof_config.proto
 
-// Begin of protos/perfetto/common/perf_events.proto
-
-message PerfEvents {
-  // What event to sample on, and how often. Commented from the perspective of
-  // its use in |PerfEventConfig|.
-  message Timebase {
-    // How often the per-cpu sampling will occur. Not guaranteed to be honored
-    // as the kernel can throttle the sampling rate if it's too high.
-    // If unset, an implementation-defined default is used.
-    oneof interval {
-      // Per-cpu sampling frequency in Hz, as requested from the kernel. Not the
-      // same as 1/period.
-      // Details: the actual sampling will still be based on a period, but the
-      // kernel will dynamically adjust it based on the observed event rate, to
-      // approximate this frequency. Works best with steady-rate events like
-      // timers.
-      uint64 frequency = 2;
-
-      // Per-cpu sampling will occur every |period| counts of |event|.
-      // Prefer |frequency| by default, as it's easier to oversample with a
-      // fixed period.
-      uint64 period = 1;
-    }
-
-    // Counting event to use as a timebase for the sampling.
-    // If unset, implies the CPU timer (SW_CPU_CLOCK) as the event,
-    // which is what you usually want.
-    // See common/perf_events.proto for the definitions.
-    oneof event {
-      Counter counter = 4;
-      Tracepoint tracepoint = 3;
-    }
-  }
-
-  enum Counter {
-    UNKNOWN_COUNTER = 0;
-    // software:
-    SW_CPU_CLOCK = 1;
-    SW_PAGE_FAULTS = 2;
-    // hardware:
-    HW_CPU_CYCLES = 10;
-    HW_INSTRUCTIONS = 11;
-  }
-
-  message Tracepoint {
-    // Group and name for the tracepoint, acceptable forms:
-    // * "sched/sched_switch"
-    // * "sched:sched_switch"
-    optional string name = 1;
-
-    // Optional field-level filter for the tracepoint. Only events matching this
-    // filter will be counted (and therefore contribute to the sampling period).
-    // Example: "prev_pid >= 42 && next_pid == 0".
-    // For full syntax, see kernel documentation on "Event filtering":
-    // https://www.kernel.org/doc/Documentation/trace/events.txt
-    optional string filter = 2;
-  }
-}
-
-// End of protos/perfetto/common/perf_events.proto
-
 // Begin of protos/perfetto/config/profiling/perf_event_config.proto
 
 // Configuration for the traced_perf profiler.
 //
-// Example config for basic cpu profiling:
-//   perf_event_config {
-//     timebase {
-//       frequency: 80
-//     }
-//     callstack_sampling {
-//       scope {
-//         target_cmdline: "surfaceflinger"
-//         target_cmdline: "system_server"
-//       }
-//       kernel_frames: true
-//     }
-//   }
-//
-// Next id: 19
+// At the time of writing, the config options are restricted to the periodic
+// system-wide stack sampling use-case (|all_cpus| must be true).
 message PerfEventConfig {
-  // What event to sample on, and how often.
-  // Defined in common/perf_events.proto.
-  optional PerfEvents.Timebase timebase = 15;
+  // If true, sample events on all CPUs.
+  optional bool all_cpus = 1;
 
-  // If set, the profiler will sample userspace processes' callstacks at the
-  // interval specified by the |timebase|.
-  // If unset, the profiler will record only the event counts.
-  optional CallstackSampling callstack_sampling = 16;
-
-  //
-  // Kernel <-> userspace ring buffer options:
-  //
+  // Per-cpu sampling frequency (requested from the kernel). Not guaranteed to
+  // be honored as the kernel can throttle the sampling rate if it's too high.
+  // If unset, an implementation-defined default is used.
+  optional uint32 sampling_frequency = 2;
 
   // How often the per-cpu ring buffers are read by the producer.
   // If unset, an implementation-defined default is used.
@@ -905,23 +665,27 @@
   // If unset, an implementation-defined default is used.
   optional uint32 ring_buffer_pages = 3;
 
-  //
-  // Daemon's resource usage limits:
-  //
+  // Process ID (TGID) whitelist. If this list is not empty, only matching
+  // samples will be retained. If multiple whitelists and blacklists are
+  // specified by the config, then all of them are evaluated for each sampled
+  // process.
+  repeated int32 target_pid = 4;
 
-  // Drop samples if the heap memory held by the samples in the unwinder queue
-  // is above the given limit. This counts the memory across all concurrent data
-  // sources (not just this one's), and there is no fairness guarantee - the
-  // whole quota might be used up by a concurrent source.
-  optional uint64 max_enqueued_footprint_kb = 17;
+  // Command line whitelist, matched against the
+  // /proc/<pid>/cmdline (not the comm string), with both sides being
+  // "normalized". Normalization is as follows: (1) trim everything beyond the
+  // first null or "@" byte; (2) if the string contains forward slashes, trim
+  // everything up to and including the last one.
+  repeated string target_cmdline = 5;
 
-  // Stop the data source if traced_perf's combined {RssAnon + Swap} memory
-  // footprint exceeds this value.
-  optional uint32 max_daemon_memory_kb = 13;
+  // PID blacklist.
+  repeated int32 exclude_pid = 6;
 
-  //
+  // Command line blacklist. Normalized in the same way as |target_cmdline|.
+  repeated string exclude_cmdline = 7;
+
+  ////////////////////
   // Uncommon options:
-  //
 
   // Timeout for the remote /proc/<pid>/{maps,mem} file descriptors for a
   // sampled process. This is primarily for Android, where this lookup is
@@ -938,80 +702,6 @@
   // processes, and require the memory footprint to be reset periodically.
   // If unset, the cached state will not be cleared.
   optional uint32 unwind_state_clear_period_ms = 10;
-
-  //
-  // Deprecated (superseded by options above):
-  //
-  // Do not set *any* of these fields in new configs.
-  //
-
-  // Note: legacy configs had to set |all_cpus| to true to pass parsing.
-  // We rely on this to detect such configs.
-  optional bool all_cpus = 1;
-  optional uint32 sampling_frequency = 2;
-  optional bool kernel_frames = 12;
-  repeated int32 target_pid = 4;
-  repeated string target_cmdline = 5;
-
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 18;
-  repeated int32 exclude_pid = 6;
-  repeated string exclude_cmdline = 7;
-  optional uint32 additional_cmdline_count = 11;
-  // previously |tracepoint|
-  reserved 14;
-
-  //
-  // Sub-messages (nested for generated code namespacing).
-  //
-
-  message CallstackSampling {
-    // Defines a set of processes for which samples are retained/skipped. If
-    // unset, all userspace samples are kept, but beware that it will be very
-    // heavy on the stack unwinder, which might start dropping samples due to
-    // overload.
-    optional Scope scope = 1;
-
-    // If true, callstacks will include the kernel-space frames. Such frames can
-    // be identified by a magical "kernel" string as their mapping name.
-    // Requires traced_perf to be running as root, or kptr_restrict to have been
-    // manually unrestricted. On Android, the platform should do the right thing
-    // on debug builds.
-    // This does *not* disclose KASLR, as only the function names are emitted.
-    optional bool kernel_frames = 2;
-  }
-
-  message Scope {
-    // Process ID (TGID) allowlist. If this list is not empty, only matching
-    // samples will be retained. If multiple allow/deny-lists are
-    // specified by the config, then all of them are evaluated for each sampled
-    // process.
-    repeated int32 target_pid = 1;
-
-    // Command line allowlist, matched against the
-    // /proc/<pid>/cmdline (not the comm string), with both sides being
-    // "normalized". Normalization is as follows: (1) trim everything beyond the
-    // first null or "@" byte; (2) if the string contains forward slashes, trim
-    // everything up to and including the last one.
-    repeated string target_cmdline = 2;
-
-    // List of excluded pids.
-    repeated int32 exclude_pid = 3;
-
-    // List of excluded cmdlines. Normalized in the same way as
-    // |target_cmdline|.
-    repeated string exclude_cmdline = 4;
-
-    // Number of additional command lines to sample. Only those which are
-    // neither explicitly included nor excluded will be considered. Processes
-    // are accepted on a first come, first served basis.
-    optional uint32 additional_cmdline_count = 5;
-  }
 }
 
 // End of protos/perfetto/config/profiling/perf_event_config.proto
@@ -1157,39 +847,6 @@
   VMSTAT_NR_ZSPAGES = 93;
   VMSTAT_NR_ION_HEAP = 94;
   VMSTAT_NR_GPU_HEAP = 95;
-  VMSTAT_ALLOCSTALL_DMA = 96;
-  VMSTAT_ALLOCSTALL_MOVABLE = 97;
-  VMSTAT_ALLOCSTALL_NORMAL = 98;
-  VMSTAT_COMPACT_DAEMON_FREE_SCANNED = 99;
-  VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED = 100;
-  VMSTAT_NR_FASTRPC = 101;
-  VMSTAT_NR_INDIRECTLY_RECLAIMABLE = 102;
-  VMSTAT_NR_ION_HEAP_POOL = 103;
-  VMSTAT_NR_KERNEL_MISC_RECLAIMABLE = 104;
-  VMSTAT_NR_SHADOW_CALL_STACK_BYTES = 105;
-  VMSTAT_NR_SHMEM_HUGEPAGES = 106;
-  VMSTAT_NR_SHMEM_PMDMAPPED = 107;
-  VMSTAT_NR_UNRECLAIMABLE_PAGES = 108;
-  VMSTAT_NR_ZONE_ACTIVE_ANON = 109;
-  VMSTAT_NR_ZONE_ACTIVE_FILE = 110;
-  VMSTAT_NR_ZONE_INACTIVE_ANON = 111;
-  VMSTAT_NR_ZONE_INACTIVE_FILE = 112;
-  VMSTAT_NR_ZONE_UNEVICTABLE = 113;
-  VMSTAT_NR_ZONE_WRITE_PENDING = 114;
-  VMSTAT_OOM_KILL = 115;
-  VMSTAT_PGLAZYFREE = 116;
-  VMSTAT_PGLAZYFREED = 117;
-  VMSTAT_PGREFILL = 118;
-  VMSTAT_PGSCAN_DIRECT = 119;
-  VMSTAT_PGSCAN_KSWAPD = 120;
-  VMSTAT_PGSKIP_DMA = 121;
-  VMSTAT_PGSKIP_MOVABLE = 122;
-  VMSTAT_PGSKIP_NORMAL = 123;
-  VMSTAT_PGSTEAL_DIRECT = 124;
-  VMSTAT_PGSTEAL_KSWAPD = 125;
-  VMSTAT_SWAP_RA = 126;
-  VMSTAT_SWAP_RA_HIT = 127;
-  VMSTAT_WORKINGSET_RESTORE = 128;
 }
 // End of protos/perfetto/common/sys_stats_counters.proto
 
@@ -1232,12 +889,6 @@
     STAT_FORK_COUNT = 4;
   }
   repeated StatCounters stat_counters = 6;
-
-  // Polls /sys/devfreq/*/curfreq every X ms, if non-zero.
-  // This is required to be > 10ms to avoid excessive CPU usage.
-  // This option can be used to record unchanging values.
-  // Updates from frequency changes can come from ftrace/set_clock_rate.
-  optional uint32 devfreq_period_ms = 7;
 }
 
 // End of protos/perfetto/config/sys_stats/sys_stats_config.proto
@@ -1326,18 +977,10 @@
   //       disabled_tags = ["*"]
   //       enabled_tags = ["my_tag"]
   //
-
-  // Default: []
-  repeated string disabled_categories = 1;
-
-  // Default: []
-  repeated string enabled_categories = 2;
-
-  // Default: [“slow”, “debug”]
-  repeated string disabled_tags = 3;
-
-  // Default: []
-  repeated string enabled_tags = 4;
+  repeated string disabled_categories = 1;  // Default: []
+  repeated string enabled_categories = 2;   // Default: []
+  repeated string disabled_tags = 3;  // Default: [“slow”, “debug”]
+  repeated string enabled_tags = 4;   // Default: []
 }
 
 // End of protos/perfetto/config/track_event/track_event_config.proto
@@ -1345,16 +988,7 @@
 // Begin of protos/perfetto/config/data_source_config.proto
 
 // The configuration that is passed to each data source when starting tracing.
-// Next id: 116
 message DataSourceConfig {
-  enum SessionInitiator {
-    SESSION_INITIATOR_UNSPECIFIED = 0;
-    // This trace was initiated from a trusted system app has DUMP and
-    // USAGE_STATS permission. This system app is expected to not expose the
-    // trace to the user of the device.
-    // This is determined by checking the UID initiating the trace.
-    SESSION_INITIATOR_TRUSTED_SYSTEM = 1;
-  };
   // Data source unique name, e.g., "linux.ftrace". This must match
   // the name passed by the data source when it registers (see
   // RegisterDataSource()).
@@ -1381,16 +1015,11 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional bool enable_extra_guardrails = 6;
 
-  // Set by the service to indicate which user initiated this trace.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional SessionInitiator session_initiator = 8;
-
   // Set by the service to indicate which tracing session the data source
   // belongs to. The intended use case for this is checking if two data sources,
   // one of which produces metadata for the other one, belong to the same trace
   // session and hence should be linked together.
   // This field was introduced in Aug 2018 after Android P.
-  // DO NOT SET in consumer as this will be overridden by the service.
   optional uint64 tracing_session_id = 4;
 
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
@@ -1439,16 +1068,6 @@
   // C++ class for it so it can pass around plain C++ objets.
   optional ChromeConfig chrome_config = 101;
 
-  // If an interceptor is specified here, packets for this data source will be
-  // rerouted to the interceptor instead of the main trace buffer. This can be
-  // used, for example, to write trace data into ETW or for logging trace points
-  // to the console.
-  //
-  // Note that interceptors are only supported by data sources registered
-  // through the Perfetto SDK API. Data sources that don't use that API (e.g.,
-  // traced_probes) may not support interception.
-  optional InterceptorConfig interceptor_config = 115;
-
   // 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
   // is part of the platform (i.e. traced service) is supposed to *not* truncate
@@ -1461,8 +1080,7 @@
   // This field is only used for testing.
   optional TestConfig for_testing = 1001;
 
-  // Was |for_testing|. Caused more problems then found.
-  reserved 268435455;
+  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
 }
 
 // End of protos/perfetto/config/data_source_config.proto
@@ -1474,16 +1092,13 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 33.
+// Next id: 30.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
 
-    // |page_size|, now deprecated.
-    reserved 2;
-
-    // |optimize_for|, now deprecated.
-    reserved 3;
+    reserved 2;  // |page_size|, now deprecated.
+    reserved 3;  // |optimize_for|, now deprecated.
 
     enum FillPolicy {
       UNSPECIFIED = 0;
@@ -1551,21 +1166,6 @@
     // only keeps track of the first and the most recent snapshot until
     // ReadBuffers() is called.
     optional uint32 snapshot_interval_ms = 6;
-
-    // Hints to the service that a suspend-aware (i.e. counting time in suspend)
-    // clock should be used for periodic snapshots of service-emitted events.
-    // This means, if a snapshot *should* have happened during suspend, it will
-    // happen immediately after the device resumes.
-    //
-    // Choosing a clock like this is done on best-effort basis; not all
-    // platforms (e.g. Windows) expose a clock which can be used for periodic
-    // tasks counting suspend. If such a clock is not available, the service
-    // falls back to the best-available alternative.
-    //
-    // Introduced in Android S.
-    // TODO(lalitm): deprecate this in T and make this the default if nothing
-    // crashes in S.
-    optional bool prefer_suspend_clock_for_snapshot = 7;
   }
   optional BuiltinDataSource builtin_data_sources = 20;
 
@@ -1649,14 +1249,13 @@
   optional uint64 max_file_size_bytes = 10;
 
   // Contains flags which override the default values of the guardrails inside
-  // Perfetto.
+  // Perfetto. These values are only affect userdebug builds.
   message GuardrailOverrides {
     // Override the default limit (in bytes) for uploading data to server within
     // a 24 hour period.
-    // On R-, this override only affected userdebug builds. Since S, it also
-    // affects user builds.
     optional uint64 max_upload_per_day_bytes = 1;
   }
+
   optional GuardrailOverrides guardrail_overrides = 11;
 
   // When true, data sources are not started until an explicit call to
@@ -1681,22 +1280,12 @@
   // Default 5s.
   optional uint32 data_source_stop_timeout_ms = 23;
 
-  // |disable_clock_snapshotting| moved.
-  reserved 15;
+  reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
   // trace ends to notify it about the trace readiness.
   optional bool notify_traceur = 16;
 
-  // Android-only. If set to a value > 0, marks the trace session as a candidate
-  // for being attached to a bugreport. This field effectively acts as a z-index
-  // for bugreports. When Android's dumpstate runs perfetto
-  // --save-for-bugreport, traced will pick the tracing session with the highest
-  // score (score <= 0 is ignored), will steal its contents, save the trace into
-  // a known path and stop prematurely.
-  // This field was introduced in Android S.
-  optional int32 bugreport_score = 30;
-
   // Triggers allow producers to start or stop the tracing session when an event
   // occurs.
   //
@@ -1732,7 +1321,7 @@
       // The producer must specify this name to activate the trigger.
       optional string name = 1;
 
-      // An std::regex that will match the producer that can activate this
+      // The a std::regex that will match the producer that can activate this
       // trigger. This is optional. If unset any producers can activate this
       // trigger.
       optional string producer_name_regex = 2;
@@ -1740,24 +1329,6 @@
       // After a trigger is received either in START_TRACING or STOP_TRACING
       // mode then the trace will end |stop_delay_ms| after triggering.
       optional uint32 stop_delay_ms = 3;
-
-      // Limits the number of traces this trigger can start/stop in a rolling
-      // 24 hour window. If this field is unset or zero, no limit is applied and
-      // activiation of this trigger *always* starts/stops the trace.
-      optional uint32 max_per_24_h = 4;
-
-      // A value between 0 and 1 which encodes the probability of skipping a
-      // trigger with this name. This is useful for reducing the probability
-      // of high-frequency triggers from dominating trace finaization. If this
-      // field is unset or zero, the trigger will *never* be skipped. If this
-      // field is greater than or equal to 1, this trigger will *always* be
-      // skipped i.e. it will be as if this trigger was never included in the
-      // first place.
-      // This probability check is applied *before* any other limits. For
-      // example, if |max_per_24_h| is also set, first we will check if the
-      // probability bar is met and only then will we check the |max_per_24_h|
-      // limit.
-      optional double skip_probability = 5;
     }
     // A list of triggers which are related to this configuration. If ANY
     // trigger is seen then an action will be performed based on |trigger_mode|.
@@ -1816,68 +1387,27 @@
   }
   optional CompressionType compression_type = 24;
 
-  // Android-only. Not for general use. If set, saves the trace into an
-  // incident. This field is read by perfetto_cmd, rather than the tracing
-  // service. This field must be set when passing the --upload flag to
-  // perfetto_cmd.
+  // Android-only. Debug builds only. Not for general use. If set, saves a
+  // Dropbox trace into an incident. This field is read by perfetto_cmd, rather
+  // than the tracing service. All fields are mandatory.
   message IncidentReportConfig {
-    // In this message, either:
-    //  * all of |destination_package|, |destination_class| and |privacy_level|
-    //    must be set.
-    //  * |skip_incidentd| must be explicitly set to true.
-
     optional string destination_package = 1;
     optional string destination_class = 2;
     // Level of filtering in the requested incident. See |Destination| in
     // frameworks/base/core/proto/android/privacy.proto.
     optional int32 privacy_level = 3;
-
-    // If true, then skips saving the trace to incidentd.
-    //
-    // This flag is useful in testing (e.g. Perfetto-statsd integration tests)
-    // or when we explicitly don't want traces to go to incidentd even when they
-    // usually would (e.g. configs deployed using statsd but only used for
-    // inclusion in bugreports using |bugreport_score|).
-    //
-    // The motivation for having this flag, instead of just not setting
-    // |incident_report_config|, is prevent accidents where
-    // |incident_report_config| is omitted by mistake.
-    optional bool skip_incidentd = 5;
-
     // If true, do not write the trace into dropbox (i.e. incident only).
     // Otherwise, write to both dropbox and incident.
-    // TODO(lalitm): remove this field as we no longer use Dropbox.
-    optional bool skip_dropbox = 4 [deprecated = true];
+    optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
 
-  enum StatsdLogging {
-    STATSD_LOGGING_UNSPECIFIED = 0;
-    STATSD_LOGGING_ENABLED = 1;
-    STATSD_LOGGING_DISABLED = 2;
-  }
-
-  // Android-only. Not for general use. If specified, sets the logging to statsd
-  // of guardrails and checkpoints in the tracing service. perfetto_cmd sets
-  // this to enabled (if not explicitly set in the config) when specifying
-  // --upload.
-  optional StatsdLogging statsd_logging = 31;
-
   // DEPRECATED. Was trace_uuid, use trace_uuid_msb and trace_uuid_lsb instead.
   reserved 26;
   // An identifier clients can use to tie this trace to other logging.
   // Alternative encoding of trace_uuid as two int64s.
   optional int64 trace_uuid_msb = 27;
   optional int64 trace_uuid_lsb = 28;
-
-  // When set applies a post-filter to the trace contents using the filter
-  // provided. The filter is applied at ReadBuffers() time and works both in the
-  // case of IPC readback and write_into_file. This filter can be generated
-  // using `tools/proto_filter -s schema.proto -F filter_out.bytes` or
-  // `-T filter_out.escaped_string` (for .pbtx).
-  // Introduced in Android S. See go/trace-filtering for design.
-  message TraceFilter { optional bytes bytecode = 1; }
-  optional TraceFilter trace_filter = 32;
 }
 
 // End of protos/perfetto/config/trace_config.proto
diff --git a/protos/perfetto/config/power/android_power_config.proto b/protos/perfetto/config/power/android_power_config.proto
index 82c4bb2..9cc795a 100644
--- a/protos/perfetto/config/power/android_power_config.proto
+++ b/protos/perfetto/config/power/android_power_config.proto
@@ -21,26 +21,14 @@
 message AndroidPowerConfig {
   enum BatteryCounters {
     BATTERY_COUNTER_UNSPECIFIED = 0;
-
-    // Coulomb counter.
-    BATTERY_COUNTER_CHARGE = 1;
-
-    // Charge (%).
-    BATTERY_COUNTER_CAPACITY_PERCENT = 2;
-
-    // Instantaneous current.
-    BATTERY_COUNTER_CURRENT = 3;
-
-    // Avg current.
-    BATTERY_COUNTER_CURRENT_AVG = 4;
+    BATTERY_COUNTER_CHARGE = 1;            // Coulomb counter.
+    BATTERY_COUNTER_CAPACITY_PERCENT = 2;  // Charge (%).
+    BATTERY_COUNTER_CURRENT = 3;           // Instantaneous current.
+    BATTERY_COUNTER_CURRENT_AVG = 4;       // Avg current.
   }
   optional uint32 battery_poll_ms = 1;
   repeated BatteryCounters battery_counters = 2;
 
   // Where available enables per-power-rail measurements.
   optional bool collect_power_rails = 3;
-
-  // Provides a breakdown of energy estimation for various subsystem (e.g. GPU).
-  // Available from Android S.
-  optional bool collect_energy_estimation_breakdown = 4;
 }
diff --git a/protos/perfetto/config/profiling/BUILD.gn b/protos/perfetto/config/profiling/BUILD.gn
index a586101..8ded46e 100644
--- a/protos/perfetto/config/profiling/BUILD.gn
+++ b/protos/perfetto/config/profiling/BUILD.gn
@@ -15,7 +15,6 @@
 import("../../../../gn/proto_library.gni")
 
 perfetto_proto_library("@TYPE@") {
-  deps = [ "../../common:@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 00dd692..e04dfe3 100644
--- a/protos/perfetto/config/profiling/heapprofd_config.proto
+++ b/protos/perfetto/config/profiling/heapprofd_config.proto
@@ -19,7 +19,7 @@
 package perfetto.protos;
 
 // Configuration for go/heapprofd.
-// Next id: 27
+// Next id: 19
 message HeapprofdConfig {
   message ContinuousDumpConfig {
     // ms to wait before first dump.
@@ -28,33 +28,13 @@
     optional uint32 dump_interval_ms = 6;
   }
 
-  // Sampling rate for all heaps not specified via heap_sampling_intervals.
-  //
-  // These are:
-  // * All heaps if heap_sampling_intervals is empty.
-  // * Those profiled due to all_heaps and not named in heaps if
-  //   heap_sampling_intervals is not empty.
-  // * The implicit libc.malloc heap if heaps is empty.
-  //
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
   //
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#sampling-interval
-  // for more details.
-  //
-  // BUGS
-  // Before Android 12, setting this to 0 would crash the target process.
+  // See https://docs.perfetto.dev/#/heapprofd?id=sampling-interval for more
+  // details.
   optional uint64 sampling_interval_bytes = 1;
 
-  // If less than the given numbers of bytes are left free in the shared
-  // memory buffer, increase sampling interval by a factor of two.
-  // Adaptive sampling is disabled when set to 0.
-  optional uint64 adaptive_sampling_shmem_threshold = 24;
-  // Stop doubling the sampling_interval once the sampling interval has reached
-  // this value.
-  optional uint64 adaptive_sampling_max_sampling_interval_bytes = 25;
-
   // E.g. surfaceflinger, com.android.phone
   // This input is normalized in the following way: if it contains slashes,
   // everything up to the last slash is discarded. If it contains "@",
@@ -67,47 +47,9 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 4;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 26;
-
-  // Which heaps to sample, e.g. "libc.malloc". If left empty, only samples
-  // "malloc".
-  //
-  // Introduced in Android 12.
-  repeated string heaps = 20;
-
-  // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
-  // combination with all_heaps;
-  //
-  // Introduced in Android 12.
-  repeated string exclude_heaps = 27;
-
-  optional bool stream_allocations = 23;
-
-  // If given, needs to be the same length as heaps and gives the sampling
-  // interval for the respective entry in heaps.
-  //
-  // Otherwise, sampling_interval_bytes is used.
-  //
-  // It is recommended to set sampling_interval_bytes to a reasonable default
-  // value when using this, as a value of 0 for sampling_interval_bytes will
-  // crash the target process before Android 12.
-  //
-  // Introduced in Android 12.
-  repeated uint64 heap_sampling_intervals = 22;
-
-  // Sample all heaps registered by target process. Introduced in Android 12.
-  optional bool all_heaps = 21;
-
   // Profile all processes eligible for profiling on the system.
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#heapprofd-targets
-  // for which processes are eligible.
+  // See https://docs.perfetto.dev/#/heapprofd?id=target-processes for which
+  // processes are eligible.
   //
   // On unmodified userdebug builds, this will lead to system crashes. Zygote
   // will crash when trying to launch a new process as it will have an
@@ -170,8 +112,17 @@
   // Introduced in Android 11.
   optional bool no_running = 11;
 
-  // deprecated idle_allocations.
-  reserved 12;
+  // 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
diff --git a/protos/perfetto/config/profiling/java_hprof_config.proto b/protos/perfetto/config/profiling/java_hprof_config.proto
index d504678..7a6c652 100644
--- a/protos/perfetto/config/profiling/java_hprof_config.proto
+++ b/protos/perfetto/config/profiling/java_hprof_config.proto
@@ -40,14 +40,6 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 2;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 7;
-
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 3;
 
@@ -61,8 +53,4 @@
   // * start with /data/app
   // * contain "extracted in memory from Y", where Y matches any of the above
   optional bool dump_smaps = 5;
-
-  // Exclude objects of the following types from the profile. This can be
-  // useful if lots of uninteresting objects, e.g. "sun.misc.Cleaner".
-  repeated string ignored_types = 6;
 }
diff --git a/protos/perfetto/config/profiling/perf_event_config.proto b/protos/perfetto/config/profiling/perf_event_config.proto
index 754d948..f5b186c 100644
--- a/protos/perfetto/config/profiling/perf_event_config.proto
+++ b/protos/perfetto/config/profiling/perf_event_config.proto
@@ -16,40 +16,20 @@
 
 syntax = "proto2";
 
-import "protos/perfetto/common/perf_events.proto";
-
 package perfetto.protos;
 
 // Configuration for the traced_perf profiler.
 //
-// Example config for basic cpu profiling:
-//   perf_event_config {
-//     timebase {
-//       frequency: 80
-//     }
-//     callstack_sampling {
-//       scope {
-//         target_cmdline: "surfaceflinger"
-//         target_cmdline: "system_server"
-//       }
-//       kernel_frames: true
-//     }
-//   }
-//
-// Next id: 19
+// At the time of writing, the config options are restricted to the periodic
+// system-wide stack sampling use-case (|all_cpus| must be true).
 message PerfEventConfig {
-  // What event to sample on, and how often.
-  // Defined in common/perf_events.proto.
-  optional PerfEvents.Timebase timebase = 15;
+  // If true, sample events on all CPUs.
+  optional bool all_cpus = 1;
 
-  // If set, the profiler will sample userspace processes' callstacks at the
-  // interval specified by the |timebase|.
-  // If unset, the profiler will record only the event counts.
-  optional CallstackSampling callstack_sampling = 16;
-
-  //
-  // Kernel <-> userspace ring buffer options:
-  //
+  // Per-cpu sampling frequency (requested from the kernel). Not guaranteed to
+  // be honored as the kernel can throttle the sampling rate if it's too high.
+  // If unset, an implementation-defined default is used.
+  optional uint32 sampling_frequency = 2;
 
   // How often the per-cpu ring buffers are read by the producer.
   // If unset, an implementation-defined default is used.
@@ -60,23 +40,27 @@
   // If unset, an implementation-defined default is used.
   optional uint32 ring_buffer_pages = 3;
 
-  //
-  // Daemon's resource usage limits:
-  //
+  // Process ID (TGID) whitelist. If this list is not empty, only matching
+  // samples will be retained. If multiple whitelists and blacklists are
+  // specified by the config, then all of them are evaluated for each sampled
+  // process.
+  repeated int32 target_pid = 4;
 
-  // Drop samples if the heap memory held by the samples in the unwinder queue
-  // is above the given limit. This counts the memory across all concurrent data
-  // sources (not just this one's), and there is no fairness guarantee - the
-  // whole quota might be used up by a concurrent source.
-  optional uint64 max_enqueued_footprint_kb = 17;
+  // Command line whitelist, matched against the
+  // /proc/<pid>/cmdline (not the comm string), with both sides being
+  // "normalized". Normalization is as follows: (1) trim everything beyond the
+  // first null or "@" byte; (2) if the string contains forward slashes, trim
+  // everything up to and including the last one.
+  repeated string target_cmdline = 5;
 
-  // Stop the data source if traced_perf's combined {RssAnon + Swap} memory
-  // footprint exceeds this value.
-  optional uint32 max_daemon_memory_kb = 13;
+  // PID blacklist.
+  repeated int32 exclude_pid = 6;
 
-  //
+  // Command line blacklist. Normalized in the same way as |target_cmdline|.
+  repeated string exclude_cmdline = 7;
+
+  ////////////////////
   // Uncommon options:
-  //
 
   // Timeout for the remote /proc/<pid>/{maps,mem} file descriptors for a
   // sampled process. This is primarily for Android, where this lookup is
@@ -93,78 +77,4 @@
   // processes, and require the memory footprint to be reset periodically.
   // If unset, the cached state will not be cleared.
   optional uint32 unwind_state_clear_period_ms = 10;
-
-  //
-  // Deprecated (superseded by options above):
-  //
-  // Do not set *any* of these fields in new configs.
-  //
-
-  // Note: legacy configs had to set |all_cpus| to true to pass parsing.
-  // We rely on this to detect such configs.
-  optional bool all_cpus = 1;
-  optional uint32 sampling_frequency = 2;
-  optional bool kernel_frames = 12;
-  repeated int32 target_pid = 4;
-  repeated string target_cmdline = 5;
-
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 18;
-  repeated int32 exclude_pid = 6;
-  repeated string exclude_cmdline = 7;
-  optional uint32 additional_cmdline_count = 11;
-  // previously |tracepoint|
-  reserved 14;
-
-  //
-  // Sub-messages (nested for generated code namespacing).
-  //
-
-  message CallstackSampling {
-    // Defines a set of processes for which samples are retained/skipped. If
-    // unset, all userspace samples are kept, but beware that it will be very
-    // heavy on the stack unwinder, which might start dropping samples due to
-    // overload.
-    optional Scope scope = 1;
-
-    // If true, callstacks will include the kernel-space frames. Such frames can
-    // be identified by a magical "kernel" string as their mapping name.
-    // Requires traced_perf to be running as root, or kptr_restrict to have been
-    // manually unrestricted. On Android, the platform should do the right thing
-    // on debug builds.
-    // This does *not* disclose KASLR, as only the function names are emitted.
-    optional bool kernel_frames = 2;
-  }
-
-  message Scope {
-    // Process ID (TGID) allowlist. If this list is not empty, only matching
-    // samples will be retained. If multiple allow/deny-lists are
-    // specified by the config, then all of them are evaluated for each sampled
-    // process.
-    repeated int32 target_pid = 1;
-
-    // Command line allowlist, matched against the
-    // /proc/<pid>/cmdline (not the comm string), with both sides being
-    // "normalized". Normalization is as follows: (1) trim everything beyond the
-    // first null or "@" byte; (2) if the string contains forward slashes, trim
-    // everything up to and including the last one.
-    repeated string target_cmdline = 2;
-
-    // List of excluded pids.
-    repeated int32 exclude_pid = 3;
-
-    // List of excluded cmdlines. Normalized in the same way as
-    // |target_cmdline|.
-    repeated string exclude_cmdline = 4;
-
-    // Number of additional command lines to sample. Only those which are
-    // neither explicitly included nor excluded will be considered. Processes
-    // are accepted on a first come, first served basis.
-    optional uint32 additional_cmdline_count = 5;
-  }
 }
diff --git a/protos/perfetto/config/stress_test_config.proto b/protos/perfetto/config/stress_test_config.proto
deleted file mode 100644
index 6ed8cbc..0000000
--- a/protos/perfetto/config/stress_test_config.proto
+++ /dev/null
@@ -1,77 +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.
- */
-
-syntax = "proto2";
-
-import "protos/perfetto/config/trace_config.proto";
-
-package perfetto.protos;
-
-// This is the schema for the config files in /test/stress_test/configs/*.cfg.
-message StressTestConfig {
-  optional TraceConfig trace_config = 1;
-
-  // Shared Memory Buffer setup, passed as arguments to Tracing.Initialize().
-  optional uint32 shmem_size_kb = 2;
-  optional uint32 shmem_page_size_kb = 3;
-
-  // How many producer processes to spawn.
-  optional uint32 num_processes = 4;
-
-  // How many writer threads each producer process should spawn.
-  optional uint32 num_threads = 5;
-
-  // The producer will write events until one of the following is met:
-  // - trace_config.duration_ms is reached.
-  // - max_events is reached.
-  optional uint32 max_events = 6;
-
-  // If > 0 will write nested messages up to N levels deep. The size of each
-  // nested message depends on the payload_mean / sttdev arguments (below).
-  // This is to cover the patching logic.
-  optional uint32 nesting = 7;
-
-  // This submessage defines the timings of each writer worker thread.
-  message WriterTiming {
-    // The size of the payload written on each iteration.
-    optional double payload_mean = 1;
-    optional double payload_stddev = 2;
-
-    // The nominal event writing rate, expressed in events/sec.
-    // E.g. if payload_mean = 500 (bytes) and rate_mean = 1000 (Hz), each thread
-    // will write 500 KB / sec approximately (% stalling).
-    optional double rate_mean = 3;
-    optional double rate_stddev = 4;
-
-    // If non-zero each worker will slow down the writing of the payload:
-    // it writes half payload, sleep for payload_write_time_ms, then write the
-    // other half.
-    optional uint32 payload_write_time_ms = 5;
-  }
-
-  // The timings used by default.
-  optional WriterTiming steady_state_timings = 8;
-
-  // Optionally it is possible to cause a writer to enter "burst mode",
-  // simulating peaks of high-intensity writing. The way it works is the
-  // following: by default the writer writes events using the
-  // |steady_state_timings|. Then every |burst_period_ms| it will switch to the
-  // |burst_timings| for |burst_duration_ms|, and go back to the steady state
-  // after that (and then repeat).
-  optional uint32 burst_period_ms = 9;
-  optional uint32 burst_duration_ms = 10;
-  optional WriterTiming burst_timings = 11;
-}
diff --git a/protos/perfetto/config/sys_stats/sys_stats_config.proto b/protos/perfetto/config/sys_stats/sys_stats_config.proto
index 0986924..4e037fc 100644
--- a/protos/perfetto/config/sys_stats/sys_stats_config.proto
+++ b/protos/perfetto/config/sys_stats/sys_stats_config.proto
@@ -57,10 +57,4 @@
     STAT_FORK_COUNT = 4;
   }
   repeated StatCounters stat_counters = 6;
-
-  // Polls /sys/devfreq/*/curfreq every X ms, if non-zero.
-  // This is required to be > 10ms to avoid excessive CPU usage.
-  // This option can be used to record unchanging values.
-  // Updates from frequency changes can come from ftrace/set_clock_rate.
-  optional uint32 devfreq_period_ms = 7;
 }
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index dbc1bab..28a78d7 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -26,16 +26,13 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 33.
+// Next id: 30.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
 
-    // |page_size|, now deprecated.
-    reserved 2;
-
-    // |optimize_for|, now deprecated.
-    reserved 3;
+    reserved 2;  // |page_size|, now deprecated.
+    reserved 3;  // |optimize_for|, now deprecated.
 
     enum FillPolicy {
       UNSPECIFIED = 0;
@@ -103,21 +100,6 @@
     // only keeps track of the first and the most recent snapshot until
     // ReadBuffers() is called.
     optional uint32 snapshot_interval_ms = 6;
-
-    // Hints to the service that a suspend-aware (i.e. counting time in suspend)
-    // clock should be used for periodic snapshots of service-emitted events.
-    // This means, if a snapshot *should* have happened during suspend, it will
-    // happen immediately after the device resumes.
-    //
-    // Choosing a clock like this is done on best-effort basis; not all
-    // platforms (e.g. Windows) expose a clock which can be used for periodic
-    // tasks counting suspend. If such a clock is not available, the service
-    // falls back to the best-available alternative.
-    //
-    // Introduced in Android S.
-    // TODO(lalitm): deprecate this in T and make this the default if nothing
-    // crashes in S.
-    optional bool prefer_suspend_clock_for_snapshot = 7;
   }
   optional BuiltinDataSource builtin_data_sources = 20;
 
@@ -201,14 +183,13 @@
   optional uint64 max_file_size_bytes = 10;
 
   // Contains flags which override the default values of the guardrails inside
-  // Perfetto.
+  // Perfetto. These values are only affect userdebug builds.
   message GuardrailOverrides {
     // Override the default limit (in bytes) for uploading data to server within
     // a 24 hour period.
-    // On R-, this override only affected userdebug builds. Since S, it also
-    // affects user builds.
     optional uint64 max_upload_per_day_bytes = 1;
   }
+
   optional GuardrailOverrides guardrail_overrides = 11;
 
   // When true, data sources are not started until an explicit call to
@@ -233,22 +214,12 @@
   // Default 5s.
   optional uint32 data_source_stop_timeout_ms = 23;
 
-  // |disable_clock_snapshotting| moved.
-  reserved 15;
+  reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
   // trace ends to notify it about the trace readiness.
   optional bool notify_traceur = 16;
 
-  // Android-only. If set to a value > 0, marks the trace session as a candidate
-  // for being attached to a bugreport. This field effectively acts as a z-index
-  // for bugreports. When Android's dumpstate runs perfetto
-  // --save-for-bugreport, traced will pick the tracing session with the highest
-  // score (score <= 0 is ignored), will steal its contents, save the trace into
-  // a known path and stop prematurely.
-  // This field was introduced in Android S.
-  optional int32 bugreport_score = 30;
-
   // Triggers allow producers to start or stop the tracing session when an event
   // occurs.
   //
@@ -284,7 +255,7 @@
       // The producer must specify this name to activate the trigger.
       optional string name = 1;
 
-      // An std::regex that will match the producer that can activate this
+      // The a std::regex that will match the producer that can activate this
       // trigger. This is optional. If unset any producers can activate this
       // trigger.
       optional string producer_name_regex = 2;
@@ -292,24 +263,6 @@
       // After a trigger is received either in START_TRACING or STOP_TRACING
       // mode then the trace will end |stop_delay_ms| after triggering.
       optional uint32 stop_delay_ms = 3;
-
-      // Limits the number of traces this trigger can start/stop in a rolling
-      // 24 hour window. If this field is unset or zero, no limit is applied and
-      // activiation of this trigger *always* starts/stops the trace.
-      optional uint32 max_per_24_h = 4;
-
-      // A value between 0 and 1 which encodes the probability of skipping a
-      // trigger with this name. This is useful for reducing the probability
-      // of high-frequency triggers from dominating trace finaization. If this
-      // field is unset or zero, the trigger will *never* be skipped. If this
-      // field is greater than or equal to 1, this trigger will *always* be
-      // skipped i.e. it will be as if this trigger was never included in the
-      // first place.
-      // This probability check is applied *before* any other limits. For
-      // example, if |max_per_24_h| is also set, first we will check if the
-      // probability bar is met and only then will we check the |max_per_24_h|
-      // limit.
-      optional double skip_probability = 5;
     }
     // A list of triggers which are related to this configuration. If ANY
     // trigger is seen then an action will be performed based on |trigger_mode|.
@@ -368,66 +321,25 @@
   }
   optional CompressionType compression_type = 24;
 
-  // Android-only. Not for general use. If set, saves the trace into an
-  // incident. This field is read by perfetto_cmd, rather than the tracing
-  // service. This field must be set when passing the --upload flag to
-  // perfetto_cmd.
+  // Android-only. Debug builds only. Not for general use. If set, saves a
+  // Dropbox trace into an incident. This field is read by perfetto_cmd, rather
+  // than the tracing service. All fields are mandatory.
   message IncidentReportConfig {
-    // In this message, either:
-    //  * all of |destination_package|, |destination_class| and |privacy_level|
-    //    must be set.
-    //  * |skip_incidentd| must be explicitly set to true.
-
     optional string destination_package = 1;
     optional string destination_class = 2;
     // Level of filtering in the requested incident. See |Destination| in
     // frameworks/base/core/proto/android/privacy.proto.
     optional int32 privacy_level = 3;
-
-    // If true, then skips saving the trace to incidentd.
-    //
-    // This flag is useful in testing (e.g. Perfetto-statsd integration tests)
-    // or when we explicitly don't want traces to go to incidentd even when they
-    // usually would (e.g. configs deployed using statsd but only used for
-    // inclusion in bugreports using |bugreport_score|).
-    //
-    // The motivation for having this flag, instead of just not setting
-    // |incident_report_config|, is prevent accidents where
-    // |incident_report_config| is omitted by mistake.
-    optional bool skip_incidentd = 5;
-
     // If true, do not write the trace into dropbox (i.e. incident only).
     // Otherwise, write to both dropbox and incident.
-    // TODO(lalitm): remove this field as we no longer use Dropbox.
-    optional bool skip_dropbox = 4 [deprecated = true];
+    optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
 
-  enum StatsdLogging {
-    STATSD_LOGGING_UNSPECIFIED = 0;
-    STATSD_LOGGING_ENABLED = 1;
-    STATSD_LOGGING_DISABLED = 2;
-  }
-
-  // Android-only. Not for general use. If specified, sets the logging to statsd
-  // of guardrails and checkpoints in the tracing service. perfetto_cmd sets
-  // this to enabled (if not explicitly set in the config) when specifying
-  // --upload.
-  optional StatsdLogging statsd_logging = 31;
-
   // DEPRECATED. Was trace_uuid, use trace_uuid_msb and trace_uuid_lsb instead.
   reserved 26;
   // An identifier clients can use to tie this trace to other logging.
   // Alternative encoding of trace_uuid as two int64s.
   optional int64 trace_uuid_msb = 27;
   optional int64 trace_uuid_lsb = 28;
-
-  // When set applies a post-filter to the trace contents using the filter
-  // provided. The filter is applied at ReadBuffers() time and works both in the
-  // case of IPC readback and write_into_file. This filter can be generated
-  // using `tools/proto_filter -s schema.proto -F filter_out.bytes` or
-  // `-T filter_out.escaped_string` (for .pbtx).
-  // Introduced in Android S. See go/trace-filtering for design.
-  message TraceFilter { optional bytes bytecode = 1; }
-  optional TraceFilter trace_filter = 32;
 }
diff --git a/protos/perfetto/config/track_event/track_event_config.proto b/protos/perfetto/config/track_event/track_event_config.proto
index 5f4160e..6ae1f8f 100644
--- a/protos/perfetto/config/track_event/track_event_config.proto
+++ b/protos/perfetto/config/track_event/track_event_config.proto
@@ -52,16 +52,8 @@
   //       disabled_tags = ["*"]
   //       enabled_tags = ["my_tag"]
   //
-
-  // Default: []
-  repeated string disabled_categories = 1;
-
-  // Default: []
-  repeated string enabled_categories = 2;
-
-  // Default: [“slow”, “debug”]
-  repeated string disabled_tags = 3;
-
-  // Default: []
-  repeated string enabled_tags = 4;
+  repeated string disabled_categories = 1;  // Default: []
+  repeated string enabled_categories = 2;   // Default: []
+  repeated string disabled_tags = 3;  // Default: [“slow”, “debug”]
+  repeated string enabled_tags = 4;   // Default: []
 }
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index 49c077e..3388b7d 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -27,7 +27,7 @@
     "producer_port.proto",
   ]
   deps = [
-    # Deliberately :cpp and not :@TYPE@. In both cases (:gen and :cpp target)
+    # Deliberately :cpp and not :@TYPE@. In both cases (:gen and :cpp taraget)
     # we want to depend on the "cpp" variants. This is because the generated
     # .ipc.h depends on the .gen.h coming from the various common/xxx.proto.
     "../common:cpp",
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index 9f6d533..b8b929c 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -112,12 +112,6 @@
   // backward/forward compatibility and feature detection.
   rpc QueryCapabilities(QueryCapabilitiesRequest)
       returns (QueryCapabilitiesResponse) {}
-
-  // ----------------------------------------------------
-  // All methods below have been introduced in Android S.
-  // ----------------------------------------------------
-  rpc SaveTraceForBugreport(SaveTraceForBugreportRequest)
-      returns (SaveTraceForBugreportResponse) {}
 }
 
 // Arguments for rpc EnableTracing().
@@ -133,10 +127,6 @@
 
 message EnableTracingResponse {
   oneof state { bool disabled = 1; }
-
-  // If present and non-empty tracing was disabled because of an error.
-  // Introduced in Android S.
-  optional string error = 3;
 }
 
 // Arguments for rpc StartTracing().
@@ -252,18 +242,4 @@
 
 message QueryCapabilitiesResponse {
   optional TracingServiceCapabilities capabilities = 1;
-}
-
-// Arguments for rpc SaveTraceForBugreport.
-message SaveTraceForBugreportRequest {}
-
-// This response is sent only after the trace was saved into file (if succeeded)
-// or something failed.
-message SaveTraceForBugreportResponse {
-  // If true, an eligible the trace was saved into a known location (on Android
-  // /data/misc/perfetto-traces, see GetBugreportPath()).
-  // If false no trace with bugreport_score > 0 was found or an error occurred.
-  // see |msg| in that case for details about the failure.
-  optional bool success = 1;
-  optional string msg = 2;
-}
+}
\ No newline at end of file
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index 50b90e7..76eb0ef 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -152,16 +152,6 @@
   // SetupTracing response. See TracingService::ConnectProducer() and
   // |using_shmem_provided_by_producer| in InitializeConnectionResponse.
   optional bool producer_provided_shmem = 6;
-
-  // ---------------------------------------------------
-  // All fields below have been introduced in Android S.
-  // ---------------------------------------------------
-
-  // The version of the client library used by the producer.
-  // This is a human readable string with and its format varies depending on
-  // the build system that is used to build the code and the repo (standalone
-  // vs AOSP). This is intended for human debugging only.
-  optional string sdk_version = 8;
 }
 
 message InitializeConnectionResponse {
@@ -169,11 +159,6 @@
   // InitializeConnectionRequest (if any). If false, the shared memory buffer FD
   // will provided by the service via the SetupTracing async command.
   optional bool using_shmem_provided_by_producer = 1;
-
-  // Indicates to the producer that the service allows direct SMB patching of
-  // chunks that have not yet been committed to it.
-  // This field has been introduced in Android S.
-  optional bool direct_smb_patching_supported = 2;
 }
 
 // Arguments for rpc RegisterDataSource().
@@ -272,11 +257,9 @@
 
   message StopDataSource { optional uint64 instance_id = 1; }
 
-  // On Android/Linux/Mac this message also transports the file descriptor for
-  // the shared memory buffer (not a proto field).
-  message SetupTracing {
-    optional uint32 shared_buffer_page_size_kb = 1;
-  }
+  // This message also transports the file descriptor for the shared memory
+  // buffer (not a proto field).
+  message SetupTracing { optional uint32 shared_buffer_page_size_kb = 1; }
 
   message Flush {
     // The instance id (i.e. StartDataSource.new_instance_id) of the data
diff --git a/protos/perfetto/ipc/wire_protocol.proto b/protos/perfetto/ipc/wire_protocol.proto
index 038d4bb..c57b71b 100644
--- a/protos/perfetto/ipc/wire_protocol.proto
+++ b/protos/perfetto/ipc/wire_protocol.proto
@@ -35,14 +35,9 @@
 
   // Client -> Host.
   message InvokeMethod {
-    // BindServiceReply.id.
-    optional uint32 service_id = 1;
-
-    // BindServiceReply.method.id.
-    optional uint32 method_id = 2;
-
-    // Proto-encoded request argument.
-    optional bytes args_proto = 3;
+    optional uint32 service_id = 1;  // BindServiceReply.id.
+    optional uint32 method_id = 2;   // BindServiceReply.method.id.
+    optional bytes args_proto = 3;   // Proto-encoded request argument.
 
     // When true the client specifies that a reply is not needed. The use case
     // is a method with an empty, where the client doesn't care about the
@@ -54,12 +49,8 @@
   // Host -> Client.
   message InvokeMethodReply {
     optional bool success = 1;
-
-    // only for streaming RPCs.
-    optional bool has_more = 2;
-
-    // proto-encoded response value.
-    optional bytes reply_proto = 3;
+    optional bool has_more = 2;      // only for streaming RPCs.
+    optional bytes reply_proto = 3;  // proto-encoded response value.
   }
 
   // Host -> Client.
diff --git a/protos/perfetto/metrics/BUILD.gn b/protos/perfetto/metrics/BUILD.gn
index a0aec35..8a35ef1 100644
--- a/protos/perfetto/metrics/BUILD.gn
+++ b/protos/perfetto/metrics/BUILD.gn
@@ -16,23 +16,14 @@
 import("../../../gn/proto_library.gni")
 
 perfetto_proto_library("@TYPE@") {
-  proto_generators = [
-    "lite",
-    "source_set",
-  ]
   deps = [ "android:@TYPE@" ]
   sources = [ "metrics.proto" ]
 }
 
-perfetto_proto_library("custom_options_@TYPE@") {
-  proto_generators = [ "source_set" ]
-  sources = [ "custom_options.proto" ]
-  import_dirs = [ "${perfetto_protobuf_src_dir}" ]
-}
-
-perfetto_proto_library("descriptor") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "metrics.descriptor"
-  deps = [ "android:source_set" ]
-  sources = [ "metrics.proto" ]
+if (perfetto_build_standalone) {
+  perfetto_proto_library("descriptor") {
+    proto_generators = [ "descriptor" ]
+    generate_descriptor = "metrics.descriptor"
+    sources = [ "metrics.proto" ]
+  }
 }
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 5e45f9c..6a15c3d 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -15,22 +15,13 @@
 import("../../../../gn/proto_library.gni")
 
 perfetto_proto_library("@TYPE@") {
-  proto_generators = [
-    "lite",
-    "source_set",
-  ]
   sources = [
     "batt_metric.proto",
     "cpu_metric.proto",
     "display_metrics.proto",
-    "dma_heap_metric.proto",
-    "fastrpc_metric.proto",
-    "g2d_metric.proto",
-    "gpu_metric.proto",
-    "hwcomposer.proto",
+    "heap_profile_callsites.proto",
     "hwui_metric.proto",
     "ion_metric.proto",
-    "jank_metric.proto",
     "java_heap_histogram.proto",
     "java_heap_stats.proto",
     "lmk_metric.proto",
@@ -41,10 +32,9 @@
     "powrails_metric.proto",
     "process_metadata.proto",
     "startup_metric.proto",
-    "surfaceflinger.proto",
-    "sysui_cuj_metrics.proto",
     "task_names.proto",
     "thread_time_in_state_metric.proto",
+    "unmapped_java_symbols.proto",
     "unsymbolized_frames.proto",
   ]
 }
diff --git a/protos/perfetto/metrics/android/batt_metric.proto b/protos/perfetto/metrics/android/batt_metric.proto
index 015a2a8..33ade61 100644
--- a/protos/perfetto/metrics/android/batt_metric.proto
+++ b/protos/perfetto/metrics/android/batt_metric.proto
@@ -36,18 +36,6 @@
     optional int64 total_screen_doze_ns = 3;
     // Total time a wakelock was held
     optional int64 total_wakelock_ns = 4;
-    // Amount of time the device was suspended. Depends on the ftrace source
-    // "power/suspend_resume".
-    optional int64 sleep_ns = 5;
-    optional int64 sleep_screen_off_ns = 6;
-    optional int64 sleep_screen_on_ns = 7;
-    optional int64 sleep_screen_doze_ns = 8;
-  }
-
-  // Period of time during the trace that the device went to sleep completely.
-  message SuspendPeriod {
-    optional int64 timestamp_ns = 1;
-    optional int64 duration_ns = 2;
   }
 
   // Battery counters info for each ts of the trace. This should only be
@@ -55,6 +43,4 @@
   repeated BatteryCounters battery_counters = 1;
 
   optional BatteryAggregates battery_aggregates = 2;
-
-  repeated SuspendPeriod suspend_period = 3;
 }
diff --git a/protos/perfetto/metrics/android/display_metrics.proto b/protos/perfetto/metrics/android/display_metrics.proto
index 0c6f163..fc858ac 100644
--- a/protos/perfetto/metrics/android/display_metrics.proto
+++ b/protos/perfetto/metrics/android/display_metrics.proto
@@ -27,28 +27,4 @@
 
   // Stat reports whether there is any duplicate_frames tracked
   optional uint32 duplicate_frames_logged = 2;
-
-  // Stat that reports the number of dpu underrrun occurs count.
-  optional uint32 total_dpu_underrun_count = 3;
-
-
-  message RefreshRateStat {
-    // The refresh rate value (the number of frames per second)
-    optional uint32 refresh_rate_fps = 1;
-
-    // Calculate the number of refresh rate switches to this fps
-    optional uint32 count = 2;
-
-    // Calculate the total duration of refresh rate stays at this fps
-    optional double total_dur_ms = 3;
-
-    // Calculate the average duration of refresh rate stays at this fps
-    optional double avg_dur_ms = 4;
-  }
-
-  // Calculate the total number of refresh rate changes
-  optional uint32 refresh_rate_switches = 4;
-
-  // The statistics for each refresh rate value
-  repeated RefreshRateStat refresh_rate_stats = 5;
-}
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/android/dma_heap_metric.proto b/protos/perfetto/metrics/android/dma_heap_metric.proto
deleted file mode 100644
index c9f95c2..0000000
--- a/protos/perfetto/metrics/android/dma_heap_metric.proto
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-// dma-buf heap memory stats on Android.
-message AndroidDmaHeapMetric {
-    optional double avg_size_bytes = 1;
-    optional double min_size_bytes = 2;
-    optional double max_size_bytes = 3;
-
-    // Total allocation size.
-    // Essentially the sum of positive allocs.
-    optional double total_alloc_size_bytes = 4;
-}
diff --git a/protos/perfetto/metrics/android/fastrpc_metric.proto b/protos/perfetto/metrics/android/fastrpc_metric.proto
deleted file mode 100644
index 417acda..0000000
--- a/protos/perfetto/metrics/android/fastrpc_metric.proto
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-// fastrpc memory stats on Android.
-message AndroidFastrpcMetric {
-  message Subsystem {
-    optional string name = 1;
-    optional double avg_size_bytes = 2;
-    optional double min_size_bytes = 3;
-    optional double max_size_bytes = 4;
-
-    // Total allocation size.
-    // Essentially the sum of positive allocs.
-    optional double total_alloc_size_bytes = 5;
-  }
-
-  repeated Subsystem subsystem = 1;
-}
diff --git a/protos/perfetto/metrics/android/g2d_metric.proto b/protos/perfetto/metrics/android/g2d_metric.proto
deleted file mode 100644
index e7a2d6a..0000000
--- a/protos/perfetto/metrics/android/g2d_metric.proto
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-message G2dMetrics {
-  message G2dInstance {
-    // G2d name.
-    optional string name = 1;
-
-    optional int64 max_dur_ns = 2;
-    optional int64 min_dur_ns = 3;
-    optional int64 avg_dur_ns = 4;
-    optional uint32 frame_count = 5;
-    optional uint32 error_count = 6;
-  }
-  message G2dMetric {
-    // G2D Metric for each G2D Instance.
-    repeated G2dInstance instances = 1;
-
-    // max/min/avg G2d frame durations for all instances.
-    optional int64 max_dur_ns = 2;
-    optional int64 min_dur_ns = 3;
-    optional int64 avg_dur_ns = 4;
-
-    // the number of frames processed by G2D
-    optional uint32 frame_count = 5;
-    // the number of error events
-    optional uint32 error_count = 6;
-  }
-
-  optional G2dMetric g2d_hw = 1;
-  optional G2dMetric g2d_sw = 2;
-}
diff --git a/protos/perfetto/metrics/android/gpu_metric.proto b/protos/perfetto/metrics/android/gpu_metric.proto
deleted file mode 100644
index 2365855..0000000
--- a/protos/perfetto/metrics/android/gpu_metric.proto
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message AndroidGpuMetric {
-  message Process {
-    // Process name.
-    optional string name = 1;
-
-    // max/min/avg GPU memory used by this process.
-    optional int64 mem_max = 2;
-    optional int64 mem_min = 3;
-    optional int64 mem_avg = 4;
-  }
-
-  // GPU metric for processes using GPU.
-  repeated Process processes = 1;
-
-  // max/min/avg GPU memory used by the entire system.
-  optional int64 mem_max = 2;
-  optional int64 mem_min = 3;
-  optional int64 mem_avg = 4;
-}
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
new file mode 100644
index 0000000..af88c6e
--- /dev/null
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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";
+
+package perfetto.protos;
+
+import "protos/perfetto/metrics/android/process_metadata.proto";
+
+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: 7
+  message InstanceStats {
+    optional uint32 pid = 1;
+    // TODO(ilkos): Remove process_name in favour of the metadata.
+    optional string process_name = 2;
+    optional AndroidProcessMetadata process = 6;
+    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/hwcomposer.proto b/protos/perfetto/metrics/android/hwcomposer.proto
deleted file mode 100644
index 72edc6d..0000000
--- a/protos/perfetto/metrics/android/hwcomposer.proto
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-message AndroidHwcomposerMetrics {
-  // Counts the number of composition total layers in the trace. (non-weighted average)
-  optional double composition_total_layers = 1;
-
-  // Counts the number of composition dpu layers in the trace. (non-weighted average)
-  optional double composition_dpu_layers = 2;
-
-  // Counts the number of composition gpu layers in the trace. (non-weighted average)
-  optional double composition_gpu_layers = 3;
-
-  // Counts the number of composition dpu cached layers in the trace. (non-weighted average)
-  optional double composition_dpu_cached_layers = 4;
-
-  // Counts the number of composition surfaceflinger cached layers in the trace.
-  // (non-weighted average)
-  optional double composition_sf_cached_layers = 5;
-
-  // Counts how many times validateDisplay is skipped.
-  optional int32 skipped_validation_count = 6;
-
-  // Counts how many times validateDisplay cannot be skipped.
-  optional int32 unskipped_validation_count = 7;
-
-  // Counts how many times validateDisplay is already separated from presentDisplay
-  // since the beginning.
-  optional int32 separated_validation_count = 8;
-
-  // Counts how many unhandled validation cases which might be caused by errors.
-  optional int32 unknown_validation_count = 9;
-
-  // the average of overall hwcomposer execution time.
-  optional double avg_all_execution_time_ms = 10;
-
-  // the average of hwcomposer execution time for skipped validation cases.
-  optional double avg_skipped_execution_time_ms = 11;
-
-  // the average of hwcomposer execution time for unskipped validation cases.
-  optional double avg_unskipped_execution_time_ms = 12;
-
-  // the average of hwcomposer execution time for separated validation cases.
-  optional double avg_separated_execution_time_ms = 13;
-}
diff --git a/protos/perfetto/metrics/android/jank_metric.proto b/protos/perfetto/metrics/android/jank_metric.proto
deleted file mode 100644
index 9708adf..0000000
--- a/protos/perfetto/metrics/android/jank_metric.proto
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message AndroidJankMetrics {
-  repeated Warning warnings = 1;
-
-  message Warning {
-    optional int64 ts = 1;
-    optional int64 dur = 2;
-
-    optional string process_name = 3;
-    optional string warning_text = 4;
-  }
-}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/android/java_heap_histogram.proto b/protos/perfetto/metrics/android/java_heap_histogram.proto
index ce23669..f0680a0 100644
--- a/protos/perfetto/metrics/android/java_heap_histogram.proto
+++ b/protos/perfetto/metrics/android/java_heap_histogram.proto
@@ -19,11 +19,8 @@
 import "protos/perfetto/metrics/android/process_metadata.proto";
 
 message JavaHeapHistogram {
-  // Next id: 5
   message TypeCount {
     optional string type_name = 1;
-    optional string category = 4;
-
     optional uint32 obj_count = 2;
     optional uint32 reachable_obj_count = 3;
   }
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index 54bf1d7..ce7e9e3 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -31,13 +31,6 @@
     optional int64 interruptible_sleep_dur_ns = 4;
   }
 
-  message McyclesByCoreType {
-    optional int64 little = 1;
-    optional int64 big = 2;
-    optional int64 bigger = 3;
-    optional int64 unknown = 4;
-  }
-
   message Slice {
     optional int64 dur_ns = 1;
     optional double dur_ms = 2;
@@ -45,20 +38,12 @@
 
   // Timing information spanning the intent received by the
   // activity manager to the first frame drawn.
-  // Next id: 31.
+  // Next id: 21.
   message ToFirstFrame {
-    // The duration between the intent received and first frame.
     optional int64 dur_ns = 1;
     optional double dur_ms = 17;
-
-    // Breakdown of time to first frame by task state for the main thread of
-    // the process starting up.
     optional TaskStateBreakdown main_thread_by_task_state = 2;
 
-    // The mcycles taken by this startup across all CPUs (broken down by core
-    // type).
-    optional McyclesByCoreType mcycles_by_core_type = 26;
-
     // In this timespan, how many processes (apart from the main activity) were
     // spawned.
     optional uint32 other_processes_spawned_count = 3;
@@ -72,10 +57,7 @@
     optional Slice time_bind_application = 6;
     optional Slice time_activity_start = 7;
     optional Slice time_activity_resume = 8;
-    optional Slice time_activity_restart = 21;
     optional Slice time_choreographer = 9;
-    optional Slice time_inflate = 22;
-    optional Slice time_get_resources = 23;
 
     // If we are starting a new process, record the duration from the
     // intent being received to the time we call the zygote.
@@ -90,20 +72,6 @@
 
     optional Slice time_post_fork = 16;
 
-    // The total time spent on opening dex files.
-    optional Slice time_dex_open = 24;
-    // Total time spent verifying classes during app startup.
-    optional Slice time_verify_class = 25;
-
-    // Number of methods that were compiled by JIT during app startup.
-    optional uint32 jit_compiled_methods = 27;
-
-    // Time spent running CPU on jit thread pool.
-    optional Slice time_jit_thread_pool_on_cpu = 28;
-
-    // Time spent on garbage collection.
-    optional Slice time_gc_total = 29;
-    optional Slice time_gc_on_cpu = 30;
     // Deprecated was other_process_to_activity_cpu_ratio
     reserved 12;
 
@@ -119,40 +87,7 @@
     optional Slice full_startup = 1;
   }
 
-  message Activity {
-    optional string name = 1;
-    optional string method = 2;
-    optional int64 ts_method_start = 4;
-
-    // Field 3 contained Slice with a sum of durations for matching slices.
-    reserved 3;
-  }
-
-  message BinderTransaction {
-    optional Slice duration = 1;
-    optional string thread = 2;
-  }
-
-  // Metrics with information about the status of odex files and the outcome
-  // of the loading process.
-  // Multiple files might be loaded for a single startup. Platform might also
-  // decide to discard an odex file and instead load a fallback, for example
-  // in case the OS or apk were updated.
-  message OptimizationStatus {
-    optional string odex_status = 1;
-    optional string compilation_filter = 2;
-    optional string compilation_reason = 3;
-    optional string location = 4;
-  }
-
-  // Contains timestamps of important events which occurred during the
-  // startup.
-  message EventTimestamps {
-    optional int64 intent_received = 1;
-    optional int64 first_frame = 2;
-  }
-
-  // Next id: 15
+  // Next id: 8
   message Startup {
     // Random id uniquely identifying an app startup in this trace.
     optional uint32 startup_id = 1;
@@ -163,13 +98,6 @@
     // Name of the process launched
     optional string process_name = 3;
 
-    // Details about the activities launched
-    repeated Activity activities = 11;
-
-    // Details about slow binder transactions during the startup. The definition
-    // of a slow transaction is an implementation detail.
-    repeated BinderTransaction long_binder_transactions = 14;
-
     // Did we ask the zygote for a new process
     optional bool zygote_new_process = 4;
 
@@ -179,30 +107,12 @@
     // it.
     optional uint32 activity_hosting_process_count = 6;
 
-    // Contains timestamps of important events which happened during
-    // the startup.
-    optional EventTimestamps event_timestamps = 13;
-
-    // Timing information spanning the intent received by the
-    // activity manager to the first frame drawn.
     optional ToFirstFrame to_first_frame = 5;
 
     // Details about the process (uid, version, etc)
     optional AndroidProcessMetadata process = 7;
 
-    // Metrics about startup which were developed by looking at experiments
-    // using high-speed cameras (HSC).
     optional HscMetrics hsc = 8;
-
-    // The time taken in the startup from intent recieved to the start time
-    // of the reportFullyDrawn slice. This should be longer than the time to
-    // first frame as the application decides this after it starts rendering.
-    optional Slice report_fully_drawn = 9;
-
-    // Conntains information about the status of odex files.
-    repeated OptimizationStatus optimization_status = 12;
-
-    reserved 10;
   }
 
   repeated Startup startup = 1;
diff --git a/protos/perfetto/metrics/android/surfaceflinger.proto b/protos/perfetto/metrics/android/surfaceflinger.proto
deleted file mode 100644
index 76fb493..0000000
--- a/protos/perfetto/metrics/android/surfaceflinger.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message AndroidSurfaceflingerMetric {
-  // Counts the number of missed frames in the trace.
-  optional uint32 missed_frames = 1;
-
-  // Counts the number of missed HWC frames in the trace.
-  optional uint32 missed_hwc_frames = 2;
-
-  // Counts the number of missed GPU frames in the trace.
-  optional uint32 missed_gpu_frames = 3;
-
-  // Calculate the number of missed frames divided by
-  // total frames
-  optional double missed_frame_rate = 4;
-
-  // Calculate the number of missed HWC frames divided by
-  // total HWC frames
-  optional double missed_hwc_frame_rate = 5;
-
-  // Calculate the number of missed GPU frames divided by
-  // total GPU frames
-  optional double missed_gpu_frame_rate = 6;
-}
diff --git a/protos/perfetto/metrics/android/sysui_cuj_metrics.proto b/protos/perfetto/metrics/android/sysui_cuj_metrics.proto
deleted file mode 100644
index 41708ce..0000000
--- a/protos/perfetto/metrics/android/sysui_cuj_metrics.proto
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/android/process_metadata.proto";
-
-// Metric that stores frame information and potential jank root causes
-// for a single Android system UI interaction/user journey.
-message AndroidSysUiCujMetrics {
-  // A list of all frames within the SysUi user journey.
-  repeated Frame frames = 1;
-
-  optional string cuj_name = 2;
-  optional int64 cuj_start = 3;
-  optional int64 cuj_dur = 4;
-
-  // Details about the process (uid, version, etc)
-  optional AndroidProcessMetadata process = 5;
-
-  message Frame {
-    // Index of the frame within the single user journey.
-    optional int64 number = 1;
-    optional int64 vsync = 5;
-    optional int64 ts = 2;
-    optional int64 dur = 3;
-
-    // A list of identified potential causes for jank.
-    // Optional.
-    repeated string jank_cause = 4;
-  }
-}
diff --git a/protos/perfetto/metrics/android/thread_time_in_state_metric.proto b/protos/perfetto/metrics/android/thread_time_in_state_metric.proto
index f664d29..ba81d83 100644
--- a/protos/perfetto/metrics/android/thread_time_in_state_metric.proto
+++ b/protos/perfetto/metrics/android/thread_time_in_state_metric.proto
@@ -22,14 +22,8 @@
 
 message AndroidThreadTimeInStateMetric {
   message MetricsByCoreType {
-    optional int32 time_in_state_cpu = 5;
     optional string core_type = 1;
-
     optional int64 runtime_ms = 2;
-    // CPU megacycles (i.e. cycles divided by 1e6).
-    optional int64 mcycles = 3;
-    // Power cost as predicted by the power profile.
-    optional double power_profile_mah = 4;
   }
 
   message Thread {
diff --git a/protos/perfetto/metrics/android/unmapped_java_symbols.proto b/protos/perfetto/metrics/android/unmapped_java_symbols.proto
new file mode 100644
index 0000000..b14cb5d
--- /dev/null
+++ b/protos/perfetto/metrics/android/unmapped_java_symbols.proto
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+import "protos/perfetto/metrics/android/process_metadata.proto";
+
+message UnmappedJavaSymbols {
+  message Field {
+    optional string field_name = 1;
+    optional string field_type_name = 2;
+  }
+
+  message ProcessSymbols {
+    reserved 3;
+
+    optional AndroidProcessMetadata process_metadata = 1;
+    repeated string type_name = 2;
+    repeated Field field = 4;
+  }
+
+  repeated ProcessSymbols process_symbols = 1;
+}
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
deleted file mode 100644
index 0789138..0000000
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  proto_generators = [ "source_set" ]
-  deps = [
-    "..:@TYPE@",
-    "..:custom_options_@TYPE@",
-  ]
-  sources = [
-    "all_chrome_metrics.proto",
-    "blink_gc_metric.proto",
-    "frame_times.proto",
-    "media_metric.proto",
-    "reported_by_page.proto",
-    "scroll_jank.proto",
-    "test_chrome_metric.proto",
-  ]
-}
-
-perfetto_proto_library("descriptor") {
-  proto_generators = [ "descriptor" ]
-  import_dirs = [ "${perfetto_protobuf_src_dir}" ]
-  generate_descriptor = "all_chrome_metrics.descriptor"
-  deps = [ ":source_set" ]
-  sources = [ "all_chrome_metrics.proto" ]
-}
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
deleted file mode 100644
index eb52099..0000000
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/metrics.proto";
-import "protos/perfetto/metrics/chrome/blink_gc_metric.proto";
-import "protos/perfetto/metrics/chrome/frame_times.proto";
-import "protos/perfetto/metrics/chrome/media_metric.proto";
-import "protos/perfetto/metrics/chrome/scroll_jank.proto";
-import "protos/perfetto/metrics/chrome/test_chrome_metric.proto";
-import "protos/perfetto/metrics/chrome/reported_by_page.proto";
-
-extend TraceMetrics {
-  optional TestChromeMetric test_chrome_metric = 1001;
-  optional FrameTimes frame_times = 1002;
-  optional ReportedByPage reported_by_page = 1003;
-  optional ScrollJank scroll_jank = 1004;
-  optional BlinkGcMetric blink_gc_metric = 1005;
-  optional MediaMetric media_metric = 1006;
-}
diff --git a/protos/perfetto/metrics/chrome/blink_gc_metric.proto b/protos/perfetto/metrics/chrome/blink_gc_metric.proto
deleted file mode 100644
index 5a367a7..0000000
--- a/protos/perfetto/metrics/chrome/blink_gc_metric.proto
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http_//www.apache.org/licenses/LICENSE_2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-message BlinkGcMetric {
-  repeated double blink_gc_atomic_pause_mark_epilogue = 1
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_atomic_mark_epilogue = 2
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_atomic_pause_mark_prologue = 3
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_atomic_mark_prologue = 4
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_atomic_pause_mark_roots = 5
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_atomic_mark_roots = 6
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_atomic_pause_sweep_and_compact = 7
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_atomic_sweep_compact = 8
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_complete_sweep = 9 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_sweep_complete = 10
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_incremental_start = 11
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_incremental_mark_start = 12
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_incremental_step = 13
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_incremental_mark_step = 14
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_sweep_allocation = 15
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_sweep_on_allocation = 16
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_sweep_task_foreground = 17
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_sweep_idle = 18
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_unified_marking_by_v8 = 19
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double unified_gc_main_thread_cycle_full_mark_step = 20
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_atomic_pause = 21 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_atomic = 22
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_atomic_pause_mark_transitive_closure = 23
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double
-      blink_gc_main_thread_cycle_full_atomic_mark_transitive_closure = 24
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_total = 25 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full = 26
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_mark_roots = 27 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_mark_roots = 28
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_mark_transitive_closure = 29
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_mark_transitive_closure = 30
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_mark_foreground = 31 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_mark = 32
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_mark_foreground_forced = 33
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_mark_forced = 34
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_mark_background = 35 [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_concurrent_thread_cycle_full_mark = 36
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_sweep_foreground = 37
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_main_thread_cycle_full_sweep = 38
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_sweep_background = 39
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double blink_gc_concurrent_thread_cycle_full_sweep = 40
-      [(unit) = "ms_smallerIsBetter"];
-  repeated double unified_gc_total = 41 [(unit) = "ms_smallerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/chrome/frame_times.proto b/protos/perfetto/metrics/chrome/frame_times.proto
deleted file mode 100644
index 5206a1c..0000000
--- a/protos/perfetto/metrics/chrome/frame_times.proto
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-message FrameTimes {
-  repeated double frame_time = 1 [(unit) = "ms_smallerIsBetter"];
-  repeated double exp_frame_time = 2 [(unit) = "ms_smallerIsBetter"];
-  optional double avg_surface_fps = 3 [(unit) = "unitless_biggerIsBetter"];
-  optional double exp_avg_surface_fps = 4 [(unit) = "unitless_biggerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/chrome/media_metric.proto b/protos/perfetto/metrics/chrome/media_metric.proto
deleted file mode 100644
index e3d9baf..0000000
--- a/protos/perfetto/metrics/chrome/media_metric.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-// Ported from catapult's media_metric.html.
-message MediaMetric {
-  repeated double time_to_video_play = 1 [(unit) = "ms_smallerIsBetter"];
-  repeated double time_to_audio_play = 2 [(unit) = "ms_smallerIsBetter"];
-  repeated int64 dropped_frame_count = 3 [(unit) = "count_smallerIsBetter"];
-  repeated double buffering_time = 4 [(unit) = "ms_smallerIsBetter"];
-  repeated double roughness = 5 [(unit) = "count_smallerIsBetter"];
-  repeated double freezing = 6 [(unit) = "ms_smallerIsBetter"];
-
-  // These have multiple dynamic histogram names in the TBMv2 version. Because
-  // TBMv3 doesn't support dynamic names, we report one value per seek into each
-  // of these two combined histograms.
-  repeated double seek_time = 8 [(unit) = "ms_smallerIsBetter"];
-  repeated double pipeline_seek_time = 9 [(unit) = "ms_smallerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/chrome/reported_by_page.proto b/protos/perfetto/metrics/chrome/reported_by_page.proto
deleted file mode 100644
index c9870e9..0000000
--- a/protos/perfetto/metrics/chrome/reported_by_page.proto
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-message ReportedByPage {
-  // Time from navigation start to telemetry:reported_by_page:viewable.
-  repeated double time_to_viewable = 1 [(unit) = "ms_smallerIsBetter"];
-  // Time from navigation start to telemetry:reported_by_page:interactive.
-  repeated double time_to_interactive = 2 [(unit) = "ms_smallerIsBetter"];
-  // Time from telemetry:reported_by_page:benchmark_begin to
-  // telemetry:reported_by_page:benchmark_end.
-  repeated double benchmark_time = 3 [(unit) = "ms_smallerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/chrome/scroll_jank.proto b/protos/perfetto/metrics/chrome/scroll_jank.proto
deleted file mode 100644
index 6fea1d8..0000000
--- a/protos/perfetto/metrics/chrome/scroll_jank.proto
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-message ScrollJank {
-  // The percentage of time we consider janky of the total time spent scrolling
-  // during the trace. I.E. approximately equal to |scroll_jank_ms|/|scroll_ms|.
-  optional double scroll_jank_percentage = 1 [(unit) = "n%_smallerIsBetter"];
-  optional double scroll_ms = 2 [(unit) = "ms_biggerIsBetter"];
-  optional double scroll_processing_ms = 3 [(unit) = "ms_biggerIsBetter"];
-  optional double scroll_jank_processing_ms = 4 [(unit) = "ms_smallerIsBetter"];
-  optional int64 num_scroll_update_count = 5 [(unit) = "count_biggerIsBetter"];
-  optional int64 num_scroll_update_jank_count = 6
-      [(unit) = "count_smallerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/chrome/test_chrome_metric.proto b/protos/perfetto/metrics/chrome/test_chrome_metric.proto
deleted file mode 100644
index 3ae3240..0000000
--- a/protos/perfetto/metrics/chrome/test_chrome_metric.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/custom_options.proto";
-
-message TestChromeMetric {
-  optional int64 test_value = 1 [(unit) = "count_smallerIsBetter"];
-}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 164377f..39d8ee3 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -20,33 +20,33 @@
 
 import "protos/perfetto/metrics/android/batt_metric.proto";
 import "protos/perfetto/metrics/android/cpu_metric.proto";
-import "protos/perfetto/metrics/android/display_metrics.proto";
-import "protos/perfetto/metrics/android/dma_heap_metric.proto";
-import "protos/perfetto/metrics/android/fastrpc_metric.proto";
-import "protos/perfetto/metrics/android/g2d_metric.proto";
-import "protos/perfetto/metrics/android/gpu_metric.proto";
-import "protos/perfetto/metrics/android/hwcomposer.proto";
-import "protos/perfetto/metrics/android/hwui_metric.proto";
-import "protos/perfetto/metrics/android/ion_metric.proto";
-import "protos/perfetto/metrics/android/jank_metric.proto";
-import "protos/perfetto/metrics/android/java_heap_histogram.proto";
-import "protos/perfetto/metrics/android/java_heap_stats.proto";
-import "protos/perfetto/metrics/android/lmk_metric.proto";
-import "protos/perfetto/metrics/android/lmk_reason_metric.proto";
 import "protos/perfetto/metrics/android/mem_metric.proto";
 import "protos/perfetto/metrics/android/mem_unagg_metric.proto";
-import "protos/perfetto/metrics/android/package_list.proto";
+import "protos/perfetto/metrics/android/ion_metric.proto";
+import "protos/perfetto/metrics/android/lmk_metric.proto";
+import "protos/perfetto/metrics/android/lmk_reason_metric.proto";
 import "protos/perfetto/metrics/android/powrails_metric.proto";
 import "protos/perfetto/metrics/android/startup_metric.proto";
-import "protos/perfetto/metrics/android/surfaceflinger.proto";
-import "protos/perfetto/metrics/android/sysui_cuj_metrics.proto";
+import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
+import "protos/perfetto/metrics/android/hwui_metric.proto";
+import "protos/perfetto/metrics/android/package_list.proto";
+import "protos/perfetto/metrics/android/unmapped_java_symbols.proto";
+import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
+import "protos/perfetto/metrics/android/java_heap_histogram.proto";
+import "protos/perfetto/metrics/android/java_heap_stats.proto";
+import "protos/perfetto/metrics/android/display_metrics.proto";
 import "protos/perfetto/metrics/android/task_names.proto";
 import "protos/perfetto/metrics/android/thread_time_in_state_metric.proto";
-import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
 
 // Trace processor metadata
 message TraceMetadata {
-  reserved 1;
+  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;
   optional string android_build_fingerprint = 4;
@@ -54,43 +54,13 @@
   optional int64 trace_size_bytes = 6;
   repeated string trace_trigger = 7;
   optional string unique_session_name = 8;
-  optional string trace_config_pbtxt = 9;
-  optional int64 sched_duration_ns = 10;
-}
-
-// Stats counters for the trace.
-// Defined in src/trace_processor/storage/stats.h
-message TraceAnalysisStats {
-  enum Severity {
-    SEVERITY_UNKNOWN = 0;
-    SEVERITY_INFO = 1;
-    SEVERITY_DATA_LOSS = 2;
-    SEVERITY_ERROR = 3;
-  }
-
-  enum Source {
-    SOURCE_UNKNOWN = 0;
-    SOURCE_TRACE = 1;
-    SOURCE_ANALYSIS = 2;
-  }
-
-  message Stat {
-    optional string name = 1;
-    optional uint32 idx = 2;
-    optional Severity severity = 3;
-    optional Source source = 4;
-
-    optional int64 count = 5;
-  }
-
-  repeated Stat stat = 1;
 }
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 34
+// Next id: 25
 message TraceMetrics {
-  reserved 4, 10, 13, 14, 16, 19;
+  reserved 4, 10, 13, 14;
 
   // Battery counters metric on Android.
   optional AndroidBatteryMetric android_batt = 5;
@@ -113,9 +83,6 @@
   // ion buffer memory metrics.
   optional AndroidIonMetric android_ion = 9;
 
-  // fastrpc subsystem memory metrics.
-  optional AndroidFastrpcMetric android_fastrpc = 31;
-
   // Statistics about low memory kills.
   optional AndroidLmkMetric android_lmk = 8;
 
@@ -125,12 +92,12 @@
   // 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;
 
-  // Trace stats (applicable to all traces).
-  optional TraceAnalysisStats trace_stats = 33;
-
   // Returns stack frames missing symbols.
   optional UnsymbolizedFrames unsymbolized_frames = 15;
 
@@ -143,6 +110,9 @@
   // Metrics used to find potential culprits of low-memory kills.
   optional AndroidLmkReasonMetric android_lmk_reason = 18;
 
+  // Java type names that have no deobfuscation mappings.
+  optional UnmappedJavaSymbols unmapped_java_symbols = 19;
+
   optional AndroidHwuiMetric android_hwui_metric = 20;
 
   optional AndroidDisplayMetrics display_metrics = 22;
@@ -151,33 +121,9 @@
 
   optional AndroidThreadTimeInStateMetric android_thread_time_in_state = 24;
 
-  // Metric associated with surfaceflinger.
-  optional AndroidSurfaceflingerMetric android_surfaceflinger = 25;
-
-  // GPU metrics on Android.
-  optional AndroidGpuMetric android_gpu = 26;
-
-  // Frame timing and jank root causes for system UI interactions.
-  optional AndroidSysUiCujMetrics android_sysui_cuj = 27;
-
-  // Metric associated with hwcomposer.
-  optional AndroidHwcomposerMetrics android_hwcomposer = 28;
-
-  // Detects common bad patterns that might lead to jank.
-  optional AndroidJankMetrics android_jank = 29;
-
-  // G2D metrics.
-  optional G2dMetrics g2d = 30;
-
-  // Dmabuf heap metrics.
-  optional AndroidDmaHeapMetric android_dma_heap = 32;
-
   // Demo extensions.
   extensions 450 to 499;
 
   // Vendor extensions.
   extensions 500 to 1000;
-
-  // Chrome metrics.
-  extensions 1001 to 2000;
 }
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index dc2196e..a06907c 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -31,18 +31,6 @@
     optional int64 total_screen_doze_ns = 3;
     // Total time a wakelock was held
     optional int64 total_wakelock_ns = 4;
-    // Amount of time the device was suspended. Depends on the ftrace source
-    // "power/suspend_resume".
-    optional int64 sleep_ns = 5;
-    optional int64 sleep_screen_off_ns = 6;
-    optional int64 sleep_screen_on_ns = 7;
-    optional int64 sleep_screen_doze_ns = 8;
-  }
-
-  // Period of time during the trace that the device went to sleep completely.
-  message SuspendPeriod {
-    optional int64 timestamp_ns = 1;
-    optional int64 duration_ns = 2;
   }
 
   // Battery counters info for each ts of the trace. This should only be
@@ -50,8 +38,6 @@
   repeated BatteryCounters battery_counters = 1;
 
   optional BatteryAggregates battery_aggregates = 2;
-
-  repeated SuspendPeriod suspend_period = 3;
 }
 
 // End of protos/perfetto/metrics/android/batt_metric.proto
@@ -130,173 +116,96 @@
 
   // Stat reports whether there is any duplicate_frames tracked
   optional uint32 duplicate_frames_logged = 2;
-
-  // Stat that reports the number of dpu underrrun occurs count.
-  optional uint32 total_dpu_underrun_count = 3;
-
-
-  message RefreshRateStat {
-    // The refresh rate value (the number of frames per second)
-    optional uint32 refresh_rate_fps = 1;
-
-    // Calculate the number of refresh rate switches to this fps
-    optional uint32 count = 2;
-
-    // Calculate the total duration of refresh rate stays at this fps
-    optional double total_dur_ms = 3;
-
-    // Calculate the average duration of refresh rate stays at this fps
-    optional double avg_dur_ms = 4;
-  }
-
-  // Calculate the total number of refresh rate changes
-  optional uint32 refresh_rate_switches = 4;
-
-  // The statistics for each refresh rate value
-  repeated RefreshRateStat refresh_rate_stats = 5;
 }
-
 // End of protos/perfetto/metrics/android/display_metrics.proto
 
-// Begin of protos/perfetto/metrics/android/dma_heap_metric.proto
+// Begin of protos/perfetto/metrics/android/process_metadata.proto
 
-// dma-buf heap memory stats on Android.
-message AndroidDmaHeapMetric {
-    optional double avg_size_bytes = 1;
-    optional double min_size_bytes = 2;
-    optional double max_size_bytes = 3;
+message AndroidProcessMetadata {
+  // Process name. Usually, cmdline or <package_name>(:<custom_name>)?.
+  optional string name = 1;
 
-    // Total allocation size.
-    // Essentially the sum of positive allocs.
-    optional double total_alloc_size_bytes = 4;
+  // User id under which this process runs.
+  optional int64 uid = 2;
+
+  // Package metadata from Android package list.
+  message Package {
+    optional string package_name = 1;
+    optional int64 apk_version_code = 2;
+    optional bool debuggable = 3;
+  }
+
+  // Package that this process belongs to.
+  //
+  // If this process shares its uid (see `packages_for_uid` field), the package
+  // is determined based on the process name and package name. If there is no
+  // match this field is empty.
+  optional Package package = 7;
+
+  // All packages using this uid.
+  //
+  // Shared uid documentation:
+  // https://developer.android.com/guide/topics/manifest/manifest-element#uid
+  repeated Package packages_for_uid = 8;
+
+  reserved 3, 4, 5, 6;
 }
 
-// End of protos/perfetto/metrics/android/dma_heap_metric.proto
+// End of protos/perfetto/metrics/android/process_metadata.proto
 
-// Begin of protos/perfetto/metrics/android/fastrpc_metric.proto
+// Begin of protos/perfetto/metrics/android/heap_profile_callsites.proto
 
-// fastrpc memory stats on Android.
-message AndroidFastrpcMetric {
-  message Subsystem {
+message HeapProfileCallsites {
+  message Frame {
     optional string name = 1;
-    optional double avg_size_bytes = 2;
-    optional double min_size_bytes = 3;
-    optional double max_size_bytes = 4;
-
-    // Total allocation size.
-    // Essentially the sum of positive allocs.
-    optional double total_alloc_size_bytes = 5;
+    optional string mapping_name = 2;
   }
 
-  repeated Subsystem subsystem = 1;
-}
+  message Counters {
+    // Count of objects allocated
+    optional int64 total_count = 1;
+    // Count of bytes allocated
+    optional int64 total_bytes = 2;
 
-// End of protos/perfetto/metrics/android/fastrpc_metric.proto
-
-// Begin of protos/perfetto/metrics/android/g2d_metric.proto
-
-message G2dMetrics {
-  message G2dInstance {
-    // G2d name.
-    optional string name = 1;
-
-    optional int64 max_dur_ns = 2;
-    optional int64 min_dur_ns = 3;
-    optional int64 avg_dur_ns = 4;
-    optional uint32 frame_count = 5;
-    optional uint32 error_count = 6;
-  }
-  message G2dMetric {
-    // G2D Metric for each G2D Instance.
-    repeated G2dInstance instances = 1;
-
-    // max/min/avg G2d frame durations for all instances.
-    optional int64 max_dur_ns = 2;
-    optional int64 min_dur_ns = 3;
-    optional int64 avg_dur_ns = 4;
-
-    // the number of frames processed by G2D
-    optional uint32 frame_count = 5;
-    // the number of error events
-    optional uint32 error_count = 6;
+    // 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;
   }
 
-  optional G2dMetric g2d_hw = 1;
-  optional G2dMetric g2d_sw = 2;
-}
+  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;
 
-// End of protos/perfetto/metrics/android/g2d_metric.proto
+    // Leaf frame of the callsite. Use parent_hash to traverse to parent nodes.
+    optional Frame frame = 3;
 
-// Begin of protos/perfetto/metrics/android/gpu_metric.proto
-
-message AndroidGpuMetric {
-  message Process {
-    // Process name.
-    optional string name = 1;
-
-    // max/min/avg GPU memory used by this process.
-    optional int64 mem_max = 2;
-    optional int64 mem_min = 3;
-    optional int64 mem_avg = 4;
+    optional Counters self_allocs = 4;
+    optional Counters child_allocs = 5;
   }
 
-  // GPU metric for processes using GPU.
-  repeated Process processes = 1;
+  // Callsites per process instance.
+  // Next id: 7
+  message InstanceStats {
+    optional uint32 pid = 1;
+    // TODO(ilkos): Remove process_name in favour of the metadata.
+    optional string process_name = 2;
+    optional AndroidProcessMetadata process = 6;
+    repeated Callsite callsites = 3;
 
-  // max/min/avg GPU memory used by the entire system.
-  optional int64 mem_max = 2;
-  optional int64 mem_min = 3;
-  optional int64 mem_avg = 4;
+    // 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;
 }
 
-// End of protos/perfetto/metrics/android/gpu_metric.proto
-
-// Begin of protos/perfetto/metrics/android/hwcomposer.proto
-
-message AndroidHwcomposerMetrics {
-  // Counts the number of composition total layers in the trace. (non-weighted average)
-  optional double composition_total_layers = 1;
-
-  // Counts the number of composition dpu layers in the trace. (non-weighted average)
-  optional double composition_dpu_layers = 2;
-
-  // Counts the number of composition gpu layers in the trace. (non-weighted average)
-  optional double composition_gpu_layers = 3;
-
-  // Counts the number of composition dpu cached layers in the trace. (non-weighted average)
-  optional double composition_dpu_cached_layers = 4;
-
-  // Counts the number of composition surfaceflinger cached layers in the trace.
-  // (non-weighted average)
-  optional double composition_sf_cached_layers = 5;
-
-  // Counts how many times validateDisplay is skipped.
-  optional int32 skipped_validation_count = 6;
-
-  // Counts how many times validateDisplay cannot be skipped.
-  optional int32 unskipped_validation_count = 7;
-
-  // Counts how many times validateDisplay is already separated from presentDisplay
-  // since the beginning.
-  optional int32 separated_validation_count = 8;
-
-  // Counts how many unhandled validation cases which might be caused by errors.
-  optional int32 unknown_validation_count = 9;
-
-  // the average of overall hwcomposer execution time.
-  optional double avg_all_execution_time_ms = 10;
-
-  // the average of hwcomposer execution time for skipped validation cases.
-  optional double avg_skipped_execution_time_ms = 11;
-
-  // the average of hwcomposer execution time for unskipped validation cases.
-  optional double avg_unskipped_execution_time_ms = 12;
-
-  // the average of hwcomposer execution time for separated validation cases.
-  optional double avg_separated_execution_time_ms = 13;
-}
-
-// End of protos/perfetto/metrics/android/hwcomposer.proto
+// End of protos/perfetto/metrics/android/heap_profile_callsites.proto
 
 // Begin of protos/perfetto/metrics/android/hwui_metric.proto
 
@@ -406,63 +315,11 @@
 
 // End of protos/perfetto/metrics/android/ion_metric.proto
 
-// Begin of protos/perfetto/metrics/android/jank_metric.proto
-
-message AndroidJankMetrics {
-  repeated Warning warnings = 1;
-
-  message Warning {
-    optional int64 ts = 1;
-    optional int64 dur = 2;
-
-    optional string process_name = 3;
-    optional string warning_text = 4;
-  }
-}
-// End of protos/perfetto/metrics/android/jank_metric.proto
-
-// Begin of protos/perfetto/metrics/android/process_metadata.proto
-
-message AndroidProcessMetadata {
-  // Process name. Usually, cmdline or <package_name>(:<custom_name>)?.
-  optional string name = 1;
-
-  // User id under which this process runs.
-  optional int64 uid = 2;
-
-  // Package metadata from Android package list.
-  message Package {
-    optional string package_name = 1;
-    optional int64 apk_version_code = 2;
-    optional bool debuggable = 3;
-  }
-
-  // Package that this process belongs to.
-  //
-  // If this process shares its uid (see `packages_for_uid` field), the package
-  // is determined based on the process name and package name. If there is no
-  // match this field is empty.
-  optional Package package = 7;
-
-  // All packages using this uid.
-  //
-  // Shared uid documentation:
-  // https://developer.android.com/guide/topics/manifest/manifest-element#uid
-  repeated Package packages_for_uid = 8;
-
-  reserved 3, 4, 5, 6;
-}
-
-// End of protos/perfetto/metrics/android/process_metadata.proto
-
 // Begin of protos/perfetto/metrics/android/java_heap_histogram.proto
 
 message JavaHeapHistogram {
-  // Next id: 5
   message TypeCount {
     optional string type_name = 1;
-    optional string category = 4;
-
     optional uint32 obj_count = 2;
     optional uint32 reachable_obj_count = 3;
   }
@@ -696,13 +553,6 @@
     optional int64 interruptible_sleep_dur_ns = 4;
   }
 
-  message McyclesByCoreType {
-    optional int64 little = 1;
-    optional int64 big = 2;
-    optional int64 bigger = 3;
-    optional int64 unknown = 4;
-  }
-
   message Slice {
     optional int64 dur_ns = 1;
     optional double dur_ms = 2;
@@ -710,20 +560,12 @@
 
   // Timing information spanning the intent received by the
   // activity manager to the first frame drawn.
-  // Next id: 31.
+  // Next id: 21.
   message ToFirstFrame {
-    // The duration between the intent received and first frame.
     optional int64 dur_ns = 1;
     optional double dur_ms = 17;
-
-    // Breakdown of time to first frame by task state for the main thread of
-    // the process starting up.
     optional TaskStateBreakdown main_thread_by_task_state = 2;
 
-    // The mcycles taken by this startup across all CPUs (broken down by core
-    // type).
-    optional McyclesByCoreType mcycles_by_core_type = 26;
-
     // In this timespan, how many processes (apart from the main activity) were
     // spawned.
     optional uint32 other_processes_spawned_count = 3;
@@ -737,10 +579,7 @@
     optional Slice time_bind_application = 6;
     optional Slice time_activity_start = 7;
     optional Slice time_activity_resume = 8;
-    optional Slice time_activity_restart = 21;
     optional Slice time_choreographer = 9;
-    optional Slice time_inflate = 22;
-    optional Slice time_get_resources = 23;
 
     // If we are starting a new process, record the duration from the
     // intent being received to the time we call the zygote.
@@ -755,20 +594,6 @@
 
     optional Slice time_post_fork = 16;
 
-    // The total time spent on opening dex files.
-    optional Slice time_dex_open = 24;
-    // Total time spent verifying classes during app startup.
-    optional Slice time_verify_class = 25;
-
-    // Number of methods that were compiled by JIT during app startup.
-    optional uint32 jit_compiled_methods = 27;
-
-    // Time spent running CPU on jit thread pool.
-    optional Slice time_jit_thread_pool_on_cpu = 28;
-
-    // Time spent on garbage collection.
-    optional Slice time_gc_total = 29;
-    optional Slice time_gc_on_cpu = 30;
     // Deprecated was other_process_to_activity_cpu_ratio
     reserved 12;
 
@@ -784,40 +609,7 @@
     optional Slice full_startup = 1;
   }
 
-  message Activity {
-    optional string name = 1;
-    optional string method = 2;
-    optional int64 ts_method_start = 4;
-
-    // Field 3 contained Slice with a sum of durations for matching slices.
-    reserved 3;
-  }
-
-  message BinderTransaction {
-    optional Slice duration = 1;
-    optional string thread = 2;
-  }
-
-  // Metrics with information about the status of odex files and the outcome
-  // of the loading process.
-  // Multiple files might be loaded for a single startup. Platform might also
-  // decide to discard an odex file and instead load a fallback, for example
-  // in case the OS or apk were updated.
-  message OptimizationStatus {
-    optional string odex_status = 1;
-    optional string compilation_filter = 2;
-    optional string compilation_reason = 3;
-    optional string location = 4;
-  }
-
-  // Contains timestamps of important events which occurred during the
-  // startup.
-  message EventTimestamps {
-    optional int64 intent_received = 1;
-    optional int64 first_frame = 2;
-  }
-
-  // Next id: 15
+  // Next id: 8
   message Startup {
     // Random id uniquely identifying an app startup in this trace.
     optional uint32 startup_id = 1;
@@ -828,13 +620,6 @@
     // Name of the process launched
     optional string process_name = 3;
 
-    // Details about the activities launched
-    repeated Activity activities = 11;
-
-    // Details about slow binder transactions during the startup. The definition
-    // of a slow transaction is an implementation detail.
-    repeated BinderTransaction long_binder_transactions = 14;
-
     // Did we ask the zygote for a new process
     optional bool zygote_new_process = 4;
 
@@ -844,30 +629,12 @@
     // it.
     optional uint32 activity_hosting_process_count = 6;
 
-    // Contains timestamps of important events which happened during
-    // the startup.
-    optional EventTimestamps event_timestamps = 13;
-
-    // Timing information spanning the intent received by the
-    // activity manager to the first frame drawn.
     optional ToFirstFrame to_first_frame = 5;
 
     // Details about the process (uid, version, etc)
     optional AndroidProcessMetadata process = 7;
 
-    // Metrics about startup which were developed by looking at experiments
-    // using high-speed cameras (HSC).
     optional HscMetrics hsc = 8;
-
-    // The time taken in the startup from intent recieved to the start time
-    // of the reportFullyDrawn slice. This should be longer than the time to
-    // first frame as the application decides this after it starts rendering.
-    optional Slice report_fully_drawn = 9;
-
-    // Conntains information about the status of odex files.
-    repeated OptimizationStatus optimization_status = 12;
-
-    reserved 10;
   }
 
   repeated Startup startup = 1;
@@ -875,63 +642,6 @@
 
 // End of protos/perfetto/metrics/android/startup_metric.proto
 
-// Begin of protos/perfetto/metrics/android/surfaceflinger.proto
-
-message AndroidSurfaceflingerMetric {
-  // Counts the number of missed frames in the trace.
-  optional uint32 missed_frames = 1;
-
-  // Counts the number of missed HWC frames in the trace.
-  optional uint32 missed_hwc_frames = 2;
-
-  // Counts the number of missed GPU frames in the trace.
-  optional uint32 missed_gpu_frames = 3;
-
-  // Calculate the number of missed frames divided by
-  // total frames
-  optional double missed_frame_rate = 4;
-
-  // Calculate the number of missed HWC frames divided by
-  // total HWC frames
-  optional double missed_hwc_frame_rate = 5;
-
-  // Calculate the number of missed GPU frames divided by
-  // total GPU frames
-  optional double missed_gpu_frame_rate = 6;
-}
-
-// End of protos/perfetto/metrics/android/surfaceflinger.proto
-
-// Begin of protos/perfetto/metrics/android/sysui_cuj_metrics.proto
-
-// Metric that stores frame information and potential jank root causes
-// for a single Android system UI interaction/user journey.
-message AndroidSysUiCujMetrics {
-  // A list of all frames within the SysUi user journey.
-  repeated Frame frames = 1;
-
-  optional string cuj_name = 2;
-  optional int64 cuj_start = 3;
-  optional int64 cuj_dur = 4;
-
-  // Details about the process (uid, version, etc)
-  optional AndroidProcessMetadata process = 5;
-
-  message Frame {
-    // Index of the frame within the single user journey.
-    optional int64 number = 1;
-    optional int64 vsync = 5;
-    optional int64 ts = 2;
-    optional int64 dur = 3;
-
-    // A list of identified potential causes for jank.
-    // Optional.
-    repeated string jank_cause = 4;
-  }
-}
-
-// End of protos/perfetto/metrics/android/sysui_cuj_metrics.proto
-
 // Begin of protos/perfetto/metrics/android/task_names.proto
 
 message AndroidTaskNames {
@@ -960,14 +670,8 @@
 
 message AndroidThreadTimeInStateMetric {
   message MetricsByCoreType {
-    optional int32 time_in_state_cpu = 5;
     optional string core_type = 1;
-
     optional int64 runtime_ms = 2;
-    // CPU megacycles (i.e. cycles divided by 1e6).
-    optional int64 mcycles = 3;
-    // Power cost as predicted by the power profile.
-    optional double power_profile_mah = 4;
   }
 
   message Thread {
@@ -987,6 +691,27 @@
 
 // End of protos/perfetto/metrics/android/thread_time_in_state_metric.proto
 
+// Begin of protos/perfetto/metrics/android/unmapped_java_symbols.proto
+
+message UnmappedJavaSymbols {
+  message Field {
+    optional string field_name = 1;
+    optional string field_type_name = 2;
+  }
+
+  message ProcessSymbols {
+    reserved 3;
+
+    optional AndroidProcessMetadata process_metadata = 1;
+    repeated string type_name = 2;
+    repeated Field field = 4;
+  }
+
+  repeated ProcessSymbols process_symbols = 1;
+}
+
+// End of protos/perfetto/metrics/android/unmapped_java_symbols.proto
+
 // Begin of protos/perfetto/metrics/android/unsymbolized_frames.proto
 
 message UnsymbolizedFrames {
@@ -1005,7 +730,13 @@
 
 // Trace processor metadata
 message TraceMetadata {
-  reserved 1;
+  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;
   optional string android_build_fingerprint = 4;
@@ -1013,43 +744,13 @@
   optional int64 trace_size_bytes = 6;
   repeated string trace_trigger = 7;
   optional string unique_session_name = 8;
-  optional string trace_config_pbtxt = 9;
-  optional int64 sched_duration_ns = 10;
-}
-
-// Stats counters for the trace.
-// Defined in src/trace_processor/storage/stats.h
-message TraceAnalysisStats {
-  enum Severity {
-    SEVERITY_UNKNOWN = 0;
-    SEVERITY_INFO = 1;
-    SEVERITY_DATA_LOSS = 2;
-    SEVERITY_ERROR = 3;
-  }
-
-  enum Source {
-    SOURCE_UNKNOWN = 0;
-    SOURCE_TRACE = 1;
-    SOURCE_ANALYSIS = 2;
-  }
-
-  message Stat {
-    optional string name = 1;
-    optional uint32 idx = 2;
-    optional Severity severity = 3;
-    optional Source source = 4;
-
-    optional int64 count = 5;
-  }
-
-  repeated Stat stat = 1;
 }
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 34
+// Next id: 25
 message TraceMetrics {
-  reserved 4, 10, 13, 14, 16, 19;
+  reserved 4, 10, 13, 14;
 
   // Battery counters metric on Android.
   optional AndroidBatteryMetric android_batt = 5;
@@ -1072,9 +773,6 @@
   // ion buffer memory metrics.
   optional AndroidIonMetric android_ion = 9;
 
-  // fastrpc subsystem memory metrics.
-  optional AndroidFastrpcMetric android_fastrpc = 31;
-
   // Statistics about low memory kills.
   optional AndroidLmkMetric android_lmk = 8;
 
@@ -1084,12 +782,12 @@
   // 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;
 
-  // Trace stats (applicable to all traces).
-  optional TraceAnalysisStats trace_stats = 33;
-
   // Returns stack frames missing symbols.
   optional UnsymbolizedFrames unsymbolized_frames = 15;
 
@@ -1102,6 +800,9 @@
   // Metrics used to find potential culprits of low-memory kills.
   optional AndroidLmkReasonMetric android_lmk_reason = 18;
 
+  // Java type names that have no deobfuscation mappings.
+  optional UnmappedJavaSymbols unmapped_java_symbols = 19;
+
   optional AndroidHwuiMetric android_hwui_metric = 20;
 
   optional AndroidDisplayMetrics display_metrics = 22;
@@ -1110,35 +811,11 @@
 
   optional AndroidThreadTimeInStateMetric android_thread_time_in_state = 24;
 
-  // Metric associated with surfaceflinger.
-  optional AndroidSurfaceflingerMetric android_surfaceflinger = 25;
-
-  // GPU metrics on Android.
-  optional AndroidGpuMetric android_gpu = 26;
-
-  // Frame timing and jank root causes for system UI interactions.
-  optional AndroidSysUiCujMetrics android_sysui_cuj = 27;
-
-  // Metric associated with hwcomposer.
-  optional AndroidHwcomposerMetrics android_hwcomposer = 28;
-
-  // Detects common bad patterns that might lead to jank.
-  optional AndroidJankMetrics android_jank = 29;
-
-  // G2D metrics.
-  optional G2dMetrics g2d = 30;
-
-  // Dmabuf heap metrics.
-  optional AndroidDmaHeapMetric android_dma_heap = 32;
-
   // Demo extensions.
   extensions 450 to 499;
 
   // Vendor extensions.
   extensions 500 to 1000;
-
-  // Chrome metrics.
-  extensions 1001 to 2000;
 }
 
 // End of protos/perfetto/metrics/metrics.proto
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index ed7b6ae..b644aaf 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -29,12 +29,8 @@
 proto_sources_non_minimal = [
   "trace_packet_defaults.proto",
   "test_event.proto",
-  "test_extensions.proto",
   "trace_packet.proto",
   "trace.proto",
-  "extension_descriptor.proto",
-  "memory_graph.proto",
-  "ui_state.proto",
 ]
 
 proto_sources_minimal = [
@@ -123,10 +119,3 @@
   complete_static_lib = true
   deps = [ ":lite" ]
 }
-
-perfetto_proto_library("test_extensions_descriptor") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "test_extensions.descriptor"
-  sources = [ "test_extensions.proto" ]
-  deps = [ "track_event:source_set" ]
-}
diff --git a/protos/perfetto/trace/android/BUILD.gn b/protos/perfetto/trace/android/BUILD.gn
index c957f64..99d7f0f 100644
--- a/protos/perfetto/trace/android/BUILD.gn
+++ b/protos/perfetto/trace/android/BUILD.gn
@@ -19,9 +19,8 @@
 
   sources = [
     "android_log.proto",
-    "frame_timeline_event.proto",
-    "gpu_mem_event.proto",
     "graphics_frame_event.proto",
+    "gpu_mem_event.proto",
     "initial_display_state.proto",
     "packages_list.proto",
   ]
diff --git a/protos/perfetto/trace/android/frame_timeline_event.proto b/protos/perfetto/trace/android/frame_timeline_event.proto
deleted file mode 100644
index bee0bc7..0000000
--- a/protos/perfetto/trace/android/frame_timeline_event.proto
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-package perfetto.protos;
-
-// Generated by SurfaceFlinger's FrameTimeline (go/adaptive-scheduling-fr).
-// Used in comparing the expected timeline of a frame to the actual timeline.
-// Key terms:
-//    1) DisplayFrame - represents SurfaceFlinger's work on a frame(composited)
-//    2) SurfaceFrame - represents App's work on its frame
-//    3) Timeline = start to end of a component's(app/SF) work on a frame.
-// SurfaceFlinger composites frames from many apps together, so
-//    One DisplayFrame can map to N SurfaceFrame(s)
-// This relationship can be reconstructed by using
-//    DisplayFrame.token = SurfaceFrame.display_frame_token
-message FrameTimelineEvent {
-  // Specifies the reason(s) most likely to have caused the jank.
-  // Used as a bitmask.
-  enum JankType {
-    JANK_UNSPECIFIED = 0;
-    JANK_NONE = 1;
-    JANK_SF_SCHEDULING = 2;
-    JANK_PREDICTION_ERROR = 4;
-    JANK_DISPLAY_HAL = 8;
-    JANK_SF_CPU_DEADLINE_MISSED = 16;
-    JANK_SF_GPU_DEADLINE_MISSED = 32;
-    JANK_APP_DEADLINE_MISSED = 64;
-    JANK_BUFFER_STUFFING = 128;
-    JANK_UNKNOWN = 256;
-    JANK_SF_STUFFING = 512;
-  };
-
-  // Specifies how a frame was presented on screen w.r.t. timing.
-  // Can be different for SurfaceFrame and DisplayFrame.
-  enum PresentType {
-    PRESENT_UNSPECIFIED = 0;
-    PRESENT_ON_TIME = 1;
-    PRESENT_LATE = 2;
-    PRESENT_EARLY = 3;
-    PRESENT_DROPPED = 4;
-    PRESENT_UNKNOWN = 5;
-  };
-
-  // Specifies if the predictions for the frame are still valid, expired or
-  // unknown.
-  enum PredictionType {
-    PREDICTION_UNSPECIFIED = 0;
-    PREDICTION_VALID = 1;
-    PREDICTION_EXPIRED = 2;
-    PREDICTION_UNKNOWN = 3;
-  };
-
-  // Indicates the start of expected timeline slice for SurfaceFrames.
-  message ExpectedSurfaceFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by the app for its work. Can be shared between multiple
-    // layers of the same app (example: pip mode).
-    optional int64 token = 2;
-    // The corresponding DisplayFrame token is required to link the App's work
-    // with SurfaceFlinger's work. Many SurfaceFrames can be mapped to a single
-    // DisplayFrame.
-    // this.display_frame_token = DisplayFrame.token
-    optional int64 display_frame_token = 3;
-
-    // Pid of the app. Used in creating the timeline tracks (and slices) inside
-    // the respective process track group.
-    optional int32 pid = 4;
-    optional string layer_name = 5;
-  };
-
-  // Indicates the start of actual timeline slice for SurfaceFrames. Also
-  // includes the jank information.
-  message ActualSurfaceFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by the app for its work. Can be shared between multiple
-    // layers of the same app (example: pip mode).
-    optional int64 token = 2;
-    // The corresponding DisplayFrame token is required to link the App's work
-    // with SurfaceFlinger's work. Many SurfaceFrames can be mapped to a single
-    // DisplayFrame.
-    // this.display_frame_token = DisplayFrame.token
-    optional int64 display_frame_token = 3;
-
-    // Pid of the app. Used in creating the timeline tracks (and slices) inside
-    // the respective process track group.
-    optional int32 pid = 4;
-    optional string layer_name = 5;
-
-    optional PresentType present_type = 6;
-    optional bool on_time_finish = 7;
-    optional bool gpu_composition = 8;
-    // A bitmask of JankType. More than one reason can be attributed to a janky
-    // frame.
-    optional int32 jank_type = 9;
-    optional PredictionType prediction_type = 10;
-    optional bool is_buffer = 11;
-  };
-
-  // Indicates the start of expected timeline slice for DisplayFrames.
-  message ExpectedDisplayFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by SurfaceFlinger for its work
-    // this.token = SurfaceFrame.display_frame_token
-    optional int64 token = 2;
-
-    // Pid of SurfaceFlinger. Used in creating the timeline tracks (and slices)
-    // inside the SurfaceFlinger process group.
-    optional int32 pid = 3;
-  };
-
-  // Indicates the start of actual timeline slice for DisplayFrames. Also
-  // includes the jank information.
-  message ActualDisplayFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by SurfaceFlinger for its work
-    // this.token = SurfaceFrame.display_frame_token
-    optional int64 token = 2;
-
-    // Pid of SurfaceFlinger. Used in creating the timeline tracks (and slices)
-    // inside the SurfaceFlinger process group.
-    optional int32 pid = 3;
-
-    optional PresentType present_type = 4;
-    optional bool on_time_finish = 5;
-    optional bool gpu_composition = 6;
-    // A bitmask of JankType. More than one reason can be attributed to a janky
-    // frame.
-    optional int32 jank_type = 7;
-    optional PredictionType prediction_type = 8;
-  };
-
-  // FrameEnd just sends the cookie to indicate that the corresponding
-  // <display/surface>frame slice's end.
-  message FrameEnd { optional int64 cookie = 1; };
-
-  oneof event {
-    ExpectedDisplayFrameStart expected_display_frame_start = 1;
-    ActualDisplayFrameStart actual_display_frame_start = 2;
-
-    ExpectedSurfaceFrameStart expected_surface_frame_start = 3;
-    ActualSurfaceFrameStart actual_surface_frame_start = 4;
-
-    FrameEnd frame_end = 5;
-  }
-}
diff --git a/protos/perfetto/trace/android/graphics_frame_event.proto b/protos/perfetto/trace/android/graphics_frame_event.proto
index 3fb67eb..616aca8 100644
--- a/protos/perfetto/trace/android/graphics_frame_event.proto
+++ b/protos/perfetto/trace/android/graphics_frame_event.proto
@@ -26,10 +26,8 @@
     POST = 3;
     ACQUIRE_FENCE = 4;
     LATCH = 5;
-    // HWC will compose this buffer
-    HWC_COMPOSITION_QUEUED = 6;
-    // renderEngine composition
-    FALLBACK_COMPOSITION = 7;
+    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
+    FALLBACK_COMPOSITION = 7;    // renderEngine composition
     PRESENT_FENCE = 8;
     RELEASE_FENCE = 9;
     MODIFY = 10;
diff --git a/protos/perfetto/trace/chrome/chrome_metadata.proto b/protos/perfetto/trace/chrome/chrome_metadata.proto
index 8882593..c9dc064 100644
--- a/protos/perfetto/trace/chrome/chrome_metadata.proto
+++ b/protos/perfetto/trace/chrome/chrome_metadata.proto
@@ -25,11 +25,6 @@
   // Version code of Chrome used by Android's Play Store. This field is only set
   // on Android.
   optional int32 chrome_version_code = 2;
-
-  // Comma separated list of enabled categories for tracing. The list of
-  // possible category strings are listed in code
-  // base/trace_event/builtin_categories.h.
-  optional string enabled_categories = 3;
 }
 
 // Metadata related to background tracing scenarios, states and triggers.
@@ -67,15 +62,10 @@
         NAVIGATION = 2;
         STARTUP = 3;
         REACHED_CODE = 4;
-        CONTENT_TRIGGER = 5;
 
         TEST_RULE = 1000;
       }
       optional EventType event_type = 1;
-
-      // If |event_type| is CONTENT_TRIGGER, then this stores the hash of the
-      // content-trigger that actually fired.
-      optional fixed64 content_trigger_name_hash = 2;
     }
     optional NamedRule named_rule = 3;
   }
diff --git a/protos/perfetto/trace/chrome/chrome_trace_event.proto b/protos/perfetto/trace/chrome/chrome_trace_event.proto
index f4ed43f..1c3725c 100644
--- a/protos/perfetto/trace/chrome/chrome_trace_event.proto
+++ b/protos/perfetto/trace/chrome/chrome_trace_event.proto
@@ -101,9 +101,7 @@
 message ChromeLegacyJsonTrace {
   enum TraceType {
     USER_TRACE = 0;
-
-    // Deprecated.
-    SYSTEM_TRACE = 1;
+    SYSTEM_TRACE = 1;  // Deprecated.
   }
   optional TraceType type = 1;
   optional string data = 2;
@@ -112,8 +110,6 @@
 message ChromeEventBundle {
   // Deprecated, use TrackEvent protos instead.
   repeated ChromeTraceEvent trace_events = 1 [deprecated = true];
-  // TODO(ssid): This should be deprecated in favor of ChromeMetadataPacket
-  // which contains typed fields.
   repeated ChromeMetadata metadata = 2;
   // ftrace output from CrOS and Cast system tracing agents.
   // TODO(eseckler): Replace system traces with native perfetto service.
diff --git a/protos/perfetto/trace/extension_descriptor.proto b/protos/perfetto/trace/extension_descriptor.proto
deleted file mode 100644
index beb65a0..0000000
--- a/protos/perfetto/trace/extension_descriptor.proto
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-import "protos/perfetto/common/descriptor.proto";
-
-// This message contains descriptors used to parse extension fields of
-// TrackEvent.
-//
-// See docs/design-docs/extensions.md for more details.
-message ExtensionDescriptor {
-  optional FileDescriptorSet extension_set = 1;
-}
diff --git a/protos/perfetto/trace/ftrace/all_protos.gni b/protos/perfetto/trace/ftrace/all_protos.gni
index 8910853..3389b54 100644
--- a/protos/perfetto/trace/ftrace/all_protos.gni
+++ b/protos/perfetto/trace/ftrace/all_protos.gni
@@ -25,16 +25,11 @@
   "cgroup.proto",
   "clk.proto",
   "compaction.proto",
-  "cpuhp.proto",
-  "dmabuf_heap.proto",
-  "dpu.proto",
   "ext4.proto",
   "f2fs.proto",
-  "fastrpc.proto",
   "fence.proto",
   "filemap.proto",
   "ftrace.proto",
-  "g2d.proto",
   "gpu_mem.proto",
   "i2c.proto",
   "ion.proto",
@@ -42,7 +37,6 @@
   "irq.proto",
   "kmem.proto",
   "lowmemorykiller.proto",
-  "mali.proto",
   "mdss.proto",
   "mm_event.proto",
   "oom.proto",
@@ -50,13 +44,11 @@
   "raw_syscalls.proto",
   "regulator.proto",
   "sched.proto",
-  "scm.proto",
   "sde.proto",
   "signal.proto",
   "sync.proto",
   "systrace.proto",
   "task.proto",
-  "thermal.proto",
   "vmscan.proto",
   "workqueue.proto",
 ]
diff --git a/protos/perfetto/trace/ftrace/cpuhp.proto b/protos/perfetto/trace/ftrace/cpuhp.proto
deleted file mode 100644
index dc45682..0000000
--- a/protos/perfetto/trace/ftrace/cpuhp.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message CpuhpExitFtraceEvent {
-  optional uint32 cpu = 1;
-  optional int32 idx = 2;
-  optional int32 ret = 3;
-  optional int32 state = 4;
-}
-message CpuhpMultiEnterFtraceEvent {
-  optional uint32 cpu = 1;
-  optional uint64 fun = 2;
-  optional int32 idx = 3;
-  optional int32 target = 4;
-}
-message CpuhpEnterFtraceEvent {
-  optional uint32 cpu = 1;
-  optional uint64 fun = 2;
-  optional int32 idx = 3;
-  optional int32 target = 4;
-}
-message CpuhpLatencyFtraceEvent {
-  optional uint32 cpu = 1;
-  optional int32 ret = 2;
-  optional uint32 state = 3;
-  optional uint64 time = 4;
-}
-message CpuhpPauseFtraceEvent {
-  optional uint32 active_cpus = 1;
-  optional uint32 cpus = 2;
-  optional uint32 pause = 3;
-  optional uint32 time = 4;
-}
diff --git a/protos/perfetto/trace/ftrace/dmabuf_heap.proto b/protos/perfetto/trace/ftrace/dmabuf_heap.proto
deleted file mode 100644
index 5b7e70f..0000000
--- a/protos/perfetto/trace/ftrace/dmabuf_heap.proto
+++ /dev/null
@@ -1,12 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message DmaHeapStatFtraceEvent {
-  optional uint64 inode = 1;
-  optional int64 len = 2;
-  optional uint64 total_allocated = 3;
-}
diff --git a/protos/perfetto/trace/ftrace/dpu.proto b/protos/perfetto/trace/ftrace/dpu.proto
deleted file mode 100644
index 31eefc3..0000000
--- a/protos/perfetto/trace/ftrace/dpu.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message DpuTracingMarkWriteFtraceEvent {
-  optional int32 pid = 1;
-  optional string trace_name = 2;
-  optional uint32 trace_begin = 3;
-  optional string name = 4;
-  optional uint32 type = 5;
-  optional int32 value = 6;
-}
diff --git a/protos/perfetto/trace/ftrace/fastrpc.proto b/protos/perfetto/trace/ftrace/fastrpc.proto
deleted file mode 100644
index 15d694c..0000000
--- a/protos/perfetto/trace/ftrace/fastrpc.proto
+++ /dev/null
@@ -1,12 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message FastrpcDmaStatFtraceEvent {
-  optional int32 cid = 1;
-  optional int64 len = 2;
-  optional uint64 total_allocated = 3;
-}
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index 31e5b92..583be1c 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -25,16 +25,11 @@
 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/cpuhp.proto";
-import "protos/perfetto/trace/ftrace/dmabuf_heap.proto";
-import "protos/perfetto/trace/ftrace/dpu.proto";
 import "protos/perfetto/trace/ftrace/ext4.proto";
 import "protos/perfetto/trace/ftrace/f2fs.proto";
-import "protos/perfetto/trace/ftrace/fastrpc.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/g2d.proto";
 import "protos/perfetto/trace/ftrace/gpu_mem.proto";
 import "protos/perfetto/trace/ftrace/i2c.proto";
 import "protos/perfetto/trace/ftrace/ion.proto";
@@ -42,7 +37,6 @@
 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/mali.proto";
 import "protos/perfetto/trace/ftrace/mdss.proto";
 import "protos/perfetto/trace/ftrace/mm_event.proto";
 import "protos/perfetto/trace/ftrace/oom.proto";
@@ -50,13 +44,11 @@
 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/scm.proto";
 import "protos/perfetto/trace/ftrace/sde.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/thermal.proto";
 import "protos/perfetto/trace/ftrace/vmscan.proto";
 import "protos/perfetto/trace/ftrace/workqueue.proto";
 import "protos/perfetto/trace/ftrace/generic.proto";
@@ -426,26 +418,6 @@
     IonStatFtraceEvent ion_stat = 335;
     IonBufferCreateFtraceEvent ion_buffer_create = 336;
     IonBufferDestroyFtraceEvent ion_buffer_destroy = 337;
-    ScmCallStartFtraceEvent scm_call_start = 338;
-    ScmCallEndFtraceEvent scm_call_end = 339;
     GpuMemTotalFtraceEvent gpu_mem_total = 340;
-    ThermalTemperatureFtraceEvent thermal_temperature = 341;
-    CdevUpdateFtraceEvent cdev_update = 342;
-    CpuhpExitFtraceEvent cpuhp_exit = 343;
-    CpuhpMultiEnterFtraceEvent cpuhp_multi_enter = 344;
-    CpuhpEnterFtraceEvent cpuhp_enter = 345;
-    CpuhpLatencyFtraceEvent cpuhp_latency = 346;
-    FastrpcDmaStatFtraceEvent fastrpc_dma_stat = 347;
-    DpuTracingMarkWriteFtraceEvent dpu_tracing_mark_write = 348;
-    G2dTracingMarkWriteFtraceEvent g2d_tracing_mark_write = 349;
-    MaliTracingMarkWriteFtraceEvent mali_tracing_mark_write = 350;
-    DmaHeapStatFtraceEvent dma_heap_stat = 351;
-    CpuhpPauseFtraceEvent cpuhp_pause = 352;
-    SchedPiSetprioFtraceEvent sched_pi_setprio = 353;
-    SdeSdeEvtlogFtraceEvent sde_sde_evtlog = 354;
-    SdeSdePerfCalcCrtcFtraceEvent sde_sde_perf_calc_crtc = 355;
-    SdeSdePerfCrtcUpdateFtraceEvent sde_sde_perf_crtc_update = 356;
-    SdeSdePerfSetQosLutsFtraceEvent sde_sde_perf_set_qos_luts = 357;
-    SdeSdePerfUpdateBusFtraceEvent sde_sde_perf_update_bus = 358;
   }
 }
diff --git a/protos/perfetto/trace/ftrace/ftrace_stats.proto b/protos/perfetto/trace/ftrace/ftrace_stats.proto
index 1f65456..5e6ea92 100644
--- a/protos/perfetto/trace/ftrace/ftrace_stats.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_stats.proto
@@ -69,15 +69,4 @@
 
   // Per-CPU stats (one entry for each CPU).
   repeated FtraceCpuStats cpu_stats = 2;
-
-  // When FtraceConfig.symbolize_ksyms = true, this records the number of
-  // symbols parsed from /proc/kallsyms, whether they have been seen in the
-  // trace or not. It can be used to debug kptr_restrict or security-related
-  // errors.
-  // Note: this will be valid only when phase = END_OF_TRACE. The symbolizer is
-  // initialized. When START_OF_TRACE is emitted it is not ready yet.
-  optional uint32 kernel_symbols_parsed = 3;
-
-  // The memory used by the kernel symbolizer (KernelSymbolMap.size_bytes()).
-  optional uint32 kernel_symbols_mem_kb = 4;
 }
diff --git a/protos/perfetto/trace/ftrace/g2d.proto b/protos/perfetto/trace/ftrace/g2d.proto
deleted file mode 100644
index d87c211..0000000
--- a/protos/perfetto/trace/ftrace/g2d.proto
+++ /dev/null
@@ -1,13 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message G2dTracingMarkWriteFtraceEvent {
-  optional int32 pid = 1;
-  optional string name = 4;
-  optional uint32 type = 5;
-  optional int32 value = 6;
-}
diff --git a/protos/perfetto/trace/ftrace/mali.proto b/protos/perfetto/trace/ftrace/mali.proto
deleted file mode 100644
index 54f2ad1..0000000
--- a/protos/perfetto/trace/ftrace/mali.proto
+++ /dev/null
@@ -1,13 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message MaliTracingMarkWriteFtraceEvent {
-  optional string name = 1;
-  optional int32 pid = 2;
-  optional uint32 type = 3;
-  optional int32 value = 4;
-}
diff --git a/protos/perfetto/trace/ftrace/sched.proto b/protos/perfetto/trace/ftrace/sched.proto
index 87f409b..9c31fac 100644
--- a/protos/perfetto/trace/ftrace/sched.proto
+++ b/protos/perfetto/trace/ftrace/sched.proto
@@ -76,9 +76,3 @@
   optional int32 pid = 2;
   optional int32 prio = 3;
 }
-message SchedPiSetprioFtraceEvent {
-  optional string comm = 1;
-  optional int32 newprio = 2;
-  optional int32 oldprio = 3;
-  optional int32 pid = 4;
-}
diff --git a/protos/perfetto/trace/ftrace/scm.proto b/protos/perfetto/trace/ftrace/scm.proto
deleted file mode 100644
index 22a80a5..0000000
--- a/protos/perfetto/trace/ftrace/scm.proto
+++ /dev/null
@@ -1,13 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message ScmCallStartFtraceEvent {
-  optional uint32 arginfo = 1;
-  optional uint64 x0 = 2;
-  optional uint64 x5 = 3;
-}
-message ScmCallEndFtraceEvent {}
diff --git a/protos/perfetto/trace/ftrace/sde.proto b/protos/perfetto/trace/ftrace/sde.proto
index 61c8d7b..724a9a3 100644
--- a/protos/perfetto/trace/ftrace/sde.proto
+++ b/protos/perfetto/trace/ftrace/sde.proto
@@ -12,46 +12,3 @@
   optional int32 value = 4;
   optional uint32 trace_begin = 5;
 }
-message SdeSdeEvtlogFtraceEvent {
-  optional string evtlog_tag = 1;
-  optional int32 pid = 2;
-  optional uint32 tag_id = 3;
-}
-message SdeSdePerfCalcCrtcFtraceEvent {
-  optional uint64 bw_ctl_ebi = 1;
-  optional uint64 bw_ctl_llcc = 2;
-  optional uint64 bw_ctl_mnoc = 3;
-  optional uint32 core_clk_rate = 4;
-  optional uint32 crtc = 5;
-  optional uint64 ib_ebi = 6;
-  optional uint64 ib_llcc = 7;
-  optional uint64 ib_mnoc = 8;
-}
-message SdeSdePerfCrtcUpdateFtraceEvent {
-  optional uint64 bw_ctl_ebi = 1;
-  optional uint64 bw_ctl_llcc = 2;
-  optional uint64 bw_ctl_mnoc = 3;
-  optional uint32 core_clk_rate = 4;
-  optional uint32 crtc = 5;
-  optional int32 params = 6;
-  optional uint64 per_pipe_ib_ebi = 7;
-  optional uint64 per_pipe_ib_llcc = 8;
-  optional uint64 per_pipe_ib_mnoc = 9;
-  optional uint32 stop_req = 10;
-  optional uint32 update_bus = 11;
-  optional uint32 update_clk = 12;
-}
-message SdeSdePerfSetQosLutsFtraceEvent {
-  optional uint32 fl = 1;
-  optional uint32 fmt = 2;
-  optional uint64 lut = 3;
-  optional uint32 lut_usage = 4;
-  optional uint32 pnum = 5;
-  optional uint32 rt = 6;
-}
-message SdeSdePerfUpdateBusFtraceEvent {
-  optional uint64 ab_quota = 1;
-  optional uint32 bus_id = 2;
-  optional int32 client = 3;
-  optional uint64 ib_quota = 4;
-}
diff --git a/protos/perfetto/trace/ftrace/thermal.proto b/protos/perfetto/trace/ftrace/thermal.proto
deleted file mode 100644
index 3aa78d3..0000000
--- a/protos/perfetto/trace/ftrace/thermal.proto
+++ /dev/null
@@ -1,17 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-package perfetto.protos;
-
-message ThermalTemperatureFtraceEvent {
-  optional int32 id = 1;
-  optional int32 temp = 2;
-  optional int32 temp_prev = 3;
-  optional string thermal_zone = 4;
-}
-message CdevUpdateFtraceEvent {
-  optional uint64 target = 1;
-  optional string type = 2;
-}
diff --git a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
index e00b39e..16f8b00 100644
--- a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
+++ b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
@@ -18,68 +18,45 @@
 
 package perfetto.protos;
 
-// next id: 15
+// next id: 13
 message GpuRenderStageEvent {
   // required. Unique ID for the event.
   optional uint64 event_id = 1;
 
-  // optional. Duration of the event in nanoseconds. If unset, this is a
-  // single time point event.
+  // 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.
-  // InternedGpuRenderStageSpecification
-  optional uint64 hw_queue_iid = 13;
+  optional int32 hw_queue_id = 3;
 
   // required. ID to a render stage description in the specifications.
-  // InternedGpuRenderStageSpecification
-  optional uint64 stage_iid = 14;
+  optional int32 stage_id = 4;
 
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 11;
-
-  // required. Graphics context for the event.
-  // For OpenGL, this is the GL context.
-  // For Vulkan, this is the VkDevice.
+  // required. GL context/VK device.
   optional uint64 context = 5;
 
   // optional. The render target for this event.
-  // For OpenGL, this is the GL frame buffer handle.
-  // For Vulkan, this is the VkFrameBuffer handle.
   optional uint64 render_target_handle = 8;
 
-  // optional. Submission ID generated by the UMD.
-  // For OpenGL, the ID should map to an API submission (e.g., glFlush,
-  // glFinish, eglSwapBufffers) event.  The set of submissions to the HW due
-  // to a single API submission should share the same ID.
-  // For Vulkan, it should map 1:1 with a vkQueueSubmit.
+  // 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. Should map 1:1 with a
+  // vkQueueSubmit.
   optional uint32 submission_id = 10;
 
-  // optional. Additional data for the user. This may include attributes for
-  // the event like resource ids, shaders, etc.
+  // 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;
 
-  // VULKAN SPECIFICS
-
-  // optional. The Vulkan render pass handle.
-  optional uint64 render_pass_handle = 9;
-
-  // optional. A bit mask representing which render subpasses contributed to
-  // this render stage event.  Subpass index 0 is represented by setting the
-  // LSB of the mask.  Additional mask can be added for subpass index greater
-  // than 63.
-  repeated uint64 render_subpass_index_mask = 15;
-
-  // optional. The Vulkan command buffer handle.
-  optional uint64 command_buffer_handle = 12;
-
-  // DEPRECATED
-
-  // Deprecated.  Use InternedGpuRenderStageSpecification instead.
   // The first trace packet of each session should include a Specifications
   // to enumerate *all* IDs that will be used. The timestamp of this packet
   // must be earlier than all other packets. Only one packet with Specifications
@@ -102,45 +79,11 @@
     // Labels to categorize render stage(binning, render, compute etc).
     repeated Description stage = 3;
   }
-  // Deprecated.  Use hw_queue_iid and stage_iid to refer to
-  // InternedGpuRenderStageSpecification instead.
-  optional Specifications specifications = 7 [deprecated = true];
+  optional Specifications specifications = 7;
 
-  // Deprecated. Use hw_queue_iid instead;
-  optional int32 hw_queue_id = 3 [deprecated = true];
-
-  // Deprecated. Use stage_iid instead;
-  optional int32 stage_id = 4 [deprecated = true];
+  // optional. Identifier for GPU in a multi-gpu device.
+  optional int32 gpu_id = 11;
 
   // Extension for vendor's custom proto.
   extensions 100;
 }
-
-// Interned data.
-
-// The iid is the numeric value of either the GL Context or the VkDevice
-// handle.
-message InternedGraphicsContext {
-  optional uint64 iid = 1;
-  optional int32 pid = 2;
-  enum Api {
-    UNDEFINED = 0;
-    OPEN_GL = 1;
-    VULKAN = 2;
-    OPEN_CL = 3;
-  }
-  optional Api api = 3;
-}
-
-message InternedGpuRenderStageSpecification {
-  optional uint64 iid = 1;
-  optional string name = 2;
-  optional string description = 3;
-
-  enum RenderStageCategory {
-    OTHER = 0;
-    GRAPHICS = 1;
-    COMPUTE = 2;
-  }
-  optional RenderStageCategory category = 4;
-}
diff --git a/protos/perfetto/trace/gpu/vulkan_memory_event.proto b/protos/perfetto/trace/gpu/vulkan_memory_event.proto
index bdb379c..b66cafd 100644
--- a/protos/perfetto/trace/gpu/vulkan_memory_event.proto
+++ b/protos/perfetto/trace/gpu/vulkan_memory_event.proto
@@ -55,21 +55,11 @@
 
   enum Operation {
     OP_UNSPECIFIED = 0;
-
-    // alloc, create
-    OP_CREATE = 1;
-
-    // free, destroy(non-bound)
-    OP_DESTROY = 2;
-
-    // bind buffer and image
-    OP_BIND = 3;
-
-    // destroy (bound)
-    OP_DESTROY_BOUND = 4;
-
-    // only annotations
-    OP_ANNOTATIONS = 5;
+    OP_CREATE = 1;         // alloc, create
+    OP_DESTROY = 2;        // free, destroy (non-bound)
+    OP_BIND = 3;           // bind buffer and image
+    OP_DESTROY_BOUND = 4;  // destroy (bound)
+    OP_ANNOTATIONS = 5;    // only annotations
   }
 
   enum AllocationScope {
diff --git a/protos/perfetto/trace/interned_data/BUILD.gn b/protos/perfetto/trace/interned_data/BUILD.gn
index 580bb5b..9ca2273 100644
--- a/protos/perfetto/trace/interned_data/BUILD.gn
+++ b/protos/perfetto/trace/interned_data/BUILD.gn
@@ -17,7 +17,6 @@
 perfetto_proto_library("@TYPE@") {
   sources = [ "interned_data.proto" ]
   deps = [
-    "../gpu:@TYPE@",
     "../profiling:@TYPE@",
     "../track_event:@TYPE@",
   ]
diff --git a/protos/perfetto/trace/interned_data/interned_data.proto b/protos/perfetto/trace/interned_data/interned_data.proto
index cc9c9e3..8b80554 100644
--- a/protos/perfetto/trace/interned_data/interned_data.proto
+++ b/protos/perfetto/trace/interned_data/interned_data.proto
@@ -16,8 +16,6 @@
 
 syntax = "proto2";
 
-import "protos/perfetto/trace/gpu/gpu_render_stage_event.proto";
-import "protos/perfetto/trace/track_event/chrome_histogram_sample.proto";
 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";
@@ -53,7 +51,7 @@
 // emitted proactively in advance of referring to them in later packets.
 //
 // Next reserved id: 8 (up to 15).
-// Next id: 27.
+// Next id: 23.
 message InternedData {
   // TODO(eseckler): Replace iid fields inside interned messages with
   // map<iid, message> type fields in InternedData.
@@ -70,7 +68,6 @@
   repeated DebugAnnotationName debug_annotation_names = 3;
   repeated SourceLocation source_locations = 4;
   repeated LogMessageBody log_message_body = 20;
-  repeated HistogramName histogram_names = 25;
 
   // Note: field IDs up to 15 should be used for frequent data only.
 
@@ -94,19 +91,4 @@
 
   // Additional Vulkan information sent in a VulkanMemoryEvent message
   repeated InternedString vulkan_memory_keys = 22;
-
-  // Graphics context of a render stage event.  This represent the GL
-  // context for an OpenGl app or the VkDevice for a Vulkan app.
-  repeated InternedGraphicsContext graphics_contexts = 23;
-
-  // Description of a GPU hardware queue or render stage.
-  repeated InternedGpuRenderStageSpecification gpu_specifications = 24;
-
-  // This is set when FtraceConfig.symbolize_ksyms = true.
-  // The id of each symbol the number that will be reported in ftrace events
-  // like sched_block_reason.caller and is obtained from a monotonic counter.
-  // The same symbol can have different indexes in different bundles.
-  // This is is NOT the real address. This is to avoid disclosing KASLR through
-  // traces.
-  repeated InternedString kernel_symbols = 26;
 }
diff --git a/protos/perfetto/trace/memory_graph.proto b/protos/perfetto/trace/memory_graph.proto
deleted file mode 100644
index ec315fb..0000000
--- a/protos/perfetto/trace/memory_graph.proto
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Message definitions for app-reported memory breakdowns. At the moment, this
-// is a Chrome-only tracing feature, historically known as 'memory-infra'. See
-// https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/ .
-// This is unrelated to the native or java heap profilers (those protos live
-// in //protos/perfetto/trace/profiling/).
-
-message MemoryTrackerSnapshot {
-  // Memory snapshot of a process. The snapshot contains memory data that is
-  // from 2 different sources, namely system stats and instrumentation stats.
-  // The system memory usage stats come from the OS based on standard API
-  // available in the platform to query memory usage. The instrumentation stats
-  // are added by instrumenting specific piece of code which tracks memory
-  // allocations and deallocations made by a small sub-system within the
-  // application.
-  // The system stats of the global memory snapshot are recorded as part of
-  // ProcessStats and SmapsPacket fields in trace packet with the same
-  // timestamp.
-  message ProcessSnapshot {
-    // Process ID of the process
-    optional int32 pid = 1;
-
-    // Memory dumps are represented as a graph of memory nodes which contain
-    // statistics. To avoid double counting the same memory across different
-    // nodes, edges are used to mark nodes that account for the same memory. See
-    // this doc for examples of the usage:
-    // https://docs.google.com/document/d/1WGQRJ1sjJrfVkNcgPVY6frm64UqPc94tsxUOXImZUZI
-
-    // A single node in the memory graph.
-    message MemoryNode {
-      // Unique ID of the node across all processes involved in the global
-      // memory dump. The ID is only unique within this particular global dump
-      // identified by GlobalMemoryDumpPacket.global_dump_id.
-      optional uint64 id = 1;
-
-      // Absolute name is a unique name for the memory node within the process
-      // with ProcessMemoryDump.pid. The name can contain multiple parts
-      // separated by '/', which traces the edges of the node from the root
-      // node.
-      // Eg: "partition_allocator/array_buffers/buffer1" refers to the child
-      // node "buffer1" in a graph structure of:
-      //   root -> partition_allocator -> array_buffers -> buffer1.
-      optional string absolute_name = 2;
-
-      // A weak node means that the instrumentation that added the current node
-      // is unsure about the existence of the actual memory. Unless a "strong"
-      // (non-weak is default) node that has an edge to the current node exists
-      // in the current global dump, the current node will be discarded.
-      optional bool weak = 3;
-
-      // Size of the node in bytes, used to compute the effective size of the
-      // nodes without double counting.
-      optional uint64 size_bytes = 4;
-
-      // Entries in the memory node that contain statistics and additional
-      // debuggable information about the memory. The size of the node is
-      // tracked separately in the |size_bytes| field.
-      message MemoryNodeEntry {
-        optional string name = 1;
-
-        enum Units {
-          UNSPECIFIED = 0;
-          BYTES = 1;
-          COUNT = 2;
-        }
-        optional Units units = 2;
-
-        // Contains either one of uint64 or string value.
-        optional uint64 value_uint64 = 3;
-        optional string value_string = 4;
-      }
-      repeated MemoryNodeEntry entries = 5;
-    }
-    repeated MemoryNode allocator_dumps = 2;
-
-    // A directed edge that connects any 2 nodes in the graph above. These are
-    // in addition to the inherent edges added due to the tree structure of the
-    // node's absolute names.
-    // Node with id |source_id| owns the node with id |target_id|, and has the
-    // effect of attributing the memory usage of target to source. |importance|
-    // is optional and relevant only for the cases of co-ownership, where it
-    // acts as a z-index: the owner with the highest importance will be
-    // attributed target's memory.
-    message MemoryEdge {
-      optional uint64 source_id = 1;
-      optional uint64 target_id = 2;
-      optional uint32 importance = 3;
-      optional bool overridable = 4;
-    }
-    repeated MemoryEdge memory_edges = 3;
-  }
-
-  // Unique ID that represents the global memory dump.
-  optional uint64 global_dump_id = 1;
-
-  enum LevelOfDetail {
-    DETAIL_FULL = 0;
-    DETAIL_LIGHT = 1;
-    DETAIL_BACKGROUND = 2;
-  }
-  optional LevelOfDetail level_of_detail = 2;
-
-  repeated ProcessSnapshot process_memory_dumps = 3;
-}
diff --git a/protos/perfetto/trace/perfetto/tracing_service_event.proto b/protos/perfetto/trace/perfetto/tracing_service_event.proto
index 04923dc..0028057 100644
--- a/protos/perfetto/trace/perfetto/tracing_service_event.proto
+++ b/protos/perfetto/trace/perfetto/tracing_service_event.proto
@@ -18,48 +18,17 @@
 
 package perfetto.protos;
 
-// Events emitted by the tracing service.
+// Events emitted by the tracing service when data source states change.
 message TracingServiceEvent {
   oneof event_type {
-    // When each of the following booleans are set to true, they report the
-    // point in time (through TracePacket's timestamp) where the condition
-    // they describe happened.
-    // The order of the booleans below matches the timestamp ordering
-    // they would generally be expected to have.
-
-    // Emitted when we start tracing and specifically, this will be before any
-    // producer is notified about the existence of this trace. This is always
-    // emitted before the all_data_sources_started event. This event is also
-    // guaranteed to be seen (byte-offset wise) before any data packets from
-    // producers.
-    bool tracing_started = 2;
-
-    // Emitted after all data sources saw the start event and ACKed it.
-    // This identifies the point in time when it's safe to assume that all data
+    // When this is set to true, reports the point in time (the TracePacket's
+    // timestamp) when all data sources did see the start event and ACKed it.
+    // This identifies the point in time when it's safe to assume tha all data
     // sources have been recording events.
+    // Note: like any other event in the trace, the byte offset at which this
+    // packet shows up in the trace is arbitrary and doesn't reflect causal
+    // ordering (i.e. it's okay to use this event to reason about the timestamps
+    // of othe packets, NOT their relative order w.r.t. this packet).
     bool all_data_sources_started = 1;
-
-    // Emitted when all data sources have been flushed successfully or with an
-    // error (including timeouts). This can generally happen many times over the
-    // course of the trace.
-    bool all_data_sources_flushed = 3;
-
-    // Emitted when reading back the central tracing buffers has been completed.
-    // If |write_into_file| is specified, this can happen many times over the
-    // course of the trace.
-    bool read_tracing_buffers_completed = 4;
-
-    // Emitted after tracing has been disabled and specifically, this will be
-    // after all packets from producers have been included in the central
-    // tracing buffer.
-    bool tracing_disabled = 5;
-
-    // Emitted if perfetto --save-for-bugreport was invoked while the current
-    // tracing session was running and it had the highest bugreport_score. In
-    // this case the original consumer will see a nearly empty trace, because
-    // the contents are routed onto the bugreport file. This event flags the
-    // situation explicitly. Traces that contain this marker should be discarded
-    // by test infrastructures / pipelines.
-    bool seized_for_bugreport = 6;
   }
 }
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index bbb1699..a445f8f 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -25,8 +25,7 @@
     VERTICES = 2;
     FRAGMENTS = 3;
     PRIMITIVES = 4;
-    // Includes counters relating to caching and bandwidth.
-    MEMORY = 5;
+    MEMORY = 5;  // Includes counters relating to caching and bandwidth.
     COMPUTE = 6;
   }
 
@@ -34,8 +33,7 @@
     optional uint32 counter_id = 1;
     optional string name = 2;
     optional string description = 3;
-    // MeasureUnit unit (deprecated)
-    reserved 4;
+    reserved 4;  // MeasureUnit unit (deprecated)
     oneof peak_value {
       int64 int_peak_value = 5;
       double double_peak_value = 6;
@@ -155,8 +153,7 @@
 // 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 {
-  // e.g., "linux.ftrace", "chromium.tracing"
-  optional string name = 1;
+  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
@@ -189,20 +186,9 @@
 message TracingServiceState {
   // Describes a producer process.
   message Producer {
-    // Unique ID of the producer (monotonic counter).
-    optional int32 id = 1;
-
-    // Typically matches the process name.
-    optional string name = 2;
-
-    // Unix uid of the remote process.
-    optional int32 uid = 3;
-
-    // The version of the client library used by the producer.
-    // This is a human readable string with and its format varies depending on
-    // the build system and the repo (standalone vs AOSP).
-    // This is intended for human debugging only.
-    optional string sdk_version = 4;
+    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
@@ -226,12 +212,6 @@
 
   // Number of tracing sessions in the started state. Always <= num_sessions.
   optional int32 num_sessions_started = 4;
-
-  // The version of traced (the same returned by `traced --version`).
-  // This is a human readable string with and its format varies depending on
-  // the build system and the repo (standalone vs AOSP).
-  // This is intended for human debugging only.
-  optional string tracing_service_version = 5;
 }
 
 // End of protos/perfetto/common/tracing_service_state.proto
@@ -257,9 +237,7 @@
 
 // Values from NDK's android/log.h.
 enum AndroidLogId {
-  // MAIN.
-  LID_DEFAULT = 0;
-
+  LID_DEFAULT = 0;  // MAIN.
   LID_RADIO = 1;
   LID_EVENTS = 2;
   LID_SYSTEM = 3;
@@ -271,10 +249,7 @@
 
 enum AndroidLogPriority {
   PRIO_UNSPECIFIED = 0;
-
-  // _DEFAULT, but should never be seen in logs.
-  PRIO_UNUSED = 1;
-
+  PRIO_UNUSED = 1;  // _DEFAULT, but should never be seen in logs.
   PRIO_VERBOSE = 2;
   PRIO_DEBUG = 3;
   PRIO_INFO = 4;
@@ -290,8 +265,7 @@
 message AndroidLogConfig {
   repeated AndroidLogId log_ids = 1;
 
-  // Was |poll_ms|, deprecated.
-  reserved 2;
+  reserved 2;  // Was |poll_ms|, deprecated.
 
   // If set ignores all log messages whose prio is < the given value.
   optional AndroidLogPriority min_prio = 3;
@@ -335,27 +309,6 @@
   // When enabled, the data source should only fill in fields in the output that
   // are not potentially privacy sensitive.
   optional bool privacy_filtering_enabled = 2;
-
-  // Instead of emitting binary protobuf, convert the trace data to the legacy
-  // JSON format. Note that the trace data will still be returned as a series of
-  // TracePackets, but the embedded data will be JSON instead of serialized
-  // protobuf.
-  optional bool convert_to_legacy_json = 3;
-
-  // Priority of the tracing session client. A higher priority session may
-  // preempt a lower priority one in configurations where concurrent sessions
-  // aren't supported.
-  enum ClientPriority {
-    UNKNOWN = 0;
-    BACKGROUND = 1;
-    USER_INITIATED = 2;
-  }
-  optional ClientPriority client_priority = 4;
-
-  // Applicable only when using legacy JSON format.
-  // If |json_agent_label_filter| is not empty, only data pertaining to
-  // the specified tracing agent label (e.g. "traceEvents") will be returned.
-  optional string json_agent_label_filter = 5;
 }
 
 // End of protos/perfetto/config/chrome/chrome_config.proto
@@ -379,19 +332,6 @@
     optional bool enabled = 1;
   }
   optional CompactSchedConfig compact_sched = 12;
-
-  // Enables symbol name resolution against /proc/kallsyms.
-  // It requires that either traced_probes is running as root or that
-  // kptr_restrict has been manually lowered.
-  // It does not disclose KASLR, symbol addresses are mangled.
-  optional bool symbolize_ksyms = 13;
-
-  // By default the kernel symbolizer is lazily initialized on a deferred task
-  // to reduce ftrace's time-to-start-recording. Unfortunately that makes
-  // ksyms integration tests hard. This flag forces the kernel symbolizer to be
-  // initialized synchronously on the data source start and hence avoiding
-  // timing races in tests.
-  optional bool initialize_ksyms_synchronously_for_testing = 14;
 }
 
 // End of protos/perfetto/config/ftrace/ftrace_config.proto
@@ -458,61 +398,21 @@
 
 // End of protos/perfetto/config/inode_file/inode_file_config.proto
 
-// Begin of protos/perfetto/config/interceptors/console_config.proto
-
-message ConsoleConfig {
-  enum Output {
-    OUTPUT_UNSPECIFIED = 0;
-    OUTPUT_STDOUT = 1;
-    OUTPUT_STDERR = 2;
-  }
-  optional Output output = 1;
-  optional bool enable_colors = 2;
-}
-
-// End of protos/perfetto/config/interceptors/console_config.proto
-
-// Begin of protos/perfetto/config/interceptor_config.proto
-
-// Configuration for trace packet interception. Used for diverting trace data to
-// non-Perfetto sources (e.g., logging to the console, ETW) when using the
-// Perfetto SDK.
-message InterceptorConfig {
-  // Matches the name given to RegisterInterceptor().
-  optional string name = 1;
-
-  optional ConsoleConfig console_config = 100 [lazy = true];
-}
-
-// End of protos/perfetto/config/interceptor_config.proto
-
 // Begin of protos/perfetto/config/power/android_power_config.proto
 
 message AndroidPowerConfig {
   enum BatteryCounters {
     BATTERY_COUNTER_UNSPECIFIED = 0;
-
-    // Coulomb counter.
-    BATTERY_COUNTER_CHARGE = 1;
-
-    // Charge (%).
-    BATTERY_COUNTER_CAPACITY_PERCENT = 2;
-
-    // Instantaneous current.
-    BATTERY_COUNTER_CURRENT = 3;
-
-    // Avg current.
-    BATTERY_COUNTER_CURRENT_AVG = 4;
+    BATTERY_COUNTER_CHARGE = 1;            // Coulomb counter.
+    BATTERY_COUNTER_CAPACITY_PERCENT = 2;  // Charge (%).
+    BATTERY_COUNTER_CURRENT = 3;           // Instantaneous current.
+    BATTERY_COUNTER_CURRENT_AVG = 4;       // Avg current.
   }
   optional uint32 battery_poll_ms = 1;
   repeated BatteryCounters battery_counters = 2;
 
   // Where available enables per-power-rail measurements.
   optional bool collect_power_rails = 3;
-
-  // Provides a breakdown of energy estimation for various subsystem (e.g. GPU).
-  // Available from Android S.
-  optional bool collect_energy_estimation_breakdown = 4;
 }
 
 // End of protos/perfetto/config/power/android_power_config.proto
@@ -571,7 +471,7 @@
 // Begin of protos/perfetto/config/profiling/heapprofd_config.proto
 
 // Configuration for go/heapprofd.
-// Next id: 27
+// Next id: 19
 message HeapprofdConfig {
   message ContinuousDumpConfig {
     // ms to wait before first dump.
@@ -580,33 +480,13 @@
     optional uint32 dump_interval_ms = 6;
   }
 
-  // Sampling rate for all heaps not specified via heap_sampling_intervals.
-  //
-  // These are:
-  // * All heaps if heap_sampling_intervals is empty.
-  // * Those profiled due to all_heaps and not named in heaps if
-  //   heap_sampling_intervals is not empty.
-  // * The implicit libc.malloc heap if heaps is empty.
-  //
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
   //
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#sampling-interval
-  // for more details.
-  //
-  // BUGS
-  // Before Android 12, setting this to 0 would crash the target process.
+  // See https://docs.perfetto.dev/#/heapprofd?id=sampling-interval for more
+  // details.
   optional uint64 sampling_interval_bytes = 1;
 
-  // If less than the given numbers of bytes are left free in the shared
-  // memory buffer, increase sampling interval by a factor of two.
-  // Adaptive sampling is disabled when set to 0.
-  optional uint64 adaptive_sampling_shmem_threshold = 24;
-  // Stop doubling the sampling_interval once the sampling interval has reached
-  // this value.
-  optional uint64 adaptive_sampling_max_sampling_interval_bytes = 25;
-
   // E.g. surfaceflinger, com.android.phone
   // This input is normalized in the following way: if it contains slashes,
   // everything up to the last slash is discarded. If it contains "@",
@@ -619,47 +499,9 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 4;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 26;
-
-  // Which heaps to sample, e.g. "libc.malloc". If left empty, only samples
-  // "malloc".
-  //
-  // Introduced in Android 12.
-  repeated string heaps = 20;
-
-  // Which heaps not to sample, e.g. "libc.malloc". This is useful when used in
-  // combination with all_heaps;
-  //
-  // Introduced in Android 12.
-  repeated string exclude_heaps = 27;
-
-  optional bool stream_allocations = 23;
-
-  // If given, needs to be the same length as heaps and gives the sampling
-  // interval for the respective entry in heaps.
-  //
-  // Otherwise, sampling_interval_bytes is used.
-  //
-  // It is recommended to set sampling_interval_bytes to a reasonable default
-  // value when using this, as a value of 0 for sampling_interval_bytes will
-  // crash the target process before Android 12.
-  //
-  // Introduced in Android 12.
-  repeated uint64 heap_sampling_intervals = 22;
-
-  // Sample all heaps registered by target process. Introduced in Android 12.
-  optional bool all_heaps = 21;
-
   // Profile all processes eligible for profiling on the system.
-  // See
-  // https://perfetto.dev/docs/data-sources/native-heap-profiler#heapprofd-targets
-  // for which processes are eligible.
+  // See https://docs.perfetto.dev/#/heapprofd?id=target-processes for which
+  // processes are eligible.
   //
   // On unmodified userdebug builds, this will lead to system crashes. Zygote
   // will crash when trying to launch a new process as it will have an
@@ -722,8 +564,17 @@
   // Introduced in Android 11.
   optional bool no_running = 11;
 
-  // deprecated idle_allocations.
-  reserved 12;
+  // 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
@@ -773,14 +624,6 @@
   // For watermark based triggering or local debugging.
   repeated uint64 pid = 2;
 
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 7;
-
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 3;
 
@@ -794,107 +637,24 @@
   // * start with /data/app
   // * contain "extracted in memory from Y", where Y matches any of the above
   optional bool dump_smaps = 5;
-
-  // Exclude objects of the following types from the profile. This can be
-  // useful if lots of uninteresting objects, e.g. "sun.misc.Cleaner".
-  repeated string ignored_types = 6;
 }
 
 // End of protos/perfetto/config/profiling/java_hprof_config.proto
 
-// Begin of protos/perfetto/common/perf_events.proto
-
-message PerfEvents {
-  // What event to sample on, and how often. Commented from the perspective of
-  // its use in |PerfEventConfig|.
-  message Timebase {
-    // How often the per-cpu sampling will occur. Not guaranteed to be honored
-    // as the kernel can throttle the sampling rate if it's too high.
-    // If unset, an implementation-defined default is used.
-    oneof interval {
-      // Per-cpu sampling frequency in Hz, as requested from the kernel. Not the
-      // same as 1/period.
-      // Details: the actual sampling will still be based on a period, but the
-      // kernel will dynamically adjust it based on the observed event rate, to
-      // approximate this frequency. Works best with steady-rate events like
-      // timers.
-      uint64 frequency = 2;
-
-      // Per-cpu sampling will occur every |period| counts of |event|.
-      // Prefer |frequency| by default, as it's easier to oversample with a
-      // fixed period.
-      uint64 period = 1;
-    }
-
-    // Counting event to use as a timebase for the sampling.
-    // If unset, implies the CPU timer (SW_CPU_CLOCK) as the event,
-    // which is what you usually want.
-    // See common/perf_events.proto for the definitions.
-    oneof event {
-      Counter counter = 4;
-      Tracepoint tracepoint = 3;
-    }
-  }
-
-  enum Counter {
-    UNKNOWN_COUNTER = 0;
-    // software:
-    SW_CPU_CLOCK = 1;
-    SW_PAGE_FAULTS = 2;
-    // hardware:
-    HW_CPU_CYCLES = 10;
-    HW_INSTRUCTIONS = 11;
-  }
-
-  message Tracepoint {
-    // Group and name for the tracepoint, acceptable forms:
-    // * "sched/sched_switch"
-    // * "sched:sched_switch"
-    optional string name = 1;
-
-    // Optional field-level filter for the tracepoint. Only events matching this
-    // filter will be counted (and therefore contribute to the sampling period).
-    // Example: "prev_pid >= 42 && next_pid == 0".
-    // For full syntax, see kernel documentation on "Event filtering":
-    // https://www.kernel.org/doc/Documentation/trace/events.txt
-    optional string filter = 2;
-  }
-}
-
-// End of protos/perfetto/common/perf_events.proto
-
 // Begin of protos/perfetto/config/profiling/perf_event_config.proto
 
 // Configuration for the traced_perf profiler.
 //
-// Example config for basic cpu profiling:
-//   perf_event_config {
-//     timebase {
-//       frequency: 80
-//     }
-//     callstack_sampling {
-//       scope {
-//         target_cmdline: "surfaceflinger"
-//         target_cmdline: "system_server"
-//       }
-//       kernel_frames: true
-//     }
-//   }
-//
-// Next id: 19
+// At the time of writing, the config options are restricted to the periodic
+// system-wide stack sampling use-case (|all_cpus| must be true).
 message PerfEventConfig {
-  // What event to sample on, and how often.
-  // Defined in common/perf_events.proto.
-  optional PerfEvents.Timebase timebase = 15;
+  // If true, sample events on all CPUs.
+  optional bool all_cpus = 1;
 
-  // If set, the profiler will sample userspace processes' callstacks at the
-  // interval specified by the |timebase|.
-  // If unset, the profiler will record only the event counts.
-  optional CallstackSampling callstack_sampling = 16;
-
-  //
-  // Kernel <-> userspace ring buffer options:
-  //
+  // Per-cpu sampling frequency (requested from the kernel). Not guaranteed to
+  // be honored as the kernel can throttle the sampling rate if it's too high.
+  // If unset, an implementation-defined default is used.
+  optional uint32 sampling_frequency = 2;
 
   // How often the per-cpu ring buffers are read by the producer.
   // If unset, an implementation-defined default is used.
@@ -905,23 +665,27 @@
   // If unset, an implementation-defined default is used.
   optional uint32 ring_buffer_pages = 3;
 
-  //
-  // Daemon's resource usage limits:
-  //
+  // Process ID (TGID) whitelist. If this list is not empty, only matching
+  // samples will be retained. If multiple whitelists and blacklists are
+  // specified by the config, then all of them are evaluated for each sampled
+  // process.
+  repeated int32 target_pid = 4;
 
-  // Drop samples if the heap memory held by the samples in the unwinder queue
-  // is above the given limit. This counts the memory across all concurrent data
-  // sources (not just this one's), and there is no fairness guarantee - the
-  // whole quota might be used up by a concurrent source.
-  optional uint64 max_enqueued_footprint_kb = 17;
+  // Command line whitelist, matched against the
+  // /proc/<pid>/cmdline (not the comm string), with both sides being
+  // "normalized". Normalization is as follows: (1) trim everything beyond the
+  // first null or "@" byte; (2) if the string contains forward slashes, trim
+  // everything up to and including the last one.
+  repeated string target_cmdline = 5;
 
-  // Stop the data source if traced_perf's combined {RssAnon + Swap} memory
-  // footprint exceeds this value.
-  optional uint32 max_daemon_memory_kb = 13;
+  // PID blacklist.
+  repeated int32 exclude_pid = 6;
 
-  //
+  // Command line blacklist. Normalized in the same way as |target_cmdline|.
+  repeated string exclude_cmdline = 7;
+
+  ////////////////////
   // Uncommon options:
-  //
 
   // Timeout for the remote /proc/<pid>/{maps,mem} file descriptors for a
   // sampled process. This is primarily for Android, where this lookup is
@@ -938,80 +702,6 @@
   // processes, and require the memory footprint to be reset periodically.
   // If unset, the cached state will not be cleared.
   optional uint32 unwind_state_clear_period_ms = 10;
-
-  //
-  // Deprecated (superseded by options above):
-  //
-  // Do not set *any* of these fields in new configs.
-  //
-
-  // Note: legacy configs had to set |all_cpus| to true to pass parsing.
-  // We rely on this to detect such configs.
-  optional bool all_cpus = 1;
-  optional uint32 sampling_frequency = 2;
-  optional bool kernel_frames = 12;
-  repeated int32 target_pid = 4;
-  repeated string target_cmdline = 5;
-
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  // Supported on Android 12+.
-  repeated string target_installed_by = 18;
-  repeated int32 exclude_pid = 6;
-  repeated string exclude_cmdline = 7;
-  optional uint32 additional_cmdline_count = 11;
-  // previously |tracepoint|
-  reserved 14;
-
-  //
-  // Sub-messages (nested for generated code namespacing).
-  //
-
-  message CallstackSampling {
-    // Defines a set of processes for which samples are retained/skipped. If
-    // unset, all userspace samples are kept, but beware that it will be very
-    // heavy on the stack unwinder, which might start dropping samples due to
-    // overload.
-    optional Scope scope = 1;
-
-    // If true, callstacks will include the kernel-space frames. Such frames can
-    // be identified by a magical "kernel" string as their mapping name.
-    // Requires traced_perf to be running as root, or kptr_restrict to have been
-    // manually unrestricted. On Android, the platform should do the right thing
-    // on debug builds.
-    // This does *not* disclose KASLR, as only the function names are emitted.
-    optional bool kernel_frames = 2;
-  }
-
-  message Scope {
-    // Process ID (TGID) allowlist. If this list is not empty, only matching
-    // samples will be retained. If multiple allow/deny-lists are
-    // specified by the config, then all of them are evaluated for each sampled
-    // process.
-    repeated int32 target_pid = 1;
-
-    // Command line allowlist, matched against the
-    // /proc/<pid>/cmdline (not the comm string), with both sides being
-    // "normalized". Normalization is as follows: (1) trim everything beyond the
-    // first null or "@" byte; (2) if the string contains forward slashes, trim
-    // everything up to and including the last one.
-    repeated string target_cmdline = 2;
-
-    // List of excluded pids.
-    repeated int32 exclude_pid = 3;
-
-    // List of excluded cmdlines. Normalized in the same way as
-    // |target_cmdline|.
-    repeated string exclude_cmdline = 4;
-
-    // Number of additional command lines to sample. Only those which are
-    // neither explicitly included nor excluded will be considered. Processes
-    // are accepted on a first come, first served basis.
-    optional uint32 additional_cmdline_count = 5;
-  }
 }
 
 // End of protos/perfetto/config/profiling/perf_event_config.proto
@@ -1157,39 +847,6 @@
   VMSTAT_NR_ZSPAGES = 93;
   VMSTAT_NR_ION_HEAP = 94;
   VMSTAT_NR_GPU_HEAP = 95;
-  VMSTAT_ALLOCSTALL_DMA = 96;
-  VMSTAT_ALLOCSTALL_MOVABLE = 97;
-  VMSTAT_ALLOCSTALL_NORMAL = 98;
-  VMSTAT_COMPACT_DAEMON_FREE_SCANNED = 99;
-  VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED = 100;
-  VMSTAT_NR_FASTRPC = 101;
-  VMSTAT_NR_INDIRECTLY_RECLAIMABLE = 102;
-  VMSTAT_NR_ION_HEAP_POOL = 103;
-  VMSTAT_NR_KERNEL_MISC_RECLAIMABLE = 104;
-  VMSTAT_NR_SHADOW_CALL_STACK_BYTES = 105;
-  VMSTAT_NR_SHMEM_HUGEPAGES = 106;
-  VMSTAT_NR_SHMEM_PMDMAPPED = 107;
-  VMSTAT_NR_UNRECLAIMABLE_PAGES = 108;
-  VMSTAT_NR_ZONE_ACTIVE_ANON = 109;
-  VMSTAT_NR_ZONE_ACTIVE_FILE = 110;
-  VMSTAT_NR_ZONE_INACTIVE_ANON = 111;
-  VMSTAT_NR_ZONE_INACTIVE_FILE = 112;
-  VMSTAT_NR_ZONE_UNEVICTABLE = 113;
-  VMSTAT_NR_ZONE_WRITE_PENDING = 114;
-  VMSTAT_OOM_KILL = 115;
-  VMSTAT_PGLAZYFREE = 116;
-  VMSTAT_PGLAZYFREED = 117;
-  VMSTAT_PGREFILL = 118;
-  VMSTAT_PGSCAN_DIRECT = 119;
-  VMSTAT_PGSCAN_KSWAPD = 120;
-  VMSTAT_PGSKIP_DMA = 121;
-  VMSTAT_PGSKIP_MOVABLE = 122;
-  VMSTAT_PGSKIP_NORMAL = 123;
-  VMSTAT_PGSTEAL_DIRECT = 124;
-  VMSTAT_PGSTEAL_KSWAPD = 125;
-  VMSTAT_SWAP_RA = 126;
-  VMSTAT_SWAP_RA_HIT = 127;
-  VMSTAT_WORKINGSET_RESTORE = 128;
 }
 // End of protos/perfetto/common/sys_stats_counters.proto
 
@@ -1232,12 +889,6 @@
     STAT_FORK_COUNT = 4;
   }
   repeated StatCounters stat_counters = 6;
-
-  // Polls /sys/devfreq/*/curfreq every X ms, if non-zero.
-  // This is required to be > 10ms to avoid excessive CPU usage.
-  // This option can be used to record unchanging values.
-  // Updates from frequency changes can come from ftrace/set_clock_rate.
-  optional uint32 devfreq_period_ms = 7;
 }
 
 // End of protos/perfetto/config/sys_stats/sys_stats_config.proto
@@ -1326,18 +977,10 @@
   //       disabled_tags = ["*"]
   //       enabled_tags = ["my_tag"]
   //
-
-  // Default: []
-  repeated string disabled_categories = 1;
-
-  // Default: []
-  repeated string enabled_categories = 2;
-
-  // Default: [“slow”, “debug”]
-  repeated string disabled_tags = 3;
-
-  // Default: []
-  repeated string enabled_tags = 4;
+  repeated string disabled_categories = 1;  // Default: []
+  repeated string enabled_categories = 2;   // Default: []
+  repeated string disabled_tags = 3;  // Default: [“slow”, “debug”]
+  repeated string enabled_tags = 4;   // Default: []
 }
 
 // End of protos/perfetto/config/track_event/track_event_config.proto
@@ -1345,16 +988,7 @@
 // Begin of protos/perfetto/config/data_source_config.proto
 
 // The configuration that is passed to each data source when starting tracing.
-// Next id: 116
 message DataSourceConfig {
-  enum SessionInitiator {
-    SESSION_INITIATOR_UNSPECIFIED = 0;
-    // This trace was initiated from a trusted system app has DUMP and
-    // USAGE_STATS permission. This system app is expected to not expose the
-    // trace to the user of the device.
-    // This is determined by checking the UID initiating the trace.
-    SESSION_INITIATOR_TRUSTED_SYSTEM = 1;
-  };
   // Data source unique name, e.g., "linux.ftrace". This must match
   // the name passed by the data source when it registers (see
   // RegisterDataSource()).
@@ -1381,16 +1015,11 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional bool enable_extra_guardrails = 6;
 
-  // Set by the service to indicate which user initiated this trace.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional SessionInitiator session_initiator = 8;
-
   // Set by the service to indicate which tracing session the data source
   // belongs to. The intended use case for this is checking if two data sources,
   // one of which produces metadata for the other one, belong to the same trace
   // session and hence should be linked together.
   // This field was introduced in Aug 2018 after Android P.
-  // DO NOT SET in consumer as this will be overridden by the service.
   optional uint64 tracing_session_id = 4;
 
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
@@ -1439,16 +1068,6 @@
   // C++ class for it so it can pass around plain C++ objets.
   optional ChromeConfig chrome_config = 101;
 
-  // If an interceptor is specified here, packets for this data source will be
-  // rerouted to the interceptor instead of the main trace buffer. This can be
-  // used, for example, to write trace data into ETW or for logging trace points
-  // to the console.
-  //
-  // Note that interceptors are only supported by data sources registered
-  // through the Perfetto SDK API. Data sources that don't use that API (e.g.,
-  // traced_probes) may not support interception.
-  optional InterceptorConfig interceptor_config = 115;
-
   // 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
   // is part of the platform (i.e. traced service) is supposed to *not* truncate
@@ -1461,8 +1080,7 @@
   // This field is only used for testing.
   optional TestConfig for_testing = 1001;
 
-  // Was |for_testing|. Caused more problems then found.
-  reserved 268435455;
+  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
 }
 
 // End of protos/perfetto/config/data_source_config.proto
@@ -1474,16 +1092,13 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 33.
+// Next id: 30.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
 
-    // |page_size|, now deprecated.
-    reserved 2;
-
-    // |optimize_for|, now deprecated.
-    reserved 3;
+    reserved 2;  // |page_size|, now deprecated.
+    reserved 3;  // |optimize_for|, now deprecated.
 
     enum FillPolicy {
       UNSPECIFIED = 0;
@@ -1551,21 +1166,6 @@
     // only keeps track of the first and the most recent snapshot until
     // ReadBuffers() is called.
     optional uint32 snapshot_interval_ms = 6;
-
-    // Hints to the service that a suspend-aware (i.e. counting time in suspend)
-    // clock should be used for periodic snapshots of service-emitted events.
-    // This means, if a snapshot *should* have happened during suspend, it will
-    // happen immediately after the device resumes.
-    //
-    // Choosing a clock like this is done on best-effort basis; not all
-    // platforms (e.g. Windows) expose a clock which can be used for periodic
-    // tasks counting suspend. If such a clock is not available, the service
-    // falls back to the best-available alternative.
-    //
-    // Introduced in Android S.
-    // TODO(lalitm): deprecate this in T and make this the default if nothing
-    // crashes in S.
-    optional bool prefer_suspend_clock_for_snapshot = 7;
   }
   optional BuiltinDataSource builtin_data_sources = 20;
 
@@ -1649,14 +1249,13 @@
   optional uint64 max_file_size_bytes = 10;
 
   // Contains flags which override the default values of the guardrails inside
-  // Perfetto.
+  // Perfetto. These values are only affect userdebug builds.
   message GuardrailOverrides {
     // Override the default limit (in bytes) for uploading data to server within
     // a 24 hour period.
-    // On R-, this override only affected userdebug builds. Since S, it also
-    // affects user builds.
     optional uint64 max_upload_per_day_bytes = 1;
   }
+
   optional GuardrailOverrides guardrail_overrides = 11;
 
   // When true, data sources are not started until an explicit call to
@@ -1681,22 +1280,12 @@
   // Default 5s.
   optional uint32 data_source_stop_timeout_ms = 23;
 
-  // |disable_clock_snapshotting| moved.
-  reserved 15;
+  reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
   // trace ends to notify it about the trace readiness.
   optional bool notify_traceur = 16;
 
-  // Android-only. If set to a value > 0, marks the trace session as a candidate
-  // for being attached to a bugreport. This field effectively acts as a z-index
-  // for bugreports. When Android's dumpstate runs perfetto
-  // --save-for-bugreport, traced will pick the tracing session with the highest
-  // score (score <= 0 is ignored), will steal its contents, save the trace into
-  // a known path and stop prematurely.
-  // This field was introduced in Android S.
-  optional int32 bugreport_score = 30;
-
   // Triggers allow producers to start or stop the tracing session when an event
   // occurs.
   //
@@ -1732,7 +1321,7 @@
       // The producer must specify this name to activate the trigger.
       optional string name = 1;
 
-      // An std::regex that will match the producer that can activate this
+      // The a std::regex that will match the producer that can activate this
       // trigger. This is optional. If unset any producers can activate this
       // trigger.
       optional string producer_name_regex = 2;
@@ -1740,24 +1329,6 @@
       // After a trigger is received either in START_TRACING or STOP_TRACING
       // mode then the trace will end |stop_delay_ms| after triggering.
       optional uint32 stop_delay_ms = 3;
-
-      // Limits the number of traces this trigger can start/stop in a rolling
-      // 24 hour window. If this field is unset or zero, no limit is applied and
-      // activiation of this trigger *always* starts/stops the trace.
-      optional uint32 max_per_24_h = 4;
-
-      // A value between 0 and 1 which encodes the probability of skipping a
-      // trigger with this name. This is useful for reducing the probability
-      // of high-frequency triggers from dominating trace finaization. If this
-      // field is unset or zero, the trigger will *never* be skipped. If this
-      // field is greater than or equal to 1, this trigger will *always* be
-      // skipped i.e. it will be as if this trigger was never included in the
-      // first place.
-      // This probability check is applied *before* any other limits. For
-      // example, if |max_per_24_h| is also set, first we will check if the
-      // probability bar is met and only then will we check the |max_per_24_h|
-      // limit.
-      optional double skip_probability = 5;
     }
     // A list of triggers which are related to this configuration. If ANY
     // trigger is seen then an action will be performed based on |trigger_mode|.
@@ -1816,68 +1387,27 @@
   }
   optional CompressionType compression_type = 24;
 
-  // Android-only. Not for general use. If set, saves the trace into an
-  // incident. This field is read by perfetto_cmd, rather than the tracing
-  // service. This field must be set when passing the --upload flag to
-  // perfetto_cmd.
+  // Android-only. Debug builds only. Not for general use. If set, saves a
+  // Dropbox trace into an incident. This field is read by perfetto_cmd, rather
+  // than the tracing service. All fields are mandatory.
   message IncidentReportConfig {
-    // In this message, either:
-    //  * all of |destination_package|, |destination_class| and |privacy_level|
-    //    must be set.
-    //  * |skip_incidentd| must be explicitly set to true.
-
     optional string destination_package = 1;
     optional string destination_class = 2;
     // Level of filtering in the requested incident. See |Destination| in
     // frameworks/base/core/proto/android/privacy.proto.
     optional int32 privacy_level = 3;
-
-    // If true, then skips saving the trace to incidentd.
-    //
-    // This flag is useful in testing (e.g. Perfetto-statsd integration tests)
-    // or when we explicitly don't want traces to go to incidentd even when they
-    // usually would (e.g. configs deployed using statsd but only used for
-    // inclusion in bugreports using |bugreport_score|).
-    //
-    // The motivation for having this flag, instead of just not setting
-    // |incident_report_config|, is prevent accidents where
-    // |incident_report_config| is omitted by mistake.
-    optional bool skip_incidentd = 5;
-
     // If true, do not write the trace into dropbox (i.e. incident only).
     // Otherwise, write to both dropbox and incident.
-    // TODO(lalitm): remove this field as we no longer use Dropbox.
-    optional bool skip_dropbox = 4 [deprecated = true];
+    optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
 
-  enum StatsdLogging {
-    STATSD_LOGGING_UNSPECIFIED = 0;
-    STATSD_LOGGING_ENABLED = 1;
-    STATSD_LOGGING_DISABLED = 2;
-  }
-
-  // Android-only. Not for general use. If specified, sets the logging to statsd
-  // of guardrails and checkpoints in the tracing service. perfetto_cmd sets
-  // this to enabled (if not explicitly set in the config) when specifying
-  // --upload.
-  optional StatsdLogging statsd_logging = 31;
-
   // DEPRECATED. Was trace_uuid, use trace_uuid_msb and trace_uuid_lsb instead.
   reserved 26;
   // An identifier clients can use to tie this trace to other logging.
   // Alternative encoding of trace_uuid as two int64s.
   optional int64 trace_uuid_msb = 27;
   optional int64 trace_uuid_lsb = 28;
-
-  // When set applies a post-filter to the trace contents using the filter
-  // provided. The filter is applied at ReadBuffers() time and works both in the
-  // case of IPC readback and write_into_file. This filter can be generated
-  // using `tools/proto_filter -s schema.proto -F filter_out.bytes` or
-  // `-T filter_out.escaped_string` (for .pbtx).
-  // Introduced in Android S. See go/trace-filtering for design.
-  message TraceFilter { optional bytes bytecode = 1; }
-  optional TraceFilter trace_filter = 32;
 }
 
 // End of protos/perfetto/config/trace_config.proto
@@ -2024,15 +1554,6 @@
   // Packets that failed validation of the TrustedPacket. If this is > 0, there
   // is a bug in the producer.
   optional uint64 invalid_packets = 10;
-
-  // This is set only when the TraceConfig specifies a TraceFilter.
-  message FilterStats {
-    optional uint64 input_packets = 1;
-    optional uint64 input_bytes = 2;
-    optional uint64 output_bytes = 3;
-    optional uint64 errors = 4;
-  }
-  optional FilterStats filter_stats = 11;
 }
 
 // End of protos/perfetto/common/trace_stats.proto
@@ -2098,175 +1619,6 @@
 
 // End of protos/perfetto/trace/android/android_log.proto
 
-// Begin of protos/perfetto/trace/android/frame_timeline_event.proto
-
-// Generated by SurfaceFlinger's FrameTimeline (go/adaptive-scheduling-fr).
-// Used in comparing the expected timeline of a frame to the actual timeline.
-// Key terms:
-//    1) DisplayFrame - represents SurfaceFlinger's work on a frame(composited)
-//    2) SurfaceFrame - represents App's work on its frame
-//    3) Timeline = start to end of a component's(app/SF) work on a frame.
-// SurfaceFlinger composites frames from many apps together, so
-//    One DisplayFrame can map to N SurfaceFrame(s)
-// This relationship can be reconstructed by using
-//    DisplayFrame.token = SurfaceFrame.display_frame_token
-message FrameTimelineEvent {
-  // Specifies the reason(s) most likely to have caused the jank.
-  // Used as a bitmask.
-  enum JankType {
-    JANK_UNSPECIFIED = 0;
-    JANK_NONE = 1;
-    JANK_SF_SCHEDULING = 2;
-    JANK_PREDICTION_ERROR = 4;
-    JANK_DISPLAY_HAL = 8;
-    JANK_SF_CPU_DEADLINE_MISSED = 16;
-    JANK_SF_GPU_DEADLINE_MISSED = 32;
-    JANK_APP_DEADLINE_MISSED = 64;
-    JANK_BUFFER_STUFFING = 128;
-    JANK_UNKNOWN = 256;
-    JANK_SF_STUFFING = 512;
-  };
-
-  // Specifies how a frame was presented on screen w.r.t. timing.
-  // Can be different for SurfaceFrame and DisplayFrame.
-  enum PresentType {
-    PRESENT_UNSPECIFIED = 0;
-    PRESENT_ON_TIME = 1;
-    PRESENT_LATE = 2;
-    PRESENT_EARLY = 3;
-    PRESENT_DROPPED = 4;
-    PRESENT_UNKNOWN = 5;
-  };
-
-  // Specifies if the predictions for the frame are still valid, expired or
-  // unknown.
-  enum PredictionType {
-    PREDICTION_UNSPECIFIED = 0;
-    PREDICTION_VALID = 1;
-    PREDICTION_EXPIRED = 2;
-    PREDICTION_UNKNOWN = 3;
-  };
-
-  // Indicates the start of expected timeline slice for SurfaceFrames.
-  message ExpectedSurfaceFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by the app for its work. Can be shared between multiple
-    // layers of the same app (example: pip mode).
-    optional int64 token = 2;
-    // The corresponding DisplayFrame token is required to link the App's work
-    // with SurfaceFlinger's work. Many SurfaceFrames can be mapped to a single
-    // DisplayFrame.
-    // this.display_frame_token = DisplayFrame.token
-    optional int64 display_frame_token = 3;
-
-    // Pid of the app. Used in creating the timeline tracks (and slices) inside
-    // the respective process track group.
-    optional int32 pid = 4;
-    optional string layer_name = 5;
-  };
-
-  // Indicates the start of actual timeline slice for SurfaceFrames. Also
-  // includes the jank information.
-  message ActualSurfaceFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by the app for its work. Can be shared between multiple
-    // layers of the same app (example: pip mode).
-    optional int64 token = 2;
-    // The corresponding DisplayFrame token is required to link the App's work
-    // with SurfaceFlinger's work. Many SurfaceFrames can be mapped to a single
-    // DisplayFrame.
-    // this.display_frame_token = DisplayFrame.token
-    optional int64 display_frame_token = 3;
-
-    // Pid of the app. Used in creating the timeline tracks (and slices) inside
-    // the respective process track group.
-    optional int32 pid = 4;
-    optional string layer_name = 5;
-
-    optional PresentType present_type = 6;
-    optional bool on_time_finish = 7;
-    optional bool gpu_composition = 8;
-    // A bitmask of JankType. More than one reason can be attributed to a janky
-    // frame.
-    optional int32 jank_type = 9;
-    optional PredictionType prediction_type = 10;
-    optional bool is_buffer = 11;
-  };
-
-  // Indicates the start of expected timeline slice for DisplayFrames.
-  message ExpectedDisplayFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by SurfaceFlinger for its work
-    // this.token = SurfaceFrame.display_frame_token
-    optional int64 token = 2;
-
-    // Pid of SurfaceFlinger. Used in creating the timeline tracks (and slices)
-    // inside the SurfaceFlinger process group.
-    optional int32 pid = 3;
-  };
-
-  // Indicates the start of actual timeline slice for DisplayFrames. Also
-  // includes the jank information.
-  message ActualDisplayFrameStart {
-    // Cookie used to correlate between the start and end messages of the same
-    // frame. Since all values except the ts are same for start and end, cookie
-    // helps in preventing redundant data transmission.
-    // The same cookie is used only by start and end messages of a single frame
-    // and is otherwise unique.
-    optional int64 cookie = 1;
-
-    // Token received by SurfaceFlinger for its work
-    // this.token = SurfaceFrame.display_frame_token
-    optional int64 token = 2;
-
-    // Pid of SurfaceFlinger. Used in creating the timeline tracks (and slices)
-    // inside the SurfaceFlinger process group.
-    optional int32 pid = 3;
-
-    optional PresentType present_type = 4;
-    optional bool on_time_finish = 5;
-    optional bool gpu_composition = 6;
-    // A bitmask of JankType. More than one reason can be attributed to a janky
-    // frame.
-    optional int32 jank_type = 7;
-    optional PredictionType prediction_type = 8;
-  };
-
-  // FrameEnd just sends the cookie to indicate that the corresponding
-  // <display/surface>frame slice's end.
-  message FrameEnd { optional int64 cookie = 1; };
-
-  oneof event {
-    ExpectedDisplayFrameStart expected_display_frame_start = 1;
-    ActualDisplayFrameStart actual_display_frame_start = 2;
-
-    ExpectedSurfaceFrameStart expected_surface_frame_start = 3;
-    ActualSurfaceFrameStart actual_surface_frame_start = 4;
-
-    FrameEnd frame_end = 5;
-  }
-}
-
-// End of protos/perfetto/trace/android/frame_timeline_event.proto
-
 // Begin of protos/perfetto/trace/android/gpu_mem_event.proto
 
 // Generated by Android's GpuService.
@@ -2289,10 +1641,8 @@
     POST = 3;
     ACQUIRE_FENCE = 4;
     LATCH = 5;
-    // HWC will compose this buffer
-    HWC_COMPOSITION_QUEUED = 6;
-    // renderEngine composition
-    FALLBACK_COMPOSITION = 7;
+    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
+    FALLBACK_COMPOSITION = 7;    // renderEngine composition
     PRESENT_FENCE = 8;
     RELEASE_FENCE = 9;
     MODIFY = 10;
@@ -2393,11 +1743,6 @@
   // Version code of Chrome used by Android's Play Store. This field is only set
   // on Android.
   optional int32 chrome_version_code = 2;
-
-  // Comma separated list of enabled categories for tracing. The list of
-  // possible category strings are listed in code
-  // base/trace_event/builtin_categories.h.
-  optional string enabled_categories = 3;
 }
 
 // Metadata related to background tracing scenarios, states and triggers.
@@ -2435,15 +1780,10 @@
         NAVIGATION = 2;
         STARTUP = 3;
         REACHED_CODE = 4;
-        CONTENT_TRIGGER = 5;
 
         TEST_RULE = 1000;
       }
       optional EventType event_type = 1;
-
-      // If |event_type| is CONTENT_TRIGGER, then this stores the hash of the
-      // content-trigger that actually fired.
-      optional fixed64 content_trigger_name_hash = 2;
     }
     optional NamedRule named_rule = 3;
   }
@@ -2543,9 +1883,7 @@
 message ChromeLegacyJsonTrace {
   enum TraceType {
     USER_TRACE = 0;
-
-    // Deprecated.
-    SYSTEM_TRACE = 1;
+    SYSTEM_TRACE = 1;  // Deprecated.
   }
   optional TraceType type = 1;
   optional string data = 2;
@@ -2554,8 +1892,6 @@
 message ChromeEventBundle {
   // Deprecated, use TrackEvent protos instead.
   repeated ChromeTraceEvent trace_events = 1 [deprecated = true];
-  // TODO(ssid): This should be deprecated in favor of ChromeMetadataPacket
-  // which contains typed fields.
   repeated ChromeMetadata metadata = 2;
   // ftrace output from CrOS and Cast system tracing agents.
   // TODO(eseckler): Replace system traces with native perfetto service.
@@ -2628,200 +1964,6 @@
 
 // End of protos/perfetto/trace/clock_snapshot.proto
 
-// Begin of protos/perfetto/common/descriptor.proto
-
-// The protocol compiler can output a FileDescriptorSet containing the .proto
-// files it parses.
-message FileDescriptorSet {
-  repeated FileDescriptorProto file = 1;
-}
-
-// Describes a complete .proto file.
-message FileDescriptorProto {
-  // file name, relative to root of source tree
-  optional string name = 1;
-  // e.g. "foo", "foo.bar", etc.
-  optional string package = 2;
-
-  // Names of files imported by this file.
-  repeated string dependency = 3;
-  // Indexes of the public imported files in the dependency list above.
-  repeated int32 public_dependency = 10;
-  // Indexes of the weak imported files in the dependency list.
-  // For Google-internal migration only. Do not use.
-  repeated int32 weak_dependency = 11;
-
-  // All top-level definitions in this file.
-  repeated DescriptorProto message_type = 4;
-  repeated EnumDescriptorProto enum_type = 5;
-  repeated FieldDescriptorProto extension = 7;
-
-  reserved 6;
-  reserved 8;
-  reserved 9;
-  reserved 12;
-}
-
-// Describes a message type.
-message DescriptorProto {
-  optional string name = 1;
-
-  repeated FieldDescriptorProto field = 2;
-  repeated FieldDescriptorProto extension = 6;
-
-  repeated DescriptorProto nested_type = 3;
-  repeated EnumDescriptorProto enum_type = 4;
-
-  reserved 5;
-
-  repeated OneofDescriptorProto oneof_decl = 8;
-
-  reserved 7;
-
-  // Range of reserved tag numbers. Reserved tag numbers may not be used by
-  // fields or extension ranges in the same message. Reserved ranges may
-  // not overlap.
-  message ReservedRange {
-    // Inclusive.
-    optional int32 start = 1;
-    // Exclusive.
-    optional int32 end = 2;
-  }
-  repeated ReservedRange reserved_range = 9;
-  // Reserved field names, which may not be used by fields in the same message.
-  // A given name may only be reserved once.
-  repeated string reserved_name = 10;
-}
-
-// Describes a field within a message.
-message FieldDescriptorProto {
-  enum Type {
-    // 0 is reserved for errors.
-    // Order is weird for historical reasons.
-    TYPE_DOUBLE = 1;
-    TYPE_FLOAT = 2;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
-    // negative values are likely.
-    TYPE_INT64 = 3;
-    TYPE_UINT64 = 4;
-    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
-    // negative values are likely.
-    TYPE_INT32 = 5;
-    TYPE_FIXED64 = 6;
-    TYPE_FIXED32 = 7;
-    TYPE_BOOL = 8;
-    TYPE_STRING = 9;
-    // Tag-delimited aggregate.
-    // Group type is deprecated and not supported in proto3. However, Proto3
-    // implementations should still be able to parse the group wire format and
-    // treat group fields as unknown fields.
-    TYPE_GROUP = 10;
-    // Length-delimited aggregate.
-    TYPE_MESSAGE = 11;
-
-    // New in version 2.
-    TYPE_BYTES = 12;
-    TYPE_UINT32 = 13;
-    TYPE_ENUM = 14;
-    TYPE_SFIXED32 = 15;
-    TYPE_SFIXED64 = 16;
-    // Uses ZigZag encoding.
-    TYPE_SINT32 = 17;
-    // Uses ZigZag encoding.
-    TYPE_SINT64 = 18;
-  };
-
-  enum Label {
-    // 0 is reserved for errors
-    LABEL_OPTIONAL = 1;
-    LABEL_REQUIRED = 2;
-    LABEL_REPEATED = 3;
-  };
-
-  optional string name = 1;
-  optional int32 number = 3;
-  optional Label label = 4;
-
-  // If type_name is set, this need not be set.  If both this and type_name
-  // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
-  optional Type type = 5;
-
-  // For message and enum types, this is the name of the type.  If the name
-  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
-  // rules are used to find the type (i.e. first the nested types within this
-  // message are searched, then within the parent, on up to the root
-  // 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;
-
-  // For numeric types, contains the original text representation of the value.
-  // For booleans, "true" or "false".
-  // For strings, contains the default text contents (not escaped in any way).
-  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
-  // TODO(kenton):  Base-64 encode?
-  optional string default_value = 7;
-
-  // If set, gives the index of a oneof in the containing type's oneof_decl
-  // list.  This field is a member of that oneof.
-  optional int32 oneof_index = 9;
-
-  reserved 10;
-
-  reserved 8;
-}
-
-// Describes a oneof.
-message OneofDescriptorProto {
-  optional string name = 1;
-  optional OneofOptions options = 2;
-}
-
-// Describes an enum type.
-message EnumDescriptorProto {
-  optional string name = 1;
-
-  repeated EnumValueDescriptorProto value = 2;
-
-  reserved 3;
-  reserved 4;
-
-  // Reserved enum value names, which may not be reused. A given name may only
-  // be reserved once.
-  repeated string reserved_name = 5;
-}
-
-// Describes a value within an enum.
-message EnumValueDescriptorProto {
-  optional string name = 1;
-  optional int32 number = 2;
-
-  reserved 3;
-}
-
-message OneofOptions {
-  reserved 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-// End of protos/perfetto/common/descriptor.proto
-
-// Begin of protos/perfetto/trace/extension_descriptor.proto
-
-// This message contains descriptors used to parse extension fields of
-// TrackEvent.
-//
-// See docs/design-docs/extensions.md for more details.
-message ExtensionDescriptor {
-  optional FileDescriptorSet extension_set = 1;
-}
-
-// End of protos/perfetto/trace/extension_descriptor.proto
-
 // Begin of protos/perfetto/trace/filesystem/inode_file_map.proto
 
 // Represents the mapping between inode numbers in a block device and their path
@@ -3189,64 +2331,6 @@
 
 // End of protos/perfetto/trace/ftrace/compaction.proto
 
-// Begin of protos/perfetto/trace/ftrace/cpuhp.proto
-
-message CpuhpExitFtraceEvent {
-  optional uint32 cpu = 1;
-  optional int32 idx = 2;
-  optional int32 ret = 3;
-  optional int32 state = 4;
-}
-message CpuhpMultiEnterFtraceEvent {
-  optional uint32 cpu = 1;
-  optional uint64 fun = 2;
-  optional int32 idx = 3;
-  optional int32 target = 4;
-}
-message CpuhpEnterFtraceEvent {
-  optional uint32 cpu = 1;
-  optional uint64 fun = 2;
-  optional int32 idx = 3;
-  optional int32 target = 4;
-}
-message CpuhpLatencyFtraceEvent {
-  optional uint32 cpu = 1;
-  optional int32 ret = 2;
-  optional uint32 state = 3;
-  optional uint64 time = 4;
-}
-message CpuhpPauseFtraceEvent {
-  optional uint32 active_cpus = 1;
-  optional uint32 cpus = 2;
-  optional uint32 pause = 3;
-  optional uint32 time = 4;
-}
-
-// End of protos/perfetto/trace/ftrace/cpuhp.proto
-
-// Begin of protos/perfetto/trace/ftrace/dmabuf_heap.proto
-
-message DmaHeapStatFtraceEvent {
-  optional uint64 inode = 1;
-  optional int64 len = 2;
-  optional uint64 total_allocated = 3;
-}
-
-// End of protos/perfetto/trace/ftrace/dmabuf_heap.proto
-
-// Begin of protos/perfetto/trace/ftrace/dpu.proto
-
-message DpuTracingMarkWriteFtraceEvent {
-  optional int32 pid = 1;
-  optional string trace_name = 2;
-  optional uint32 trace_begin = 3;
-  optional string name = 4;
-  optional uint32 type = 5;
-  optional int32 value = 6;
-}
-
-// End of protos/perfetto/trace/ftrace/dpu.proto
-
 // Begin of protos/perfetto/trace/ftrace/ext4.proto
 
 message Ext4DaWriteBeginFtraceEvent {
@@ -4153,16 +3237,6 @@
 
 // End of protos/perfetto/trace/ftrace/f2fs.proto
 
-// Begin of protos/perfetto/trace/ftrace/fastrpc.proto
-
-message FastrpcDmaStatFtraceEvent {
-  optional int32 cid = 1;
-  optional int64 len = 2;
-  optional uint64 total_allocated = 3;
-}
-
-// End of protos/perfetto/trace/ftrace/fastrpc.proto
-
 // Begin of protos/perfetto/trace/ftrace/fence.proto
 
 message FenceInitFtraceEvent {
@@ -4220,17 +3294,6 @@
 
 // End of protos/perfetto/trace/ftrace/ftrace.proto
 
-// Begin of protos/perfetto/trace/ftrace/g2d.proto
-
-message G2dTracingMarkWriteFtraceEvent {
-  optional int32 pid = 1;
-  optional string name = 4;
-  optional uint32 type = 5;
-  optional int32 value = 6;
-}
-
-// End of protos/perfetto/trace/ftrace/g2d.proto
-
 // Begin of protos/perfetto/trace/ftrace/generic.proto
 
 // This generic proto is used to output events in the trace
@@ -4625,17 +3688,6 @@
 
 // End of protos/perfetto/trace/ftrace/lowmemorykiller.proto
 
-// Begin of protos/perfetto/trace/ftrace/mali.proto
-
-message MaliTracingMarkWriteFtraceEvent {
-  optional string name = 1;
-  optional int32 pid = 2;
-  optional uint32 type = 3;
-  optional int32 value = 4;
-}
-
-// End of protos/perfetto/trace/ftrace/mali.proto
-
 // Begin of protos/perfetto/trace/ftrace/mdss.proto
 
 message MdpCmdKickoffFtraceEvent {
@@ -4968,26 +4020,9 @@
   optional int32 pid = 2;
   optional int32 prio = 3;
 }
-message SchedPiSetprioFtraceEvent {
-  optional string comm = 1;
-  optional int32 newprio = 2;
-  optional int32 oldprio = 3;
-  optional int32 pid = 4;
-}
 
 // End of protos/perfetto/trace/ftrace/sched.proto
 
-// Begin of protos/perfetto/trace/ftrace/scm.proto
-
-message ScmCallStartFtraceEvent {
-  optional uint32 arginfo = 1;
-  optional uint64 x0 = 2;
-  optional uint64 x5 = 3;
-}
-message ScmCallEndFtraceEvent {}
-
-// End of protos/perfetto/trace/ftrace/scm.proto
-
 // Begin of protos/perfetto/trace/ftrace/sde.proto
 
 message SdeTracingMarkWriteFtraceEvent {
@@ -4997,49 +4032,6 @@
   optional int32 value = 4;
   optional uint32 trace_begin = 5;
 }
-message SdeSdeEvtlogFtraceEvent {
-  optional string evtlog_tag = 1;
-  optional int32 pid = 2;
-  optional uint32 tag_id = 3;
-}
-message SdeSdePerfCalcCrtcFtraceEvent {
-  optional uint64 bw_ctl_ebi = 1;
-  optional uint64 bw_ctl_llcc = 2;
-  optional uint64 bw_ctl_mnoc = 3;
-  optional uint32 core_clk_rate = 4;
-  optional uint32 crtc = 5;
-  optional uint64 ib_ebi = 6;
-  optional uint64 ib_llcc = 7;
-  optional uint64 ib_mnoc = 8;
-}
-message SdeSdePerfCrtcUpdateFtraceEvent {
-  optional uint64 bw_ctl_ebi = 1;
-  optional uint64 bw_ctl_llcc = 2;
-  optional uint64 bw_ctl_mnoc = 3;
-  optional uint32 core_clk_rate = 4;
-  optional uint32 crtc = 5;
-  optional int32 params = 6;
-  optional uint64 per_pipe_ib_ebi = 7;
-  optional uint64 per_pipe_ib_llcc = 8;
-  optional uint64 per_pipe_ib_mnoc = 9;
-  optional uint32 stop_req = 10;
-  optional uint32 update_bus = 11;
-  optional uint32 update_clk = 12;
-}
-message SdeSdePerfSetQosLutsFtraceEvent {
-  optional uint32 fl = 1;
-  optional uint32 fmt = 2;
-  optional uint64 lut = 3;
-  optional uint32 lut_usage = 4;
-  optional uint32 pnum = 5;
-  optional uint32 rt = 6;
-}
-message SdeSdePerfUpdateBusFtraceEvent {
-  optional uint64 ab_quota = 1;
-  optional uint32 bus_id = 2;
-  optional int32 client = 3;
-  optional uint64 ib_quota = 4;
-}
 
 // End of protos/perfetto/trace/ftrace/sde.proto
 
@@ -5107,21 +4099,6 @@
 
 // End of protos/perfetto/trace/ftrace/task.proto
 
-// Begin of protos/perfetto/trace/ftrace/thermal.proto
-
-message ThermalTemperatureFtraceEvent {
-  optional int32 id = 1;
-  optional int32 temp = 2;
-  optional int32 temp_prev = 3;
-  optional string thermal_zone = 4;
-}
-message CdevUpdateFtraceEvent {
-  optional uint64 target = 1;
-  optional string type = 2;
-}
-
-// End of protos/perfetto/trace/ftrace/thermal.proto
-
 // Begin of protos/perfetto/trace/ftrace/vmscan.proto
 
 message MmVmscanDirectReclaimBeginFtraceEvent {
@@ -5529,27 +4506,7 @@
     IonStatFtraceEvent ion_stat = 335;
     IonBufferCreateFtraceEvent ion_buffer_create = 336;
     IonBufferDestroyFtraceEvent ion_buffer_destroy = 337;
-    ScmCallStartFtraceEvent scm_call_start = 338;
-    ScmCallEndFtraceEvent scm_call_end = 339;
     GpuMemTotalFtraceEvent gpu_mem_total = 340;
-    ThermalTemperatureFtraceEvent thermal_temperature = 341;
-    CdevUpdateFtraceEvent cdev_update = 342;
-    CpuhpExitFtraceEvent cpuhp_exit = 343;
-    CpuhpMultiEnterFtraceEvent cpuhp_multi_enter = 344;
-    CpuhpEnterFtraceEvent cpuhp_enter = 345;
-    CpuhpLatencyFtraceEvent cpuhp_latency = 346;
-    FastrpcDmaStatFtraceEvent fastrpc_dma_stat = 347;
-    DpuTracingMarkWriteFtraceEvent dpu_tracing_mark_write = 348;
-    G2dTracingMarkWriteFtraceEvent g2d_tracing_mark_write = 349;
-    MaliTracingMarkWriteFtraceEvent mali_tracing_mark_write = 350;
-    DmaHeapStatFtraceEvent dma_heap_stat = 351;
-    CpuhpPauseFtraceEvent cpuhp_pause = 352;
-    SchedPiSetprioFtraceEvent sched_pi_setprio = 353;
-    SdeSdeEvtlogFtraceEvent sde_sde_evtlog = 354;
-    SdeSdePerfCalcCrtcFtraceEvent sde_sde_perf_calc_crtc = 355;
-    SdeSdePerfCrtcUpdateFtraceEvent sde_sde_perf_crtc_update = 356;
-    SdeSdePerfSetQosLutsFtraceEvent sde_sde_perf_set_qos_luts = 357;
-    SdeSdePerfUpdateBusFtraceEvent sde_sde_perf_update_bus = 358;
   }
 }
 
@@ -5656,17 +4613,6 @@
 
   // Per-CPU stats (one entry for each CPU).
   repeated FtraceCpuStats cpu_stats = 2;
-
-  // When FtraceConfig.symbolize_ksyms = true, this records the number of
-  // symbols parsed from /proc/kallsyms, whether they have been seen in the
-  // trace or not. It can be used to debug kptr_restrict or security-related
-  // errors.
-  // Note: this will be valid only when phase = END_OF_TRACE. The symbolizer is
-  // initialized. When START_OF_TRACE is emitted it is not ready yet.
-  optional uint32 kernel_symbols_parsed = 3;
-
-  // The memory used by the kernel symbolizer (KernelSymbolMap.size_bytes()).
-  optional uint32 kernel_symbols_mem_kb = 4;
 }
 
 // End of protos/perfetto/trace/ftrace/ftrace_stats.proto
@@ -5717,68 +4663,45 @@
 
 // Begin of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
 
-// next id: 15
+// next id: 13
 message GpuRenderStageEvent {
   // required. Unique ID for the event.
   optional uint64 event_id = 1;
 
-  // optional. Duration of the event in nanoseconds. If unset, this is a
-  // single time point event.
+  // 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.
-  // InternedGpuRenderStageSpecification
-  optional uint64 hw_queue_iid = 13;
+  optional int32 hw_queue_id = 3;
 
   // required. ID to a render stage description in the specifications.
-  // InternedGpuRenderStageSpecification
-  optional uint64 stage_iid = 14;
+  optional int32 stage_id = 4;
 
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 11;
-
-  // required. Graphics context for the event.
-  // For OpenGL, this is the GL context.
-  // For Vulkan, this is the VkDevice.
+  // required. GL context/VK device.
   optional uint64 context = 5;
 
   // optional. The render target for this event.
-  // For OpenGL, this is the GL frame buffer handle.
-  // For Vulkan, this is the VkFrameBuffer handle.
   optional uint64 render_target_handle = 8;
 
-  // optional. Submission ID generated by the UMD.
-  // For OpenGL, the ID should map to an API submission (e.g., glFlush,
-  // glFinish, eglSwapBufffers) event.  The set of submissions to the HW due
-  // to a single API submission should share the same ID.
-  // For Vulkan, it should map 1:1 with a vkQueueSubmit.
+  // 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. Should map 1:1 with a
+  // vkQueueSubmit.
   optional uint32 submission_id = 10;
 
-  // optional. Additional data for the user. This may include attributes for
-  // the event like resource ids, shaders, etc.
+  // 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;
 
-  // VULKAN SPECIFICS
-
-  // optional. The Vulkan render pass handle.
-  optional uint64 render_pass_handle = 9;
-
-  // optional. A bit mask representing which render subpasses contributed to
-  // this render stage event.  Subpass index 0 is represented by setting the
-  // LSB of the mask.  Additional mask can be added for subpass index greater
-  // than 63.
-  repeated uint64 render_subpass_index_mask = 15;
-
-  // optional. The Vulkan command buffer handle.
-  optional uint64 command_buffer_handle = 12;
-
-  // DEPRECATED
-
-  // Deprecated.  Use InternedGpuRenderStageSpecification instead.
   // The first trace packet of each session should include a Specifications
   // to enumerate *all* IDs that will be used. The timestamp of this packet
   // must be earlier than all other packets. Only one packet with Specifications
@@ -5801,49 +4724,15 @@
     // Labels to categorize render stage(binning, render, compute etc).
     repeated Description stage = 3;
   }
-  // Deprecated.  Use hw_queue_iid and stage_iid to refer to
-  // InternedGpuRenderStageSpecification instead.
-  optional Specifications specifications = 7 [deprecated = true];
+  optional Specifications specifications = 7;
 
-  // Deprecated. Use hw_queue_iid instead;
-  optional int32 hw_queue_id = 3 [deprecated = true];
-
-  // Deprecated. Use stage_iid instead;
-  optional int32 stage_id = 4 [deprecated = true];
+  // optional. Identifier for GPU in a multi-gpu device.
+  optional int32 gpu_id = 11;
 
   // Extension for vendor's custom proto.
   extensions 100;
 }
 
-// Interned data.
-
-// The iid is the numeric value of either the GL Context or the VkDevice
-// handle.
-message InternedGraphicsContext {
-  optional uint64 iid = 1;
-  optional int32 pid = 2;
-  enum Api {
-    UNDEFINED = 0;
-    OPEN_GL = 1;
-    VULKAN = 2;
-    OPEN_CL = 3;
-  }
-  optional Api api = 3;
-}
-
-message InternedGpuRenderStageSpecification {
-  optional uint64 iid = 1;
-  optional string name = 2;
-  optional string description = 3;
-
-  enum RenderStageCategory {
-    OTHER = 0;
-    GRAPHICS = 1;
-    COMPUTE = 2;
-  }
-  optional RenderStageCategory category = 4;
-}
-
 // End of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
 
 // Begin of protos/perfetto/trace/gpu/vulkan_api_event.proto
@@ -5922,21 +4811,11 @@
 
   enum Operation {
     OP_UNSPECIFIED = 0;
-
-    // alloc, create
-    OP_CREATE = 1;
-
-    // free, destroy(non-bound)
-    OP_DESTROY = 2;
-
-    // bind buffer and image
-    OP_BIND = 3;
-
-    // destroy (bound)
-    OP_DESTROY_BOUND = 4;
-
-    // only annotations
-    OP_ANNOTATIONS = 5;
+    OP_CREATE = 1;         // alloc, create
+    OP_DESTROY = 2;        // free, destroy (non-bound)
+    OP_BIND = 3;           // bind buffer and image
+    OP_DESTROY_BOUND = 4;  // destroy (bound)
+    OP_ANNOTATIONS = 5;    // only annotations
   }
 
   enum AllocationScope {
@@ -6000,13 +4879,8 @@
   // 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.
-
-  // key to InternedString
-  repeated uint64 function_name_id = 2;
-
-  // key to InternedString
-  repeated uint64 file_name_id = 3;
-
+  repeated uint64 function_name_id = 2;  // key to InternedString
+  repeated uint64 file_name_id = 3;      // key to InternedString
   repeated uint32 line_number = 4;
 }
 
@@ -6044,11 +4918,8 @@
 }
 
 message Mapping {
-  // Interning key.
-  optional uint64 iid = 1;
-
-  // Interning key.
-  optional uint64 build_id = 2;
+  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.
@@ -6074,28 +4945,19 @@
   // 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.
-
-  // This is not set on Android 10.
-  optional uint64 exact_offset = 8;
-
+  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"]
-  // id of string.
-  repeated uint64 path_string_ids = 7;
+  repeated uint64 path_string_ids = 7;  // id of string.
 }
 
 message Frame {
-  // Interning key
-  optional uint64 iid = 1;
-
+  optional uint64 iid = 1;  // Interning key
   // E.g. "fopen"
-  // id of string.
-  optional uint64 function_name_id = 2;
-
+  optional uint64 function_name_id = 2;  // id of string.
   optional uint64 mapping_id = 3;
   optional uint64 rel_pc = 4;
 }
@@ -6108,105 +4970,17 @@
 
 // End of protos/perfetto/trace/profiling/profile_common.proto
 
-// Begin of protos/perfetto/trace/track_event/chrome_histogram_sample.proto
-
-message HistogramName {
-  optional uint64 iid = 1;
-  optional string name = 2;
-}
-
-// An individual histogram sample logged via Chrome's UMA metrics system.
-message ChromeHistogramSample {
-  // MD5 hash of the metric name. Either |name_hash| or |name|/|name_iid| or
-  // both must be present.
-  optional uint64 name_hash = 1;
-  optional string name = 2;
-  optional int64 sample = 3;
-  // Interned HistogramName. Only one of |name|, |name_iid| can be set.
-  optional uint64 name_iid = 4;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_histogram_sample.proto
-
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
-// Proto representation of untyped key/value annotations provided in TRACE_EVENT
-// macros. Users of the Perfetto SDK should prefer to use the
-// perfetto::TracedValue API to fill these protos, rather than filling them
-// manually.
+// 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.
 //
-// Debug annotations are intended for debug use and are not considered a stable
-// API of the trace contents. Trace-based metrics that use debug annotation
-// values are prone to breakage, so please rely on typed TrackEvent fields for
-// these instead.
-//
-// DebugAnnotations support nested arrays and dictionaries. Each entry is
-// encoded as a single DebugAnnotation message. Only dictionary entries
-// set the "name" field. The TrackEvent message forms an implicit root
-// dictionary.
-//
-// Example TrackEvent with nested annotations:
-//   track_event {
-//     debug_annotations {
-//       name: "foo"
-//       dict_entries {
-//         name: "a"
-//         bool_value: true
-//       }
-//       dict_entries {
-//         name: "b"
-//         int_value: 123
-//       }
-//     }
-//     debug_annotations {
-//       name: "bar"
-//       array_values {
-//         string_value: "hello"
-//       }
-//       array_values {
-//         string_value: "world"
-//       }
-//     }
-//   }
-//
-// Next ID: 13.
+// Next ID: 10.
 message DebugAnnotation {
-  // Name fields are set only for dictionary entries.
-  oneof name_field {
-    // interned DebugAnnotationName.
-    uint64 name_iid = 1;
-    // non-interned variant.
-    string name = 10;
-  }
-
-  oneof value {
-    bool bool_value = 2;
-    uint64 uint_value = 3;
-    int64 int_value = 4;
-    double double_value = 5;
-    string string_value = 6;
-    // Pointers are stored in a separate type as the JSON output treats them
-    // differently from other uint64 values.
-    uint64 pointer_value = 7;
-
-    // Deprecated. Use dict_entries / array_values instead.
-    NestedValue nested_value = 8;
-
-    // Legacy instrumentation may not support conversion of nested data to
-    // NestedValue yet.
-    string legacy_json_value = 9;
-  }
-
-  repeated DebugAnnotation dict_entries = 11;
-  repeated DebugAnnotation array_values = 12;
-
-  // Deprecated legacy way to use nested values. Only kept for
-  // backwards-compatibility in TraceProcessor. May be removed in the future -
-  // code filling protos should use |dict_entries| and |array_values| instead.
   message NestedValue {
     enum NestedType {
-      // leaf value.
-      UNSPECIFIED = 0;
+      UNSPECIFIED = 0;  // leaf value.
       DICT = 1;
       ARRAY = 2;
     }
@@ -6220,6 +4994,27 @@
     optional bool bool_value = 7;
     optional string string_value = 8;
   }
+
+  oneof name_field {
+    uint64 name_iid = 1;  // interned DebugAnnotationName.
+    string name = 10;     // non-interned variant.
+  }
+
+  oneof value {
+    bool bool_value = 2;
+    uint64 uint_value = 3;
+    int64 int_value = 4;
+    double double_value = 5;
+    string string_value = 6;
+    // Pointers are stored in a separate type as the JSON output treats them
+    // differently from other uint64 values.
+    uint64 pointer_value = 7;
+    NestedValue nested_value = 8;
+
+    // Legacy instrumentation may not support conversion of nested data to
+    // NestedValue yet.
+    string legacy_json_value = 9;
+  }
 }
 
 // --------------------
@@ -6236,10 +5031,8 @@
 // Begin of protos/perfetto/trace/track_event/log_message.proto
 
 message LogMessage {
-  // interned SourceLocation.
-  optional uint64 source_location_iid = 1;
-  // interned LogMessageBody.
-  optional uint64 body_iid = 2;
+  optional uint64 source_location_iid = 1;  // interned SourceLocation.
+  optional uint64 body_iid = 2;             // interned LogMessageBody.
 }
 
 // --------------------
@@ -6269,25 +5062,6 @@
 
 // End of protos/perfetto/trace/track_event/source_location.proto
 
-// Begin of protos/perfetto/trace/track_event/chrome_application_state_info.proto
-
-
-// Trace event arguments for application state changes.
-message ChromeApplicationStateInfo {
-  // Enum definition taken from:
-  // https://source.chromium.org/chromium/chromium/src/+/master:base/android/application_status_listener.h
-  enum ChromeApplicationState {
-    APPLICATION_STATE_UNKNOWN = 0;
-    APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1;
-    APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2;
-    APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3;
-    APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = 4;
-  };
-  optional ChromeApplicationState application_state = 1;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_application_state_info.proto
-
 // Begin of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
 
 // Describes Chrome's Compositor scheduler's current state and associated
@@ -6537,98 +5311,18 @@
 
 // End of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
 
-// Begin of protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto
+// Begin of protos/perfetto/trace/track_event/chrome_histogram_sample.proto
 
-// Details about ContentSettings trace events.
-message ChromeContentSettingsEventInfo {
-  // The number of user defined hostname patterns for content settings at
-  // browser start. Similar to UMA histogram
-  // 'ContentSettings.NumberOfExceptions'.
-  optional uint32 number_of_exceptions = 1;
-}
-// End of protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto
-
-// Begin of protos/perfetto/trace/track_event/chrome_frame_reporter.proto
-
-message ChromeFrameReporter {
-  enum State {
-    // The frame did not have any updates to present.
-    STATE_NO_UPDATE_DESIRED = 0;
-
-    // The frame presented all the desired updates (i.e. any updates requested
-    // from both the compositor thread and main-threads were handled).
-    STATE_PRESENTED_ALL = 1;
-
-    // The frame was presented with some updates, but also missed some updates
-    // (e.g. missed updates from the main-thread, but included updates from the
-    // compositor thread).
-    STATE_PRESENTED_PARTIAL = 2;
-
-    // The frame was dropped, i.e. some updates were desired for the frame, but
-    // was not presented.
-    STATE_DROPPED = 3;
-  };
-
-  optional State state = 1;
-
-  enum FrameDropReason {
-    REASON_UNSPECIFIED = 0;
-
-    // Frame was dropped by the display-compositor.
-    // The display-compositor may drop a frame some times (e.g. the frame missed
-    // the deadline, or was blocked on surface-sync, etc.)
-    REASON_DISPLAY_COMPOSITOR = 1;
-
-    // Frame was dropped because of the main-thread.
-    // The main-thread may cause a frame to be dropped, e.g. if the main-thread
-    // is running expensive javascript, or doing a lot of layout updates, etc.
-    REASON_MAIN_THREAD = 2;
-
-    // Frame was dropped by the client compositor.
-    // The client compositor can drop some frames too (e.g. attempting to
-    // recover latency, missing the deadline, etc.).
-    REASON_CLIENT_COMPOSITOR = 3;
-  };
-
-  // The reason is set only if |state| is not |STATE_UPDATED_ALL|.
-  optional FrameDropReason reason = 2;
-
-  optional uint64 frame_source = 3;
-  optional uint64 frame_sequence = 4;
-
-  // If this is a droped frame (i.e. if |state| is set to |STATE_DROPPED| or
-  // |STATE_PRESENTED_PARTIAL|), then indicates whether this frame impacts
-  // smoothness.
-  optional bool affects_smoothness = 5;
-
-  enum ScrollState {
-    SCROLL_NONE = 0;
-    SCROLL_MAIN_THREAD = 1;
-    SCROLL_COMPOSITOR_THREAD = 2;
-
-    // Used when it can't be determined wheter a scroll is in progress or not.
-    SCROLL_UNKNOWN = 3;
-  }
-
-  // The type of active scroll
-  optional ScrollState scroll_state = 6;
-
-  // If any main thread animation is active during this frame.
-  optional bool has_main_animation = 7;
-  // If any compositor thread animation is active during this frame.
-  optional bool has_compositor_animation = 8;
-  // If any touch-driven UX (not scroll) is active during this frame.
-  optional bool has_smooth_input_main = 9;
-
-  // Whether the frame contained any missing content (i.e. whether there was
-  // checkerboarding in the frame).
-  optional bool has_missing_content = 10;
-
-  // The id of layer_tree_host that the frame has been produced for.
-  optional uint64 layer_tree_host_id = 11;
+// An individual histogram sample logged via Chrome's UMA metrics system.
+message ChromeHistogramSample {
+  // MD5 hash of the metric name. Either |name_hash| or |name| or both
+  // must be present.
+  optional uint64 name_hash = 1;
+  optional string name = 2;
+  optional int64 sample = 3;
 }
 
-// End of protos/perfetto/trace/track_event/chrome_frame_reporter.proto
+// End of protos/perfetto/trace/track_event/chrome_histogram_sample.proto
 
 // Begin of protos/perfetto/trace/track_event/chrome_keyed_service.proto
 
@@ -6646,7 +5340,7 @@
 message ChromeLatencyInfo {
   optional int64 trace_id = 1;
 
-  // NEXT ID: 12
+  // NEXT ID: 11
   // All step are optional but the enum is ordered (not by number) below in the
   // order we expect them to appear if they are emitted in trace in a blocking
   // fashion.
@@ -6670,9 +5364,6 @@
     STEP_SWAP_BUFFERS = 6;
     // Happens on the VizCompositor in the GPU process.
     STEP_DRAW_AND_SWAP = 7;
-    // Happens on the GPU main thread after the swap has completed.
-    STEP_FINISHED_SWAP_BUFFERS = 11;
-    // See above for NEXT ID, enum steps are not ordered by tag number.
   };
 
   optional Step step = 2;
@@ -6770,62 +5461,6 @@
 
 // End of protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
 
-// Begin of protos/perfetto/trace/track_event/chrome_message_pump.proto
-
-// Details about Chrome message pump events
-message ChromeMessagePump {
-  // True if there are sent messages in the queue.
-  optional bool sent_messages_in_queue = 1;
-  // Interned SourceLocation of IO handler that MessagePumpForIO is about to
-  // invoke.
-  optional uint64 io_handler_location_iid = 2;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_message_pump.proto
-
-// Begin of protos/perfetto/trace/track_event/chrome_mojo_event_info.proto
-
-// Contains information to identify mojo handling events. The trace events in
-// mojo are common for all mojo interfaces and this information is used to
-// identify who is the caller or callee.
-message ChromeMojoEventInfo {
-  // Contains the interface name or the file name of the creator of a mojo
-  // handle watcher, recorded when an event if notified to the watcher. The code
-  // that runs within the track event belongs to the interface.
-  optional string watcher_notify_interface_tag = 1;
-
-  // The hash of the IPC message that is being handled.
-  optional uint32 ipc_hash = 2;
-
-  // A static string representing the mojo interface name of the message that is
-  // being handled.
-  optional string mojo_interface_tag = 3;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_mojo_event_info.proto
-
-// Begin of protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto
-
-// Describes the state of the RendererScheduler for a given Renderer Process.
-
-// RAIL Mode is an indication of the kind of work that a Renderer is currently
-// performing which is in turn used to prioritise work accordingly.
-// A fuller description of these modes can be found https://web.dev/rail/
-enum ChromeRAILMode {
-  RAIL_MODE_NONE = 0;
-  RAIL_MODE_RESPONSE = 1;
-  RAIL_MODE_ANIMATION = 2;
-  RAIL_MODE_IDLE = 3;
-  RAIL_MODE_LOAD = 4;
-}
-
-// Next id: 2
-message ChromeRendererSchedulerState {
-  optional ChromeRAILMode rail_mode = 1;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto
-
 // Begin of protos/perfetto/trace/track_event/chrome_user_event.proto
 
 // Details about a UI interaction initiated by the user, such as opening or
@@ -6842,24 +5477,12 @@
 
 // End of protos/perfetto/trace/track_event/chrome_user_event.proto
 
-// Begin of protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto
-
-// Details about HWNDMessageHandler trace events.
-message ChromeWindowHandleEventInfo {
-  optional uint32 dpi = 1;
-  optional uint32 message_id = 2;
-  optional fixed64 hwnd_ptr = 3;
-}
-
-// End of protos/perfetto/trace/track_event/chrome_window_handle_event_info.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.
-  // interned SourceLocation.
-  optional uint64 posted_from_iid = 1;
+  optional uint64 posted_from_iid = 1;  // interned SourceLocation.
 }
 // End of protos/perfetto/trace/track_event/task_execution.proto
 
@@ -6874,7 +5497,6 @@
 // referred to via the track's UUID.
 //
 // A simple TrackEvent packet specifies a timestamp, category, name and type:
-// ```protobuf
 //   trace_packet {
 //     timestamp: 1000
 //     track_event {
@@ -6883,11 +5505,9 @@
 //       type: TYPE_INSTANT
 //      }
 //    }
-// ```
 //
 // 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:
-// ```protobuf
 //   trace_packet {
 //     track_descriptor {
 //       track_uuid: 1234
@@ -6901,11 +5521,8 @@
 //       }
 //     }
 //   }
-// ```
 //
 // A pair of TYPE_SLICE_BEGIN and _END events form a slice on the track:
-//
-// ```protobuf
 //   trace_packet {
 //     timestamp: 1200
 //     track_event {
@@ -6922,7 +5539,7 @@
 //       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.
@@ -6930,14 +5547,12 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 13 (up to 15). Next id: 47.
+// Next reserved id: 13 (up to 15). Next id: 32.
 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.
-  // interned EventCategoryName.
-  repeated uint64 category_iids = 3;
-  // non-interned variant.
-  repeated string categories = 22;
+  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.
@@ -6946,10 +5561,8 @@
   // changing. Instead, they should use typed arguments to identify the events
   // they are interested in.
   oneof name_field {
-    // interned EventName.
-    uint64 name_iid = 10;
-    // non-interned variant.
-    string name = 23;
+    uint64 name_iid = 10;  // interned EventName.
+    string name = 23;      // non-interned variant.
   }
 
   // TODO(eseckler): Support using binary symbols for category/event names.
@@ -7002,10 +5615,7 @@
   // of a slice, see |extra_counter_values| and |extra_counter_track_uuids|.
   // Counter values can optionally be encoded in as delta values (positive or
   // negative) on each packet sequence (see CounterIncrementalBase).
-  oneof counter_value_field {
-    int64 counter_value = 30;
-    double double_counter_value = 44;
-  }
+  optional int64 counter_value = 30;
 
   // To encode counter values more efficiently, we support attaching additional
   // counter values to a TrackEvent of any type. All values will share the same
@@ -7024,31 +5634,7 @@
   repeated uint64 extra_counter_track_uuids = 31;
   repeated int64 extra_counter_values = 12;
 
-  // Counter snapshots using floating point instead of integer values.
-  repeated uint64 extra_double_counter_track_uuids = 45;
-  repeated double extra_double_counter_values = 46;
-
-  // IDs of flows originating, passing through, or ending at this event.
-  // Flow IDs are global within a trace.
-  //
-  // A flow connects a sequence of TrackEvents within or across tracks, e.g.
-  // an input event may be handled on one thread but cause another event on
-  // a different thread - a flow between the two events can associate them.
-  //
-  // The direction of the flows between events is inferred from the events'
-  // timestamps. The earliest event with the same flow ID becomes the source
-  // of the flow. Any events thereafter are intermediate steps of the flow,
-  // until the flow terminates at the last event with the flow ID.
-  //
-  // Flows can also be explicitly terminated (see |terminating_flow_ids|), so
-  // that the same ID can later be reused for another flow.
-  repeated uint64 flow_ids = 36;
-
-  // List of flow ids which should terminate on this event, otherwise same as
-  // |flow_ids|.
-  // Any one flow ID should be either listed as part of |flow_ids| OR
-  // |terminating_flow_ids|, not both.
-  repeated uint64 terminating_flow_ids = 42;
+  // TODO(eseckler): Add flow event support.
 
   // ---------------------------------------------------------------------------
   // TrackEvent arguments:
@@ -7067,42 +5653,8 @@
   optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   optional ChromeHistogramSample chrome_histogram_sample = 28;
   optional ChromeLatencyInfo chrome_latency_info = 29;
-  optional ChromeFrameReporter chrome_frame_reporter = 32;
-  optional ChromeApplicationStateInfo chrome_application_state_info = 39;
-  optional ChromeRendererSchedulerState chrome_renderer_scheduler_state = 40;
-  optional ChromeWindowHandleEventInfo chrome_window_handle_event_info = 41;
-  optional ChromeContentSettingsEventInfo chrome_content_settings_event_info =
-      43;
-
-  // This field is used only if the source location represents the function that
-  // executes during this event.
-  oneof source_location_field {
-    // Non-interned field.
-    SourceLocation source_location = 33;
-    // Interned field.
-    uint64 source_location_iid = 34;
-  }
-
-  optional ChromeMessagePump chrome_message_pump = 35;
-  optional ChromeMojoEventInfo chrome_mojo_event_info = 38;
-
   // New argument types go here :)
 
-  // Extension range for typed events defined externally.
-  // See docs/design-docs/extensions.md for more details.
-  //
-  // Extension support is work-in-progress, in the future the way to reserve a
-  // subrange for a particular project will be described here and in the design
-  // document linked above.
-  //
-  // Contact perfetto-dev@googlegroups.com if you are interested in a subrange
-  // for your project.
-
-  // Extension range for future use.
-  extensions 1000 to 9899;
-  // Reserved for Perfetto unit and integration tests.
-  extensions 9900 to 10000;
-
   // ---------------------------------------------------------------------------
   // Deprecated / legacy event fields, which will be removed in the future:
   // ---------------------------------------------------------------------------
@@ -7161,8 +5713,7 @@
   // Next id: 20.
   message LegacyEvent {
     // Deprecated, use TrackEvent::name(_iid) instead.
-    // interned EventName.
-    optional uint64 name_iid = 1;
+    optional uint64 name_iid = 1;  // interned EventName.
     optional int32 phase = 2;
     optional int64 duration_us = 3;
     optional int64 thread_duration_us = 4;
@@ -7170,8 +5721,7 @@
     // Elapsed retired instruction count during the event.
     optional int64 thread_instruction_delta = 15;
 
-    // used to be |flags|.
-    reserved 5;
+    reserved 5;  // used to be |flags|.
 
     oneof id {
       uint64 unscoped_id = 6;
@@ -7224,7 +5774,6 @@
 message TrackEventDefaults {
   optional uint64 track_uuid = 11;
   repeated uint64 extra_counter_track_uuids = 31;
-  repeated uint64 extra_double_counter_track_uuids = 45;
 
   // TODO(eseckler): Support default values for more TrackEvent fields.
 }
@@ -7274,7 +5823,7 @@
 // emitted proactively in advance of referring to them in later packets.
 //
 // Next reserved id: 8 (up to 15).
-// Next id: 27.
+// Next id: 23.
 message InternedData {
   // TODO(eseckler): Replace iid fields inside interned messages with
   // map<iid, message> type fields in InternedData.
@@ -7291,7 +5840,6 @@
   repeated DebugAnnotationName debug_annotation_names = 3;
   repeated SourceLocation source_locations = 4;
   repeated LogMessageBody log_message_body = 20;
-  repeated HistogramName histogram_names = 25;
 
   // Note: field IDs up to 15 should be used for frequent data only.
 
@@ -7315,133 +5863,10 @@
 
   // Additional Vulkan information sent in a VulkanMemoryEvent message
   repeated InternedString vulkan_memory_keys = 22;
-
-  // Graphics context of a render stage event.  This represent the GL
-  // context for an OpenGl app or the VkDevice for a Vulkan app.
-  repeated InternedGraphicsContext graphics_contexts = 23;
-
-  // Description of a GPU hardware queue or render stage.
-  repeated InternedGpuRenderStageSpecification gpu_specifications = 24;
-
-  // This is set when FtraceConfig.symbolize_ksyms = true.
-  // The id of each symbol the number that will be reported in ftrace events
-  // like sched_block_reason.caller and is obtained from a monotonic counter.
-  // The same symbol can have different indexes in different bundles.
-  // This is is NOT the real address. This is to avoid disclosing KASLR through
-  // traces.
-  repeated InternedString kernel_symbols = 26;
 }
 
 // End of protos/perfetto/trace/interned_data/interned_data.proto
 
-// Begin of protos/perfetto/trace/memory_graph.proto
-
-// Message definitions for app-reported memory breakdowns. At the moment, this
-// is a Chrome-only tracing feature, historically known as 'memory-infra'. See
-// https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/ .
-// This is unrelated to the native or java heap profilers (those protos live
-// in //protos/perfetto/trace/profiling/).
-
-message MemoryTrackerSnapshot {
-  // Memory snapshot of a process. The snapshot contains memory data that is
-  // from 2 different sources, namely system stats and instrumentation stats.
-  // The system memory usage stats come from the OS based on standard API
-  // available in the platform to query memory usage. The instrumentation stats
-  // are added by instrumenting specific piece of code which tracks memory
-  // allocations and deallocations made by a small sub-system within the
-  // application.
-  // The system stats of the global memory snapshot are recorded as part of
-  // ProcessStats and SmapsPacket fields in trace packet with the same
-  // timestamp.
-  message ProcessSnapshot {
-    // Process ID of the process
-    optional int32 pid = 1;
-
-    // Memory dumps are represented as a graph of memory nodes which contain
-    // statistics. To avoid double counting the same memory across different
-    // nodes, edges are used to mark nodes that account for the same memory. See
-    // this doc for examples of the usage:
-    // https://docs.google.com/document/d/1WGQRJ1sjJrfVkNcgPVY6frm64UqPc94tsxUOXImZUZI
-
-    // A single node in the memory graph.
-    message MemoryNode {
-      // Unique ID of the node across all processes involved in the global
-      // memory dump. The ID is only unique within this particular global dump
-      // identified by GlobalMemoryDumpPacket.global_dump_id.
-      optional uint64 id = 1;
-
-      // Absolute name is a unique name for the memory node within the process
-      // with ProcessMemoryDump.pid. The name can contain multiple parts
-      // separated by '/', which traces the edges of the node from the root
-      // node.
-      // Eg: "partition_allocator/array_buffers/buffer1" refers to the child
-      // node "buffer1" in a graph structure of:
-      //   root -> partition_allocator -> array_buffers -> buffer1.
-      optional string absolute_name = 2;
-
-      // A weak node means that the instrumentation that added the current node
-      // is unsure about the existence of the actual memory. Unless a "strong"
-      // (non-weak is default) node that has an edge to the current node exists
-      // in the current global dump, the current node will be discarded.
-      optional bool weak = 3;
-
-      // Size of the node in bytes, used to compute the effective size of the
-      // nodes without double counting.
-      optional uint64 size_bytes = 4;
-
-      // Entries in the memory node that contain statistics and additional
-      // debuggable information about the memory. The size of the node is
-      // tracked separately in the |size_bytes| field.
-      message MemoryNodeEntry {
-        optional string name = 1;
-
-        enum Units {
-          UNSPECIFIED = 0;
-          BYTES = 1;
-          COUNT = 2;
-        }
-        optional Units units = 2;
-
-        // Contains either one of uint64 or string value.
-        optional uint64 value_uint64 = 3;
-        optional string value_string = 4;
-      }
-      repeated MemoryNodeEntry entries = 5;
-    }
-    repeated MemoryNode allocator_dumps = 2;
-
-    // A directed edge that connects any 2 nodes in the graph above. These are
-    // in addition to the inherent edges added due to the tree structure of the
-    // node's absolute names.
-    // Node with id |source_id| owns the node with id |target_id|, and has the
-    // effect of attributing the memory usage of target to source. |importance|
-    // is optional and relevant only for the cases of co-ownership, where it
-    // acts as a z-index: the owner with the highest importance will be
-    // attributed target's memory.
-    message MemoryEdge {
-      optional uint64 source_id = 1;
-      optional uint64 target_id = 2;
-      optional uint32 importance = 3;
-      optional bool overridable = 4;
-    }
-    repeated MemoryEdge memory_edges = 3;
-  }
-
-  // Unique ID that represents the global memory dump.
-  optional uint64 global_dump_id = 1;
-
-  enum LevelOfDetail {
-    DETAIL_FULL = 0;
-    DETAIL_LIGHT = 1;
-    DETAIL_BACKGROUND = 2;
-  }
-  optional LevelOfDetail level_of_detail = 2;
-
-  repeated ProcessSnapshot process_memory_dumps = 3;
-}
-
-// End of protos/perfetto/trace/memory_graph.proto
-
 // Begin of protos/perfetto/trace/perfetto/perfetto_metatrace.proto
 
 // Used to trace the execution of perfetto itself.
@@ -7481,115 +5906,23 @@
 
 // Begin of protos/perfetto/trace/perfetto/tracing_service_event.proto
 
-// Events emitted by the tracing service.
+// Events emitted by the tracing service when data source states change.
 message TracingServiceEvent {
   oneof event_type {
-    // When each of the following booleans are set to true, they report the
-    // point in time (through TracePacket's timestamp) where the condition
-    // they describe happened.
-    // The order of the booleans below matches the timestamp ordering
-    // they would generally be expected to have.
-
-    // Emitted when we start tracing and specifically, this will be before any
-    // producer is notified about the existence of this trace. This is always
-    // emitted before the all_data_sources_started event. This event is also
-    // guaranteed to be seen (byte-offset wise) before any data packets from
-    // producers.
-    bool tracing_started = 2;
-
-    // Emitted after all data sources saw the start event and ACKed it.
-    // This identifies the point in time when it's safe to assume that all data
+    // When this is set to true, reports the point in time (the TracePacket's
+    // timestamp) when all data sources did see the start event and ACKed it.
+    // This identifies the point in time when it's safe to assume tha all data
     // sources have been recording events.
+    // Note: like any other event in the trace, the byte offset at which this
+    // packet shows up in the trace is arbitrary and doesn't reflect causal
+    // ordering (i.e. it's okay to use this event to reason about the timestamps
+    // of othe packets, NOT their relative order w.r.t. this packet).
     bool all_data_sources_started = 1;
-
-    // Emitted when all data sources have been flushed successfully or with an
-    // error (including timeouts). This can generally happen many times over the
-    // course of the trace.
-    bool all_data_sources_flushed = 3;
-
-    // Emitted when reading back the central tracing buffers has been completed.
-    // If |write_into_file| is specified, this can happen many times over the
-    // course of the trace.
-    bool read_tracing_buffers_completed = 4;
-
-    // Emitted after tracing has been disabled and specifically, this will be
-    // after all packets from producers have been included in the central
-    // tracing buffer.
-    bool tracing_disabled = 5;
-
-    // Emitted if perfetto --save-for-bugreport was invoked while the current
-    // tracing session was running and it had the highest bugreport_score. In
-    // this case the original consumer will see a nearly empty trace, because
-    // the contents are routed onto the bugreport file. This event flags the
-    // situation explicitly. Traces that contain this marker should be discarded
-    // by test infrastructures / pipelines.
-    bool seized_for_bugreport = 6;
   }
 }
 
 // End of protos/perfetto/trace/perfetto/tracing_service_event.proto
 
-// Begin of protos/perfetto/common/android_energy_consumer_descriptor.proto
-
-// Energy consumer based on aidl class:
-// android.hardware.power.stats.EnergyConsumer.
-message AndroidEnergyConsumer {
-  // Unique ID of this energy consumer.  Matches the ID in a
-  // AndroidEnergyEstimationBreakdown.
-  optional int32 energy_consumer_id = 1;
-
-  // For a group of energy consumers of the same logical type, sorting by
-  // ordinal gives their physical order. Ordinals must be consecutive integers
-  // starting from 0.
-  optional int32 ordinal = 2;
-
-  // Type of this energy consumer.
-  optional string type = 3;
-
-  // Unique name of this energy consumer. Vendor/device specific. Opaque to
-  // framework.
-  optional string name = 4;
-}
-
-message AndroidEnergyConsumerDescriptor {
-  repeated AndroidEnergyConsumer energy_consumers = 1;
-}
-
-// End of protos/perfetto/common/android_energy_consumer_descriptor.proto
-
-// Begin of protos/perfetto/trace/power/android_energy_estimation_breakdown.proto
-
-// Energy data retrieve using the ODPM(On Device Power Monitor) API.
-// This proto represents the aidl class:
-// android.hardware.power.stats.EnergyConsumerResult.
-message AndroidEnergyEstimationBreakdown {
-  // The first trace packet of each session should include a energy consumer
-  // descriptor.
-  optional AndroidEnergyConsumerDescriptor energy_consumer_descriptor = 1;
-
-  // ID of the AndroidEnergyConsumer associated with this result.  Matches
-  // the energy_consumer_id in the AndroidEnergyConsumerDescriptor that
-  // should be sent at the beginning of a trace.
-  optional int32 energy_consumer_id = 2;
-
-  // Total accumulated energy since boot in microwatt-seconds (uWs)
-  optional int64 energy_uws = 3;
-
-  message EnergyUidBreakdown {
-    // Android ID/Linux UID, the accumulated energy is attributed to.
-    optional int32 uid = 1;
-
-    // Accumulated energy since boot in microwatt-seconds (uWs).
-    optional int64 energy_uws = 2;
-  }
-  // Optional attributed energy per Android ID / Linux UID for this
-  // EnergyConsumer. Sum total of attributed energy must be less than or equal
-  // to total accumulated energy.
-  repeated EnergyUidBreakdown per_uid_breakdown = 4;
-}
-
-// End of protos/perfetto/trace/power/android_energy_estimation_breakdown.proto
-
 // Begin of protos/perfetto/trace/power/battery_counters.proto
 
 message BatteryCounters {
@@ -7600,9 +5933,8 @@
   optional float capacity_percent = 2;
 
   // Instantaneous battery current in microamperes(µA).
-  // Positive values indicate current drained from the battery,
-  // negative values current feeding the battery from a charge source (USB).
-  // See https://perfetto.dev/docs/data-sources/battery-counters for more.
+  // Positive values indicate net current entering the battery from a charge
+  // source, negative values indicate net current discharging from the battery.
   optional int64 current_ua = 3;
 
   // Instantaneous battery current in microamperes(µA).
@@ -7648,7 +5980,7 @@
 
 // End of protos/perfetto/trace/power/power_rails.proto
 
-// Begin of protos/perfetto/trace/profiling/deobfuscation.proto
+// Begin of protos/perfetto/trace/profiling/heap_graph.proto
 
 message ObfuscatedMember {
   // This is the obfuscated field name relative to the class containing the
@@ -7664,9 +5996,7 @@
 message ObfuscatedClass {
   optional string obfuscated_name = 1;
   optional string deobfuscated_name = 2;
-  // fields.
   repeated ObfuscatedMember obfuscated_members = 3;
-  repeated ObfuscatedMember obfuscated_methods = 4;
 }
 
 message DeobfuscationMapping {
@@ -7674,9 +6004,6 @@
   optional int64 version_code = 2;
   repeated ObfuscatedClass obfuscated_classes = 3;
 }
-// End of protos/perfetto/trace/profiling/deobfuscation.proto
-
-// Begin of protos/perfetto/trace/profiling/heap_graph.proto
 
 message HeapGraphRoot {
   enum Type {
@@ -7703,58 +6030,24 @@
 }
 
 message HeapGraphType {
-  enum Kind {
-    KIND_UNKNOWN = 0;
-    KIND_NORMAL = 1;
-    KIND_NOREFERENCES = 2;
-    KIND_STRING = 3;
-    KIND_ARRAY = 4;
-    KIND_CLASS = 5;
-    KIND_CLASSLOADER = 6;
-    KIND_DEXCACHE = 7;
-    KIND_SOFT_REFERENCE = 8;
-    KIND_WEAK_REFERENCE = 9;
-    KIND_FINALIZER_REFERENCE = 10;
-    KIND_PHANTOM_REFERENCE = 11;
-  };
   // TODO(fmayer): Consider removing this and using the index in the repeaed
   // field to save space.
   optional uint64 id = 1;
   optional uint64 location_id = 2;
   optional string class_name = 3;
-  // Size of objects of this type.
-  optional uint64 object_size = 4;
-  optional uint64 superclass_id = 5;
-  // Indices for InternedData.field_names for the names of the fields of
-  // instances of this class. This does NOT include the fields from
-  // superclasses. The consumer of this data needs to walk all super
-  // classes to get a full lists of fields. Objects always write the
-  // fields in order of most specific class to the furthest up superclass.
-  repeated uint64 reference_field_id = 6 [packed = true];
-  optional Kind kind = 7;
-  optional uint64 classloader_id = 8;
 }
 
 message HeapGraphObject {
-  oneof identifier {
-    uint64 id = 1;
-    uint64 id_delta = 7;
-  }
+  optional uint64 id = 1;
 
-  // Index for InternedData.types for the name of the type of this object.
+  // 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;
 
-  // Add this to all non-zero values in reference_field_id. This is used to
-  // get more compact varint encoding.
-  optional uint64 reference_field_id_base = 6;
-
   // Indices for InternedData.field_names for the name of the field referring
-  // to the object. For Android S+ and for instances of normal classes (e.g.
-  // not instances of java.lang.Class or arrays), this is instead set in the
-  // corresponding HeapGraphType, and this is left empty.
+  // to the object.
   repeated uint64 reference_field_id = 4 [packed = true];
 
   // Ids of the Object that is referred to.
@@ -7780,7 +6073,12 @@
   // Types used in HeapGraphObjects.
   repeated HeapGraphType types = 9;
 
-  reserved 3;
+  // Legacy way to encode types. Names here are emitted by old perfetto_hprof,
+  // which do not include the class_name. Handle like a HeapGraphType with
+  // no location_id.
+  // TODO(b/153552977): Remove this. This was was not used in any publicly
+  // available release.
+  repeated InternedString type_names = 3;
 
   // Field names for references in managed heap graph.
   repeated InternedString field_names = 4;
@@ -7816,20 +6114,17 @@
     optional uint64 self_allocated = 2;
     // bytes allocated at this callstack that have been freed.
     optional uint64 self_freed = 3;
-    // deprecated self_idle.
-    reserved 7;
+    // 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;
-    // Number of allocations that were sampled at 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_count = 9;
-    // timestamp [opt]
-    optional uint64 timestamp = 4;
+    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
@@ -7859,16 +6154,10 @@
     optional uint64 map_reparses = 3;
     optional Histogram unwinding_time_us = 4;
     optional uint64 total_unwinding_time_us = 5;
-    optional uint64 client_spinlock_blocked_us = 6;
   }
 
   repeated ProcessHeapSamples process_dumps = 5;
   message ProcessHeapSamples {
-    enum ClientError {
-      CLIENT_ERROR_NONE = 0;
-      CLIENT_ERROR_HIT_TIMEOUT = 1;
-      CLIENT_ERROR_INVALID_STACK_BOUNDS = 2;
-    }
     optional uint64 pid = 1;
 
     // This process was profiled from startup.
@@ -7885,12 +6174,8 @@
 
     // If disconnected, this disconnect was caused by the client overrunning
     // the buffer.
-    // Equivalent to client_error == CLIENT_ERROR_HIT_TIMEOUT
-    // on new S builds.
     optional bool buffer_overran = 7;
 
-    optional ClientError client_error = 14;
-
     // If disconnected, this disconnected was caused by the shared memory
     // buffer being corrupted. THIS IS ALWAYS A BUG IN HEAPPROFD OR CLIENT
     // MEMORY CORRUPTION.
@@ -7900,10 +6185,6 @@
     // guardrails during this profiling session.
     optional bool hit_guardrail = 10;
 
-    optional string heap_name = 11;
-    optional uint64 sampling_interval_bytes = 12;
-    optional uint64 orig_sampling_interval_bytes = 13;
-
     // Timestamp of the state of the target process that this dump represents.
     // This can be different to the timestamp of the TracePackets for various
     // reasons:
@@ -7934,28 +6215,10 @@
   optional uint64 index = 7;
 }
 
-message StreamingAllocation {
-  // TODO(fmayer): Add callstack.
-  repeated uint64 address = 1;
-  repeated uint64 size = 2;
-  repeated uint64 sample_size = 3;
-  repeated uint64 clock_monotonic_coarse_timestamp = 4;
-  repeated uint32 heap_id = 5;
-  repeated uint64 sequence_number = 6;
-};
-
-message StreamingFree {
-  // TODO(fmayer): Add callstack.
-  repeated uint64 address = 1;
-  repeated uint32 heap_id = 2;
-  repeated uint64 sequence_number = 3;
-};
-
 // Message used to represent individual stack samples sampled at discrete
 // points in time, rather than aggregated over an interval.
 message StreamingProfilePacket {
-  // Index into InternedData.callstacks
-  repeated uint64 callstack_iid = 1;
+  repeated uint64 callstack_iid = 1;  // Index into InternedData.callstacks
   // TODO(eseckler): ThreadDescriptor-based timestamps are deprecated. Replace
   // this with ClockSnapshot-based delta encoding instead.
   repeated int64 timestamp_delta_us = 2;
@@ -7986,24 +6249,16 @@
     UNWIND_ERROR_MAX_FRAMES_EXCEEDED = 6;
     UNWIND_ERROR_REPEATED_FRAME = 7;
     UNWIND_ERROR_INVALID_ELF = 8;
-    UNWIND_ERROR_SYSTEM_CALL = 9;
-    UNWIND_ERROR_THREAD_TIMEOUT = 10;
-    UNWIND_ERROR_THREAD_DOES_NOT_EXIST = 11;
   }
 }
 
 // Individual performance sampling packet payload. Typically corresponds to a
 // stack sample on a configration-dependent counter overflow.
-//
-// Timestamps are within the root packet. This used to use the CLOCK_BOOTTIME
-// domain, but now the default is CLOCK_MONOTONIC_RAW which is compatible with
-// more event types.
-//
-// There are several distinct views of this message:
+// Timestamps are within the root packet (in the CLOCK_BOOTTIME domain).
+// There are three distinct views of this message:
 // * completely processed sample (callstack_iid set)
 // * indication of kernel buffer data loss (kernel_records_lost set)
 // * indication of skipped samples (sample_skipped_reason set)
-// * notable event in the sampling implementation (producer_event set)
 message PerfSample {
   optional uint32 cpu = 1;
   optional uint32 pid = 2;
@@ -8012,11 +6267,8 @@
   // Execution state that the process was sampled at.
   optional Profiling.CpuMode cpu_mode = 5;
 
-  // Value of the timebase counter (since the event was configured, no deltas).
-  optional uint64 timebase_count = 6;
-
   // Unwound callstack. Might be partial, in which case a synthetic "error"
-  // frame is appended, and |unwind_error| is set accordingly.
+  // frame is appended, and |unwind_error| is set appropriately.
   optional uint64 callstack_iid = 4;
 
   // If set, stack unwinding was incomplete due to an error.
@@ -8048,26 +6300,8 @@
   oneof optional_sample_skipped_reason {
     SampleSkipReason sample_skipped_reason = 18;
   };
-
-  // A notable event within the sampling implementation.
-  message ProducerEvent {
-    enum DataSourceStopReason {
-      PROFILER_STOP_UNKNOWN = 0;
-      PROFILER_STOP_GUARDRAIL = 1;
-    }
-    oneof optional_source_stop_reason {
-      DataSourceStopReason source_stop_reason = 1;
-    }
-  }
-  optional ProducerEvent producer_event = 19;
 }
 
-// Submessage for TracePacketDefaults.
-message PerfSampleDefaults {
-  // The sampling timebase. Might not be identical to the data source config if
-  // the implementation decided to default/override some parameters.
-  optional PerfEvents.Timebase timebase = 1;
-}
 // End of protos/perfetto/trace/profiling/profile_packet.proto
 
 // Begin of protos/perfetto/trace/profiling/smaps.proto
@@ -8077,22 +6311,6 @@
   optional uint64 size_kb = 2;
   optional uint64 private_dirty_kb = 3;
   optional uint64 swap_kb = 4;
-
-  // for field upload (instead of path).
-  optional string file_name = 5;
-
-  // TODO(crbug.com/1098746): Consider encoding this as incremental values.
-  optional uint64 start_address = 6;
-  optional uint64 module_timestamp = 7;
-  optional string module_debugid = 8;
-  optional string module_debug_path = 9;
-  optional uint32 protection_flags = 10;
-
-  optional uint64 private_clean_resident_kb = 11;
-  optional uint64 shared_dirty_resident_kb = 12;
-  optional uint64 shared_clean_resident_kb = 13;
-  optional uint64 locked_kb = 14;
-  optional uint64 proportional_resident_kb = 15;
 };
 
 message SmapsPacket {
@@ -8148,17 +6366,6 @@
     optional int64 oom_score_adj = 10;
 
     repeated Thread threads = 11;
-
-    // The peak resident set size is resettable in newer Posix kernels.
-    // This field specifies if reset is supported and if the writer had reset
-    // the peaks after each process stats recording.
-    optional bool is_peak_rss_resettable = 12;
-
-    // Private, shared and swap footprint of the process as measured by
-    // Chrome. To know more about these metrics refer to:
-    // https://docs.google.com/document/d/1_WmgE1F5WUrhwkPqJis3dWyOiUmQKvpXp5cd4w86TvA
-    optional uint32 chrome_private_footprint_kb = 13;
-    optional uint32 chrome_peak_resident_set_kb = 14;
   }
   repeated Process processes = 1;
 
@@ -8176,11 +6383,6 @@
 
 // Begin of protos/perfetto/trace/ps/process_tree.proto
 
-// Metadata about the processes and threads in the trace.
-// Note: this proto was designed to be filled in by traced_probes and should
-// only be populated with accurate information coming from the system. Other
-// trace writers should prefer to fill ThreadDescriptor and ProcessDescriptor
-// in TrackDescriptor.
 message ProcessTree {
   // Representation of a thread.
   message Thread {
@@ -8256,30 +6458,15 @@
   // Times in each mode, since boot. Unit: nanoseconds.
   message CpuTimes {
     optional uint32 cpu_id = 1;
-
-    // Time spent in user mode.
-    optional uint64 user_ns = 2;
-
-    // Time spent in user mode (low prio).
-    optional uint64 user_ice_ns = 3;
-
-    // Time spent in system mode.
-    optional uint64 system_mode_ns = 4;
-
-    // Time spent in the idle task.
-    optional uint64 idle_ns = 5;
-
-    // Time spent waiting for I/O.
-    optional uint64 io_wait_ns = 6;
-
-    // Time spent servicing interrupts.
-    optional uint64 irq_ns = 7;
-
-    // Time spent servicing softirqs.
-    optional uint64 softirq_ns = 8;
+    optional uint64 user_ns = 2;         // Time spent in user mode.
+    optional uint64 user_ice_ns = 3;     // Time spent in user mode (low prio).
+    optional uint64 system_mode_ns = 4;  // Time spent in system mode.
+    optional uint64 idle_ns = 5;         // Time spent in the idle task.
+    optional uint64 io_wait_ns = 6;      // Time spent waiting for I/O.
+    optional uint64 irq_ns = 7;          // Time spent servicing interrupts.
+    optional uint64 softirq_ns = 8;      // Time spent servicing softirqs.
   }
-  // One entry per cpu.
-  repeated CpuTimes cpu_stat = 3;
+  repeated CpuTimes cpu_stat = 3;  // One entry per cpu.
 
   // Num processes forked since boot.
   // Populated only if FORK_COUNT in config.stat_counters.
@@ -8292,33 +6479,18 @@
 
   // Number of interrupts, broken by IRQ number.
   // Populated only if IRQ_COUNTS in config.stat_counters.
-
-  // Total num of irqs serviced since boot.
-  optional uint64 num_irq_total = 5;
+  optional uint64 num_irq_total = 5;  // Total num of irqs serviced since boot.
   repeated InterruptCount num_irq = 6;
 
   // Number of softirqs, broken by softirq number.
   // Populated only if SOFTIRQ_COUNTS in config.stat_counters.
-
-  // Total num of softirqs since boot.
-  optional uint64 num_softirq_total = 7;
-
-  // Per-softirq count.
-  repeated InterruptCount num_softirq = 8;
+  optional uint64 num_softirq_total = 7;    // Total num of softirqs since boot.
+  repeated InterruptCount num_softirq = 8;  // Per-softirq count.
 
   // The time at which we finish collecting this set of samples;
   // the top-level packet timestamp is the time at which
   // we begin collection.
   optional uint64 collection_end_timestamp = 9;
-
-  // Frequencies for /sys/class/devfreq/ entries in kHz.
-  message DevfreqValue {
-    optional string key = 1;
-    optional uint64 value = 2;
-  };
-
-  // One entry per device.
-  repeated DevfreqValue devfreq = 10;
 }
 
 // End of protos/perfetto/trace/sys_stats/sys_stats.proto
@@ -8338,12 +6510,6 @@
 
   // Ticks per second - sysconf(_SC_CLK_TCK).
   optional int64 hz = 3;
-
-  // The version of traced (the same returned by `traced --version`).
-  // This is a human readable string with and its format varies depending on
-  // the build system and the repo (standalone vs AOSP).
-  // This is intended for human debugging only.
-  optional string tracing_service_version = 4;
 }
 
 // End of protos/perfetto/trace/system_info.proto
@@ -8379,26 +6545,6 @@
 
   // The current value of the random number sequence used in tests.
   optional uint32 seq_value = 2;
-
-  // Monotonically increased on each packet.
-  optional uint64 counter = 3;
-
-  // No more packets should follow (from the current sequence).
-  optional bool is_last = 4;
-
-  message TestPayload {
-    repeated string str = 1;
-    repeated TestPayload nested = 2;
-
-    optional string single_string = 4;
-
-    optional int32 single_int = 5;
-    repeated int32 repeated_ints = 6;
-
-    // When 0 this is the bottom-most nested message.
-    optional uint32 remaining_nesting_depth = 3;
-  }
-  optional TestPayload payload = 5;
 }
 
 // End of protos/perfetto/trace/test_event.proto
@@ -8417,9 +6563,6 @@
 
   // Default values for TrackEvents (e.g. default track).
   optional TrackEventDefaults track_event_defaults = 11;
-
-  // Defaults for perf profiler packets (PerfSample).
-  optional PerfSampleDefaults perf_sample_defaults = 12;
 }
 // End of protos/perfetto/trace/trace_packet_defaults.proto
 
@@ -8428,17 +6571,13 @@
 // Describes a process's attributes. Emitted as part of a TrackDescriptor,
 // usually by the process's main thread.
 //
-// Next id: 8.
+// Next id: 7.
 message ProcessDescriptor {
   optional int32 pid = 1;
   repeated string cmdline = 2;
   optional string process_name = 6;
 
   optional int32 process_priority = 5;
-  // Process start time in nanoseconds.
-  // The timestamp refers to the trace clock by default. Other clock IDs
-  // provided in TracePacket are not supported.
-  optional int64 start_timestamp_ns = 7;
 
   // ---------------------------------------------------------------------------
   // Deprecated / legacy fields, which will be removed in the future:
@@ -8529,7 +6668,7 @@
 // Describes the attributes for a Chrome process. Must be paired with a
 // ProcessDescriptor in the same TrackDescriptor.
 //
-// Next id: 6.
+// Next id: 4.
 message ChromeProcessDescriptor {
   // See chromium's content::ProcessType.
   enum ProcessType {
@@ -8542,60 +6681,12 @@
     PROCESS_GPU = 6;
     PROCESS_PPAPI_PLUGIN = 7;
     PROCESS_PPAPI_BROKER = 8;
-    PROCESS_SERVICE_NETWORK = 9;
-    PROCESS_SERVICE_TRACING = 10;
-    PROCESS_SERVICE_STORAGE = 11;
-    PROCESS_SERVICE_AUDIO = 12;
-    PROCESS_SERVICE_DATA_DECODER = 13;
-    PROCESS_SERVICE_UTIL_WIN = 14;
-    PROCESS_SERVICE_PROXY_RESOLVER = 15;
-    PROCESS_SERVICE_CDM = 16;
-    PROCESS_SERVICE_VIDEO_CAPTURE = 17;
-    PROCESS_SERVICE_UNZIPPER = 18;
-    PROCESS_SERVICE_MIRRORING = 19;
-    PROCESS_SERVICE_FILEPATCHER = 20;
-    PROCESS_SERVICE_TTS = 21;
-    PROCESS_SERVICE_PRINTING = 22;
-    PROCESS_SERVICE_QUARANTINE = 23;
-    PROCESS_SERVICE_CROS_LOCALSEARCH = 24;
-    PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = 25;
-    PROCESS_SERVICE_FILEUTIL = 26;
-    PROCESS_SERVICE_PRINTCOMPOSITOR = 27;
-    PROCESS_SERVICE_PAINTPREVIEW = 28;
-    PROCESS_SERVICE_SPEECHRECOGNITION = 29;
-    PROCESS_SERVICE_XRDEVICE = 30;
-    PROCESS_SERVICE_READICON = 31;
-    PROCESS_SERVICE_LANGUAGEDETECTION = 32;
-    PROCESS_SERVICE_SHARING = 33;
-    PROCESS_SERVICE_MEDIAPARSER = 34;
-    PROCESS_SERVICE_QRCODEGENERATOR = 35;
-    PROCESS_SERVICE_PROFILEIMPORT = 36;
-    PROCESS_SERVICE_IME = 37;
-    PROCESS_SERVICE_RECORDING = 38;
-    PROCESS_SERVICE_SHAPEDETECTION = 39;
   }
   optional ProcessType process_type = 1;
   optional int32 process_priority = 2;
 
   // To support old UI. New UI should determine default sorting by process_type.
   optional int32 legacy_sort_index = 3;
-
-  // Name of the hosting app for WebView. Used to match renderer processes to
-  // their hosting apps.
-  optional string host_app_package_name = 4;
-
-  // The ID to link crashes to trace.
-  // Notes:
-  // * The ID is per process. So, each trace may contain many IDs, and you need
-  //   to look for the ID from crashed process to find the crash report.
-  // * Having a "chrome-trace-id" in crash doesn't necessarily mean we can
-  //   get an uploaded trace, since uploads could have failed.
-  // * On the other hand, if there was a crash during the session and trace was
-  //   uploaded, it is very likely to find a crash report with the trace ID.
-  // * This is not crash ID or trace ID. It is just a random 64-bit number
-  //   recorded in both traces and crashes. It is possible to have collisions,
-  //   though very rare.
-  optional uint64 crash_trace_id = 5;
 }
 
 // End of protos/perfetto/trace/track_event/chrome_process_descriptor.proto
@@ -8614,54 +6705,25 @@
     THREAD_MAIN = 1;
     THREAD_IO = 2;
 
+    // Scheduler:
     THREAD_POOL_BG_WORKER = 3;
     THREAD_POOL_FG_WORKER = 4;
-    THREAD_POOL_FG_BLOCKING = 5;
     THREAD_POOL_BG_BLOCKING = 6;
+    THREAD_POOL_FG_BLOCKING = 5;
     THREAD_POOL_SERVICE = 7;
 
+    // Compositor:
     THREAD_COMPOSITOR = 8;
     THREAD_VIZ_COMPOSITOR = 9;
     THREAD_COMPOSITOR_WORKER = 10;
 
+    // Renderer:
     THREAD_SERVICE_WORKER = 11;
-    THREAD_NETWORK_SERVICE = 12;
 
-    THREAD_CHILD_IO = 13;
-    THREAD_BROWSER_IO = 14;
-
-    THREAD_BROWSER_MAIN = 15;
-    THREAD_RENDERER_MAIN = 16;
-    THREAD_UTILITY_MAIN = 17;
-    THREAD_GPU_MAIN = 18;
-
-    THREAD_CACHE_BLOCKFILE = 19;
-    THREAD_MEDIA = 20;
-    THREAD_AUDIO_OUTPUTDEVICE = 21;
-    THREAD_AUDIO_INPUTDEVICE = 22;
-    THREAD_GPU_MEMORY = 23;
-    THREAD_GPU_VSYNC = 24;
-    THREAD_DXA_VIDEODECODER = 25;
-    THREAD_BROWSER_WATCHDOG = 26;
-    THREAD_WEBRTC_NETWORK = 27;
-    THREAD_WINDOW_OWNER = 28;
-    THREAD_WEBRTC_SIGNALING = 29;
-    THREAD_WEBRTC_WORKER = 30;
-    THREAD_PPAPI_MAIN = 31;
-    THREAD_GPU_WATCHDOG = 32;
-    THREAD_SWAPPER = 33;
-    THREAD_GAMEPAD_POLLING = 34;
-    THREAD_WEBCRYPTO = 35;
-    THREAD_DATABASE = 36;
-    THREAD_PROXYRESOLVER = 37;
-    THREAD_DEVTOOLSADB = 38;
-    THREAD_NETWORKCONFIGWATCHER = 39;
-    THREAD_WASAPI_RENDER = 40;
-
+    // Tracing related threads:
     THREAD_MEMORY_INFRA = 50;
     THREAD_SAMPLING_PROFILER = 51;
   };
-
   optional ThreadType thread_type = 1;
 
   // To support old UI. New UI should determine default sorting by thread_type.
@@ -8685,7 +6747,7 @@
 // Values for counters that are only emitted on a single packet sequence can
 // optionally be delta-encoded, see |is_incremental|.
 //
-// Next id: 7.
+// Next id: 6.
 message CounterDescriptor {
   // Built-in counters, usually with special meaning in the client library,
   // trace processor, legacy JSON format, or UI. Trace processor will infer a
@@ -8695,12 +6757,8 @@
 
     // Thread-scoped counters. The thread's track should be specified via
     // |parent_uuid| in the TrackDescriptor for such a counter.
-
-    // implies UNIT_TIME_NS.
-    COUNTER_THREAD_TIME_NS = 1;
-
-    // implies UNIT_COUNT.
-    COUNTER_THREAD_INSTRUCTION_COUNT = 2;
+    COUNTER_THREAD_TIME_NS = 1;            // implies UNIT_TIME_NS.
+    COUNTER_THREAD_INSTRUCTION_COUNT = 2;  // implies UNIT_COUNT.
   }
 
   // Type of the values for the counters - to supply lower granularity units,
@@ -8727,10 +6785,6 @@
   // field.
   optional Unit unit = 3;
 
-  // In order to use a unit not defined as a part of |Unit|, a free-form unit
-  // name can be used instead.
-  optional string unit_name = 6;
-
   // Multiplication factor of this counter's values, e.g. to supply
   // COUNTER_THREAD_TIME_NS timestamps in microseconds instead.
   optional int64 unit_multiplier = 4;
@@ -8833,45 +6887,6 @@
 
 // End of protos/perfetto/trace/trigger.proto
 
-// Begin of protos/perfetto/trace/ui_state.proto
-
-// Common state for UIs visualizing Perfetto traces.
-// This message can be appended as a TracePacket by UIs to save the
-// visible state (e.g. scroll position/zoom state) for future opening
-// of the trace.
-// Design doc: go/trace-ui-state.
-message UiState {
-  // The start and end bounds of the viewport of the UI in nanoseconds.
-  //
-  // This is the absolute time associated to slices and other events in
-  // trace processor tables (i.e. the |ts| column of most tables)
-  optional int64 timeline_start_ts = 1;
-  optional int64 timeline_end_ts = 2;
-
-  // Indicates that the given process should be highlighted by the UI.
-  message HighlightProcess {
-    oneof selector {
-      // The pid of the process to highlight. This is useful for UIs to focus
-      // on tracks of a particular process in the trace.
-      //
-      // If more than one process in a trace has the same pid, it is UI
-      // implementation specific how the process to be focused will be
-      // chosen.
-      uint32 pid = 1;
-
-      // The command line of the process to highlight; for most Android apps,
-      // this is the package name of the app. This is useful for UIs to focus
-      // on a particular app in the trace.
-      //
-      // If more than one process hasthe same cmdline, it is UI implementation
-      // specific how the process to be focused will be chosen.
-      string cmdline = 2;
-    }
-  }
-  optional HighlightProcess highlight_process = 3;
-}
-// End of protos/perfetto/trace/ui_state.proto
-
 // Begin of protos/perfetto/trace/trace_packet.proto
 
 // TracePacket is the root object of a Perfeto trace.
@@ -8893,8 +6908,8 @@
 //
 // See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
 //
-// Next reserved id: 14 (up to 15).
-// Next id: 79.
+// Next reserved id: 13 (up to 15).
+// Next id: 72.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -8921,14 +6936,12 @@
     TrackEvent track_event = 11;
 
     // IDs up to 15 are reserved. They take only one byte to encode their
-    // preamble so should be used for frequent events.
+    // preamble so should be used for freqeuent events.
 
     TraceConfig trace_config = 33;
     FtraceStats ftrace_stats = 34;
     TraceStats trace_stats = 35;
     ProfilePacket profile_packet = 37;
-    StreamingAllocation streaming_allocation = 74;
-    StreamingFree streaming_free = 75;
     BatteryCounters battery = 38;
     PowerRails power_rails = 40;
     AndroidLogPacket android_log = 39;
@@ -8952,10 +6965,6 @@
     TracingServiceEvent service_event = 69;
     InitialDisplayState initial_display_state = 70;
     GpuMemTotalEvent gpu_mem_total_event = 71;
-    MemoryTrackerSnapshot memory_tracker_snapshot = 73;
-    FrameTimelineEvent frame_timeline_event = 76;
-    AndroidEnergyEstimationBreakdown android_energy_estimation_breakdown = 77;
-    UiState ui_state = 78;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -8985,13 +6994,6 @@
     // sizes) should be less than 512KB.
     bytes compressed_packets = 50;
 
-    // Data sources can extend the trace proto with custom extension protos (see
-    // docs/design-docs/extensions.md). When they do that, the descriptor of
-    // their extension proto descriptor is serialized in this packet. This
-    // allows trace_processor to deserialize extended messages using reflection
-    // even if the extension proto is not checked in the Perfetto repo.
-    ExtensionDescriptor extension_descriptor = 72;
-
     // This field is only used for testing.
     // In previous versions of this proto this field had the id 268435455
     // This caused many problems:
diff --git a/protos/perfetto/trace/power/BUILD.gn b/protos/perfetto/trace/power/BUILD.gn
index ec595de..5664f2d 100644
--- a/protos/perfetto/trace/power/BUILD.gn
+++ b/protos/perfetto/trace/power/BUILD.gn
@@ -15,9 +15,7 @@
 import("../../../../gn/proto_library.gni")
 
 perfetto_proto_library("@TYPE@") {
-  deps = [ "../../common:@TYPE@" ]
   sources = [
-    "android_energy_estimation_breakdown.proto",
     "battery_counters.proto",
     "power_rails.proto",
   ]
diff --git a/protos/perfetto/trace/power/android_energy_estimation_breakdown.proto b/protos/perfetto/trace/power/android_energy_estimation_breakdown.proto
deleted file mode 100644
index 2ad4dd1..0000000
--- a/protos/perfetto/trace/power/android_energy_estimation_breakdown.proto
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-package perfetto.protos;
-
-import "protos/perfetto/common/android_energy_consumer_descriptor.proto";
-
-// Energy data retrieve using the ODPM(On Device Power Monitor) API.
-// This proto represents the aidl class:
-// android.hardware.power.stats.EnergyConsumerResult.
-message AndroidEnergyEstimationBreakdown {
-  // The first trace packet of each session should include a energy consumer
-  // descriptor.
-  optional AndroidEnergyConsumerDescriptor energy_consumer_descriptor = 1;
-
-  // ID of the AndroidEnergyConsumer associated with this result.  Matches
-  // the energy_consumer_id in the AndroidEnergyConsumerDescriptor that
-  // should be sent at the beginning of a trace.
-  optional int32 energy_consumer_id = 2;
-
-  // Total accumulated energy since boot in microwatt-seconds (uWs)
-  optional int64 energy_uws = 3;
-
-  message EnergyUidBreakdown {
-    // Android ID/Linux UID, the accumulated energy is attributed to.
-    optional int32 uid = 1;
-
-    // Accumulated energy since boot in microwatt-seconds (uWs).
-    optional int64 energy_uws = 2;
-  }
-  // Optional attributed energy per Android ID / Linux UID for this
-  // EnergyConsumer. Sum total of attributed energy must be less than or equal
-  // to total accumulated energy.
-  repeated EnergyUidBreakdown per_uid_breakdown = 4;
-}
diff --git a/protos/perfetto/trace/power/battery_counters.proto b/protos/perfetto/trace/power/battery_counters.proto
index 719f9a8..2337c41 100644
--- a/protos/perfetto/trace/power/battery_counters.proto
+++ b/protos/perfetto/trace/power/battery_counters.proto
@@ -25,9 +25,8 @@
   optional float capacity_percent = 2;
 
   // Instantaneous battery current in microamperes(µA).
-  // Positive values indicate current drained from the battery,
-  // negative values current feeding the battery from a charge source (USB).
-  // See https://perfetto.dev/docs/data-sources/battery-counters for more.
+  // Positive values indicate net current entering the battery from a charge
+  // source, negative values indicate net current discharging from the battery.
   optional int64 current_ua = 3;
 
   // Instantaneous battery current in microamperes(µA).
diff --git a/protos/perfetto/trace/profiling/BUILD.gn b/protos/perfetto/trace/profiling/BUILD.gn
index 62ce517..3bf8905 100644
--- a/protos/perfetto/trace/profiling/BUILD.gn
+++ b/protos/perfetto/trace/profiling/BUILD.gn
@@ -15,9 +15,7 @@
 import("../../../../gn/proto_library.gni")
 
 perfetto_proto_library("@TYPE@") {
-  deps = [ "../../common:@TYPE@" ]
   sources = [
-    "deobfuscation.proto",
     "heap_graph.proto",
     "profile_common.proto",
     "profile_packet.proto",
diff --git a/protos/perfetto/trace/profiling/deobfuscation.proto b/protos/perfetto/trace/profiling/deobfuscation.proto
deleted file mode 100644
index 94dde63..0000000
--- a/protos/perfetto/trace/profiling/deobfuscation.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message ObfuscatedMember {
-  // This is the obfuscated field name relative to the class containing the
-  // ObfuscatedMember.
-  optional string obfuscated_name = 1;
-  // If this is fully qualified (i.e. contains a '.') this is the deobfuscated
-  // field name including its class. Otherwise, this is this the unqualified
-  // deobfuscated field name relative to the class containing this
-  // ObfuscatedMember.
-  optional string deobfuscated_name = 2;
-}
-
-message ObfuscatedClass {
-  optional string obfuscated_name = 1;
-  optional string deobfuscated_name = 2;
-  // fields.
-  repeated ObfuscatedMember obfuscated_members = 3;
-  repeated ObfuscatedMember obfuscated_methods = 4;
-}
-
-message DeobfuscationMapping {
-  optional string package_name = 1;
-  optional int64 version_code = 2;
-  repeated ObfuscatedClass obfuscated_classes = 3;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace/profiling/heap_graph.proto b/protos/perfetto/trace/profiling/heap_graph.proto
index 2b7a44b..eeb5bec 100644
--- a/protos/perfetto/trace/profiling/heap_graph.proto
+++ b/protos/perfetto/trace/profiling/heap_graph.proto
@@ -16,9 +16,6 @@
 
 syntax = "proto2";
 
-// TODO(fmayer): Remove this import once clients are migrated to the new
-// location.
-import public "protos/perfetto/trace/profiling/deobfuscation.proto";
 import "protos/perfetto/trace/profiling/profile_common.proto";
 
 // These messages encode a graph of objects that retain one another. Currently
@@ -26,6 +23,29 @@
 
 package perfetto.protos;
 
+message ObfuscatedMember {
+  // This is the obfuscated field name relative to the class containing the
+  // ObfuscatedMember.
+  optional string obfuscated_name = 1;
+  // If this is fully qualified (i.e. contains a '.') this is the deobfuscated
+  // field name including its class. Otherwise, this is this the unqualified
+  // deobfuscated field name relative to the class containing this
+  // ObfuscatedMember.
+  optional string deobfuscated_name = 2;
+}
+
+message ObfuscatedClass {
+  optional string obfuscated_name = 1;
+  optional string deobfuscated_name = 2;
+  repeated ObfuscatedMember obfuscated_members = 3;
+}
+
+message DeobfuscationMapping {
+  optional string package_name = 1;
+  optional int64 version_code = 2;
+  repeated ObfuscatedClass obfuscated_classes = 3;
+}
+
 message HeapGraphRoot {
   enum Type {
     ROOT_UNKNOWN = 0;
@@ -51,58 +71,24 @@
 }
 
 message HeapGraphType {
-  enum Kind {
-    KIND_UNKNOWN = 0;
-    KIND_NORMAL = 1;
-    KIND_NOREFERENCES = 2;
-    KIND_STRING = 3;
-    KIND_ARRAY = 4;
-    KIND_CLASS = 5;
-    KIND_CLASSLOADER = 6;
-    KIND_DEXCACHE = 7;
-    KIND_SOFT_REFERENCE = 8;
-    KIND_WEAK_REFERENCE = 9;
-    KIND_FINALIZER_REFERENCE = 10;
-    KIND_PHANTOM_REFERENCE = 11;
-  };
   // TODO(fmayer): Consider removing this and using the index in the repeaed
   // field to save space.
   optional uint64 id = 1;
   optional uint64 location_id = 2;
   optional string class_name = 3;
-  // Size of objects of this type.
-  optional uint64 object_size = 4;
-  optional uint64 superclass_id = 5;
-  // Indices for InternedData.field_names for the names of the fields of
-  // instances of this class. This does NOT include the fields from
-  // superclasses. The consumer of this data needs to walk all super
-  // classes to get a full lists of fields. Objects always write the
-  // fields in order of most specific class to the furthest up superclass.
-  repeated uint64 reference_field_id = 6 [packed = true];
-  optional Kind kind = 7;
-  optional uint64 classloader_id = 8;
 }
 
 message HeapGraphObject {
-  oneof identifier {
-    uint64 id = 1;
-    uint64 id_delta = 7;
-  }
+  optional uint64 id = 1;
 
-  // Index for InternedData.types for the name of the type of this object.
+  // 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;
 
-  // Add this to all non-zero values in reference_field_id. This is used to
-  // get more compact varint encoding.
-  optional uint64 reference_field_id_base = 6;
-
   // Indices for InternedData.field_names for the name of the field referring
-  // to the object. For Android S+ and for instances of normal classes (e.g.
-  // not instances of java.lang.Class or arrays), this is instead set in the
-  // corresponding HeapGraphType, and this is left empty.
+  // to the object.
   repeated uint64 reference_field_id = 4 [packed = true];
 
   // Ids of the Object that is referred to.
@@ -128,7 +114,12 @@
   // Types used in HeapGraphObjects.
   repeated HeapGraphType types = 9;
 
-  reserved 3;
+  // Legacy way to encode types. Names here are emitted by old perfetto_hprof,
+  // which do not include the class_name. Handle like a HeapGraphType with
+  // no location_id.
+  // TODO(b/153552977): Remove this. This was was not used in any publicly
+  // available release.
+  repeated InternedString type_names = 3;
 
   // Field names for references in managed heap graph.
   repeated InternedString field_names = 4;
diff --git a/protos/perfetto/trace/profiling/profile_common.proto b/protos/perfetto/trace/profiling/profile_common.proto
index c058395..1c0bd6f 100644
--- a/protos/perfetto/trace/profiling/profile_common.proto
+++ b/protos/perfetto/trace/profiling/profile_common.proto
@@ -45,13 +45,8 @@
   // 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.
-
-  // key to InternedString
-  repeated uint64 function_name_id = 2;
-
-  // key to InternedString
-  repeated uint64 file_name_id = 3;
-
+  repeated uint64 function_name_id = 2;  // key to InternedString
+  repeated uint64 file_name_id = 3;      // key to InternedString
   repeated uint32 line_number = 4;
 }
 
@@ -89,11 +84,8 @@
 }
 
 message Mapping {
-  // Interning key.
-  optional uint64 iid = 1;
-
-  // Interning key.
-  optional uint64 build_id = 2;
+  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.
@@ -119,28 +111,19 @@
   // 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.
-
-  // This is not set on Android 10.
-  optional uint64 exact_offset = 8;
-
+  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"]
-  // id of string.
-  repeated uint64 path_string_ids = 7;
+  repeated uint64 path_string_ids = 7;  // id of string.
 }
 
 message Frame {
-  // Interning key
-  optional uint64 iid = 1;
-
+  optional uint64 iid = 1;  // Interning key
   // E.g. "fopen"
-  // id of string.
-  optional uint64 function_name_id = 2;
-
+  optional uint64 function_name_id = 2;  // id of string.
   optional uint64 mapping_id = 3;
   optional uint64 rel_pc = 4;
 }
diff --git a/protos/perfetto/trace/profiling/profile_packet.proto b/protos/perfetto/trace/profiling/profile_packet.proto
index 8548a4e..eb994b7 100644
--- a/protos/perfetto/trace/profiling/profile_packet.proto
+++ b/protos/perfetto/trace/profiling/profile_packet.proto
@@ -16,7 +16,6 @@
 
 syntax = "proto2";
 
-import "protos/perfetto/common/perf_events.proto";
 import "protos/perfetto/trace/profiling/profile_common.proto";
 
 package perfetto.protos;
@@ -41,20 +40,17 @@
     optional uint64 self_allocated = 2;
     // bytes allocated at this callstack that have been freed.
     optional uint64 self_freed = 3;
-    // deprecated self_idle.
-    reserved 7;
+    // 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;
-    // Number of allocations that were sampled at 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_count = 9;
-    // timestamp [opt]
-    optional uint64 timestamp = 4;
+    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
@@ -84,16 +80,10 @@
     optional uint64 map_reparses = 3;
     optional Histogram unwinding_time_us = 4;
     optional uint64 total_unwinding_time_us = 5;
-    optional uint64 client_spinlock_blocked_us = 6;
   }
 
   repeated ProcessHeapSamples process_dumps = 5;
   message ProcessHeapSamples {
-    enum ClientError {
-      CLIENT_ERROR_NONE = 0;
-      CLIENT_ERROR_HIT_TIMEOUT = 1;
-      CLIENT_ERROR_INVALID_STACK_BOUNDS = 2;
-    }
     optional uint64 pid = 1;
 
     // This process was profiled from startup.
@@ -110,12 +100,8 @@
 
     // If disconnected, this disconnect was caused by the client overrunning
     // the buffer.
-    // Equivalent to client_error == CLIENT_ERROR_HIT_TIMEOUT
-    // on new S builds.
     optional bool buffer_overran = 7;
 
-    optional ClientError client_error = 14;
-
     // If disconnected, this disconnected was caused by the shared memory
     // buffer being corrupted. THIS IS ALWAYS A BUG IN HEAPPROFD OR CLIENT
     // MEMORY CORRUPTION.
@@ -125,10 +111,6 @@
     // guardrails during this profiling session.
     optional bool hit_guardrail = 10;
 
-    optional string heap_name = 11;
-    optional uint64 sampling_interval_bytes = 12;
-    optional uint64 orig_sampling_interval_bytes = 13;
-
     // Timestamp of the state of the target process that this dump represents.
     // This can be different to the timestamp of the TracePackets for various
     // reasons:
@@ -159,28 +141,10 @@
   optional uint64 index = 7;
 }
 
-message StreamingAllocation {
-  // TODO(fmayer): Add callstack.
-  repeated uint64 address = 1;
-  repeated uint64 size = 2;
-  repeated uint64 sample_size = 3;
-  repeated uint64 clock_monotonic_coarse_timestamp = 4;
-  repeated uint32 heap_id = 5;
-  repeated uint64 sequence_number = 6;
-};
-
-message StreamingFree {
-  // TODO(fmayer): Add callstack.
-  repeated uint64 address = 1;
-  repeated uint32 heap_id = 2;
-  repeated uint64 sequence_number = 3;
-};
-
 // Message used to represent individual stack samples sampled at discrete
 // points in time, rather than aggregated over an interval.
 message StreamingProfilePacket {
-  // Index into InternedData.callstacks
-  repeated uint64 callstack_iid = 1;
+  repeated uint64 callstack_iid = 1;  // Index into InternedData.callstacks
   // TODO(eseckler): ThreadDescriptor-based timestamps are deprecated. Replace
   // this with ClockSnapshot-based delta encoding instead.
   repeated int64 timestamp_delta_us = 2;
@@ -211,24 +175,16 @@
     UNWIND_ERROR_MAX_FRAMES_EXCEEDED = 6;
     UNWIND_ERROR_REPEATED_FRAME = 7;
     UNWIND_ERROR_INVALID_ELF = 8;
-    UNWIND_ERROR_SYSTEM_CALL = 9;
-    UNWIND_ERROR_THREAD_TIMEOUT = 10;
-    UNWIND_ERROR_THREAD_DOES_NOT_EXIST = 11;
   }
 }
 
 // Individual performance sampling packet payload. Typically corresponds to a
 // stack sample on a configration-dependent counter overflow.
-//
-// Timestamps are within the root packet. This used to use the CLOCK_BOOTTIME
-// domain, but now the default is CLOCK_MONOTONIC_RAW which is compatible with
-// more event types.
-//
-// There are several distinct views of this message:
+// Timestamps are within the root packet (in the CLOCK_BOOTTIME domain).
+// There are three distinct views of this message:
 // * completely processed sample (callstack_iid set)
 // * indication of kernel buffer data loss (kernel_records_lost set)
 // * indication of skipped samples (sample_skipped_reason set)
-// * notable event in the sampling implementation (producer_event set)
 message PerfSample {
   optional uint32 cpu = 1;
   optional uint32 pid = 2;
@@ -237,11 +193,8 @@
   // Execution state that the process was sampled at.
   optional Profiling.CpuMode cpu_mode = 5;
 
-  // Value of the timebase counter (since the event was configured, no deltas).
-  optional uint64 timebase_count = 6;
-
   // Unwound callstack. Might be partial, in which case a synthetic "error"
-  // frame is appended, and |unwind_error| is set accordingly.
+  // frame is appended, and |unwind_error| is set appropriately.
   optional uint64 callstack_iid = 4;
 
   // If set, stack unwinding was incomplete due to an error.
@@ -273,23 +226,4 @@
   oneof optional_sample_skipped_reason {
     SampleSkipReason sample_skipped_reason = 18;
   };
-
-  // A notable event within the sampling implementation.
-  message ProducerEvent {
-    enum DataSourceStopReason {
-      PROFILER_STOP_UNKNOWN = 0;
-      PROFILER_STOP_GUARDRAIL = 1;
-    }
-    oneof optional_source_stop_reason {
-      DataSourceStopReason source_stop_reason = 1;
-    }
-  }
-  optional ProducerEvent producer_event = 19;
 }
-
-// Submessage for TracePacketDefaults.
-message PerfSampleDefaults {
-  // The sampling timebase. Might not be identical to the data source config if
-  // the implementation decided to default/override some parameters.
-  optional PerfEvents.Timebase timebase = 1;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace/profiling/smaps.proto b/protos/perfetto/trace/profiling/smaps.proto
index 92521c3..ec8ec2e 100644
--- a/protos/perfetto/trace/profiling/smaps.proto
+++ b/protos/perfetto/trace/profiling/smaps.proto
@@ -23,22 +23,6 @@
   optional uint64 size_kb = 2;
   optional uint64 private_dirty_kb = 3;
   optional uint64 swap_kb = 4;
-
-  // for field upload (instead of path).
-  optional string file_name = 5;
-
-  // TODO(crbug.com/1098746): Consider encoding this as incremental values.
-  optional uint64 start_address = 6;
-  optional uint64 module_timestamp = 7;
-  optional string module_debugid = 8;
-  optional string module_debug_path = 9;
-  optional uint32 protection_flags = 10;
-
-  optional uint64 private_clean_resident_kb = 11;
-  optional uint64 shared_dirty_resident_kb = 12;
-  optional uint64 shared_clean_resident_kb = 13;
-  optional uint64 locked_kb = 14;
-  optional uint64 proportional_resident_kb = 15;
 };
 
 message SmapsPacket {
diff --git a/protos/perfetto/trace/ps/process_stats.proto b/protos/perfetto/trace/ps/process_stats.proto
index df82c75..9c1b1aa 100644
--- a/protos/perfetto/trace/ps/process_stats.proto
+++ b/protos/perfetto/trace/ps/process_stats.proto
@@ -61,17 +61,6 @@
     optional int64 oom_score_adj = 10;
 
     repeated Thread threads = 11;
-
-    // The peak resident set size is resettable in newer Posix kernels.
-    // This field specifies if reset is supported and if the writer had reset
-    // the peaks after each process stats recording.
-    optional bool is_peak_rss_resettable = 12;
-
-    // Private, shared and swap footprint of the process as measured by
-    // Chrome. To know more about these metrics refer to:
-    // https://docs.google.com/document/d/1_WmgE1F5WUrhwkPqJis3dWyOiUmQKvpXp5cd4w86TvA
-    optional uint32 chrome_private_footprint_kb = 13;
-    optional uint32 chrome_peak_resident_set_kb = 14;
   }
   repeated Process processes = 1;
 
diff --git a/protos/perfetto/trace/ps/process_tree.proto b/protos/perfetto/trace/ps/process_tree.proto
index 67556a3..446c689 100644
--- a/protos/perfetto/trace/ps/process_tree.proto
+++ b/protos/perfetto/trace/ps/process_tree.proto
@@ -17,11 +17,6 @@
 syntax = "proto2";
 package perfetto.protos;
 
-// Metadata about the processes and threads in the trace.
-// Note: this proto was designed to be filled in by traced_probes and should
-// only be populated with accurate information coming from the system. Other
-// trace writers should prefer to fill ThreadDescriptor and ProcessDescriptor
-// in TrackDescriptor.
 message ProcessTree {
   // Representation of a thread.
   message Thread {
diff --git a/protos/perfetto/trace/sys_stats/sys_stats.proto b/protos/perfetto/trace/sys_stats/sys_stats.proto
index 30edac0..ce485f3 100644
--- a/protos/perfetto/trace/sys_stats/sys_stats.proto
+++ b/protos/perfetto/trace/sys_stats/sys_stats.proto
@@ -40,30 +40,15 @@
   // Times in each mode, since boot. Unit: nanoseconds.
   message CpuTimes {
     optional uint32 cpu_id = 1;
-
-    // Time spent in user mode.
-    optional uint64 user_ns = 2;
-
-    // Time spent in user mode (low prio).
-    optional uint64 user_ice_ns = 3;
-
-    // Time spent in system mode.
-    optional uint64 system_mode_ns = 4;
-
-    // Time spent in the idle task.
-    optional uint64 idle_ns = 5;
-
-    // Time spent waiting for I/O.
-    optional uint64 io_wait_ns = 6;
-
-    // Time spent servicing interrupts.
-    optional uint64 irq_ns = 7;
-
-    // Time spent servicing softirqs.
-    optional uint64 softirq_ns = 8;
+    optional uint64 user_ns = 2;         // Time spent in user mode.
+    optional uint64 user_ice_ns = 3;     // Time spent in user mode (low prio).
+    optional uint64 system_mode_ns = 4;  // Time spent in system mode.
+    optional uint64 idle_ns = 5;         // Time spent in the idle task.
+    optional uint64 io_wait_ns = 6;      // Time spent waiting for I/O.
+    optional uint64 irq_ns = 7;          // Time spent servicing interrupts.
+    optional uint64 softirq_ns = 8;      // Time spent servicing softirqs.
   }
-  // One entry per cpu.
-  repeated CpuTimes cpu_stat = 3;
+  repeated CpuTimes cpu_stat = 3;  // One entry per cpu.
 
   // Num processes forked since boot.
   // Populated only if FORK_COUNT in config.stat_counters.
@@ -76,31 +61,16 @@
 
   // Number of interrupts, broken by IRQ number.
   // Populated only if IRQ_COUNTS in config.stat_counters.
-
-  // Total num of irqs serviced since boot.
-  optional uint64 num_irq_total = 5;
+  optional uint64 num_irq_total = 5;  // Total num of irqs serviced since boot.
   repeated InterruptCount num_irq = 6;
 
   // Number of softirqs, broken by softirq number.
   // Populated only if SOFTIRQ_COUNTS in config.stat_counters.
-
-  // Total num of softirqs since boot.
-  optional uint64 num_softirq_total = 7;
-
-  // Per-softirq count.
-  repeated InterruptCount num_softirq = 8;
+  optional uint64 num_softirq_total = 7;    // Total num of softirqs since boot.
+  repeated InterruptCount num_softirq = 8;  // Per-softirq count.
 
   // The time at which we finish collecting this set of samples;
   // the top-level packet timestamp is the time at which
   // we begin collection.
   optional uint64 collection_end_timestamp = 9;
-
-  // Frequencies for /sys/class/devfreq/ entries in kHz.
-  message DevfreqValue {
-    optional string key = 1;
-    optional uint64 value = 2;
-  };
-
-  // One entry per device.
-  repeated DevfreqValue devfreq = 10;
 }
diff --git a/protos/perfetto/trace/system_info.proto b/protos/perfetto/trace/system_info.proto
index ddce4ca..90a7a57 100644
--- a/protos/perfetto/trace/system_info.proto
+++ b/protos/perfetto/trace/system_info.proto
@@ -31,10 +31,4 @@
 
   // Ticks per second - sysconf(_SC_CLK_TCK).
   optional int64 hz = 3;
-
-  // The version of traced (the same returned by `traced --version`).
-  // This is a human readable string with and its format varies depending on
-  // the build system and the repo (standalone vs AOSP).
-  // This is intended for human debugging only.
-  optional string tracing_service_version = 4;
 }
diff --git a/protos/perfetto/trace/test_event.proto b/protos/perfetto/trace/test_event.proto
index 67a8f60..7a6902b 100644
--- a/protos/perfetto/trace/test_event.proto
+++ b/protos/perfetto/trace/test_event.proto
@@ -25,24 +25,4 @@
 
   // The current value of the random number sequence used in tests.
   optional uint32 seq_value = 2;
-
-  // Monotonically increased on each packet.
-  optional uint64 counter = 3;
-
-  // No more packets should follow (from the current sequence).
-  optional bool is_last = 4;
-
-  message TestPayload {
-    repeated string str = 1;
-    repeated TestPayload nested = 2;
-
-    optional string single_string = 4;
-
-    optional int32 single_int = 5;
-    repeated int32 repeated_ints = 6;
-
-    // When 0 this is the bottom-most nested message.
-    optional uint32 remaining_nesting_depth = 3;
-  }
-  optional TestPayload payload = 5;
 }
diff --git a/protos/perfetto/trace/test_extensions.proto b/protos/perfetto/trace/test_extensions.proto
deleted file mode 100644
index 94118dc..0000000
--- a/protos/perfetto/trace/test_extensions.proto
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-import public "protos/perfetto/trace/track_event/track_event.proto";
-
-package perfetto.protos;
-
-// Extensions for TrackEvent used for integration testing. This proto file is
-// compiled to descriptor and is used in tools/diff_test_trace_processor.py.
-//
-// See docs/design-docs/extensions.md for more details.
-message TestExtension {
-  extend TrackEvent {
-    optional string string_extension_for_testing = 9900;
-    repeated int32 int_extension_for_testing = 9901;
-    optional string omitted_extension_for_testing = 9902;
-    optional TestExtensionChild nested_message_extension_for_testing = 9903;
-  }
-}
-
-message TestExtensionChild {
-  optional string child_field_for_testing = 1;
-}
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 2428427..01a7c5d 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -18,9 +18,7 @@
 
 import "protos/perfetto/common/trace_stats.proto";
 import "protos/perfetto/config/trace_config.proto";
-import "protos/perfetto/trace/extension_descriptor.proto";
 import "protos/perfetto/trace/android/android_log.proto";
-import "protos/perfetto/trace/android/frame_timeline_event.proto";
 import "protos/perfetto/trace/android/gpu_mem_event.proto";
 import "protos/perfetto/trace/android/graphics_frame_event.proto";
 import "protos/perfetto/trace/android/initial_display_state.proto";
@@ -38,13 +36,10 @@
 import "protos/perfetto/trace/gpu/vulkan_memory_event.proto";
 import "protos/perfetto/trace/gpu/vulkan_api_event.proto";
 import "protos/perfetto/trace/interned_data/interned_data.proto";
-import "protos/perfetto/trace/memory_graph.proto";
 import "protos/perfetto/trace/perfetto/perfetto_metatrace.proto";
 import "protos/perfetto/trace/perfetto/tracing_service_event.proto";
-import "protos/perfetto/trace/power/android_energy_estimation_breakdown.proto";
 import "protos/perfetto/trace/power/battery_counters.proto";
 import "protos/perfetto/trace/power/power_rails.proto";
-import "protos/perfetto/trace/profiling/deobfuscation.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";
@@ -61,7 +56,6 @@
 import "protos/perfetto/trace/track_event/track_event.proto";
 import "protos/perfetto/trace/trigger.proto";
 import "protos/perfetto/trace/test_event.proto";
-import "protos/perfetto/trace/ui_state.proto";
 
 package perfetto.protos;
 
@@ -84,8 +78,8 @@
 //
 // See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
 //
-// Next reserved id: 14 (up to 15).
-// Next id: 79.
+// Next reserved id: 13 (up to 15).
+// Next id: 72.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -112,14 +106,12 @@
     TrackEvent track_event = 11;
 
     // IDs up to 15 are reserved. They take only one byte to encode their
-    // preamble so should be used for frequent events.
+    // preamble so should be used for freqeuent events.
 
     TraceConfig trace_config = 33;
     FtraceStats ftrace_stats = 34;
     TraceStats trace_stats = 35;
     ProfilePacket profile_packet = 37;
-    StreamingAllocation streaming_allocation = 74;
-    StreamingFree streaming_free = 75;
     BatteryCounters battery = 38;
     PowerRails power_rails = 40;
     AndroidLogPacket android_log = 39;
@@ -143,10 +135,6 @@
     TracingServiceEvent service_event = 69;
     InitialDisplayState initial_display_state = 70;
     GpuMemTotalEvent gpu_mem_total_event = 71;
-    MemoryTrackerSnapshot memory_tracker_snapshot = 73;
-    FrameTimelineEvent frame_timeline_event = 76;
-    AndroidEnergyEstimationBreakdown android_energy_estimation_breakdown = 77;
-    UiState ui_state = 78;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -176,13 +164,6 @@
     // sizes) should be less than 512KB.
     bytes compressed_packets = 50;
 
-    // Data sources can extend the trace proto with custom extension protos (see
-    // docs/design-docs/extensions.md). When they do that, the descriptor of
-    // their extension proto descriptor is serialized in this packet. This
-    // allows trace_processor to deserialize extended messages using reflection
-    // even if the extension proto is not checked in the Perfetto repo.
-    ExtensionDescriptor extension_descriptor = 72;
-
     // This field is only used for testing.
     // In previous versions of this proto this field had the id 268435455
     // This caused many problems:
diff --git a/protos/perfetto/trace/trace_packet_defaults.proto b/protos/perfetto/trace/trace_packet_defaults.proto
index 0a25c0f..032b852 100644
--- a/protos/perfetto/trace/trace_packet_defaults.proto
+++ b/protos/perfetto/trace/trace_packet_defaults.proto
@@ -16,7 +16,6 @@
 
 syntax = "proto2";
 
-import "protos/perfetto/trace/profiling/profile_packet.proto";
 import "protos/perfetto/trace/track_event/track_event.proto";
 
 package perfetto.protos;
@@ -33,7 +32,4 @@
 
   // Default values for TrackEvents (e.g. default track).
   optional TrackEventDefaults track_event_defaults = 11;
-
-  // Defaults for perf profiler packets (PerfSample).
-  optional PerfSampleDefaults perf_sample_defaults = 12;
 }
\ 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 d1a8177..d1667d7 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -16,21 +16,14 @@
 
 perfetto_proto_library("@TYPE@") {
   sources = [
-    "chrome_application_state_info.proto",
     "chrome_compositor_scheduler_state.proto",
-    "chrome_content_settings_event_info.proto",
-    "chrome_frame_reporter.proto",
     "chrome_histogram_sample.proto",
     "chrome_keyed_service.proto",
     "chrome_latency_info.proto",
     "chrome_legacy_ipc.proto",
-    "chrome_message_pump.proto",
-    "chrome_mojo_event_info.proto",
     "chrome_process_descriptor.proto",
-    "chrome_renderer_scheduler_state.proto",
     "chrome_thread_descriptor.proto",
     "chrome_user_event.proto",
-    "chrome_window_handle_event_info.proto",
     "counter_descriptor.proto",
     "debug_annotation.proto",
     "log_message.proto",
@@ -42,10 +35,3 @@
     "track_event.proto",
   ]
 }
-
-perfetto_proto_library("track_event_@TYPE@") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "track_event.descriptor"
-  sources = [ "track_event.proto" ]
-  deps = [ ":source_set" ]
-}
diff --git a/protos/perfetto/trace/track_event/chrome_application_state_info.proto b/protos/perfetto/trace/track_event/chrome_application_state_info.proto
deleted file mode 100644
index f5884a2..0000000
--- a/protos/perfetto/trace/track_event/chrome_application_state_info.proto
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-
-// Trace event arguments for application state changes.
-message ChromeApplicationStateInfo {
-  // Enum definition taken from:
-  // https://source.chromium.org/chromium/chromium/src/+/master:base/android/application_status_listener.h
-  enum ChromeApplicationState {
-    APPLICATION_STATE_UNKNOWN = 0;
-    APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1;
-    APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2;
-    APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3;
-    APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = 4;
-  };
-  optional ChromeApplicationState application_state = 1;
-}
diff --git a/protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto b/protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto
deleted file mode 100644
index f31fa15..0000000
--- a/protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-// Details about ContentSettings trace events.
-message ChromeContentSettingsEventInfo {
-  // The number of user defined hostname patterns for content settings at
-  // browser start. Similar to UMA histogram
-  // 'ContentSettings.NumberOfExceptions'.
-  optional uint32 number_of_exceptions = 1;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace/track_event/chrome_frame_reporter.proto b/protos/perfetto/trace/track_event/chrome_frame_reporter.proto
deleted file mode 100644
index 00930c7..0000000
--- a/protos/perfetto/trace/track_event/chrome_frame_reporter.proto
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message ChromeFrameReporter {
-  enum State {
-    // The frame did not have any updates to present.
-    STATE_NO_UPDATE_DESIRED = 0;
-
-    // The frame presented all the desired updates (i.e. any updates requested
-    // from both the compositor thread and main-threads were handled).
-    STATE_PRESENTED_ALL = 1;
-
-    // The frame was presented with some updates, but also missed some updates
-    // (e.g. missed updates from the main-thread, but included updates from the
-    // compositor thread).
-    STATE_PRESENTED_PARTIAL = 2;
-
-    // The frame was dropped, i.e. some updates were desired for the frame, but
-    // was not presented.
-    STATE_DROPPED = 3;
-  };
-
-  optional State state = 1;
-
-  enum FrameDropReason {
-    REASON_UNSPECIFIED = 0;
-
-    // Frame was dropped by the display-compositor.
-    // The display-compositor may drop a frame some times (e.g. the frame missed
-    // the deadline, or was blocked on surface-sync, etc.)
-    REASON_DISPLAY_COMPOSITOR = 1;
-
-    // Frame was dropped because of the main-thread.
-    // The main-thread may cause a frame to be dropped, e.g. if the main-thread
-    // is running expensive javascript, or doing a lot of layout updates, etc.
-    REASON_MAIN_THREAD = 2;
-
-    // Frame was dropped by the client compositor.
-    // The client compositor can drop some frames too (e.g. attempting to
-    // recover latency, missing the deadline, etc.).
-    REASON_CLIENT_COMPOSITOR = 3;
-  };
-
-  // The reason is set only if |state| is not |STATE_UPDATED_ALL|.
-  optional FrameDropReason reason = 2;
-
-  optional uint64 frame_source = 3;
-  optional uint64 frame_sequence = 4;
-
-  // If this is a droped frame (i.e. if |state| is set to |STATE_DROPPED| or
-  // |STATE_PRESENTED_PARTIAL|), then indicates whether this frame impacts
-  // smoothness.
-  optional bool affects_smoothness = 5;
-
-  enum ScrollState {
-    SCROLL_NONE = 0;
-    SCROLL_MAIN_THREAD = 1;
-    SCROLL_COMPOSITOR_THREAD = 2;
-
-    // Used when it can't be determined wheter a scroll is in progress or not.
-    SCROLL_UNKNOWN = 3;
-  }
-
-  // The type of active scroll
-  optional ScrollState scroll_state = 6;
-
-  // If any main thread animation is active during this frame.
-  optional bool has_main_animation = 7;
-  // If any compositor thread animation is active during this frame.
-  optional bool has_compositor_animation = 8;
-  // If any touch-driven UX (not scroll) is active during this frame.
-  optional bool has_smooth_input_main = 9;
-
-  // Whether the frame contained any missing content (i.e. whether there was
-  // checkerboarding in the frame).
-  optional bool has_missing_content = 10;
-
-  // The id of layer_tree_host that the frame has been produced for.
-  optional uint64 layer_tree_host_id = 11;
-}
diff --git a/protos/perfetto/trace/track_event/chrome_histogram_sample.proto b/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
index d326b62..67dd28c 100644
--- a/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
+++ b/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
@@ -18,18 +18,11 @@
 
 package perfetto.protos;
 
-message HistogramName {
-  optional uint64 iid = 1;
-  optional string name = 2;
-}
-
 // An individual histogram sample logged via Chrome's UMA metrics system.
 message ChromeHistogramSample {
-  // MD5 hash of the metric name. Either |name_hash| or |name|/|name_iid| or
-  // both must be present.
+  // MD5 hash of the metric name. Either |name_hash| or |name| or both
+  // must be present.
   optional uint64 name_hash = 1;
   optional string name = 2;
   optional int64 sample = 3;
-  // Interned HistogramName. Only one of |name|, |name_iid| can be set.
-  optional uint64 name_iid = 4;
 }
diff --git a/protos/perfetto/trace/track_event/chrome_latency_info.proto b/protos/perfetto/trace/track_event/chrome_latency_info.proto
index 5412b40..ba4c767 100644
--- a/protos/perfetto/trace/track_event/chrome_latency_info.proto
+++ b/protos/perfetto/trace/track_event/chrome_latency_info.proto
@@ -21,7 +21,7 @@
 message ChromeLatencyInfo {
   optional int64 trace_id = 1;
 
-  // NEXT ID: 12
+  // NEXT ID: 11
   // All step are optional but the enum is ordered (not by number) below in the
   // order we expect them to appear if they are emitted in trace in a blocking
   // fashion.
@@ -45,9 +45,6 @@
     STEP_SWAP_BUFFERS = 6;
     // Happens on the VizCompositor in the GPU process.
     STEP_DRAW_AND_SWAP = 7;
-    // Happens on the GPU main thread after the swap has completed.
-    STEP_FINISHED_SWAP_BUFFERS = 11;
-    // See above for NEXT ID, enum steps are not ordered by tag number.
   };
 
   optional Step step = 2;
diff --git a/protos/perfetto/trace/track_event/chrome_message_pump.proto b/protos/perfetto/trace/track_event/chrome_message_pump.proto
deleted file mode 100644
index 866fdfb..0000000
--- a/protos/perfetto/trace/track_event/chrome_message_pump.proto
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Details about Chrome message pump events
-message ChromeMessagePump {
-  // True if there are sent messages in the queue.
-  optional bool sent_messages_in_queue = 1;
-  // Interned SourceLocation of IO handler that MessagePumpForIO is about to
-  // invoke.
-  optional uint64 io_handler_location_iid = 2;
-}
diff --git a/protos/perfetto/trace/track_event/chrome_mojo_event_info.proto b/protos/perfetto/trace/track_event/chrome_mojo_event_info.proto
deleted file mode 100644
index d7ace5d..0000000
--- a/protos/perfetto/trace/track_event/chrome_mojo_event_info.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Contains information to identify mojo handling events. The trace events in
-// mojo are common for all mojo interfaces and this information is used to
-// identify who is the caller or callee.
-message ChromeMojoEventInfo {
-  // Contains the interface name or the file name of the creator of a mojo
-  // handle watcher, recorded when an event if notified to the watcher. The code
-  // that runs within the track event belongs to the interface.
-  optional string watcher_notify_interface_tag = 1;
-
-  // The hash of the IPC message that is being handled.
-  optional uint32 ipc_hash = 2;
-
-  // A static string representing the mojo interface name of the message that is
-  // being handled.
-  optional string mojo_interface_tag = 3;
-}
diff --git a/protos/perfetto/trace/track_event/chrome_process_descriptor.proto b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
index ee6e196..f7d0177 100644
--- a/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
@@ -21,7 +21,7 @@
 // Describes the attributes for a Chrome process. Must be paired with a
 // ProcessDescriptor in the same TrackDescriptor.
 //
-// Next id: 6.
+// Next id: 4.
 message ChromeProcessDescriptor {
   // See chromium's content::ProcessType.
   enum ProcessType {
@@ -34,58 +34,10 @@
     PROCESS_GPU = 6;
     PROCESS_PPAPI_PLUGIN = 7;
     PROCESS_PPAPI_BROKER = 8;
-    PROCESS_SERVICE_NETWORK = 9;
-    PROCESS_SERVICE_TRACING = 10;
-    PROCESS_SERVICE_STORAGE = 11;
-    PROCESS_SERVICE_AUDIO = 12;
-    PROCESS_SERVICE_DATA_DECODER = 13;
-    PROCESS_SERVICE_UTIL_WIN = 14;
-    PROCESS_SERVICE_PROXY_RESOLVER = 15;
-    PROCESS_SERVICE_CDM = 16;
-    PROCESS_SERVICE_VIDEO_CAPTURE = 17;
-    PROCESS_SERVICE_UNZIPPER = 18;
-    PROCESS_SERVICE_MIRRORING = 19;
-    PROCESS_SERVICE_FILEPATCHER = 20;
-    PROCESS_SERVICE_TTS = 21;
-    PROCESS_SERVICE_PRINTING = 22;
-    PROCESS_SERVICE_QUARANTINE = 23;
-    PROCESS_SERVICE_CROS_LOCALSEARCH = 24;
-    PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER = 25;
-    PROCESS_SERVICE_FILEUTIL = 26;
-    PROCESS_SERVICE_PRINTCOMPOSITOR = 27;
-    PROCESS_SERVICE_PAINTPREVIEW = 28;
-    PROCESS_SERVICE_SPEECHRECOGNITION = 29;
-    PROCESS_SERVICE_XRDEVICE = 30;
-    PROCESS_SERVICE_READICON = 31;
-    PROCESS_SERVICE_LANGUAGEDETECTION = 32;
-    PROCESS_SERVICE_SHARING = 33;
-    PROCESS_SERVICE_MEDIAPARSER = 34;
-    PROCESS_SERVICE_QRCODEGENERATOR = 35;
-    PROCESS_SERVICE_PROFILEIMPORT = 36;
-    PROCESS_SERVICE_IME = 37;
-    PROCESS_SERVICE_RECORDING = 38;
-    PROCESS_SERVICE_SHAPEDETECTION = 39;
   }
   optional ProcessType process_type = 1;
   optional int32 process_priority = 2;
 
   // To support old UI. New UI should determine default sorting by process_type.
   optional int32 legacy_sort_index = 3;
-
-  // Name of the hosting app for WebView. Used to match renderer processes to
-  // their hosting apps.
-  optional string host_app_package_name = 4;
-
-  // The ID to link crashes to trace.
-  // Notes:
-  // * The ID is per process. So, each trace may contain many IDs, and you need
-  //   to look for the ID from crashed process to find the crash report.
-  // * Having a "chrome-trace-id" in crash doesn't necessarily mean we can
-  //   get an uploaded trace, since uploads could have failed.
-  // * On the other hand, if there was a crash during the session and trace was
-  //   uploaded, it is very likely to find a crash report with the trace ID.
-  // * This is not crash ID or trace ID. It is just a random 64-bit number
-  //   recorded in both traces and crashes. It is possible to have collisions,
-  //   though very rare.
-  optional uint64 crash_trace_id = 5;
 }
diff --git a/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto b/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto
deleted file mode 100644
index ade7897..0000000
--- a/protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Describes the state of the RendererScheduler for a given Renderer Process.
-
-// RAIL Mode is an indication of the kind of work that a Renderer is currently
-// performing which is in turn used to prioritise work accordingly.
-// A fuller description of these modes can be found https://web.dev/rail/
-enum ChromeRAILMode {
-  RAIL_MODE_NONE = 0;
-  RAIL_MODE_RESPONSE = 1;
-  RAIL_MODE_ANIMATION = 2;
-  RAIL_MODE_IDLE = 3;
-  RAIL_MODE_LOAD = 4;
-}
-
-// Next id: 2
-message ChromeRendererSchedulerState {
-  optional ChromeRAILMode rail_mode = 1;
-}
diff --git a/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
index f142e49..d19e3bd 100644
--- a/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
+++ b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
@@ -30,54 +30,25 @@
     THREAD_MAIN = 1;
     THREAD_IO = 2;
 
+    // Scheduler:
     THREAD_POOL_BG_WORKER = 3;
     THREAD_POOL_FG_WORKER = 4;
-    THREAD_POOL_FG_BLOCKING = 5;
     THREAD_POOL_BG_BLOCKING = 6;
+    THREAD_POOL_FG_BLOCKING = 5;
     THREAD_POOL_SERVICE = 7;
 
+    // Compositor:
     THREAD_COMPOSITOR = 8;
     THREAD_VIZ_COMPOSITOR = 9;
     THREAD_COMPOSITOR_WORKER = 10;
 
+    // Renderer:
     THREAD_SERVICE_WORKER = 11;
-    THREAD_NETWORK_SERVICE = 12;
 
-    THREAD_CHILD_IO = 13;
-    THREAD_BROWSER_IO = 14;
-
-    THREAD_BROWSER_MAIN = 15;
-    THREAD_RENDERER_MAIN = 16;
-    THREAD_UTILITY_MAIN = 17;
-    THREAD_GPU_MAIN = 18;
-
-    THREAD_CACHE_BLOCKFILE = 19;
-    THREAD_MEDIA = 20;
-    THREAD_AUDIO_OUTPUTDEVICE = 21;
-    THREAD_AUDIO_INPUTDEVICE = 22;
-    THREAD_GPU_MEMORY = 23;
-    THREAD_GPU_VSYNC = 24;
-    THREAD_DXA_VIDEODECODER = 25;
-    THREAD_BROWSER_WATCHDOG = 26;
-    THREAD_WEBRTC_NETWORK = 27;
-    THREAD_WINDOW_OWNER = 28;
-    THREAD_WEBRTC_SIGNALING = 29;
-    THREAD_WEBRTC_WORKER = 30;
-    THREAD_PPAPI_MAIN = 31;
-    THREAD_GPU_WATCHDOG = 32;
-    THREAD_SWAPPER = 33;
-    THREAD_GAMEPAD_POLLING = 34;
-    THREAD_WEBCRYPTO = 35;
-    THREAD_DATABASE = 36;
-    THREAD_PROXYRESOLVER = 37;
-    THREAD_DEVTOOLSADB = 38;
-    THREAD_NETWORKCONFIGWATCHER = 39;
-    THREAD_WASAPI_RENDER = 40;
-
+    // Tracing related threads:
     THREAD_MEMORY_INFRA = 50;
     THREAD_SAMPLING_PROFILER = 51;
   };
-
   optional ThreadType thread_type = 1;
 
   // To support old UI. New UI should determine default sorting by thread_type.
diff --git a/protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto b/protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto
deleted file mode 100644
index 8808a45..0000000
--- a/protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-// Details about HWNDMessageHandler trace events.
-message ChromeWindowHandleEventInfo {
-  optional uint32 dpi = 1;
-  optional uint32 message_id = 2;
-  optional fixed64 hwnd_ptr = 3;
-}
diff --git a/protos/perfetto/trace/track_event/counter_descriptor.proto b/protos/perfetto/trace/track_event/counter_descriptor.proto
index 2cf7762..2821842 100644
--- a/protos/perfetto/trace/track_event/counter_descriptor.proto
+++ b/protos/perfetto/trace/track_event/counter_descriptor.proto
@@ -31,7 +31,7 @@
 // Values for counters that are only emitted on a single packet sequence can
 // optionally be delta-encoded, see |is_incremental|.
 //
-// Next id: 7.
+// Next id: 6.
 message CounterDescriptor {
   // Built-in counters, usually with special meaning in the client library,
   // trace processor, legacy JSON format, or UI. Trace processor will infer a
@@ -41,12 +41,8 @@
 
     // Thread-scoped counters. The thread's track should be specified via
     // |parent_uuid| in the TrackDescriptor for such a counter.
-
-    // implies UNIT_TIME_NS.
-    COUNTER_THREAD_TIME_NS = 1;
-
-    // implies UNIT_COUNT.
-    COUNTER_THREAD_INSTRUCTION_COUNT = 2;
+    COUNTER_THREAD_TIME_NS = 1;            // implies UNIT_TIME_NS.
+    COUNTER_THREAD_INSTRUCTION_COUNT = 2;  // implies UNIT_COUNT.
   }
 
   // Type of the values for the counters - to supply lower granularity units,
@@ -73,10 +69,6 @@
   // field.
   optional Unit unit = 3;
 
-  // In order to use a unit not defined as a part of |Unit|, a free-form unit
-  // name can be used instead.
-  optional string unit_name = 6;
-
   // Multiplication factor of this counter's values, e.g. to supply
   // COUNTER_THREAD_TIME_NS timestamps in microseconds instead.
   optional int64 unit_multiplier = 4;
diff --git a/protos/perfetto/trace/track_event/debug_annotation.proto b/protos/perfetto/trace/track_event/debug_annotation.proto
index d6766cb..8b755d8 100644
--- a/protos/perfetto/trace/track_event/debug_annotation.proto
+++ b/protos/perfetto/trace/track_event/debug_annotation.proto
@@ -18,83 +18,15 @@
 
 package perfetto.protos;
 
-// Proto representation of untyped key/value annotations provided in TRACE_EVENT
-// macros. Users of the Perfetto SDK should prefer to use the
-// perfetto::TracedValue API to fill these protos, rather than filling them
-// manually.
+// 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.
 //
-// Debug annotations are intended for debug use and are not considered a stable
-// API of the trace contents. Trace-based metrics that use debug annotation
-// values are prone to breakage, so please rely on typed TrackEvent fields for
-// these instead.
-//
-// DebugAnnotations support nested arrays and dictionaries. Each entry is
-// encoded as a single DebugAnnotation message. Only dictionary entries
-// set the "name" field. The TrackEvent message forms an implicit root
-// dictionary.
-//
-// Example TrackEvent with nested annotations:
-//   track_event {
-//     debug_annotations {
-//       name: "foo"
-//       dict_entries {
-//         name: "a"
-//         bool_value: true
-//       }
-//       dict_entries {
-//         name: "b"
-//         int_value: 123
-//       }
-//     }
-//     debug_annotations {
-//       name: "bar"
-//       array_values {
-//         string_value: "hello"
-//       }
-//       array_values {
-//         string_value: "world"
-//       }
-//     }
-//   }
-//
-// Next ID: 13.
+// Next ID: 10.
 message DebugAnnotation {
-  // Name fields are set only for dictionary entries.
-  oneof name_field {
-    // interned DebugAnnotationName.
-    uint64 name_iid = 1;
-    // non-interned variant.
-    string name = 10;
-  }
-
-  oneof value {
-    bool bool_value = 2;
-    uint64 uint_value = 3;
-    int64 int_value = 4;
-    double double_value = 5;
-    string string_value = 6;
-    // Pointers are stored in a separate type as the JSON output treats them
-    // differently from other uint64 values.
-    uint64 pointer_value = 7;
-
-    // Deprecated. Use dict_entries / array_values instead.
-    NestedValue nested_value = 8;
-
-    // Legacy instrumentation may not support conversion of nested data to
-    // NestedValue yet.
-    string legacy_json_value = 9;
-  }
-
-  repeated DebugAnnotation dict_entries = 11;
-  repeated DebugAnnotation array_values = 12;
-
-  // Deprecated legacy way to use nested values. Only kept for
-  // backwards-compatibility in TraceProcessor. May be removed in the future -
-  // code filling protos should use |dict_entries| and |array_values| instead.
   message NestedValue {
     enum NestedType {
-      // leaf value.
-      UNSPECIFIED = 0;
+      UNSPECIFIED = 0;  // leaf value.
       DICT = 1;
       ARRAY = 2;
     }
@@ -108,6 +40,27 @@
     optional bool bool_value = 7;
     optional string string_value = 8;
   }
+
+  oneof name_field {
+    uint64 name_iid = 1;  // interned DebugAnnotationName.
+    string name = 10;     // non-interned variant.
+  }
+
+  oneof value {
+    bool bool_value = 2;
+    uint64 uint_value = 3;
+    int64 int_value = 4;
+    double double_value = 5;
+    string string_value = 6;
+    // Pointers are stored in a separate type as the JSON output treats them
+    // differently from other uint64 values.
+    uint64 pointer_value = 7;
+    NestedValue nested_value = 8;
+
+    // Legacy instrumentation may not support conversion of nested data to
+    // NestedValue yet.
+    string legacy_json_value = 9;
+  }
 }
 
 // --------------------
diff --git a/protos/perfetto/trace/track_event/log_message.proto b/protos/perfetto/trace/track_event/log_message.proto
index 7a8134e..55263f9 100644
--- a/protos/perfetto/trace/track_event/log_message.proto
+++ b/protos/perfetto/trace/track_event/log_message.proto
@@ -19,10 +19,8 @@
 package perfetto.protos;
 
 message LogMessage {
-  // interned SourceLocation.
-  optional uint64 source_location_iid = 1;
-  // interned LogMessageBody.
-  optional uint64 body_iid = 2;
+  optional uint64 source_location_iid = 1;  // interned SourceLocation.
+  optional uint64 body_iid = 2;             // interned LogMessageBody.
 }
 
 // --------------------
diff --git a/protos/perfetto/trace/track_event/process_descriptor.proto b/protos/perfetto/trace/track_event/process_descriptor.proto
index 1a6388d..3ba9049 100644
--- a/protos/perfetto/trace/track_event/process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/process_descriptor.proto
@@ -21,17 +21,13 @@
 // Describes a process's attributes. Emitted as part of a TrackDescriptor,
 // usually by the process's main thread.
 //
-// Next id: 8.
+// Next id: 7.
 message ProcessDescriptor {
   optional int32 pid = 1;
   repeated string cmdline = 2;
   optional string process_name = 6;
 
   optional int32 process_priority = 5;
-  // Process start time in nanoseconds.
-  // The timestamp refers to the trace clock by default. Other clock IDs
-  // provided in TracePacket are not supported.
-  optional int64 start_timestamp_ns = 7;
 
   // ---------------------------------------------------------------------------
   // Deprecated / legacy fields, which will be removed in the future:
diff --git a/protos/perfetto/trace/track_event/task_execution.proto b/protos/perfetto/trace/track_event/task_execution.proto
index eb3cde9..77f4599 100644
--- a/protos/perfetto/trace/track_event/task_execution.proto
+++ b/protos/perfetto/trace/track_event/task_execution.proto
@@ -21,6 +21,5 @@
 // TrackEvent arguments describing the execution of a task.
 message TaskExecution {
   // Source location that the task was posted from.
-  // interned SourceLocation.
-  optional uint64 posted_from_iid = 1;
+  optional uint64 posted_from_iid = 1;  // interned SourceLocation.
 }
\ No newline at end of file
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index 9c2952f..3825b76 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -19,20 +19,12 @@
 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 "protos/perfetto/trace/track_event/chrome_application_state_info.proto";
 import "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto";
-import "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto";
-import "protos/perfetto/trace/track_event/chrome_frame_reporter.proto";
 import "protos/perfetto/trace/track_event/chrome_histogram_sample.proto";
 import "protos/perfetto/trace/track_event/chrome_keyed_service.proto";
 import "protos/perfetto/trace/track_event/chrome_latency_info.proto";
 import "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto";
-import "protos/perfetto/trace/track_event/chrome_message_pump.proto";
-import "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto";
-import "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto";
 import "protos/perfetto/trace/track_event/chrome_user_event.proto";
-import "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto";
-import "protos/perfetto/trace/track_event/source_location.proto";
 
 package perfetto.protos;
 
@@ -45,7 +37,6 @@
 // referred to via the track's UUID.
 //
 // A simple TrackEvent packet specifies a timestamp, category, name and type:
-// ```protobuf
 //   trace_packet {
 //     timestamp: 1000
 //     track_event {
@@ -54,11 +45,9 @@
 //       type: TYPE_INSTANT
 //      }
 //    }
-// ```
 //
 // 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:
-// ```protobuf
 //   trace_packet {
 //     track_descriptor {
 //       track_uuid: 1234
@@ -72,11 +61,8 @@
 //       }
 //     }
 //   }
-// ```
 //
 // A pair of TYPE_SLICE_BEGIN and _END events form a slice on the track:
-//
-// ```protobuf
 //   trace_packet {
 //     timestamp: 1200
 //     track_event {
@@ -93,7 +79,7 @@
 //       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.
@@ -101,14 +87,12 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 13 (up to 15). Next id: 47.
+// Next reserved id: 13 (up to 15). Next id: 32.
 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.
-  // interned EventCategoryName.
-  repeated uint64 category_iids = 3;
-  // non-interned variant.
-  repeated string categories = 22;
+  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.
@@ -117,10 +101,8 @@
   // changing. Instead, they should use typed arguments to identify the events
   // they are interested in.
   oneof name_field {
-    // interned EventName.
-    uint64 name_iid = 10;
-    // non-interned variant.
-    string name = 23;
+    uint64 name_iid = 10;  // interned EventName.
+    string name = 23;      // non-interned variant.
   }
 
   // TODO(eseckler): Support using binary symbols for category/event names.
@@ -173,10 +155,7 @@
   // of a slice, see |extra_counter_values| and |extra_counter_track_uuids|.
   // Counter values can optionally be encoded in as delta values (positive or
   // negative) on each packet sequence (see CounterIncrementalBase).
-  oneof counter_value_field {
-    int64 counter_value = 30;
-    double double_counter_value = 44;
-  }
+  optional int64 counter_value = 30;
 
   // To encode counter values more efficiently, we support attaching additional
   // counter values to a TrackEvent of any type. All values will share the same
@@ -195,31 +174,7 @@
   repeated uint64 extra_counter_track_uuids = 31;
   repeated int64 extra_counter_values = 12;
 
-  // Counter snapshots using floating point instead of integer values.
-  repeated uint64 extra_double_counter_track_uuids = 45;
-  repeated double extra_double_counter_values = 46;
-
-  // IDs of flows originating, passing through, or ending at this event.
-  // Flow IDs are global within a trace.
-  //
-  // A flow connects a sequence of TrackEvents within or across tracks, e.g.
-  // an input event may be handled on one thread but cause another event on
-  // a different thread - a flow between the two events can associate them.
-  //
-  // The direction of the flows between events is inferred from the events'
-  // timestamps. The earliest event with the same flow ID becomes the source
-  // of the flow. Any events thereafter are intermediate steps of the flow,
-  // until the flow terminates at the last event with the flow ID.
-  //
-  // Flows can also be explicitly terminated (see |terminating_flow_ids|), so
-  // that the same ID can later be reused for another flow.
-  repeated uint64 flow_ids = 36;
-
-  // List of flow ids which should terminate on this event, otherwise same as
-  // |flow_ids|.
-  // Any one flow ID should be either listed as part of |flow_ids| OR
-  // |terminating_flow_ids|, not both.
-  repeated uint64 terminating_flow_ids = 42;
+  // TODO(eseckler): Add flow event support.
 
   // ---------------------------------------------------------------------------
   // TrackEvent arguments:
@@ -238,42 +193,8 @@
   optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   optional ChromeHistogramSample chrome_histogram_sample = 28;
   optional ChromeLatencyInfo chrome_latency_info = 29;
-  optional ChromeFrameReporter chrome_frame_reporter = 32;
-  optional ChromeApplicationStateInfo chrome_application_state_info = 39;
-  optional ChromeRendererSchedulerState chrome_renderer_scheduler_state = 40;
-  optional ChromeWindowHandleEventInfo chrome_window_handle_event_info = 41;
-  optional ChromeContentSettingsEventInfo chrome_content_settings_event_info =
-      43;
-
-  // This field is used only if the source location represents the function that
-  // executes during this event.
-  oneof source_location_field {
-    // Non-interned field.
-    SourceLocation source_location = 33;
-    // Interned field.
-    uint64 source_location_iid = 34;
-  }
-
-  optional ChromeMessagePump chrome_message_pump = 35;
-  optional ChromeMojoEventInfo chrome_mojo_event_info = 38;
-
   // New argument types go here :)
 
-  // Extension range for typed events defined externally.
-  // See docs/design-docs/extensions.md for more details.
-  //
-  // Extension support is work-in-progress, in the future the way to reserve a
-  // subrange for a particular project will be described here and in the design
-  // document linked above.
-  //
-  // Contact perfetto-dev@googlegroups.com if you are interested in a subrange
-  // for your project.
-
-  // Extension range for future use.
-  extensions 1000 to 9899;
-  // Reserved for Perfetto unit and integration tests.
-  extensions 9900 to 10000;
-
   // ---------------------------------------------------------------------------
   // Deprecated / legacy event fields, which will be removed in the future:
   // ---------------------------------------------------------------------------
@@ -332,8 +253,7 @@
   // Next id: 20.
   message LegacyEvent {
     // Deprecated, use TrackEvent::name(_iid) instead.
-    // interned EventName.
-    optional uint64 name_iid = 1;
+    optional uint64 name_iid = 1;  // interned EventName.
     optional int32 phase = 2;
     optional int64 duration_us = 3;
     optional int64 thread_duration_us = 4;
@@ -341,8 +261,7 @@
     // Elapsed retired instruction count during the event.
     optional int64 thread_instruction_delta = 15;
 
-    // used to be |flags|.
-    reserved 5;
+    reserved 5;  // used to be |flags|.
 
     oneof id {
       uint64 unscoped_id = 6;
@@ -395,7 +314,6 @@
 message TrackEventDefaults {
   optional uint64 track_uuid = 11;
   repeated uint64 extra_counter_track_uuids = 31;
-  repeated uint64 extra_double_counter_track_uuids = 45;
 
   // TODO(eseckler): Support default values for more TrackEvent fields.
 }
diff --git a/protos/perfetto/trace/ui_state.proto b/protos/perfetto/trace/ui_state.proto
deleted file mode 100644
index 149730d..0000000
--- a/protos/perfetto/trace/ui_state.proto
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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";
-
-package perfetto.protos;
-
-// Common state for UIs visualizing Perfetto traces.
-// This message can be appended as a TracePacket by UIs to save the
-// visible state (e.g. scroll position/zoom state) for future opening
-// of the trace.
-// Design doc: go/trace-ui-state.
-message UiState {
-  // The start and end bounds of the viewport of the UI in nanoseconds.
-  //
-  // This is the absolute time associated to slices and other events in
-  // trace processor tables (i.e. the |ts| column of most tables)
-  optional int64 timeline_start_ts = 1;
-  optional int64 timeline_end_ts = 2;
-
-  // Indicates that the given process should be highlighted by the UI.
-  message HighlightProcess {
-    oneof selector {
-      // The pid of the process to highlight. This is useful for UIs to focus
-      // on tracks of a particular process in the trace.
-      //
-      // If more than one process in a trace has the same pid, it is UI
-      // implementation specific how the process to be focused will be
-      // chosen.
-      uint32 pid = 1;
-
-      // The command line of the process to highlight; for most Android apps,
-      // this is the package name of the app. This is useful for UIs to focus
-      // on a particular app in the trace.
-      //
-      // If more than one process hasthe same cmdline, it is UI implementation
-      // specific how the process to be focused will be chosen.
-      string cmdline = 2;
-    }
-  }
-  optional HighlightProcess highlight_process = 3;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace_processor/BUILD.gn b/protos/perfetto/trace_processor/BUILD.gn
index ee1c795..2446bef 100644
--- a/protos/perfetto/trace_processor/BUILD.gn
+++ b/protos/perfetto/trace_processor/BUILD.gn
@@ -17,11 +17,11 @@
 
 perfetto_proto_library("@TYPE@") {
   proto_generators = [ "zero" ]
-  deps = [ "../common:zero" ]  # ../common:zero needed for descriptor.proto.
   sources = []
   foreach(source, trace_processor_protos) {
     sources += [ "$source.proto" ]
   }
+  deps = [ "../metrics:@TYPE@" ]
 }
 
 perfetto_proto_library("metrics_impl_zero") {
diff --git a/protos/perfetto/trace_processor/trace_processor.proto b/protos/perfetto/trace_processor/trace_processor.proto
index f32745b..66bbe63 100644
--- a/protos/perfetto/trace_processor/trace_processor.proto
+++ b/protos/perfetto/trace_processor/trace_processor.proto
@@ -18,7 +18,7 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/common/descriptor.proto";
+import "protos/perfetto/metrics/metrics.proto";
 
 // This file defines the schema for {,un}marshalling arguments and return values
 // when interfacing to the trace processor binary interface.
@@ -44,7 +44,6 @@
 }
 
 // Output for the /raw_query endpoint.
-// DEPRECATED, use /query. See QueryResult below.
 message RawQueryResult {
   message ColumnDesc {
     optional string name = 1;
@@ -75,60 +74,6 @@
   optional uint64 execution_time_ns = 5;
 }
 
-// Output for the /query endpoint.
-// Returns a query result set, grouping cells into batches. Batching allows a
-// more efficient encoding of results, at the same time allowing to return
-// O(M) results in a pipelined fashion, without full-memory buffering.
-// Batches are split when either a large number of cells (~thousands) is reached
-// or the string/blob payload becomes too large (~hundreds of KB).
-// Data is batched in cells, scanning results by row -> column. e.g. if a query
-// returns 3 columns and 2 rows, the cells will be emitted in this order:
-// R0C0, R0C1, R0C2, R1C0, R1C1, R1C2.
-message QueryResult {
-  // This determines the number and names of columns.
-  repeated string column_names = 1;
-
-  // If non-emty the query returned an error. Note that some cells might still
-  // be present, if the error happened while iterating.
-  optional string error = 2;
-
-  // A batch contains an array of cell headers, stating the type of each cell.
-  // The payload of each cell is stored in the corresponding xxx_cells field
-  // below (unless the cell is NULL).
-  // So if |cells| contains: [VARINT, FLOAT64, VARINT, STRING], the results will
-  // be available as:
-  // [varint_cells[0], float64_cells[0], varint_cells[1], string_cells[0]].
-  message CellsBatch {
-    enum CellType {
-      CELL_INVALID = 0;
-      CELL_NULL = 1;
-      CELL_VARINT = 2;
-      CELL_FLOAT64 = 3;
-      CELL_STRING = 4;
-      CELL_BLOB = 5;
-    }
-    repeated CellType cells = 1 [packed = true];
-
-    repeated int64 varint_cells = 2 [packed = true];
-    repeated double float64_cells = 3 [packed = true];
-    repeated bytes blob_cells = 4;
-
-    // The string cells are concatenated in a single field. Each cell is
-    // NUL-terminated. This is because JS incurs into a non-negligible overhead
-    // when decoding strings and one decode + split('\0') is measurably faster
-    // than decoding N strings. See goto.google.com/postmessage-benchmark .
-    // \0-concatenated.
-    optional string string_cells = 5;
-
-    // If true this is the last batch for the query result.
-    optional bool is_last_batch = 6;
-
-    // Padding field. Used only to re-align and fill gaps in the binary format.
-    reserved 7;
-  }
-  repeated CellsBatch batch = 3;
-}
-
 // Input for the /status endpoint.
 message StatusArgs {}
 
@@ -142,28 +87,12 @@
 
 // Input for the /compute_metric endpoint.
 message ComputeMetricArgs {
-  enum ResultFormat {
-    BINARY_PROTOBUF = 0;
-    TEXTPROTO = 1;
-  }
   repeated string metric_names = 1;
-  optional ResultFormat format = 2;
 }
 
 // Output for the /compute_metric endpoint.
 message ComputeMetricResult {
-  oneof result {
-    // This is meant to contain a perfetto.protos.TraceMetrics. We're using
-    // bytes instead of the actual type because we do not want to generate
-    // protozero code for the metrics protos. We always encode/decode metrics
-    // using a reflection based mechanism that does not require the compiled C++
-    // code. This allows us to read in new protos at runtime.
-    bytes metrics = 1;
-
-    // A perfetto.protos.TraceMetrics formatted as prototext.
-    string metrics_as_prototext = 3;
-  }
-
+  optional perfetto.protos.TraceMetrics metrics = 1;
   optional string error = 2;
 }
 
@@ -183,17 +112,3 @@
   optional bytes metatrace = 1;
   optional string error = 2;
 }
-
-// Convenience wrapper for multiple descriptors, similar to FileDescriptorSet
-// in descriptor.proto.
-message DescriptorSet {
-  repeated DescriptorProto descriptors = 1;
-}
-
-// Input for the /get_metric_descriptors endpoint.
-message GetMetricDescriptorsArgs {}
-
-// Output for the /get_metric_descriptors endpoint.
-message GetMetricDescriptorsResult {
-  optional DescriptorSet descriptor_set = 1;
-}
diff --git a/protos/third_party/chromium/BUILD.gn b/protos/third_party/chromium/BUILD.gn
deleted file mode 100644
index cff5b38..0000000
--- a/protos/third_party/chromium/BUILD.gn
+++ /dev/null
@@ -1,16 +0,0 @@
-import("../../../gn/perfetto.gni")
-import("../../../gn/proto_library.gni")
-import("sources.gni")
-
-perfetto_proto_library("chrome_track_event_@TYPE@") {
-  proto_generators = [ "descriptor" ]
-  sources = chrome_track_event_sources
-  generate_descriptor = "chrome_track_event.descriptor"
-  deps = [ "../../perfetto/trace/track_event:source_set" ]
-
-  # When rolled into Chrome, extension descriptor is going to be linked into
-  # binary, therefore increasing its size. Including imports means that the
-  # full TrackEvent descriptor is going to be included as well, increasing the
-  # binary size unnecessarily. Therefore, exclude_imports is used.
-  exclude_imports = true
-}
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
deleted file mode 100644
index 813b174..0000000
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-import public "protos/perfetto/trace/track_event/track_event.proto";
-
-package perfetto.protos;
-
-enum ChromeAppState {
-  APP_STATE_FOREGROUND = 1;
-  APP_STATE_BACKGROUND = 2;
-}
-
-enum MemoryPressureLevel {
-  MEMORY_PRESSURE_LEVEL_NONE = 0;
-  MEMORY_PRESSURE_LEVEL_MODERATE = 1;
-  MEMORY_PRESSURE_LEVEL_CRITICAL = 2;
-}
-
-message ChromeMemoryPressureNotification {
-  optional MemoryPressureLevel level = 1;
-
-  // ID of interned source location where MemoryPressureListener was created
-  optional uint64 creation_location_iid = 2;
-}
-
-message ChromeTaskAnnotator {
-  optional uint32 ipc_hash = 1;
-}
-
-message ChromeBrowserContext {
-  optional fixed64 ptr = 1;
-}
-
-message ChromeProfileDestroyer {
-  optional fixed64 profile_ptr = 1;
-  optional bool is_off_the_record = 2;
-  optional string otr_profile_id = 3;
-  optional uint32 host_count_at_creation = 4;
-  optional uint32 host_count_at_destruction = 5;
-  optional fixed64 render_process_host_ptr = 6;
-}
-
-message ChromeTaskPostedToDisabledQueue {
-  optional string task_queue_name = 1;
-  optional uint64 time_since_disabled_ms = 2;
-  optional uint32 ipc_hash = 3;
-  optional uint64 source_location_iid = 4;
-}
-
-message ChromeRasterTask {
-  optional int64 source_frame_number = 1;
-}
-
-message ChromeMessagePumpForUI {
-  // The MSG defined in winuser.h.
-  optional uint32 message_id = 1;
-}
-
-// An enumeration specifying the reason of the RenderFrame deletion.
-// This is copied from content/common/frame.mojom.
-enum FrameDeleteIntention {
-  // The frame being deleted isn't a (speculative) main frame.
-  FRAME_DELETE_INTENTION_NOT_MAIN_FRAME = 0;
-
-  // The frame being deleted is a speculative main frame, and it is being
-  // deleted as part of the shutdown for that WebContents. The entire RenderView
-  // etc will be destroyed by a separate IPC sent later.
-  FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_SHUTDOWN = 1;
-
-  // The frame being deleted is a speculative main frame, and it is being
-  // deleted because the speculative navigation was cancelled. This is not part
-  // of shutdown.
-  FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_NAVIGATION_CANCELLED = 2;
-}
-
-message RenderFrameImplDeletion {
-  // The intent for the deletion.
-  optional FrameDeleteIntention intent = 1;
-
-  // Whether the frame that's about to be deleted has a pending navigation
-  // commit.
-  optional bool has_pending_commit = 2;
-
-  // Whether the frame that's about to be deleted has a pending cross-document
-  // navigation commit.
-  optional bool has_pending_cross_document_commit = 3;
-
-  // The FrameTreeNode ID of the frame that's about to be deleted.
-  optional uint64 frame_tree_node_id = 4;
-}
-
-enum ShouldSwapBrowsingInstance {
-  // No BrowsingInstance swap.
-  SHOULD_SWAP_BROWSING_INSTANCE_NO = 0;
-
-  // Forced BrowsingInstance swap.
-  SHOULD_SWAP_BROWSING_INSTANCE_YES_FORCE_SWAP = 1;
-
-  // Proactive BrowsingInstance swap for cross-site navigation.
-  SHOULD_SWAP_BROWSING_INSTANCE_YES_CROSS_SITE_PROACTIVE_SWAP = 2;
-
-  // Proactive BrowsingInstance swap for same-site navigation.
-  SHOULD_SWAP_BROWSING_INSTANCE_YES_SAME_SITE_PROACTIVE_SWAP = 3;
-}
-
-message ShouldSwapBrowsingInstancesResult {
-  // The FrameTreeNode ID.
-  optional uint64 frame_tree_node_id = 1;
-
-  // Whether a navigation will do a BrowsingInstance swap or not.
-  optional ShouldSwapBrowsingInstance result = 2;
-}
-
-message FrameTreeNodeInfo {
-  // The FrameTreeNode ID.
-  optional uint64 frame_tree_node_id = 1;
-
-  // Whether the frame is a main frame or not.
-  optional bool is_main_frame = 2;
-
-  // Whether there's a speculative RenderFrameHost or not.
-  optional bool has_speculative_render_frame_host = 3;
-}
-
-message ChromeHashedPerformanceMark {
-  optional uint32 site_hash = 1;
-  optional string site = 2;
-  optional uint32 mark_hash = 3;
-  optional string mark = 4;
-}
-
-message ChromeTrackEvent {
-  // Extension range for Chrome: 1000-1999
-  // Next ID: 1012
-  extend TrackEvent {
-    optional ChromeAppState chrome_app_state = 1000;
-
-    optional ChromeMemoryPressureNotification
-        chrome_memory_pressure_notification = 1001;
-
-    optional ChromeTaskAnnotator chrome_task_annotator = 1002;
-
-    optional ChromeBrowserContext chrome_browser_context = 1003;
-
-    optional ChromeProfileDestroyer chrome_profile_destroyer = 1004;
-
-    optional ChromeTaskPostedToDisabledQueue
-        chrome_task_posted_to_disabled_queue = 1005;
-
-    optional ChromeRasterTask chrome_raster_task = 1006;
-
-    optional ChromeMessagePumpForUI chrome_message_pump_for_ui = 1007;
-
-    optional RenderFrameImplDeletion render_frame_impl_deletion = 1008;
-
-    optional ShouldSwapBrowsingInstancesResult
-        should_swap_browsing_instances_result = 1009;
-
-    optional FrameTreeNodeInfo frame_tree_node_info = 1010;
-
-    optional ChromeHashedPerformanceMark chrome_hashed_performance_mark = 1011;
-  }
-}
diff --git a/protos/third_party/chromium/sources.gni b/protos/third_party/chromium/sources.gni
deleted file mode 100644
index cef4a8e..0000000
--- a/protos/third_party/chromium/sources.gni
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# List of .proto files used when defining Chromium extensions for typed events.
-# New files should be added to this list.
-#
-# DO NOT EDIT THIS AT THE MOMENT. This file has to be supported in Perfetto
-# first in order to be useful.
-# TODO(b/181318121): Implement the support in Perfetto and remove the warning.
-chrome_track_event_sources = [ "chrome_track_event.proto" ]
diff --git a/protos/third_party/pprof/profile.proto b/protos/third_party/pprof/profile.proto
index 21282c5..23aadc4 100644
--- a/protos/third_party/pprof/profile.proto
+++ b/protos/third_party/pprof/profile.proto
@@ -69,12 +69,10 @@
   repeated string string_table = 6;
   // frames with Function.function_name fully matching the following
   // regexp will be dropped from the samples, along with their successors.
-  // Index into string table.
-  int64 drop_frames = 7;
+  int64 drop_frames = 7;  // Index into string table.
   // frames with Function.function_name fully matching the following
   // regexp will be kept, even if it matches drop_functions.
-  // Index into string table.
-  int64 keep_frames = 8;
+  int64 keep_frames = 8;  // Index into string table.
 
   // The following fields are informational, do not affect
   // interpretation of results.
@@ -89,8 +87,7 @@
   // The number of events between sampled occurrences.
   int64 period = 12;
   // Freeform text associated to the profile.
-  // Indices into string table.
-  repeated int64 comment = 13;
+  repeated int64 comment = 13;  // Indices into string table.
   // Index into the string table of the type of the preferred sample
   // value. If unset, clients should default to the last sample value.
   int64 default_sample_type = 14;
@@ -98,10 +95,8 @@
 
 // ValueType describes the semantics and measurement units of a value.
 message ValueType {
-  // Index into string table.
-  int64 type = 1;
-  // Index into string table.
-  int64 unit = 2;
+  int64 type = 1;  // Index into string table.
+  int64 unit = 2;  // Index into string table.
 }
 
 // Each Sample records values encountered in some program
@@ -125,14 +120,10 @@
 }
 
 message Label {
-  // Index into string table
-  int64 key = 1;
+  int64 key = 1;  // Index into string table
 
   // At most one of the following must be present
-
-  // Index into string table
-  int64 str = 2;
-
+  int64 str = 2;  // Index into string table
   int64 num = 3;
 
   // Should only be present when num is present.
@@ -142,9 +133,7 @@
   // Consumers may also  interpret units like "bytes" and "kilobytes" as memory
   // units and units like "seconds" and "nanoseconds" as time units,
   // and apply appropriate unit conversions to these.
-
-  // Index into string table
-  int64 num_unit = 4;
+  int64 num_unit = 4;  // Index into string table
 }
 
 message Mapping {
@@ -159,13 +148,11 @@
   // The object this entry is loaded from.  This can be a filename on
   // disk for the main binary and shared libraries, or virtual
   // abstractions like "[vdso]".
-  // Index into string table
-  int64 filename = 5;
+  int64 filename = 5;  // Index into string table
   // A string that uniquely identifies a particular program version
   // with high probability. E.g., for binaries generated by GNU tools,
   // it could be the contents of the .note.gnu.build-id field.
-  // Index into string table
-  int64 build_id = 6;
+  int64 build_id = 6;  // Index into string table
 
   // The following fields indicate the resolution of symbolic info.
   bool has_functions = 7;
@@ -216,15 +203,12 @@
   // Unique nonzero id for the function.
   uint64 id = 1;
   // Name of the function, in human-readable form if available.
-  // Index into string table
-  int64 name = 2;
+  int64 name = 2;  // Index into string table
   // Name of the function, as identified by the system.
   // For instance, it can be a C++ mangled name.
-  // Index into string table
-  int64 system_name = 3;
+  int64 system_name = 3;  // Index into string table
   // Source file containing the function.
-  // Index into string table
-  int64 filename = 4;
+  int64 filename = 4;  // Index into string table
   // Line number in source file.
   int64 start_line = 5;
 }
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 02d07fb..956e07c 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -14,67 +14,27 @@
 
 import("../../gn/perfetto.gni")
 
-# This GN file should not be referenced in chromium builds.
-assert(!build_with_chromium)
-
 # 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.
-# perfetto_build_with_android is only true when running the GN -> Android.bp
-# build file translator //tools/gen_android_bp .
-if (perfetto_build_with_android) {
-  shared_library("libperfetto_android_internal") {
-    deps = [
-      ":headers",
-      "../../gn:default_deps",
-    ]
-    sources = [
-      "atrace_hal.cc",
-      "health_hal.cc",
-      "incident_service.cc",
-      "power_stats.cc",
-      "statsd_logging.cc",
-      "tracing_service_proxy.cc",
-    ]
-    libs = [
-      "android.hardware.health@2.0",
-      "android.hardware.power.stats@1.0",
-      "android.hardware.power.stats-V1-cpp",
-      "android.hardware.atrace@1.0",
-      "statslog_perfetto",
-      "statssocket",
-      "cutils",
-      "base",
-      "binder",
-      "log",
-      "hidlbase",
-      "incident",
-      "services",
-      "tracingproxy",
-      "utils",
-    ]
-
-    # This target should never depend on any other perfetto target to avoid ODR
-    # violation by doubly linking code in two .so(s) loaded in the same exe.
-    assert_no_deps = [
-      "//include/*",
-      "//src/base/*",
-      "//src/tracing/*",
-    ]
-  }
-}  # if (perfetto_build_with_android)
+shared_library("libperfetto_android_internal") {
+  deps = [
+    ":android_internal",
+    "../../gn:default_deps",
+  ]
+}
 
 source_set("headers") {
   deps = [
     "../../gn:default_deps",
-    "../android_stats:perfetto_atoms",
+    "../../src/perfetto_cmd:perfetto_atoms",
   ]
   sources = [
     "atrace_hal.h",
+    "dropbox_service.h",
     "health_hal.h",
     "incident_service.h",
-    "power_stats.h",
+    "power_stats_hal.h",
     "statsd_logging.h",
-    "tracing_service_proxy.h",
   ]
 }
 
@@ -88,7 +48,48 @@
     "lazy_library_loader.cc",
     "lazy_library_loader.h",
   ]
-  if (!is_win) {
-    libs = [ "dl" ]
+  libs = [ "dl" ]
+}
+
+# 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" ]
+  deps = [
+    ":headers",
+    "../../gn:default_deps",
+  ]
+  if (perfetto_build_with_android) {
+    sources = [
+      "atrace_hal.cc",
+      "dropbox_service.cc",
+      "health_hal.cc",
+      "incident_service.cc",
+      "power_stats_hal.cc",
+      "statsd_logging.cc",
+    ]
+    libs = [
+      "android.hardware.health@2.0",
+      "android.hardware.power.stats@1.0",
+      "android.hardware.atrace@1.0",
+      "statslog_perfetto",
+      "statssocket",
+      "cutils",
+      "base",
+      "binder",
+      "log",
+      "hidlbase",
+      "incident",
+      "services",
+      "utils",
+    ]
   }
+
+  # This target should never depend on any other perfetto target to avoid ODR
+  # violation by doubly linking code in two .so(s) loaded in the same exe.
+  assert_no_deps = [
+    "//include/*",
+    "//src/base/*",
+    "//src/tracing/*",
+  ]
 }
diff --git a/src/android_internal/dropbox_service.cc b/src/android_internal/dropbox_service.cc
new file mode 100644
index 0000000..8088028
--- /dev/null
+++ b/src/android_internal/dropbox_service.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
new file mode 100644
index 0000000..6365355
--- /dev/null
+++ b/src/android_internal/dropbox_service.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/lazy_library_loader.cc b/src/android_internal/lazy_library_loader.cc
index baf6072..27c2d44 100644
--- a/src/android_internal/lazy_library_loader.cc
+++ b/src/android_internal/lazy_library_loader.cc
@@ -16,22 +16,12 @@
 
 #include "src/android_internal/lazy_library_loader.h"
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-namespace perfetto {
-namespace android_internal {
-void* LazyLoadFunction(const char*) {
-  PERFETTO_CHECK(false);
-}
-}  // namespace android_internal
-}  // namespace perfetto
-#else
-
 #include <dlfcn.h>
 #include <stdlib.h>
 
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
+
 namespace perfetto {
 namespace android_internal {
 
@@ -77,5 +67,3 @@
 
 }  // namespace android_internal
 }  // namespace perfetto
-
-#endif  // !OS_WIN
diff --git a/src/android_internal/power_stats.cc b/src/android_internal/power_stats.cc
deleted file mode 100644
index 34da342..0000000
--- a/src/android_internal/power_stats.cc
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/power_stats.h"
-
-#include "perfetto/ext/base/utils.h"
-
-#include <string.h>
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-// Legacy HAL interfacte for devices shipped before Android S.
-#include <android/hardware/power/stats/1.0/IPowerStats.h>
-
-// AIDL interface for Android S+.
-#include <android/hardware/power/stats/IPowerStats.h>
-
-#include <binder/IServiceManager.h>
-
-namespace perfetto {
-namespace android_internal {
-
-namespace hal = android::hardware::power::stats::V1_0;
-namespace aidl = android::hardware::power::stats;
-
-namespace {
-
-// Common interface for data from power stats service.  Devices prior to
-// Android S, uses the HAL interface while device from Android S or later
-// uses the AIDL interfact.
-class PowerStatsDataProvider {
- public:
-  virtual bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) = 0;
-  virtual bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) = 0;
-
-  // Available from Android S+.
-  virtual bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
-                                     size_t* size_of_arr) = 0;
-  virtual bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
-                                 size_t* size_of_arr) = 0;
-  virtual ~PowerStatsDataProvider() = default;
-};
-
-class PowerStatsHalDataProvider : public PowerStatsDataProvider {
- public:
-  bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
-  bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
-  bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
-                             size_t* size_of_arr) override;
-  bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
-                         size_t* size_of_arr) override;
-
-  PowerStatsHalDataProvider() = default;
-  ~PowerStatsHalDataProvider() override = default;
-
- private:
-  android::sp<hal::IPowerStats> svc_;
-  hal::IPowerStats* MaybeGetService();
-};
-
-class PowerStatsAidlDataProvider : public PowerStatsDataProvider {
- public:
-  static constexpr char INSTANCE[] =
-      "android.hardware.power.stats.IPowerStats/default";
-
-  bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
-  bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
-  bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
-                             size_t* size_of_arr) override;
-  bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
-                         size_t* size_of_arr) override;
-
-  PowerStatsAidlDataProvider() = default;
-  ~PowerStatsAidlDataProvider() override = default;
-
- private:
-  android::sp<aidl::IPowerStats> svc_;
-
-  aidl::IPowerStats* MaybeGetService();
-  void ResetService();
-};
-
-PowerStatsDataProvider* GetDataProvider() {
-  static std::unique_ptr<PowerStatsDataProvider> data_provider;
-  if (data_provider == nullptr) {
-    const android::sp<android::IServiceManager> sm =
-        android::defaultServiceManager();
-    if (sm->isDeclared(
-            android::String16(PowerStatsAidlDataProvider::INSTANCE))) {
-      data_provider = std::make_unique<PowerStatsAidlDataProvider>();
-    } else {
-      data_provider = std::make_unique<PowerStatsHalDataProvider>();
-    }
-  }
-  return data_provider.get();
-}
-
-}  // anonymous namespace
-
-bool GetAvailableRails(RailDescriptor* descriptor, size_t* size_of_arr) {
-  return GetDataProvider()->GetAvailableRails(descriptor, size_of_arr);
-}
-
-bool GetRailEnergyData(RailEnergyData* data, size_t* size_of_arr) {
-  return GetDataProvider()->GetRailEnergyData(data, size_of_arr);
-}
-
-bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers, size_t* size_of_arr) {
-  return GetDataProvider()->GetEnergyConsumerInfo(consumers, size_of_arr);
-}
-
-bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
-                       size_t* size_of_arr) {
-  return GetDataProvider()->GetEnergyConsumed(breakdown, size_of_arr);
-}
-
-/*** Power Stats HAL Implemenation *******************************************/
-
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-
-hal::IPowerStats* PowerStatsHalDataProvider::MaybeGetService() {
-  if (svc_ == nullptr) {
-    svc_ = hal::IPowerStats::tryGetService();
-  }
-  return svc_.get();
-}
-
-bool PowerStatsHalDataProvider::GetAvailableRails(
-    RailDescriptor* rail_descriptors,
-    size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-  hal::IPowerStats* svc = MaybeGetService();
-  if (svc == nullptr) {
-    return false;
-  }
-
-  hal::Status status;
-  auto rails_cb = [rail_descriptors, size_of_arr, &in_array_size, &status](
-                      hidl_vec<hal::RailInfo> r, hal::Status s) {
-    status = s;
-    if (status == hal::Status::SUCCESS) {
-      *size_of_arr = std::min(in_array_size, r.size());
-      for (int i = 0; i < *size_of_arr; ++i) {
-        const hal::RailInfo& rail_info = r[i];
-        RailDescriptor& descriptor = rail_descriptors[i];
-
-        descriptor.index = rail_info.index;
-        descriptor.sampling_rate = rail_info.samplingRate;
-
-        strncpy(descriptor.rail_name, rail_info.railName.c_str(),
-                sizeof(descriptor.rail_name));
-        strncpy(descriptor.subsys_name, rail_info.subsysName.c_str(),
-                sizeof(descriptor.subsys_name));
-        descriptor.rail_name[sizeof(descriptor.rail_name) - 1] = '\0';
-        descriptor.subsys_name[sizeof(descriptor.subsys_name) - 1] = '\0';
-      }
-    }
-  };
-
-  Return<void> ret = svc->getRailInfo(rails_cb);
-  return status == hal::Status::SUCCESS;
-}
-
-bool PowerStatsHalDataProvider::GetRailEnergyData(
-    RailEnergyData* rail_energy_array,
-    size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-
-  hal::IPowerStats* svc = MaybeGetService();
-  if (svc == nullptr) {
-    return false;
-  }
-
-  hal::Status status;
-  auto energy_cb = [rail_energy_array, size_of_arr, &in_array_size, &status](
-                       hidl_vec<hal::EnergyData> m, hal::Status s) {
-    status = s;
-    if (status == hal::Status::SUCCESS) {
-      *size_of_arr = std::min(in_array_size, m.size());
-      for (int i = 0; i < *size_of_arr; ++i) {
-        const hal::EnergyData& measurement = m[i];
-        RailEnergyData& element = rail_energy_array[i];
-
-        element.index = measurement.index;
-        element.timestamp = measurement.timestamp;
-        element.energy = measurement.energy;
-      }
-    }
-  };
-
-  Return<void> ret = svc_->getEnergyData(hidl_vec<uint32_t>(), energy_cb);
-  return status == hal::Status::SUCCESS;
-}
-
-bool PowerStatsHalDataProvider::GetEnergyConsumerInfo(EnergyConsumerInfo*,
-                                                      size_t*) {
-  return false;
-}
-
-bool PowerStatsHalDataProvider::GetEnergyConsumed(EnergyEstimationBreakdown*,
-                                                  size_t*) {
-  return false;
-}
-
-/*** End of Power Stats HAL Implemenation *************************************/
-
-/*** Power Stats AIDL Implemenation *******************************************/
-aidl::IPowerStats* PowerStatsAidlDataProvider::MaybeGetService() {
-  if (svc_ == nullptr) {
-    svc_ = android::checkDeclaredService<aidl::IPowerStats>(
-        android::String16(INSTANCE));
-  }
-  return svc_.get();
-}
-
-void PowerStatsAidlDataProvider::ResetService() {
-  svc_.clear();
-}
-
-bool PowerStatsAidlDataProvider::GetAvailableRails(RailDescriptor* descriptor,
-                                                   size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-
-  aidl::IPowerStats* svc = MaybeGetService();
-  if (svc_ == nullptr) {
-    return false;
-  }
-
-  std::vector<aidl::Channel> results;
-  android::binder::Status status = svc->getEnergyMeterInfo(&results);
-  if (!status.isOk()) {
-    if (status.transactionError() == android::DEAD_OBJECT) {
-      // Service has died.  Reset it to attempt to acquire a new one next time.
-      ResetService();
-    }
-    return false;
-  }
-
-  size_t max_size = std::min(in_array_size, results.size());
-  for (const auto& result : results) {
-    if (*size_of_arr >= max_size) {
-      break;
-    }
-    auto& cur = descriptor[(*size_of_arr)++];
-    cur.index = result.id;
-    cur.sampling_rate = 0;
-    strncpy(cur.rail_name, result.name.c_str(), sizeof(cur.rail_name));
-    strncpy(cur.subsys_name, result.subsystem.c_str(), sizeof(cur.subsys_name));
-    cur.rail_name[sizeof(cur.rail_name) - 1] = '\0';
-    cur.subsys_name[sizeof(cur.subsys_name) - 1] = '\0';
-  }
-  return true;
-}
-
-bool PowerStatsAidlDataProvider::GetRailEnergyData(RailEnergyData* data,
-                                                   size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-
-  aidl::IPowerStats* svc = MaybeGetService();
-  if (svc == nullptr) {
-    return false;
-  }
-
-  std::vector<int> ids;
-  std::vector<aidl::EnergyMeasurement> results;
-  android::binder::Status status = svc->readEnergyMeter(ids, &results);
-  if (!status.isOk()) {
-    if (status.transactionError() == android::DEAD_OBJECT) {
-      // Service has died.  Reset it to attempt to acquire a new one next time.
-      ResetService();
-    }
-    return false;
-  }
-
-  size_t max_size = std::min(in_array_size, results.size());
-  for (const auto& result : results) {
-    if (*size_of_arr >= max_size) {
-      break;
-    }
-    auto& cur = data[(*size_of_arr)++];
-    cur.index = result.id;
-    cur.timestamp = result.timestampMs;
-    cur.energy = result.energyUWs;
-  }
-  return true;
-}
-
-bool PowerStatsAidlDataProvider::GetEnergyConsumerInfo(
-    EnergyConsumerInfo* consumers,
-    size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-
-  aidl::IPowerStats* svc = MaybeGetService();
-  if (svc == nullptr) {
-    return false;
-  }
-  std::vector<aidl::EnergyConsumer> results;
-  android::binder::Status status = svc->getEnergyConsumerInfo(&results);
-
-  if (!status.isOk()) {
-    if (status.transactionError() == android::DEAD_OBJECT) {
-      // Service has died.  Reset it to attempt to acquire a new one next time.
-      ResetService();
-    }
-    return false;
-  }
-  size_t max_size = std::min(in_array_size, results.size());
-  for (const auto& result : results) {
-    if (*size_of_arr >= max_size) {
-      break;
-    }
-    auto& cur = consumers[(*size_of_arr)++];
-    cur.energy_consumer_id = result.id;
-    cur.ordinal = result.ordinal;
-    strncpy(cur.type, aidl::toString(result.type).c_str(), sizeof(cur.type));
-    cur.type[sizeof(cur.type) - 1] = '\0';
-    strncpy(cur.name, result.name.c_str(), sizeof(cur.name));
-    cur.name[sizeof(cur.name) - 1] = '\0';
-  }
-  return true;
-}
-bool PowerStatsAidlDataProvider::GetEnergyConsumed(
-    EnergyEstimationBreakdown* breakdown,
-    size_t* size_of_arr) {
-  const size_t in_array_size = *size_of_arr;
-  *size_of_arr = 0;
-
-  aidl::IPowerStats* svc = MaybeGetService();
-  if (svc == nullptr) {
-    return false;
-  }
-
-  std::vector<int> ids;
-  std::vector<aidl::EnergyConsumerResult> results;
-  android::binder::Status status = svc->getEnergyConsumed(ids, &results);
-
-  if (!status.isOk()) {
-    if (status.transactionError() == android::DEAD_OBJECT) {
-      // Service has died.  Reset it to attempt to acquire a new one next time.
-      ResetService();
-    }
-    return false;
-  }
-
-  size_t max_size = std::min(in_array_size, results.size());
-  // Iterate through all consumer ID.
-  for (const auto& result : results) {
-    if (*size_of_arr >= max_size) {
-      break;
-    }
-    auto& cur = breakdown[(*size_of_arr)++];
-    cur.energy_consumer_id = result.id;
-    cur.uid = ALL_UIDS_FOR_CONSUMER;
-    cur.energy_uws = result.energyUWs;
-
-    // Iterate through all UIDs for this consumer.
-    for (const auto& attribution : result.attribution) {
-      if (*size_of_arr >= max_size) {
-        break;
-      }
-      auto& cur = breakdown[(*size_of_arr)++];
-      cur.energy_consumer_id = result.id;
-      cur.uid = attribution.uid;
-      cur.energy_uws = attribution.energyUWs;
-    }
-  }
-  return true;
-}
-/*** End of Power Stats AIDL Implemenation ************************************/
-
-}  // namespace android_internal
-}  // namespace perfetto
diff --git a/src/android_internal/power_stats.h b/src/android_internal/power_stats.h
deleted file mode 100644
index 3225d29..0000000
--- a/src/android_internal/power_stats.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_POWER_STATS_H_
-#define SRC_ANDROID_INTERNAL_POWER_STATS_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-// This header declares proxy functions defined in
-// libperfetto_android_internal.so that allow traced_probes to access internal
-// android functions (e.g., hwbinder).
-// Do not add any include to either perfetto headers or android headers. See
-// README.md for more.
-
-namespace perfetto {
-namespace android_internal {
-
-const int32_t ALL_UIDS_FOR_CONSUMER = -1;
-
-struct RailDescriptor {
-  // Index corresponding to the rail
-  uint32_t index;
-  // Name of the rail
-  char rail_name[64];
-  // Name of the subsystem to which this rail belongs
-  char subsys_name[64];
-  // Hardware sampling rate
-  uint32_t sampling_rate;
-};
-
-struct RailEnergyData {
-  // Index corresponding to RailDescriptor.index
-  uint32_t index;
-  // Time since device boot(CLOCK_BOOTTIME) in milli-seconds
-  uint64_t timestamp;
-  // Accumulated energy since device boot in microwatt-seconds (uWs)
-  uint64_t energy;
-};
-
-struct EnergyConsumerInfo {
-  // Unique ID of this energy consumer.  Matches the ID in a
-  // EnergyEstimationBreakdown.
-  int32_t energy_consumer_id;
-
-  // For a group of energy consumers of the same logical type, sorting by
-  // ordinal gives their physical order. Ordinals must be consecutive integers
-  // starting from 0.
-  int32_t ordinal;
-
-  // Type of this energy consumer.
-  char type[64];
-
-  // Unique name of this energy consumer. Vendor/device specific. Opaque to
-  // framework.
-  char name[64];
-};
-
-struct EnergyEstimationBreakdown {
-  // Energy consumer ID.
-  int32_t energy_consumer_id;
-
-  // Process uid.  ALL_UIDS_FOR_CONSUMER represents energy for all processes
-  // for the energy_consumer_id.
-  int32_t uid;
-
-  // Energy usage in microwatts-second(µWs).
-  int64_t energy_uws;
-};
-
-extern "C" {
-
-// These functions are not thread safe unless specified otherwise.
-
-bool __attribute__((visibility("default")))
-GetAvailableRails(RailDescriptor*, size_t* size_of_arr);
-
-bool __attribute__((visibility("default")))
-GetRailEnergyData(RailEnergyData*, size_t* size_of_arr);
-
-bool __attribute__((visibility("default")))
-GetEnergyConsumerInfo(EnergyConsumerInfo* consumers, size_t* size_of_arr);
-
-// Retrieve the energy estimation breakdown for all energy consumer.  For each
-// consumer, there will be an entry with a uid of ALL_UIDS_FOR_CONSUMER,
-// followed by the energy breakdown for each process contributing to that
-// consumer.
-bool __attribute__((visibility("default")))
-GetEnergyConsumed(EnergyEstimationBreakdown* breakdown, size_t* size_of_arr);
-
-}  // extern "C"
-
-}  // namespace android_internal
-}  // namespace perfetto
-
-#endif  // SRC_ANDROID_INTERNAL_POWER_STATS_H_
diff --git a/src/android_internal/power_stats_hal.cc b/src/android_internal/power_stats_hal.cc
new file mode 100644
index 0000000..9027e4e
--- /dev/null
+++ b/src/android_internal/power_stats_hal.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/power_stats_hal.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+namespace perfetto {
+namespace android_internal {
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+
+namespace {
+
+android::sp<IPowerStats> g_svc;
+
+bool GetService() {
+  if (!g_svc)
+    g_svc = IPowerStats::getService();
+
+  return g_svc != nullptr;
+}
+
+}  // namespace
+
+bool GetAvailableRails(RailDescriptor* rail_descriptors, size_t* size_of_arr) {
+  const size_t in_array_size = *size_of_arr;
+  *size_of_arr = 0;
+  if (!GetService())
+    return false;
+
+  Status status;
+  auto rails_cb = [rail_descriptors, size_of_arr, &in_array_size, &status](
+                      hidl_vec<RailInfo> r, Status s) {
+    status = s;
+    if (status == Status::SUCCESS) {
+      *size_of_arr = std::min(in_array_size, r.size());
+      for (int i = 0; i < *size_of_arr; ++i) {
+        const RailInfo& rail_info = r[i];
+        RailDescriptor& descriptor = rail_descriptors[i];
+
+        descriptor.index = rail_info.index;
+        descriptor.sampling_rate = rail_info.samplingRate;
+
+        strncpy(descriptor.rail_name, rail_info.railName.c_str(),
+                sizeof(descriptor.rail_name));
+        strncpy(descriptor.subsys_name, rail_info.subsysName.c_str(),
+                sizeof(descriptor.subsys_name));
+        descriptor.rail_name[sizeof(descriptor.rail_name) - 1] = '\0';
+        descriptor.subsys_name[sizeof(descriptor.subsys_name) - 1] = '\0';
+      }
+    }
+  };
+
+  Return<void> ret = g_svc->getRailInfo(rails_cb);
+  return status == Status::SUCCESS;
+}
+
+bool GetRailEnergyData(RailEnergyData* rail_energy_array, size_t* size_of_arr) {
+  const size_t in_array_size = *size_of_arr;
+  *size_of_arr = 0;
+
+  if (!GetService())
+    return false;
+
+  Status status;
+  auto energy_cb = [rail_energy_array, size_of_arr, &in_array_size, &status](
+                       hidl_vec<EnergyData> m, Status s) {
+    status = s;
+    if (status == Status::SUCCESS) {
+      *size_of_arr = std::min(in_array_size, m.size());
+      for (int i = 0; i < *size_of_arr; ++i) {
+        const EnergyData& measurement = m[i];
+        RailEnergyData& element = rail_energy_array[i];
+
+        element.index = measurement.index;
+        element.timestamp = measurement.timestamp;
+        element.energy = measurement.energy;
+      }
+    }
+  };
+
+  Return<void> ret = g_svc->getEnergyData(hidl_vec<uint32_t>(), energy_cb);
+  return status == Status::SUCCESS;
+}
+
+}  // namespace android_internal
+}  // namespace perfetto
diff --git a/src/android_internal/power_stats_hal.h b/src/android_internal/power_stats_hal.h
new file mode 100644
index 0000000..6773b19
--- /dev/null
+++ b/src/android_internal/power_stats_hal.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 SRC_ANDROID_INTERNAL_POWER_STATS_HAL_H_
+#define SRC_ANDROID_INTERNAL_POWER_STATS_HAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// This header declares proxy functions defined in
+// libperfetto_android_internal.so that allow traced_probes to access internal
+// android functions (e.g., hwbinder).
+// Do not add any include to either perfetto headers or android headers. See
+// README.md for more.
+
+namespace perfetto {
+namespace android_internal {
+
+struct RailDescriptor {
+  // Index corresponding to the rail
+  uint32_t index;
+  // Name of the rail
+  char rail_name[64];
+  // Name of the subsystem to which this rail belongs
+  char subsys_name[64];
+  // Hardware sampling rate
+  uint32_t sampling_rate;
+};
+
+struct RailEnergyData {
+  // Index corresponding to RailDescriptor.index
+  uint32_t index;
+  // Time since device boot(CLOCK_BOOTTIME) in milli-seconds
+  uint64_t timestamp;
+  // Accumulated energy since device boot in microwatt-seconds (uWs)
+  uint64_t energy;
+};
+
+extern "C" {
+
+// These functions are not thread safe unless specified otherwise.
+
+bool __attribute__((visibility("default")))
+GetAvailableRails(RailDescriptor*, size_t* size_of_arr);
+
+bool __attribute__((visibility("default")))
+GetRailEnergyData(RailEnergyData*, size_t* size_of_arr);
+
+}  // extern "C"
+
+}  // namespace android_internal
+}  // namespace perfetto
+
+#endif  // SRC_ANDROID_INTERNAL_POWER_STATS_HAL_H_
diff --git a/src/android_internal/statsd_logging.cc b/src/android_internal/statsd_logging.cc
index a164adf..aa7b24b 100644
--- a/src/android_internal/statsd_logging.cc
+++ b/src/android_internal/statsd_logging.cc
@@ -23,16 +23,11 @@
 namespace perfetto {
 namespace android_internal {
 
-void StatsdLogUploadEvent(PerfettoStatsdAtom atom,
-                          int64_t uuid_lsb,
-                          int64_t uuid_msb,
-                          const char* trigger_name) {
-  stats_write(PERFETTO_UPLOADED, static_cast<int32_t>(atom), uuid_lsb, uuid_msb,
-              trigger_name ? trigger_name : "");
-}
-
-void StatsdLogTriggerEvent(PerfettoTriggerAtom atom, const char* trigger_name) {
-  stats_write(PERFETTO_TRIGGER, static_cast<int32_t>(atom), trigger_name);
+void StatsdLogEvent(PerfettoStatsdAtom atom,
+                    int64_t uuid_lsb,
+                    int64_t uuid_msb) {
+  stats_write(PERFETTO_UPLOADED, static_cast<int32_t>(atom), uuid_lsb,
+              uuid_msb);
 }
 
 }  // namespace android_internal
diff --git a/src/android_internal/statsd_logging.h b/src/android_internal/statsd_logging.h
index aecfb7d..e1f9c76 100644
--- a/src/android_internal/statsd_logging.h
+++ b/src/android_internal/statsd_logging.h
@@ -20,7 +20,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "src/android_stats/perfetto_atoms.h"
+#include "src/perfetto_cmd/perfetto_atoms.h"
 
 namespace perfetto {
 namespace android_internal {
@@ -28,13 +28,7 @@
 extern "C" {
 
 void __attribute__((visibility("default")))
-StatsdLogUploadEvent(PerfettoStatsdAtom atom,
-                     int64_t uuid_lsb,
-                     int64_t uuid_msb,
-                     const char* trigger_name);
-
-void __attribute__((visibility("default")))
-StatsdLogTriggerEvent(PerfettoTriggerAtom atom, const char* trigger_name);
+StatsdLogEvent(PerfettoStatsdAtom atom, int64_t uuid_lsb, int64_t uuid_msb);
 
 }  // extern "C"
 
diff --git a/src/android_internal/tracing_service_proxy.cc b/src/android_internal/tracing_service_proxy.cc
deleted file mode 100644
index e297b75..0000000
--- a/src/android_internal/tracing_service_proxy.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/tracing_service_proxy.h"
-
-#include <android/tracing/ITracingServiceProxy.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
-#include <binder/Status.h>
-
-namespace perfetto {
-namespace android_internal {
-
-using android::sp;
-using android::binder::Status;
-using android::tracing::ITracingServiceProxy;
-
-bool NotifyTraceSessionEnded(bool session_stolen) {
-  sp<ITracingServiceProxy> service = android::interface_cast<ITracingServiceProxy>(
-      android::defaultServiceManager()->getService(android::String16("tracing.proxy")));
-
-  if (service == nullptr) {
-    return false;
-  }
-
-  Status s = service->notifyTraceSessionEnded(session_stolen);
-  return s.isOk();
-}
-
-} // namespace android_internal
-} // namespace perfetto
diff --git a/src/android_internal/tracing_service_proxy.h b/src/android_internal/tracing_service_proxy.h
deleted file mode 100644
index 0b045e2..0000000
--- a/src/android_internal/tracing_service_proxy.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TRACING_SERVICE_PROXY_H_
-#define SRC_ANDROID_INTERNAL_TRACING_SERVICE_PROXY_H_
-
-namespace perfetto {
-namespace android_internal {
-
-extern "C" {
-
-bool __attribute__((visibility("default")))
-NotifyTraceSessionEnded(bool session_stolen);
-
-} // extern "C"
-
-} // namespace android_internal
-} // namespace perfetto
-#endif  // SRC_ANDROID_INTERNAL_TRACING_SERVICE_PROXY_H_
diff --git a/src/android_stats/BUILD.gn b/src/android_stats/BUILD.gn
deleted file mode 100644
index be5edea..0000000
--- a/src/android_stats/BUILD.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../gn/perfetto.gni")
-
-source_set("perfetto_atoms") {
-  sources = [ "perfetto_atoms.h" ]
-  deps = [ "../../gn:default_deps" ]
-}
-
-source_set("android_stats") {
-  deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/base",
-  ]
-  public_deps = [ ":perfetto_atoms" ]
-  sources = [
-    "statsd_logging_helper.cc",
-    "statsd_logging_helper.h",
-  ]
-  if (is_android && perfetto_build_with_android) {
-    deps += [
-      "../android_internal:headers",
-      "../android_internal:lazy_library_loader",
-    ]
-  }
-}
diff --git a/src/android_stats/perfetto_atoms.h b/src/android_stats/perfetto_atoms.h
deleted file mode 100644
index 3731c2e..0000000
--- a/src/android_stats/perfetto_atoms.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
-#define SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
-
-namespace perfetto {
-
-// This must match the values of the PerfettoUploadEvent enum in:
-// frameworks/proto_logging/stats/atoms.proto
-enum class PerfettoStatsdAtom {
-  kUndefined = 0,
-
-  // Checkpoints inside perfetto_cmd before tracing is finished.
-  kTraceBegin = 1,
-  kBackgroundTraceBegin = 2,
-  kOnConnect = 3,
-
-  // Guardrails inside perfetto_cmd before tracing is finished.
-  kOnTimeout = 16,
-  kCmdUserBuildTracingNotAllowed = 43,
-  kCmdFailedToInitGuardrailState = 44,
-  kCmdInvalidGuardrailState = 45,
-  kCmdHitUploadLimit = 46,
-
-  // Checkpoints inside traced.
-  kTracedEnableTracing = 37,
-  kTracedStartTracing = 38,
-  kTracedDisableTracing = 39,
-  kTracedNotifyTracingDisabled = 40,
-
-  // Trigger checkpoints inside traced.
-  // These atoms are special because, along with the UUID,
-  // they log the trigger name.
-  kTracedTriggerStartTracing = 41,
-  kTracedTriggerStopTracing = 42,
-
-  // Guardrails inside traced.
-  kTracedEnableTracingExistingTraceSession = 18,
-  kTracedEnableTracingTooLongTrace = 19,
-  kTracedEnableTracingInvalidTriggerTimeout = 20,
-  kTracedEnableTracingDurationWithTrigger = 21,
-  kTracedEnableTracingStopTracingWriteIntoFile = 22,
-  kTracedEnableTracingDuplicateTriggerName = 23,
-  kTracedEnableTracingInvalidDeferredStart = 24,
-  kTracedEnableTracingInvalidBufferSize = 25,
-  kTracedEnableTracingBufferSizeTooLarge = 26,
-  kTracedEnableTracingTooManyBuffers = 27,
-  kTracedEnableTracingDuplicateSessionName = 28,
-  kTracedEnableTracingSessionNameTooRecent = 29,
-  kTracedEnableTracingTooManySessionsForUid = 30,
-  kTracedEnableTracingTooManyConcurrentSessions = 31,
-  kTracedEnableTracingInvalidFdOutputFile = 32,
-  kTracedEnableTracingFailedToCreateFile = 33,
-  kTracedEnableTracingOom = 34,
-  kTracedEnableTracingUnknown = 35,
-  kTracedStartTracingInvalidSessionState = 36,
-  kTracedEnableTracingInvalidFilter = 47,
-
-  // Checkpoints inside perfetto_cmd after tracing has finished.
-  kOnTracingDisabled = 4,
-  kUploadIncidentBegin = 8,
-  kFinalizeTraceAndExit = 11,
-  kNotUploadingEmptyTrace = 17,
-
-  // Guardrails inside perfetto_cmd after tracing has finished.
-  kUploadIncidentFailure = 10,
-
-  // Deprecated as "success" is misleading; it simply means we were
-  // able to communicate with incidentd. Will be removed once
-  // incidentd is properly instrumented.
-  kUploadIncidentSuccess = 9,
-
-  // Deprecated as has the potential to be too spammy. Will be
-  // replaced with a whole new atom proto which uses a count metric
-  // instead of the event metric used for this proto.
-  kTriggerBegin = 12,
-  kTriggerSuccess = 13,
-  kTriggerFailure = 14,
-
-  // Deprecated as too coarse grained to be useful. Will be replaced
-  // with better broken down atoms as we do with traced.
-  kHitGuardrails = 15,
-
-  // Contained status of Dropbox uploads. Removed as Perfetto no
-  // longer supports uploading traces using Dropbox.
-  // reserved 5, 6, 7;
-};
-
-// This must match the values of the PerfettoTrigger::TriggerType enum in:
-// frameworks/base/cmds/statsd/src/atoms.proto
-enum PerfettoTriggerAtom {
-  kUndefined = 0,
-
-  kCmdTrigger = 1,
-  kCmdTriggerFail = 2,
-
-  kTriggerPerfettoTrigger = 3,
-  kTriggerPerfettoTriggerFail = 4,
-
-  kTracedLimitProbability = 5,
-  kTracedLimitMaxPer24h = 6,
-
-  kProbesProducerTrigger = 7,
-  kProbesProducerTriggerFail = 8,
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_ANDROID_STATS_PERFETTO_ATOMS_H_
diff --git a/src/android_stats/statsd_logging_helper.cc b/src/android_stats/statsd_logging_helper.cc
deleted file mode 100644
index c943027..0000000
--- a/src/android_stats/statsd_logging_helper.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/android_stats/statsd_logging_helper.h"
-
-#include <string>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include "src/android_internal/lazy_library_loader.h"  // nogncheck
-#include "src/android_internal/statsd_logging.h"       // nogncheck
-#endif
-
-namespace perfetto {
-namespace android_stats {
-
-// Make sure we don't accidentally log on non-Android tree build. Note that even
-// removing this ifdef still doesn't make uploads work on OS_ANDROID.
-// PERFETTO_LAZY_LOAD will return a nullptr on non-Android and non-in-tree
-// builds as libperfetto_android_internal will not be available.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-
-void MaybeLogUploadEvent(PerfettoStatsdAtom atom,
-                         int64_t uuid_lsb,
-                         int64_t uuid_msb,
-                         const std::string& trigger_name) {
-  PERFETTO_LAZY_LOAD(android_internal::StatsdLogUploadEvent, log_event_fn);
-  if (log_event_fn) {
-    log_event_fn(atom, uuid_lsb, uuid_msb, trigger_name.c_str());
-  }
-}
-
-void MaybeLogTriggerEvent(PerfettoTriggerAtom atom,
-                          const std::string& trigger_name) {
-  PERFETTO_LAZY_LOAD(android_internal::StatsdLogTriggerEvent, log_event_fn);
-  if (log_event_fn) {
-    log_event_fn(atom, trigger_name.c_str());
-  }
-}
-
-void MaybeLogTriggerEvents(PerfettoTriggerAtom atom,
-                           const std::vector<std::string>& triggers) {
-  PERFETTO_LAZY_LOAD(android_internal::StatsdLogTriggerEvent, log_event_fn);
-  if (log_event_fn) {
-    for (const std::string& trigger_name : triggers) {
-      log_event_fn(atom, trigger_name.c_str());
-    }
-  }
-}
-
-#else
-void MaybeLogUploadEvent(PerfettoStatsdAtom,
-                         int64_t,
-                         int64_t,
-                         const std::string&) {}
-void MaybeLogTriggerEvent(PerfettoTriggerAtom, const std::string&) {}
-void MaybeLogTriggerEvents(PerfettoTriggerAtom,
-                           const std::vector<std::string>&) {}
-#endif
-
-}  // namespace android_stats
-}  // namespace perfetto
diff --git a/src/android_stats/statsd_logging_helper.h b/src/android_stats/statsd_logging_helper.h
deleted file mode 100644
index 5f0911f..0000000
--- a/src/android_stats/statsd_logging_helper.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
-#define SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
-
-#include <stdint.h>
-#include <string>
-#include <vector>
-
-#include "src/android_stats/perfetto_atoms.h"
-
-namespace perfetto {
-namespace android_stats {
-
-// Functions in this file are only active on built in the Android
-// tree. On other platforms (including Android standalone and Chromium
-// on Android) these functions are a noop.
-
-// Logs the upload event to statsd if built in the Android tree.
-void MaybeLogUploadEvent(PerfettoStatsdAtom atom,
-                         int64_t uuid_lsb,
-                         int64_t uuid_msb,
-                         const std::string& trigger_name = "");
-
-// Logs the trigger events to statsd if built in the Android tree.
-void MaybeLogTriggerEvent(PerfettoTriggerAtom atom, const std::string& trigger);
-
-// Logs the trigger events to statsd if built in the Android tree.
-void MaybeLogTriggerEvents(PerfettoTriggerAtom atom,
-                           const std::vector<std::string>& triggers);
-
-}  // namespace android_stats
-}  // namespace perfetto
-
-#endif  // SRC_ANDROID_STATS_STATSD_LOGGING_HELPER_H_
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index f761a53..083faf3 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -13,86 +13,52 @@
 # limitations under the License.
 
 import("//build_overrides/build.gni")
-import("../../gn/gen_perfetto_version_header.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_component.gni")
 import("../../gn/test.gni")
 import("../../gn/wasm.gni")
 
-# On standalone builds this is all the OSes we support. On chromium builds,
-# though, this really means !is_fuchsia && !is_nacl.
-_subprocess_supported =
-    is_linux || is_chromeos || is_android || is_mac || is_win
+enable_stack_trace = is_debug && perfetto_build_standalone && !is_wasm
 
-perfetto_component("base") {
+source_set("base") {
   deps = [ "../../gn:default_deps" ]
   public_deps = [
     "../../include/perfetto/base",
     "../../include/perfetto/ext/base",
   ]
   sources = [
-    "ctrl_c_handler.cc",
-    "event_fd.cc",
     "file_utils.cc",
-    "getopt_compat.cc",
     "logging.cc",
     "metatrace.cc",
     "paged_memory.cc",
-    "periodic_task.cc",
-    "pipe.cc",
-    "status.cc",
     "string_splitter.cc",
     "string_utils.cc",
     "string_view.cc",
-    "temp_file.cc",
+    "subprocess.cc",
     "thread_checker.cc",
     "time.cc",
-    "utils.cc",
     "uuid.cc",
-    "version.cc",
     "virtual_destructors.cc",
     "waitable_event.cc",
     "watchdog_posix.cc",
   ]
 
-  if (!is_nacl) {
+  # TODO(brucedawson): Enable these for Windows when possible.
+  if (!is_win && !is_nacl) {
     sources += [
+      "event_fd.cc",
+      "pipe.cc",
+      "temp_file.cc",
       "thread_task_runner.cc",
       "unix_task_runner.cc",
     ]
   }
 
-  if (_subprocess_supported) {
-    sources += [
-      "subprocess.cc",
-      "subprocess_posix.cc",
-      "subprocess_windows.cc",
-    ]
-  }
-
-  if (enable_perfetto_stderr_crash_dump) {
+  if (enable_stack_trace) {
     deps += [ ":debug_crash_stack_trace" ]
   }
-
-  if (enable_perfetto_version_gen) {
-    deps += [ ":version_gen_h" ]
-  }
 }
 
-if (enable_perfetto_version_gen) {
-  config("version_gen_config") {
-    include_dirs = [ root_gen_dir ]
-  }
-
-  # Note: the build file translators (tools/gn_utils.py) depend on the hardcoded
-  # "//src/base:version_gen_h". If you rename this target, update build file
-  # translators accordingly.
-  gen_perfetto_version_header("version_gen_h") {
-    cpp_out = "${root_gen_dir}/perfetto_version.gen.h"
-  }
-}
-
-if (enable_perfetto_stderr_crash_dump) {
+if (enable_stack_trace) {
   source_set("debug_crash_stack_trace") {
     sources = [ "debug_crash_stack_trace.cc" ]
     deps = [
@@ -109,15 +75,13 @@
 
 if (enable_perfetto_ipc) {
   # This cannot be in :base as it does not build on WASM.
-  perfetto_component("unix_socket") {
+  source_set("unix_socket") {
     deps = [
       "../../gn:default_deps",
       "../../include/perfetto/ext/base",
+      "../../include/perfetto/ext/base",
     ]
     sources = [ "unix_socket.cc" ]
-    if (is_win && perfetto_build_standalone) {
-      libs = [ "Ws2_32.lib" ]
-    }
   }
 }
 
@@ -134,9 +98,8 @@
     "test/vm_test_utils.h",
   ]
 
-  if (!is_nacl) {
-    # test_task_runner depends on unix_task_runner, which isn't available on
-    # NaCL.
+  # The Perfetto task runner is not used on Windows.
+  if (!is_win) {
     sources += [
       "test/test_task_runner.cc",
       "test/test_task_runner.h",
@@ -156,46 +119,37 @@
   sources = [
     "circular_queue_unittest.cc",
     "flat_set_unittest.cc",
-    "getopt_compat_unittest.cc",
-    "logging_unittest.cc",
     "no_destructor_unittest.cc",
     "optional_unittest.cc",
     "paged_memory_unittest.cc",
-    "periodic_task_unittest.cc",
     "scoped_file_unittest.cc",
     "string_splitter_unittest.cc",
     "string_utils_unittest.cc",
     "string_view_unittest.cc",
     "string_writer_unittest.cc",
-    "task_runner_unittest.cc",
-    "temp_file_unittest.cc",
-    "thread_checker_unittest.cc",
+    "subprocess_unittest.cc",
     "time_unittest.cc",
-    "utils_unittest.cc",
     "uuid_unittest.cc",
     "weak_ptr_unittest.cc",
   ]
-  if (_subprocess_supported) {
-    # Don't run on Fuchsia, NaCL. They pretend to be POSIX but then give up on
-    # execve(2).
-    sources += [ "subprocess_unittest.cc" ]
-  }
 
   # TODO: 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",
       "thread_task_runner_unittest.cc",
-      "watchdog_posix_unittest.cc",
+      "utils_unittest.cc",
     ]
   }
   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" ]
     }
-    sources += [ "unix_socket_unittest.cc" ]
-    deps += [ ":unix_socket" ]
   }
 }
 
diff --git a/src/base/ctrl_c_handler.cc b/src/base/ctrl_c_handler.cc
deleted file mode 100644
index 080f0cf..0000000
--- a/src/base/ctrl_c_handler.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/ctrl_c_handler.h"
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/logging.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <io.h>
-#else
-#include <signal.h>
-#include <unistd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-namespace {
-CtrlCHandlerFunction g_handler = nullptr;
-}
-
-void InstallCtrCHandler(CtrlCHandlerFunction handler) {
-  PERFETTO_CHECK(g_handler == nullptr);
-  g_handler = handler;
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  auto trampoline = [](DWORD type) -> int {
-    if (type == CTRL_C_EVENT) {
-      g_handler();
-      return true;
-    }
-    return false;
-  };
-  ::SetConsoleCtrlHandler(trampoline, true);
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-  // Setup signal handler.
-  struct sigaction sa {};
-
-// Glibc headers for sa_sigaction trigger this.
-#pragma GCC diagnostic push
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
-#endif
-  sa.sa_handler = [](int) { g_handler(); };
-  sa.sa_flags = static_cast<decltype(sa.sa_flags)>(SA_RESETHAND | SA_RESTART);
-#pragma GCC diagnostic pop
-  sigaction(SIGINT, &sa, nullptr);
-  sigaction(SIGTERM, &sa, nullptr);
-#else
-  // Do nothing on NaCL and Fuchsia.
-  ignore_result(handler);
-#endif
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/debug_crash_stack_trace.cc b/src/base/debug_crash_stack_trace.cc
index 4da0fba..ae857a4 100644
--- a/src/base/debug_crash_stack_trace.cc
+++ b/src/base/debug_crash_stack_trace.cc
@@ -220,7 +220,7 @@
 // In order to retrigger it, we have to queue a new signal by calling
 // kill() ourselves.  The special case (si_pid == 0 && sig == SIGABRT) is
 // due to the kernel sending a SIGABRT from a user request via SysRQ.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
     if (kill(getpid(), sig_num) < 0) {
 #else
     if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), sig_num) < 0) {
diff --git a/src/base/event_fd.cc b/src/base/event_fd.cc
index 0856818..976db19 100644
--- a/src/base/event_fd.cc
+++ b/src/base/event_fd.cc
@@ -15,96 +15,67 @@
  */
 
 #include "perfetto/base/build_config.h"
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
-#include <errno.h>
 #include <stdint.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <synchapi.h>
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/eventfd.h>
 #include <unistd.h>
-#else  // Mac, Fuchsia and other non-Linux UNIXes
-#include <unistd.h>
-#endif
 
 #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() = default;
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 EventFd::EventFd() {
-  event_handle_.reset(
-      CreateEventA(/*lpEventAttributes=*/nullptr, /*bManualReset=*/true,
-                   /*bInitialState=*/false, /*bInitialState=*/nullptr));
-}
-
-void EventFd::Notify() {
-  if (!SetEvent(event_handle_.get()))  // 0: fail, !0: success, unlike UNIX.
-    PERFETTO_DFATAL("EventFd::Notify()");
-}
-
-void EventFd::Clear() {
-  if (!ResetEvent(event_handle_.get()))  // 0: fail, !0: success, unlike UNIX.
-    PERFETTO_DFATAL("EventFd::Clear()");
-}
-
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-
-EventFd::EventFd() {
-  event_handle_.reset(eventfd(/*initval=*/0, EFD_CLOEXEC | EFD_NONBLOCK));
-  PERFETTO_CHECK(event_handle_);
-}
-
-void EventFd::Notify() {
-  const uint64_t value = 1;
-  ssize_t ret = write(event_handle_.get(), &value, sizeof(value));
-  if (ret <= 0 && errno != EAGAIN)
-    PERFETTO_DFATAL("EventFd::Notify()");
-}
-
-void EventFd::Clear() {
-  uint64_t value;
-  ssize_t ret = read(event_handle_.get(), &value, sizeof(value));
-  if (ret <= 0 && errno != EAGAIN)
-    PERFETTO_DFATAL("EventFd::Clear()");
-}
-
+#if PERFETTO_USE_EVENTFD()
+  fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
+  PERFETTO_CHECK(fd_);
 #else
-
-EventFd::EventFd() {
   // 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);
-  event_handle_ = ScopedPlatformHandle(std::move(pipe.rd).release());
+  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));
-  if (ret <= 0 && errno != EAGAIN)
-    PERFETTO_DFATAL("EventFd::Notify()");
+#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(event_handle_.get(), &buffer[0], sizeof(buffer));
-  if (ret <= 0 && errno != EAGAIN)
-    PERFETTO_DFATAL("EventFd::Clear()");
-}
+  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 9b92af2..b8020ad 100644
--- a/src/base/file_utils.cc
+++ b/src/base/file_utils.cc
@@ -14,26 +14,20 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/file_utils.h"
-
 #include <sys/stat.h>
-#include <sys/types.h>
-
-#include <algorithm>
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/base/platform_handle.h"
+#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/utils.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <direct.h>
-#include <io.h>
-#else
-#include <dirent.h>
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
+    PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
 #include <unistd.h>
+#else
+#include <corecrt_io.h>
+#include <io.h>
 #endif
 
 namespace perfetto {
@@ -42,14 +36,6 @@
 constexpr size_t kBufSize = 2048;
 }
 
-ssize_t Read(int fd, void* dst, size_t dst_size) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  return _read(fd, dst, static_cast<unsigned>(dst_size));
-#else
-  return PERFETTO_EINTR(read(fd, dst, dst_size));
-#endif
-}
-
 bool ReadFileDescriptor(int fd, std::string* out) {
   // Do not override existing data in string.
   size_t i = out->size();
@@ -65,7 +51,7 @@
     if (out->size() < i + kBufSize)
       out->resize(out->size() + kBufSize);
 
-    bytes_read = Read(fd, &((*out)[i]), kBufSize);
+    bytes_read = PERFETTO_EINTR(read(fd, &((*out)[i]), kBufSize));
     if (bytes_read > 0) {
       i += static_cast<size_t>(bytes_read);
     } else {
@@ -75,35 +61,6 @@
   }
 }
 
-bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Do not override existing data in string.
-  size_t i = out->size();
-
-  for (;;) {
-    if (out->size() < i + kBufSize)
-      out->resize(out->size() + kBufSize);
-    DWORD bytes_read = 0;
-    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
-    if (res && bytes_read > 0) {
-      i += static_cast<size_t>(bytes_read);
-    } else {
-      out->resize(i);
-      const bool is_eof = res && bytes_read == 0;
-      auto err = res ? 0 : GetLastError();
-      // The "Broken pipe" error on Windows is slighly different than Unix:
-      // On Unix: a "broken pipe" error can happen only on the writer side. On
-      // the reader there is no broken pipe, just a EOF.
-      // On windows: the reader also sees a broken pipe error.
-      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
-      return is_eof || err == ERROR_BROKEN_PIPE;
-    }
-  }
-#else
-  return ReadFileDescriptor(h, out);
-#endif
-}
-
 bool ReadFileStream(FILE* f, std::string* out) {
   return ReadFileDescriptor(fileno(f), out);
 }
@@ -119,11 +76,8 @@
 ssize_t WriteAll(int fd, const void* buf, size_t count) {
   size_t written = 0;
   while (written < count) {
-    // write() on windows takes an unsigned int size.
-    uint32_t bytes_left = static_cast<uint32_t>(
-        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
     ssize_t wr = PERFETTO_EINTR(
-        write(fd, static_cast<const char*>(buf) + written, bytes_left));
+        write(fd, static_cast<const char*>(buf) + written, count - written));
     if (wr == 0)
       break;
     if (wr < 0)
@@ -133,19 +87,6 @@
   return static_cast<ssize_t>(written);
 }
 
-ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  DWORD wsize = 0;
-  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
-    return wsize;
-  } else {
-    return -1;
-  }
-#else
-  return WriteAll(h, buf, count);
-#endif
-}
-
 bool FlushFile(int fd) {
   PERFETTO_DCHECK(fd != 0);
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
@@ -158,55 +99,5 @@
 #endif
 }
 
-bool Mkdir(const std::string& path) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  return _mkdir(path.c_str()) == 0;
-#else
-  return mkdir(path.c_str(), 0755) == 0;
-#endif
-}
-
-bool Rmdir(const std::string& path) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  return _rmdir(path.c_str()) == 0;
-#else
-  return rmdir(path.c_str()) == 0;
-#endif
-}
-
-int CloseFile(int fd) {
-  return close(fd);
-}
-
-ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
-  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
-#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;
-}
-
-bool FileExists(const std::string& path) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  return _access(path.c_str(), 0) == 0;
-#else
-  return access(path.c_str(), F_OK) == 0;
-#endif
-}
-
-// Declared in base/platform_handle.h.
-int ClosePlatformHandle(PlatformHandle handle) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Make the return value UNIX-style.
-  return CloseHandle(handle) ? 0 : -1;
-#else
-  return close(handle);
-#endif
-}
-
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/getopt_compat.cc b/src/base/getopt_compat.cc
deleted file mode 100644
index 19c8adc..0000000
--- a/src/base/getopt_compat.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/getopt_compat.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <vector>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace base {
-namespace getopt_compat {
-
-char* optarg = nullptr;
-int optind = 0;
-
-namespace {
-
-char* nextchar = nullptr;
-
-const option* LookupLongOpt(const std::vector<option>& opts,
-                            const char* name,
-                            size_t len) {
-  for (const option& opt : opts) {
-    if (strncmp(opt.name, name, len) == 0 && strlen(opt.name) == len)
-      return &opt;
-  }
-  return nullptr;
-}
-
-const option* LookupShortOpt(const std::vector<option>& opts, char c) {
-  for (const option& opt : opts) {
-    if (opt.name == nullptr && opt.val == c)
-      return &opt;
-  }
-  return nullptr;
-}
-
-bool ParseOpts(const char* shortopts,
-               const option* longopts,
-               std::vector<option>* res) {
-  // Parse long options first.
-  for (const option* lopt = longopts; lopt && lopt->name; lopt++) {
-    PERFETTO_CHECK(lopt->flag == nullptr);
-    PERFETTO_CHECK(lopt->has_arg == no_argument ||
-                   lopt->has_arg == required_argument);
-    res->emplace_back(*lopt);
-  }
-
-  // Merge short options.
-  for (const char* sopt = shortopts; sopt && *sopt;) {
-    const size_t idx = static_cast<size_t>(sopt - shortopts);
-    char c = *sopt++;
-    bool valid = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
-                 (c >= '0' && c <= '9');
-    if (!valid) {
-      fprintf(stderr,
-              "Error parsing shortopts. Unexpected char '%c' at offset %zu\n",
-              c, idx);
-      return false;
-    }
-    res->emplace_back();
-    option& opt = res->back();
-    opt.val = c;
-    opt.has_arg = no_argument;
-    if (*sopt == ':') {
-      opt.has_arg = required_argument;
-      ++sopt;
-    }
-  }
-  return true;
-}
-
-}  // namespace
-
-int getopt_long(int argc,
-                char** argv,
-                const char* shortopts,
-                const option* longopts,
-                std::nullptr_t /*longind*/) {
-  std::vector<option> opts;
-  optarg = nullptr;
-
-  if (optind == 0)
-    optind = 1;
-
-  if (optind >= argc)
-    return -1;
-
-  if (!ParseOpts(shortopts, longopts, &opts))
-    return '?';
-
-  char* arg = argv[optind];
-
-  if (!nextchar) {
-    // If |nextchar| is null we are NOT in the middle of a short option and we
-    // should parse the next argv.
-    if (strncmp(arg, "--", 2) == 0 && strlen(arg) > 2) {
-      // A --long option.
-      arg += 2;
-      char* sep = strchr(arg, '=');
-      optind++;
-
-      size_t len = sep ? static_cast<size_t>(sep - arg) : strlen(arg);
-      const option* opt = LookupLongOpt(opts, arg, len);
-      if (!opt) {
-        fprintf(stderr, "unrecognized option '--%s'\n", arg);
-        return '?';
-      }
-
-      if (opt->has_arg == no_argument) {
-        if (sep) {
-          fprintf(stderr, "option '--%s' doesn't allow an argument\n", arg);
-          return '?';
-        } else {
-          return opt->val;
-        }
-      } else if (opt->has_arg == required_argument) {
-        if (sep) {
-          optarg = sep + 1;
-          return opt->val;
-        } else if (optind >= argc) {
-          fprintf(stderr, "option '--%s' requires an argument\n", arg);
-          return '?';
-        } else {
-          optarg = argv[optind++];
-          return opt->val;
-        }
-      }
-      // has_arg must be either |no_argument| or |required_argument|. We
-      // shoulnd't get here unless the check in ParseOpts() has a bug.
-      PERFETTO_CHECK(false);
-    }  // if (arg ~= "--*").
-
-    if (strlen(arg) > 1 && arg[0] == '-' && arg[1] != '-') {
-      // A sequence of short options. Parsing logic continues below.
-      nextchar = &arg[1];
-    }
-  }  // if(!nextchar)
-
-  if (nextchar) {
-    // At this point either:
-    // 1. This is the first char of a sequence of short options, and we fell
-    //    through here from the lines above.
-    // 2. This is the N (>1) char of a sequence of short options, and we got
-    //    here from a new getopt() call to getopt().
-    const char cur_char = *nextchar;
-    PERFETTO_CHECK(cur_char != '\0');
-
-    // Advance the option char in any case, before we start reasoning on them.
-    // if we got to the end of the "-abc" sequence, increment optind so the next
-    // getopt() call resumes from the next argv argument.
-    if (*(++nextchar) == '\0') {
-      nextchar = nullptr;
-      ++optind;
-    }
-
-    const option* opt = LookupShortOpt(opts, cur_char);
-    if (!opt) {
-      fprintf(stderr, "invalid option -- '%c'\n", cur_char);
-      return '?';
-    }
-    if (opt->has_arg == no_argument) {
-      return cur_char;
-    } else if (opt->has_arg == required_argument) {
-      // This is a subtle getopt behavior. Say you call `tar -fx`, there are
-      // two cases:
-      // 1. If 'f' is no_argument then 'x' (and anything else after) is
-      //    interpreted as an independent argument (like `tar -f -x`).
-      // 2. If 'f' is required_argument, than everything else after the 'f'
-      //    is interpreted as the option argument (like `tar -f x`)
-      if (!nextchar) {
-        // Case 1.
-        if (optind >= argc) {
-          fprintf(stderr, "option requires an argument -- '%c'\n", cur_char);
-          return '?';
-        } else {
-          optarg = argv[optind++];
-          return cur_char;
-        }
-      } else {
-        // Case 2.
-        optarg = nextchar;
-        nextchar = nullptr;
-        optind++;
-        return cur_char;
-      }
-    }
-    PERFETTO_CHECK(false);
-  }  // if (nextchar)
-
-  // If we get here, we found the first non-option argument. Stop here.
-
-  if (strcmp(arg, "--") == 0)
-    optind++;
-
-  return -1;
-}
-
-int getopt(int argc, char** argv, const char* shortopts) {
-  return getopt_long(argc, argv, shortopts, nullptr, nullptr);
-}
-
-}  // namespace getopt_compat
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/getopt_compat_unittest.cc b/src/base/getopt_compat_unittest.cc
deleted file mode 100644
index a7d4db3..0000000
--- a/src/base/getopt_compat_unittest.cc
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/getopt_compat.h"
-
-// This test has two roles:
-// 1. In Windows builds it's a plain unittest for our getopt_compat.cc
-// 2. On other builds it also checks that the behavior of our getopt_compat.cc
-//    is the same of <getopt.h> (for the options we support).
-// It does so creating a gtest typed test, and defining two structs that inject
-// getopt functions and global variables like optind.
-
-#include "perfetto/base/build_config.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <getopt.h>
-#endif
-
-#include <initializer_list>
-
-#include "test/gtest_and_gmock.h"
-
-using testing::ElementsAre;
-using testing::ElementsAreArray;
-
-namespace perfetto {
-namespace base {
-namespace {
-
-struct OurGetopt {
-  using LongOptionType = getopt_compat::option;
-  using GetoptFn = decltype(&getopt_compat::getopt);
-  using GetoptLongFn = decltype(&getopt_compat::getopt_long);
-  GetoptFn getopt = &getopt_compat::getopt;
-  GetoptLongFn getopt_long = &getopt_compat::getopt_long;
-  int& optind = getopt_compat::optind;
-  char*& optarg = getopt_compat::optarg;
-};
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-struct SystemGetopt {
-  using LongOptionType = ::option;
-  using GetoptFn = decltype(&::getopt);
-  using GetoptLongFn = decltype(&::getopt_long);
-  GetoptFn getopt = &::getopt;
-  GetoptLongFn getopt_long = &::getopt_long;
-  int& optind = ::optind;
-  char*& optarg = ::optarg;
-};
-#endif
-
-template <typename T>
-class GetoptCompatTest : public testing::Test {
- public:
-  inline void SetCmdline(std::initializer_list<const char*> arg_list) {
-    // Reset the getopt() state.
-    // When calling getopt() several times, MacOS requires that optind is reset
-    // to 1, while Linux requires optind to be reset to 0. Also MacOS requires
-    // optreset to be set as well.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-    impl.optind = 1;
-    optreset = 1;  // It has no corresponding variable in other OSes.
-#else
-    impl.optind = 0;
-#endif
-    argc = static_cast<int>(arg_list.size());
-    for (char*& arg : argv)
-      arg = nullptr;
-    size_t i = 0;
-    for (const char* arg : arg_list)
-      argv[i++] = const_cast<char*>(arg);
-  }
-  int argc;
-  char* argv[32];  // We don't use more than 32 entries on our tests.
-  T impl;
-};
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using GetoptTestTypes = ::testing::Types<OurGetopt>;
-#else
-using GetoptTestTypes = ::testing::Types<OurGetopt, SystemGetopt>;
-#endif
-TYPED_TEST_SUITE(GetoptCompatTest, GetoptTestTypes, /* trailing ',' for GCC*/);
-
-TYPED_TEST(GetoptCompatTest, ShortOptions) {
-  auto& t = this->impl;
-
-  const char* sops = "";
-  this->SetCmdline({"argv0"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-
-  sops = "h";
-  this->SetCmdline({"argv0"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-
-  sops = "h";
-  this->SetCmdline({"argv0", "-h"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'h');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 2);
-
-  sops = "h";
-  this->SetCmdline({"argv0", "positional1", "positional2"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-
-  sops = "h";
-  this->SetCmdline({"argv0", "--", "positional1", "positional2"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 2);
-
-  sops = "h";
-  this->SetCmdline({"argv0", "-h"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'h');
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 2);
-
-  sops = "abc";
-  this->SetCmdline({"argv0", "-c", "-a", "-b"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optind, 3);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
-  EXPECT_EQ(t.optind, 4);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 4);
-
-  sops = "abc";
-  this->SetCmdline({"argv0", "-c", "-a", "--", "nonopt"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 3);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 4);
-
-  sops = "abc";
-  this->SetCmdline({"argv0", "-cb"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 1);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optarg, nullptr);
-  EXPECT_EQ(t.optind, 2);
-
-  sops = "abc";
-  this->SetCmdline({"argv0", "-aa", "-c"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optind, 1);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_EQ(t.optind, 3);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 3);
-
-  sops = "a:bc";
-  // The semantic here is `-a b -c`
-  this->SetCmdline({"argv0", "-ab", "-c"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_STREQ(t.optarg, "b");
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_EQ(t.optind, 3);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 3);
-
-  sops = "a:bc";
-  this->SetCmdline({"argv0", "-ab", "--", "-c"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_EQ(t.optind, 2);
-  EXPECT_STREQ(t.optarg, "b");
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 3);
-
-  sops = "a:b:c:";
-  this->SetCmdline({"argv0", "-a", "arg1", "-b", "--", "-c", "-carg"});
-  // This is sbutle, the "--" is an arg value for "-b", not a separator.
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
-  EXPECT_STREQ(t.optarg, "arg1");
-  EXPECT_EQ(t.optind, 3);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
-  EXPECT_STREQ(t.optarg, "--");
-  EXPECT_EQ(t.optind, 5);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
-  EXPECT_STREQ(t.optarg, "-carg");
-  EXPECT_EQ(t.optind, 7);
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
-  EXPECT_EQ(t.optind, 7);
-
-  sops = "a";
-  this->SetCmdline({"argv0", "-q"});
-  EXPECT_EQ(t.getopt(this->argc, this->argv, sops), '?');
-  EXPECT_EQ(t.optind, 2);
-}
-
-TYPED_TEST(GetoptCompatTest, LongOptions) {
-  auto& t = this->impl;
-  using LongOptionType = typename decltype(this->impl)::LongOptionType;
-
-  {
-    LongOptionType lopts[]{
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 1);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0", "--unknown"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 2);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {"one", 0 /*no_argument*/, nullptr, 1},
-        {"two", 0 /*no_argument*/, nullptr, 2},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0", "--two", "--one"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 2);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 3);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {"one", 0 /*no_argument*/, nullptr, 1},
-        {"two", 0 /*no_argument*/, nullptr, 2},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0", "--two", "--one", "--not-an-opt"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 2);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 4);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {"one", 0 /*no_argument*/, nullptr, 1},
-        {"two", 0 /*no_argument*/, nullptr, 2},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0", "--two", "--one", "--", "--not-an-opt"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optind, 2);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optind, 4);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {"no1", 0 /*no_argument*/, nullptr, 1},
-        {"req2", 1 /*required_argument*/, nullptr, 2},
-        {"req3", 1 /*required_argument*/, nullptr, 3},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    // This is subtle: the "--" really is an argument for req2, not an argument
-    // separator. The first positional arg is "!!!".
-    this->SetCmdline({"argv0", "--req3", "-", "--no1", "--req2", "--", "!!!"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 3);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_STREQ(t.optarg, "-");
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
-    EXPECT_EQ(t.optind, 4);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_STREQ(t.optarg, "--");
-    EXPECT_EQ(t.optind, 6);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optind, 6);
-  }
-
-  {
-    LongOptionType lopts[]{
-        {"no1", 0 /*no_argument*/, nullptr, 1},
-        {"req2", 1 /*required_argument*/, nullptr, 2},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "";
-    this->SetCmdline({"argv0", "--req2", "foo", "--", "--no1"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_STREQ(t.optarg, "foo");
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optind, 4);
-  }
-}
-
-TYPED_TEST(GetoptCompatTest, ShortAndLongOptions) {
-  auto& t = this->impl;
-  using LongOptionType = typename decltype(this->impl)::LongOptionType;
-
-  {
-    LongOptionType lopts[]{
-        {"one", 0 /*no_argument*/, nullptr, 1},
-        {"two", 0 /*no_argument*/, nullptr, 2},
-        {"three", 0 /*no_argument*/, nullptr, 3},
-        {nullptr, 0, nullptr, 0},
-    };
-    const char* sops = "123";
-
-    this->SetCmdline({"argv0"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optarg, nullptr);
-    EXPECT_EQ(t.optind, 1);
-
-    this->SetCmdline({"argv0", "-13", "--two", "--three", "--", "--one"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
-    EXPECT_EQ(t.optind, 1);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '3');
-    EXPECT_EQ(t.optind, 2);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 3);
-    EXPECT_EQ(t.optind, 4);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optind, 5);
-
-    this->SetCmdline({"argv0", "--two", "-1", "--two", "-13"});
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optind, 2);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
-    EXPECT_EQ(t.optind, 3);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
-    EXPECT_EQ(t.optind, 4);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
-    EXPECT_EQ(t.optind, 4);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '3');
-    EXPECT_EQ(t.optind, 5);
-    EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
-    EXPECT_EQ(t.optind, 5);
-  }
-}
-
-}  // namespace
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/logging.cc b/src/base/logging.cc
index 5b251d6..b733988 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -23,7 +23,6 @@
 #include <unistd.h>  // For isatty()
 #endif
 
-#include <atomic>
 #include <memory>
 
 #include "perfetto/base/time.h"
@@ -39,14 +38,8 @@
 const char kBoldGreen[] = "\x1b[1m\x1b[32m";
 const char kLightGray[] = "\x1b[90m";
 
-std::atomic<LogMessageCallback> g_log_callback{};
-
 }  // namespace
 
-void SetLogMessageCallback(LogMessageCallback callback) {
-  g_log_callback.store(callback, std::memory_order_relaxed);
-}
-
 void LogMessage(LogLev level,
                 const char* fname,
                 int line,
@@ -82,12 +75,6 @@
     log_msg = &large_buf[0];
   }
 
-  LogMessageCallback cb = g_log_callback.load(std::memory_order_relaxed);
-  if (cb) {
-    cb({level, line, fname, log_msg});
-    return;
-  }
-
   const char* color = kDefault;
   switch (level) {
     case kLogDebug:
diff --git a/src/base/logging_unittest.cc b/src/base/logging_unittest.cc
deleted file mode 100644
index 5349290..0000000
--- a/src/base/logging_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/logging.h"
-
-#include <stdint.h>
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace base {
-namespace {
-
-char g_last_line[256];
-
-TEST(LoggingTest, Basic) {
-  SetLogMessageCallback(nullptr);
-  LogMessage(kLogDebug, "file.cc", 100, "test message %d", 1);
-
-  SetLogMessageCallback(+[](LogMessageCallbackArgs log) {
-    sprintf(g_last_line, "%d:%s:%d:%s", log.level, log.filename, log.line,
-            log.message);
-  });
-
-  g_last_line[0] = 0;
-  LogMessage(kLogDebug, "file.cc", 101, "test message %d", 2);
-  ASSERT_STREQ(g_last_line, "0:file.cc:101:test message 2");
-
-  g_last_line[0] = 0;
-  SetLogMessageCallback(nullptr);
-  LogMessage(kLogDebug, "file.cc", 102, "test message %d", 3);
-  ASSERT_STREQ(g_last_line, "");
-}
-
-}  // namespace
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/metatrace.cc b/src/base/metatrace.cc
index c676d80..67d167c 100644
--- a/src/base/metatrace.cc
+++ b/src/base/metatrace.cc
@@ -20,7 +20,6 @@
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
 #include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/thread_annotations.h"
 
 namespace perfetto {
 namespace metatrace {
diff --git a/src/base/metatrace_unittest.cc b/src/base/metatrace_unittest.cc
index d0c9bb0..88f1a67 100644
--- a/src/base/metatrace_unittest.cc
+++ b/src/base/metatrace_unittest.cc
@@ -15,13 +15,11 @@
  */
 
 #include <array>
-#include <atomic>
 #include <chrono>
 #include <deque>
 #include <thread>
 
 #include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/thread_annotations.h"
 #include "src/base/test/test_task_runner.h"
 #include "test/gtest_and_gmock.h"
 
@@ -166,7 +164,7 @@
 // consistently without gaps.
 TEST_F(MetatraceTest, InterleavedReadWrites) {
   Enable(m::TAG_ANY);
-  constexpr int kMaxValue = m::RingBuffer::kCapacity * 3;
+  constexpr int kMaxValue = m::RingBuffer::kCapacity * 10;
 
   std::atomic<int> last_value_read{-1};
   auto read_task = [&last_value_read] {
@@ -174,14 +172,8 @@
     for (auto it = m::RingBuffer::GetReadIterator(); it; ++it) {
       if (it->type_and_id.load(std::memory_order_acquire) == 0)
         break;
-      // TSan doesn't know about the happens-before relationship between the
-      // type_and_id marker and the value being valid. Fixing this properly
-      // would require making all accesses to the metatrace object as
-      // std::atomic and read them with memory_order_relaxed, which is overkill.
-      PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(&it->counter_value, sizeof(int), "")
-      int32_t counter_value = it->counter_value;
-      EXPECT_EQ(counter_value, last + 1);
-      last = counter_value;
+      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.
@@ -198,13 +190,8 @@
       const int kCapacity = static_cast<int>(m::RingBuffer::kCapacity);
 
       // Wait for the reader to avoid overruns.
-      // Using memory_order_relaxed because the QEMU arm emulator seems to incur
-      // in very high costs when dealing with full barriers, causing timeouts.
-      for (int sleep_us = 1;
-           i - last_value_read.load(std::memory_order_relaxed) >= kCapacity - 1;
-           sleep_us = std::min(sleep_us * 10, 1000)) {
-        std::this_thread::sleep_for(std::chrono::microseconds(sleep_us));
-      }
+      while (i - last_value_read >= kCapacity - 1)
+        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
     }
     task_runner_.PostTask(writer_done);
   });
diff --git a/src/base/optional_unittest.cc b/src/base/optional_unittest.cc
index 285db51..9c073ec 100644
--- a/src/base/optional_unittest.cc
+++ b/src/base/optional_unittest.cc
@@ -16,10 +16,8 @@
 
 // Comparisions of floats is used extensively in this file. Ignore warnings
 // as we want to stay close to Chromium.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wfloat-equal"
-#endif
 
 #include <memory>
 #include <set>
@@ -2206,6 +2204,4 @@
 }  // namespace base
 }  // namespace perfetto
 
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic pop
-#endif
diff --git a/src/base/paged_memory.cc b/src/base/paged_memory.cc
index 551c5ca..c7feb53 100644
--- a/src/base/paged_memory.cc
+++ b/src/base/paged_memory.cc
@@ -34,47 +34,39 @@
 
 namespace {
 
+constexpr size_t kGuardSize = kPageSize;
+
 #if TRACK_COMMITTED_SIZE()
-constexpr size_t kCommitChunkSize = 4 * 1024 * 1024;  // 4MB
-#endif
-
-size_t RoundUpToSysPageSize(size_t req_size) {
-  const size_t page_size = GetSysPageSize();
-  return (req_size + page_size - 1) & ~(page_size - 1);
-}
-
-size_t GuardSize() {
-  return GetSysPageSize();
-}
+constexpr size_t kCommitChunkSize = kPageSize * 1024;  // 4mB
+#endif                                                 // TRACK_COMMITTED_SIZE()
 
 }  // namespace
 
 // static
-PagedMemory PagedMemory::Allocate(size_t req_size, int flags) {
-  size_t rounded_up_size = RoundUpToSysPageSize(req_size);
-  PERFETTO_CHECK(rounded_up_size >= req_size);
-  size_t outer_size = rounded_up_size + GuardSize() * 2;
+PagedMemory PagedMemory::Allocate(size_t size, int flags) {
+  PERFETTO_DCHECK(size % kPageSize == 0);
+  size_t outer_size = size + kGuardSize * 2;
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   void* ptr = VirtualAlloc(nullptr, outer_size, MEM_RESERVE, PAGE_NOACCESS);
   if (!ptr && (flags & kMayFail))
     return PagedMemory();
   PERFETTO_CHECK(ptr);
-  char* usable_region = reinterpret_cast<char*>(ptr) + GuardSize();
+  char* usable_region = reinterpret_cast<char*>(ptr) + kGuardSize;
 #else   // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   void* ptr = mmap(nullptr, outer_size, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (ptr == MAP_FAILED && (flags & kMayFail))
     return PagedMemory();
   PERFETTO_CHECK(ptr && ptr != MAP_FAILED);
-  char* usable_region = reinterpret_cast<char*>(ptr) + GuardSize();
-  int res = mprotect(ptr, GuardSize(), PROT_NONE);
-  res |= mprotect(usable_region + rounded_up_size, GuardSize(), PROT_NONE);
+  char* usable_region = reinterpret_cast<char*>(ptr) + kGuardSize;
+  int res = mprotect(ptr, kGuardSize, PROT_NONE);
+  res |= mprotect(usable_region + size, kGuardSize, PROT_NONE);
   PERFETTO_CHECK(res == 0);
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
-  auto memory = PagedMemory(usable_region, req_size);
+  auto memory = PagedMemory(usable_region, size);
 #if TRACK_COMMITTED_SIZE()
-  size_t initial_commit = req_size;
+  size_t initial_commit = size;
   if (flags & kDontCommit)
     initial_commit = std::min(initial_commit, kCommitChunkSize);
   memory.EnsureCommitted(initial_commit);
@@ -105,12 +97,12 @@
   if (!p_)
     return;
   PERFETTO_CHECK(size_);
-  char* start = p_ - GuardSize();
+  char* start = p_ - kGuardSize;
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   BOOL res = VirtualFree(start, 0, MEM_RELEASE);
   PERFETTO_CHECK(res != 0);
 #else   // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  const size_t outer_size = RoundUpToSysPageSize(size_) + GuardSize() * 2;
+  const size_t outer_size = size_ + kGuardSize * 2;
   int res = munmap(start, outer_size);
   PERFETTO_CHECK(res == 0);
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/paged_memory_unittest.cc b/src/base/paged_memory_unittest.cc
index fd2790d..06695d6 100644
--- a/src/base/paged_memory_unittest.cc
+++ b/src/base/paged_memory_unittest.cc
@@ -19,12 +19,11 @@
 #include <stdint.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/utils.h"
 #include "src/base/test/vm_test_utils.h"
 #include "test/gtest_and_gmock.h"
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&   \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&    \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
 #include <sys/resource.h>
 #endif
@@ -64,32 +63,6 @@
 #endif
 }
 
-TEST(PagedMemoryTest, SubPageGranularity) {
-  const size_t kSize = GetSysPageSize() + 1024;
-  PagedMemory mem = PagedMemory::Allocate(kSize);
-  ASSERT_TRUE(mem.IsValid());
-  ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(mem.Get()) % GetSysPageSize());
-  void* ptr_raw = mem.Get();
-  for (size_t i = 0; i < kSize / sizeof(uint64_t); i++) {
-    auto* ptr64 = reinterpret_cast<volatile uint64_t*>(ptr_raw) + i;
-    ASSERT_EQ(0u, *ptr64);
-    *ptr64 = i;
-  }
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  // Do an AdviseDontNeed on the whole range, which is NOT an integer multiple
-  // of the page size. The initial page must be cleared. The remaining 1024
-  // might or might not be cleared depending on the OS implementation.
-  ASSERT_TRUE(mem.AdviseDontNeed(ptr_raw, kSize));
-  ASSERT_FALSE(vm_test_utils::IsMapped(ptr_raw, GetSysPageSize()));
-  for (size_t i = 0; i < GetSysPageSize() / sizeof(uint64_t); i++) {
-    auto* ptr64 = reinterpret_cast<volatile uint64_t*>(ptr_raw) + i;
-    ASSERT_EQ(0u, *ptr64);
-  }
-#endif
-}
-
 TEST(PagedMemoryTest, Uncommitted) {
   constexpr size_t kNumPages = 4096;
   constexpr size_t kSize = 4096 * kNumPages;
@@ -164,7 +137,7 @@
 #endif  // ADDRESS_SANITIZER
 
 TEST(PagedMemoryTest, GuardRegions) {
-  const size_t kSize = GetSysPageSize();
+  const size_t kSize = 4096;
   PagedMemory mem = PagedMemory::Allocate(kSize);
   ASSERT_TRUE(mem.IsValid());
   volatile char* raw = reinterpret_cast<char*>(mem.Get());
@@ -176,7 +149,7 @@
 // MacOS: because it doesn't seem to have an equivalent rlimit to bound mmap().
 // Fuchsia: doesn't support rlimit.
 // Sanitizers: they seem to try to shadow mmaped memory and fail due to OOMs.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) &&                                  \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) &&                                 \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&                                    \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA) && !defined(ADDRESS_SANITIZER) && \
     !defined(LEAK_SANITIZER) && !defined(THREAD_SANITIZER) &&                  \
diff --git a/src/base/periodic_task.cc b/src/base/periodic_task.cc
deleted file mode 100644
index fcbc9de..0000000
--- a/src/base/periodic_task.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/periodic_task.h"
-
-#include <limits>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    (PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && __ANDROID_API__ >= 19)
-#include <sys/timerfd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-namespace {
-base::ScopedPlatformHandle CreateTimerFd(uint32_t period_ms) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    (PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && __ANDROID_API__ >= 19)
-  base::ScopedPlatformHandle tfd(
-      timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK));
-  // The initial phase, aligned on wall clock.
-  uint32_t phase_ms =
-      period_ms -
-      static_cast<uint32_t>(base::GetBootTimeNs().count() % period_ms);
-  struct itimerspec its {};
-  // The "1 +" is to make sure that we never pass a zero it_value in the
-  // unlikely case of phase_ms being 0. That would cause the timer to be
-  // considered disarmed by timerfd_settime.
-  its.it_value.tv_sec = static_cast<time_t>(phase_ms / 1000u);
-  its.it_value.tv_nsec = 1 + static_cast<long>((phase_ms % 1000u) * 1000000u);
-  its.it_interval.tv_sec = static_cast<time_t>(period_ms / 1000u);
-  its.it_interval.tv_nsec = static_cast<long>((period_ms % 1000u) * 1000000u);
-  if (timerfd_settime(*tfd, 0, &its, nullptr) < 0)
-    return base::ScopedPlatformHandle();
-  return tfd;
-#else
-  base::ignore_result(period_ms);
-  return base::ScopedPlatformHandle();
-#endif
-}
-}  // namespace
-
-PeriodicTask::PeriodicTask(base::TaskRunner* task_runner)
-    : task_runner_(task_runner), weak_ptr_factory_(this) {}
-
-PeriodicTask::~PeriodicTask() {
-  Reset();
-}
-
-void PeriodicTask::Start(Args args) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  Reset();
-  if (args.period_ms == 0 || !args.task) {
-    PERFETTO_DCHECK(args.period_ms > 0);
-    PERFETTO_DCHECK(args.task);
-    return;
-  }
-  args_ = std::move(args);
-  if (args_.use_suspend_aware_timer) {
-    timer_fd_ = CreateTimerFd(args_.period_ms);
-    if (timer_fd_) {
-      auto weak_this = weak_ptr_factory_.GetWeakPtr();
-      task_runner_->AddFileDescriptorWatch(
-          *timer_fd_,
-          std::bind(PeriodicTask::RunTaskAndPostNext, weak_this, generation_));
-    } else {
-      PERFETTO_DPLOG("timerfd not supported, falling back on PostDelayedTask");
-    }
-  }  // if (use_suspend_aware_timer).
-
-  if (!timer_fd_)
-    PostNextTask();
-
-  if (args_.start_first_task_immediately)
-    args_.task();
-}
-
-void PeriodicTask::PostNextTask() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DCHECK(args_.period_ms > 0);
-  PERFETTO_DCHECK(!timer_fd_);
-  uint32_t delay_ms =
-      args_.period_ms -
-      static_cast<uint32_t>(base::GetWallTimeMs().count() % args_.period_ms);
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      std::bind(PeriodicTask::RunTaskAndPostNext, weak_this, generation_),
-      delay_ms);
-}
-
-// static
-// This function can be called in two ways (both from the TaskRunner):
-// 1. When using a timerfd, this task is registered as a FD watch.
-// 2. When using PostDelayedTask, this is the task posted on the TaskRunner.
-void PeriodicTask::RunTaskAndPostNext(base::WeakPtr<PeriodicTask> thiz,
-                                      uint32_t generation) {
-  if (!thiz || !thiz->args_.task || generation != thiz->generation_)
-    return;  // Destroyed or Reset() in the meanwhile.
-  PERFETTO_DCHECK_THREAD(thiz->thread_checker_);
-  if (thiz->timer_fd_) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    PERFETTO_FATAL("timerfd for periodic tasks unsupported on Windows");
-#else
-    // If we are using a timerfd there is no need to repeatedly call
-    // PostDelayedTask(). The kernel will wakeup the timer fd periodically. We
-    // just need to read() it.
-    uint64_t ignored = 0;
-    errno = 0;
-    auto rsize = base::Read(*thiz->timer_fd_, &ignored, sizeof(&ignored));
-    if (rsize != sizeof(uint64_t)) {
-      if (errno == EAGAIN)
-        return;  // A spurious wakeup. Rare, but can happen, just ignore.
-      PERFETTO_PLOG("read(timerfd) failed, falling back on PostDelayedTask");
-      thiz->ResetTimerFd();
-    }
-#endif
-  }
-  // The repetition of the if() is to deal with the ResetTimerFd() case above.
-  if (!thiz->timer_fd_) {
-    thiz->PostNextTask();
-  }
-  // Create a copy of the task in the unlikely event that the task ends up
-  // up destroying the PeriodicTask object or calling Reset() on it. That would
-  // cause a reset of the args_.task itself, which would invalidate the task
-  // bind state while we are invoking it.
-  auto task = thiz->args_.task;
-  task();
-}
-
-void PeriodicTask::Reset() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  ++generation_;
-  args_ = Args();
-  PERFETTO_DCHECK(!args_.task);
-  ResetTimerFd();
-}
-
-void PeriodicTask::ResetTimerFd() {
-  if (!timer_fd_)
-    return;
-  task_runner_->RemoveFileDescriptorWatch(*timer_fd_);
-  timer_fd_.reset();
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/periodic_task_unittest.cc b/src/base/periodic_task_unittest.cc
deleted file mode 100644
index 4919720..0000000
--- a/src/base/periodic_task_unittest.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/periodic_task.h"
-
-#include "perfetto/ext/base/file_utils.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/gtest_and_gmock.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <unistd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-namespace {
-
-TEST(PeriodicTaskTest, PostDelayedTaskMode) {
-  TestTaskRunner task_runner;
-  PeriodicTask pt(&task_runner);
-  uint32_t num_callbacks = 0;
-  auto quit_closure = task_runner.CreateCheckpoint("all_timers_done");
-
-  PeriodicTask::Args args;
-  args.task = [&] {
-    if (++num_callbacks == 3)
-      quit_closure();
-  };
-  args.period_ms = 1;
-  args.start_first_task_immediately = true;
-  pt.Start(std::move(args));
-  EXPECT_EQ(num_callbacks, 1u);
-  task_runner.RunUntilCheckpoint("all_timers_done");
-  EXPECT_EQ(num_callbacks, 3u);
-}
-
-// Call Reset() from a callback, ensure no further calls are made.
-TEST(PeriodicTaskTest, ResetFromCallback) {
-  TestTaskRunner task_runner;
-  PeriodicTask pt(&task_runner);
-  uint32_t num_callbacks = 0;
-  PeriodicTask::Args args;
-  auto quit_closure = task_runner.CreateCheckpoint("quit_closure");
-  args.task = [&] {
-    ++num_callbacks;
-    pt.Reset();
-    task_runner.PostDelayedTask(quit_closure, 5);
-  };
-  args.period_ms = 1;
-  pt.Start(std::move(args));
-  EXPECT_EQ(num_callbacks, 0u);  // No immediate execution.
-
-  task_runner.RunUntilCheckpoint("quit_closure");
-  EXPECT_EQ(num_callbacks, 1u);
-}
-
-// Invalidates the timerfd, by replacing it with /dev/null, in the middle of
-// the periodic ticks. That causes the next read() to fail and fall back on
-// PostDelayedTask().
-// On Mac and other systems where timerfd is not supported this will fall back
-// on PostDelayedTask() immediately (and work).
-TEST(PeriodicTaskTest, FallbackIfTimerfdFails) {
-  TestTaskRunner task_runner;
-  PeriodicTask pt(&task_runner);
-  uint32_t num_callbacks = 0;
-  auto quit_closure = task_runner.CreateCheckpoint("all_timers_done");
-
-  PeriodicTask::Args args;
-  args.task = [&] {
-    ++num_callbacks;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    if (num_callbacks == 3 && pt.timer_fd_for_testing() > 0) {
-      ScopedFile dev_null = OpenFile("/dev/null", O_RDONLY);
-      dup2(*dev_null, pt.timer_fd_for_testing());
-    }
-#else
-    EXPECT_FALSE(base::ScopedPlatformHandle::ValidityChecker::IsValid(
-        pt.timer_fd_for_testing()));
-#endif
-    if (num_callbacks == 6)
-      quit_closure();
-  };
-  args.period_ms = 1;
-  args.use_suspend_aware_timer = true;
-  pt.Start(std::move(args));
-  task_runner.RunUntilCheckpoint("all_timers_done");
-  EXPECT_EQ(num_callbacks, 6u);
-}
-
-TEST(PeriodicTaskTest, DestroyedFromCallback) {
-  TestTaskRunner task_runner;
-  std::unique_ptr<PeriodicTask> pt(new PeriodicTask(&task_runner));
-  uint32_t num_callbacks = 0;
-  PeriodicTask::Args args;
-  auto quit_closure = task_runner.CreateCheckpoint("quit_closure");
-  args.task = [&] {
-    ++num_callbacks;
-    pt.reset();
-    task_runner.PostDelayedTask(quit_closure, 5);
-  };
-  args.period_ms = 1;
-  args.use_suspend_aware_timer = true;
-  pt->Start(std::move(args));
-
-  task_runner.RunUntilCheckpoint("quit_closure");
-  EXPECT_EQ(num_callbacks, 1u);
-  EXPECT_FALSE(pt);
-}
-
-TEST(PeriodicTaskTest, DestroyedFromAnotherTask) {
-  TestTaskRunner task_runner;
-  std::unique_ptr<PeriodicTask> pt(new PeriodicTask(&task_runner));
-  uint32_t num_callbacks = 0;
-  PeriodicTask::Args args;
-  auto quit_closure = task_runner.CreateCheckpoint("quit_closure");
-  args.task = [&] {
-    if (++num_callbacks == 2) {
-      task_runner.PostTask([&] {
-        pt.reset();
-        task_runner.PostDelayedTask(quit_closure, 5);
-      });
-    }
-  };
-  args.period_ms = 1;
-  args.use_suspend_aware_timer = true;
-  pt->Start(std::move(args));
-
-  task_runner.RunUntilCheckpoint("quit_closure");
-  EXPECT_EQ(num_callbacks, 2u);
-  EXPECT_FALSE(pt);
-}
-
-// Checks the generation logic.
-TEST(PeriodicTaskTest, RestartWhileRunning) {
-  TestTaskRunner task_runner;
-  PeriodicTask pt(&task_runner);
-  uint32_t num_callbacks_a = 0;
-  uint32_t num_callbacks_b = 0;
-  auto quit_closure = task_runner.CreateCheckpoint("quit_closure");
-
-  auto reuse = [&] {
-    PeriodicTask::Args args;
-    args.period_ms = 1;
-    args.task = [&] {
-      if (++num_callbacks_b == 3)
-        quit_closure();
-    };
-    pt.Start(std::move(args));
-  };
-
-  PeriodicTask::Args args;
-  args.task = [&] {
-    if (++num_callbacks_a == 2)
-      task_runner.PostTask(reuse);
-  };
-  args.period_ms = 1;
-  args.use_suspend_aware_timer = true;
-  pt.Start(std::move(args));
-
-  task_runner.RunUntilCheckpoint("quit_closure");
-  EXPECT_EQ(num_callbacks_a, 2u);
-  EXPECT_EQ(num_callbacks_b, 3u);
-}
-
-TEST(PeriodicTaskTest, ImmediateExecution) {
-  TestTaskRunner task_runner;
-  PeriodicTask pt(&task_runner);
-  uint32_t num_callbacks = 0;
-
-  PeriodicTask::Args args;
-  args.task = [&] { ++num_callbacks; };
-  args.period_ms = 1;
-  pt.Start(args);
-  EXPECT_EQ(num_callbacks, 0u);  // No immediate execution.
-
-  args.start_first_task_immediately = true;
-  pt.Start(args);
-  EXPECT_EQ(num_callbacks, 1u);
-}
-
-}  // namespace
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/pipe.cc b/src/base/pipe.cc
index f4912f7..c61492f 100644
--- a/src/base/pipe.cc
+++ b/src/base/pipe.cc
@@ -14,19 +14,13 @@
  * 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/build_config.h"
-
-#include <fcntl.h>  // For O_BINARY (Windows) and F_SETxx (UNIX)
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <namedpipeapi.h>
-#else
 #include <sys/types.h>
 #include <unistd.h>
-#endif
 
 #include "perfetto/base/logging.h"
 
@@ -38,20 +32,15 @@
 Pipe& Pipe::operator=(Pipe&&) = default;
 
 Pipe Pipe::Create(Flags flags) {
-  PlatformHandle fds[2];
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  PERFETTO_CHECK(::CreatePipe(&fds[0], &fds[1], /*lpPipeAttributes=*/nullptr,
-                              0 /*default size*/));
-#else
+  int fds[2];
   PERFETTO_CHECK(pipe(fds) == 0);
-  PERFETTO_CHECK(fcntl(fds[0], F_SETFD, FD_CLOEXEC) == 0);
-  PERFETTO_CHECK(fcntl(fds[1], F_SETFD, FD_CLOEXEC) == 0);
-#endif
   Pipe p;
   p.rd.reset(fds[0]);
   p.wr.reset(fds[1]);
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+  PERFETTO_CHECK(fcntl(*p.rd, F_SETFD, FD_CLOEXEC) == 0);
+  PERFETTO_CHECK(fcntl(*p.wr, F_SETFD, FD_CLOEXEC) == 0);
+
   if (flags == kBothNonBlock || flags == kRdNonBlock) {
     int cur_flags = fcntl(*p.rd, F_GETFL, 0);
     PERFETTO_CHECK(cur_flags >= 0);
@@ -63,11 +52,10 @@
     PERFETTO_CHECK(cur_flags >= 0);
     PERFETTO_CHECK(fcntl(*p.wr, F_SETFL, cur_flags | O_NONBLOCK) == 0);
   }
-#else
-  PERFETTO_CHECK(flags == kBothBlock);
-#endif
   return p;
 }
 
 }  // 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 7590955..dff4413 100644
--- a/src/base/scoped_file_unittest.cc
+++ b/src/base/scoped_file_unittest.cc
@@ -18,11 +18,10 @@
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/base/build_config.h"
 
-#include <fcntl.h>
-
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <io.h>
+#include <corecrt_io.h>
 #else
+#include <fcntl.h>
 #include <unistd.h>
 // Double closing of file handles on Windows leads to invocation of the invalid
 // parameter handler or asserts and therefore it cannot be tested, but it can
diff --git a/src/base/status.cc b/src/base/status.cc
deleted file mode 100644
index 30ccc47..0000000
--- a/src/base/status.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/base/status.h"
-
-#include <stdarg.h>
-
-namespace perfetto {
-namespace base {
-
-Status ErrStatus(const char* format, ...) {
-  char buffer[1024];
-  va_list ap;
-  va_start(ap, format);
-  vsnprintf(buffer, sizeof(buffer), format, ap);
-  va_end(ap);
-  Status status(buffer);
-  return status;
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/string_utils.cc b/src/base/string_utils.cc
index c0b0780..f1ee35e 100644
--- a/src/base/string_utils.cc
+++ b/src/base/string_utils.cc
@@ -16,73 +16,14 @@
 
 #include "perfetto/ext/base/string_utils.h"
 
-#include <inttypes.h>
-#include <locale.h>
 #include <string.h>
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-#include <xlocale.h>
-#endif
-
 #include <algorithm>
 
 #include "perfetto/base/logging.h"
 
 namespace perfetto {
 namespace base {
-namespace {
-constexpr char kBase64Table[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "abcdefghijklmnopqrstuvwxyz0123456789+/";
-}
-
-// Locale-independant as possible version of strtod.
-double StrToD(const char* nptr, char** endptr) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-  static auto c_locale = newlocale(LC_ALL, "C", nullptr);
-  return strtod_l(nptr, endptr, c_locale);
-#else
-  return strtod(nptr, endptr);
-#endif
-}
-
-std::string QuoteAndEscapeControlCodes(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 + '"';
-}
 
 bool StartsWith(const std::string& str, const std::string& prefix) {
   return str.compare(0, prefix.length(), prefix) == 0;
@@ -98,12 +39,8 @@
   return haystack.find(needle) != std::string::npos;
 }
 
-bool Contains(const std::string& haystack, const char needle) {
-  return haystack.find(needle) != std::string::npos;
-}
-
 size_t Find(const StringView& needle, const StringView& haystack) {
-  if (needle.empty())
+  if (needle.size() == 0)
     return 0;
   if (needle.size() > haystack.size())
     return std::string::npos;
@@ -201,20 +138,6 @@
   return buf;
 }
 
-std::string Uint64ToHexString(uint64_t number) {
-  return "0x" + Uint64ToHexStringNoPrefix(number);
-}
-
-std::string Uint64ToHexStringNoPrefix(uint64_t number) {
-  size_t max_size = 17;  // Max uint64 is FFFFFFFFFFFFFFFF + 1 for null byte.
-  std::string buf;
-  buf.resize(max_size);
-  auto final_size = snprintf(&buf[0], max_size, "%" PRIx64 "", number);
-  PERFETTO_DCHECK(final_size >= 0);
-  buf.resize(static_cast<size_t>(final_size));  // Cuts off the final null byte.
-  return buf;
-}
-
 std::string StripChars(const std::string& str,
                        const std::string& chars,
                        char replacement) {
@@ -226,60 +149,5 @@
   return res;
 }
 
-std::string ReplaceAll(std::string str,
-                       const std::string& to_replace,
-                       const std::string& replacement) {
-  PERFETTO_CHECK(!to_replace.empty());
-  size_t pos = 0;
-  while ((pos = str.find(to_replace, pos)) != std::string::npos) {
-    str.replace(pos, to_replace.length(), replacement);
-    pos += replacement.length();
-  }
-  return str;
-}
-
-std::string TrimLeading(const std::string& str) {
-  size_t idx = str.find_first_not_of(' ');
-  return idx == std::string::npos ? str : str.substr(idx);
-}
-
-std::string Base64Encode(const void* raw, size_t size) {
-  // The following three cases are based on the tables in the example
-  // section in https://en.wikipedia.org/wiki/Base64. We process three
-  // input bytes at a time, emitting 4 output bytes at a time.
-  const uint8_t* ptr = static_cast<const uint8_t*>(raw);
-  size_t ii = 0;
-
-  std::string out;
-  out.reserve((size + 2) * 4 / 3);
-
-  // While possible, process three input bytes.
-  for (; ii + 3 <= size; ii += 3) {
-    uint32_t twentyfour_bits =
-        (uint32_t(ptr[ii]) << 16) | (uint32_t(ptr[ii + 1]) << 8) | ptr[ii + 2];
-    out.push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out.push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out.push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
-    out.push_back(kBase64Table[twentyfour_bits & 0x3f]);
-  }
-  if (ii + 2 <= size) {  // Process two input bytes.
-    uint32_t twentyfour_bits =
-        (uint32_t(ptr[ii]) << 16) | (uint32_t(ptr[ii + 1]) << 8);
-    out.push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out.push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out.push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
-    out.push_back('=');  // Emit padding.
-    return out;
-  }
-  if (ii + 1 <= size) {  // Process a single input byte.
-    uint32_t twentyfour_bits = (uint32_t(ptr[ii]) << 16);
-    out.push_back(kBase64Table[(twentyfour_bits >> 18)]);
-    out.push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
-    out.push_back('=');  // Emit padding.
-    out.push_back('=');  // Emit padding.
-  }
-  return out;
-}
-
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/string_utils_unittest.cc b/src/base/string_utils_unittest.cc
index 5c41f16..f41c470 100644
--- a/src/base/string_utils_unittest.cc
+++ b/src/base/string_utils_unittest.cc
@@ -134,15 +134,10 @@
   EXPECT_DOUBLE_EQ(StringToDouble("1").value(), 1l);
   EXPECT_DOUBLE_EQ(StringToDouble("-42").value(), -42l);
   EXPECT_DOUBLE_EQ(StringToDouble("-42.5").value(), -42.5l);
-  EXPECT_DOUBLE_EQ(StringToDouble("0.5").value(), .5l);
-  EXPECT_DOUBLE_EQ(StringToDouble(".5").value(), .5l);
   EXPECT_EQ(StringToDouble(""), nullopt);
   EXPECT_EQ(StringToDouble("!?"), nullopt);
   EXPECT_EQ(StringToDouble("abc"), nullopt);
   EXPECT_EQ(StringToDouble("123 abc"), nullopt);
-  EXPECT_EQ(StringToDouble("124,456"), nullopt);
-  EXPECT_EQ(StringToDouble("4 2"), nullopt);
-  EXPECT_EQ(StringToDouble(" - 42"), nullopt);
 }
 
 TEST(StringUtilsTest, StartsWith) {
@@ -172,28 +167,13 @@
   EXPECT_EQ(ToHex("abc123"), "616263313233");
 }
 
-TEST(StringUtilsTest, IntToHex) {
+TEST(StringUtilsTest, intToHex) {
   EXPECT_EQ(IntToHexString(0), "0x00");
   EXPECT_EQ(IntToHexString(1), "0x01");
   EXPECT_EQ(IntToHexString(16), "0x10");
   EXPECT_EQ(IntToHexString(4294967295), "0xffffffff");
 }
 
-TEST(StringUtilsTest, Uint64ToHex) {
-  EXPECT_EQ(Uint64ToHexString(0), "0x0");
-  EXPECT_EQ(Uint64ToHexString(1), "0x1");
-  EXPECT_EQ(Uint64ToHexString(16), "0x10");
-  EXPECT_EQ(Uint64ToHexString(18446744073709551615UL), "0xffffffffffffffff");
-}
-
-TEST(StringUtilsTest, Uint64ToHexNoPrefix) {
-  EXPECT_EQ(Uint64ToHexStringNoPrefix(0), "0");
-  EXPECT_EQ(Uint64ToHexStringNoPrefix(1), "1");
-  EXPECT_EQ(Uint64ToHexStringNoPrefix(16), "10");
-  EXPECT_EQ(Uint64ToHexStringNoPrefix(18446744073709551615UL),
-            "ffffffffffffffff");
-}
-
 TEST(StringUtilsTest, CaseInsensitiveEqual) {
   EXPECT_TRUE(CaseInsensitiveEqual("", ""));
   EXPECT_TRUE(CaseInsensitiveEqual("abc", "abc"));
@@ -268,49 +248,6 @@
   EXPECT_EQ(Find("abc", ""), std::string::npos);
 }
 
-TEST(StringUtilsTest, ReplaceAll) {
-  EXPECT_EQ(ReplaceAll("", "a", ""), "");
-  EXPECT_EQ(ReplaceAll("", "a", "b"), "");
-  EXPECT_EQ(ReplaceAll("a", "a", "b"), "b");
-  EXPECT_EQ(ReplaceAll("aaaa", "a", "b"), "bbbb");
-  EXPECT_EQ(ReplaceAll("aaaa", "aa", "b"), "bb");
-  EXPECT_EQ(ReplaceAll("aa", "aa", "bb"), "bb");
-  EXPECT_EQ(ReplaceAll("aa", "a", "bb"), "bbbb");
-  EXPECT_EQ(ReplaceAll("abc", "a", "b"), "bbc");
-  EXPECT_EQ(ReplaceAll("abc", "c", "b"), "abb");
-  EXPECT_EQ(ReplaceAll("abc", "c", "bbb"), "abbbb");
-}
-
-TEST(StringUtilsTest, TrimLeading) {
-  EXPECT_EQ(TrimLeading(""), "");
-  EXPECT_EQ(TrimLeading("a"), "a");
-  EXPECT_EQ(TrimLeading(" aaaa"), "aaaa");
-  EXPECT_EQ(TrimLeading(" aaaaa     "), "aaaaa     ");
-}
-
-TEST(StringUtilsTest, Base64Encode) {
-  auto base64_encode = [](const std::string& str) {
-    return Base64Encode(str.c_str(), str.size());
-  };
-
-  EXPECT_EQ(base64_encode(""), "");
-  EXPECT_EQ(base64_encode("f"), "Zg==");
-  EXPECT_EQ(base64_encode("fo"), "Zm8=");
-  EXPECT_EQ(base64_encode("foo"), "Zm9v");
-  EXPECT_EQ(base64_encode("foob"), "Zm9vYg==");
-  EXPECT_EQ(base64_encode("fooba"), "Zm9vYmE=");
-  EXPECT_EQ(base64_encode("foobar"), "Zm9vYmFy");
-
-  EXPECT_EQ(Base64Encode("foo\0bar", 7), "Zm9vAGJhcg==");
-
-  std::vector<uint8_t> buffer = {0x04, 0x53, 0x42, 0x35,
-                                 0x32, 0xFF, 0x00, 0xFE};
-  EXPECT_EQ(Base64Encode(buffer.data(), buffer.size()), "BFNCNTL/AP4=");
-
-  buffer = {0xfb, 0xf0, 0x3e, 0x07, 0xfc};
-  EXPECT_EQ(Base64Encode(buffer.data(), buffer.size()), "+/A+B/w=");
-}
-
 }  // namespace
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/subprocess.cc b/src/base/subprocess.cc
index 3a18239..6be24bd 100644
--- a/src/base/subprocess.cc
+++ b/src/base/subprocess.cc
@@ -16,54 +16,408 @@
 
 #include "perfetto/ext/base/subprocess.h"
 
-#include <tuple>
+#if PERFETTO_HAS_SUBPROCESS()
 
-// This file contains only the common bits (ctors / dtors / move operators).
-// The rest lives in subprocess_posix.cc and subprocess_windows.cc.
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <thread>
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/time.h"
+#include "perfetto/ext/base/utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/prctl.h>
+#endif
+
+// In MacOS this is not defined in any header.
+extern "C" char** environ;
 
 namespace perfetto {
 namespace base {
 
+namespace {
+
+struct ChildProcessArgs {
+  Subprocess::Args* create_args;
+  const char* exec_cmd = nullptr;
+  std::vector<char*> argv;
+  std::vector<char*> env;
+  int stdin_pipe_rd = -1;
+  int stdouterr_pipe_wr = -1;
+};
+
+// Don't add any dynamic allocation in this function. This will be invoked
+// under a fork(), potentially in a state where the allocator lock is held.
+void __attribute__((noreturn)) ChildProcess(ChildProcessArgs* args) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  // In no case we want a child process to outlive its parent process. This is
+  // relevant for tests, so that a test failure/crash doesn't leave child
+  // processes around that get reparented to init.
+  prctl(PR_SET_PDEATHSIG, SIGKILL);
+#endif
+
+  auto die = [args](const char* err) __attribute__((noreturn)) {
+    base::ignore_result(write(args->stdouterr_pipe_wr, err, strlen(err)));
+    base::ignore_result(write(args->stdouterr_pipe_wr, "\n", 1));
+    // From https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
+    // "In particular, the value 128 is used to indicate failure to execute
+    // another program in a subprocess. This convention is not universally
+    // obeyed, but it is a good idea to follow it in your programs."
+    _exit(128);
+  };
+
+  auto set_fd_close_on_exec = [&die](int fd, bool close_on_exec) {
+    int flags = fcntl(fd, F_GETFD, 0);
+    if (flags < 0)
+      die("fcntl(F_GETFD) failed");
+    flags = close_on_exec ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
+    if (fcntl(fd, F_SETFD, flags) < 0)
+      die("fcntl(F_SETFD) failed");
+  };
+
+  if (getppid() == 1)
+    die("terminating because parent process died");
+
+  if (dup2(args->stdin_pipe_rd, STDIN_FILENO) == -1)
+    die("Failed to dup2(STDIN)");
+  close(args->stdin_pipe_rd);
+
+  switch (args->create_args->stdout_mode) {
+    case Subprocess::kInherit:
+      break;
+    case Subprocess::kDevNull: {
+      if (dup2(open("/dev/null", O_RDWR), STDOUT_FILENO) == -1)
+        die("Failed to dup2(STDOUT)");
+      break;
+    }
+    case Subprocess::kBuffer:
+      if (dup2(args->stdouterr_pipe_wr, STDOUT_FILENO) == -1)
+        die("Failed to dup2(STDOUT)");
+      break;
+  }
+
+  switch (args->create_args->stderr_mode) {
+    case Subprocess::kInherit:
+      break;
+    case Subprocess::kDevNull: {
+      if (dup2(open("/dev/null", O_RDWR), STDERR_FILENO) == -1)
+        die("Failed to dup2(STDERR)");
+      break;
+    }
+    case Subprocess::kBuffer:
+      if (dup2(args->stdouterr_pipe_wr, STDERR_FILENO) == -1)
+        die("Failed to dup2(STDERR)");
+      break;
+  }
+
+  // Close all FDs % stdin/out/err and the ones that the client explicitly
+  // asked to retain. The reason for this is twofold:
+  // 1. For exec-only (i.e. entrypoint == empty) cases: it avoids leaking FDs
+  //    that didn't get marked as O_CLOEXEC by accident.
+  // 2. In fork() mode (entrypoint not empty) avoids retaining a dup of eventfds
+  //    that would prevent the parent process to receive EOFs (tests usually use
+  //    pipes as a synchronization mechanism between subprocesses).
+  const auto& preserve_fds = args->create_args->preserve_fds;
+  for (int i = 0; i < 512; i++) {
+    if (i != STDIN_FILENO && i != STDERR_FILENO && i != STDOUT_FILENO &&
+        i != args->stdouterr_pipe_wr &&
+        !std::count(preserve_fds.begin(), preserve_fds.end(), i)) {
+      close(i);
+    }
+  }
+
+  // Clears O_CLOEXEC from stdin/out/err. These are the only FDs that we want
+  // to be preserved after the exec().
+  set_fd_close_on_exec(STDIN_FILENO, false);
+  set_fd_close_on_exec(STDOUT_FILENO, false);
+  set_fd_close_on_exec(STDERR_FILENO, false);
+
+  // If the caller specified a std::function entrypoint, run that first.
+  if (args->create_args->entrypoint_for_testing)
+    args->create_args->entrypoint_for_testing();
+
+  // If the caller specified only an entrypoint, without any args, exit now.
+  // Otherwise proceed with the exec() below.
+  if (!args->exec_cmd)
+    _exit(0);
+
+  // If |args[0]| is a path use execv() (which takes a path), othewise use
+  // exevp(), which uses the shell and follows PATH.
+  if (strchr(args->exec_cmd, '/')) {
+    char** env = args->env.empty() ? environ : args->env.data();
+    execve(args->exec_cmd, args->argv.data(), env);
+  } else {
+    // There is no execvpe() on Mac.
+    if (!args->env.empty())
+      die("A full path is required for |exec_cmd| when setting |env|");
+    execvp(args->exec_cmd, args->argv.data());
+  }
+
+  // Reached only if execv fails.
+  die("execve() failed");
+}
+
+}  // namespace
+
 Subprocess::Args::Args(Args&&) noexcept = default;
 Subprocess::Args& Subprocess::Args::operator=(Args&&) = default;
 
-Subprocess::Subprocess(std::initializer_list<std::string> a)
-    : args(a), s_(new MovableState()) {}
+Subprocess::Subprocess(std::initializer_list<std::string> _args)
+    : args(_args) {}
 
-Subprocess::Subprocess(Subprocess&& other) noexcept {
-  static_assert(sizeof(Subprocess) ==
-                    sizeof(std::tuple<std::unique_ptr<MovableState>, Args>),
-                "base::Subprocess' move ctor needs updating");
-  s_ = std::move(other.s_);
-  args = std::move(other.args);
-
-  // Reset the state of the moved-from object.
-  other.s_.reset(new MovableState());
-  other.~Subprocess();
-  new (&other) Subprocess();
-}
-
-Subprocess& Subprocess::operator=(Subprocess&& other) {
-  this->~Subprocess();
-  new (this) Subprocess(std::move(other));
-  return *this;
-}
+Subprocess::Subprocess(Subprocess&&) noexcept = default;
+Subprocess& Subprocess::operator=(Subprocess&&) = default;
 
 Subprocess::~Subprocess() {
-  if (s_->status == kRunning)
+  if (status_ == kRunning)
     KillAndWaitForTermination();
+  PERFETTO_CHECK(!waitpid_thread_.joinable());
+}
+
+void Subprocess::Start() {
+  ChildProcessArgs proc_args;
+  proc_args.create_args = &args;
+
+  // Setup argv.
+  if (!args.exec_cmd.empty()) {
+    proc_args.exec_cmd = args.exec_cmd[0].c_str();
+    for (const std::string& arg : args.exec_cmd)
+      proc_args.argv.push_back(const_cast<char*>(arg.c_str()));
+    proc_args.argv.push_back(nullptr);
+
+    if (!args.argv0_override.empty())
+      proc_args.argv[0] = const_cast<char*>(args.argv0_override.c_str());
+  }
+
+  // Setup env.
+  if (!args.env.empty()) {
+    for (const std::string& str : args.env)
+      proc_args.env.push_back(const_cast<char*>(str.c_str()));
+    proc_args.env.push_back(nullptr);
+  }
+
+  // Setup the pipes for stdin/err redirection.
+  stdin_pipe_ = base::Pipe::Create(base::Pipe::kWrNonBlock);
+  proc_args.stdin_pipe_rd = *stdin_pipe_.rd;
+  stdouterr_pipe_ = base::Pipe::Create(base::Pipe::kRdNonBlock);
+  proc_args.stdouterr_pipe_wr = *stdouterr_pipe_.wr;
+
+  // Spawn the child process that will exec().
+  pid_ = fork();
+  PERFETTO_CHECK(pid_ >= 0);
+  if (pid_ == 0) {
+    // Close the parent-ends of the pipes.
+    stdin_pipe_.wr.reset();
+    stdouterr_pipe_.rd.reset();
+    ChildProcess(&proc_args);
+    // ChildProcess() doesn't return, not even in case of failures.
+    PERFETTO_FATAL("not reached");
+  }
+
+  status_ = kRunning;
+
+  // Close the child-end of the pipes.
+  // Deliberately NOT closing the stdin_pipe_.rd. This is to avoid crashing
+  // with a SIGPIPE if the process exits without consuming its stdin, while
+  // the parent tries to write() on the other end of the stdin pipe.
+  stdouterr_pipe_.wr.reset();
+
+  // Spawn a thread that is blocked on waitpid() and writes the termination
+  // status onto a pipe. The problem here is that waipid() doesn't have a
+  // timeout option and can't be passed to poll(). The alternative would be
+  // using a SIGCHLD handler, but anecdotally signal handlers introduce more
+  // problems than what they solve.
+  exit_status_pipe_ = base::Pipe::Create(base::Pipe::kRdNonBlock);
+
+  // Both ends of the pipe are closed after the thread.join().
+  int pid = pid_;
+  int exit_status_pipe_wr = exit_status_pipe_.wr.release();
+  waitpid_thread_ = std::thread([pid, exit_status_pipe_wr] {
+    int pid_stat = -1;
+    int wait_res = PERFETTO_EINTR(waitpid(pid, &pid_stat, 0));
+    PERFETTO_CHECK(wait_res == pid);
+    base::ignore_result(PERFETTO_EINTR(
+        write(exit_status_pipe_wr, &pid_stat, sizeof(pid_stat))));
+    PERFETTO_CHECK(close(exit_status_pipe_wr) == 0 || errno == EINTR);
+  });
+}
+
+Subprocess::Status Subprocess::Poll() {
+  if (status_ != kRunning)
+    return status_;  // Nothing to poll.
+  while (PollInternal(0 /* don't block*/)) {
+  }
+  return status_;
+}
+
+// |timeout_ms| semantic:
+//   -1: Block indefinitely.
+//    0: Don't block, return immediately.
+//   >0: Block for at most X ms.
+// Returns:
+//  True: Read at least one fd (so there might be more queued).
+//  False: if all fds reached quiescent (no data to read/write).
+bool Subprocess::PollInternal(int poll_timeout_ms) {
+  struct pollfd fds[3]{};
+  size_t num_fds = 0;
+  if (exit_status_pipe_.rd) {
+    fds[num_fds].fd = *exit_status_pipe_.rd;
+    fds[num_fds].events = POLLIN;
+    num_fds++;
+  }
+  if (stdouterr_pipe_.rd) {
+    fds[num_fds].fd = *stdouterr_pipe_.rd;
+    fds[num_fds].events = POLLIN;
+    num_fds++;
+  }
+  if (stdin_pipe_.wr) {
+    fds[num_fds].fd = *stdin_pipe_.wr;
+    fds[num_fds].events = POLLOUT;
+    num_fds++;
+  }
+
+  if (num_fds == 0)
+    return false;
+
+  auto nfds = static_cast<nfds_t>(num_fds);
+  int poll_res = PERFETTO_EINTR(poll(fds, nfds, poll_timeout_ms));
+  PERFETTO_CHECK(poll_res >= 0);
+
+  TryReadStdoutAndErr();
+  TryPushStdin();
+  TryReadExitStatus();
+
+  return poll_res > 0;
+}
+
+bool Subprocess::Wait(int timeout_ms) {
+  PERFETTO_CHECK(status_ != kNotStarted);
+
+  // Break out of the loop only after both conditions are satisfied:
+  // - All stdout/stderr data has been read (if kBuffer).
+  // - The process exited.
+  // Note that the two events can happen arbitrary order. After the process
+  // exits, there might be still data in the pipe buffer, which we want to
+  // read fully.
+  //
+  // Instead, don't wait on the stdin to be fully written. The child process
+  // might exit prematurely (or crash). If that happens, we can end up in a
+  // state where the write(stdin_pipe_.wr) will never unblock.
+
+  const int64_t t_start = base::GetWallTimeMs().count();
+  while (exit_status_pipe_.rd || stdouterr_pipe_.rd) {
+    int poll_timeout_ms = -1;  // Block until a FD is ready.
+    if (timeout_ms > 0) {
+      const int64_t now = GetWallTimeMs().count();
+      poll_timeout_ms = timeout_ms - static_cast<int>(now - t_start);
+      if (poll_timeout_ms <= 0)
+        return false;
+    }
+    PollInternal(poll_timeout_ms);
+  }  // while(...)
+  return true;
 }
 
 bool Subprocess::Call(int timeout_ms) {
-  PERFETTO_CHECK(s_->status == kNotStarted);
+  PERFETTO_CHECK(status_ == kNotStarted);
   Start();
 
   if (!Wait(timeout_ms)) {
-    s_->timed_out = true;
-    KillAndWaitForTermination(kTimeoutSignal);
+    KillAndWaitForTermination();
+    // TryReadExitStatus must have joined the thread.
+    PERFETTO_DCHECK(!waitpid_thread_.joinable());
   }
-  PERFETTO_DCHECK(s_->status != kRunning);
-  return s_->status == kTerminated && s_->returncode == 0;
+  PERFETTO_DCHECK(status_ != kRunning);
+  return status_ == kExited && returncode_ == 0;
+}
+
+void Subprocess::TryReadExitStatus() {
+  if (!exit_status_pipe_.rd)
+    return;
+
+  int pid_stat = -1;
+  int64_t rsize =
+      PERFETTO_EINTR(read(*exit_status_pipe_.rd, &pid_stat, sizeof(pid_stat)));
+  if (rsize < 0 && errno == EAGAIN)
+    return;
+
+  if (rsize > 0) {
+    PERFETTO_CHECK(rsize == sizeof(pid_stat));
+  } else if (rsize < 0) {
+    PERFETTO_PLOG("Subprocess read(exit_status_pipe_) failed");
+  }
+  waitpid_thread_.join();
+  exit_status_pipe_.rd.reset();
+
+  if (WIFEXITED(pid_stat)) {
+    returncode_ = WEXITSTATUS(pid_stat);
+    status_ = kExited;
+  } else if (WIFSIGNALED(pid_stat)) {
+    returncode_ = 128 + WTERMSIG(pid_stat);  // Follow bash convention.
+    status_ = kKilledBySignal;
+  } else {
+    PERFETTO_FATAL("waitpid() returned an unexpected value (0x%x)", pid_stat);
+  }
+}
+
+// If the stidn pipe is still open, push input data and close it at the end.
+void Subprocess::TryPushStdin() {
+  if (!stdin_pipe_.wr)
+    return;
+
+  PERFETTO_DCHECK(args.input.empty() || input_written_ < args.input.size());
+  if (args.input.size()) {
+    int64_t wsize =
+        PERFETTO_EINTR(write(*stdin_pipe_.wr, &args.input[input_written_],
+                             args.input.size() - input_written_));
+    if (wsize < 0 && errno == EAGAIN)
+      return;
+
+    if (wsize >= 0) {
+      // Whether write() can return 0 is one of the greatest mysteries of UNIX.
+      // Just ignore it.
+      input_written_ += static_cast<size_t>(wsize);
+    } else {
+      PERFETTO_PLOG("Subprocess write(stdin) failed");
+      stdin_pipe_.wr.reset();
+    }
+  }
+  PERFETTO_DCHECK(input_written_ <= args.input.size());
+  if (input_written_ == args.input.size())
+    stdin_pipe_.wr.reset();  // Close stdin.
+}
+
+void Subprocess::TryReadStdoutAndErr() {
+  if (!stdouterr_pipe_.rd)
+    return;
+  char buf[4096];
+  int64_t rsize = PERFETTO_EINTR(read(*stdouterr_pipe_.rd, buf, sizeof(buf)));
+  if (rsize < 0 && errno == EAGAIN)
+    return;
+
+  if (rsize > 0) {
+    output_.append(buf, static_cast<size_t>(rsize));
+  } else if (rsize == 0 /* EOF */) {
+    stdouterr_pipe_.rd.reset();
+  } else {
+    PERFETTO_PLOG("Subprocess read(stdout/err) failed");
+    stdouterr_pipe_.rd.reset();
+  }
+}
+
+void Subprocess::KillAndWaitForTermination() {
+  kill(pid_, SIGKILL);
+  Wait();
 }
 
 std::string Subprocess::Args::GetCmdString() const {
@@ -78,3 +432,5 @@
 
 }  // namespace base
 }  // namespace perfetto
+
+#endif  // PERFETTO_HAS_SUBPROCESS()
diff --git a/src/base/subprocess_posix.cc b/src/base/subprocess_posix.cc
deleted file mode 100644
index 85df339..0000000
--- a/src/base/subprocess_posix.cc
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/base/subprocess.h"
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <thread>
-#include <tuple>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/prctl.h>
-#endif
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/utils.h"
-
-// In MacOS this is not defined in any header.
-extern "C" char** environ;
-
-namespace perfetto {
-namespace base {
-
-namespace {
-
-struct ChildProcessArgs {
-  Subprocess::Args* create_args;
-  const char* exec_cmd = nullptr;
-  std::vector<char*> argv;
-  std::vector<char*> env;
-  int stdin_pipe_rd = -1;
-  int stdouterr_pipe_wr = -1;
-};
-
-// Don't add any dynamic allocation in this function. This will be invoked
-// under a fork(), potentially in a state where the allocator lock is held.
-void __attribute__((noreturn)) ChildProcess(ChildProcessArgs* args) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  // In no case we want a child process to outlive its parent process. This is
-  // relevant for tests, so that a test failure/crash doesn't leave child
-  // processes around that get reparented to init.
-  prctl(PR_SET_PDEATHSIG, SIGKILL);
-#endif
-
-  auto die = [args](const char* err) __attribute__((noreturn)) {
-    base::ignore_result(write(args->stdouterr_pipe_wr, err, strlen(err)));
-    base::ignore_result(write(args->stdouterr_pipe_wr, "\n", 1));
-    // From https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
-    // "In particular, the value 128 is used to indicate failure to execute
-    // another program in a subprocess. This convention is not universally
-    // obeyed, but it is a good idea to follow it in your programs."
-    _exit(128);
-  };
-
-  auto set_fd_close_on_exec = [&die](int fd, bool close_on_exec) {
-    int flags = fcntl(fd, F_GETFD, 0);
-    if (flags < 0)
-      die("fcntl(F_GETFD) failed");
-    flags = close_on_exec ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
-    if (fcntl(fd, F_SETFD, flags) < 0)
-      die("fcntl(F_SETFD) failed");
-  };
-
-  if (getppid() == 1)
-    die("terminating because parent process died");
-
-  if (dup2(args->stdin_pipe_rd, STDIN_FILENO) == -1)
-    die("Failed to dup2(STDIN)");
-  close(args->stdin_pipe_rd);
-
-  switch (args->create_args->stdout_mode) {
-    case Subprocess::kInherit:
-      break;
-    case Subprocess::kDevNull: {
-      if (dup2(open("/dev/null", O_RDWR), STDOUT_FILENO) == -1)
-        die("Failed to dup2(STDOUT)");
-      break;
-    }
-    case Subprocess::kBuffer:
-      if (dup2(args->stdouterr_pipe_wr, STDOUT_FILENO) == -1)
-        die("Failed to dup2(STDOUT)");
-      break;
-    case Subprocess::kFd:
-      if (dup2(*args->create_args->out_fd, STDOUT_FILENO) == -1)
-        die("Failed to dup2(STDOUT)");
-      break;
-  }
-
-  switch (args->create_args->stderr_mode) {
-    case Subprocess::kInherit:
-      break;
-    case Subprocess::kDevNull: {
-      if (dup2(open("/dev/null", O_RDWR), STDERR_FILENO) == -1)
-        die("Failed to dup2(STDERR)");
-      break;
-    }
-    case Subprocess::kBuffer:
-      if (dup2(args->stdouterr_pipe_wr, STDERR_FILENO) == -1)
-        die("Failed to dup2(STDERR)");
-      break;
-    case Subprocess::kFd:
-      if (dup2(*args->create_args->out_fd, STDERR_FILENO) == -1)
-        die("Failed to dup2(STDERR)");
-      break;
-  }
-
-  // Close all FDs % stdin/out/err and the ones that the client explicitly
-  // asked to retain. The reason for this is twofold:
-  // 1. For exec-only (i.e. entrypoint == empty) cases: it avoids leaking FDs
-  //    that didn't get marked as O_CLOEXEC by accident.
-  // 2. In fork() mode (entrypoint not empty) avoids retaining a dup of eventfds
-  //    that would prevent the parent process to receive EOFs (tests usually use
-  //    pipes as a synchronization mechanism between subprocesses).
-  const auto& preserve_fds = args->create_args->preserve_fds;
-  for (int i = 0; i < 512; i++) {
-    if (i != STDIN_FILENO && i != STDERR_FILENO && i != STDOUT_FILENO &&
-        i != args->stdouterr_pipe_wr &&
-        !std::count(preserve_fds.begin(), preserve_fds.end(), i)) {
-      close(i);
-    }
-  }
-
-  // Clears O_CLOEXEC from stdin/out/err. These are the only FDs that we want
-  // to be preserved after the exec().
-  set_fd_close_on_exec(STDIN_FILENO, false);
-  set_fd_close_on_exec(STDOUT_FILENO, false);
-  set_fd_close_on_exec(STDERR_FILENO, false);
-
-  // If the caller specified a std::function entrypoint, run that first.
-  if (args->create_args->posix_entrypoint_for_testing)
-    args->create_args->posix_entrypoint_for_testing();
-
-  // If the caller specified only an entrypoint, without any args, exit now.
-  // Otherwise proceed with the exec() below.
-  if (!args->exec_cmd)
-    _exit(0);
-
-  // If |args[0]| is a path use execv() (which takes a path), othewise use
-  // exevp(), which uses the shell and follows PATH.
-  if (strchr(args->exec_cmd, '/')) {
-    char** env = args->env.empty() ? environ : args->env.data();
-    execve(args->exec_cmd, args->argv.data(), env);
-  } else {
-    // There is no execvpe() on Mac.
-    if (!args->env.empty())
-      die("A full path is required for |exec_cmd| when setting |env|");
-    execvp(args->exec_cmd, args->argv.data());
-  }
-
-  // Reached only if execv fails.
-  die("execve() failed");
-}
-
-}  // namespace
-
-// static
-const int Subprocess::kTimeoutSignal = SIGKILL;
-
-void Subprocess::Start() {
-  ChildProcessArgs proc_args;
-  proc_args.create_args = &args;
-
-  // Setup argv.
-  if (!args.exec_cmd.empty()) {
-    proc_args.exec_cmd = args.exec_cmd[0].c_str();
-    for (const std::string& arg : args.exec_cmd)
-      proc_args.argv.push_back(const_cast<char*>(arg.c_str()));
-    proc_args.argv.push_back(nullptr);
-
-    if (!args.posix_argv0_override_for_testing.empty()) {
-      proc_args.argv[0] =
-          const_cast<char*>(args.posix_argv0_override_for_testing.c_str());
-    }
-  }
-
-  // Setup env.
-  if (!args.env.empty()) {
-    for (const std::string& str : args.env)
-      proc_args.env.push_back(const_cast<char*>(str.c_str()));
-    proc_args.env.push_back(nullptr);
-  }
-
-  // Setup the pipes for stdin/err redirection.
-  s_->stdin_pipe = base::Pipe::Create(base::Pipe::kWrNonBlock);
-  proc_args.stdin_pipe_rd = *s_->stdin_pipe.rd;
-  s_->stdouterr_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
-  proc_args.stdouterr_pipe_wr = *s_->stdouterr_pipe.wr;
-
-  // Spawn the child process that will exec().
-  s_->pid = fork();
-  PERFETTO_CHECK(s_->pid >= 0);
-  if (s_->pid == 0) {
-    // Close the parent-ends of the pipes.
-    s_->stdin_pipe.wr.reset();
-    s_->stdouterr_pipe.rd.reset();
-    ChildProcess(&proc_args);
-    // ChildProcess() doesn't return, not even in case of failures.
-    PERFETTO_FATAL("not reached");
-  }
-
-  s_->status = kRunning;
-
-  // Close the child-end of the pipes.
-  // Deliberately NOT closing the s_->stdin_pipe.rd. This is to avoid crashing
-  // with a SIGPIPE if the process exits without consuming its stdin, while
-  // the parent tries to write() on the other end of the stdin pipe.
-  s_->stdouterr_pipe.wr.reset();
-  proc_args.create_args->out_fd.reset();
-
-  // Spawn a thread that is blocked on waitpid() and writes the termination
-  // status onto a pipe. The problem here is that waipid() doesn't have a
-  // timeout option and can't be passed to poll(). The alternative would be
-  // using a SIGCHLD handler, but anecdotally signal handlers introduce more
-  // problems than what they solve.
-  s_->exit_status_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
-
-  // Both ends of the pipe are closed after the thread.join().
-  int pid = s_->pid;
-  int exit_status_pipe_wr = s_->exit_status_pipe.wr.release();
-  auto* rusage = s_->rusage.get();
-  s_->waitpid_thread = std::thread([pid, exit_status_pipe_wr, rusage] {
-    int pid_stat = -1;
-    struct rusage usg {};
-    int wait_res = PERFETTO_EINTR(wait4(pid, &pid_stat, 0, &usg));
-    PERFETTO_CHECK(wait_res == pid);
-
-    auto tv_to_ms = [](const struct timeval& tv) {
-      return static_cast<uint32_t>(tv.tv_sec * 1000 + tv.tv_usec / 1000);
-    };
-    rusage->cpu_utime_ms = tv_to_ms(usg.ru_utime);
-    rusage->cpu_stime_ms = tv_to_ms(usg.ru_stime);
-    rusage->max_rss_kb = static_cast<uint32_t>(usg.ru_maxrss) / 1000;
-    rusage->min_page_faults = static_cast<uint32_t>(usg.ru_minflt);
-    rusage->maj_page_faults = static_cast<uint32_t>(usg.ru_majflt);
-    rusage->vol_ctx_switch = static_cast<uint32_t>(usg.ru_nvcsw);
-    rusage->invol_ctx_switch = static_cast<uint32_t>(usg.ru_nivcsw);
-
-    base::ignore_result(PERFETTO_EINTR(
-        write(exit_status_pipe_wr, &pid_stat, sizeof(pid_stat))));
-    PERFETTO_CHECK(close(exit_status_pipe_wr) == 0 || errno == EINTR);
-  });
-}
-
-Subprocess::Status Subprocess::Poll() {
-  if (s_->status != kRunning)
-    return s_->status;  // Nothing to poll.
-  while (PollInternal(0 /* don't block*/)) {
-  }
-  return s_->status;
-}
-
-// |timeout_ms| semantic:
-//   -1: Block indefinitely.
-//    0: Don't block, return immediately.
-//   >0: Block for at most X ms.
-// Returns:
-//  True: Read at least one fd (so there might be more queued).
-//  False: if all fds reached quiescent (no data to read/write).
-bool Subprocess::PollInternal(int poll_timeout_ms) {
-  struct pollfd fds[3]{};
-  size_t num_fds = 0;
-  if (s_->exit_status_pipe.rd) {
-    fds[num_fds].fd = *s_->exit_status_pipe.rd;
-    fds[num_fds].events = POLLIN;
-    num_fds++;
-  }
-  if (s_->stdouterr_pipe.rd) {
-    fds[num_fds].fd = *s_->stdouterr_pipe.rd;
-    fds[num_fds].events = POLLIN;
-    num_fds++;
-  }
-  if (s_->stdin_pipe.wr) {
-    fds[num_fds].fd = *s_->stdin_pipe.wr;
-    fds[num_fds].events = POLLOUT;
-    num_fds++;
-  }
-
-  if (num_fds == 0)
-    return false;
-
-  auto nfds = static_cast<nfds_t>(num_fds);
-  int poll_res = PERFETTO_EINTR(poll(fds, nfds, poll_timeout_ms));
-  PERFETTO_CHECK(poll_res >= 0);
-
-  TryReadStdoutAndErr();
-  TryPushStdin();
-  TryReadExitStatus();
-
-  return poll_res > 0;
-}
-
-bool Subprocess::Wait(int timeout_ms) {
-  PERFETTO_CHECK(s_->status != kNotStarted);
-
-  // Break out of the loop only after both conditions are satisfied:
-  // - All stdout/stderr data has been read (if kBuffer).
-  // - The process exited.
-  // Note that the two events can happen arbitrary order. After the process
-  // exits, there might be still data in the pipe buffer, which we want to
-  // read fully.
-  //
-  // Instead, don't wait on the stdin to be fully written. The child process
-  // might exit prematurely (or crash). If that happens, we can end up in a
-  // state where the write(stdin_pipe_.wr) will never unblock.
-
-  const int64_t t_start = base::GetWallTimeMs().count();
-  while (s_->exit_status_pipe.rd || s_->stdouterr_pipe.rd) {
-    int poll_timeout_ms = -1;  // Block until a FD is ready.
-    if (timeout_ms > 0) {
-      const int64_t now = GetWallTimeMs().count();
-      poll_timeout_ms = timeout_ms - static_cast<int>(now - t_start);
-      if (poll_timeout_ms <= 0)
-        return false;
-    }
-    PollInternal(poll_timeout_ms);
-  }  // while(...)
-  return true;
-}
-
-void Subprocess::TryReadExitStatus() {
-  if (!s_->exit_status_pipe.rd)
-    return;
-
-  int pid_stat = -1;
-  int64_t rsize = PERFETTO_EINTR(
-      read(*s_->exit_status_pipe.rd, &pid_stat, sizeof(pid_stat)));
-  if (rsize < 0 && errno == EAGAIN)
-    return;
-
-  if (rsize > 0) {
-    PERFETTO_CHECK(rsize == sizeof(pid_stat));
-  } else if (rsize < 0) {
-    PERFETTO_PLOG("Subprocess read(s_->exit_status_pipe) failed");
-  }
-  s_->waitpid_thread.join();
-  s_->exit_status_pipe.rd.reset();
-
-  s_->status = kTerminated;
-  if (WIFEXITED(pid_stat)) {
-    s_->returncode = WEXITSTATUS(pid_stat);
-  } else if (WIFSIGNALED(pid_stat)) {
-    s_->returncode = 128 + WTERMSIG(pid_stat);  // Follow bash convention.
-  } else {
-    PERFETTO_FATAL("waitpid() returned an unexpected value (0x%x)", pid_stat);
-  }
-}
-
-// If the stidn pipe is still open, push input data and close it at the end.
-void Subprocess::TryPushStdin() {
-  if (!s_->stdin_pipe.wr)
-    return;
-
-  PERFETTO_DCHECK(args.input.empty() || s_->input_written < args.input.size());
-  if (!args.input.empty()) {
-    int64_t wsize =
-        PERFETTO_EINTR(write(*s_->stdin_pipe.wr, &args.input[s_->input_written],
-                             args.input.size() - s_->input_written));
-    if (wsize < 0 && errno == EAGAIN)
-      return;
-
-    if (wsize >= 0) {
-      // Whether write() can return 0 is one of the greatest mysteries of UNIX.
-      // Just ignore it.
-      s_->input_written += static_cast<size_t>(wsize);
-    } else {
-      PERFETTO_PLOG("Subprocess write(stdin) failed");
-      s_->stdin_pipe.wr.reset();
-    }
-  }
-  PERFETTO_DCHECK(s_->input_written <= args.input.size());
-  if (s_->input_written == args.input.size())
-    s_->stdin_pipe.wr.reset();  // Close stdin.
-}
-
-void Subprocess::TryReadStdoutAndErr() {
-  if (!s_->stdouterr_pipe.rd)
-    return;
-  char buf[4096];
-  int64_t rsize =
-      PERFETTO_EINTR(read(*s_->stdouterr_pipe.rd, buf, sizeof(buf)));
-  if (rsize < 0 && errno == EAGAIN)
-    return;
-
-  if (rsize > 0) {
-    s_->output.append(buf, static_cast<size_t>(rsize));
-  } else if (rsize == 0 /* EOF */) {
-    s_->stdouterr_pipe.rd.reset();
-  } else {
-    PERFETTO_PLOG("Subprocess read(stdout/err) failed");
-    s_->stdouterr_pipe.rd.reset();
-  }
-}
-
-void Subprocess::KillAndWaitForTermination(int sig_num) {
-  kill(s_->pid, sig_num ? sig_num : SIGKILL);
-  Wait();
-  // TryReadExitStatus must have joined the thread.
-  PERFETTO_DCHECK(!s_->waitpid_thread.joinable());
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // PERFETTO_OS_LINUX || PERFETTO_OS_ANDROID || PERFETTO_OS_APPLE
diff --git a/src/base/subprocess_unittest.cc b/src/base/subprocess_unittest.cc
index b52c804..f31b360 100644
--- a/src/base/subprocess_unittest.cc
+++ b/src/base/subprocess_unittest.cc
@@ -16,19 +16,14 @@
 
 #include "perfetto/ext/base/subprocess.h"
 
+#if PERFETTO_HAS_SUBPROCESS()
 #include <thread>
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#else
 #include <signal.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#endif
 
-#include "perfetto/base/time.h"
 #include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "test/gtest_and_gmock.h"
 
@@ -36,16 +31,6 @@
 namespace base {
 namespace {
 
-std::string GetOutput(const Subprocess& p) {
-  std::string output = p.output();
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  size_t pos = 0;
-  while ((pos = output.find("\r\n", pos)) != std::string::npos)
-    output.erase(pos, 1);
-#endif
-  return output;
-}
-
 std::string GenLargeString() {
   std::string contents;
   for (int i = 0; i < 4096; i++) {
@@ -59,101 +44,68 @@
 TEST(SubprocessTest, InvalidPath) {
   Subprocess p({"/usr/bin/invalid_1337"});
   EXPECT_FALSE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  EXPECT_EQ(p.returncode(), ERROR_FILE_NOT_FOUND);
-#else
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 128);
-  EXPECT_EQ(GetOutput(p), "execve() failed\n");
-#endif
+  EXPECT_EQ(p.output(), "execve() failed\n");
 }
 
 TEST(SubprocessTest, StdoutOnly) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "(echo skip_err 1>&2) && echo out_only"});
-#else
   Subprocess p({"sh", "-c", "(echo skip_err >&2); echo out_only"});
-#endif
   p.args.stdout_mode = Subprocess::kBuffer;
   p.args.stderr_mode = Subprocess::kDevNull;
-
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_EQ(GetOutput(p), "out_only\n");
+  EXPECT_EQ(p.status(), Subprocess::kExited);
+  EXPECT_EQ(p.output(), "out_only\n");
 }
 
 TEST(SubprocessTest, StderrOnly) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "(echo err_only>&2) && echo skip_out"});
-#else
   Subprocess p({"sh", "-c", "(echo err_only >&2); echo skip_out"});
-#endif
   p.args.stdout_mode = Subprocess::kDevNull;
   p.args.stderr_mode = Subprocess::kBuffer;
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(GetOutput(p), "err_only\n");
+  EXPECT_EQ(p.output(), "err_only\n");
 }
 
 TEST(SubprocessTest, BothStdoutAndStderr) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "echo out&&(echo err>&2)&&echo out2"});
-#else
   Subprocess p({"sh", "-c", "echo out; (echo err >&2); echo out2"});
-#endif
   p.args.stdout_mode = Subprocess::kBuffer;
   p.args.stderr_mode = Subprocess::kBuffer;
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(GetOutput(p), "out\nerr\nout2\n");
+  EXPECT_EQ(p.output(), "out\nerr\nout2\n");
 }
 
 TEST(SubprocessTest, BinTrue) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "(exit 0)"});
-#else
   Subprocess p({"true"});
-#endif
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 0);
 }
 
 TEST(SubprocessTest, BinFalse) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "(exit 1)"});
-#else
   Subprocess p({"false"});
-#endif
   EXPECT_FALSE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 1);
 }
 
 TEST(SubprocessTest, Echo) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "echo|set /p ignored_var=foobar"});
-#else
   Subprocess p({"echo", "-n", "foobar"});
-#endif
   p.args.stdout_mode = Subprocess::kBuffer;
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 0);
-  EXPECT_EQ(GetOutput(p), "foobar");
+  EXPECT_EQ(p.output(), "foobar");
 }
 
 TEST(SubprocessTest, FeedbackLongInput) {
   std::string contents = GenLargeString();
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/C", "findstr ."});
-#else
   Subprocess p({"cat", "-"});
-#endif
   p.args.stdout_mode = Subprocess::kBuffer;
   p.args.input = contents;
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 0);
-  EXPECT_EQ(GetOutput(p), contents);
+  EXPECT_EQ(p.output(), contents);
 }
 
 TEST(SubprocessTest, CatLargeFile) {
@@ -161,253 +113,87 @@
   TempFile tf = TempFile::Create();
   WriteAll(tf.fd(), contents.data(), contents.size());
   FlushFile(tf.fd());
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", ("type \"" + tf.path() + "\"").c_str()});
-#else
   Subprocess p({"cat", tf.path().c_str()});
-#endif
   p.args.stdout_mode = Subprocess::kBuffer;
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(GetOutput(p), contents);
+  EXPECT_EQ(p.output(), contents);
 }
 
 TEST(SubprocessTest, Timeout) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"ping", "127.0.0.1", "-n", "60"});
-  p.args.stdout_mode = Subprocess::kDevNull;
-#else
   Subprocess p({"sleep", "60"});
-#endif
-
   EXPECT_FALSE(p.Call(/*timeout_ms=*/1));
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_TRUE(p.timed_out());
+  EXPECT_EQ(p.status(), Subprocess::kKilledBySignal);
 }
 
 TEST(SubprocessTest, TimeoutNotHit) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"ping", "127.0.0.1", "-n", "1"});
-  p.args.stdout_mode = Subprocess::kDevNull;
-#else
   Subprocess p({"sleep", "0.01"});
-#endif
   EXPECT_TRUE(p.Call(/*timeout_ms=*/100000));
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
 }
 
 TEST(SubprocessTest, TimeoutStopOutput) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "FOR /L %N IN () DO @echo stuff>NUL"});
-#else
   Subprocess p({"sh", "-c", "while true; do echo stuff; done"});
-#endif
   p.args.stdout_mode = Subprocess::kDevNull;
   EXPECT_FALSE(p.Call(/*timeout_ms=*/10));
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_TRUE(p.timed_out());
+  EXPECT_EQ(p.status(), Subprocess::kKilledBySignal);
 }
 
 TEST(SubprocessTest, ExitBeforeReadingStdin) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"ping", "127.0.0.1", "-n", "1"});
-#else
   // 'sh -c' is to avoid closing stdin (sleep closes it before sleeping).
   Subprocess p({"sh", "-c", "sleep 0.01"});
-#endif
   p.args.stdout_mode = Subprocess::kDevNull;
   p.args.stderr_mode = Subprocess::kDevNull;
   p.args.input = GenLargeString();
   EXPECT_TRUE(p.Call());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
+  EXPECT_EQ(p.status(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 0);
 }
 
 TEST(SubprocessTest, StdinWriteStall) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"ping", "127.0.0.1", "-n", "10"});
-#else
   // 'sh -c' is to avoid closing stdin (sleep closes it before sleeping).
   // This causes a situation where the write on the stdin will stall because
   // nobody reads it and the pipe buffer fills up. In this situation we should
   // still handle the timeout properly.
   Subprocess p({"sh", "-c", "sleep 10"});
-#endif
   p.args.stdout_mode = Subprocess::kDevNull;
   p.args.stderr_mode = Subprocess::kDevNull;
   p.args.input = GenLargeString();
   EXPECT_FALSE(p.Call(/*timeout_ms=*/10));
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_TRUE(p.timed_out());
+  EXPECT_EQ(p.status(), Subprocess::kKilledBySignal);
 }
 
 TEST(SubprocessTest, StartAndWait) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"ping", "127.0.0.1", "-n", "1000"});
-#else
   Subprocess p({"sleep", "1000"});
-#endif
-  p.args.stdout_mode = Subprocess::kDevNull;
   p.Start();
   EXPECT_EQ(p.Poll(), Subprocess::kRunning);
   p.KillAndWaitForTermination();
-
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_EQ(p.Poll(), Subprocess::kTerminated);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  EXPECT_EQ(p.returncode(), static_cast<int>(STATUS_CONTROL_C_EXIT));
-#else
-  EXPECT_EQ(p.returncode(), static_cast<int>(128 + SIGKILL));
-#endif
+  EXPECT_EQ(p.status(), Subprocess::kKilledBySignal);
+  EXPECT_EQ(p.Poll(), Subprocess::kKilledBySignal);
+  EXPECT_EQ(p.returncode(), 128 + SIGKILL);
 }
 
 TEST(SubprocessTest, PollBehavesProperly) {
-  Pipe pipe = Pipe::Create();
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "(exit 0)"});
-#else
-  Subprocess p({"true"});
-#endif
-  p.args.stdout_mode = Subprocess::kFd;
-  p.args.out_fd = std::move(pipe.wr);
+  Subprocess p({"sh", "-c", "echo foobar"});
+  p.args.stdout_mode = Subprocess::kBuffer;
+  p.args.input = "ignored";
   p.Start();
 
-  // Wait for EOF (which really means the child process has terminated).
-  std::string ignored;
-  ReadPlatformHandle(*pipe.rd, &ignored);
-
-  // The kernel takes some time to detect the termination of the process. The
-  // best thing we can do here is check that we detect the termination within
-  // some reasonable time.
-  auto start_ms = GetWallTimeMs();
-  while (p.Poll() != Subprocess::kTerminated) {
-    auto elapsed_ms = GetWallTimeMs() - start_ms;
-    ASSERT_LT(elapsed_ms, TimeMillis(10000));
-    std::this_thread::sleep_for(TimeMillis(5));
+  // Here we use kill() as a way to tell if the process is still running.
+  // SIGWINCH is ignored by default.
+  while (kill(p.pid(), SIGWINCH) == 0) {
+    usleep(1000);
   }
 
   // At this point Poll() must detect the termination.
-  EXPECT_EQ(p.Poll(), Subprocess::kTerminated);
+  EXPECT_EQ(p.Poll(), Subprocess::kExited);
   EXPECT_EQ(p.returncode(), 0);
 }
 
-TEST(SubprocessTest, Wait) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  Subprocess p({"cmd", "/c", "echo exec_done && FOR /L %N IN () DO @echo>NUL"});
-#else
-  Subprocess p({"sh", "-c", "echo exec_done; while true; do true; done"});
-#endif
-  p.args.stdout_mode = Subprocess::kBuffer;
-  p.Start();
-
-  // Wait for the fork()+exec() to complete.
-  while (p.output().find("exec_done") == std::string::npos) {
-    EXPECT_FALSE(p.Wait(1 /*ms*/));
-    EXPECT_EQ(p.status(), Subprocess::kRunning);
-  }
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  ScopedPlatformHandle proc_handle(::OpenProcess(
-      PROCESS_TERMINATE, /*inherit=*/false, static_cast<DWORD>(p.pid())));
-  ASSERT_TRUE(proc_handle);
-  ASSERT_TRUE(::TerminateProcess(*proc_handle, DBG_CONTROL_BREAK));
-#else
-  kill(p.pid(), SIGBUS);
-#endif
-  EXPECT_TRUE(p.Wait(30000 /*ms*/));  // We shouldn't hit this.
-  EXPECT_TRUE(p.Wait());              // Should be a no-op.
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  EXPECT_EQ(p.returncode(), static_cast<int>(DBG_CONTROL_BREAK));
-#else
-  EXPECT_EQ(p.returncode(), 128 + SIGBUS);
-#endif
-}
-
-TEST(SubprocessTest, KillOnDtor) {
-  auto is_process_alive = [](PlatformProcessId pid) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    DWORD ignored = 0;
-    return ProcessIdToSessionId(static_cast<DWORD>(pid), &ignored);
-#else
-    // We use kill(SIGWINCH) as a way to tell if the process is still alive by
-    // looking at the kill(2) return value. SIGWINCH is one of the few signals
-    // that has default ignore disposition.
-    return kill(pid, SIGWINCH) == 0;
-#endif
-  };
-
-  PlatformProcessId pid;
-  {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    Subprocess p({"ping", "127.0.0.1", "-n", "1000"});
-#else
-    Subprocess p({"sleep", "1000"});
-#endif
-    p.Start();
-    pid = p.pid();
-    EXPECT_TRUE(is_process_alive(pid));
-  }
-
-  // Both on Windows and Linux, kill can take some time to free up the pid.
-  bool alive = true;
-  for (int attempt = 0; attempt < 1000 && alive; attempt++) {
-    alive = is_process_alive(pid);
-    std::this_thread::sleep_for(TimeMillis(5));
-  }
-  EXPECT_FALSE(alive);
-}
-
-// Regression test for b/162505491.
-TEST(SubprocessTest, MoveOperators) {
-  {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    Subprocess initial({"ping", "127.0.0.1", "-n", "100"});
-#else
-    Subprocess initial = Subprocess({"sleep", "10000"});
-#endif
-    initial.args.stdout_mode = Subprocess::kDevNull;
-    initial.Start();
-    Subprocess moved(std::move(initial));
-    EXPECT_EQ(moved.Poll(), Subprocess::kRunning);
-    EXPECT_EQ(initial.Poll(), Subprocess::kNotStarted);
-
-    // Check that reuse works
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    initial = Subprocess({"cmd", "/c", "echo|set /p ignored_var=hello"});
-#else
-    initial = Subprocess({"echo", "-n", "hello"});
-#endif
-    initial.args.stdout_mode = Subprocess::OutputMode::kBuffer;
-    initial.Start();
-    initial.Wait(/*timeout=*/5000);
-    EXPECT_EQ(initial.status(), Subprocess::kTerminated);
-    EXPECT_EQ(initial.returncode(), 0);
-    EXPECT_EQ(initial.output(), "hello");
-  }
-
-  std::vector<Subprocess> v;
-  for (int i = 0; i < 10; i++) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    v.emplace_back(Subprocess({"ping", "127.0.0.1", "-n", "10"}));
-#else
-    v.emplace_back(Subprocess({"sleep", "10"}));
-#endif
-    v.back().args.stdout_mode = Subprocess::OutputMode::kDevNull;
-    v.back().Start();
-  }
-  for (auto& p : v)
-    EXPECT_EQ(p.Poll(), Subprocess::kRunning);
-}
-
-// posix_entrypoint_for_testing is not supported on Windows.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
 // Test the case of passing a lambda in |entrypoint| but no cmd.c
 TEST(SubprocessTest, Entrypoint) {
   Subprocess p;
   p.args.input = "ping\n";
   p.args.stdout_mode = Subprocess::kBuffer;
-  p.args.posix_entrypoint_for_testing = [] {
+  p.args.entrypoint_for_testing = [] {
     char buf[32]{};
     PERFETTO_CHECK(fgets(buf, sizeof(buf), stdin));
     PERFETTO_CHECK(strcmp(buf, "ping\n") == 0);
@@ -417,7 +203,7 @@
   };
   EXPECT_FALSE(p.Call());
   EXPECT_EQ(p.returncode(), 42);
-  EXPECT_EQ(GetOutput(p), "pong\n");
+  EXPECT_EQ(p.output(), "pong\n");
 }
 
 // Test the case of passing both a lambda entrypoint and a process to exec.
@@ -430,7 +216,7 @@
   Subprocess p({"echo", "123"});
   p.args.stdout_mode = Subprocess::kBuffer;
   p.args.preserve_fds.push_back(pipe2_wr);
-  p.args.posix_entrypoint_for_testing = [pipe1_wr, pipe2_wr] {
+  p.args.entrypoint_for_testing = [pipe1_wr, pipe2_wr] {
     base::ignore_result(write(pipe1_wr, "fail", 4));
     base::ignore_result(write(pipe2_wr, "pass", 4));
   };
@@ -445,12 +231,39 @@
   buf[4] = '\0';
   EXPECT_STREQ(buf, "pass");
   EXPECT_TRUE(p.Wait());
-  EXPECT_EQ(p.status(), Subprocess::kTerminated);
-  EXPECT_EQ(GetOutput(p), "123\n");
+  EXPECT_EQ(p.status(), Subprocess::kExited);
+  EXPECT_EQ(p.output(), "123\n");
 }
 
-#endif
+TEST(SubprocessTest, Wait) {
+  Subprocess p({"sleep", "10000"});
+  p.Start();
+  for (int i = 0; i < 3; i++) {
+    EXPECT_FALSE(p.Wait(1 /*ms*/));
+    EXPECT_EQ(p.status(), Subprocess::kRunning);
+  }
+  kill(p.pid(), SIGBUS);
+  EXPECT_TRUE(p.Wait(30000 /*ms*/));
+  EXPECT_TRUE(p.Wait());  // Should be a no-op.
+  EXPECT_EQ(p.status(), Subprocess::kKilledBySignal);
+  EXPECT_EQ(p.returncode(), 128 + SIGBUS);
+}
+
+TEST(SubprocessTest, KillOnDtor) {
+  // Here we use kill(SIGWINCH) as a way to tell if the process is still alive.
+  // SIGWINCH is one of the few signals that has default ignore disposition.
+  int pid;
+  {
+    Subprocess p({"sleep", "10000"});
+    p.Start();
+    pid = p.pid();
+    EXPECT_EQ(kill(pid, SIGWINCH), 0);
+  }
+  EXPECT_EQ(kill(pid, SIGWINCH), -1);
+}
 
 }  // namespace
 }  // namespace base
 }  // namespace perfetto
+
+#endif  // PERFETTO_HAS_SUBPROCESS()
diff --git a/src/base/subprocess_windows.cc b/src/base/subprocess_windows.cc
deleted file mode 100644
index d58d7bd..0000000
--- a/src/base/subprocess_windows.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/base/subprocess.h"
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <stdio.h>
-
-#include <algorithm>
-#include <mutex>
-#include <tuple>
-
-#include <Windows.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace base {
-
-// static
-const int Subprocess::kTimeoutSignal = static_cast<int>(STATUS_TIMEOUT);
-
-void Subprocess::Start() {
-  if (args.exec_cmd.empty()) {
-    PERFETTO_ELOG("Subprocess.exec_cmd cannot be empty on Windows");
-    return;
-  }
-
-  // Quote arguments but only when ambiguous. When quoting, CreateProcess()
-  // assumes that the command is an absolute path and does not search in the
-  // %PATH%. If non quoted, instead, CreateProcess() tries both. This is to
-  // allow Subprocess("cmd.exe", "/c", "shell command").
-  std::string cmd;
-  for (const auto& part : args.exec_cmd) {
-    if (part.find(" ") != std::string::npos) {
-      cmd += "\"" + part + "\" ";
-    } else {
-      cmd += part + " ";
-    }
-  }
-  // Remove trailing space.
-  if (!cmd.empty())
-    cmd.resize(cmd.size() - 1);
-
-  s_->stdin_pipe = Pipe::Create();
-  // Allow the child process to inherit the other end of the pipe.
-  PERFETTO_CHECK(
-      ::SetHandleInformation(*s_->stdin_pipe.rd, HANDLE_FLAG_INHERIT, 1));
-
-  if (args.stderr_mode == kBuffer || args.stdout_mode == kBuffer) {
-    s_->stdouterr_pipe = Pipe::Create();
-    PERFETTO_CHECK(
-        ::SetHandleInformation(*s_->stdouterr_pipe.wr, HANDLE_FLAG_INHERIT, 1));
-  }
-
-  ScopedPlatformHandle nul_handle;
-  if (args.stderr_mode == kDevNull || args.stdout_mode == kDevNull) {
-    nul_handle.reset(::CreateFileA("NUL", GENERIC_WRITE, FILE_SHARE_WRITE,
-                                   nullptr, OPEN_EXISTING,
-                                   FILE_ATTRIBUTE_NORMAL, nullptr));
-    PERFETTO_CHECK(::SetHandleInformation(*nul_handle, HANDLE_FLAG_INHERIT, 1));
-  }
-
-  PROCESS_INFORMATION proc_info{};
-  STARTUPINFOA start_info{};
-  start_info.cb = sizeof(STARTUPINFOA);
-
-  if (args.stderr_mode == kInherit) {
-    start_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
-  } else if (args.stderr_mode == kBuffer) {
-    start_info.hStdError = *s_->stdouterr_pipe.wr;
-  } else if (args.stderr_mode == kDevNull) {
-    start_info.hStdError = *nul_handle;
-  } else if (args.stderr_mode == kFd) {
-    PERFETTO_CHECK(
-        ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
-    start_info.hStdError = *args.out_fd;
-  } else {
-    PERFETTO_CHECK(false);
-  }
-
-  if (args.stdout_mode == kInherit) {
-    start_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
-  } else if (args.stdout_mode == kBuffer) {
-    start_info.hStdOutput = *s_->stdouterr_pipe.wr;
-  } else if (args.stdout_mode == kDevNull) {
-    start_info.hStdOutput = *nul_handle;
-  } else if (args.stdout_mode == kFd) {
-    PERFETTO_CHECK(
-        ::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
-    start_info.hStdOutput = *args.out_fd;
-  } else {
-    PERFETTO_CHECK(false);
-  }
-
-  start_info.hStdInput = *s_->stdin_pipe.rd;
-  start_info.dwFlags |= STARTF_USESTDHANDLES;
-
-  // Create the child process.
-  bool success =
-      ::CreateProcessA(nullptr,      // App name. Needs to be null to use PATH.
-                       &cmd[0],      // Command line.
-                       nullptr,      // Process security attributes.
-                       nullptr,      // Primary thread security attributes.
-                       true,         // Handles are inherited.
-                       0,            // Flags.
-                       nullptr,      // Use parent's environment.
-                       nullptr,      // Use parent's current directory.
-                       &start_info,  // STARTUPINFO pointer.
-                       &proc_info);  // Receives PROCESS_INFORMATION.
-
-  // Close on our side the pipe ends that we passed to the child process.
-  s_->stdin_pipe.rd.reset();
-  s_->stdouterr_pipe.wr.reset();
-  args.out_fd.reset();
-
-  if (!success) {
-    s_->returncode = ERROR_FILE_NOT_FOUND;
-    s_->status = kTerminated;
-    s_->stdin_pipe.wr.reset();
-    s_->stdouterr_pipe.rd.reset();
-    PERFETTO_ELOG("CreateProcess failed: %lx, cmd: %s", GetLastError(),
-                  &cmd[0]);
-    return;
-  }
-
-  s_->pid = proc_info.dwProcessId;
-  s_->win_proc_handle = ScopedPlatformHandle(proc_info.hProcess);
-  s_->win_thread_handle = ScopedPlatformHandle(proc_info.hThread);
-  s_->status = kRunning;
-
-  MovableState* s = s_.get();
-  s_->stdin_thread = std::thread(&Subprocess::StdinThread, s, args.input);
-
-  if (args.stderr_mode == kBuffer || args.stdout_mode == kBuffer) {
-    PERFETTO_DCHECK(s_->stdouterr_pipe.rd);
-    s_->stdouterr_thread = std::thread(&Subprocess::StdoutErrThread, s);
-  }
-}
-
-// static
-void Subprocess::StdinThread(MovableState* s, std::string input) {
-  size_t input_written = 0;
-  while (input_written < input.size()) {
-    DWORD wsize = 0;
-    if (::WriteFile(*s->stdin_pipe.wr, input.data() + input_written,
-                    static_cast<DWORD>(input.size() - input_written), &wsize,
-                    nullptr)) {
-      input_written += wsize;
-    } else {
-      // ERROR_BROKEN_PIPE is WAI when the child just closes stdin and stops
-      // accepting input.
-      auto err = ::GetLastError();
-      if (err != ERROR_BROKEN_PIPE)
-        PERFETTO_PLOG("Subprocess WriteFile(stdin) failed %lx", err);
-      break;
-    }
-  }  // while(...)
-  std::unique_lock<std::mutex> lock(s->mutex);
-  s->stdin_pipe.wr.reset();
-}
-
-// static
-void Subprocess::StdoutErrThread(MovableState* s) {
-  char buf[4096];
-  for (;;) {
-    DWORD rsize = 0;
-    bool res =
-        ::ReadFile(*s->stdouterr_pipe.rd, buf, sizeof(buf), &rsize, nullptr);
-    if (!res) {
-      auto err = GetLastError();
-      if (err != ERROR_BROKEN_PIPE)
-        PERFETTO_PLOG("Subprocess ReadFile(stdouterr) failed %ld", err);
-    }
-
-    if (rsize > 0) {
-      std::unique_lock<std::mutex> lock(s->mutex);
-      s->locked_outerr_buf.append(buf, static_cast<size_t>(rsize));
-    } else {  // EOF or some error.
-      break;
-    }
-  }  // For(..)
-
-  // Close the stdouterr_pipe. The main loop looks at the pipe closure to
-  // determine whether the stdout/err thread has completed.
-  {
-    std::unique_lock<std::mutex> lock(s->mutex);
-    s->stdouterr_pipe.rd.reset();
-  }
-  s->stdouterr_done_event.Notify();
-}
-
-Subprocess::Status Subprocess::Poll() {
-  if (s_->status != kRunning)
-    return s_->status;  // Nothing to poll.
-  Wait(1 /*ms*/);
-  return s_->status;
-}
-
-bool Subprocess::Wait(int timeout_ms) {
-  PERFETTO_CHECK(s_->status != kNotStarted);
-  const bool wait_forever = timeout_ms == 0;
-  const int64_t wait_start_ms = base::GetWallTimeMs().count();
-
-  // Break out of the loop only after both conditions are satisfied:
-  // - All stdout/stderr data has been read (if kBuffer).
-  // - The process exited.
-  // Note that the two events can happen arbitrary order. After the process
-  // exits, there might be still data in the pipe buffer, which we want to
-  // read fully.
-  // Note also that stdout/err might be "complete" before starting, if neither
-  // is operating in kBuffer mode. In that case we just want to wait for the
-  // process termination.
-  //
-  // Instead, don't wait on the stdin to be fully written. The child process
-  // might exit prematurely (or crash). If that happens, we can end up in a
-  // state where the write(stdin_pipe_.wr) will never unblock.
-  bool stdouterr_complete = false;
-  for (;;) {
-    HANDLE wait_handles[2]{};
-    DWORD num_handles = 0;
-
-    // Check if the process exited.
-    bool process_exited = !s_->win_proc_handle;
-    if (!process_exited) {
-      DWORD exit_code = STILL_ACTIVE;
-      PERFETTO_CHECK(::GetExitCodeProcess(*s_->win_proc_handle, &exit_code));
-      if (exit_code != STILL_ACTIVE) {
-        s_->returncode = static_cast<int>(exit_code);
-        s_->status = kTerminated;
-        s_->win_proc_handle.reset();
-        s_->win_thread_handle.reset();
-        process_exited = true;
-      }
-    } else {
-      PERFETTO_DCHECK(s_->status != kRunning);
-    }
-    if (!process_exited) {
-      wait_handles[num_handles++] = *s_->win_proc_handle;
-    }
-
-    // Check if there is more output and if the stdout/err pipe has been closed.
-    {
-      std::unique_lock<std::mutex> lock(s_->mutex);
-      // Move the output from the internal buffer shared with the
-      // stdouterr_thread to the final buffer exposed to the client.
-      if (!s_->locked_outerr_buf.empty()) {
-        s_->output.append(std::move(s_->locked_outerr_buf));
-        s_->locked_outerr_buf.clear();
-      }
-      stdouterr_complete = !s_->stdouterr_pipe.rd;
-      if (!stdouterr_complete) {
-        wait_handles[num_handles++] = s_->stdouterr_done_event.fd();
-      }
-    }  // lock(s_->mutex)
-
-    if (num_handles == 0) {
-      PERFETTO_DCHECK(process_exited && stdouterr_complete);
-      break;
-    }
-
-    DWORD wait_ms;  // Note: DWORD is unsigned.
-    if (wait_forever) {
-      wait_ms = INFINITE;
-    } else {
-      const int64_t now = GetWallTimeMs().count();
-      const int64_t wait_left_ms = timeout_ms - (now - wait_start_ms);
-      if (wait_left_ms <= 0)
-        return false;  // Timed out
-      wait_ms = static_cast<DWORD>(wait_left_ms);
-    }
-
-    auto wait_res =
-        ::WaitForMultipleObjects(num_handles, wait_handles, false, wait_ms);
-    PERFETTO_CHECK(wait_res != WAIT_FAILED);
-  }
-
-  PERFETTO_DCHECK(!s_->win_proc_handle);
-  PERFETTO_DCHECK(!s_->win_thread_handle);
-
-  if (s_->stdin_thread.joinable())  // Might not exist if CreateProcess failed.
-    s_->stdin_thread.join();
-  if (s_->stdouterr_thread.joinable())
-    s_->stdouterr_thread.join();
-
-  // The stdin pipe is closed by the dedicated stdin thread. However if that is
-  // not started (e.g. because of no redirection) force close it now. Needs to
-  // happen after the join() to be thread safe.
-  s_->stdin_pipe.wr.reset();
-  s_->stdouterr_pipe.rd.reset();
-
-  return true;
-}
-
-void Subprocess::KillAndWaitForTermination(int exit_code) {
-  auto code = exit_code ? static_cast<DWORD>(exit_code) : STATUS_CONTROL_C_EXIT;
-  ::TerminateProcess(*s_->win_proc_handle, code);
-  Wait();
-  // TryReadExitStatus must have joined the threads.
-  PERFETTO_DCHECK(!s_->stdin_thread.joinable());
-  PERFETTO_DCHECK(!s_->stdouterr_thread.joinable());
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // PERFETTO_OS_WIN
diff --git a/src/base/task_runner_unittest.cc b/src/base/task_runner_unittest.cc
index ae2297a..10f047b 100644
--- a/src/base/task_runner_unittest.cc
+++ b/src/base/task_runner_unittest.cc
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-
 #include "perfetto/ext/base/unix_task_runner.h"
 
 #include <thread>
 
-#include "perfetto/ext/base/event_fd.h"
+#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"
@@ -37,6 +35,25 @@
   UnixTaskRunner task_runner;
 };
 
+struct TestPipe : Pipe {
+  TestPipe() : Pipe(Pipe::Create()) {
+    // Make the pipe initially readable.
+    Write();
+  }
+
+  void Read() {
+    char b;
+    ssize_t rd = read(*this->rd, &b, 1);
+    PERFETTO_DCHECK(rd == 1);
+  }
+
+  void Write() {
+    const char b = '?';
+    ssize_t wr = WriteAll(*this->wr, &b, 1);
+    PERFETTO_DCHECK(wr == 1);
+  }
+};
+
 TEST_F(TaskRunnerTest, PostImmediateTask) {
   auto& task_runner = this->task_runner;
   int counter = 0;
@@ -107,22 +124,20 @@
 
 TEST_F(TaskRunnerTest, AddFileDescriptorWatch) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  task_runner.AddFileDescriptorWatch(evt.fd(),
+  TestPipe pipe;
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                      [&task_runner] { task_runner.Quit(); });
-  evt.Notify();
   task_runner.Run();
 }
 
 TEST_F(TaskRunnerTest, RemoveFileDescriptorWatch) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
+  TestPipe pipe;
 
   bool watch_ran = false;
-  task_runner.AddFileDescriptorWatch(evt.fd(),
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                      [&watch_ran] { watch_ran = true; });
-  task_runner.RemoveFileDescriptorWatch(evt.fd());
+  task_runner.RemoveFileDescriptorWatch(pipe.rd.get());
   task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
   task_runner.Run();
 
@@ -131,14 +146,13 @@
 
 TEST_F(TaskRunnerTest, RemoveFileDescriptorWatchFromTask) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
+  TestPipe pipe;
 
   bool watch_ran = false;
-  task_runner.PostTask([&task_runner, &evt] {
-    task_runner.RemoveFileDescriptorWatch(evt.fd());
+  task_runner.PostTask([&task_runner, &pipe] {
+    task_runner.RemoveFileDescriptorWatch(pipe.rd.get());
   });
-  task_runner.AddFileDescriptorWatch(evt.fd(),
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                      [&watch_ran] { watch_ran = true; });
   task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
   task_runner.Run();
@@ -148,31 +162,30 @@
 
 TEST_F(TaskRunnerTest, AddFileDescriptorWatchFromAnotherWatch) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  EventFd evt2;
-  evt.Notify();
-  evt2.Notify();
-  task_runner.AddFileDescriptorWatch(evt.fd(), [&task_runner, &evt, &evt2] {
-    evt.Clear();
-    task_runner.AddFileDescriptorWatch(evt2.fd(),
-                                       [&task_runner] { task_runner.Quit(); });
-  });
+  TestPipe pipe;
+  TestPipe pipe2;
+
+  task_runner.AddFileDescriptorWatch(
+      pipe.rd.get(), [&task_runner, &pipe, &pipe2] {
+        pipe.Read();
+        task_runner.AddFileDescriptorWatch(
+            pipe2.rd.get(), [&task_runner] { task_runner.Quit(); });
+      });
   task_runner.Run();
 }
 
 TEST_F(TaskRunnerTest, RemoveFileDescriptorWatchFromAnotherWatch) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  EventFd evt2;
-  evt.Notify();
+  TestPipe pipe;
+  TestPipe pipe2;
 
   bool watch_ran = false;
-  task_runner.AddFileDescriptorWatch(evt.fd(), [&task_runner, &evt, &evt2] {
-    evt.Clear();
-    evt2.Notify();
-    task_runner.RemoveFileDescriptorWatch(evt2.fd());
-  });
-  task_runner.AddFileDescriptorWatch(evt2.fd(),
+  task_runner.AddFileDescriptorWatch(
+      pipe.rd.get(), [&task_runner, &pipe, &pipe2] {
+        pipe.Read();
+        task_runner.RemoveFileDescriptorWatch(pipe2.rd.get());
+      });
+  task_runner.AddFileDescriptorWatch(pipe2.rd.get(),
                                      [&watch_ran] { watch_ran = true; });
   task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
   task_runner.Run();
@@ -182,19 +195,16 @@
 
 TEST_F(TaskRunnerTest, ReplaceFileDescriptorWatchFromAnotherWatch) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  EventFd evt2;
+  TestPipe pipe;
+  TestPipe pipe2;
 
   bool watch_ran = false;
-  evt.Notify();
-  task_runner.AddFileDescriptorWatch(evt.fd(), [&task_runner, &evt, &evt2] {
-    evt.Clear();
-    evt2.Notify();
-    task_runner.RemoveFileDescriptorWatch(evt2.fd());
-    task_runner.AddFileDescriptorWatch(evt2.fd(),
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(), [&task_runner, &pipe2] {
+    task_runner.RemoveFileDescriptorWatch(pipe2.rd.get());
+    task_runner.AddFileDescriptorWatch(pipe2.rd.get(),
                                        [&task_runner] { task_runner.Quit(); });
   });
-  task_runner.AddFileDescriptorWatch(evt2.fd(),
+  task_runner.AddFileDescriptorWatch(pipe2.rd.get(),
                                      [&watch_ran] { watch_ran = true; });
   task_runner.Run();
 
@@ -203,11 +213,10 @@
 
 TEST_F(TaskRunnerTest, AddFileDescriptorWatchFromAnotherThread) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
+  TestPipe pipe;
 
-  std::thread thread([&task_runner, &evt] {
-    task_runner.AddFileDescriptorWatch(evt.fd(),
+  std::thread thread([&task_runner, &pipe] {
+    task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                        [&task_runner] { task_runner.Quit(); });
   });
   task_runner.Run();
@@ -216,23 +225,30 @@
 
 TEST_F(TaskRunnerTest, FileDescriptorWatchWithMultipleEvents) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
+  TestPipe pipe;
 
   int event_count = 0;
-  task_runner.AddFileDescriptorWatch(
-      evt.fd(), [&task_runner, &evt, &event_count] {
-        ASSERT_LT(event_count, 3);
-        if (++event_count == 3) {
-          task_runner.Quit();
-          return;
-        }
-        evt.Clear();
-        task_runner.PostTask([&evt] { evt.Notify(); });
-      });
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
+                                     [&task_runner, &pipe, &event_count] {
+                                       if (++event_count == 3) {
+                                         task_runner.Quit();
+                                         return;
+                                       }
+                                       pipe.Read();
+                                     });
+  task_runner.PostTask([&pipe] { pipe.Write(); });
+  task_runner.PostTask([&pipe] { pipe.Write(); });
   task_runner.Run();
 }
 
+TEST_F(TaskRunnerTest, FileDescriptorClosedEvent) {
+  auto& task_runner = this->task_runner;
+  TestPipe pipe;
+  pipe.wr.reset();
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
+                                     [&task_runner] { task_runner.Quit(); });
+  task_runner.Run();
+}
 
 TEST_F(TaskRunnerTest, PostManyDelayedTasks) {
   // Check that PostTask doesn't start failing if there are too many scheduled
@@ -266,11 +282,9 @@
 
 TEST_F(TaskRunnerTest, FileDescriptorWatchesNotStarved) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
-
+  TestPipe pipe;
   task_runner.PostTask(std::bind(&RepeatingTask, &task_runner));
-  task_runner.AddFileDescriptorWatch(evt.fd(),
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                      [&task_runner] { task_runner.Quit(); });
   task_runner.Run();
 }
@@ -280,20 +294,17 @@
     task_runner->Quit();
     return;
   }
-  task_runner->PostDelayedTask(std::bind(&CountdownTask, task_runner, counter),
-                               1);
+  task_runner->PostTask(std::bind(&CountdownTask, task_runner, counter));
 }
 
 TEST_F(TaskRunnerTest, NoDuplicateFileDescriptorWatchCallbacks) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
-
+  TestPipe pipe;
   bool watch_called = 0;
   int counter = 10;
-  task_runner.AddFileDescriptorWatch(evt.fd(), [&evt, &watch_called] {
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(), [&pipe, &watch_called] {
     ASSERT_FALSE(watch_called);
-    evt.Clear();
+    pipe.Read();
     watch_called = true;
   });
   task_runner.PostTask(std::bind(&CountdownTask, &task_runner, &counter));
@@ -302,17 +313,16 @@
 
 TEST_F(TaskRunnerTest, ReplaceFileDescriptorWatchFromOtherThread) {
   auto& task_runner = this->task_runner;
-  EventFd evt;
-  evt.Notify();
+  TestPipe pipe;
 
   // The two watch tasks here race each other. We don't particularly care which
   // wins as long as one of them runs.
-  task_runner.AddFileDescriptorWatch(evt.fd(),
+  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                      [&task_runner] { task_runner.Quit(); });
 
-  std::thread thread([&task_runner, &evt] {
-    task_runner.RemoveFileDescriptorWatch(evt.fd());
-    task_runner.AddFileDescriptorWatch(evt.fd(),
+  std::thread thread([&task_runner, &pipe] {
+    task_runner.RemoveFileDescriptorWatch(pipe.rd.get());
+    task_runner.AddFileDescriptorWatch(pipe.rd.get(),
                                        [&task_runner] { task_runner.Quit(); });
   });
 
@@ -347,46 +357,6 @@
   thread.join();
 }
 
-TEST_F(TaskRunnerTest, FileDescriptorWatchFairness) {
-  auto& task_runner = this->task_runner;
-  EventFd evt[5];
-  std::map<PlatformHandle, int /*num_tasks*/> num_tasks;
-  static constexpr int kNumTasksPerHandle = 100;
-  for (auto& e : evt) {
-    e.Notify();
-    task_runner.AddFileDescriptorWatch(e.fd(), [&] {
-      if (++num_tasks[e.fd()] == kNumTasksPerHandle) {
-        e.Clear();
-        task_runner.Quit();
-      }
-    });
-  }
-
-  task_runner.Run();
-
-  // The sequence evt[0], evt[1], evt[2] should be repeated N times. On the
-  // Nth time the task runner quits. All tasks should have been running at least
-  // N-1 times (we can't predict which one of the tasks will quit).
-  for (auto& e : evt) {
-    ASSERT_GE(num_tasks[e.fd()], kNumTasksPerHandle - 1);
-    ASSERT_LE(num_tasks[e.fd()], kNumTasksPerHandle);
-  }
-}
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-// This tests UNIX-specific behavior on pipe closure.
-TEST_F(TaskRunnerTest, FileDescriptorClosedEvent) {
-  auto& task_runner = this->task_runner;
-  Pipe pipe = Pipe::Create();
-  pipe.wr.reset();
-  task_runner.AddFileDescriptorWatch(pipe.rd.get(),
-                                     [&task_runner] { task_runner.Quit(); });
-  task_runner.Run();
-}
-
-#endif
-
 }  // namespace
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/temp_file.cc b/src/base/temp_file.cc
index 11e3f37..59a5089 100644
--- a/src/base/temp_file.cc
+++ b/src/base/temp_file.cc
@@ -14,81 +14,36 @@
  * 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/build_config.h"
-
-#include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <direct.h>
-#include <fileapi.h>
-#include <io.h>
-#else
 #include <unistd.h>
-#endif
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_utils.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-namespace {
-std::string GetTempName() {
-  char name[] = "perfetto-XXXXXX";
-  PERFETTO_CHECK(_mktemp_s(name, sizeof(name)) == 0);
-  return name;
-}
-}  // namespace
-#endif
 
 namespace perfetto {
 namespace base {
 
-std::string GetSysTempDir() {
-  const char* tmpdir = nullptr;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  if ((tmpdir = getenv("TMP")))
-    return tmpdir;
-  if ((tmpdir = getenv("TEMP")))
-    return tmpdir;
-  return "C:\\TEMP";
-#else
-  if ((tmpdir = getenv("TMPDIR")))
-    return base::StripSuffix(tmpdir, "/");
+namespace {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  return "/data/local/tmp";
+constexpr char kSysTmpPath[] = "/data/local/tmp";
 #else
-  return "/tmp";
-#endif  // !OS_ANDROID
-#endif  // !OS_WIN
-}
+constexpr char kSysTmpPath[] = "/tmp";
+#endif
+}  // namespace
 
 // static
 TempFile TempFile::Create() {
   TempFile temp_file;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  temp_file.path_ = GetSysTempDir() + "\\" + GetTempName();
-  // Several tests want to read-back the temp file while still open. On Windows,
-  // that requires FILE_SHARE_READ. FILE_SHARE_READ is NOT settable when using
-  // the POSIX-compat equivalent function _open(). Hence the CreateFileA +
-  // _open_osfhandle dance here.
-  HANDLE h =
-      ::CreateFileA(temp_file.path_.c_str(), GENERIC_READ | GENERIC_WRITE,
-                    FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS,
-                    FILE_ATTRIBUTE_TEMPORARY, nullptr);
-  PERFETTO_CHECK(PlatformHandleChecker::IsValid(h));
-  // According to MSDN, when using _open_osfhandle the caller must not call
-  // CloseHandle(). Ownership is moved to the file descriptor, which then needs
-  // to be closed with just with _close().
-  temp_file.fd_.reset(_open_osfhandle(reinterpret_cast<intptr_t>(h), 0));
-#else
-  temp_file.path_ = GetSysTempDir() + "/perfetto-XXXXXXXX";
+  const char* tmpdir = getenv("TMPDIR");
+  if (tmpdir) {
+    temp_file.path_.assign(tmpdir);
+  } else {
+    temp_file.path_.assign(kSysTmpPath);
+  }
+  temp_file.path_.append("/perfetto-XXXXXXXX");
   temp_file.fd_.reset(mkstemp(&temp_file.path_[0]));
-#endif
   if (PERFETTO_UNLIKELY(!temp_file.fd_)) {
     PERFETTO_FATAL("Could not create temp file %s", temp_file.path_.c_str());
   }
@@ -116,13 +71,7 @@
 void TempFile::Unlink() {
   if (path_.empty())
     return;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // If the FD is still open DeleteFile will mark the file as pending deletion
-  // and delete it only when the process exists.
-  PERFETTO_CHECK(DeleteFileA(path_.c_str()));
-#else
   PERFETTO_CHECK(unlink(path_.c_str()) == 0);
-#endif
   path_.clear();
 }
 
@@ -132,25 +81,20 @@
 // static
 TempDir TempDir::Create() {
   TempDir temp_dir;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  temp_dir.path_ = GetSysTempDir() + "\\" + GetTempName();
-  PERFETTO_CHECK(_mkdir(temp_dir.path_.c_str()) == 0);
-#else
-  temp_dir.path_ = GetSysTempDir() + "/perfetto-XXXXXXXX";
+  temp_dir.path_.assign(kSysTmpPath);
+  temp_dir.path_.append("/perfetto-XXXXXXXX");
   PERFETTO_CHECK(mkdtemp(&temp_dir.path_[0]));
-#endif
   return temp_dir;
 }
 
 TempDir::TempDir() = default;
-TempDir::TempDir(TempDir&&) noexcept = default;
-TempDir& TempDir::operator=(TempDir&&) = default;
 
 TempDir::~TempDir() {
-  if (path_.empty())
-    return;  // For objects that get std::move()d.
-  PERFETTO_CHECK(Rmdir(path_));
+  PERFETTO_CHECK(rmdir(path_.c_str()) == 0);
 }
 
 }  // 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 614894e..c2e2f4d 100644
--- a/src/base/temp_file_unittest.cc
+++ b/src/base/temp_file_unittest.cc
@@ -17,12 +17,7 @@
 #include "perfetto/ext/base/temp_file.h"
 
 #include <sys/stat.h>
-
-#include "perfetto/base/build_config.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <unistd.h>
-#endif
 
 #include "test/gtest_and_gmock.h"
 
@@ -65,10 +60,7 @@
   // The file should be deleted and closed now.
   ASSERT_FALSE(PathExists(path));
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Windows UCRT aborts when trying to write into a closed FD.
   ASSERT_EQ(-1, write(fd, "foo", 4));
-#endif
 }
 
 TEST(TempFileTest, CreateUnlinked) {
@@ -80,11 +72,7 @@
     ASSERT_GE(fd, 0);
     ASSERT_GE(write(fd, "foo", 4), 0);
   }
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Windows UCRT aborts when trying to write into a closed FD.
   ASSERT_EQ(-1, write(fd, "foo", 4));
-#endif
 }
 
 TEST(TempFileTest, ReleaseUnlinked) {
diff --git a/src/base/test/test_task_runner.cc b/src/base/test/test_task_runner.cc
index 3576996..7e490d4 100644
--- a/src/base/test/test_task_runner.cc
+++ b/src/base/test/test_task_runner.cc
@@ -17,6 +17,7 @@
 #include "src/base/test/test_task_runner.h"
 
 #include <stdio.h>
+#include <unistd.h>
 
 #include <chrono>
 
@@ -54,8 +55,9 @@
                                         uint32_t timeout_ms) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   if (checkpoints_.count(checkpoint) == 0) {
-    PERFETTO_FATAL("[TestTaskRunner] Checkpoint \"%s\" does not exist.\n",
-                   checkpoint.c_str());
+    fprintf(stderr, "[TestTaskRunner] Checkpoint \"%s\" does not exist.\n",
+            checkpoint.c_str());
+    abort();
   }
   if (checkpoints_[checkpoint])
     return;
@@ -64,8 +66,9 @@
       [this, checkpoint] {
         if (checkpoints_[checkpoint])
           return;
-        PERFETTO_FATAL("[TestTaskRunner] Failed to reach checkpoint \"%s\"\n",
-                       checkpoint.c_str());
+        fprintf(stderr, "[TestTaskRunner] Failed to reach checkpoint \"%s\"\n",
+                checkpoint.c_str());
+        abort();
       },
       timeout_ms);
 
@@ -98,12 +101,12 @@
   task_runner_.PostDelayedTask(std::move(closure), delay_ms);
 }
 
-void TestTaskRunner::AddFileDescriptorWatch(PlatformHandle fd,
+void TestTaskRunner::AddFileDescriptorWatch(int fd,
                                             std::function<void()> callback) {
   task_runner_.AddFileDescriptorWatch(fd, std::move(callback));
 }
 
-void TestTaskRunner::RemoveFileDescriptorWatch(PlatformHandle fd) {
+void TestTaskRunner::RemoveFileDescriptorWatch(int fd) {
   task_runner_.RemoveFileDescriptorWatch(fd);
 }
 
diff --git a/src/base/test/test_task_runner.h b/src/base/test/test_task_runner.h
index a7c5784..2d970ec 100644
--- a/src/base/test/test_task_runner.h
+++ b/src/base/test/test_task_runner.h
@@ -17,13 +17,14 @@
 #ifndef SRC_BASE_TEST_TEST_TASK_RUNNER_H_
 #define SRC_BASE_TEST_TEST_TASK_RUNNER_H_
 
+#include <sys/select.h>
+
 #include <functional>
 #include <list>
 #include <map>
 #include <string>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
 #include "perfetto/ext/base/thread_checker.h"
 #include "perfetto/ext/base/unix_task_runner.h"
 
@@ -36,7 +37,7 @@
   ~TestTaskRunner() override;
 
   void RunUntilIdle();
-  void PERFETTO_NORETURN Run();
+  void __attribute__((__noreturn__)) Run();
 
   std::function<void()> CreateCheckpoint(const std::string& checkpoint);
   void RunUntilCheckpoint(const std::string& checkpoint,
@@ -45,9 +46,8 @@
   // TaskRunner implementation.
   void PostTask(std::function<void()> closure) override;
   void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(PlatformHandle,
-                              std::function<void()> callback) override;
-  void RemoveFileDescriptorWatch(PlatformHandle) override;
+  void AddFileDescriptorWatch(int fd, std::function<void()> callback) override;
+  void RemoveFileDescriptorWatch(int fd) override;
   bool RunsTasksOnCurrentThread() const override;
 
  private:
diff --git a/src/base/test/utils.cc b/src/base/test/utils.cc
index 0a56611..95c6e60 100644
--- a/src/base/test/utils.cc
+++ b/src/base/test/utils.cc
@@ -18,26 +18,24 @@
 
 #include <stdlib.h>
 
-#include <memory>
-
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) ||   \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) ||  \
     PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
 #include <limits.h>
 #include <unistd.h>
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+#include <corecrt_io.h>
 #include <io.h>
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #include <mach-o/dyld.h>
 #endif
 
@@ -54,16 +52,11 @@
   PERFETTO_CHECK(size != -1);
   // readlink does not null terminate.
   self_path = std::string(buf, static_cast<size_t>(size));
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   uint32_t size = 0;
   PERFETTO_CHECK(_NSGetExecutablePath(nullptr, &size));
   self_path.resize(size);
   PERFETTO_CHECK(_NSGetExecutablePath(&self_path[0], &size) == 0);
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  char buf[MAX_PATH];
-  auto len = ::GetModuleFileNameA(nullptr /*current*/, buf, sizeof(buf));
-  self_path = std::string(buf, len);
-  self_path = self_path.substr(0, self_path.find_last_of("\\"));
 #else
   PERFETTO_FATAL(
       "GetCurExecutableDir() not implemented on the current platform");
@@ -75,37 +68,14 @@
 std::string GetTestDataPath(const std::string& path) {
   std::string self_path = GetCurExecutableDir();
   std::string full_path = self_path + "/../../" + path;
-  if (FileExists(full_path))
+  if (access(full_path.c_str(), 0 /*F_OK*/) == 0)
     return full_path;
   full_path = self_path + "/" + path;
-  if (FileExists(full_path))
+  if (access(full_path.c_str(), 0 /*F_OK*/) == 0)
     return full_path;
   // Fall back to relative to root dir.
   return path;
 }
 
-std::string HexDump(const void* data_void, size_t len, size_t bytes_per_line) {
-  const char* data = reinterpret_cast<const char*>(data_void);
-  std::string res;
-  static const size_t kPadding = bytes_per_line * 3 + 12;
-  std::unique_ptr<char[]> line(new char[bytes_per_line * 4 + 128]);
-  for (size_t i = 0; i < len; i += bytes_per_line) {
-    char* wptr = line.get();
-    wptr += sprintf(wptr, "%08zX: ", i);
-    for (size_t j = i; j < i + bytes_per_line && j < len; j++)
-      wptr += sprintf(wptr, "%02X ", static_cast<unsigned>(data[j]) & 0xFF);
-    for (size_t j = static_cast<size_t>(wptr - line.get()); j < kPadding; ++j)
-      *(wptr++) = ' ';
-    for (size_t j = i; j < i + bytes_per_line && j < len; j++) {
-      char c = data[j];
-      *(wptr++) = (c >= 32 && c < 127) ? c : '.';
-    }
-    *(wptr++) = '\n';
-    *(wptr++) = '\0';
-    res.append(line.get());
-  }
-  return res;
-}
-
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/test/utils.h b/src/base/test/utils.h
index e53b786..365c93f 100644
--- a/src/base/test/utils.h
+++ b/src/base/test/utils.h
@@ -37,9 +37,9 @@
 // we just fall back on executing the code directly.
 #if defined(GTEST_EXECUTE_STATEMENT_)
 #define EXPECT_DCHECK_DEATH(statement) \
-  GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
+    GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
 #define ASSERT_DCHECK_DEATH(statement) \
-  GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
+    GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
 #else
 #define EXPECT_DCHECK_DEATH(statement) [&]() { statement }()
 #define ASSERT_DCHECK_DEATH(statement) [&]() { statement }()
@@ -53,13 +53,6 @@
 std::string GetCurExecutableDir();
 std::string GetTestDataPath(const std::string& path);
 
-// Returns a xxd-style hex dump (hex + ascii chars) of the input data.
-std::string HexDump(const void* data, size_t len, size_t bytes_per_line = 16);
-inline std::string HexDump(const std::string& data,
-                           size_t bytes_per_line = 16) {
-  return HexDump(data.data(), data.size(), bytes_per_line);
-}
-
 }  // namespace base
 }  // namespace perfetto
 
diff --git a/src/base/test/vm_test_utils.cc b/src/base/test/vm_test_utils.cc
index e4d66f8..2efa845 100644
--- a/src/base/test/vm_test_utils.cc
+++ b/src/base/test/vm_test_utils.cc
@@ -36,17 +36,16 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 namespace base {
 namespace vm_test_utils {
 
 bool IsMapped(void* start, size_t size) {
-  const size_t page_size = GetSysPageSize();
+  PERFETTO_CHECK(size % kPageSize == 0);
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   int retries = 5;
-  size_t number_of_entries = 4000;  // Just a guess.
+  int number_of_entries = 4000;  // Just a guess.
   PSAPI_WORKING_SET_INFORMATION* ws_info = nullptr;
 
   std::vector<char> buffer;
@@ -70,7 +69,7 @@
 
     // Maybe some entries are being added right now. Increase the buffer to
     // take that into account. Increasing by 10% should generally be enough.
-    number_of_entries = static_cast<size_t>(double(number_of_entries) * 1.1);
+    number_of_entries *= 1.1;
 
     PERFETTO_CHECK(--retries > 0);  // If we're looping, eventually fail.
   }
@@ -79,32 +78,28 @@
   // Now scan the working-set information looking for the addresses.
   unsigned pages_found = 0;
   for (unsigned i = 0; i < ws_info->NumberOfEntries; ++i) {
-    void* address = reinterpret_cast<void*>(
-        ws_info->WorkingSetInfo[i].VirtualPage * page_size);
+    void* address =
+        reinterpret_cast<void*>(ws_info->WorkingSetInfo[i].VirtualPage *
+        kPageSize);
     if (address >= start && address < end)
       ++pages_found;
   }
 
-  if (pages_found * page_size == size)
+  if (pages_found * kPageSize == size)
     return true;
   return false;
 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
   // Fuchsia doesn't yet support paging (b/119503290).
-  ignore_result(page_size);
-  return true;
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
-  // mincore isn't available on NaCL.
-  ignore_result(page_size);
   return true;
 #else
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   using PageState = char;
   static constexpr PageState kIncoreMask = MINCORE_INCORE;
 #else
   using PageState = unsigned char;
   static constexpr PageState kIncoreMask = 1;
 #endif
-  const size_t num_pages = (size + page_size - 1) / page_size;
+  const size_t num_pages = size / kPageSize;
   std::unique_ptr<PageState[]> page_states(new PageState[num_pages]);
   memset(page_states.get(), 0, num_pages * sizeof(PageState));
   int res = mincore(start, size, page_states.get());
diff --git a/src/base/thread_checker_unittest.cc b/src/base/thread_checker_unittest.cc
index 08b7d02..f63ec5d 100644
--- a/src/base/thread_checker_unittest.cc
+++ b/src/base/thread_checker_unittest.cc
@@ -16,9 +16,10 @@
 
 #include "perfetto/ext/base/thread_checker.h"
 
+#include <pthread.h>
+
 #include <functional>
 #include <memory>
-#include <thread>
 
 #include "test/gtest_and_gmock.h"
 
@@ -26,29 +27,39 @@
 namespace base {
 namespace {
 
-bool RunOnThread(std::function<bool(void)> closure) {
-  bool res = false;
-  std::thread thread([&res, &closure] { res = closure(); });
-  thread.join();
-  return res;
+// We just need two distinct pointers to return to pthread_join().
+void* const kTrue = reinterpret_cast<void*>(1);
+void* const kFalse = nullptr;
+
+void* RunOnThread(std::function<void*(void)> closure) {
+  pthread_t thread;
+  auto thread_main = [](void* arg) -> void* {
+    pthread_exit((*reinterpret_cast<std::function<void*(void)>*>(arg))());
+  };
+  EXPECT_EQ(0, pthread_create(&thread, nullptr, thread_main, &closure));
+  void* retval = nullptr;
+  EXPECT_EQ(0, pthread_join(thread, &retval));
+  return retval;
 }
 
 TEST(ThreadCheckerTest, Basic) {
   ThreadChecker thread_checker;
   ASSERT_TRUE(thread_checker.CalledOnValidThread());
-  bool res = RunOnThread(
-      [&thread_checker] { return thread_checker.CalledOnValidThread(); });
+  void* res = RunOnThread([&thread_checker]() -> void* {
+    return thread_checker.CalledOnValidThread() ? kTrue : kFalse;
+  });
   ASSERT_TRUE(thread_checker.CalledOnValidThread());
-  ASSERT_FALSE(res);
+  ASSERT_EQ(kFalse, res);
 }
 
 TEST(ThreadCheckerTest, Detach) {
   ThreadChecker thread_checker;
   ASSERT_TRUE(thread_checker.CalledOnValidThread());
   thread_checker.DetachFromThread();
-  bool res = RunOnThread(
-      [&thread_checker] { return thread_checker.CalledOnValidThread(); });
-  ASSERT_TRUE(res);
+  void* res = RunOnThread([&thread_checker]() -> void* {
+    return thread_checker.CalledOnValidThread() ? kTrue : kFalse;
+  });
+  ASSERT_EQ(kTrue, res);
   ASSERT_FALSE(thread_checker.CalledOnValidThread());
 }
 
@@ -57,17 +68,19 @@
   ThreadChecker copied_thread_checker = thread_checker;
   ASSERT_TRUE(thread_checker.CalledOnValidThread());
   ASSERT_TRUE(copied_thread_checker.CalledOnValidThread());
-  bool res = RunOnThread([&copied_thread_checker] {
-    return copied_thread_checker.CalledOnValidThread();
+  void* res = RunOnThread([&copied_thread_checker]() -> void* {
+    return copied_thread_checker.CalledOnValidThread() ? kTrue : kFalse;
   });
-  ASSERT_FALSE(res);
+  ASSERT_EQ(kFalse, res);
 
   copied_thread_checker.DetachFromThread();
-  res = RunOnThread([&thread_checker, &copied_thread_checker] {
-    return copied_thread_checker.CalledOnValidThread() &&
-           !thread_checker.CalledOnValidThread();
+  res = RunOnThread([&thread_checker, &copied_thread_checker]() -> void* {
+    return (copied_thread_checker.CalledOnValidThread() &&
+            !thread_checker.CalledOnValidThread())
+               ? kTrue
+               : kFalse;
   });
-  ASSERT_TRUE(res);
+  ASSERT_EQ(kTrue, res);
 }
 
 }  // namespace
diff --git a/src/base/thread_task_runner.cc b/src/base/thread_task_runner.cc
index 08e3cea..bed6b72 100644
--- a/src/base/thread_task_runner.cc
+++ b/src/base/thread_task_runner.cc
@@ -15,6 +15,7 @@
  */
 
 #include "perfetto/base/build_config.h"
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
 #include "perfetto/ext/base/thread_task_runner.h"
 
@@ -114,28 +115,7 @@
   return thread_time_ns;
 }
 
-void ThreadTaskRunner::PostTask(std::function<void()> task) {
-  task_runner_->PostTask(std::move(task));
-}
-
-void ThreadTaskRunner::PostDelayedTask(std::function<void()> task,
-                                       uint32_t delay_ms) {
-  task_runner_->PostDelayedTask(std::move(task), delay_ms);
-}
-
-void ThreadTaskRunner::AddFileDescriptorWatch(
-    PlatformHandle handle,
-    std::function<void()> watch_task) {
-  task_runner_->AddFileDescriptorWatch(handle, std::move(watch_task));
-}
-
-void ThreadTaskRunner::RemoveFileDescriptorWatch(PlatformHandle handle) {
-  task_runner_->RemoveFileDescriptorWatch(handle);
-}
-
-bool ThreadTaskRunner::RunsTasksOnCurrentThread() const {
-  return task_runner_->RunsTasksOnCurrentThread();
-}
-
 }  // namespace base
 }  // namespace perfetto
+
+#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/time.cc b/src/base/time.cc
index 6c45efc..01bf02d 100644
--- a/src/base/time.cc
+++ b/src/base/time.cc
@@ -15,9 +15,7 @@
  */
 
 #include "perfetto/base/time.h"
-
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <Windows.h>
@@ -35,8 +33,7 @@
   ::QueryPerformanceFrequency(&freq);
   LARGE_INTEGER counter;
   ::QueryPerformanceCounter(&counter);
-  double elapsed_nanoseconds = (1e9 * static_cast<double>(counter.QuadPart)) /
-                               static_cast<double>(freq.QuadPart);
+  double elapsed_nanoseconds = (1e9 * counter.QuadPart) / freq.QuadPart;
   return TimeNanos(static_cast<uint64_t>(elapsed_nanoseconds));
 }
 
@@ -68,15 +65,5 @@
 
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
-std::string GetTimeFmt(const std::string& fmt) {
-  time_t raw_time;
-  time(&raw_time);
-  struct tm* local_tm;
-  local_tm = localtime(&raw_time);
-  char buf[128];
-  PERFETTO_CHECK(strftime(buf, 80, fmt.c_str(), local_tm) > 0);
-  return buf;
-}
-
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/time_unittest.cc b/src/base/time_unittest.cc
index 62c8566..04b40aa 100644
--- a/src/base/time_unittest.cc
+++ b/src/base/time_unittest.cc
@@ -25,8 +25,7 @@
 TEST(TimeTest, Conversions) {
   TimeMillis ms = GetWallTimeMs();
   TimeNanos ns = GetWallTimeNs();
-  EXPECT_NEAR(static_cast<double>(ms.count()),
-              static_cast<double>(ns.count()) / 1000000, 1000);
+  EXPECT_NEAR(ms.count(), ns.count() / 1000000, 1000);
 
   {
     struct timespec ts = ToPosixTimespec(TimeMillis(0));
diff --git a/src/base/unix_socket.cc b/src/base/unix_socket.cc
index 5986917..7db0ff7 100644
--- a/src/base/unix_socket.cc
+++ b/src/base/unix_socket.cc
@@ -18,32 +18,15 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include "perfetto/base/compiler.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// The include order matters on these three Windows header groups.
-#include <Windows.h>
-
-#include <WS2tcpip.h>
-#include <WinSock2.h>
-
-#include <afunix.h>
-#else
 #include <netdb.h>
 #include <netinet/in.h>
-#include <netinet/tcp.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/un.h>
 #include <unistd.h>
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-#include <sys/ucred.h>
-#endif
 
 #include <algorithm>
 #include <memory>
@@ -54,13 +37,16 @@
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/utils.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+#include <sys/ucred.h>
+#endif
+
 namespace perfetto {
 namespace base {
 
 // The CMSG_* macros use NULL instead of nullptr.
-// Note: MSVC doesn't have #pragma GCC diagnostic, hence the if __GNUC__.
-#if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
 #pragma GCC diagnostic push
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
 #endif
 
@@ -68,9 +54,7 @@
 
 // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
 // created with SO_NOSIGPIPE (See InitializeSocket()).
-// On Windows this does't apply as signals don't exist.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 constexpr int kNoSigPipe = 0;
 #else
 constexpr int kNoSigPipe = MSG_NOSIGNAL;
@@ -90,8 +74,7 @@
 // more importantly, are bigger than the base struct sockaddr.
 struct SockaddrAny {
   SockaddrAny() : size() {}
-  SockaddrAny(const void* addr, socklen_t sz)
-      : data(new char[static_cast<size_t>(sz)]), size(sz) {
+  SockaddrAny(const void* addr, socklen_t sz) : data(new char[sz]), size(sz) {
     memcpy(data.get(), addr, static_cast<size_t>(size));
   }
 
@@ -109,8 +92,6 @@
       return AF_UNIX;
     case SockFamily::kInet:
       return AF_INET;
-    case SockFamily::kInet6:
-      return AF_INET6;
   }
   PERFETTO_CHECK(false);  // For GCC.
 }
@@ -142,17 +123,8 @@
         return SockaddrAny();
       }
       memcpy(saddr.sun_path, socket_name.data(), name_len);
-      if (saddr.sun_path[0] == '@') {
+      if (saddr.sun_path[0] == '@')
         saddr.sun_path[0] = '\0';
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-        // The MSDN blog claims that abstract (non-filesystem based) AF_UNIX
-        // socket are supported, but that doesn't seem true.
-        PERFETTO_ELOG(
-            "Abstract AF_UNIX sockets are not supported on Windows, see "
-            "https://github.com/microsoft/WSL/issues/4240");
-        return SockaddrAny{};
-#endif
-      }
       saddr.sun_family = AF_UNIX;
       auto size = static_cast<socklen_t>(
           __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
@@ -168,26 +140,7 @@
       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,
-                      static_cast<socklen_t>(addr_info->ai_addrlen));
-      freeaddrinfo(addr_info);
-      return res;
-    }
-    case SockFamily::kInet6: {
-      auto parts = SplitString(socket_name, "]");
-      PERFETTO_CHECK(parts.size() == 2);
-      auto address = SplitString(parts[0], "[");
-      PERFETTO_CHECK(address.size() == 1);
-      auto port = SplitString(parts[1], ":");
-      PERFETTO_CHECK(port.size() == 1);
-      struct addrinfo* addr_info = nullptr;
-      struct addrinfo hints {};
-      hints.ai_family = AF_INET6;
-      PERFETTO_CHECK(getaddrinfo(address[0].c_str(), port[0].c_str(), &hints,
-                                 &addr_info) == 0);
-      PERFETTO_CHECK(addr_info->ai_family == AF_INET6);
-      SockaddrAny res(addr_info->ai_addr,
-                      static_cast<socklen_t>(addr_info->ai_addrlen));
+      SockaddrAny res(addr_info->ai_addr, addr_info->ai_addrlen);
       freeaddrinfo(addr_info);
       return res;
     }
@@ -195,33 +148,14 @@
   PERFETTO_CHECK(false);  // For GCC.
 }
 
-ScopedSocketHandle CreateSocketHandle(SockFamily family, SockType type) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  static bool init_winsock_once = [] {
-    WSADATA ignored{};
-    return WSAStartup(MAKEWORD(2, 2), &ignored) == 0;
-  }();
-  PERFETTO_CHECK(init_winsock_once);
-#endif
-  return ScopedSocketHandle(
-      socket(GetSockFamily(family), GetSockType(type), 0));
-}
-
 }  // namespace
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-int CloseSocket(SocketHandle s) {
-  return ::closesocket(s);
-}
-#endif
-
 // +-----------------------+
 // | UnixSocketRaw methods |
 // +-----------------------+
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 // static
-void UnixSocketRaw::ShiftMsgHdrPosix(size_t n, struct msghdr* msg) {
+void UnixSocketRaw::ShiftMsgHdr(size_t n, struct msghdr* msg) {
   using LenType = decltype(msg->msg_iovlen);  // Mac and Linux don't agree.
   for (LenType i = 0; i < msg->msg_iovlen; ++i) {
     struct iovec* vec = &msg->msg_iov[i];
@@ -243,7 +177,16 @@
 }
 
 // static
-std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePairPosix(
+UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
+  auto fd = ScopedFile(socket(GetSockFamily(family), GetSockType(type), 0));
+  if (!fd) {
+    return UnixSocketRaw();
+  }
+  return UnixSocketRaw(std::move(fd), family, type);
+}
+
+// static
+std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePair(
     SockFamily family,
     SockType type) {
   int fds[2];
@@ -253,103 +196,58 @@
   return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), family, type),
                         UnixSocketRaw(ScopedFile(fds[1]), family, type));
 }
-#endif
-
-// static
-UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
-  auto fd = CreateSocketHandle(family, type);
-  if (!fd)
-    return UnixSocketRaw();
-  return UnixSocketRaw(std::move(fd), family, type);
-}
 
 UnixSocketRaw::UnixSocketRaw() = default;
 
 UnixSocketRaw::UnixSocketRaw(SockFamily family, SockType type)
-    : UnixSocketRaw(CreateSocketHandle(family, type), family, type) {}
+    : UnixSocketRaw(
+          ScopedFile(socket(GetSockFamily(family), GetSockType(type), 0)),
+          family,
+          type) {}
 
-UnixSocketRaw::UnixSocketRaw(ScopedSocketHandle fd,
-                             SockFamily family,
-                             SockType type)
+UnixSocketRaw::UnixSocketRaw(ScopedFile fd, SockFamily family, SockType type)
     : fd_(std::move(fd)), family_(family), type_(type) {
   PERFETTO_CHECK(fd_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#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 || family == SockFamily::kInet6) {
+  if (family == SockFamily::kInet) {
     int flag = 1;
-    // The reinterpret_cast<const char*> is needed for Windows, where the 4th
-    // arg is a const char* (on other POSIX system is a const void*).
-    PERFETTO_CHECK(!setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR,
-                               reinterpret_cast<const char*>(&flag),
-                               sizeof(flag)));
-    flag = 1;
-    // Disable Nagle's algorithm, optimize for low-latency.
-    // See https://github.com/google/perfetto/issues/70.
-    setsockopt(*fd_, IPPROTO_TCP, TCP_NODELAY,
-               reinterpret_cast<const char*>(&flag), sizeof(flag));
+    PERFETTO_CHECK(
+        !setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)));
   }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // We use one event handle for all socket events, to stay consistent to what
-  // we do on UNIX with the base::TaskRunner's poll().
-  event_handle_.reset(WSACreateEvent());
-  PERFETTO_CHECK(event_handle_);
-#else
   // 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);
   PERFETTO_CHECK(fcntl_res == 0);
-#endif
 }
 
 void UnixSocketRaw::SetBlocking(bool is_blocking) {
   PERFETTO_DCHECK(fd_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  unsigned long flag = is_blocking ? 0 : 1;  // FIONBIO has reverse logic.
-  if (is_blocking) {
-    // When switching between non-blocking -> blocking mode, we need to reset
-    // the event handle registration, otherwise the call will fail.
-    PERFETTO_CHECK(WSAEventSelect(*fd_, *event_handle_, 0) == 0);
-  }
-  PERFETTO_CHECK(ioctlsocket(*fd_, static_cast<long>(FIONBIO), &flag) == 0);
-  if (!is_blocking) {
-    PERFETTO_CHECK(
-        WSAEventSelect(*fd_, *event_handle_,
-                       FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE) == 0);
-  }
-#else
   int flags = fcntl(*fd_, F_GETFL, 0);
   if (!is_blocking) {
     flags |= O_NONBLOCK;
   } else {
     flags &= ~static_cast<int>(O_NONBLOCK);
   }
-  int fcntl_res = fcntl(*fd_, F_SETFL, flags);
+  bool fcntl_res = fcntl(*fd_, F_SETFL, flags);
   PERFETTO_CHECK(fcntl_res == 0);
-#endif
 }
 
 void UnixSocketRaw::RetainOnExec() {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   PERFETTO_DCHECK(fd_);
   int flags = fcntl(*fd_, F_GETFD, 0);
   flags &= ~static_cast<int>(FD_CLOEXEC);
-  int fcntl_res = fcntl(*fd_, F_SETFD, flags);
+  bool fcntl_res = fcntl(*fd_, F_SETFD, flags);
   PERFETTO_CHECK(fcntl_res == 0);
-#endif
 }
 
-void UnixSocketRaw::DcheckIsBlocking(bool expected) const {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  ignore_result(expected);
-#else
+bool UnixSocketRaw::IsBlocking() const {
   PERFETTO_DCHECK(fd_);
-  bool is_blocking = (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0;
-  PERFETTO_DCHECK(is_blocking == expected);
-#endif
+  return (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0;
 }
 
 bool UnixSocketRaw::Bind(const std::string& socket_name) {
@@ -379,46 +277,17 @@
     return false;
 
   int res = PERFETTO_EINTR(connect(*fd_, addr.addr(), addr.size));
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  bool continue_async = WSAGetLastError() == WSAEWOULDBLOCK;
-#else
-  bool continue_async = errno == EINPROGRESS;
-#endif
-  if (res && !continue_async)
+  if (res && errno != EINPROGRESS)
     return false;
 
   return true;
 }
 
 void UnixSocketRaw::Shutdown() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Somebody felt very strongly about the naming of this constant.
-  shutdown(*fd_, SD_BOTH);
-#else
   shutdown(*fd_, SHUT_RDWR);
-#endif
   fd_.reset();
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-ssize_t UnixSocketRaw::Send(const void* msg,
-                            size_t len,
-                            const int* /*send_fds*/,
-                            size_t num_fds) {
-  PERFETTO_DCHECK(num_fds == 0);
-  return sendto(*fd_, static_cast<const char*>(msg), static_cast<int>(len), 0,
-                nullptr, 0);
-}
-
-ssize_t UnixSocketRaw::Receive(void* msg,
-                               size_t len,
-                               ScopedFile* /*fd_vec*/,
-                               size_t /*max_files*/) {
-  return recv(*fd_, static_cast<char*>(msg), static_cast<int>(len), 0);
-}
-
-#else
 // For the interested reader, Linux kernel dive to verify this is not only a
 // theoretical possibility: sock_stream_sendmsg, if sock_alloc_send_pskb returns
 // NULL [1] (which it does when it gets interrupted [2]), returns early with the
@@ -427,7 +296,7 @@
 // [1]:
 // https://elixir.bootlin.com/linux/v4.18.10/source/net/unix/af_unix.c#L1872
 // [2]: https://elixir.bootlin.com/linux/v4.18.10/source/net/core/sock.c#L2101
-ssize_t UnixSocketRaw::SendMsgAllPosix(struct msghdr* msg) {
+ssize_t UnixSocketRaw::SendMsgAll(struct msghdr* msg) {
   // This does not make sense on non-blocking sockets.
   PERFETTO_DCHECK(fd_);
 
@@ -440,7 +309,7 @@
       return sent;
     }
     total_sent += sent;
-    ShiftMsgHdrPosix(static_cast<size_t>(sent), msg);
+    ShiftMsgHdr(static_cast<size_t>(sent), msg);
     // Only send the ancillary data with the first sendmsg call.
     msg->msg_control = nullptr;
     msg->msg_controllen = 0;
@@ -476,7 +345,7 @@
     // msg_hdr.msg_controllen would need to be adjusted, see "man 3 cmsg".
   }
 
-  return SendMsgAllPosix(&msg_hdr);
+  return SendMsgAll(&msg_hdr);
 }
 
 ssize_t UnixSocketRaw::Receive(void* msg,
@@ -521,9 +390,6 @@
   if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) {
     for (size_t i = 0; fds && i < fds_len; ++i)
       close(fds[i]);
-    PERFETTO_ELOG(
-        "Socket message truncated. This might be due to a SELinux denial on "
-        "fd:use.");
     errno = EMSGSIZE;
     return -1;
   }
@@ -537,19 +403,15 @@
 
   return sz;
 }
-#endif  // OS_WIN
 
 bool UnixSocketRaw::SetTxTimeout(uint32_t timeout_ms) {
   PERFETTO_DCHECK(fd_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  DWORD timeout = timeout_ms;
-#else
   struct timeval timeout {};
   uint32_t timeout_sec = timeout_ms / 1000;
   timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
   timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
       (timeout_ms - (timeout_sec * 1000)) * 1000);
-#endif
+
   return setsockopt(*fd_, SOL_SOCKET, SO_SNDTIMEO,
                     reinterpret_cast<const char*>(&timeout),
                     sizeof(timeout)) == 0;
@@ -557,23 +419,18 @@
 
 bool UnixSocketRaw::SetRxTimeout(uint32_t timeout_ms) {
   PERFETTO_DCHECK(fd_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  DWORD timeout = timeout_ms;
-#else
   struct timeval timeout {};
   uint32_t timeout_sec = timeout_ms / 1000;
   timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
   timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
       (timeout_ms - (timeout_sec * 1000)) * 1000);
-#endif
+
   return setsockopt(*fd_, SOL_SOCKET, SO_RCVTIMEO,
                     reinterpret_cast<const char*>(&timeout),
                     sizeof(timeout)) == 0;
 }
 
-#if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
 #pragma GCC diagnostic pop
-#endif
 
 // +--------------------+
 // | UnixSocket methods |
@@ -597,91 +454,86 @@
 }
 
 // static
-std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedSocketHandle fd,
+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, SockPeerCredMode::kDefault));
+  return std::unique_ptr<UnixSocket>(
+      new UnixSocket(event_listener, task_runner, std::move(fd),
+                     State::kListening, sock_family, 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,
-    SockPeerCredMode peer_cred_mode) {
-  std::unique_ptr<UnixSocket> sock(new UnixSocket(
-      event_listener, task_runner, sock_family, sock_type, peer_cred_mode));
+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));
   sock->DoConnect(socket_name);
   return sock;
 }
 
 // static
 std::unique_ptr<UnixSocket> UnixSocket::AdoptConnected(
-    ScopedSocketHandle fd,
+    ScopedFile fd,
     EventListener* event_listener,
     TaskRunner* task_runner,
     SockFamily sock_family,
-    SockType sock_type,
-    SockPeerCredMode peer_cred_mode) {
-  return std::unique_ptr<UnixSocket>(new UnixSocket(
-      event_listener, task_runner, std::move(fd), State::kConnected,
-      sock_family, sock_type, peer_cred_mode));
+    SockType sock_type) {
+  return std::unique_ptr<UnixSocket>(
+      new UnixSocket(event_listener, task_runner, std::move(fd),
+                     State::kConnected, sock_family, sock_type));
 }
 
 UnixSocket::UnixSocket(EventListener* event_listener,
                        TaskRunner* task_runner,
                        SockFamily sock_family,
-                       SockType sock_type,
-                       SockPeerCredMode peer_cred_mode)
+                       SockType sock_type)
     : UnixSocket(event_listener,
                  task_runner,
-                 ScopedSocketHandle(),
+                 ScopedFile(),
                  State::kDisconnected,
                  sock_family,
-                 sock_type,
-                 peer_cred_mode) {}
+                 sock_type) {}
 
 UnixSocket::UnixSocket(EventListener* event_listener,
                        TaskRunner* task_runner,
-                       ScopedSocketHandle adopt_fd,
+                       ScopedFile adopt_fd,
                        State adopt_state,
                        SockFamily sock_family,
-                       SockType sock_type,
-                       SockPeerCredMode peer_cred_mode)
-    : peer_cred_mode_(peer_cred_mode),
-      event_listener_(event_listener),
+                       SockType sock_type)
+    : event_listener_(event_listener),
       task_runner_(task_runner),
       weak_ptr_factory_(this) {
   state_ = State::kDisconnected;
   if (adopt_state == State::kDisconnected) {
     PERFETTO_DCHECK(!adopt_fd);
     sock_raw_ = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
-    if (!sock_raw_)
+    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);
     state_ = State::kConnected;
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
-      ReadPeerCredentialsPosix();
-#endif
+    ReadPeerCredentials();
   } else if (adopt_state == State::kListening) {
     // We get here from Listen().
 
     // |adopt_fd| might genuinely be invalid if the bind() failed.
-    if (!adopt_fd)
+    if (!adopt_fd) {
+      last_error_ = errno;
       return;
+    }
 
     sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
     if (!sock_raw_.Listen()) {
-      PERFETTO_DPLOG("listen() failed");
+      last_error_ = errno;
+      PERFETTO_DPLOG("listen()");
       return;
     }
     state_ = State::kListening;
@@ -690,12 +542,13 @@
   }
 
   PERFETTO_CHECK(sock_raw_);
+  last_error_ = 0;
 
   sock_raw_.SetBlocking(false);
 
   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
 
-  task_runner_->AddFileDescriptorWatch(sock_raw_.watch_handle(), [weak_ptr] {
+  task_runner_->AddFileDescriptorWatch(sock_raw_.fd(), [weak_ptr] {
     if (weak_ptr)
       weak_ptr->OnEvent();
   });
@@ -710,7 +563,7 @@
   // This will invalidate any pending calls to OnEvent.
   state_ = State::kDisconnected;
   if (sock_raw_)
-    task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
+    task_runner_->RemoveFileDescriptorWatch(sock_raw_.fd());
 
   return std::move(sock_raw_);
 }
@@ -723,11 +576,14 @@
   if (!sock_raw_)
     return NotifyConnectionState(false);
 
-  if (!sock_raw_.Connect(socket_name))
+  if (!sock_raw_.Connect(socket_name)) {
+    last_error_ = errno;
     return NotifyConnectionState(false);
+  }
 
   // At this point either connect() succeeded or started asynchronously
   // (errno = EINPROGRESS).
+  last_error_ = 0;
   state_ = State::kConnecting;
 
   // Even if the socket is non-blocking, connecting to a UNIX socket can be
@@ -745,12 +601,10 @@
   });
 }
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-void UnixSocket::ReadPeerCredentialsPosix() {
+void UnixSocket::ReadPeerCredentials() {
   // Peer credentials are supported only on AF_UNIX sockets.
   if (sock_raw_.family() != SockFamily::kUnix)
     return;
-  PERFETTO_CHECK(peer_cred_mode_ != SockPeerCredMode::kIgnore);
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -761,98 +615,16 @@
   PERFETTO_CHECK(res == 0);
   peer_uid_ = user_cred.uid;
   peer_pid_ = user_cred.pid;
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#else
   struct xucred user_cred;
   socklen_t len = sizeof(user_cred);
   int res = getsockopt(sock_raw_.fd(), 0, LOCAL_PEERCRED, &user_cred, &len);
   PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION);
   peer_uid_ = static_cast<uid_t>(user_cred.cr_uid);
-  // There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD.
+// There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD.
 #endif
 }
-#endif  // !OS_WIN
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-void UnixSocket::OnEvent() {
-  WSANETWORKEVENTS evts{};
-  PERFETTO_CHECK(WSAEnumNetworkEvents(sock_raw_.fd(), sock_raw_.watch_handle(),
-                                      &evts) == 0);
-  if (state_ == State::kDisconnected)
-    return;  // Some spurious event, typically queued just before Shutdown().
-
-  if (state_ == State::kConnecting && (evts.lNetworkEvents & FD_CONNECT)) {
-    PERFETTO_DCHECK(sock_raw_);
-    int err = evts.iErrorCode[FD_CONNECT_BIT];
-    if (err) {
-      PERFETTO_DPLOG("Connection error: %d", err);
-      Shutdown(false);
-      event_listener_->OnConnect(this, false /* connected */);
-      return;
-    }
-
-    // kReadOnConnect is not supported on Windows.
-    PERFETTO_DCHECK(peer_cred_mode_ != SockPeerCredMode::kReadOnConnect);
-    state_ = State::kConnected;
-    event_listener_->OnConnect(this, true /* connected */);
-  }
-
-  // This is deliberately NOT an else-if. When a client socket connects and
-  // there is already data queued, the following will happen within the same
-  // OnEvent() call:
-  // 1. The block above will transition kConnecting -> kConnected.
-  // 2. This block will cause an OnDataAvailable() call.
-  // Unlike UNIX, where poll() keeps signalling the event until the client
-  // does a recv(), Windows is more picky and stops signalling the event until
-  // the next call to recv() is made. In other words, in Windows we cannot
-  // miss an OnDataAvailable() call or the event pump will stop.
-  if (state_ == State::kConnected) {
-    if (evts.lNetworkEvents & FD_READ) {
-      event_listener_->OnDataAvailable(this);
-      // TODO(primiano): I am very conflicted here. Because of the behavior
-      // described above, if the event listener doesn't do a Recv() call in
-      // the OnDataAvailable() callback, WinSock won't notify the event ever
-      // again. On one side, I don't see any reason why a client should decide
-      // to not do a Recv() in OnDataAvailable. On the other side, the
-      // behavior here diverges from UNIX, where OnDataAvailable() would be
-      // re-posted immediately. In both cases, not doing a Recv() in
-      // OnDataAvailable, leads to something bad (getting stuck on Windows,
-      // getting in a hot loop on Linux), so doesn't feel we should worry too
-      // much about this. If we wanted to keep the behavrior consistent, here
-      // we should do something like: `if (sock_raw_)
-      // sock_raw_.SetBlocking(false)` (Note that the socket might be closed
-      // by the time we come back here, hence the if part).
-      return;
-    }
-    // Could read EOF and disconnect here.
-    if (evts.lNetworkEvents & FD_CLOSE) {
-      Shutdown(true);
-      return;
-    }
-  }
-
-  // New incoming connection.
-  if (state_ == State::kListening && (evts.lNetworkEvents & FD_ACCEPT)) {
-    // There could be more than one incoming connection behind each FD watch
-    // notification. Drain'em all.
-    for (;;) {
-      // Note: right now we don't need the remote endpoint, hence we pass
-      // nullptr to |addr| and |addrlen|. If we ever need to do so, be
-      // extremely careful. Windows' WinSock API will happily write more than
-      // |addrlen| (hence corrupt the stack) if the |addr| argument passed is
-      // not big enough (e.g. passing a struct sockaddr_in to a AF_UNIX
-      // socket, where sizeof(sockaddr_un) is >> sizef(sockaddr_in)). It seems
-      // a Windows / CRT bug in the AF_UNIX implementation.
-      ScopedSocketHandle new_fd(accept(sock_raw_.fd(), nullptr, nullptr));
-      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(), peer_cred_mode_));
-      event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
-    }
-  }
-}
-#else
 void UnixSocket::OnEvent() {
   if (state_ == State::kDisconnected)
     return;  // Some spurious event, typically queued just before Shutdown().
@@ -870,12 +642,12 @@
     if (res == 0 && sock_err == EINPROGRESS)
       return;  // Not connected yet, just a spurious FD watch wakeup.
     if (res == 0 && sock_err == 0) {
-      if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
-        ReadPeerCredentialsPosix();
+      ReadPeerCredentials();
       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 */);
   }
@@ -885,44 +657,54 @@
     // There could be more than one incoming connection behind each FD watch
     // notification. Drain'em all.
     for (;;) {
-      ScopedFile new_fd(
-          PERFETTO_EINTR(accept(sock_raw_.fd(), nullptr, nullptr)));
+      struct sockaddr_in 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(), peer_cred_mode_));
+          sock_raw_.family(), sock_raw_.type()));
       event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
     }
   }
 }
-#endif
 
 bool UnixSocket::Send(const void* msg,
                       size_t len,
                       const int* send_fds,
                       size_t num_fds) {
   if (state_ != State::kConnected) {
-    errno = ENOTCONN;
+    errno = last_error_ = ENOTCONN;
     return false;
   }
 
   sock_raw_.SetBlocking(true);
   const ssize_t sz = sock_raw_.Send(msg, len, send_fds, num_fds);
+  int saved_errno = errno;
   sock_raw_.SetBlocking(false);
 
   if (sz == static_cast<ssize_t>(len)) {
+    last_error_ = 0;
     return true;
   }
 
-  // If we ever decide to support non-blocking sends again, here we should
-  // watch for both EAGAIN and EWOULDBLOCK (see base::IsAgain()).
+  // If sendmsg() succeeds 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.
 
-  // If sendmsg() succeeds but the returned size is >= 0 and < |len| it means
-  // that the endpoint disconnected in the middle of the read, and we managed
-  // to send only a portion of the buffer.
-  // If sz < 0, either the other endpoint disconnected (ECONNRESET) or some
-  // other error happened. In both cases we should just give up.
+  if (sz < 0 && (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK)) {
+    // A genuine out-of-buffer. The client should retry or give up.
+    // Man pages specify that EAGAIN and EWOULDBLOCK have the same semantic here
+    // and clients should check for both.
+    last_error_ = EAGAIN;
+    return false;
+  }
+
+  // Either the other endpoint disconnected (ECONNRESET) or some other error
+  // happened.
+  last_error_ = saved_errno;
   PERFETTO_DPLOG("sendmsg() failed");
   Shutdown(true);
   return false;
@@ -945,7 +727,7 @@
   }
 
   if (sock_raw_) {
-    task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
+    task_runner_->RemoveFileDescriptorWatch(sock_raw_.fd());
     sock_raw_.Shutdown();
   }
   state_ = State::kDisconnected;
@@ -955,19 +737,18 @@
                            size_t len,
                            ScopedFile* fd_vec,
                            size_t max_files) {
-  if (state_ != State::kConnected)
+  if (state_ != State::kConnected) {
+    last_error_ = ENOTCONN;
     return 0;
+  }
 
   const ssize_t sz = sock_raw_.Receive(msg, len, fd_vec, max_files);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  bool async_would_block = WSAGetLastError() == WSAEWOULDBLOCK;
-#else
-  bool async_would_block = IsAgain(errno);
-#endif
-  if (sz < 0 && async_would_block)
+  if (sz < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+    last_error_ = EAGAIN;
     return 0;
-
+  }
   if (sz <= 0) {
+    last_error_ = errno;
     Shutdown(true);
     return 0;
   }
@@ -978,8 +759,8 @@
 std::string UnixSocket::ReceiveString(size_t max_length) {
   std::unique_ptr<char[]> buf(new char[max_length + 1]);
   size_t rsize = Receive(buf.get(), max_length);
-  PERFETTO_CHECK(rsize <= max_length);
-  buf[rsize] = '\0';
+  PERFETTO_CHECK(static_cast<size_t>(rsize) <= max_length);
+  buf[static_cast<size_t>(rsize)] = '\0';
   return std::string(buf.get());
 }
 
diff --git a/src/base/unix_socket_unittest.cc b/src/base/unix_socket_unittest.cc
index 9ef69c9..2a43200 100644
--- a/src/base/unix_socket_unittest.cc
+++ b/src/base/unix_socket_unittest.cc
@@ -17,15 +17,12 @@
 #include "perfetto/ext/base/unix_socket.h"
 
 #include <signal.h>
-#include <sys/types.h>
-#include <list>
-#include <thread>
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <sys/mman.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <sys/un.h>
-#endif
+#include <list>
+#include <thread>
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
@@ -47,7 +44,7 @@
 using ::testing::InvokeWithoutArgs;
 using ::testing::Mock;
 
-ipc::TestSocket kTestSocket{"unix_socket_unittest"};
+constexpr char kSocketName[] = TEST_SOCK_NAME("unix_socket_unittest");
 
 class MockEventListener : public UnixSocket::EventListener {
  public:
@@ -78,17 +75,16 @@
 
 class UnixSocketTest : public ::testing::Test {
  protected:
-  void SetUp() override { kTestSocket.Destroy(); }
-  void TearDown() override { kTestSocket.Destroy(); }
+  void SetUp() override { DESTROY_TEST_SOCK(kSocketName); }
+  void TearDown() override { DESTROY_TEST_SOCK(kSocketName); }
 
   TestTaskRunner task_runner_;
   MockEventListener event_listener_;
 };
 
 TEST_F(UnixSocketTest, ConnectionFailureIfUnreachable) {
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
   ASSERT_FALSE(cli->is_connected());
   auto checkpoint = task_runner_.CreateCheckpoint("failure");
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), false))
@@ -99,9 +95,8 @@
 // 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(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                SockFamily::kUnix, SockType::kStream);
   ASSERT_TRUE(srv->is_listening());
 
   // The server will immediately shutdown the connection upon
@@ -116,9 +111,8 @@
           }));
 
   auto checkpoint = task_runner_.CreateCheckpoint("cli_connected");
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
       .WillOnce(InvokeWithoutArgs(checkpoint));
   task_runner_.RunUntilCheckpoint("cli_connected");
@@ -128,36 +122,27 @@
   auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
   EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
       .WillOnce(InvokeWithoutArgs(cli_disconnected));
-
-  // On Windows the first send immediately after the disconnection succeeds, the
-  // kernel will detect the disconnection only later.
-  cli->Send(".");
-  EXPECT_FALSE(cli->Send("should_fail_both_on_win_and_unix"));
+  EXPECT_FALSE(cli->Send("whatever"));
   task_runner_.RunUntilCheckpoint("cli_disconnected");
 }
 
 TEST_F(UnixSocketTest, ClientAndServerExchangeData) {
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                SockFamily::kUnix, SockType::kStream);
   ASSERT_TRUE(srv->is_listening());
 
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
+  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
-  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli_connected));
-  auto srv_conn_seen = task_runner_.CreateCheckpoint("srv_conn_seen");
   auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
   EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(Invoke([this, srv_conn_seen, srv_disconnected](
+      .WillOnce(Invoke([this, cli_connected, srv_disconnected](
                            UnixSocket*, UnixSocket* srv_conn) {
         EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
             .WillOnce(InvokeWithoutArgs(srv_disconnected));
-        srv_conn_seen();
+        cli_connected();
       }));
-  task_runner_.RunUntilCheckpoint("srv_conn_seen");
   task_runner_.RunUntilCheckpoint("cli_connected");
 
   auto srv_conn = event_listener_.GetIncomingConnection();
@@ -199,380 +184,16 @@
   task_runner_.RunUntilCheckpoint("srv_disconnected");
 }
 
-TEST_F(UnixSocketTest, ListenWithPassedSocketHandle) {
-  auto sock_raw =
-      UnixSocketRaw::CreateMayFail(kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(sock_raw.Bind(kTestSocket.name()));
-  auto fd = sock_raw.ReleaseFd();
-  auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_,
-                                kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-
-  auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
-  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli_connected));
-  auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
-  auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(Invoke([this, srv_connected, srv_disconnected](
-                           UnixSocket*, UnixSocket* srv_conn) {
-        // An empty OnDataAvailable might be raised to signal the EOF state.
-        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
-            .WillRepeatedly(
-                InvokeWithoutArgs([srv_conn] { srv_conn->ReceiveString(); }));
-        EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
-            .WillOnce(InvokeWithoutArgs(srv_disconnected));
-        srv_connected();
-      }));
-  task_runner_.RunUntilCheckpoint("srv_connected");
-  task_runner_.RunUntilCheckpoint("cli_connected");
-  ASSERT_TRUE(cli->is_connected());
-  cli.reset();
-  task_runner_.RunUntilCheckpoint("srv_disconnected");
-}
-
-// 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(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-  constexpr size_t kNumClients = 32;
-  std::unique_ptr<UnixSocket> cli[kNumClients];
-
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .Times(kNumClients)
-      .WillRepeatedly(Invoke([this](UnixSocket*, UnixSocket* s) {
-        EXPECT_CALL(event_listener_, OnDataAvailable(s))
-            .WillOnce(Invoke([](UnixSocket* t) {
-              ASSERT_EQ("PING", t->ReceiveString());
-              ASSERT_TRUE(t->Send("PONG"));
-            }));
-      }));
-
-  for (size_t i = 0; i < kNumClients; i++) {
-    cli[i] =
-        UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                            kTestSocket.family(), SockType::kStream);
-    EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true))
-        .WillOnce(Invoke([](UnixSocket* s, bool success) {
-          ASSERT_TRUE(success);
-          ASSERT_TRUE(s->Send("PING"));
-        }));
-
-    auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
-    EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
-        .WillOnce(Invoke([checkpoint](UnixSocket* s) {
-          ASSERT_EQ("PONG", s->ReceiveString());
-          checkpoint();
-        }));
-  }
-
-  for (size_t i = 0; i < kNumClients; i++) {
-    task_runner_.RunUntilCheckpoint(std::to_string(i));
-    ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
-  }
-}
-
-TEST_F(UnixSocketTest, BlockingSend) {
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-
-  auto all_frames_done = task_runner_.CreateCheckpoint("all_frames_done");
-  size_t total_bytes_received = 0;
-  static constexpr size_t kTotalBytes = 1024 * 1024 * 4;
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(Invoke([this, &total_bytes_received, all_frames_done](
-                           UnixSocket*, UnixSocket* srv_conn) {
-        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
-            .WillRepeatedly(
-                Invoke([&total_bytes_received, all_frames_done](UnixSocket* s) {
-                  char buf[1024];
-                  size_t res = s->Receive(buf, sizeof(buf));
-                  total_bytes_received += res;
-                  if (total_bytes_received == kTotalBytes)
-                    all_frames_done();
-                }));
-      }));
-
-  // Override default timeout as this test can take time on the emulator.
-  static constexpr int kTimeoutMs = 60000 * 3;
-
-  // Perform the blocking send form another thread.
-  std::thread tx_thread([] {
-    TestTaskRunner tx_task_runner;
-    MockEventListener tx_events;
-    auto cli =
-        UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
-                            kTestSocket.family(), SockType::kStream);
-
-    auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
-    EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
-        .WillOnce(InvokeWithoutArgs(cli_connected));
-    tx_task_runner.RunUntilCheckpoint("cli_connected");
-
-    auto all_sent = tx_task_runner.CreateCheckpoint("all_sent");
-    char buf[1024 * 32] = {};
-    tx_task_runner.PostTask([&cli, &buf, all_sent] {
-      for (size_t i = 0; i < kTotalBytes / sizeof(buf); i++)
-        cli->Send(buf, sizeof(buf));
-      all_sent();
-    });
-    tx_task_runner.RunUntilCheckpoint("all_sent", kTimeoutMs);
-  });
-
-  task_runner_.RunUntilCheckpoint("all_frames_done", kTimeoutMs);
-  tx_thread.join();
-}
-
-// Regression test for b/76155349 . If the receiver end disconnects while the
-// 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(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-  static constexpr int kTimeoutMs = 30000;
-
-  auto receive_done = task_runner_.CreateCheckpoint("receive_done");
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(Invoke([this, receive_done](UnixSocket*, UnixSocket* srv_conn) {
-        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
-            .WillOnce(Invoke([receive_done](UnixSocket* s) {
-              char buf[1024];
-              size_t res = s->Receive(buf, sizeof(buf));
-              ASSERT_EQ(1024u, res);
-              s->Shutdown(false /*notify*/);
-              receive_done();
-            }));
-      }));
-
-  // Perform the blocking send form another thread.
-  std::thread tx_thread([] {
-    TestTaskRunner tx_task_runner;
-    MockEventListener tx_events;
-    auto cli =
-        UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
-                            kTestSocket.family(), SockType::kStream);
-
-    auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
-    EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
-        .WillOnce(InvokeWithoutArgs(cli_connected));
-    tx_task_runner.RunUntilCheckpoint("cli_connected");
-
-    auto send_done = tx_task_runner.CreateCheckpoint("send_done");
-    static constexpr size_t kBufSize = 32 * 1024 * 1024;
-    std::unique_ptr<char[]> buf(new char[kBufSize]());
-    tx_task_runner.PostTask([&cli, &buf, send_done] {
-      cli->Send(buf.get(), kBufSize);
-      send_done();
-    });
-
-    tx_task_runner.RunUntilCheckpoint("send_done", kTimeoutMs);
-  });
-  task_runner_.RunUntilCheckpoint("receive_done", kTimeoutMs);
-  tx_thread.join();
-}
-
-TEST_F(UnixSocketTest, ReleaseSocket) {
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-  auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
-  UnixSocket* peer = nullptr;
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(
-          Invoke([srv_connected, &peer](UnixSocket*, UnixSocket* new_conn) {
-            peer = new_conn;
-            srv_connected();
-          }));
-
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
-  auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
-  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli_connected));
-  task_runner_.RunUntilCheckpoint("srv_connected");
-  task_runner_.RunUntilCheckpoint("cli_connected");
-  srv->Shutdown(true);
-
-  cli->Send("test");
-
-  ASSERT_NE(peer, nullptr);
-  auto raw_sock = peer->ReleaseSocket();
-
-  EXPECT_CALL(event_listener_, OnDataAvailable(_)).Times(0);
-  task_runner_.RunUntilIdle();
-
-  char buf[sizeof("test")];
-  ASSERT_TRUE(raw_sock);
-  ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)),
-            static_cast<ssize_t>(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"));
-      }));
-
-  for (size_t i = 0; i < kNumClients; i++) {
-    cli[i] = UnixSocket::Connect(host_and_port, &event_listener_, &task_runner_,
-                                 SockFamily::kInet, SockType::kStream);
-    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()));
-  }
-}
-
-// ---------------------------------
-// Posix-only tests below this point
-// ---------------------------------
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-// Tests the SockPeerCredMode::kIgnore logic.
-TEST_F(UnixSocketTest, IgnorePeerCredentials) {
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-  auto cli1_connected = task_runner_.CreateCheckpoint("cli1_connected");
-  auto cli1 = UnixSocket::Connect(kTestSocket.name(), &event_listener_,
-                                  &task_runner_, kTestSocket.family(),
-                                  SockType::kStream, SockPeerCredMode::kIgnore);
-  EXPECT_CALL(event_listener_, OnConnect(cli1.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli1_connected));
-
-  auto cli2_connected = task_runner_.CreateCheckpoint("cli2_connected");
-  auto cli2 = UnixSocket::Connect(
-      kTestSocket.name(), &event_listener_, &task_runner_, kTestSocket.family(),
-      SockType::kStream, SockPeerCredMode::kReadOnConnect);
-  EXPECT_CALL(event_listener_, OnConnect(cli2.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli2_connected));
-
-  task_runner_.RunUntilCheckpoint("cli1_connected");
-  task_runner_.RunUntilCheckpoint("cli2_connected");
-
-  ASSERT_EQ(cli1->peer_uid_posix(/*skip_check_for_testing=*/true), kInvalidUid);
-  ASSERT_EQ(cli2->peer_uid_posix(), geteuid());
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  ASSERT_EQ(cli1->peer_pid_linux(/*skip_check_for_testing=*/true), kInvalidPid);
-  ASSERT_EQ(cli2->peer_pid_linux(), getpid());
-#endif
-}
-
-// Checks that the peer_uid() is retained after the client disconnects. The IPC
-// layer needs to rely on this to validate messages received immediately before
-// a client disconnects.
-TEST_F(UnixSocketTest, PeerCredentialsRetainedAfterDisconnect) {
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
-  ASSERT_TRUE(srv->is_listening());
-  UnixSocket* srv_client_conn = nullptr;
-  auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .WillOnce(Invoke([&srv_client_conn, srv_connected](UnixSocket*,
-                                                         UnixSocket* srv_conn) {
-        srv_client_conn = srv_conn;
-        EXPECT_EQ(geteuid(), static_cast<uint32_t>(srv_conn->peer_uid_posix()));
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-        EXPECT_EQ(getpid(), static_cast<pid_t>(srv_conn->peer_pid_linux()));
-#endif
-        srv_connected();
-      }));
-  auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
-  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
-      .WillOnce(InvokeWithoutArgs(cli_connected));
-
-  task_runner_.RunUntilCheckpoint("cli_connected");
-  task_runner_.RunUntilCheckpoint("srv_connected");
-  ASSERT_NE(nullptr, srv_client_conn);
-  ASSERT_TRUE(srv_client_conn->is_connected());
-
-  auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
-  EXPECT_CALL(event_listener_, OnDisconnect(srv_client_conn))
-      .WillOnce(InvokeWithoutArgs(cli_disconnected));
-
-  // TODO(primiano): when the a peer disconnects, the other end receives a
-  // spurious OnDataAvailable() that needs to be acked with a Receive() to read
-  // the EOF. See b/69536434.
-  EXPECT_CALL(event_listener_, OnDataAvailable(srv_client_conn))
-      .WillOnce(Invoke([](UnixSocket* sock) { sock->ReceiveString(); }));
-
-  cli.reset();
-  task_runner_.RunUntilCheckpoint("cli_disconnected");
-  ASSERT_FALSE(srv_client_conn->is_connected());
-  EXPECT_EQ(geteuid(),
-            static_cast<uint32_t>(srv_client_conn->peer_uid_posix()));
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  EXPECT_EQ(getpid(), static_cast<pid_t>(srv_client_conn->peer_pid_linux()));
-#endif
-}
+constexpr char cli_str[] = "cli>srv";
+constexpr char srv_str[] = "srv>cli";
 
 TEST_F(UnixSocketTest, ClientAndServerExchangeFDs) {
-  static constexpr char cli_str[] = "cli>srv";
-  static constexpr char srv_str[] = "srv>cli";
-  auto srv =
-      UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                         kTestSocket.family(), SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                SockFamily::kUnix, SockType::kStream);
   ASSERT_TRUE(srv->is_listening());
 
-  auto cli =
-      UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                          kTestSocket.family(), SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
   auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
@@ -650,6 +271,79 @@
   task_runner_.RunUntilCheckpoint("cli_disconnected");
 }
 
+TEST_F(UnixSocketTest, ListenWithPassedFileDescriptor) {
+  auto sock_raw =
+      UnixSocketRaw::CreateMayFail(SockFamily::kUnix, 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);
+  ASSERT_TRUE(srv->is_listening());
+
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
+  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
+  auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
+  auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke([this, cli_connected, srv_disconnected](
+                           UnixSocket*, UnixSocket* srv_conn) {
+        // Read the EOF state.
+        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
+            .WillOnce(
+                InvokeWithoutArgs([srv_conn] { srv_conn->ReceiveString(); }));
+        EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
+            .WillOnce(InvokeWithoutArgs(srv_disconnected));
+        cli_connected();
+      }));
+  task_runner_.RunUntilCheckpoint("cli_connected");
+  ASSERT_TRUE(cli->is_connected());
+  cli.reset();
+  task_runner_.RunUntilCheckpoint("srv_disconnected");
+}
+
+// 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);
+  ASSERT_TRUE(srv->is_listening());
+  constexpr size_t kNumClients = 32;
+  std::unique_ptr<UnixSocket> cli[kNumClients];
+
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .Times(kNumClients)
+      .WillRepeatedly(Invoke([this](UnixSocket*, UnixSocket* s) {
+        EXPECT_CALL(event_listener_, OnDataAvailable(s))
+            .WillOnce(Invoke([](UnixSocket* t) {
+              ASSERT_EQ("PING", t->ReceiveString());
+              ASSERT_TRUE(t->Send("PONG"));
+            }));
+      }));
+
+  for (size_t i = 0; i < kNumClients; i++) {
+    cli[i] = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
+    EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true))
+        .WillOnce(Invoke([](UnixSocket* s, bool success) {
+          ASSERT_TRUE(success);
+          ASSERT_TRUE(s->Send("PING"));
+        }));
+
+    auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
+    EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
+        .WillOnce(Invoke([checkpoint](UnixSocket* s) {
+          ASSERT_EQ("PONG", s->ReceiveString());
+          checkpoint();
+        }));
+  }
+
+  for (size_t i = 0; i < kNumClients; i++) {
+    task_runner_.RunUntilCheckpoint(std::to_string(i));
+    ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
+  }
+}
+
 // Creates two processes. The server process creates a file and passes it over
 // the socket to the client. Both processes mmap the file in shared mode and
 // check that they see the same contents.
@@ -669,9 +363,8 @@
     ASSERT_NE(nullptr, mem);
     memcpy(mem, "shm rocks", 10);
 
-    auto srv =
-        UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
-                           kTestSocket.family(), SockType::kStream);
+    auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                  SockFamily::kUnix, SockType::kStream);
     ASSERT_TRUE(srv->is_listening());
     // Signal the other process that it can connect.
     ASSERT_EQ(1, base::WriteAll(*pipe.wr, ".", 1));
@@ -679,8 +372,7 @@
     EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
         .WillOnce(Invoke(
             [this, tmp_fd, checkpoint, mem](UnixSocket*, UnixSocket* new_conn) {
-              ASSERT_EQ(geteuid(),
-                        static_cast<uint32_t>(new_conn->peer_uid_posix()));
+              ASSERT_EQ(geteuid(), static_cast<uint32_t>(new_conn->peer_uid()));
               ASSERT_TRUE(new_conn->Send("txfd", 5, tmp_fd));
               // Wait for the client to change this again.
               EXPECT_CALL(event_listener_, OnDataAvailable(new_conn))
@@ -697,9 +389,8 @@
     char sync_cmd = '\0';
     ASSERT_EQ(1, PERFETTO_EINTR(read(*pipe.rd, &sync_cmd, 1)));
     ASSERT_EQ('.', sync_cmd);
-    auto cli =
-        UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
-                            kTestSocket.family(), SockType::kStream);
+    auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                   SockFamily::kUnix, SockType::kStream);
     EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
     auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_client");
     EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
@@ -729,6 +420,158 @@
   }
 }
 
+// Checks that the peer_uid() is retained after the client disconnects. The IPC
+// 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);
+  ASSERT_TRUE(srv->is_listening());
+  UnixSocket* srv_client_conn = nullptr;
+  auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke(
+          [&srv_client_conn, srv_connected](UnixSocket*, UnixSocket* srv_conn) {
+            srv_client_conn = srv_conn;
+            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()));
+#endif
+            srv_connected();
+          }));
+  auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
+  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
+      .WillOnce(InvokeWithoutArgs(cli_connected));
+
+  task_runner_.RunUntilCheckpoint("cli_connected");
+  task_runner_.RunUntilCheckpoint("srv_connected");
+  ASSERT_NE(nullptr, srv_client_conn);
+  ASSERT_TRUE(srv_client_conn->is_connected());
+
+  auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
+  EXPECT_CALL(event_listener_, OnDisconnect(srv_client_conn))
+      .WillOnce(InvokeWithoutArgs(cli_disconnected));
+
+  // TODO(primiano): when the a peer disconnects, the other end receives a
+  // spurious OnDataAvailable() that needs to be acked with a Receive() to read
+  // the EOF. See b/69536434.
+  EXPECT_CALL(event_listener_, OnDataAvailable(srv_client_conn))
+      .WillOnce(Invoke([](UnixSocket* sock) { sock->ReceiveString(); }));
+
+  cli.reset();
+  task_runner_.RunUntilCheckpoint("cli_disconnected");
+  ASSERT_FALSE(srv_client_conn->is_connected());
+  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()));
+#endif
+}
+
+TEST_F(UnixSocketTest, BlockingSend) {
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                SockFamily::kUnix, SockType::kStream);
+  ASSERT_TRUE(srv->is_listening());
+
+  auto all_frames_done = task_runner_.CreateCheckpoint("all_frames_done");
+  size_t total_bytes_received = 0;
+  constexpr size_t kTotalBytes = 1024 * 1024 * 4;
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke([this, &total_bytes_received, all_frames_done](
+                           UnixSocket*, UnixSocket* srv_conn) {
+        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
+            .WillRepeatedly(
+                Invoke([&total_bytes_received, all_frames_done](UnixSocket* s) {
+                  char buf[1024];
+                  size_t res = s->Receive(buf, sizeof(buf));
+                  total_bytes_received += res;
+                  if (total_bytes_received == kTotalBytes)
+                    all_frames_done();
+                }));
+      }));
+
+  // Override default timeout as this test can take time on the emulator.
+  const int kTimeoutMs = 60000 * 3;
+
+  // Perform the blocking send form another thread.
+  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_connected = tx_task_runner.CreateCheckpoint("cli_connected");
+    EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
+        .WillOnce(InvokeWithoutArgs(cli_connected));
+    tx_task_runner.RunUntilCheckpoint("cli_connected");
+
+    auto all_sent = tx_task_runner.CreateCheckpoint("all_sent");
+    char buf[1024 * 32] = {};
+    tx_task_runner.PostTask([&cli, &buf, all_sent] {
+      for (size_t i = 0; i < kTotalBytes / sizeof(buf); i++)
+        cli->Send(buf, sizeof(buf));
+      all_sent();
+    });
+    tx_task_runner.RunUntilCheckpoint("all_sent", kTimeoutMs);
+  });
+
+  task_runner_.RunUntilCheckpoint("all_frames_done", kTimeoutMs);
+  tx_thread.join();
+}
+
+// Regression test for b/76155349 . If the receiver end disconnects while the
+// 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);
+  ASSERT_TRUE(srv->is_listening());
+  const int kTimeoutMs = 30000;
+
+  auto receive_done = task_runner_.CreateCheckpoint("receive_done");
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke([this, receive_done](UnixSocket*, UnixSocket* srv_conn) {
+        EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
+            .WillOnce(Invoke([receive_done](UnixSocket* s) {
+              char buf[1024];
+              size_t res = s->Receive(buf, sizeof(buf));
+              ASSERT_EQ(1024u, res);
+              s->Shutdown(false /*notify*/);
+              receive_done();
+            }));
+      }));
+
+  // Perform the blocking send form another thread.
+  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_connected = tx_task_runner.CreateCheckpoint("cli_connected");
+    EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
+        .WillOnce(InvokeWithoutArgs(cli_connected));
+    tx_task_runner.RunUntilCheckpoint("cli_connected");
+
+    auto send_done = tx_task_runner.CreateCheckpoint("send_done");
+    // We need a
+    static constexpr size_t kBufSize = 32 * 1024 * 1024;
+    std::unique_ptr<char[]> buf(new char[kBufSize]());
+    tx_task_runner.PostTask([&cli, &buf, send_done] {
+      bool send_res = cli->Send(buf.get(), kBufSize);
+      ASSERT_FALSE(send_res);
+      send_done();
+    });
+
+    tx_task_runner.RunUntilCheckpoint("send_done", kTimeoutMs);
+  });
+  task_runner_.RunUntilCheckpoint("receive_done", kTimeoutMs);
+  tx_thread.join();
+}
+
 TEST_F(UnixSocketTest, ShiftMsgHdrSendPartialFirst) {
   // Send a part of the first iov, then send the rest.
   struct iovec iov[2] = {};
@@ -744,7 +587,7 @@
   hdr.msg_iov = iov;
   hdr.msg_iovlen = base::ArraySize(iov);
 
-  UnixSocketRaw::ShiftMsgHdrPosix(1, &hdr);
+  UnixSocketRaw::ShiftMsgHdr(1, &hdr);
   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]);
@@ -752,13 +595,13 @@
   EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "ello");
   EXPECT_EQ(iov[0].iov_len, base::ArraySize(hello) - 1);
 
-  UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) - 1, &hdr);
+  UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) - 1, &hdr);
   EXPECT_EQ(hdr.msg_iov, &iov[1]);
   EXPECT_EQ(static_cast<int>(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::ShiftMsgHdrPosix(base::ArraySize(world), &hdr);
+  UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world), &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
   EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
 }
@@ -778,13 +621,13 @@
   hdr.msg_iov = iov;
   hdr.msg_iovlen = base::ArraySize(iov);
 
-  UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) + 1, &hdr);
+  UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) + 1, &hdr);
   EXPECT_NE(hdr.msg_iov, nullptr);
   EXPECT_EQ(static_cast<int>(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::ShiftMsgHdrPosix(base::ArraySize(world) - 1, &hdr);
+  UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) - 1, &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
   EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
 }
@@ -804,13 +647,14 @@
   hdr.msg_iov = iov;
   hdr.msg_iovlen = base::ArraySize(iov);
 
-  UnixSocketRaw::ShiftMsgHdrPosix(
-      base::ArraySize(world) + base::ArraySize(hello), &hdr);
+  UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) + base::ArraySize(hello),
+                             &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
   EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
 }
 
-// For use in PartialSendMsgAll template argument. Cannot be a lambda.
+void Handler(int) {}
+
 int RollbackSigaction(const struct sigaction* act) {
   return sigaction(SIGWINCH, act, nullptr);
 }
@@ -819,7 +663,7 @@
   UnixSocketRaw send_sock;
   UnixSocketRaw recv_sock;
   std::tie(send_sock, recv_sock) =
-      UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
+      UnixSocketRaw::CreatePair(SockFamily::kUnix, SockType::kStream);
   ASSERT_TRUE(send_sock);
   ASSERT_TRUE(recv_sock);
 
@@ -848,7 +692,7 @@
   //   this action will affect the whole process.
   struct sigaction oldact;
   struct sigaction newact = {};
-  newact.sa_handler = [](int) {};
+  newact.sa_handler = Handler;
   ASSERT_EQ(sigaction(SIGWINCH, &newact, &oldact), 0);
   base::ScopedResource<const struct sigaction*, RollbackSigaction, nullptr>
       rollback(&oldact);
@@ -859,7 +703,7 @@
     ASSERT_EQ(rd, 1);
     // We are now sure the other thread is in sendmsg, interrupt send.
     ASSERT_EQ(pthread_kill(blocked_thread, SIGWINCH), 0);
-    // Drain the socket to allow SendMsgAllPosix to succeed.
+    // Drain the socket to allow SendMsgAll to succeed.
     size_t offset = 1;
     while (offset < sizeof(recv_buf)) {
       rd = PERFETTO_EINTR(
@@ -870,7 +714,7 @@
   });
 
   // Test sending the send_buf in several chunks as an iov to exercise the
-  // more complicated code-paths of SendMsgAllPosix.
+  // more complicated code-paths of SendMsgAll.
   struct msghdr hdr = {};
   struct iovec iov[4];
   static_assert(sizeof(send_buf) % base::ArraySize(iov) == 0,
@@ -883,15 +727,110 @@
   hdr.msg_iov = iov;
   hdr.msg_iovlen = base::ArraySize(iov);
 
-  ASSERT_EQ(send_sock.SendMsgAllPosix(&hdr),
-            static_cast<ssize_t>(sizeof(send_buf)));
+  ASSERT_EQ(send_sock.SendMsgAll(&hdr), static_cast<ssize_t>(sizeof(send_buf)));
   send_sock.Shutdown();
   th.join();
   // Make sure the re-entry logic was actually triggered.
   ASSERT_EQ(hdr.msg_iov, nullptr);
   ASSERT_EQ(memcmp(send_buf, recv_buf, sizeof(send_buf)), 0);
 }
-#endif  // !OS_WIN
+
+TEST_F(UnixSocketTest, ReleaseSocket) {
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
+                                SockFamily::kUnix, SockType::kStream);
+  ASSERT_TRUE(srv->is_listening());
+  auto connected = task_runner_.CreateCheckpoint("connected");
+  UnixSocket* peer = nullptr;
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke([connected, &peer](UnixSocket*, UnixSocket* new_conn) {
+        peer = new_conn;
+        connected();
+      }));
+
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
+                                 SockFamily::kUnix, SockType::kStream);
+  EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
+  task_runner_.RunUntilCheckpoint("connected");
+  srv->Shutdown(true);
+
+  cli->Send("test");
+
+  ASSERT_NE(peer, nullptr);
+  auto raw_sock = peer->ReleaseSocket();
+
+  EXPECT_CALL(event_listener_, OnDataAvailable(_)).Times(0);
+  task_runner_.RunUntilIdle();
+
+  char buf[sizeof("test")];
+  ASSERT_TRUE(raw_sock);
+  ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)),
+            static_cast<ssize_t>(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"));
+      }));
+
+  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.
+
+// TODO(primiano); add a test to check that a socket can be reused after
+// Shutdown(),
+
+// TODO(primiano): add a test to check that OnDisconnect() is called in all
+// possible cases.
+
+// TODO(primiano): add tests that destroy the socket in all possible stages and
+// verify that no spurious EventListener callback is received.
 
 }  // namespace
 }  // namespace base
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index f6b6c19..422947f 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -15,20 +15,14 @@
  */
 
 #include "perfetto/base/build_config.h"
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
 #include "perfetto/ext/base/unix_task_runner.h"
 
 #include <errno.h>
 #include <stdlib.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <synchapi.h>
-#else
 #include <unistd.h>
-#endif
 
-#include <algorithm>
 #include <limits>
 
 #include "perfetto/ext/base/watchdog.h"
@@ -62,29 +56,13 @@
       poll_timeout_ms = GetDelayMsToNextTaskLocked();
       UpdateWatchTasksLocked();
     }
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    DWORD timeout =
-        poll_timeout_ms >= 0 ? static_cast<DWORD>(poll_timeout_ms) : INFINITE;
-    DWORD ret =
-        WaitForMultipleObjects(static_cast<DWORD>(poll_fds_.size()),
-                               &poll_fds_[0], /*bWaitAll=*/false, timeout);
-    // Unlike poll(2), WaitForMultipleObjects() returns only *one* handle in the
-    // set, even when >1 is signalled. In order to avoid starvation,
-    // PostFileDescriptorWatches() will WaitForSingleObject() each other handle
-    // to ensure fairness. |ret| here is passed just to avoid an extra
-    // WaitForSingleObject() for the one handle that WaitForMultipleObject()
-    // returned.
-    PostFileDescriptorWatches(ret);
-#else
     int ret = PERFETTO_EINTR(poll(
         &poll_fds_[0], static_cast<nfds_t>(poll_fds_.size()), poll_timeout_ms));
     PERFETTO_CHECK(ret >= 0);
-    PostFileDescriptorWatches(0 /*ignored*/);
-#endif
 
     // To avoid starvation we always interleave all types of tasks -- immediate,
     // delayed and file descriptor watches.
+    PostFileDescriptorWatches();
     RunImmediateAndDelayedTask();
   }
 }
@@ -107,22 +85,13 @@
 
 void UnixTaskRunner::UpdateWatchTasksLocked() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   if (!watch_tasks_changed_)
     return;
   watch_tasks_changed_ = false;
-#endif
   poll_fds_.clear();
   for (auto& it : watch_tasks_) {
-    PlatformHandle handle = it.first;
-    WatchTask& watch_task = it.second;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    if (!watch_task.pending)
-      poll_fds_.push_back(handle);
-#else
-    watch_task.poll_fd_index = poll_fds_.size();
-    poll_fds_.push_back({handle, POLLIN | POLLHUP, 0});
-#endif
+    it.second.poll_fd_index = poll_fds_.size();
+    poll_fds_.push_back({it.first, POLLIN | POLLHUP, 0});
   }
 }
 
@@ -154,81 +123,47 @@
     RunTaskWithWatchdogGuard(delayed_task);
 }
 
-void UnixTaskRunner::PostFileDescriptorWatches(uint64_t windows_wait_result) {
+void UnixTaskRunner::PostFileDescriptorWatches() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   for (size_t i = 0; i < poll_fds_.size(); i++) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    const PlatformHandle handle = poll_fds_[i];
-    // |windows_wait_result| is the result of WaitForMultipleObjects() call. If
-    // one of the objects was signalled, it will have a value between
-    // [0, poll_fds_.size()].
-    if (i != windows_wait_result &&
-        WaitForSingleObject(handle, 0) != WAIT_OBJECT_0) {
-      continue;
-    }
-#else
-    base::ignore_result(windows_wait_result);
-    const PlatformHandle handle = poll_fds_[i].fd;
     if (!(poll_fds_[i].revents & (POLLIN | POLLHUP)))
       continue;
     poll_fds_[i].revents = 0;
-#endif
 
     // The wake-up event is handled inline to avoid an infinite recursion of
     // posted tasks.
-    if (handle == event_.fd()) {
+    if (poll_fds_[i].fd == event_.fd()) {
       event_.Clear();
       continue;
     }
 
     // Binding to |this| is safe since we are the only object executing the
     // task.
-    PostTask(std::bind(&UnixTaskRunner::RunFileDescriptorWatch, this, handle));
+    PostTask(std::bind(&UnixTaskRunner::RunFileDescriptorWatch, this,
+                       poll_fds_[i].fd));
 
-    // Flag the task as pending.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    // On Windows this is done by marking the WatchTask entry as pending. This
-    // is more expensive than Linux as requires rebuilding the |poll_fds_|
-    // vector on each call. There doesn't seem to be a good alternative though.
-    auto it = watch_tasks_.find(handle);
-    PERFETTO_CHECK(it != watch_tasks_.end());
-    PERFETTO_DCHECK(!it->second.pending);
-    it->second.pending = true;
-#else
-    // On UNIX systems instead, we just make the fd negative while its task is
-    // pending. This makes poll(2) ignore the fd.
+    // Make the fd negative while a posted task is pending. This makes poll(2)
+    // ignore the fd.
     PERFETTO_DCHECK(poll_fds_[i].fd >= 0);
     poll_fds_[i].fd = -poll_fds_[i].fd;
-#endif
   }
 }
 
-void UnixTaskRunner::RunFileDescriptorWatch(PlatformHandle fd) {
+void UnixTaskRunner::RunFileDescriptorWatch(int fd) {
   std::function<void()> task;
   {
     std::lock_guard<std::mutex> lock(lock_);
     auto it = watch_tasks_.find(fd);
     if (it == watch_tasks_.end())
       return;
-    WatchTask& watch_task = it->second;
-
     // Make poll(2) pay attention to the fd again. Since another thread may have
     // updated this watch we need to refresh the set first.
     UpdateWatchTasksLocked();
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    // On Windows we manually track the presence of outstanding tasks for the
-    // watch. The UpdateWatchTasksLocked() in the Run() loop will re-add the
-    // task to the |poll_fds_| vector.
-    PERFETTO_DCHECK(watch_task.pending);
-    watch_task.pending = false;
-#else
-    size_t fd_index = watch_task.poll_fd_index;
+    size_t fd_index = it->second.poll_fd_index;
     PERFETTO_DCHECK(fd_index < poll_fds_.size());
     PERFETTO_DCHECK(::abs(poll_fds_[fd_index].fd) == fd);
     poll_fds_[fd_index].fd = fd;
-#endif
-    task = watch_task.callback;
+    task = it->second.callback;
   }
   errno = 0;
   RunTaskWithWatchdogGuard(task);
@@ -266,26 +201,20 @@
   WakeUp();
 }
 
-void UnixTaskRunner::AddFileDescriptorWatch(PlatformHandle fd,
+void UnixTaskRunner::AddFileDescriptorWatch(int fd,
                                             std::function<void()> task) {
-  PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
+  PERFETTO_DCHECK(fd >= 0);
   {
     std::lock_guard<std::mutex> lock(lock_);
     PERFETTO_DCHECK(!watch_tasks_.count(fd));
-    WatchTask& watch_task = watch_tasks_[fd];
-    watch_task.callback = std::move(task);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    watch_task.pending = false;
-#else
-    watch_task.poll_fd_index = SIZE_MAX;
-#endif
+    watch_tasks_[fd] = {std::move(task), SIZE_MAX};
     watch_tasks_changed_ = true;
   }
   WakeUp();
 }
 
-void UnixTaskRunner::RemoveFileDescriptorWatch(PlatformHandle fd) {
-  PERFETTO_DCHECK(PlatformHandleChecker::IsValid(fd));
+void UnixTaskRunner::RemoveFileDescriptorWatch(int fd) {
+  PERFETTO_DCHECK(fd >= 0);
   {
     std::lock_guard<std::mutex> lock(lock_);
     PERFETTO_DCHECK(watch_tasks_.count(fd));
@@ -301,3 +230,5 @@
 
 }  // namespace base
 }  // namespace perfetto
+
+#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/utils.cc b/src/base/utils.cc
deleted file mode 100644
index d5bd5a0..0000000
--- a/src/base/utils.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/utils.h"
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-#include <unistd.h>  // For getpagesize() and geteuid() & fork()
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-#include <mach/vm_page_size.h>
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <dlfcn.h>
-#include <malloc.h>
-
-#ifdef M_PURGE
-#define PERFETTO_M_PURGE M_PURGE
-#else
-// Only available in in-tree builds and on newer SDKs.
-#define PERFETTO_M_PURGE -101
-#endif
-
-namespace {
-extern "C" {
-using MalloptType = void (*)(int, int);
-}
-}  // namespace
-#endif  // OS_ANDROID
-
-namespace perfetto {
-namespace base {
-
-void MaybeReleaseAllocatorMemToOS() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  // mallopt() on Android requires SDK level 26. Many targets and embedders
-  // still depend on a lower SDK level. Given mallopt() is a quite simple API,
-  // use reflection to do this rather than bumping the SDK level for all
-  // embedders. This keeps the behavior of standalone builds aligned with
-  // in-tree builds.
-  static MalloptType mallopt_fn =
-      reinterpret_cast<MalloptType>(dlsym(RTLD_DEFAULT, "mallopt"));
-  if (!mallopt_fn)
-    return;
-  mallopt_fn(PERFETTO_M_PURGE, 0);
-#endif
-}
-
-uint32_t GetSysPageSize() {
-  ignore_result(kPageSize);  // Just to keep the amalgamated build happy.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  static std::atomic<uint32_t> page_size{0};
-  // This function might be called in hot paths. Avoid calling getpagesize() all
-  // the times, in many implementations getpagesize() calls sysconf() which is
-  // not cheap.
-  uint32_t cached_value = page_size.load(std::memory_order_relaxed);
-  if (PERFETTO_UNLIKELY(cached_value == 0)) {
-    cached_value = static_cast<uint32_t>(getpagesize());
-    page_size.store(cached_value, std::memory_order_relaxed);
-  }
-  return cached_value;
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-  return static_cast<uint32_t>(vm_page_size);
-#else
-  return 4096;
-#endif
-}
-
-uid_t GetCurrentUserId() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-  return geteuid();
-#else
-  // TODO(primiano): On Windows we could hash the current user SID and derive a
-  // numeric user id [1]. It is not clear whether we need that. Right now that
-  // would not bring any benefit. Returning 0 unil we can prove we need it.
-  // [1]:https://android-review.googlesource.com/c/platform/external/perfetto/+/1513879/25/src/base/utils.cc
-  return 0;
-#endif
-}
-
-void SetEnv(const std::string& key, const std::string& value) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  PERFETTO_CHECK(::_putenv_s(key.c_str(), value.c_str()) == 0);
-#else
-  PERFETTO_CHECK(::setenv(key.c_str(), value.c_str(), /*overwrite=*/true) == 0);
-#endif
-}
-
-void Daemonize() {
-   #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-       PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-       PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-      pid_t pid;
-      switch (pid = fork()) {
-        case -1:
-          PERFETTO_FATAL("fork");
-        case 0: {
-          PERFETTO_CHECK(setsid() != -1);
-          base::ignore_result(chdir("/"));
-          base::ScopedFile null = base::OpenFile("/dev/null", O_RDONLY);
-          PERFETTO_CHECK(null);
-          PERFETTO_CHECK(dup2(*null, STDIN_FILENO) != -1);
-          PERFETTO_CHECK(dup2(*null, STDOUT_FILENO) != -1);
-          PERFETTO_CHECK(dup2(*null, STDERR_FILENO) != -1);
-          // Do not accidentally close stdin/stdout/stderr.
-          if (*null <= 2)
-            null.release();
-          break;
-        }
-        default:
-          printf("%d\n", pid);
-          exit(0);
-      }
-  #else
-    // Avoid -Wunreachable warnings.
-    if (reinterpret_cast<intptr_t>(&Daemonize) != 16)
-      PERFETTO_FATAL("--background is only supported on Linux/Android/Mac");
-  #endif  // OS_WIN
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/utils_unittest.cc b/src/base/utils_unittest.cc
index ef6e657..eade8f7 100644
--- a/src/base/utils_unittest.cc
+++ b/src/base/utils_unittest.cc
@@ -16,25 +16,13 @@
 
 #include "perfetto/ext/base/utils.h"
 
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#else
 #include <fcntl.h>
 #include <signal.h>
-#include <unistd.h>
-#endif
-
 #include <stdint.h>
-
-#include <algorithm>
-#include <random>
-#include <thread>
+#include <unistd.h>
 
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/temp_file.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
@@ -70,82 +58,9 @@
   EXPECT_EQ(4u, ArraySize(bar_4));
 }
 
-TEST(UtilsTest, PipeBlockingRW) {
-  Pipe pipe = Pipe::Create();
-  std::string expected;
-  expected.resize(1024 * 512u);
-  for (size_t i = 0; i < expected.size(); i++)
-    expected[i] = '!' + static_cast<char>(i % 64);
-
-  std::thread writer([&] {
-    std::string tx = expected;
-    std::minstd_rand0 rnd_engine(0);
-
-    while (!tx.empty()) {
-      size_t wsize = static_cast<size_t>(rnd_engine() % 4096) + 1;
-      wsize = std::min(wsize, tx.size());
-      WriteAllHandle(*pipe.wr, &tx[0], wsize);
-      tx.erase(0, wsize);
-    }
-    pipe.wr.reset();
-  });
-
-  std::string actual;
-  ASSERT_TRUE(ReadPlatformHandle(*pipe.rd, &actual));
-  ASSERT_EQ(actual, expected);
-  writer.join();
-}
-
-// Tests that WriteAllHandle and ReadPlatformHandle work as advertised.
-// TODO(primiano): normalize File handling on Windows. Right now some places
-// use POSIX-compat APIs that use "int" file descriptors (_open, _read, _write),
-// some other places use WINAPI files (CreateFile(), ReadFile()), where the file
-// is a HANDLE.
-TEST(UtilsTest, ReadWritePlatformHandle) {
-  auto tmp = TempDir::Create();
-  std::string payload = "foo\nbar\0baz\r\nqux";
-  std::string tmp_path = tmp.path() + "/temp.txt";
-
-  // Write a file using PlatformHandle. Note: the {} blocks are to make sure
-  // that the file is automatically closed via RAII before being reopened.
-  {
-    ScopedPlatformHandle handle {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-      ::CreateFileA(tmp_path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
-                    FILE_ATTRIBUTE_NORMAL, nullptr)
-#else
-      OpenFile(tmp_path, O_WRONLY | O_CREAT | O_TRUNC, 0644)
-#endif
-    };
-    ASSERT_TRUE(handle);
-    ASSERT_EQ(WriteAllHandle(*handle, payload.data(), payload.size()),
-              static_cast<ssize_t>(payload.size()));
-  }
-
-  // Read it back.
-  {
-    ScopedPlatformHandle handle {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-      ::CreateFileA(tmp_path.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING,
-                    FILE_ATTRIBUTE_NORMAL, nullptr)
-#else
-      OpenFile(tmp_path, O_RDONLY)
-#endif
-    };
-    ASSERT_TRUE(handle);
-    std::string actual = "preserve_existing:";
-    ASSERT_TRUE(ReadPlatformHandle(*handle, &actual));
-    ASSERT_EQ(actual, "preserve_existing:" + payload);
-  }
-
-  ASSERT_EQ(remove(tmp_path.c_str()), 0);
-}
-
 // Fuchsia doesn't currently support sigaction(), see
 // fuchsia.atlassian.net/browse/ZX-560.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
 TEST(UtilsTest, EintrWrapper) {
   Pipe pipe = Pipe::Create();
 
@@ -186,7 +101,7 @@
   // Restore the old handler.
   sigaction(SIGUSR2, &old_sa, nullptr);
 }
-#endif  // LINUX | ANDROID | APPLE
+#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
 
 TEST(UtilsTest, Align) {
   EXPECT_EQ(0u, AlignUp<4>(0));
diff --git a/src/base/version.cc b/src/base/version.cc
deleted file mode 100644
index 18569d3..0000000
--- a/src/base/version.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/base/version.h"
-
-#include "perfetto/base/build_config.h"
-
-#include <stdio.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
-#include "perfetto_version.gen.h"
-#else
-#define PERFETTO_VERSION_STRING() "v0.0"
-#define PERFETTO_VERSION_SCM_REVISION() "unknown"
-#endif
-
-namespace perfetto {
-namespace base {
-
-const char* GetVersionString() {
-  static const char* version_str = [] {
-    static constexpr size_t kMaxLen = 256;
-    char* version = new char[kMaxLen + 1];
-    snprintf(version, kMaxLen, "Perfetto %s (%s)", PERFETTO_VERSION_STRING(),
-             PERFETTO_VERSION_SCM_REVISION());
-    return version;
-  }();
-  return version_str;
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index fea7cd9..2f251b7 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -29,9 +29,7 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/thread_utils.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 namespace base {
@@ -72,7 +70,7 @@
   c[c_pos] = '\0';
 
   if (sscanf(c,
-             "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu "
+             "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu"
              "%lu %*d %*d %*d %*d %*d %*d %*u %*u %ld",
              &out->utime, &out->stime, &out->rss_pages) != 3) {
     PERFETTO_ELOG("Invalid stat format: %s", c);
@@ -169,7 +167,7 @@
 
     uint64_t cpu_time = stat.utime + stat.stime;
     uint64_t rss_bytes =
-        static_cast<uint64_t>(stat.rss_pages) * base::GetSysPageSize();
+        static_cast<uint64_t>(stat.rss_pages) * base::kPageSize;
 
     CheckMemory(rss_bytes);
     CheckCpu(cpu_time);
@@ -254,27 +252,25 @@
     return;  // No-op timer created when the watchdog is disabled.
 
   struct sigevent sev = {};
-  timer_t timerid;
   sev.sigev_notify = SIGEV_THREAD_ID;
   sev._sigev_un._tid = base::GetThreadId();
   sev.sigev_signo = SIGABRT;
-  PERFETTO_CHECK(timer_create(CLOCK_MONOTONIC, &sev, &timerid) != -1);
-  timerid_ = base::make_optional(timerid);
+  PERFETTO_CHECK(timer_create(CLOCK_MONOTONIC, &sev, &timerid_) != -1);
   struct itimerspec its = {};
   its.it_value.tv_sec = ms / 1000;
   its.it_value.tv_nsec = 1000000L * (ms % 1000);
-  PERFETTO_CHECK(timer_settime(timerid_.value(), 0, &its, nullptr) != -1);
+  PERFETTO_CHECK(timer_settime(timerid_, 0, &its, nullptr) != -1);
 }
 
 Watchdog::Timer::~Timer() {
-  if (timerid_) {
-    timer_delete(timerid_.value());
+  if (timerid_ != nullptr) {
+    timer_delete(timerid_);
   }
 }
 
 Watchdog::Timer::Timer(Timer&& other) noexcept {
-  timerid_ = std::move(other.timerid_);
-  other.timerid_ = base::nullopt;
+  timerid_ = other.timerid_;
+  other.timerid_ = nullptr;
 }
 
 }  // namespace base
diff --git a/src/base/watchdog_posix_unittest.cc b/src/base/watchdog_posix_unittest.cc
deleted file mode 100644
index 52bd49d..0000000
--- a/src/base/watchdog_posix_unittest.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
-
-#include "perfetto/ext/base/watchdog_posix.h"
-
-#include <stdio.h>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace base {
-namespace {
-
-TEST(WatchdogPosixTest, ParseProcStat) {
-  constexpr const char stat[] =
-      "2965981 (zsh) S 2965977 2965981 2965981 34822 2966607 4194304 6632 6697 "
-      "0 0 11 6 4 1 20 0 1 0 227163466 15839232 2311 18446744073709551615 "
-      "94823961161728 94823961762781 140722993535472 0 0 0 2 3686400 134295555 "
-      "0 0 0 17 2 0 0 0 0 0 94823961905904 94823961935208 94823993954304 "
-      "140722993543678 140722993543691 140722993543691 140722993545195 0";
-  TempFile f = TempFile::CreateUnlinked();
-  WriteAll(f.fd(), stat, sizeof(stat));
-  ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
-  ProcStat ps;
-  ASSERT_TRUE(ReadProcStat(f.fd(), &ps));
-  EXPECT_EQ(ps.utime, 11u);
-  EXPECT_EQ(ps.stime, 6u);
-  EXPECT_EQ(ps.rss_pages, 2311);
-}
-
-}  // namespace
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index 39843f1..d8ee2b4 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -14,7 +14,6 @@
 
 import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_component.gni")
 import("../../gn/proto_library.gni")
 import("../../gn/test.gni")
 
@@ -22,15 +21,6 @@
 # projects should be depending on our IPC layer.
 assert(enable_perfetto_ipc)
 
-if (perfetto_component_type == "static_library") {
-  # In build generators everything else outside should just depend on the
-  # :perfetto_ipc static library (at the end of this file) rather than
-  # individual sub-targets.
-  _ipc_visibility = [ ":*" ]  # Only targets defined in this file.
-} else {
-  _ipc_visibility = [ "*" ]  # Default visibility.
-}
-
 source_set("client") {
   public_deps = [
     "../../include/perfetto/ext/ipc",
@@ -47,7 +37,6 @@
     "client_impl.h",
     "service_proxy.cc",
   ]
-  visibility = _ipc_visibility
 }
 
 source_set("host") {
@@ -65,7 +54,6 @@
     "host_impl.cc",
     "host_impl.h",
   ]
-  visibility = _ipc_visibility
 }
 
 source_set("common") {
@@ -83,7 +71,6 @@
     "deferred.cc",
     "virtual_destructors.cc",
   ]
-  visibility = _ipc_visibility
 }
 
 perfetto_fuzzer_test("buffered_frame_deserializer_fuzzer") {
@@ -132,14 +119,10 @@
   ]
 }
 
-# This is used by Bazel BUILD rules. The problem it solves is the following:
-# In GN builds we want to keep client and host separate. This allows reducing
-# the binary size by splitting targets all the way up to the client library
-# (libperfetto_client_experimental). In bazel/blaze we fuse everything together
-# because handling this split is too complex due to the lack of a
-# source_set-equivalent.
-perfetto_component("perfetto_ipc") {
-  public_deps = [
+# This is used by Bazel BUILD rules.
+static_library("perfetto_ipc") {
+  complete_static_lib = true
+  deps = [
     ":client",
     ":host",
     "../../gn:default_deps",
diff --git a/src/ipc/buffered_frame_deserializer.cc b/src/ipc/buffered_frame_deserializer.cc
index d893dfb..9ef22eb 100644
--- a/src/ipc/buffered_frame_deserializer.cc
+++ b/src/ipc/buffered_frame_deserializer.cc
@@ -38,8 +38,8 @@
 
 BufferedFrameDeserializer::BufferedFrameDeserializer(size_t max_capacity)
     : capacity_(max_capacity) {
-  PERFETTO_CHECK(max_capacity % base::GetSysPageSize() == 0);
-  PERFETTO_CHECK(max_capacity >= base::GetSysPageSize());
+  PERFETTO_CHECK(max_capacity % base::kPageSize == 0);
+  PERFETTO_CHECK(max_capacity > base::kPageSize);
 }
 
 BufferedFrameDeserializer::~BufferedFrameDeserializer() = default;
@@ -56,8 +56,7 @@
 
     // Surely we are going to use at least the first page, but we may not need
     // the rest for a bit.
-    const auto page_size = base::GetSysPageSize();
-    buf_.AdviseDontNeed(buf() + page_size, capacity_ - page_size);
+    buf_.AdviseDontNeed(buf() + base::kPageSize, capacity_ - base::kPageSize);
   }
 
   PERFETTO_CHECK(capacity_ > size_);
@@ -65,7 +64,6 @@
 }
 
 bool BufferedFrameDeserializer::EndReceive(size_t recv_size) {
-  const auto page_size = base::GetSysPageSize();
   PERFETTO_CHECK(recv_size + size_ <= capacity_);
   size_ += recv_size;
 
@@ -141,8 +139,8 @@
     // If we just finished decoding a large frame that used more than one page,
     // release the extra memory in the buffer. Large frames should be quite
     // rare.
-    if (consumed_size > page_size) {
-      size_t size_rounded_up = (size_ / page_size + 1) * page_size;
+    if (consumed_size > base::kPageSize) {
+      size_t size_rounded_up = (size_ / base::kPageSize + 1) * base::kPageSize;
       if (size_rounded_up < capacity_) {
         char* madvise_begin = buf() + size_rounded_up;
         const size_t madvise_size = capacity_ - size_rounded_up;
diff --git a/src/ipc/buffered_frame_deserializer.h b/src/ipc/buffered_frame_deserializer.h
index 1f78a96..83f5307 100644
--- a/src/ipc/buffered_frame_deserializer.h
+++ b/src/ipc/buffered_frame_deserializer.h
@@ -22,6 +22,8 @@
 #include <list>
 #include <memory>
 
+#include <sys/mman.h>
+
 #include "perfetto/ext/base/paged_memory.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/ipc/basic_types.h"
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index 540656f..c569eb4 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -18,11 +18,11 @@
 
 #include <fcntl.h>
 #include <inttypes.h>
+#include <unistd.h>
 
 #include <utility>
 
 #include "perfetto/base/task_runner.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"
@@ -36,34 +36,18 @@
 namespace perfetto {
 namespace ipc {
 
-namespace {
-constexpr base::SockFamily kClientSockFamily =
-    kUseTCPSocket ? base::SockFamily::kInet : base::SockFamily::kUnix;
-}  // namespace
-
 // static
-std::unique_ptr<Client> Client::CreateInstance(ConnArgs conn_args,
+std::unique_ptr<Client> Client::CreateInstance(const char* socket_name,
                                                base::TaskRunner* task_runner) {
-  std::unique_ptr<Client> client(
-      new ClientImpl(std::move(conn_args), task_runner));
+  std::unique_ptr<Client> client(new ClientImpl(socket_name, task_runner));
   return client;
 }
 
-ClientImpl::ClientImpl(ConnArgs conn_args, base::TaskRunner* task_runner)
-    : socket_name_(conn_args.socket_name),
-      socket_retry_(conn_args.retry),
-      task_runner_(task_runner),
-      weak_ptr_factory_(this) {
-  if (conn_args.socket_fd) {
-    // Create the client using a connected socket. This code path will never hit
-    // OnConnect().
-    sock_ = base::UnixSocket::AdoptConnected(
-        std::move(conn_args.socket_fd), this, task_runner_, kClientSockFamily,
-        base::SockType::kStream, base::SockPeerCredMode::kIgnore);
-  } else {
-    // Connect using the socket name.
-    TryConnect();
-  }
+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);
 }
 
 ClientImpl::~ClientImpl() {
@@ -73,13 +57,6 @@
       nullptr);  // The base::UnixSocket* ptr is not used in OnDisconnect().
 }
 
-void ClientImpl::TryConnect() {
-  PERFETTO_DCHECK(socket_name_);
-  sock_ = base::UnixSocket::Connect(socket_name_, this, task_runner_,
-                                    kClientSockFamily, base::SockType::kStream,
-                                    base::SockPeerCredMode::kIgnore);
-}
-
 void ClientImpl::BindService(base::WeakPtr<ServiceProxy> service_proxy) {
   if (!service_proxy)
     return;
@@ -152,40 +129,21 @@
 }
 
 void ClientImpl::OnConnect(base::UnixSocket*, bool connected) {
-  if (!connected && socket_retry_) {
-    socket_backoff_ms_ =
-        (socket_backoff_ms_ < 10000) ? socket_backoff_ms_ + 1000 : 30000;
-    PERFETTO_DLOG(
-        "Connection to traced's UNIX socket failed, retrying in %u seconds",
-        socket_backoff_ms_ / 1000);
-    auto weak_this = weak_ptr_factory_.GetWeakPtr();
-    task_runner_->PostDelayedTask(
-        [weak_this] {
-          if (weak_this)
-            static_cast<ClientImpl&>(*weak_this).TryConnect();
-        },
-        socket_backoff_ms_);
-    return;
-  }
-
-  // Drain the BindService() calls that were queued before establishing the
-  // connection with the host. Note that if we got disconnected, the call to
-  // OnConnect below might delete |this|, so move everything on the stack first.
-  auto queued_bindings = std::move(queued_bindings_);
-  queued_bindings_.clear();
-  for (base::WeakPtr<ServiceProxy>& service_proxy : queued_bindings) {
+  // Drain the BindService() calls that were queued before establishig the
+  // connection with the host.
+  for (base::WeakPtr<ServiceProxy>& service_proxy : queued_bindings_) {
     if (connected) {
       BindService(service_proxy);
     } else if (service_proxy) {
       service_proxy->OnConnect(false /* success */);
     }
   }
-  // Don't access |this| below here.
+  queued_bindings_.clear();
 }
 
 void ClientImpl::OnDisconnect(base::UnixSocket*) {
-  for (const auto& it : service_bindings_) {
-    base::WeakPtr<ServiceProxy> service_proxy = it.second;
+  for (auto it : service_bindings_) {
+    base::WeakPtr<ServiceProxy>& service_proxy = it.second;
     task_runner_->PostTask([service_proxy] {
       if (service_proxy)
         service_proxy->OnDisconnect();
@@ -201,16 +159,12 @@
     auto buf = frame_deserializer_.BeginReceive();
     base::ScopedFile fd;
     rsize = sock_->Receive(buf.data, buf.size, &fd);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    PERFETTO_DCHECK(!fd);
-#else
     if (fd) {
       PERFETTO_DCHECK(!received_fd_);
       int res = fcntl(*fd, F_SETFD, FD_CLOEXEC);
       PERFETTO_DCHECK(res == 0);
       received_fd_ = std::move(fd);
     }
-#endif
     if (!frame_deserializer_.EndReceive(rsize)) {
       // The endpoint tried to send a frame that is way too large.
       return sock_->Shutdown(true);  // In turn will trigger an OnDisconnect().
diff --git a/src/ipc/client_impl.h b/src/ipc/client_impl.h
index 43e6045..ff9c7bc 100644
--- a/src/ipc/client_impl.h
+++ b/src/ipc/client_impl.h
@@ -46,7 +46,7 @@
 
 class ClientImpl : public Client, public base::UnixSocket::EventListener {
  public:
-  ClientImpl(ConnArgs, base::TaskRunner*);
+  ClientImpl(const char* socket_name, base::TaskRunner*);
   ~ClientImpl() override;
 
   // Client implementation.
@@ -67,8 +67,6 @@
                         base::WeakPtr<ServiceProxy>,
                         int fd = -1);
 
-  base::UnixSocket* GetUnixSocketForTesting() { return sock_.get(); }
-
  private:
   struct QueuedRequest {
     QueuedRequest();
@@ -83,7 +81,6 @@
   ClientImpl(const ClientImpl&) = delete;
   ClientImpl& operator=(const ClientImpl&) = delete;
 
-  void TryConnect();
   bool SendFrame(const Frame&, int fd = -1);
   void OnFrameReceived(const Frame&);
   void OnBindServiceReply(QueuedRequest,
@@ -92,9 +89,6 @@
                            const protos::gen::IPCFrame_InvokeMethodReply&);
 
   bool invoking_method_reply_ = false;
-  const char* socket_name_ = nullptr;
-  bool socket_retry_ = false;
-  uint32_t socket_backoff_ms_ = 0;
   std::unique_ptr<base::UnixSocket> sock_;
   base::TaskRunner* const task_runner_;
   RequestID last_request_id_ = 0;
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index 0a31a8c..183fbf0 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -17,6 +17,7 @@
 #include "src/ipc/client_impl.h"
 
 #include <stdio.h>
+#include <unistd.h>
 
 #include <string>
 
@@ -45,7 +46,7 @@
 using ::testing::Invoke;
 using ::testing::Mock;
 
-ipc::TestSocket kTestSocket{"client_impl_unittest"};
+constexpr char kSockName[] = TEST_SOCK_NAME("client_impl_unittest");
 
 // A fake ServiceProxy. This fakes the client-side class that would be
 // auto-generated from .proto-files.
@@ -78,8 +79,8 @@
   MOCK_METHOD0(OnDisconnect, void());
 };
 
-// A fake host implementation. Listens on |kTestSocket.name()| and replies to
-// IPC metohds like a real one.
+// A fake host implementation. Listens on |kSockName| and replies to IPC
+// metohds like a real one.
 class FakeHost : public base::UnixSocket::EventListener {
  public:
   struct FakeMethod {
@@ -104,13 +105,13 @@
   };  // FakeService.
 
   explicit FakeHost(base::TaskRunner* task_runner) {
-    kTestSocket.Destroy();
-    listening_sock =
-        base::UnixSocket::Listen(kTestSocket.name(), this, task_runner,
-                                 kTestSocket.family(), base::SockType::kStream);
+    DESTROY_TEST_SOCK(kSockName);
+    listening_sock = base::UnixSocket::Listen(kSockName, this, task_runner,
+                                              base::SockFamily::kUnix,
+                                              base::SockType::kStream);
     EXPECT_TRUE(listening_sock->is_listening());
   }
-  ~FakeHost() override { kTestSocket.Destroy(); }
+  ~FakeHost() override { DESTROY_TEST_SOCK(kSockName); }
 
   FakeService* AddFakeService(const std::string& name) {
     auto it_and_inserted =
@@ -204,8 +205,7 @@
   void SetUp() override {
     task_runner_.reset(new base::TestTaskRunner());
     host_.reset(new FakeHost(task_runner_.get()));
-    cli_ = Client::CreateInstance({kTestSocket.name(), /*retry=*/false},
-                                  task_runner_.get());
+    cli_ = Client::CreateInstance(kSockName, task_runner_.get());
   }
 
   void TearDown() override {
@@ -340,8 +340,6 @@
   ASSERT_EQ(kNumReplies, replies_seen);
 }
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// File descriptor sending over IPC is not supported on Windows.
 TEST_F(ClientImplTest, ReceiveFileDescriptor) {
   auto* host_svc = host_->AddFakeService("FakeSvc");
   auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
@@ -431,7 +429,6 @@
             PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
   ASSERT_STREQ(kFileContent, buf);
 }
-#endif  // !OS_WIN
 
 TEST_F(ClientImplTest, BindSameServiceMultipleTimesShouldFail) {
   host_->AddFakeService("FakeSvc");
@@ -578,27 +575,6 @@
   task_runner_->RunUntilCheckpoint("on_disconnect");
 }
 
-TEST_F(ClientImplTest, HostConnectionFailure) {
-  ipc::TestSocket kNonexistentSock{"client_impl_unittest_nonexistent"};
-  std::unique_ptr<Client> client = Client::CreateInstance(
-      {kNonexistentSock.name(), /*retry=*/false}, task_runner_.get());
-
-  // Connect a client to a non-existent socket, which will always fail. The
-  // client will notify the proxy of disconnection.
-  std::unique_ptr<FakeProxy> proxy(new FakeProxy("FakeSvc", &proxy_events_));
-  client->BindService(proxy->GetWeakPtr());
-
-  // Make sure the client copes with being deleted by the disconnection
-  // callback.
-  auto on_disconnect_reached = task_runner_->CreateCheckpoint("on_disconnect");
-  auto on_disconnect = [&] {
-    client.reset();
-    on_disconnect_reached();
-  };
-  EXPECT_CALL(proxy_events_, OnDisconnect()).WillOnce(Invoke(on_disconnect));
-  task_runner_->RunUntilCheckpoint("on_disconnect");
-}
-
 // TODO(primiano): add the tests below.
 // TEST(ClientImplTest, UnparsableReply) {}
 
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index d0f370c..2806a53 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -33,23 +33,6 @@
 namespace perfetto {
 namespace ipc {
 
-namespace {
-
-constexpr base::SockFamily kHostSockFamily =
-    kUseTCPSocket ? base::SockFamily::kInet : base::SockFamily::kUnix;
-
-uid_t GetPosixPeerUid(base::UnixSocket* sock) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  base::ignore_result(sock);
-  // Unsupported. Must be != kInvalidUid or the PacketValidator will fail.
-  return 0;
-#else
-  return sock->peer_uid_posix();
-#endif
-}
-
-}  // namespace
-
 // static
 std::unique_ptr<Host> Host::CreateInstance(const char* socket_name,
                                            base::TaskRunner* task_runner) {
@@ -60,7 +43,7 @@
 }
 
 // static
-std::unique_ptr<Host> Host::CreateInstance(base::ScopedSocketHandle socket_fd,
+std::unique_ptr<Host> Host::CreateInstance(base::ScopedFile socket_fd,
                                            base::TaskRunner* task_runner) {
   std::unique_ptr<HostImpl> host(
       new HostImpl(std::move(socket_fd), task_runner));
@@ -69,22 +52,20 @@
   return std::unique_ptr<Host>(std::move(host));
 }
 
-HostImpl::HostImpl(base::ScopedSocketHandle socket_fd,
-                   base::TaskRunner* task_runner)
+HostImpl::HostImpl(base::ScopedFile socket_fd, base::TaskRunner* task_runner)
     : task_runner_(task_runner), weak_ptr_factory_(this) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_,
-                                   kHostSockFamily, base::SockType::kStream);
+                                   base::SockFamily::kUnix,
+                                   base::SockType::kStream);
 }
 
 HostImpl::HostImpl(const char* socket_name, base::TaskRunner* task_runner)
     : task_runner_(task_runner), weak_ptr_factory_(this) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   sock_ = base::UnixSocket::Listen(socket_name, this, task_runner_,
-                                   kHostSockFamily, base::SockType::kStream);
-  if (!sock_) {
-    PERFETTO_PLOG("Failed to create %s", socket_name);
-  }
+                                   base::SockFamily::kUnix,
+                                   base::SockType::kStream);
 }
 
 HostImpl::~HostImpl() = default;
@@ -111,8 +92,6 @@
   clients_by_socket_[new_conn.get()] = client.get();
   client->id = client_id;
   client->sock = std::move(new_conn);
-  // Watchdog is 30 seconds, so set the socket timeout to 10 seconds.
-  client->sock->SetTxTimeout(10000);
   clients_[client_id] = std::move(client);
 }
 
@@ -218,8 +197,7 @@
     });
   }
 
-  service->client_info_ =
-      ClientInfo(client->id, GetPosixPeerUid(client->sock.get()));
+  service->client_info_ = ClientInfo(client->id, client->sock->peer_uid());
   service->received_fd_ = &client->received_fd;
   method.invoker(service, *decoded_req_args, std::move(deferred_reply));
   service->received_fd_ = nullptr;
@@ -254,14 +232,11 @@
 void HostImpl::SendFrame(ClientConnection* client, const Frame& frame, int fd) {
   std::string buf = BufferedFrameDeserializer::Serialize(frame);
 
-  // When a new Client connects in OnNewClientConnection we set a timeout on
-  // Send (see call to SetTxTimeout).
-  //
-  // The old behaviour was to do a blocking I/O call, which caused crashes from
-  // misbehaving producers (see b/169051440).
+  // TODO(primiano): this should do non-blocking I/O. But then what if the
+  // socket buffer is full? We might want to either drop the request or throttle
+  // the send and PostTask the reply later? Right now we are making Send()
+  // blocking as a workaround. Propagate bakpressure to the caller instead.
   bool res = client->sock->Send(buf.data(), buf.size(), fd);
-  // If we timeout |res| will be false, but the UnixSocket will have called
-  // UnixSocket::ShutDown() and thus |is_connected()| is false.
   PERFETTO_CHECK(res || !client->sock->is_connected());
 }
 
@@ -271,8 +246,7 @@
   if (it == clients_by_socket_.end())
     return;
   ClientID client_id = it->second->id;
-
-  ClientInfo client_info(client_id, GetPosixPeerUid(sock));
+  ClientInfo client_info(client_id, sock->peer_uid());
   clients_by_socket_.erase(it);
   PERFETTO_DCHECK(clients_.count(client_id));
   clients_.erase(client_id);
diff --git a/src/ipc/host_impl.h b/src/ipc/host_impl.h
index ac0a593..7b12d9f 100644
--- a/src/ipc/host_impl.h
+++ b/src/ipc/host_impl.h
@@ -35,7 +35,7 @@
 class HostImpl : public Host, public base::UnixSocket::EventListener {
  public:
   HostImpl(const char* socket_name, base::TaskRunner*);
-  HostImpl(base::ScopedSocketHandle, base::TaskRunner*);
+  HostImpl(base::ScopedFile socket_fd, base::TaskRunner*);
   ~HostImpl() override;
 
   // Host implementation.
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index a04ff22..d030a02 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -44,7 +44,7 @@
 using ::testing::InvokeWithoutArgs;
 using ::testing::Return;
 
-ipc::TestSocket kTestSocket{"host_impl_unittest"};
+constexpr char kSockName[] = TEST_SOCK_NAME("host_impl_unittest.sock");
 
 // RequestProto and ReplyProto are defined in client_unittest_messages.proto.
 
@@ -90,8 +90,8 @@
   MOCK_METHOD0(OnRequestError, void());
 
   explicit FakeClient(base::TaskRunner* task_runner) {
-    sock_ = base::UnixSocket::Connect(kTestSocket.name(), this, task_runner,
-                                      kTestSocket.family(),
+    sock_ = base::UnixSocket::Connect(kSockName, this, task_runner,
+                                      base::SockFamily::kUnix,
                                       base::SockType::kStream);
   }
 
@@ -168,10 +168,9 @@
 class HostImplTest : public ::testing::Test {
  public:
   void SetUp() override {
-    kTestSocket.Destroy();
+    DESTROY_TEST_SOCK(kSockName);
     task_runner_.reset(new base::TestTaskRunner());
-    Host* host =
-        Host::CreateInstance(kTestSocket.name(), task_runner_.get()).release();
+    Host* host = Host::CreateInstance(kSockName, task_runner_.get()).release();
     ASSERT_NE(nullptr, host);
     host_.reset(static_cast<HostImpl*>(host));
     cli_.reset(new FakeClient(task_runner_.get()));
@@ -186,7 +185,7 @@
     host_.reset();
     task_runner_->RunUntilIdle();
     task_runner_.reset();
-    kTestSocket.Destroy();
+    DESTROY_TEST_SOCK(kSockName);
   }
 
   // ::testing::StrictMock<MockEventListener> proxy_events_;
@@ -321,8 +320,6 @@
   task_runner_->RunUntilCheckpoint("on_reply_received");
 }
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// File descriptor sending over IPC is not supported on Windows.
 TEST_F(HostImplTest, SendFileDescriptor) {
   FakeService* fake_service = new FakeService("FakeService");
   ASSERT_TRUE(host_->ExposeService(std::unique_ptr<Service>(fake_service)));
@@ -401,7 +398,6 @@
             PERFETTO_EINTR(read(*rx_fd, buf, sizeof(buf))));
   ASSERT_STREQ(kFileContent, buf);
 }
-#endif  // !OS_WIN
 
 // Invoke a method and immediately after disconnect the client.
 TEST_F(HostImplTest, OnClientDisconnect) {
diff --git a/src/ipc/test/ipc_integrationtest.cc b/src/ipc/test/ipc_integrationtest.cc
index b1b0631..b681f95 100644
--- a/src/ipc/test/ipc_integrationtest.cc
+++ b/src/ipc/test/ipc_integrationtest.cc
@@ -37,7 +37,7 @@
 
 using namespace ::ipc_test::gen;
 
-::perfetto::ipc::TestSocket kTestSocket{"ipc_integrationtest"};
+constexpr char kSockName[] = TEST_SOCK_NAME("ipc_integrationtest");
 
 class MockEventListener : public ServiceProxy::EventListener {
  public:
@@ -64,16 +64,15 @@
 
 class IPCIntegrationTest : public ::testing::Test {
  protected:
-  void SetUp() override { kTestSocket.Destroy(); }
-  void TearDown() override { kTestSocket.Destroy(); }
+  void SetUp() override { DESTROY_TEST_SOCK(kSockName); }
+  void TearDown() override { DESTROY_TEST_SOCK(kSockName); }
 
   perfetto::base::TestTaskRunner task_runner_;
   MockEventListener svc_proxy_events_;
 };
 
 TEST_F(IPCIntegrationTest, SayHelloWaveGoodbye) {
-  std::unique_ptr<Host> host =
-      Host::CreateInstance(kTestSocket.name(), &task_runner_);
+  std::unique_ptr<Host> host = Host::CreateInstance(kSockName, &task_runner_);
   ASSERT_TRUE(host);
 
   MockGreeterService* svc = new MockGreeterService();
@@ -81,8 +80,8 @@
 
   auto on_connect = task_runner_.CreateCheckpoint("on_connect");
   EXPECT_CALL(svc_proxy_events_, OnConnect()).WillOnce(Invoke(on_connect));
-  std::unique_ptr<Client> cli = Client::CreateInstance(
-      {kTestSocket.name(), /*retry=*/false}, &task_runner_);
+  std::unique_ptr<Client> cli =
+      Client::CreateInstance(kSockName, &task_runner_);
   std::unique_ptr<GreeterProxy> svc_proxy(new GreeterProxy(&svc_proxy_events_));
   cli->BindService(svc_proxy->GetWeakPtr());
   task_runner_.RunUntilCheckpoint("on_connect");
diff --git a/src/ipc/test/test_socket.h b/src/ipc/test/test_socket.h
index e55a8df..f68ef4b 100644
--- a/src/ipc/test/test_socket.h
+++ b/src/ipc/test/test_socket.h
@@ -17,69 +17,17 @@
 #ifndef SRC_IPC_TEST_TEST_SOCKET_H_
 #define SRC_IPC_TEST_TEST_SOCKET_H_
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/unix_socket.h"
 
-namespace perfetto {
-namespace ipc {
-
-struct TestSocket {
-  explicit constexpr TestSocket(const char* test_name)
-      : test_name_(test_name) {}
-
-  const char* test_name_;
-  char buf_[64]{};
-
-  // Inline to avoid multiple definition linker warnings (and avoid a .cc file).
-  inline base::SockFamily family();
-  inline const char* name();
-  inline void Destroy();
-};
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-const char* TestSocket::name() {
-  uint64_t hash = 5381;
-  for (const char* c = test_name_; *c; c++)
-    hash = 33 * hash + static_cast<uint64_t>(*c);
-  snprintf(buf_, sizeof(buf_), "127.0.0.1:%" PRIu64, 40000 + (hash % 20000));
-  return buf_;
-}
-base::SockFamily TestSocket::family() {
-  return base::SockFamily::kInet;
-}
-void TestSocket::Destroy() {}
-
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-
-const char* TestSocket::name() {
-  snprintf(buf_, sizeof(buf_), "@%s", test_name_);
-  return buf_;
-}
-base::SockFamily TestSocket::family() {
-  return base::SockFamily::kUnix;
-}
-void TestSocket::Destroy() {}
-
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define TEST_SOCK_NAME(x) "@" x
+#define DESTROY_TEST_SOCK(x) \
+  do {                       \
+  } while (0)
 #else
-
-const char* TestSocket::name() {
-  snprintf(buf_, sizeof(buf_), "/tmp/%s.sock", test_name_);
-  return buf_;
-}
-base::SockFamily TestSocket::family() {
-  return base::SockFamily::kUnix;
-}
-void TestSocket::Destroy() {
-  remove(name());
-}
+#include <unistd.h>
+#define TEST_SOCK_NAME(x) "/tmp/" x ".sock"
+#define DESTROY_TEST_SOCK(x) unlink(x)
 #endif
 
-}  // namespace ipc
-}  // namespace perfetto
-
 #endif  // SRC_IPC_TEST_TEST_SOCKET_H_
diff --git a/src/kallsyms/BUILD.gn b/src/kallsyms/BUILD.gn
deleted file mode 100644
index 5f305f8..0000000
--- a/src/kallsyms/BUILD.gn
+++ /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.
-
-import("../../gn/test.gni")
-
-source_set("kallsyms") {
-  deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/protozero",
-    "../base",
-  ]
-  sources = [
-    "kernel_symbol_map.cc",
-    "kernel_symbol_map.h",
-    "lazy_kernel_symbolizer.cc",
-    "lazy_kernel_symbolizer.h",
-  ]
-}
-
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    ":kallsyms",
-    "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
-    "../base",
-  ]
-  sources = [
-    "kernel_symbol_map_unittest.cc",
-    "lazy_kernel_symbolizer_unittest.cc",
-  ]
-}
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":kallsyms",
-      "../../gn:benchmark",
-      "../../gn:default_deps",
-      "../base",
-      "../base:test_support",
-    ]
-    sources = [ "kernel_symbol_map_benchmark.cc" ]
-  }
-}
diff --git a/src/kallsyms/kernel_symbol_map.cc b/src/kallsyms/kernel_symbol_map.cc
deleted file mode 100644
index 920c897..0000000
--- a/src/kallsyms/kernel_symbol_map.cc
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/kallsyms/kernel_symbol_map.h"
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/metatrace.h"
-#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/utils.h"
-#include "perfetto/protozero/proto_utils.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <functional>
-#include <map>
-#include <utility>
-
-namespace perfetto {
-
-// On a Pixel 3 this gives an avg. lookup time of 600 ns and a memory usage
-// of 1.1 MB for 65k symbols. See go/kallsyms-parser-bench.
-size_t KernelSymbolMap::kSymIndexSampling = 16;
-size_t KernelSymbolMap::kTokenIndexSampling = 4;
-
-namespace {
-
-using TokenId = KernelSymbolMap::TokenTable::TokenId;
-constexpr size_t kSymNameMaxLen = 128;
-constexpr size_t kSymMaxSizeBytes = 1024 * 1024;
-
-// Reads a kallsyms file in blocks of 4 pages each and decode its lines using
-// a simple FSM. Calls the passed lambda for each valid symbol.
-// It skips undefined symbols and other useless stuff.
-template <typename Lambda /* void(uint64_t, const char*) */>
-void ForEachSym(const std::string& kallsyms_path, Lambda fn) {
-  base::ScopedFile fd = base::OpenFile(kallsyms_path.c_str(), O_RDONLY);
-  if (!fd) {
-    PERFETTO_PLOG("Cannot open %s", kallsyms_path.c_str());
-    return;
-  }
-
-  // /proc/kallsyms looks as follows:
-  // 0000000000026a80 A bpf_trace_sds
-  //
-  // ffffffffc03a6000 T cpufreq_gov_powersave_init<TAB> [cpufreq_powersave]
-  // ffffffffc035d000 T cpufreq_gov_userspace_init<TAB> [cpufreq_userspace]
-  //
-  // We parse it with a state machine that has four states, one for each column.
-  // We don't care about the part in the square brackets and ignore everything
-  // after the symbol name.
-
-  static constexpr size_t kBufSize = 16 * 1024;
-  base::PagedMemory buffer = base::PagedMemory::Allocate(kBufSize);
-  enum { kSymAddr, kSymType, kSymName, kEatRestOfLine } state = kSymAddr;
-  uint64_t sym_addr = 0;
-  char sym_type = '\0';
-  char sym_name[kSymNameMaxLen + 1];
-  size_t sym_name_len = 0;
-  for (;;) {
-    char* buf = static_cast<char*>(buffer.Get());
-    auto rsize = base::Read(*fd, buf, kBufSize);
-    if (rsize < 0) {
-      PERFETTO_PLOG("read(%s) failed", kallsyms_path.c_str());
-      return;
-    }
-    if (rsize == 0)
-      return;  // EOF
-    for (size_t i = 0; i < static_cast<size_t>(rsize); i++) {
-      char c = buf[i];
-      const bool is_space = c == ' ' || c == '\t';
-      switch (state) {
-        case kSymAddr:
-          if (c >= '0' && c <= '9') {
-            sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - '0');
-          } else if (c >= 'a' && c <= 'f') {
-            sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - 'a' + 10);
-          } else if (is_space) {
-            state = kSymType;
-          } else if (c == '\0') {
-            return;
-          } else {
-            PERFETTO_ELOG("kallsyms parser error: chr 0x%x @ off=%zu", c, i);
-            return;
-          }
-          break;
-
-        case kSymType:
-          if (is_space)
-            break;  // Eat leading spaces.
-          sym_type = c;
-          state = kSymName;
-          sym_name_len = 0;
-          break;
-
-        case kSymName:
-          if (is_space && sym_name_len == 0)
-            break;  // Eat leading spaces.
-          if (c && c != '\n' && !is_space && sym_name_len < kSymNameMaxLen) {
-            sym_name[sym_name_len++] = c;
-            break;
-          }
-          sym_name[sym_name_len] = '\0';
-          fn(sym_addr, sym_type, sym_name);
-          sym_addr = 0;
-          sym_type = '\0';
-          state = c == '\n' ? kSymAddr : kEatRestOfLine;
-          break;
-
-        case kEatRestOfLine:
-          if (c == '\n')
-            state = kSymAddr;
-          break;
-      }  // switch(state)
-    }    // for (char in buf)
-  }      // for (read chunk)
-}
-
-// Splits a symbol name into tokens using '_' as a separator, calling the passed
-// lambda for each token. It splits tokens in a way that allows the original
-// string to be rebuilt as-is by re-joining using a '_' between each token.
-// For instance:
-// _fo_a_b      ->  ["", fo, a, b]
-// __fo_a_b     ->  [_, fo, a, b]
-// __fo_a_b_    ->  [_, fo, a, b, ""]
-// __fo_a_b____ ->  [_, fo, a, b, ___]
-template <typename Lambda /* void(base::StringView) */>
-void Tokenize(const char* name, Lambda fn) {
-  const char* tok_start = name;
-  bool is_start_of_token = true;
-  bool tok_is_sep = false;
-  for (const char* ptr = name;; ptr++) {
-    const char c = *ptr;
-    if (is_start_of_token) {
-      tok_is_sep = *tok_start == '_';  // Deals with tokens made of '_'s.
-      is_start_of_token = false;
-    }
-    // Scan until either the end of string or the next character (which is a '_'
-    // in nominal cases, or anything != '_' for tokens made by 1+ '_').
-    if (c == '\0' || (!tok_is_sep && c == '_') || (tok_is_sep && c != '_')) {
-      size_t tok_len = static_cast<size_t>(ptr - tok_start);
-      if (tok_is_sep && c != '\0')
-        --tok_len;
-      fn(base::StringView(tok_start, tok_len));
-      if (c == '\0')
-        return;
-      tok_start = tok_is_sep ? ptr : ptr + 1;
-      is_start_of_token = true;
-    }
-  }
-}
-
-}  // namespace
-
-KernelSymbolMap::TokenTable::TokenTable() {
-  // Insert a null token as id 0. We can't just add "" because the empty string
-  // is special-cased and doesn't insert an actual token. So we push a string of
-  // size one that contains only the null character instead.
-  char null_tok = 0;
-  Add(std::string(&null_tok, 1));
-}
-
-KernelSymbolMap::TokenTable::~TokenTable() = default;
-
-// Adds a new token to the db. Does not dedupe identical token (with the
-// exception of the empty string). The caller has to deal with that.
-// Supports only ASCII characters in the range [1, 127].
-// The last character of the token will have the MSB set.
-TokenId KernelSymbolMap::TokenTable::Add(const std::string& token) {
-  const size_t token_size = token.size();
-  if (token_size == 0)
-    return 0;
-  TokenId id = num_tokens_++;
-
-  const size_t buf_size_before_insertion = buf_.size();
-  if (id % kTokenIndexSampling == 0)
-    index_.emplace_back(buf_size_before_insertion);
-
-  const size_t prev_size = buf_.size();
-  buf_.resize(prev_size + token_size);
-  char* tok_wptr = &buf_[prev_size];
-  for (size_t i = 0; i < token_size - 1; i++) {
-    PERFETTO_DCHECK((token.at(i) & 0x80) == 0);  // |token| must be ASCII only.
-    *(tok_wptr++) = token.at(i) & 0x7f;
-  }
-  *(tok_wptr++) = static_cast<char>(token.at(token_size - 1) | 0x80);
-  PERFETTO_DCHECK(tok_wptr == &buf_[buf_.size()]);
-  return id;
-}
-
-// NOTE: the caller need to mask the returned chars with 0x7f. The last char of
-// the StringView will have its MSB set (it's used as a EOF char internally).
-base::StringView KernelSymbolMap::TokenTable::Lookup(TokenId id) {
-  if (id == 0)
-    return base::StringView();
-  if (id > num_tokens_)
-    return base::StringView("<error>");
-  // We don't know precisely where the id-th token starts in the buffer. We
-  // store only one position every kTokenIndexSampling. From there, the token
-  // can be found with a linear scan of at most kTokenIndexSampling steps.
-  size_t index_off = id / kTokenIndexSampling;
-  PERFETTO_DCHECK(index_off < index_.size());
-  TokenId cur_id = static_cast<TokenId>(index_off * kTokenIndexSampling);
-  uint32_t begin = index_[index_off];
-  PERFETTO_DCHECK(begin == 0 || buf_[begin - 1] & 0x80);
-  const size_t buf_size = buf_.size();
-  for (uint32_t off = begin; off < buf_size; ++off) {
-    // Advance |off| until the end of the token (which has the MSB set).
-    if ((buf_[off] & 0x80) == 0)
-      continue;
-    if (cur_id == id)
-      return base::StringView(&buf_[begin], off - begin + 1);
-    ++cur_id;
-    begin = off + 1;
-  }
-  return base::StringView();
-}
-
-size_t KernelSymbolMap::Parse(const std::string& kallsyms_path) {
-  PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, KALLSYMS_PARSE);
-  using SymAddr = uint64_t;
-
-  struct TokenInfo {
-    uint32_t count = 0;
-    TokenId id = 0;
-  };
-
-  // Note if changing the container: the code below relies on stable iterators.
-  using TokenMap = std::map<std::string, TokenInfo>;
-  using TokenMapPtr = TokenMap::value_type*;
-  TokenMap tokens;
-
-  // Keep the (ordered) list of tokens for each symbol.
-  struct SymAddrAndTokenPtr {
-    SymAddr addr;
-    TokenMapPtr token_map_entry;
-
-    bool operator<(const SymAddrAndTokenPtr& other) const {
-      return addr < other.addr;
-    }
-  };
-  std::vector<SymAddrAndTokenPtr> symbol_tokens;
-
-  // Based on `cat /proc/kallsyms | egrep "\b[tT]\b" | wc -l`.
-  symbol_tokens.reserve(128 * 1024);
-
-  ForEachSym(kallsyms_path, [&](SymAddr addr, char type, const char* name) {
-    if (addr == 0 || (type != 't' && type != 'T') || name[0] == '$') {
-      return;
-    }
-
-    // Split each symbol name in tokens, using '_' as a separator (so that
-    // "foo_bar" -> ["foo", "bar"]). For each token hash:
-    // 1. Keep track of the frequency of each token.
-    // 2. Keep track of the list of token hashes for each symbol.
-    Tokenize(name, [&tokens, &symbol_tokens, addr](base::StringView token) {
-      // Strip the .cfi part if present.
-      if (token.substr(token.size() - 4) == ".cfi")
-        token = token.substr(0, token.size() - 4);
-      auto it_and_ins = tokens.emplace(token.ToStdString(), TokenInfo{});
-      it_and_ins.first->second.count++;
-      symbol_tokens.emplace_back(SymAddrAndTokenPtr{addr, &*it_and_ins.first});
-    });
-  });
-
-  symbol_tokens.shrink_to_fit();
-
-  // For each symbol address, T entries are inserted into |symbol_tokens|, one
-  // for each token. These symbols are added in arbitrary address (as seen in
-  // /proc/kallsyms). Here we want to sort symbols by addresses, but at the same
-  // time preserve the order of tokens within each address.
-  // For instance, if kallsyms has: {0x41: connect_socket, 0x42: write_file}:
-  // Before sort: [(0x42, write), (0x42, file), (0x41, connect), (0x41, socket)]
-  // After sort: [(0x41, connect), (0x41, socket), (0x42, write), (0x42, file)]
-  std::stable_sort(symbol_tokens.begin(), symbol_tokens.end());
-
-  // At this point we have broken down each symbol into a set of token hashes.
-  // Now generate the token ids, putting high freq tokens first, so they use
-  // only one byte to varint encode.
-
-  // This block limits the lifetime of |tokens_by_freq|.
-  {
-    std::vector<TokenMapPtr> tokens_by_freq;
-    tokens_by_freq.resize(tokens.size());
-    size_t tok_idx = 0;
-    for (auto& kv : tokens)
-      tokens_by_freq[tok_idx++] = &kv;
-
-    auto comparer = [](TokenMapPtr a, TokenMapPtr b) {
-      PERFETTO_DCHECK(a && b);
-      return b->second.count < a->second.count;
-    };
-    std::sort(tokens_by_freq.begin(), tokens_by_freq.end(), comparer);
-    for (TokenMapPtr tinfo : tokens_by_freq) {
-      tinfo->second.id = tokens_.Add(tinfo->first);
-    }
-  }
-  tokens_.shrink_to_fit();
-
-  buf_.resize(2 * 1024 * 1024);  // Based on real-word observations.
-  base_addr_ = symbol_tokens.empty() ? 0 : symbol_tokens.begin()->addr;
-  SymAddr prev_sym_addr = base_addr_;
-  uint8_t* wptr = buf_.data();
-
-  for (auto it = symbol_tokens.begin(); it != symbol_tokens.end();) {
-    const SymAddr sym_addr = it->addr;
-
-    // Find the iterator to the first token of the next symbol (or the end).
-    auto sym_start = it;
-    auto sym_end = it;
-    while (sym_end != symbol_tokens.end() && sym_end->addr == sym_addr)
-      ++sym_end;
-
-    // The range [sym_start, sym_end) has all the tokens for the current symbol.
-    uint32_t size_before = static_cast<uint32_t>(wptr - buf_.data());
-
-    // Make sure there is enough headroom to write the symbol.
-    if (buf_.size() - size_before < 1024) {
-      buf_.resize(buf_.size() + 32768);
-      wptr = buf_.data() + size_before;
-    }
-
-    uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
-    const size_t sym_num = num_syms_++;
-    if (sym_num % kSymIndexSampling == 0)
-      index_.emplace_back(std::make_pair(sym_rel_addr, size_before));
-    PERFETTO_DCHECK(sym_addr >= prev_sym_addr);
-    uint32_t delta = static_cast<uint32_t>(sym_addr - prev_sym_addr);
-    wptr = protozero::proto_utils::WriteVarInt(delta, wptr);
-    // Append all the token ids.
-    for (it = sym_start; it != sym_end;) {
-      PERFETTO_DCHECK(it->addr == sym_addr);
-      TokenMapPtr const token_map_entry = it->token_map_entry;
-      const TokenInfo& token_info = token_map_entry->second;
-      TokenId token_id = token_info.id << 1;
-      ++it;
-      token_id |= (it == sym_end) ? 1 : 0;  // Last one has LSB set to 1.
-      wptr = protozero::proto_utils::WriteVarInt(token_id, wptr);
-    }
-    prev_sym_addr = sym_addr;
-  }  // for (symbols)
-
-  buf_.resize(static_cast<size_t>(wptr - buf_.data()));
-  buf_.shrink_to_fit();
-  base::MaybeReleaseAllocatorMemToOS();  // For Scudo, b/170217718.
-
-  if (num_syms_ == 0) {
-    PERFETTO_ELOG(
-        "Failed to parse kallsyms. Kernel functions will not be symbolized. On "
-        "Linux this requires either running traced_probes as root or manually "
-        "lowering /proc/sys/kernel/kptr_restrict");
-  } else {
-    PERFETTO_DLOG(
-        "Loaded %zu kalllsyms entries. Mem usage: %zu B (addresses) + %zu B "
-        "(tokens), total: %zu B",
-        num_syms_, addr_bytes(), tokens_.size_bytes(), size_bytes());
-  }
-
-  return num_syms_;
-}
-
-std::string KernelSymbolMap::Lookup(uint64_t sym_addr) {
-  if (index_.empty() || sym_addr < base_addr_)
-    return "";
-
-  // First find the highest symbol address <= sym_addr.
-  // Start with a binary search using the sparse index.
-
-  const uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
-  auto it = std::upper_bound(index_.cbegin(), index_.cend(),
-                             std::make_pair(sym_rel_addr, 0u));
-  if (it != index_.cbegin())
-    --it;
-
-  // Then continue with a linear scan (of at most kSymIndexSampling steps).
-  uint32_t addr = it->first;
-  uint32_t off = it->second;
-  const uint8_t* rdptr = &buf_[off];
-  const uint8_t* const buf_end = &buf_[buf_.size()];
-  bool parsing_addr = true;
-  const uint8_t* next_rdptr = nullptr;
-  uint64_t sym_start_addr = 0;
-  for (bool is_first_addr = true;; is_first_addr = false) {
-    uint64_t v = 0;
-    const auto* prev_rdptr = rdptr;
-    rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
-    if (rdptr == prev_rdptr)
-      break;
-    if (parsing_addr) {
-      addr += is_first_addr ? 0 : static_cast<uint32_t>(v);
-      parsing_addr = false;
-      if (addr > sym_rel_addr)
-        break;
-      next_rdptr = rdptr;
-      sym_start_addr = addr;
-    } else {
-      // This is a token. Wait for the EOF maker.
-      parsing_addr = (v & 1) == 1;
-    }
-  }
-
-  if (!next_rdptr)
-    return "";
-
-  PERFETTO_DCHECK(sym_rel_addr >= sym_start_addr);
-
-  // If this address is too far from the start of the symbol, this is likely
-  // a pointer to something else (e.g. some vmalloc struct) and we just picked
-  // the very last symbol for a loader region.
-  if (sym_rel_addr - sym_start_addr > kSymMaxSizeBytes)
-    return "";
-
-  // The address has been found. Now rejoin the tokens to form the symbol name.
-
-  rdptr = next_rdptr;
-  std::string sym_name;
-  sym_name.reserve(kSymNameMaxLen);
-  for (bool eof = false, is_first_token = true; !eof; is_first_token = false) {
-    uint64_t v = 0;
-    const auto* old = rdptr;
-    rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
-    if (rdptr == old)
-      break;
-    eof = v & 1;
-    base::StringView token = tokens_.Lookup(static_cast<TokenId>(v >> 1));
-    if (!is_first_token)
-      sym_name.push_back('_');
-    for (size_t i = 0; i < token.size(); i++)
-      sym_name.push_back(token.at(i) & 0x7f);
-  }
-  return sym_name;
-}
-
-}  // namespace perfetto
diff --git a/src/kallsyms/kernel_symbol_map.h b/src/kallsyms/kernel_symbol_map.h
deleted file mode 100644
index c69d86a..0000000
--- a/src/kallsyms/kernel_symbol_map.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_KALLSYMS_KERNEL_SYMBOL_MAP_H_
-#define SRC_KALLSYMS_KERNEL_SYMBOL_MAP_H_
-
-#include <stdint.h>
-
-#include <array>
-#include <forward_list>
-#include <string>
-#include <vector>
-
-namespace perfetto {
-
-namespace base {
-class StringView;
-}
-
-// A parser and memory-efficient container for /proc/kallsyms.
-// It can store a full kernel symbol table in ~1.2MB of memory and perform fast
-// lookups using logarithmic binary searches + bounded linear scans.
-//
-// /proc/kallsyms is a ~10 MB text file that contains the map of kernel symbols,
-// as follows:
-// ffffff8f77682f8c t el0_sync_invalid
-// ffffff8f77683060 t el0_irq_invalid
-// ...
-// In a typipcal Android kernel, it consists of 213K lines. Out of these, only
-// 116K are interesting for the sake of symbolizing kernel functions, the rest
-// are .rodata (variables), weak or other useless symbols.
-// Still, even keeping around 116K pointers would require 116K * 8 ~= 1 MB of
-// memory, without accounting for any strings for the symbols names.
-// The SUM(str.len) for the 116K symbol names adds up to 2.7 MB (without
-// counting their addresses).
-// However consider the following:
-// - Symbol addresses are mostly contiguous. Modulo the initial KASLR loading
-//   address, most symbols are few hundreds bytes apart from each other.
-// - Symbol names are made of tokens that are quite frequent (token: the result
-//   of name.split('_')). If we tokenize the 2.7 MB of strings, the resulting
-//   SUM(distinct_token.len) goes down 2.7MB -> 146 KB. This is because tokens
-//   like "get", "set" or "event" show up thousands of times.
-// - Symbol names are ASCII strings using only 7 out of 8 bits.
-//
-// In the light of this, the in-memory architecture of this data structure is
-// as follows:
-// We keep two tables around: (1) a token table and (2) a symbol table. Both
-// table are a flat byte vector with some sparse lookaside index to make lookups
-// faster and avoid full linear scans.
-//
-// Token table
-// -----------
-// The token table is a flat char buffer. Tokens are variable size (>0). Each
-// token is identified by its ordinality, so token id 3 is the 3rd token in
-// the table. All tokens are concatenated together.
-// Given the ASCII encoding, the MSB is used as a terminator. So instead of
-// wasting an extra NUL byte for each string, the last char of each token has
-// the MSB set.
-// Furthermore, a lookaside index stores the offset of tokens (i.e. Token N
-// starts at offset O in the buffer) to allow fast lookups. In order to avoid
-// wasting too much memory, the index is sparse and track the offsets of only
-// one every kTokenIndexSamplinig tokens.
-// When looking up a token ID N, the table seeks at the offset of the closest
-// token <= N, and then scans linearly the next (at most kTokenIndexSamplinig)
-// tokens, counting the MSBs found, until the right token id is found.
-// buf:   set*get*kernel*load*fpsimd*return*wrapper*el0*skip*sync*neon*bit*aes
-//        ^                   ^                         ^
-//        |                   |                         |
-// index: 0@0                 4@15                      8@21
-
-// Symbol table
-// ------------
-// The symbol table is a flat char buffer that stores for each symbol: its
-// address + the list of token indexes in the token table. The main caveats are
-// that:
-// - Symbol addresses are delta encoded (delta from prev symbol's addr).
-// - Both delta addresses and token indexes are var-int encoded.
-// - The LSB of token indexes is used as EOF marker (i.e. the next varint is
-//   the delta-addr for the next symbol). This time the LSB is used because of
-//   the varint encoding.
-// At parsing time symbols are ordered by address and tokens are sorted by
-// frequency, so that the top used 64 tokens can be represented with 1 byte.
-// (Rationale for 64: 1 byte = 8 bits. The MSB bit of each byte is used for the
-// varint encoding, the LSB bit of each number is used as end-of-tokens marker.
-// There are 6 bits left -> 64 indexes can be represented using one byte).
-// In summary the symbol table looks as follows:
-//
-// Base address: 0xbeef0000
-// Symbol buffer:
-// 0 1|0  4|0  6|1    // 0xbeef0000: 1,4,6 -> get_fpsimd_wrapper
-// 8 7|0  3|1         // 0xbeef0008: 7,3   -> el0_load
-// ...
-// Like in the case of the token table, a lookaside index keeps track of the
-// offset of one every kSymIndexSamplinig addresses.
-// The Lookup(ADDR) function operates as follows:
-// 1. Performs a logarithmic binary search in the symbols index, finding the
-//    offset of the closest addres <= ADDR.
-// 2. Skip over at most kSymIndexSamplinig until the symbol is found.
-// 3. For each token index, lookup the corresponding token string and
-//    concatenate them to build the symbol name.
-
-class KernelSymbolMap {
- public:
-  // The two constants below are changeable only for the benchmark use.
-  // Trades off size of the root |index_| vs worst-case linear scans size.
-  // A higher number makes the index more sparse.
-  static size_t kSymIndexSampling;
-
-  // Trades off size of the TokenTable |index_| vs worst-case linear scans size.
-  static size_t kTokenIndexSampling;
-
-  // Parses a kallsyms file. Returns the number of valid symbols decoded.
-  size_t Parse(const std::string& kallsyms_path);
-
-  // Looks up the closest symbol (i.e. the one with the highest address <=
-  // |addr|) from its absolute 64-bit address.
-  // Returns an empty string if the symbol is not found (which can happen only
-  // if the passed |addr| is < min(addr)).
-  std::string Lookup(uint64_t addr);
-
-  // Returns the numberr of valid symbols decoded.
-  size_t num_syms() const { return num_syms_; }
-
-  // Returns the size in bytes used by the adddress table (without counting
-  // the tokens).
-  size_t addr_bytes() const { return buf_.size() + index_.size() * 8; }
-
-  // Returns the total memory usage in bytes.
-  size_t size_bytes() const { return addr_bytes() + tokens_.size_bytes(); }
-
-  // Token table.
-  class TokenTable {
-   public:
-    using TokenId = uint32_t;
-    TokenTable();
-    ~TokenTable();
-    TokenId Add(const std::string&);
-    base::StringView Lookup(TokenId);
-    size_t size_bytes() const { return buf_.size() + index_.size() * 4; }
-
-    void shrink_to_fit() {
-      buf_.shrink_to_fit();
-      index_.shrink_to_fit();
-    }
-
-   private:
-    TokenId num_tokens_ = 0;
-
-    std::vector<char> buf_;  // Token buffer.
-
-    // The value i-th in the vector contains the offset (within |buf_|) of the
-    // (i * kTokenIndexSamplinig)-th token.
-    std::vector<uint32_t> index_;
-  };
-
- private:
-  TokenTable tokens_;  // Token table.
-
-  uint64_t base_addr_ = 0;    // Address of the first symbol (after sorting).
-  size_t num_syms_ = 0;       // Number of valid symbols stored.
-  std::vector<uint8_t> buf_;  // Symbol buffer.
-
-  // The key is (address - base_addr_), the value is the byte offset in |buf_|
-  // where the symbol entry starts (i.e. the start of the varint that tells the
-  // delta from the previous symbol).
-  std::vector<std::pair<uint32_t /*rel_addr*/, uint32_t /*offset*/>> index_;
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KALLSYMS_KERNEL_SYMBOL_MAP_H_
diff --git a/src/kallsyms/kernel_symbol_map_benchmark.cc b/src/kallsyms/kernel_symbol_map_benchmark.cc
deleted file mode 100644
index 7c3e9a9..0000000
--- a/src/kallsyms/kernel_symbol_map_benchmark.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 <set>
-#include <unordered_set>
-
-#include <benchmark/benchmark.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "src/base/test/utils.h"
-#include "src/kallsyms/kernel_symbol_map.h"
-
-namespace {
-
-bool IsBenchmarkFunctionalOnly() {
-  return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
-}
-
-void BenchmarkArgs(benchmark::internal::Benchmark* b) {
-  if (IsBenchmarkFunctionalOnly()) {
-    b->Ranges({{16, 16}, {16, 16}});
-  } else {
-    b->RangeMultiplier(2)->Ranges({{4, 512}, {4, 512}});
-  }
-}
-
-struct ExpectedSym {
-  uint64_t addr;
-  const char* name;
-};
-
-// This set of symbols has been chosen by randomly picking 40 random symbols
-// from the original kallsyms.
-ExpectedSym kExpectedSyms[] = {
-    {0xffffff8f79c0d978, "__map_memblock"},
-    {0xffffff8f78fddbb8, "smack_inode_getsecid"},
-    {0xffffff8f78fe43b4, "msm_smmu_set_attribute"},
-    {0xffffff8f79d23e20, "__initcall_41_dm_verity_init6"},
-    {0xffffff8f74206c5c, "sme_update_fast_transition_enabled"},
-    {0xffffff8f74878c8c, "tavil_hph_idle_detect_put"},
-    {0xffffff8f78fd7db0, "privileged_wrt_inode_uidgid"},
-    {0xffffff8f78ffe030, "__hrtimer_tasklet_trampoline"},
-    {0xffffff8f78fd86b0, "store_enable"},
-    {0xffffff8f78ffbcb8, "raw6_exit_net"},
-    {0xffffff8f78ffa6ec, "idProduct_show"},
-    {0xffffff8f78fd99c0, "perf_tp_event"},
-    {0xffffff8f78fe1468, "rpmh_tx_done"},
-    {0xffffff8f78fda274, "page_unlock_anon_vma_read"},
-    {0xffffff8f78ffedfc, "vmstat_period_ms_operations_open"},
-    {0xffffff8f78fe0148, "devm_gpio_request"},
-    {0xffffff8f77915028, "ctx_sched_out"},
-    {0xffffff8f77ccdc2c, "gcm_hash_crypt_remain_continue"},
-    {0xffffff8f790022ec, "loop_init"},
-    {0xffffff8f78ff0004, "pcim_release"},
-    {0xffffff8f78fe1d8c, "uart_close"},
-    {0xffffff8f78fda9d4, "pipe_lock"},
-    {0xffffff8f78e62c68, "local_bh_enable.117091"},
-    {0xffffff8f78fd918c, "fork_idle"},
-    {0xffffff8f78fe24c4, "drm_dp_downstream_debug"},
-    {0xffffff8f78ff41d0, "inet_addr_onlink"},
-    {0xffffff8f78fdf2d4, "idr_alloc"},
-    {0xffffff8f78ff073c, "fts_remove"},
-    {0xffffff8f78ffe294, "xfrm4_local_error"},
-    {0xffffff8f79001994, "cpu_feature_match_PMULL_init"},
-    {0xffffff8f78ff4740, "xfrm_state_find"},
-    {0xffffff8f78ff58b0, "inet_del_offload"},
-    {0xffffff8f742041ac, "csr_is_conn_state_connected_infra"},
-    {0xffffff8f78fe1fd4, "diag_add_client"},
-    {0xffffff8f78ffc000, "trace_raw_output_mm_vmscan_kswapd_sleep"},
-    {0xffffff8f78fe6388, "scsi_queue_insert"},
-    {0xffffff8f78fdd480, "selinux_sb_clone_mnt_opts"},
-    {0xffffff8f78fe0e9c, "clk_fixed_rate_recalc_rate"},
-    {0xffffff8f78fedaec, "cap_inode_killpriv"},
-    {0xffffff8f79002b64, "audio_amrwb_init"},
-};
-
-}  // namespace
-
-static void BM_KallSyms(benchmark::State& state) {
-  perfetto::KernelSymbolMap::kTokenIndexSampling =
-      static_cast<size_t>(state.range(0));
-  perfetto::KernelSymbolMap::kSymIndexSampling =
-      static_cast<size_t>(state.range(1));
-  perfetto::KernelSymbolMap kallsyms;
-
-  // Don't run the benchmark on the CI as it requires pushing all test data,
-  // which slows down significantly the CI.
-  const bool skip = IsBenchmarkFunctionalOnly();
-  if (!skip) {
-    kallsyms.Parse(perfetto::base::GetTestDataPath("test/data/kallsyms.txt"));
-  }
-
-  for (auto _ : state) {
-    for (size_t i = 0; i < perfetto::base::ArraySize(kExpectedSyms); i++) {
-      const auto& exp = kExpectedSyms[i];
-      PERFETTO_CHECK(skip || kallsyms.Lookup(exp.addr) == exp.name);
-    }
-  }
-
-  state.counters["mem"] = static_cast<double>(kallsyms.size_bytes());
-}
-
-BENCHMARK(BM_KallSyms)->Apply(BenchmarkArgs);
diff --git a/src/kallsyms/kernel_symbol_map_unittest.cc b/src/kallsyms/kernel_symbol_map_unittest.cc
deleted file mode 100644
index deba34a..0000000
--- a/src/kallsyms/kernel_symbol_map_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/kallsyms/kernel_symbol_map.h"
-
-#include <inttypes.h>
-
-#include <random>
-#include <unordered_map>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/temp_file.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-using TokenId = KernelSymbolMap::TokenTable::TokenId;
-
-std::string Lookup(KernelSymbolMap::TokenTable& tokens, TokenId id) {
-  base::StringView sv = tokens.Lookup(id);
-  std::string str;
-  str.reserve(sv.size() + 1);
-  for (const char c : sv)
-    str.push_back(c & 0x7f);
-  return str;
-}
-
-TEST(KernelSymbolMapTest, TokenTable) {
-  KernelSymbolMap::TokenTable tokens;
-  ASSERT_EQ(tokens.Add("a"), 1u);
-  ASSERT_EQ(tokens.Add("bb"), 2u);
-  ASSERT_EQ(tokens.Add("ccc"), 3u);
-  ASSERT_EQ(tokens.Add("foobar"), 4u);
-  ASSERT_EQ(tokens.Add("foobaz"), 5u);
-  ASSERT_EQ(tokens.Add("_"), 6u);
-  ASSERT_EQ(Lookup(tokens, 0), "");
-  ASSERT_EQ(Lookup(tokens, 1), "a");
-  ASSERT_EQ(Lookup(tokens, 2), "bb");
-  ASSERT_EQ(Lookup(tokens, 3), "ccc");
-  ASSERT_EQ(Lookup(tokens, 4), "foobar");
-  ASSERT_EQ(Lookup(tokens, 5), "foobaz");
-  ASSERT_EQ(Lookup(tokens, 6), "_");
-  ASSERT_EQ(Lookup(tokens, 0), "");
-  ASSERT_EQ(Lookup(tokens, 42), "<error>");
-}
-
-TEST(KernelSymbolMapTest, ManyTokens) {
-  KernelSymbolMap::TokenTable tokens;
-  std::unordered_map<TokenId, std::string> tok_map;
-  static std::minstd_rand rng(0);
-  for (int rep = 0; rep < 10000; rep++) {
-    static const size_t kNameMax = 128;
-    std::string sym_name;
-    sym_name.reserve(kNameMax);
-    size_t len = 1 + (rng() % kNameMax);
-    for (size_t j = 0; j < len; j++)
-      sym_name.push_back(rng() & 0x7f);
-    TokenId id = tokens.Add(sym_name);
-    ASSERT_EQ(tok_map.count(id), 0u);
-    tok_map[id] = sym_name;
-  }
-  for (const auto& kv : tok_map) {
-    ASSERT_EQ(Lookup(tokens, kv.first), kv.second);
-  }
-}
-
-TEST(KernelSymbolMapTest, EdgeCases) {
-  base::TempFile tmp = base::TempFile::Create();
-  static const char kContents[] = R"(ffffff8f73e2fa10 t one
-ffffff8f73e2fa20 t two_
-ffffff8f73e2fa30 t _three  [module_name_ignored]
-ffffff8f73e2fa40 x ignore
-ffffff8f73e2fa40 t _fo_ur_
-ffffff8f73e2fa50 t _five__.cfi
-ffffff8f73e2fa60 t __si__x__
-ffffff8f73e2fa70 t ___se___v_e__n___
-ffffff8f73e2fa80 t _eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_should_be_truncated_exactly_here_because_this_is_the_128_char_TRUNCATED_HERE
-ffffff8f73e2fa90 t NiNe
-)";
-  base::WriteAll(tmp.fd(), kContents, sizeof(kContents));
-  base::FlushFile(tmp.fd());
-
-  KernelSymbolMap kallsyms;
-  EXPECT_EQ(kallsyms.Lookup(0x42), "");
-
-  kallsyms.Parse(tmp.path().c_str());
-  EXPECT_EQ(kallsyms.num_syms(), 9u);
-
-  // Test first exact lookups.
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa10ULL), "one");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa20ULL), "two_");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa30LL), "_three");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa40ULL), "_fo_ur_");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa50ULL), "_five__");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa60ULL), "__si__x__");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa70ULL), "___se___v_e__n___");
-  EXPECT_EQ(
-      kallsyms.Lookup(0xffffff8f73e2fa80ULL),
-      "_eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_"
-      "should_be_truncated_exactly_here_because_this_is_the_128_char");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa90ULL), "NiNe");
-
-  // Now check bound searches.
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa00ULL), "");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa11ULL), "one");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa19ULL), "one");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa71ULL), "___se___v_e__n___");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa91ULL), "NiNe");
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa99ULL), "NiNe");
-
-  // This is too far from the last symbol and should fail.
-  EXPECT_EQ(kallsyms.Lookup(0xffffff8fffffffffULL), "");
-}
-
-TEST(KernelSymbolMapTest, GoldenTest) {
-  std::string fake_kallsyms;
-  fake_kallsyms.reserve(8 * 1024 * 1024);
-  static std::minstd_rand rng(0);
-  static const size_t kNameMax = 64;
-  std::map<uint64_t, std::string> symbols;
-  for (int rep = 0; rep < 1000; rep++) {
-    uint64_t addr = static_cast<uint64_t>(rng());
-    if (symbols.count(addr))
-      continue;
-    static const char kCharset[] = "_abcdef";
-    char sym_name[kNameMax + 1];  // Deliberately not initialized.
-    size_t sym_name_len = 1 + (rng() % kNameMax);
-    for (size_t i = 0; i < sym_name_len; i++)
-      sym_name[i] = kCharset[rng() % strlen(kCharset)];
-    sym_name[sym_name_len] = '\0';
-    char line[kNameMax + 40];
-    sprintf(line, "%" PRIx64 " t %s\n", addr, sym_name);
-    symbols[addr] = sym_name;
-    fake_kallsyms += line;
-  }
-  base::TempFile tmp = base::TempFile::Create();
-  base::WriteAll(tmp.fd(), fake_kallsyms.data(), fake_kallsyms.size());
-  base::FlushFile(tmp.fd());
-
-  KernelSymbolMap kallsyms;
-  kallsyms.Parse(tmp.path().c_str());
-  ASSERT_EQ(kallsyms.num_syms(), symbols.size());
-  for (const auto& kv : symbols) {
-    ASSERT_EQ(kallsyms.Lookup(kv.first), kv.second);
-  }
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/kallsyms/lazy_kernel_symbolizer.cc b/src/kallsyms/lazy_kernel_symbolizer.cc
deleted file mode 100644
index 8ed0af8..0000000
--- a/src/kallsyms/lazy_kernel_symbolizer.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/kallsyms/lazy_kernel_symbolizer.h"
-
-#include <string>
-
-#include <unistd.h>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "src/kallsyms/kernel_symbol_map.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/system_properties.h>
-#endif
-
-namespace perfetto {
-
-namespace {
-
-const char kKallsymsPath[] = "/proc/kallsyms";
-const char kPtrRestrictPath[] = "/proc/sys/kernel/kptr_restrict";
-const char kLowerPtrRestrictAndroidProp[] = "security.lower_kptr_restrict";
-
-// This class takes care of temporarily lowering kptr_restrict and putting it
-// back to the original value if necessary. It solves the following problem:
-// When reading /proc/kallsyms on Linux/Android, the symbol addresses can be
-// masked out (i.e. they are all 00000000) through the kptr_restrict file.
-// On Android kptr_restrict defaults to 2. On Linux, it depends on the
-// distribution. On Android we cannot simply write() kptr_restrict ourselves.
-// Doing so requires the union of:
-// - filesystem ACLs: kptr_restrict is rw-r--r--// and owned by root.
-// - Selinux rules: kptr_restrict is labelled as proc_security and restricted.
-// - CAP_SYS_ADMIN: when writing to kptr_restrict, the kernel enforces that the
-//                  caller has the SYS_ADMIN capability at write() time.
-// The latter would be problematic, we don't want traced_probes to have that,
-// CAP_SYS_ADMIN is too broad.
-// Instead, we opt for the following model: traced_probes sets an Android
-// property introduced in S (security.lower_kptr_restrict); init (which
-// satisfies all the requirements above) in turn sets kptr_restrict.
-// On Linux and standalone builds, instead, we don't have many options. Either:
-// - The system administrator takes care of lowering kptr_restrict before
-//   tracing.
-// - The system administrator runs traced_probes as root / CAP_SYS_ADMIN and we
-//   temporarily lower and restore kptr_restrict ourselves.
-// This class deals with all these cases.
-class ScopedKptrUnrestrict {
- public:
-  ScopedKptrUnrestrict();   // Lowers kptr_restrict if necessary.
-  ~ScopedKptrUnrestrict();  // Restores the initial kptr_restrict.
-
- private:
-  static void WriteKptrRestrict(const std::string&);
-
-  static const bool kUseAndroidProperty;
-  std::string initial_value_;
-  bool restore_on_dtor_ = true;
-};
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-// This is true only on Android in-tree builds (not on standalone).
-const bool ScopedKptrUnrestrict::kUseAndroidProperty = true;
-#else
-const bool ScopedKptrUnrestrict::kUseAndroidProperty = false;
-#endif
-
-ScopedKptrUnrestrict::ScopedKptrUnrestrict() {
-  if (LazyKernelSymbolizer::CanReadKernelSymbolAddresses()) {
-    // Everything seems to work (e.g., we are running as root and kptr_restrict
-    // is < 2). Don't touching anything.
-    restore_on_dtor_ = false;
-    return;
-  }
-
-  if (kUseAndroidProperty) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    __system_property_set(kLowerPtrRestrictAndroidProp, "1");
-#endif
-    // Init takes some time to react to the property change.
-    // Unfortunately, we cannot read kptr_restrict because of SELinux. Instead,
-    // we detect this by reading the initial lines of kallsyms and checking
-    // that they are non-zero. This loop waits for at most 250ms (50 * 5ms).
-    for (int attempt = 1; attempt <= 50; ++attempt) {
-      usleep(5000);
-      if (LazyKernelSymbolizer::CanReadKernelSymbolAddresses())
-        return;
-    }
-    PERFETTO_ELOG("kallsyms addresses are still masked after setting %s",
-                  kLowerPtrRestrictAndroidProp);
-    return;
-  }  // if (kUseAndroidProperty)
-
-  // On Linux and Android standalone, read the kptr_restrict value and lower it
-  // if needed.
-  bool read_res = base::ReadFile(kPtrRestrictPath, &initial_value_);
-  if (!read_res) {
-    PERFETTO_PLOG("Failed to read %s", kPtrRestrictPath);
-    return;
-  }
-
-  // Progressively lower kptr_restrict until we can read kallsyms.
-  for (int value = atoi(initial_value_.c_str()); value > 0; --value) {
-    WriteKptrRestrict(std::to_string(value));
-    if (LazyKernelSymbolizer::CanReadKernelSymbolAddresses())
-      return;
-  }
-}
-
-ScopedKptrUnrestrict::~ScopedKptrUnrestrict() {
-  if (!restore_on_dtor_)
-    return;
-  if (kUseAndroidProperty) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    __system_property_set(kLowerPtrRestrictAndroidProp, "0");
-#endif
-  } else if (!initial_value_.empty()) {
-    WriteKptrRestrict(initial_value_);
-  }
-}
-
-void ScopedKptrUnrestrict::WriteKptrRestrict(const std::string& value) {
-  // Note: kptr_restrict requires O_WRONLY. O_RDWR won't work.
-  PERFETTO_DCHECK(!value.empty());
-  base::ScopedFile fd = base::OpenFile(kPtrRestrictPath, O_WRONLY);
-  auto wsize = write(*fd, value.c_str(), value.size());
-  if (wsize <= 0)
-    PERFETTO_PLOG("Failed to set %s to %s", kPtrRestrictPath, value.c_str());
-}
-
-}  // namespace
-
-LazyKernelSymbolizer::LazyKernelSymbolizer() = default;
-LazyKernelSymbolizer::~LazyKernelSymbolizer() = default;
-
-KernelSymbolMap* LazyKernelSymbolizer::GetOrCreateKernelSymbolMap() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (symbol_map_)
-    return symbol_map_.get();
-
-  symbol_map_.reset(new KernelSymbolMap());
-
-  // If kptr_restrict is set, try temporarily lifting it (it works only if
-  // traced_probes is run as a privileged user).
-  ScopedKptrUnrestrict kptr_unrestrict;
-  symbol_map_->Parse(kKallsymsPath);
-  return symbol_map_.get();
-}
-
-void LazyKernelSymbolizer::Destroy() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  symbol_map_.reset();
-  base::MaybeReleaseAllocatorMemToOS();  // For Scudo, b/170217718.
-}
-
-// static
-bool LazyKernelSymbolizer::CanReadKernelSymbolAddresses(
-    const char* ksyms_path_for_testing) {
-  auto* path = ksyms_path_for_testing ? ksyms_path_for_testing : kKallsymsPath;
-  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
-  if (!fd) {
-    PERFETTO_PLOG("open(%s) failed", kKallsymsPath);
-    return false;
-  }
-  // Don't just use fscanf() as that might read the whole file (b/36473442).
-  char buf[4096];
-  auto rsize_signed = base::Read(*fd, buf, sizeof(buf) - 1);
-  if (rsize_signed <= 0) {
-    PERFETTO_PLOG("read(%s) failed", kKallsymsPath);
-    return false;
-  }
-  size_t rsize = static_cast<size_t>(rsize_signed);
-  buf[rsize] = '\0';
-
-  // Iterate over the first page of kallsyms. If we find any non-zero address
-  // call it success. If all addresses are 0, pessimistically assume
-  // kptr_restrict is still restricted.
-  // We cannot look only at the first line because on some devices
-  // /proc/kallsyms can look like this (note the zeros in the first two addrs):
-  // 0000000000000000 A fixed_percpu_data
-  // 0000000000000000 A __per_cpu_start
-  // 0000000000001000 A cpu_debug_store
-  bool reading_addr = true;
-  bool addr_is_zero = true;
-  for (size_t i = 0; i < rsize; i++) {
-    const char c = buf[i];
-    if (reading_addr) {
-      const bool is_hex = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
-      if (is_hex) {
-        addr_is_zero = addr_is_zero && c == '0';
-      } else {
-        if (!addr_is_zero)
-          return true;
-        reading_addr = false;  // Will consume the rest of the line until \n.
-      }
-    } else if (c == '\n') {
-      reading_addr = true;
-    }  // if (!reading_addr)
-  }    // for char in buf
-
-  return false;
-}
-
-}  // namespace perfetto
diff --git a/src/kallsyms/lazy_kernel_symbolizer.h b/src/kallsyms/lazy_kernel_symbolizer.h
deleted file mode 100644
index 6f954e5..0000000
--- a/src/kallsyms/lazy_kernel_symbolizer.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KALLSYMS_LAZY_KERNEL_SYMBOLIZER_H_
-#define SRC_KALLSYMS_LAZY_KERNEL_SYMBOLIZER_H_
-
-#include <memory>
-
-#include "perfetto/ext/base/thread_checker.h"
-
-namespace perfetto {
-
-class KernelSymbolMap;
-
-// This class is a wrapper around KernelSymbolMap. It serves two purposes:
-// 1. Deals with /proc/kallsyms reads and temporary lowering of kptr_restrict.
-//    KernelSymbolMap is just a parser and doesn't do I/O.
-// 2. Allows to share the same KernelSymbolMap instance across several clients
-//    and tear it down when tracing stops.
-//
-// LazyKernelSymbolizer is owned by the (one) FtraceController. FtraceController
-// handles LazyKernelSymbolizer pointers to  N CpuReader-s (one per CPU). In
-// this way all CpuReader instances can share the same symbol map instance.
-// The object being shared is LazyKernelSymbolizer, which is cheap and always
-// valid. LazyKernelSymbolizer may or may not contain a valid symbol map.
-class LazyKernelSymbolizer {
- public:
-  // Constructs an empty instance. Does NOT load any symbols upon construction.
-  // Loading and parsing happens on the first GetOrCreateKernelSymbolMap() call.
-  LazyKernelSymbolizer();
-  ~LazyKernelSymbolizer();
-
-  // Returns |instance_|, creating it if doesn't exist or was destroyed.
-  KernelSymbolMap* GetOrCreateKernelSymbolMap();
-
-  bool is_valid() const { return !!symbol_map_; }
-
-  // Destroys the |symbol_map_| freeing up memory. A further call to
-  // GetOrCreateKernelSymbolMap() will create it again.
-  void Destroy();
-
-  // Exposed for testing.
-  static bool CanReadKernelSymbolAddresses(
-      const char* ksyms_path_for_testing = nullptr);
-
- private:
-  std::unique_ptr<KernelSymbolMap> symbol_map_;
-  PERFETTO_THREAD_CHECKER(thread_checker_)
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KALLSYMS_LAZY_KERNEL_SYMBOLIZER_H_
diff --git a/src/kallsyms/lazy_kernel_symbolizer_unittest.cc b/src/kallsyms/lazy_kernel_symbolizer_unittest.cc
deleted file mode 100644
index c219dda..0000000
--- a/src/kallsyms/lazy_kernel_symbolizer_unittest.cc
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/kallsyms/lazy_kernel_symbolizer.h"
-
-#include <inttypes.h>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-const char kUnrestrictedKallsyms[] = R"(
-0000000000000000 A fixed_percpu_data
-0000000000000000 A __per_cpu_start
-0000000000001000 A cpu_debug_store
-0000000000002000 A irq_stack_backing_store
-0000000000006000 A cpu_tss_rw
-0000000000009000 A gdt_page
-000000000000a000 A entry_stack_storage
-000000000000b000 A exception_stacks
-0000000000010000 A espfix_stack
-0000000000010008 A espfix_waddr
-0000000000010010 A cpu_llc_id
-0000000000010020 A mce_banks_array
-0000000000010220 A mce_num_banks
-0000000000010228 A cpu_sibling_map
-0000000000010230 A cpu_core_map
-0000000000010238 A cpu_die_map
-0000000000010240 A cpu_info
-0000000000010330 A cpu_llc_shared_map
-0000000000010338 A cpu_number
-0000000000010340 A this_cpu_off
-0000000000010348 A x86_cpu_to_apicid
-000000000001034a A x86_bios_cpu_apicid
-000000000001034c A x86_cpu_to_acpiid
-0000000000010350 A sched_core_priority
-0000000000011000 A svm_data
-0000000000011008 A current_tsc_ratio
-0000000000011010 A saved_epb
-0000000000011018 A cluster_masks
-0000000000011020 A x86_cpu_to_logical_apicid
-0000000000011028 A ipi_mask
-0000000000011030 A menu_devices
-0000000000011098 A cpu_loops_per_jiffy
-00000000000110a0 A cpu_hw_events
-00000000000123b0 A pmc_prev_left
-00000000000125b0 A perf_nmi_tstamp
-0000000000013000 A bts_ctx
-0000000000016000 A insn_buffer
-0000000000016008 A pt_ctx
-00000000000160b0 A cpu_tsc_khz
-00000000000160b8 A current_vcpu
-00000000000160c0 A loaded_vmcss_on_cpu
-00000000000160d0 A current_vmcs
-00000000000160d8 A vmxarea
-00000000000160e0 A blocked_vcpu_on_cpu
-00000000000160f0 A blocked_vcpu_on_cpu_lock
-00000000000160f8 A irq_regs
-0000000000016100 A nmi_state
-0000000000016108 A nmi_cr2
-0000000000016110 A update_debug_stack
-0000000000016118 A last_nmi_rip
-0000000000016120 A nmi_stats
-0000000000016130 A swallow_nmi
-0000000000016140 A vector_irq
-0000000000028458 A processor_device_array
-0000000000028460 A acpi_cpuidle_device
-0000000000028470 A acpi_cstate
-00000000000284c0 A cpufreq_thermal_reduction_pctg
-00000000000284c8 A cpc_desc_ptr
-00000000000284d0 A cpu_pcc_subspace_idx
-00000000000284d8 A irq_randomness
-00000000000284f8 A batched_entropy_u64
-0000000000028540 A batched_entropy_u32
-00000000000285c0 A drm_unplug_srcu_srcu_data
-0000000000028740 A device_links_srcu_srcu_data
-00000000000288c0 A cpu_sys_devices
-00000000000288c8 A ci_cpu_cacheinfo
-00000000000288e0 A ci_cache_dev
-00000000000288e8 A ci_index_dev
-0000000000028900 A wakeup_srcu_srcu_data
-0000000000028a80 A flush_idx
-0000000000028ac0 A dax_srcu_srcu_data
-0000000000028c40 A cpufreq_cpu_data
-0000000000028c80 A cpufreq_transition_notifier_list_head_srcu_data
-0000000000028e00 A cpu_dbs
-0000000000028e30 A cpuidle_devices
-0000000000028e38 A cpuidle_dev
-00000000000290f8 A netdev_alloc_cache
-0000000000029110 A napi_alloc_cache
-0000000000029330 A flush_works
-0000000000029360 A bpf_redirect_info
-0000000000029388 A bpf_sp
-0000000000029588 A nf_skb_duplicated
-000000000002958c A xt_recseq
-0000000000029590 A rt_cache_stat
-00000000000295b0 A tsq_tasklet
-00000000000295e8 A xfrm_trans_tasklet
-0000000000029628 A radix_tree_preloads
-0000000000029640 A irq_stat
-00000000000296c0 A cyc2ns
-0000000000029700 A cpu_tlbstate
-0000000000029780 A flush_tlb_info
-00000000000297c0 A cpu_worker_pools
-0000000000029ec0 A runqueues
-000000000002aa80 A sched_clock_data
-000000000002aac0 A osq_node
-000000000002ab00 A qnodes
-000000000002ab40 A rcu_data
-000000000002ae80 A cfd_data
-000000000002aec0 A call_single_queue
-000000000002af00 A csd_data
-000000000002af40 A softnet_data
-000000000002b200 A rt_uncached_list
-000000000002b240 A rt6_uncached_list
-000000000002b258 A __per_cpu_end
-ffffffffb7e00000 T startup_64
-ffffffffb7e00000 T _stext
-ffffffffb7e00000 T _text
-ffffffffb7e00030 T secondary_startup_64
-ffffffffb7e000e0 T verify_cpu
-ffffffffb7e001e0 T start_cpu0
-ffffffffb7e001f0 T __startup_64
-)";
-
-const char kRestrictedKallsyms[] = R"(
-0000000000000000 A fixed_percpu_data
-0000000000000000 A __per_cpu_start
-0000000000000000 A cpu_debug_store
-0000000000000000 A irq_stack_backing_store
-0000000000000000 A cpu_tss_rw
-0000000000000000 A gdt_page
-0000000000000000 A entry_stack_storage
-0000000000000000 A exception_stacks
-0000000000000000 A espfix_stack
-0000000000000000 A espfix_waddr
-0000000000000000 A cpu_llc_id
-0000000000000000 A mce_banks_array
-0000000000000000 A mce_num_banks
-0000000000000000 A cpu_sibling_map
-0000000000000000 A cpu_core_map
-0000000000000000 A cpu_die_map
-0000000000000000 A cpu_info
-0000000000000000 A cpu_llc_shared_map
-0000000000000000 A cpu_number
-0000000000000000 A this_cpu_off
-0000000000000000 A x86_cpu_to_apicid
-0000000000000000 A x86_bios_cpu_apicid
-0000000000000000 A x86_cpu_to_acpiid
-0000000000000000 A sched_core_priority
-0000000000000000 A svm_data
-0000000000000000 A current_tsc_ratio
-0000000000000000 A saved_epb
-0000000000000000 A cluster_masks
-0000000000000000 A x86_cpu_to_logical_apicid
-0000000000000000 A ipi_mask
-0000000000000000 A menu_devices
-0000000000000000 A cpu_loops_per_jiffy
-0000000000000000 A cpu_hw_events
-0000000000000000 A pmc_prev_left
-0000000000000000 A perf_nmi_tstamp
-0000000000000000 A bts_ctx
-0000000000000000 A insn_buffer
-0000000000000000 A pt_ctx
-0000000000000000 A cpu_tsc_khz
-0000000000000000 A current_vcpu
-0000000000000000 A loaded_vmcss_on_cpu
-0000000000000000 A current_vmcs
-0000000000000000 A vmxarea
-0000000000000000 A blocked_vcpu_on_cpu
-0000000000000000 A blocked_vcpu_on_cpu_lock
-0000000000000000 A irq_regs
-0000000000000000 A nmi_state
-0000000000000000 A nmi_cr2
-0000000000000000 A update_debug_stack
-0000000000000000 A last_nmi_rip
-0000000000000000 A nmi_stats
-0000000000000000 A swallow_nmi
-0000000000000000 A vector_irq
-0000000000000000 A processor_device_array
-0000000000000000 A acpi_cpuidle_device
-0000000000000000 A acpi_cstate
-0000000000000000 A cpufreq_thermal_reduction_pctg
-0000000000000000 A cpc_desc_ptr
-0000000000000000 A cpu_pcc_subspace_idx
-0000000000000000 A irq_randomness
-0000000000000000 A batched_entropy_u64
-0000000000000000 A batched_entropy_u32
-0000000000000000 A drm_unplug_srcu_srcu_data
-0000000000000000 A device_links_srcu_srcu_data
-0000000000000000 A cpu_sys_devices
-0000000000000000 A ci_cpu_cacheinfo
-0000000000000000 A ci_cache_dev
-0000000000000000 A ci_index_dev
-0000000000000000 A wakeup_srcu_srcu_data
-0000000000000000 A flush_idx
-0000000000000000 A dax_srcu_srcu_data
-0000000000000000 A cpufreq_cpu_data
-0000000000000000 A cpufreq_transition_notifier_list_head_srcu_data
-0000000000000000 A cpu_dbs
-0000000000000000 A cpuidle_devices
-0000000000000000 A cpuidle_dev
-0000000000000000 A netdev_alloc_cache
-0000000000000000 A napi_alloc_cache
-0000000000000000 A flush_works
-0000000000000000 A bpf_redirect_info
-0000000000000000 A bpf_sp
-0000000000000000 A nf_skb_duplicated
-0000000000000000 A xt_recseq
-0000000000000000 A rt_cache_stat
-0000000000000000 A tsq_tasklet
-0000000000000000 A xfrm_trans_tasklet
-0000000000000000 A radix_tree_preloads
-0000000000000000 A irq_stat
-0000000000000000 A cyc2ns
-0000000000000000 A cpu_tlbstate
-0000000000000000 A flush_tlb_info
-0000000000000000 A cpu_worker_pools
-0000000000000000 A runqueues
-0000000000000000 A sched_clock_data
-0000000000000000 A osq_node
-0000000000000000 A qnodes
-0000000000000000 A rcu_data
-0000000000000000 A cfd_data
-0000000000000000 A call_single_queue
-0000000000000000 A csd_data
-0000000000000000 A softnet_data
-0000000000000000 A rt_uncached_list
-0000000000000000 A rt6_uncached_list
-0000000000000000 A __per_cpu_end
-0000000000000000 T startup_64
-0000000000000000 T _stext
-0000000000000000 T _text
-0000000000000000 T secondary_startup_64
-0000000000000000 T verify_cpu
-0000000000000000 T start_cpu0
-0000000000000000 T __startup_64
-)";
-
-TEST(LazyKernelSymbolizerTest, CanReadKernelSymbolAddresses) {
-  {
-    base::TempFile tmp = base::TempFile::Create();
-    base::WriteAll(tmp.fd(), kRestrictedKallsyms, sizeof(kRestrictedKallsyms));
-    base::FlushFile(tmp.fd());
-    EXPECT_FALSE(
-        LazyKernelSymbolizer::CanReadKernelSymbolAddresses(tmp.path().c_str()));
-  }
-
-  {
-    base::TempFile tmp = base::TempFile::Create();
-    base::WriteAll(tmp.fd(), kUnrestrictedKallsyms,
-                   sizeof(kUnrestrictedKallsyms));
-    base::FlushFile(tmp.fd());
-    EXPECT_TRUE(
-        LazyKernelSymbolizer::CanReadKernelSymbolAddresses(tmp.path().c_str()));
-  }
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 637436f..4b06501 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_cc_proto_descriptor.gni")
 import("../../gn/proto_library.gni")
 import("../../gn/test.gni")
 
@@ -41,6 +40,10 @@
   sources = [ "trigger_perfetto_main.cc" ]
 }
 
+source_set("perfetto_atoms") {
+  sources = [ "perfetto_atoms.h" ]
+}
+
 # Contains all the implementation but not the main() entry point. This target
 # is shared both by the executable and tests.
 source_set("perfetto_cmd") {
@@ -49,13 +52,13 @@
     "../../include/perfetto/ext/traced",
   ]
   deps = [
-    ":gen_cc_config_descriptor",
+    ":perfetto_atoms",
     ":trigger_producer",
     "../../gn:default_deps",
     "../../protos/perfetto/common:cpp",
     "../../protos/perfetto/config:cpp",
     "../../protos/perfetto/config/ftrace:cpp",
-    "../android_stats",
+    "../android_internal:lazy_library_loader",
     "../base",
     "../protozero",
     "../tracing/ipc/consumer",
@@ -72,20 +75,15 @@
     "pbtxt_to_pb.h",
     "perfetto_cmd.cc",
     "perfetto_cmd.h",
+    "perfetto_config.descriptor.h",
     "rate_limiter.cc",
     "rate_limiter.h",
   ]
   if (is_android) {
-    deps += [ "../android_internal:lazy_library_loader" ]
     sources += [ "perfetto_cmd_android.cc" ]
   }
 }
 
-perfetto_cc_proto_descriptor("gen_cc_config_descriptor") {
-  descriptor_name = "perfetto_config.descriptor"
-  descriptor_target = "../../protos/perfetto/config:perfetto_config_descriptor"
-}
-
 source_set("trigger_perfetto_cmd") {
   public_deps = [
     ":protos",
@@ -94,7 +92,6 @@
   deps = [
     ":trigger_producer",
     "../../gn:default_deps",
-    "../android_stats",
     "../base",
     "../tracing/ipc/producer",
   ]
diff --git a/src/perfetto_cmd/config.cc b/src/perfetto_cmd/config.cc
index f2b40d4..1f1d2fd 100644
--- a/src/perfetto_cmd/config.cc
+++ b/src/perfetto_cmd/config.cc
@@ -19,7 +19,6 @@
 #include <stdlib.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/trace_config.h"
 
@@ -32,7 +31,7 @@
 
 bool SplitValueAndUnit(const std::string& arg, ValueUnit* out) {
   char* end;
-  if (arg.empty())
+  if (!arg.size())
     return false;
   out->first = strtoull(arg.c_str(), &end, 10);
   if (end == arg.data())
@@ -50,11 +49,6 @@
     return true;
   }
 
-  if (arg == "0") {
-    *out = 0;
-    return true;
-  }
-
   ValueUnit value_unit{};
   if (!SplitValueAndUnit(arg, &value_unit))
     return false;
@@ -117,18 +111,10 @@
   std::vector<std::string> atrace_apps = options.atrace_apps;
 
   for (const auto& category : options.categories) {
-    if (base::Contains(category, '/')) {
-      ftrace_events.push_back(category);
-    } else {
+    if (category.find("/") == std::string::npos) {
       atrace_categories.push_back(category);
-    }
-
-    // For the gfx category, also add the frame timeline data source
-    // as it's very useful for debugging gfx issues.
-    if (category == "gfx") {
-      auto* frame_timeline = config->add_data_sources();
-      frame_timeline->mutable_config()->set_name(
-          "android.surfaceflinger.frametimeline");
+    } else {
+      ftrace_events.push_back(category);
     }
   }
 
diff --git a/src/perfetto_cmd/config_unittest.cc b/src/perfetto_cmd/config_unittest.cc
index cc1db34..99b57f9 100644
--- a/src/perfetto_cmd/config_unittest.cc
+++ b/src/perfetto_cmd/config_unittest.cc
@@ -45,12 +45,6 @@
   EXPECT_EQ(config.duration_ms(), 2u);
 }
 
-TEST_F(CreateConfigFromOptionsTest, ZeroTime) {
-  options.time = "0";
-  ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 0u);
-}
-
 TEST_F(CreateConfigFromOptionsTest, Seconds) {
   options.time = "100s";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
@@ -69,12 +63,6 @@
   EXPECT_EQ(config.duration_ms(), 2 * 60 * 60 * 1000u);
 }
 
-TEST_F(CreateConfigFromOptionsTest, ZeroBufferSize) {
-  options.buffer_size = "0";
-  ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.buffers()[0].size_kb(), 0u);
-}
-
 TEST_F(CreateConfigFromOptionsTest, Kilobyte) {
   options.buffer_size = "2kb";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
diff --git a/src/perfetto_cmd/packet_writer.cc b/src/perfetto_cmd/packet_writer.cc
index 2bee2f0..4897469 100644
--- a/src/perfetto_cmd/packet_writer.cc
+++ b/src/perfetto_cmd/packet_writer.cc
@@ -19,12 +19,13 @@
 #include <array>
 
 #include <fcntl.h>
+#include <getopt.h>
 #include <signal.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/paged_memory.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
@@ -37,7 +38,9 @@
 namespace perfetto {
 namespace {
 
+using protozero::proto_utils::kMessageLengthFieldSize;
 using protozero::proto_utils::MakeTagLengthDelimited;
+using protozero::proto_utils::WriteRedundantVarInt;
 using protozero::proto_utils::WriteVarInt;
 using Preamble = std::array<char, 16>;
 
diff --git a/src/perfetto_cmd/packet_writer_unittest.cc b/src/perfetto_cmd/packet_writer_unittest.cc
index 4825384..fb64f50 100644
--- a/src/perfetto_cmd/packet_writer_unittest.cc
+++ b/src/perfetto_cmd/packet_writer_unittest.cc
@@ -17,6 +17,7 @@
 #include "src/perfetto_cmd/packet_writer.h"
 
 #include <string.h>
+#include <unistd.h>
 
 #include <random>
 
diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc
index b78d938..6f270b1 100644
--- a/src/perfetto_cmd/pbtxt_to_pb.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb.cc
@@ -47,20 +47,12 @@
 
 namespace {
 
-constexpr bool IsOct(char c) {
-  return (c >= '0' && c <= '7');
-}
-
-constexpr bool IsDigit(char c) {
-  return (c >= '0' && c <= '9');
-}
-
 constexpr bool IsIdentifierStart(char c) {
   return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '_';
 }
 
 constexpr bool IsIdentifierBody(char c) {
-  return IsIdentifierStart(c) || IsDigit(c);
+  return IsIdentifierStart(c) || isdigit(c);
 }
 
 const char* FieldToTypeName(const FieldDescriptorProto* field) {
@@ -158,22 +150,19 @@
   }
 
   void NumericField(Token key, Token value) {
-    const FieldDescriptorProto* field =
-        FindFieldByName(key, value,
-                        {
-                            FieldDescriptorProto::TYPE_UINT64,
-                            FieldDescriptorProto::TYPE_UINT32,
-                            FieldDescriptorProto::TYPE_INT64,
-                            FieldDescriptorProto::TYPE_SINT64,
-                            FieldDescriptorProto::TYPE_INT32,
-                            FieldDescriptorProto::TYPE_SINT32,
-                            FieldDescriptorProto::TYPE_FIXED64,
-                            FieldDescriptorProto::TYPE_SFIXED64,
-                            FieldDescriptorProto::TYPE_FIXED32,
-                            FieldDescriptorProto::TYPE_SFIXED32,
-                            FieldDescriptorProto::TYPE_DOUBLE,
-                            FieldDescriptorProto::TYPE_FLOAT,
-                        });
+    const FieldDescriptorProto* field = FindFieldByName(
+        key, value,
+        {
+            FieldDescriptorProto::TYPE_UINT64,
+            FieldDescriptorProto::TYPE_UINT32, FieldDescriptorProto::TYPE_INT64,
+            FieldDescriptorProto::TYPE_SINT64, FieldDescriptorProto::TYPE_INT32,
+            FieldDescriptorProto::TYPE_SINT32,
+            FieldDescriptorProto::TYPE_FIXED64,
+            FieldDescriptorProto::TYPE_SFIXED64,
+            FieldDescriptorProto::TYPE_FIXED32,
+            FieldDescriptorProto::TYPE_SFIXED32,
+            FieldDescriptorProto::TYPE_DOUBLE, FieldDescriptorProto::TYPE_FLOAT,
+        });
     if (!field)
       return;
     const auto& field_type = field->type();
@@ -213,12 +202,11 @@
   }
 
   void StringField(Token key, Token value) {
-    const FieldDescriptorProto* field =
-        FindFieldByName(key, value,
-                        {
-                            FieldDescriptorProto::TYPE_STRING,
-                            FieldDescriptorProto::TYPE_BYTES,
-                        });
+    const FieldDescriptorProto* field = FindFieldByName(
+        key, value,
+        {
+            FieldDescriptorProto::TYPE_STRING, FieldDescriptorProto::TYPE_BYTES,
+        });
     if (!field)
       return;
     uint32_t field_id = static_cast<uint32_t>(field->number());
@@ -229,16 +217,15 @@
     std::unique_ptr<char, base::FreeDeleter> s(
         static_cast<char*>(malloc(value.size())));
     size_t j = 0;
-    const char* const txt = value.txt.data();
     for (size_t i = 0; i < value.size(); i++) {
-      char c = txt[i];
+      char c = value.txt.data()[i];
       if (c == '\\') {
         if (i + 1 >= value.size()) {
           // This should be caught by the lexer.
           PERFETTO_FATAL("Escape at end of string.");
           return;
         }
-        char next = txt[++i];
+        char next = value.txt.data()[++i];
         switch (next) {
           case '\\':
           case '\'':
@@ -267,44 +254,6 @@
           case 'v':
             s.get()[j++] = '\v';
             break;
-          case '0':
-          case '1':
-          case '2':
-          case '3':
-          case '4':
-          case '5':
-          case '6':
-          case '7':
-          case '8':
-          case '9': {
-            // Cases 8 and 9 are not really required and are only added for the
-            // sake of error reporting.
-            bool oct_err = false;
-            if (i + 2 >= value.size() || !IsOct(txt[i + 1]) ||
-                !IsOct(txt[i + 2])) {
-              oct_err = true;
-            } else {
-              char buf[4]{next, txt[++i], txt[++i], '\0'};
-              auto octval = base::CStringToUInt32(buf, 8);
-              if (!octval.has_value() || *octval > 0xff) {
-                oct_err = true;
-              } else {
-                s.get()[j++] = static_cast<char>(static_cast<uint8_t>(*octval));
-              }
-            }
-            if (oct_err) {
-              AddError(value,
-                       "Malformed string escape in $k in proto $n on '$v'. "
-                       "\\NNN escapes must be exactly three octal digits <= "
-                       "\\377 (0xff).",
-                       std::map<std::string, std::string>{
-                           {"$k", key.ToStdString()},
-                           {"$n", descriptor_name()},
-                           {"$v", value.ToStdString()},
-                       });
-            }
-            break;
-          }
           default:
             AddError(value,
                      "Unknown string escape in $k in "
@@ -324,12 +273,11 @@
   }
 
   void IdentifierField(Token key, Token value) {
-    const FieldDescriptorProto* field =
-        FindFieldByName(key, value,
-                        {
-                            FieldDescriptorProto::TYPE_BOOL,
-                            FieldDescriptorProto::TYPE_ENUM,
-                        });
+    const FieldDescriptorProto* field = FindFieldByName(
+        key, value,
+        {
+            FieldDescriptorProto::TYPE_BOOL, FieldDescriptorProto::TYPE_ENUM,
+        });
     if (!field)
       return;
     uint32_t field_id = static_cast<uint32_t>(field->number());
@@ -467,8 +415,7 @@
     if (!field_descriptor) {
       AddError(key, "No field named \"$n\" in proto $p",
                {
-                   {"$n", field_name},
-                   {"$p", descriptor_name()},
+                   {"$n", field_name}, {"$p", descriptor_name()},
                });
       return nullptr;
     }
@@ -602,7 +549,7 @@
           state = kReadingStringValue;
           continue;
         }
-        if (c == '-' || IsDigit(c) || c == '.') {
+        if (c == '-' || isdigit(c)) {
           state = kReadingNumericValue;
           continue;
         }
@@ -629,7 +576,7 @@
           delegate->NumericField(key, value);
           continue;
         }
-        if (IsDigit(c) || c == '.')
+        if (isdigit(c))
           continue;
         break;
 
diff --git a/src/perfetto_cmd/pbtxt_to_pb_unittest.cc b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
index 251c8f0..018e562 100644
--- a/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
@@ -240,8 +240,8 @@
         field_sfixed64: 6;
         field_fixed32: 7;
         field_sfixed32: 8;
-        field_double: 9.9;
-        field_float: 10.10;
+        field_double: 9;
+        field_float: 10;
         field_sint64: 11;
         field_sint32: 12;
         field_string: "13";
@@ -261,33 +261,14 @@
   ASSERT_EQ(fields.field_sfixed64(), 6);
   ASSERT_EQ(fields.field_fixed32(), 7u);
   ASSERT_EQ(fields.field_sfixed32(), 8);
-  ASSERT_DOUBLE_EQ(fields.field_double(), 9.9);
-  ASSERT_FLOAT_EQ(fields.field_float(), 10.10f);
+  ASSERT_DOUBLE_EQ(fields.field_double(), 9);
+  ASSERT_FLOAT_EQ(fields.field_float(), 10);
   ASSERT_EQ(fields.field_sint64(), 11);
   ASSERT_EQ(fields.field_sint32(), 12);
   ASSERT_EQ(fields.field_string(), "13");
   ASSERT_EQ(fields.field_bytes(), "14");
 }
 
-TEST(PbtxtToPb, LeadingDots) {
-  TraceConfig config = ToProto(R"(
-data_sources {
-  config {
-    for_testing {
-      dummy_fields {
-        field_double:  .1;
-        field_float:   .2;
-      }
-    }
-  }
-}
-  )");
-  const auto& fields =
-      config.data_sources()[0].config().for_testing().dummy_fields();
-  ASSERT_DOUBLE_EQ(fields.field_double(), .1);
-  ASSERT_FLOAT_EQ(fields.field_float(), .2f);
-}
-
 TEST(PbtxtToPb, NegativeNumbers) {
   TraceConfig config = ToProto(R"(
 data_sources {
@@ -300,8 +281,8 @@
         field_sfixed64: -4;
         field_fixed32: -5;
         field_sfixed32: -6;
-        field_double: -7.7;
-        field_float: -8.8;
+        field_double: -7;
+        field_float: -8;
         field_sint64: -9;
         field_sint32: -10;
       }
@@ -317,8 +298,8 @@
   ASSERT_EQ(fields.field_sfixed64(), -4);
   ASSERT_EQ(fields.field_fixed32(), static_cast<uint32_t>(-5));
   ASSERT_EQ(fields.field_sfixed32(), -6);
-  ASSERT_DOUBLE_EQ(fields.field_double(), -7.7);
-  ASSERT_FLOAT_EQ(fields.field_float(), -8.8f);
+  ASSERT_DOUBLE_EQ(fields.field_double(), -7);
+  ASSERT_FLOAT_EQ(fields.field_float(), -8);
   ASSERT_EQ(fields.field_sint64(), -9);
   ASSERT_EQ(fields.field_sint32(), -10);
 }
@@ -403,7 +384,6 @@
       ftrace_events: "newline\nnewline"
       ftrace_events: "\"quoted\""
       ftrace_events: "\a\b\f\n\r\t\v\\\'\"\?"
-      ftrace_events: "\0127_\03422.\177"
     }
   }
 }
@@ -418,7 +398,6 @@
   EXPECT_THAT(events, Contains("newline\nnewline"));
   EXPECT_THAT(events, Contains("\"quoted\""));
   EXPECT_THAT(events, Contains("\a\b\f\n\r\t\v\\\'\"\?"));
-  EXPECT_THAT(events, Contains("\0127_\03422.\177"));
 }
 
 TEST(PbtxtToPb, UnknownField) {
diff --git a/src/perfetto_cmd/perfetto_atoms.h b/src/perfetto_cmd/perfetto_atoms.h
new file mode 100644
index 0000000..35903ea
--- /dev/null
+++ b/src/perfetto_cmd/perfetto_atoms.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_PERFETTO_CMD_PERFETTO_ATOMS_H_
+#define SRC_PERFETTO_CMD_PERFETTO_ATOMS_H_
+
+namespace perfetto {
+
+// This must match the values of the PerfettoUploadEvent enum in:
+// frameworks/base/cmds/statsd/src/atoms.proto
+enum class PerfettoStatsdAtom {
+  kUndefined = 0,
+
+  kTraceBegin = 1,
+  kBackgroundTraceBegin = 2,
+
+  kOnConnect = 3,
+  kOnTracingDisabled = 4,
+
+  kUploadDropboxBegin = 5,
+  kUploadDropboxSuccess = 6,
+  kUploadDropboxFailure = 7,
+
+  kUploadIncidentBegin = 8,
+  kUploadIncidentSuccess = 9,
+  kUploadIncidentFailure = 10,
+
+  kFinalizeTraceAndExit = 11,
+
+  kTriggerBegin = 12,
+  kTriggerSuccess = 13,
+  kTriggerFailure = 14,
+
+  kHitGuardrails = 15,
+  kOnTimeout = 16,
+  kNotUploadingEmptyTrace = 17,
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_PERFETTO_CMD_PERFETTO_ATOMS_H_
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 67ea3ea..bdfef73 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -16,25 +16,18 @@
 
 #include "src/perfetto_cmd/perfetto_cmd.h"
 
-#include "perfetto/base/build_config.h"
-
 #include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
-
+#include <unistd.h>
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <sys/system_properties.h>
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 
-// For dup().
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
 #include <fstream>
 #include <iostream>
 #include <iterator>
@@ -43,14 +36,11 @@
 #include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/ctrl_c_handler.h"
 #include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/thread_utils.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/base/uuid.h"
-#include "perfetto/ext/base/version.h"
 #include "perfetto/ext/traced/traced.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
@@ -59,7 +49,6 @@
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/trace_config.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
-#include "src/android_stats/statsd_logging_helper.h"
 #include "src/perfetto_cmd/config.h"
 #include "src/perfetto_cmd/packet_writer.h"
 #include "src/perfetto_cmd/pbtxt_to_pb.h"
@@ -145,27 +134,13 @@
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
 }
 
-base::Optional<PerfettoStatsdAtom> ConvertRateLimiterResponseToAtom(
-    RateLimiter::ShouldTraceResponse resp) {
-  switch (resp) {
-    case RateLimiter::kNotAllowedOnUserBuild:
-      return PerfettoStatsdAtom::kCmdUserBuildTracingNotAllowed;
-    case RateLimiter::kFailedToInitState:
-      return PerfettoStatsdAtom::kCmdFailedToInitGuardrailState;
-    case RateLimiter::kInvalidState:
-      return PerfettoStatsdAtom::kCmdInvalidGuardrailState;
-    case RateLimiter::kHitUploadLimit:
-      return PerfettoStatsdAtom::kCmdHitUploadLimit;
-    case RateLimiter::kOkToTrace:
-      return base::nullopt;
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
 }  // namespace
 
 const char* kStateDir = "/data/misc/perfetto-traces";
 
+using protozero::proto_utils::MakeTagLengthDelimited;
+using protozero::proto_utils::WriteVarInt;
+
 int PerfettoCmd::PrintUsage(const char* argv0) {
   PERFETTO_ELOG(R"(
 Usage: %s
@@ -176,7 +151,7 @@
   --upload                 : Upload field trace (Android only)
   --dropbox        TAG     : DEPRECATED: Use --upload instead
                              TAG should always be set to 'perfetto'
-  --no-guardrails          : Ignore guardrails triggered when using --upload
+  --no-guardrails          : Ignore guardrails triggered when using --dropbox
                              (for testing).
   --txt                    : Parse config as pbtxt. Not for production use.
                              Not a stable API.
@@ -186,8 +161,6 @@
                              human-readable text.
   --query-raw              : Like --query, but prints raw proto-encoded bytes
                              of tracing_service_state.proto.
-  --save-for-bugreport     : If a trace with bugreport_score > 0 is running, it
-                             saves it into a file. Outputs the path when done.
   --help           -h
 
 
@@ -195,9 +168,10 @@
   --time           -t      : Trace duration N[s,m,h] (default: 10s)
   --buffer         -b      : Ring buffer size N[mb,gb] (default: 32mb)
   --size           -s      : Max file size N[mb,gb] (default: in-memory ring-buffer only)
-  --app            -a      : Android (atrace) app name
   ATRACE_CAT               : Record ATRACE_CAT (e.g. wm)
   FTRACE_GROUP/FTRACE_NAME : Record ftrace event (e.g. sched/sched_switch)
+  FTRACE_GROUP/*           : Record all events in group (e.g. sched/*)
+
 
 statsd-specific flags:
   --alert-id           : ID of the alert that triggered this trace.
@@ -205,7 +179,7 @@
   --config-uid         : UID of app which registered the config.
   --subscription-id    : ID of the subscription that triggered this trace.
 
-Detach mode. DISCOURAGED, read https://perfetto.dev/docs/concepts/detached-mode :
+Detach mode. DISCOURAGED, read https://docs.perfetto.dev/#/detached-mode :
   --detach=key          : Detach from the tracing session with the given key.
   --attach=key [--stop] : Re-attach to the session (optionally stop tracing once reattached).
   --is_detached=key     : Check if the session can be re-attached (0:Yes, 2:No, 1:Error).
@@ -215,12 +189,10 @@
 }
 
 int PerfettoCmd::Main(int argc, char** argv) {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   umask(0000);  // make sure that file creation is not affected by umask.
-#endif
+
   enum LongOption {
     OPT_ALERT_ID = 1000,
-    OPT_BUGREPORT,
     OPT_CONFIG_ID,
     OPT_CONFIG_UID,
     OPT_SUBSCRIPTION_ID,
@@ -228,6 +200,7 @@
     OPT_PBTXT_CONFIG,
     OPT_DROPBOX,
     OPT_UPLOAD,
+    OPT_ATRACE_APP,
     OPT_IGNORE_GUARDRAILS,
     OPT_DETACH,
     OPT_ATTACH,
@@ -235,9 +208,8 @@
     OPT_STOP,
     OPT_QUERY,
     OPT_QUERY_RAW,
-    OPT_VERSION,
   };
-  static const option long_options[] = {
+  static const struct option long_options[] = {
       {"help", no_argument, nullptr, 'h'},
       {"config", required_argument, nullptr, 'c'},
       {"out", required_argument, nullptr, 'o'},
@@ -245,7 +217,6 @@
       {"time", required_argument, nullptr, 't'},
       {"buffer", required_argument, nullptr, 'b'},
       {"size", required_argument, nullptr, 's'},
-      {"app", required_argument, nullptr, 'a'},
       {"no-guardrails", no_argument, nullptr, OPT_IGNORE_GUARDRAILS},
       {"txt", no_argument, nullptr, OPT_PBTXT_CONFIG},
       {"upload", no_argument, nullptr, OPT_UPLOAD},
@@ -259,18 +230,17 @@
       {"attach", required_argument, nullptr, OPT_ATTACH},
       {"is_detached", required_argument, nullptr, OPT_IS_DETACHED},
       {"stop", no_argument, nullptr, OPT_STOP},
+      {"app", required_argument, nullptr, OPT_ATRACE_APP},
       {"query", no_argument, nullptr, OPT_QUERY},
       {"query-raw", no_argument, nullptr, OPT_QUERY_RAW},
-      {"version", no_argument, nullptr, OPT_VERSION},
-      {"save-for-bugreport", no_argument, nullptr, OPT_BUGREPORT},
       {nullptr, 0, nullptr, 0}};
 
+  int option_index = 0;
   std::string config_file_name;
   std::string trace_config_raw;
   bool background = false;
   bool ignore_guardrails = false;
   bool parse_as_pbtxt = false;
-  bool upload_flag = false;
   TraceConfig::StatsdMetadata statsd_metadata;
   RateLimiter limiter;
 
@@ -279,7 +249,7 @@
 
   for (;;) {
     int option =
-        getopt_long(argc, argv, "hc:o:dt:b:s:a:", long_options, nullptr);
+        getopt_long(argc, argv, "hc:o:dt:b:s:", long_options, &option_index);
 
     if (option == -1)
       break;  // EOF.
@@ -335,15 +305,9 @@
       continue;
     }
 
-    if (option == 'a') {
-      config_options.atrace_apps.push_back(std::string(optarg));
-      has_config_options = true;
-      continue;
-    }
-
     if (option == OPT_UPLOAD) {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-      upload_flag = true;
+      dropbox_tag_ = "perfetto";
       continue;
 #else
       PERFETTO_ELOG("--upload is only supported on Android");
@@ -354,7 +318,7 @@
     if (option == OPT_DROPBOX) {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
       PERFETTO_CHECK(optarg);
-      upload_flag = true;
+      dropbox_tag_ = optarg;
       continue;
 #else
       PERFETTO_ELOG("--dropbox is only supported on Android");
@@ -398,6 +362,12 @@
       continue;
     }
 
+    if (option == OPT_ATRACE_APP) {
+      config_options.atrace_apps.push_back(std::string(optarg));
+      has_config_options = true;
+      continue;
+    }
+
     if (option == OPT_DETACH) {
       detach_key_ = std::string(optarg);
       PERFETTO_CHECK(!detach_key_.empty());
@@ -433,16 +403,6 @@
       continue;
     }
 
-    if (option == OPT_VERSION) {
-      printf("%s\n", base::GetVersionString());
-      return 0;
-    }
-
-    if (option == OPT_BUGREPORT) {
-      bugreport_ = true;
-      continue;
-    }
-
     return PrintUsage(argv[0]);
   }
 
@@ -471,12 +431,6 @@
     return 1;
   }
 
-  if (bugreport_ &&
-      (is_attach() | is_detach() || query_service_ || has_config_options)) {
-    PERFETTO_ELOG("--save-for-bugreport cannot take any other argument");
-    return 1;
-  }
-
   // Parse the trace config. It can be either:
   // 1) A proto-encoded file/stdin (-c ...).
   // 2) A proto-text file/stdin (-c ... --txt).
@@ -487,7 +441,7 @@
 
   std::vector<std::string> triggers_to_activate;
   bool parsed = false;
-  const bool will_trace = !is_attach() && !query_service_ && !bugreport_;
+  const bool will_trace = !is_attach() && !query_service_;
   if (!will_trace) {
     if ((!trace_config_raw.empty() || has_config_options)) {
       PERFETTO_ELOG("Cannot specify a trace config with this option");
@@ -539,63 +493,32 @@
     uuid_ = uuid.ToString();
   }
 
-  if (!trace_config_->incident_report_config().destination_package().empty() &&
-      !upload_flag) {
-    PERFETTO_ELOG(
-        "Unexpected IncidentReportConfig without --dropbox / --upload.");
-    return 1;
+  if (!trace_config_->incident_report_config().destination_package().empty()) {
+    if (dropbox_tag_.empty()) {
+      PERFETTO_ELOG(
+          "Unexpected IncidentReportConfig without --dropbox / --upload.");
+      return 1;
+    }
   }
 
-  if (trace_config_->activate_triggers().empty() &&
-      trace_config_->incident_report_config().destination_package().empty() &&
-      !trace_config_->incident_report_config().skip_incidentd() &&
-      upload_flag) {
-    PERFETTO_ELOG(
-        "Missing IncidentReportConfig.destination_package with --dropbox / "
-        "--upload.");
-    return 1;
-  }
-
-  // Only save to incidentd if both --upload is set and |skip_incidentd| is
-  // absent or false.
-  save_to_incidentd_ =
-      upload_flag && !trace_config_->incident_report_config().skip_incidentd();
-
-  // Respect the wishes of the config with respect to statsd logging or fall
-  // back on the presence of the --upload flag if not set.
-  switch (trace_config_->statsd_logging()) {
-    case TraceConfig::STATSD_LOGGING_ENABLED:
-      statsd_logging_ = true;
-      break;
-    case TraceConfig::STATSD_LOGGING_DISABLED:
-      statsd_logging_ = false;
-      break;
-    case TraceConfig::STATSD_LOGGING_UNSPECIFIED:
-      statsd_logging_ = upload_flag;
-      break;
-  }
-  trace_config_->set_statsd_logging(statsd_logging_
-                                        ? TraceConfig::STATSD_LOGGING_ENABLED
-                                        : TraceConfig::STATSD_LOGGING_DISABLED);
-
-  // Set up the output file. Either --out or --upload are expected, with the
+  // Set up the output file. Either --out or --dropbox are expected, with the
   // only exception of --attach. In this case the output file is passed when
   // detaching.
-  if (!trace_out_path_.empty() && upload_flag) {
+  if (!trace_out_path_.empty() && !dropbox_tag_.empty()) {
     PERFETTO_ELOG(
-        "Can't log to a file (--out) and incidentd (--upload) at the same "
+        "Can't log to a file (--out) and DropBox (--dropbox) at the same "
         "time");
     return 1;
   }
 
   if (!trace_config_->output_path().empty()) {
-    if (!trace_out_path_.empty() || upload_flag) {
+    if (!trace_out_path_.empty() || !dropbox_tag_.empty()) {
       PERFETTO_ELOG(
-          "Can't pass --out or --upload if output_path is set in the "
+          "Can't pass --out or --dropbox if output_path is set in the "
           "trace config");
       return 1;
     }
-    if (base::FileExists(trace_config_->output_path())) {
+    if (access(trace_config_->output_path().c_str(), F_OK) == 0) {
       PERFETTO_ELOG(
           "The output_path must not exist, the service cannot overwrite "
           "existing files for security reasons. Remove %s or use a different "
@@ -619,30 +542,21 @@
   bool open_out_file = true;
   if (!will_trace) {
     open_out_file = false;
-    if (!trace_out_path_.empty() || upload_flag) {
-      PERFETTO_ELOG("Can't pass an --out file (or --upload) with this option");
+    if (!trace_out_path_.empty() || !dropbox_tag_.empty()) {
+      PERFETTO_ELOG("Can't pass an --out file (or --dropbox) with this option");
       return 1;
     }
   } else if (!triggers_to_activate.empty() ||
              (trace_config_->write_into_file() &&
               !trace_config_->output_path().empty())) {
     open_out_file = false;
-  } else if (trace_out_path_.empty() && !upload_flag) {
-    PERFETTO_ELOG("Either --out or --upload is required");
+  } else if (trace_out_path_.empty() && dropbox_tag_.empty()) {
+    PERFETTO_ELOG("Either --out or --dropbox is required");
     return 1;
   } else if (is_detach() && !trace_config_->write_into_file()) {
     // In detached mode we must pass the file descriptor to the service and
     // let that one write the trace. We cannot use the IPC readback code path
     // because the client process is about to exit soon after detaching.
-    // We could support detach && !write_into_file, but that would make the
-    // cmdline logic more complex. The feasible configurations are:
-    // 1. Using write_into_file and passing the file path on the --detach call.
-    // 2. Using pure ring-buffer mode, setting write_into_file = false and
-    //    passing the output file path to the --attach call.
-    // This is too complicated and harder to reason about, so we support only 1.
-    // Traceur gets around this by always setting write_into_file and specifying
-    // file_write_period_ms = 1week (which effectively means: write into the
-    // file only at the end of the trace) to achieve ring buffer traces.
     PERFETTO_ELOG(
         "TraceConfig's write_into_file must be true when using --detach");
     return 1;
@@ -655,7 +569,27 @@
   }
 
   if (background) {
-    base::Daemonize();
+    pid_t pid;
+    switch (pid = fork()) {
+      case -1:
+        PERFETTO_FATAL("fork");
+      case 0: {
+        PERFETTO_CHECK(setsid() != -1);
+        base::ignore_result(chdir("/"));
+        base::ScopedFile null = base::OpenFile("/dev/null", O_RDONLY);
+        PERFETTO_CHECK(null);
+        PERFETTO_CHECK(dup2(*null, STDIN_FILENO) != -1);
+        PERFETTO_CHECK(dup2(*null, STDOUT_FILENO) != -1);
+        PERFETTO_CHECK(dup2(*null, STDERR_FILENO) != -1);
+        // Do not accidentally close stdin/stdout/stderr.
+        if (*null <= 2)
+          null.release();
+        break;
+      }
+      default:
+        printf("%d\n", pid);
+        exit(0);
+    }
   }
 
   // If we are just activating triggers then we don't need to rate limit,
@@ -663,8 +597,6 @@
   // the options.
   if (!triggers_to_activate.empty()) {
     LogUploadEvent(PerfettoStatsdAtom::kTriggerBegin);
-    LogTriggerEvents(PerfettoTriggerAtom::kCmdTrigger, triggers_to_activate);
-
     bool finished_with_success = false;
     TriggerProducer producer(
         &task_runner_,
@@ -678,13 +610,11 @@
       LogUploadEvent(PerfettoStatsdAtom::kTriggerSuccess);
     } else {
       LogUploadEvent(PerfettoStatsdAtom::kTriggerFailure);
-      LogTriggerEvents(PerfettoTriggerAtom::kCmdTriggerFail,
-                       triggers_to_activate);
     }
     return finished_with_success ? 0 : 1;
   }
 
-  if (query_service_ || bugreport_) {
+  if (query_service_) {
     consumer_endpoint_ =
         ConsumerIPCClient::Connect(GetConsumerSocket(), this, &task_runner_);
     task_runner_.Run();
@@ -706,18 +636,21 @@
 
   RateLimiter::Args args{};
   args.is_user_build = IsUserBuild();
-  args.is_uploading = save_to_incidentd_;
+  args.is_dropbox = !dropbox_tag_.empty();
   args.current_time = base::GetWallTimeS();
   args.ignore_guardrails = ignore_guardrails;
   args.allow_user_build_tracing = trace_config_->allow_user_build_tracing();
   args.unique_session_name = trace_config_->unique_session_name();
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_USERDEBUG_BUILD) || \
+    PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
   args.max_upload_bytes_override =
       trace_config_->guardrail_overrides().max_upload_per_day_bytes();
+#endif
 
   if (!args.unique_session_name.empty())
     base::MaybeSetThreadName("p-" + args.unique_session_name);
 
-  if (args.is_uploading && !args.ignore_guardrails &&
+  if (args.is_dropbox && !args.ignore_guardrails &&
       (trace_config_->duration_ms() == 0 &&
        trace_config_->trigger_config().trigger_timeout_ms() == 0)) {
     PERFETTO_ELOG("Can't trace indefinitely when tracing to Dropbox.");
@@ -740,11 +673,8 @@
     LogUploadEvent(PerfettoStatsdAtom::kBackgroundTraceBegin);
   }
 
-  auto err_atom = ConvertRateLimiterResponseToAtom(limiter.ShouldTrace(args));
-  if (err_atom) {
-    // TODO(lalitm): remove this once we're ready on server side.
+  if (!limiter.ShouldTrace(args)) {
     LogUploadEvent(PerfettoStatsdAtom::kHitGuardrails);
-    LogUploadEvent(err_atom.value());
     return 1;
   }
 
@@ -753,7 +683,7 @@
   SetupCtrlCSignalHandler();
   task_runner_.Run();
 
-  return limiter.OnTraceDone(args, update_guardrail_state_, bytes_written_) ? 0
+  return limiter.OnTraceDone(args, did_process_full_trace_, bytes_written_) ? 0
                                                                             : 1;
 }
 
@@ -769,19 +699,6 @@
     return;
   }
 
-  if (bugreport_) {
-    consumer_endpoint_->SaveTraceForBugreport(
-        [](bool success, const std::string& msg) {
-          if (success) {
-            PERFETTO_ILOG("Trace saved into %s", msg.c_str());
-            exit(0);
-          }
-          PERFETTO_ELOG("%s", msg.c_str());
-          exit(1);
-        });
-    return;
-  }
-
   if (is_attach()) {
     consumer_endpoint_->Attach(attach_key_);
     return;
@@ -795,9 +712,7 @@
   }
 
   PERFETTO_DCHECK(trace_config_);
-  trace_config_->set_enable_extra_guardrails(save_to_incidentd_);
-
-  // Set the statsd logging flag if we're uploading
+  trace_config_->set_enable_extra_guardrails(!dropbox_tag_.empty());
 
   base::ScopedFile optional_fd;
   if (trace_config_->write_into_file() && trace_config_->output_path().empty())
@@ -812,9 +727,8 @@
 
   // Failsafe mechanism to avoid waiting indefinitely if the service hangs.
   if (expected_duration_ms_) {
-    uint32_t trace_timeout = expected_duration_ms_ + 60000 +
-                             trace_config_->flush_timeout_ms() +
-                             trace_config_->data_source_stop_timeout_ms();
+    uint32_t trace_timeout =
+        expected_duration_ms_ + 60000 + trace_config_->flush_timeout_ms();
     task_runner_.PostDelayedTask(std::bind(&PerfettoCmd::OnTimeout, this),
                                  trace_timeout);
   }
@@ -854,27 +768,7 @@
     FinalizeTraceAndExit();  // Reached end of trace.
 }
 
-void PerfettoCmd::OnTracingDisabled(const std::string& error) {
-  if (!error.empty()) {
-    // Some of these errors (e.g. unique session name already exists) are soft
-    // errors and likely to happen in nominal condition. As such they shouldn't
-    // be marked as "E" in the event log. Hence why LOG and not ELOG here.
-    PERFETTO_LOG("Service error: %s", error.c_str());
-
-    // Update guardrail state even if we failed. This is for two
-    // reasons:
-    // 1. Keeps compatibility with pre-stats code which used to
-    // ignore errors from the service and always update state.
-    // 2. We want to prevent failure storms and the guardrails help
-    // by preventing tracing too frequently with the same session.
-    update_guardrail_state_ = true;
-    task_runner_.Quit();
-    return;
-  }
-
-  // Make sure to only log this atom if |error| is empty; traced
-  // would have logged a terminal error atom corresponding to |error|
-  // and we don't want to log anything after that.
+void PerfettoCmd::OnTracingDisabled() {
   LogUploadEvent(PerfettoStatsdAtom::kOnTracingDisabled);
 
   if (trace_config_->write_into_file()) {
@@ -902,7 +796,7 @@
       bytes_written_ = static_cast<size_t>(sz);
   }
 
-  if (save_to_incidentd_) {
+  if (!dropbox_tag_.empty()) {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     SaveTraceIntoDropboxAndIncidentOrCrash();
 #endif
@@ -917,18 +811,18 @@
     }
   }
 
-  update_guardrail_state_ = true;
+  did_process_full_trace_ = true;
   task_runner_.Quit();
 }
 
 bool PerfettoCmd::OpenOutputFile() {
   base::ScopedFile fd;
-  if (trace_out_path_.empty()) {
+  if (!dropbox_tag_.empty()) {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    fd = CreateUnlinkedTmpFile();
+    fd = OpenDropboxTmpFile();
 #endif
   } else if (trace_out_path_ == "-") {
-    fd.reset(dup(fileno(stdout)));
+    fd.reset(dup(STDOUT_FILENO));
   } else {
     fd = base::OpenFile(trace_out_path_, O_RDWR | O_CREAT | O_TRUNC, 0600);
   }
@@ -946,7 +840,20 @@
 }
 
 void PerfettoCmd::SetupCtrlCSignalHandler() {
-  base::InstallCtrCHandler([] { g_consumer_cmd->SignalCtrlC(); });
+  // Setup signal handler.
+  struct sigaction sa {};
+
+// Glibc headers for sa_sigaction trigger this.
+#pragma GCC diagnostic push
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
+#endif
+  sa.sa_handler = [](int) { g_consumer_cmd->SignalCtrlC(); };
+  sa.sa_flags = static_cast<decltype(sa.sa_flags)>(SA_RESETHAND | SA_RESTART);
+#pragma GCC diagnostic pop
+  sigaction(SIGINT, &sa, nullptr);
+  sigaction(SIGTERM, &sa, nullptr);
+
   task_runner_.AddFileDescriptorWatch(ctrl_c_evt_.fd(), [this] {
     PERFETTO_LOG("SIGINT/SIGTERM received: disabling tracing.");
     ctrl_c_evt_.Clear();
@@ -1021,7 +928,6 @@
     printf("  id: %d\n", producer.id());
     printf("  name: \"%s\" \n", producer.name().c_str());
     printf("  uid: %d \n", producer.uid());
-    printf("  sdk_version: \"%s\" \n", producer.sdk_version().c_str());
     printf("}\n");
   }
 
@@ -1033,8 +939,6 @@
     printf("  }\n");
     printf("}\n");
   }
-  printf("tracing_service_version: \"%s\"\n",
-         svc_state.tracing_service_version().c_str());
   printf("num_sessions: %d\n", svc_state.num_sessions());
   printf("num_sessions_started: %d\n", svc_state.num_sessions_started());
 }
@@ -1043,21 +947,15 @@
     const ObservableEvents& /*observable_events*/) {}
 
 void PerfettoCmd::LogUploadEvent(PerfettoStatsdAtom atom) {
-  if (!statsd_logging_)
-    return;
-  base::Uuid uuid(uuid_);
-  android_stats::MaybeLogUploadEvent(atom, uuid.lsb(), uuid.msb());
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  LogUploadEventAndroid(atom);
+#else
+  base::ignore_result(atom);
+#endif
 }
 
-void PerfettoCmd::LogTriggerEvents(
-    PerfettoTriggerAtom atom,
-    const std::vector<std::string>& trigger_names) {
-  if (!statsd_logging_)
-    return;
-  android_stats::MaybeLogTriggerEvents(atom, trigger_names);
-}
-
-int PERFETTO_EXPORT_ENTRYPOINT PerfettoCmdMain(int argc, char** argv) {
+int __attribute__((visibility("default")))
+PerfettoCmdMain(int argc, char** argv) {
   g_consumer_cmd = new perfetto::PerfettoCmd();
   return g_consumer_cmd->Main(argc, argv);
 }
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index 215c3be..b017708 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -30,7 +30,7 @@
 #include "perfetto/ext/base/unix_task_runner.h"
 #include "perfetto/ext/tracing/core/consumer.h"
 #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
-#include "src/android_stats/perfetto_atoms.h"
+#include "src/perfetto_cmd/perfetto_atoms.h"
 #include "src/perfetto_cmd/rate_limiter.h"
 
 namespace perfetto {
@@ -48,7 +48,7 @@
   // perfetto::Consumer implementation.
   void OnConnect() override;
   void OnDisconnect() override;
-  void OnTracingDisabled(const std::string& error) override;
+  void OnTracingDisabled() override;
   void OnTraceData(std::vector<TracePacket>, bool has_more) override;
   void OnDetach(bool) override;
   void OnAttach(bool, const TraceConfig&) override;
@@ -76,13 +76,13 @@
   void CheckTraceDataTimeout();
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  static base::ScopedFile CreateUnlinkedTmpFile();
+  static base::ScopedFile OpenDropboxTmpFile();
   void SaveTraceIntoDropboxAndIncidentOrCrash();
+  void SaveOutputToDropboxOrCrash();
   void SaveOutputToIncidentTraceOrCrash();
+  void LogUploadEventAndroid(PerfettoStatsdAtom atom);
 #endif
   void LogUploadEvent(PerfettoStatsdAtom atom);
-  void LogTriggerEvents(PerfettoTriggerAtom atom,
-                        const std::vector<std::string>& trigger_names);
 
   base::UnixTaskRunner task_runner_;
 
@@ -95,9 +95,8 @@
 
   std::string trace_out_path_;
   base::EventFd ctrl_c_evt_;
-  bool save_to_incidentd_ = false;
-  bool statsd_logging_ = false;
-  bool update_guardrail_state_ = false;
+  std::string dropbox_tag_;
+  bool did_process_full_trace_ = false;
   uint64_t bytes_written_ = 0;
   std::string detach_key_;
   std::string attach_key_;
@@ -105,7 +104,6 @@
   bool redetach_once_attached_ = false;
   bool query_service_ = false;
   bool query_service_output_raw_ = false;
-  bool bugreport_ = false;
   std::string uuid_;
 
   // How long we expect to trace for or 0 if the trace is indefinite.
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index d64fe85..f332073 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -21,46 +21,75 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/uuid.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"
+#include "src/android_internal/statsd_logging.h"
 
 namespace perfetto {
-namespace {
-
-constexpr int64_t kSendfileTimeoutNs = 10UL * 1000 * 1000 * 1000;  // 10s
-
-}  // namespace
 
 void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
-  PERFETTO_CHECK(save_to_incidentd_);
-  PERFETTO_CHECK(
-      !trace_config_->incident_report_config().destination_package().empty());
+  PERFETTO_CHECK(!dropbox_tag_.empty());
+
+  bool use_dropbox = !trace_config_->incident_report_config().skip_dropbox();
+  bool use_incident =
+      !trace_config_->incident_report_config().destination_package().empty();
 
   if (bytes_written_ == 0) {
     LogUploadEvent(PerfettoStatsdAtom::kNotUploadingEmptyTrace);
-    PERFETTO_LOG("Skipping write to incident. Empty trace.");
+    if (use_dropbox)
+      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
+    if (use_incident)
+      PERFETTO_LOG("Skipping write to incident. Empty trace.");
     return;
   }
 
-  // Save the trace as an incident.
-  SaveOutputToIncidentTraceOrCrash();
-
-  if (!uuid_.empty()) {
-    base::Uuid uuid(uuid_);
-    PERFETTO_LOG("go/trace-uuid/%s  (%" PRIu64 " bytes)",
-                 uuid.ToPrettyString().c_str(), bytes_written_);
+  // Otherwise, write to Dropbox unless there's a special override in the
+  // incident report config.
+  if (use_dropbox) {
+    SaveOutputToDropboxOrCrash();
   }
 
-  // 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()));
+  // Optionally save the trace as an incident. This is either in addition to, or
+  // instead of, the Dropbox write.
+  if (use_incident) {
+    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() {
+  LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxBegin);
+
+  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())) {
+    LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxSuccess);
+    PERFETTO_LOG("Wrote %" PRIu64
+                 " bytes (before compression) into DropBox with tag %s",
+                 bytes_written_, dropbox_tag_.c_str());
+  } else {
+    LogUploadEvent(PerfettoStatsdAtom::kUploadDropboxFailure);
+    PERFETTO_FATAL("DropBox upload failed");
+  }
 }
 
 // Open a staging file (unlinking the previous instance), copy the trace
@@ -78,48 +107,14 @@
 
   PERFETTO_CHECK(unlink(kTempIncidentTracePath) == 0 || errno == ENOENT);
 
-  // TODO(b/155024256) These should not be necessary (we flush when destroying
-  // packet writer and sendfile should ignore file offset) however they should
-  // not harm anything and it will help debug the linked issue.
-  PERFETTO_CHECK(fflush(*trace_out_stream_) == 0);
-  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
-
   // SELinux constrains the set of readers.
   base::ScopedFile staging_fd =
-      base::OpenFile(kTempIncidentTracePath, O_CREAT | O_EXCL | O_RDWR, 0666);
+      base::OpenFile(kTempIncidentTracePath, O_CREAT | O_RDWR, 0666);
   PERFETTO_CHECK(staging_fd);
-
-  int fd = fileno(*trace_out_stream_);
   off_t offset = 0;
-  size_t remaining = static_cast<size_t>(bytes_written_);
-
-  // Count time in terms of CPU to avoid timeouts due to suspend:
-  base::TimeNanos start = base::GetThreadCPUTimeNs();
-  for (;;) {
-    errno = 0;
-    PERFETTO_DCHECK(static_cast<size_t>(offset) + remaining == bytes_written_);
-    auto wsize = PERFETTO_EINTR(sendfile(*staging_fd, fd, &offset, remaining));
-    if (wsize < 0) {
-      PERFETTO_FATAL("sendfile() failed wsize=%zd, off=%" PRId64
-                     ", initial=%" PRIu64 ", remaining=%zu",
-                     wsize, static_cast<int64_t>(offset), bytes_written_,
-                     remaining);
-    }
-    remaining -= static_cast<size_t>(wsize);
-    if (remaining == 0) {
-      break;
-    }
-    base::TimeNanos now = base::GetThreadCPUTimeNs();
-    if (now < start || (now - start).count() > kSendfileTimeoutNs) {
-      PERFETTO_FATAL("sendfile() timed out wsize=%zd, off=%" PRId64
-                     ", initial=%" PRIu64
-                     ", remaining=%zu, start=%lld, now=%lld",
-                     wsize, static_cast<int64_t>(offset), bytes_written_,
-                     remaining, static_cast<long long int>(start.count()),
-                     static_cast<long long int>(now.count()));
-    }
-  }
-
+  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
@@ -128,7 +123,7 @@
 }
 
 // static
-base::ScopedFile PerfettoCmd::CreateUnlinkedTmpFile() {
+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);
@@ -137,4 +132,12 @@
   return fd;
 }
 
+void PerfettoCmd::LogUploadEventAndroid(PerfettoStatsdAtom atom) {
+  if (dropbox_tag_.empty())
+    return;
+  PERFETTO_LAZY_LOAD(android_internal::StatsdLogEvent, log_event_fn);
+  base::Uuid uuid(uuid_);
+  log_event_fn(atom, uuid.lsb(), uuid.msb());
+}
+
 }  // namespace perfetto
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
new file mode 100644
index 0000000..fce3e15
--- /dev/null
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -0,0 +1,1552 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
+#define SRC_PERFETTO_CMD_PERFETTO_CONFIG_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)
+// 3df80477da2ea38cc659967487b37051a154bb69
+// SHA1(protos/perfetto/config/perfetto_config.proto)
+// b23d2885e13039d2a7ec2c88cd59d37fcbafa9ff
+
+// 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, 18121> kPerfettoConfigDescriptor{
+    {0x0a, 0xc5, 0x8d, 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, 0xbd, 0x0d, 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, 0x86, 0x04, 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, 0x12, 0x4d, 0x0a, 0x06, 0x67, 0x72, 0x6f,
+     0x75, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0e, 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, 0x47,
+     0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73,
+     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, 0x75, 0x0a, 0x0f, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e,
+     0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x10, 0x0a, 0x0c,
+     0x55, 0x4e, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x49, 0x46, 0x49, 0x45, 0x44,
+     0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d,
+     0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43,
+     0x45, 0x53, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x52, 0x41, 0x47,
+     0x4d, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x50,
+     0x52, 0x49, 0x4d, 0x49, 0x54, 0x49, 0x56, 0x45, 0x53, 0x10, 0x04, 0x12,
+     0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x4d, 0x4f, 0x52, 0x59, 0x10, 0x05, 0x12,
+     0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, 0x10, 0x06,
+     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, 0x5e, 0x0a, 0x12, 0x54,
+     0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74,
+     0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+     0x65, 0x18, 0x01, 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, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+     0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+     0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x6e, 0x0a, 0x14, 0x54,
+     0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x56, 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,
+     0x0b, 0x32, 0x23, 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, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f,
+     0x72, 0x79, 0x52, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
+     0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 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, 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, 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, 0x33, 0x0a, 0x18, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+     0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6c, 0x6c,
+     0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70,
+     0x6f, 0x6c, 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, 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, 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, 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, 0x8a,
+     0x01, 0x0a, 0x12, 0x56, 0x75, 0x6c, 0x6b, 0x61, 0x6e, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a,
+     0x19, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x72, 0x69, 0x76, 0x65,
+     0x72, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x61,
+     0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x19,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
+     0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x61, 0x67,
+     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x74, 0x72, 0x61,
+     0x63, 0x6b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x6d, 0x6f,
+     0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 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, 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,
+     0x83, 0x04, 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, 0x12,
+     0x3c, 0x0a, 0x1b, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x74, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x17, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x12, 0x43, 0x0a, 0x1f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f,
+     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x65, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+     0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 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, 0xb3, 0x07, 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, 0x35,
+     0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x6e, 0x6f, 0x6e, 0x79, 0x6d,
+     0x6f, 0x75, 0x73, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6b,
+     0x62, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x69, 0x6e,
+     0x41, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x4b, 0x62, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78,
+     0x5f, 0x68, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x5f, 0x6d,
+     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6b, 0x62, 0x18, 0x10, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x70,
+     0x72, 0x6f, 0x66, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4b, 0x62,
+     0x12, 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70,
+     0x70, 0x72, 0x6f, 0x66, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x73, 0x65,
+     0x63, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6d, 0x61,
+     0x78, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x70,
+     0x75, 0x53, 0x65, 0x63, 0x73, 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, 0x35, 0x0a,
+     0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+     0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x75, 0x73,
+     0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63,
+     0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f,
+     0x75, 0x74, 0x55, 0x73, 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, 0x12, 0x32, 0x0a,
+     0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72,
+     0x6b, 0x5f, 0x74, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x12,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
+     0x65, 0x46, 0x6f, 0x72, 0x6b, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77,
+     0x6e, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+     0x5f, 0x76, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63,
+     0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15,
+     0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x66, 0x6f, 0x72, 0x6b,
+     0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0xf5, 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, 0x12,
+     0x35, 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x6e, 0x6f, 0x6e, 0x79,
+     0x6d, 0x6f, 0x75, 0x73, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f,
+     0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x69,
+     0x6e, 0x41, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x4d, 0x65,
+     0x6d, 0x6f, 0x72, 0x79, 0x4b, 0x62, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x75,
+     0x6d, 0x70, 0x5f, 0x73, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x6d, 0x70, 0x53, 0x6d, 0x61, 0x70,
+     0x73, 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, 0xd4, 0x03, 0x0a, 0x0f,
+     0x50, 0x65, 0x72, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x5f, 0x63,
+     0x70, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61,
+     0x6c, 0x6c, 0x43, 0x70, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x61,
+     0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75,
+     0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11,
+     0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x65, 0x71,
+     0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3a, 0x0a, 0x1a, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x61,
+     0x64, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18,
+     0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x72, 0x69, 0x6e, 0x67, 0x42,
+     0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x50, 0x65, 0x72,
+     0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x67,
+     0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x72, 0x69,
+     0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x50, 0x61, 0x67, 0x65,
+     0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
+     0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x09, 0x74,
+     0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e,
+     0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61,
+     0x72, 0x67, 0x65, 0x74, 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12,
+     0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70,
+     0x69, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x78,
+     0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f,
+     0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x6c,
+     0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x65,
+     0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e,
+     0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f,
+     0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x74,
+     0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x0d, 0x52, 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x44,
+     0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d,
+     0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3e, 0x0a, 0x1c, 0x75, 0x6e,
+     0x77, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63,
+     0x6c, 0x65, 0x61, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f,
+     0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x75, 0x6e,
+     0x77, 0x69, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x65,
+     0x61, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 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, 0xba, 0x01, 0x0a, 0x10, 0x54, 0x72,
+     0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
+     0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65,
+     0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x64, 0x69, 0x73,
+     0x61, 0x62, 0x6c, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
+     0x69, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c,
+     0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65,
+     0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x65, 0x6e, 0x61,
+     0x62, 0x6c, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69,
+     0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
+     0x65, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x54,
+     0x61, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c,
+     0x65, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0b, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x54, 0x61,
+     0x67, 0x73, 0x22, 0xf2, 0x0c, 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, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x50, 0x0a, 0x11, 0x70, 0x65, 0x72, 0x66, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6f,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50,
+     0x65, 0x72, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x0f, 0x70, 0x65, 0x72, 0x66,
+     0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x59, 0x0a, 0x14, 0x76, 0x75, 0x6c, 0x6b, 0x61, 0x6e, 0x5f, 0x6d, 0x65,
+     0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+     0x70, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x56, 0x75, 0x6c, 0x6b, 0x61, 0x6e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x12,
+     0x76, 0x75, 0x6c, 0x6b, 0x61, 0x6e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x53, 0x0a, 0x12, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x18, 0x71, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
+     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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28,
+     0x01, 0x52, 0x10, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e,
+     0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x6c, 0x0a, 0x1b, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x65,
+     0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x18, 0x72, 0x20, 0x01, 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, 0x50, 0x6f,
+     0x6c, 0x6c, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x18, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x74,
+     0x61, 0x74, 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,
+     0x9a, 0x1d, 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, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
+     0x70, 0x61, 0x74, 0x68, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+     0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x50, 0x61, 0x74, 0x68, 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, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x6d, 0x73, 0x62, 0x18, 0x1b,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55,
+     0x75, 0x69, 0x64, 0x4d, 0x73, 0x62, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x6c, 0x73, 0x62,
+     0x18, 0x1c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x55, 0x75, 0x69, 0x64, 0x4c, 0x73, 0x62, 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, 0xb6, 0x01, 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, 0x12, 0x3b,
+     0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x66, 0x69,
+     0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17,
+     0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+     0x52, 0x65, 0x67, 0x65, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a,
+     0xea, 0x02, 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, 0x12, 0x34, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+     0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65,
+     0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64,
+     0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+     0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x13, 0x70,
+     0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x74,
+     0x69, 0x6e, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x11, 0x70, 0x72, 0x69,
+     0x6d, 0x61, 0x72, 0x79, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6c, 0x6f,
+     0x63, 0x6b, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
+     0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f,
+     0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x73, 0x6e,
+     0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76,
+     0x61, 0x6c, 0x4d, 0x73, 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, 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, 0x4a, 0x04, 0x08, 0x1a, 0x10, 0x1b, 0x2a, 0x8c, 0x02, 0x0a,
+     0x0c, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x43, 0x6c, 0x6f, 0x63,
+     0x6b, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e,
+     0x5f, 0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f,
+     0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x55, 0x49, 0x4c,
+     0x54, 0x49, 0x4e, 0x5f, 0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x52, 0x45,
+     0x41, 0x4c, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d,
+     0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x5f, 0x43, 0x4c, 0x4f, 0x43,
+     0x4b, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x43,
+     0x4f, 0x41, 0x52, 0x53, 0x45, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x42,
+     0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x5f, 0x43, 0x4c, 0x4f, 0x43, 0x4b,
+     0x5f, 0x4d, 0x4f, 0x4e, 0x4f, 0x54, 0x4f, 0x4e, 0x49, 0x43, 0x10, 0x03,
+     0x12, 0x22, 0x0a, 0x1e, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x5f,
+     0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, 0x4f, 0x4e, 0x4f, 0x54, 0x4f,
+     0x4e, 0x49, 0x43, 0x5f, 0x43, 0x4f, 0x41, 0x52, 0x53, 0x45, 0x10, 0x04,
+     0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x5f,
+     0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, 0x4f, 0x4e, 0x4f, 0x54, 0x4f,
+     0x4e, 0x49, 0x43, 0x5f, 0x52, 0x41, 0x57, 0x10, 0x05, 0x12, 0x1a, 0x0a,
+     0x16, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x5f, 0x43, 0x4c, 0x4f,
+     0x43, 0x4b, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x54, 0x49, 0x4d, 0x45, 0x10,
+     0x06, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e,
+     0x5f, 0x43, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x49,
+     0x44, 0x10, 0x3f, 0x22, 0x04, 0x08, 0x07, 0x10, 0x07, 0x22, 0x04, 0x08,
+     0x08, 0x10, 0x08, 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, 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, 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, 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, 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, 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, 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, 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, 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}};
+
+}  // namespace perfetto
+
+#endif  // SRC_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
diff --git a/src/perfetto_cmd/rate_limiter.cc b/src/perfetto_cmd/rate_limiter.cc
index 65e26e3..daa4403 100644
--- a/src/perfetto_cmd/rate_limiter.cc
+++ b/src/perfetto_cmd/rate_limiter.cc
@@ -16,10 +16,10 @@
 
 #include "src/perfetto_cmd/rate_limiter.h"
 
-#include <fcntl.h>
 #include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <algorithm>
 
@@ -48,13 +48,13 @@
 RateLimiter::RateLimiter() = default;
 RateLimiter::~RateLimiter() = default;
 
-RateLimiter::ShouldTraceResponse RateLimiter::ShouldTrace(const Args& args) {
+bool RateLimiter::ShouldTrace(const Args& args) {
   uint64_t now_in_s = static_cast<uint64_t>(args.current_time.count());
 
-  // Not uploading?
+  // Not storing in Dropbox?
   // -> We can just trace.
-  if (!args.is_uploading)
-    return ShouldTraceResponse::kOkToTrace;
+  if (!args.is_dropbox)
+    return true;
 
   // If we're tracing a user build we should only trace if the override in
   // the config is set:
@@ -62,7 +62,7 @@
     PERFETTO_ELOG(
         "Guardrail: allow_user_build_tracing must be set to trace on user "
         "builds");
-    return ShouldTraceResponse::kNotAllowedOnUserBuild;
+    return false;
   }
 
   // The state file is gone.
@@ -74,7 +74,7 @@
     // -> Give up.
     if (!ClearState()) {
       PERFETTO_ELOG("Guardrail: failed to initialize guardrail state.");
-      return ShouldTraceResponse::kFailedToInitState;
+      return false;
     }
   }
 
@@ -90,7 +90,7 @@
     ClearState();
     PERFETTO_ELOG("Guardrail: state invalid, clearing it.");
     if (!args.ignore_guardrails)
-      return ShouldTraceResponse::kInvalidState;
+      return false;
   }
 
   // First trace was more than 24h ago? Reset state.
@@ -99,7 +99,7 @@
     state_.set_first_trace_timestamp(0);
     state_.set_last_trace_timestamp(0);
     state_.set_total_bytes_uploaded(0);
-    return ShouldTraceResponse::kOkToTrace;
+    return true;
   }
 
   uint64_t max_upload_guardrail = kMaxUploadInBytes;
@@ -129,10 +129,10 @@
                   " in the last 24h. Limit is %" PRIu64 ".",
                   uploaded_so_far, max_upload_guardrail);
     if (!args.ignore_guardrails)
-      return ShouldTraceResponse::kHitUploadLimit;
+      return false;
   }
 
-  return ShouldTraceResponse::kOkToTrace;
+  return true;
 }
 
 bool RateLimiter::OnTraceDone(const Args& args, bool success, uint64_t bytes) {
@@ -142,7 +142,7 @@
   if (!success)
     return false;
 
-  if (!args.is_uploading)
+  if (!args.is_dropbox)
     return true;
 
   // If the first trace timestamp is 0 (either because this is the
@@ -207,7 +207,7 @@
     return false;
   std::string s;
   base::ReadFileDescriptor(in_fd.get(), &s);
-  if (s.empty())
+  if (s.size() == 0)
     return false;
   return state->ParseFromString(s);
 }
diff --git a/src/perfetto_cmd/rate_limiter.h b/src/perfetto_cmd/rate_limiter.h
index 7543090..5866cd1 100644
--- a/src/perfetto_cmd/rate_limiter.h
+++ b/src/perfetto_cmd/rate_limiter.h
@@ -26,25 +26,18 @@
  public:
   struct Args {
     bool is_user_build = false;
-    bool is_uploading = false;
+    bool is_dropbox = false;
     bool ignore_guardrails = false;
     bool allow_user_build_tracing = false;
     base::TimeSeconds current_time = base::TimeSeconds(0);
     uint64_t max_upload_bytes_override = 0;
     std::string unique_session_name = "";
   };
-  enum ShouldTraceResponse {
-    kOkToTrace,
-    kNotAllowedOnUserBuild,
-    kFailedToInitState,
-    kInvalidState,
-    kHitUploadLimit,
-  };
 
   RateLimiter();
   virtual ~RateLimiter();
 
-  ShouldTraceResponse ShouldTrace(const Args& args);
+  bool ShouldTrace(const Args& args);
   bool OnTraceDone(const Args& args, bool success, uint64_t bytes);
 
   bool ClearState();
diff --git a/src/perfetto_cmd/rate_limiter_unittest.cc b/src/perfetto_cmd/rate_limiter_unittest.cc
index 7ba499b..1f6612d 100644
--- a/src/perfetto_cmd/rate_limiter_unittest.cc
+++ b/src/perfetto_cmd/rate_limiter_unittest.cc
@@ -158,7 +158,7 @@
 TEST(RateLimiterTest, NotDropBox) {
   StrictMock<MockRateLimiter> limiter;
 
-  ASSERT_EQ(limiter.ShouldTrace({}), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace({}));
   ASSERT_TRUE(limiter.OnTraceDone({}, true, 10000));
   ASSERT_FALSE(limiter.StateFileExists());
 }
@@ -175,13 +175,13 @@
   RateLimiter::Args args;
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.ignore_guardrails = true;
   args.current_time = base::TimeSeconds(41);
 
   EXPECT_CALL(limiter, SaveState(_));
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_));
   ASSERT_TRUE(limiter.OnTraceDone(args, true, 42u));
@@ -198,12 +198,12 @@
   RateLimiter::Args args;
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(10000);
 
   EXPECT_CALL(limiter, SaveState(_));
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_));
   ASSERT_TRUE(limiter.OnTraceDone(args, true, 1024 * 1024));
@@ -226,11 +226,11 @@
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(input.last_trace_timestamp() + 60 * 10);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_));
   ASSERT_TRUE(limiter.OnTraceDone(args, true, 1024 * 1024));
@@ -254,12 +254,12 @@
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.unique_session_name = "foo";
   args.current_time = base::TimeSeconds(input.last_trace_timestamp() + 60 * 10);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_));
   ASSERT_TRUE(limiter.OnTraceDone(args, true, 1024 * 1024));
@@ -287,13 +287,13 @@
   RateLimiter::Args args;
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
 
   WriteGarbageToFile(limiter.GetStateFilePath().c_str());
 
   EXPECT_CALL(limiter, LoadState(_));
   EXPECT_CALL(limiter, SaveState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kInvalidState);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 
   gen::PerfettoCmdState output{};
   ASSERT_TRUE(limiter.LoadStateConcrete(&output));
@@ -312,12 +312,12 @@
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(99);
 
   EXPECT_CALL(limiter, LoadState(_));
   EXPECT_CALL(limiter, SaveState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kInvalidState);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 
   gen::PerfettoCmdState output{};
   ASSERT_TRUE(limiter.LoadStateConcrete(&output));
@@ -339,12 +339,12 @@
 
   args.is_user_build = true;
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.unique_session_name = "bar";
   args.current_time = base::TimeSeconds(60 * 60);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_TooMuch_Session) {
@@ -360,12 +360,12 @@
 
   args.is_user_build = true;
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.unique_session_name = "foo";
   args.current_time = base::TimeSeconds(60 * 60);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kHitUploadLimit);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_TooMuch_User) {
@@ -378,11 +378,11 @@
 
   args.is_user_build = true;
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(60 * 60);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kHitUploadLimit);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_TooMuch_Override) {
@@ -396,13 +396,13 @@
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(60 * 60);
   args.max_upload_bytes_override = 10 * 1024 * 1024 + 2;
   args.unique_session_name = "foo";
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 }
 
 // Override doesn't apply to traces without session name.
@@ -415,12 +415,12 @@
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
   args.allow_user_build_tracing = true;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(60 * 60);
   args.max_upload_bytes_override = 10 * 1024 * 1024 + 2;
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kHitUploadLimit);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_TooMuchWasUploaded) {
@@ -433,11 +433,11 @@
   input.set_total_bytes_uploaded(10 * 1024 * 1024 + 1);
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(60 * 60 * 24 + 2);
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_));
   ASSERT_TRUE(limiter.OnTraceDone(args, true, 1024 * 1024));
@@ -455,12 +455,12 @@
   StrictMock<MockRateLimiter> limiter;
   RateLimiter::Args args;
 
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(10000);
 
   EXPECT_CALL(limiter, SaveState(_));
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
   ASSERT_FALSE(limiter.OnTraceDone(args, false, 1024 * 1024));
 }
 
@@ -468,12 +468,12 @@
   StrictMock<MockRateLimiter> limiter;
   RateLimiter::Args args;
 
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(10000);
 
   EXPECT_CALL(limiter, SaveState(_));
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 
   EXPECT_CALL(limiter, SaveState(_)).WillOnce(Return(false));
   ASSERT_FALSE(limiter.OnTraceDone(args, true, 1024 * 1024));
@@ -485,10 +485,10 @@
 
   args.is_user_build = true;
   args.allow_user_build_tracing = false;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(10000);
 
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kNotAllowedOnUserBuild);
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_CanTraceOnUser) {
@@ -497,12 +497,12 @@
 
   args.is_user_build = false;
   args.allow_user_build_tracing = false;
-  args.is_uploading = true;
+  args.is_dropbox = true;
   args.current_time = base::TimeSeconds(10000);
 
   EXPECT_CALL(limiter, SaveState(_));
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_EQ(limiter.ShouldTrace(args), RateLimiter::kOkToTrace);
+  ASSERT_TRUE(limiter.ShouldTrace(args));
 }
 
 }  // namespace
diff --git a/src/perfetto_cmd/trigger_perfetto.cc b/src/perfetto_cmd/trigger_perfetto.cc
index 3b7f891..cd22ea2 100644
--- a/src/perfetto_cmd/trigger_perfetto.cc
+++ b/src/perfetto_cmd/trigger_perfetto.cc
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
+#include <getopt.h>
+
 #include <string>
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/unix_task_runner.h"
 #include "perfetto/ext/traced/traced.h"
-#include "src/android_stats/statsd_logging_helper.h"
 #include "src/perfetto_cmd/trigger_producer.h"
 
 namespace perfetto {
@@ -38,57 +38,33 @@
 
 }  // namespace
 
-int PERFETTO_EXPORT_ENTRYPOINT TriggerPerfettoMain(int argc, char** argv) {
-  static const option long_options[] = {{"help", no_argument, nullptr, 'h'},
-                                        {nullptr, 0, nullptr, 0}};
+int __attribute__((visibility("default")))
+TriggerPerfettoMain(int argc, char** argv) {
+  static const struct option long_options[] = {
+      {"help", no_argument, nullptr, 'h'}, {nullptr, 0, nullptr, 0}};
 
-  // Set opterror to zero to disable |getopt_long| from printing an error and
-  // exiting when it encounters an unknown option. Instead, |getopt_long|
-  // will return '?' which we silently ignore.
-  //
-  // We prefer ths behaviour rather than erroring on unknown options because
-  // trigger_perfetto can be called by apps so it's command line API needs to
-  // be backward and forward compatible. If we introduce an option here which
-  // apps will use in the future, we don't want to cause errors on older
-  // platforms where the command line flag did not exist.
-  //
-  // This behaviour was introduced in Android S.
-  opterr = 0;
+  int option_index = 0;
 
   std::vector<std::string> triggers_to_activate;
-  bool seen_unknown_arg = false;
 
   for (;;) {
-    int option = getopt_long(argc, argv, "h", long_options, nullptr);
+    int option = getopt_long(argc, argv, "h", long_options, &option_index);
 
     if (option == 'h')
       return PrintUsage(argv[0]);
 
-    if (option == '?') {
-      seen_unknown_arg = true;
-    }
-
     if (option == -1)
       break;  // EOF.
   }
 
-  // See above for rationale on why we just ignore unknown args instead of
-  // exiting.
-  if (seen_unknown_arg) {
-    PERFETTO_ELOG("Ignoring unknown arguments. See --help for usage.");
-  }
-
   for (int i = optind; i < argc; i++)
     triggers_to_activate.push_back(std::string(argv[i]));
 
-  if (triggers_to_activate.empty()) {
+  if (triggers_to_activate.size() == 0) {
     PERFETTO_ELOG("At least one trigger must the specified.");
     return PrintUsage(argv[0]);
   }
 
-  android_stats::MaybeLogTriggerEvents(
-      PerfettoTriggerAtom::kTriggerPerfettoTrigger, triggers_to_activate);
-
   bool finished_with_success = false;
   base::UnixTaskRunner task_runner;
   TriggerProducer producer(
@@ -100,12 +76,7 @@
       &triggers_to_activate);
   task_runner.Run();
 
-  if (!finished_with_success) {
-    android_stats::MaybeLogTriggerEvents(
-        PerfettoTriggerAtom::kTriggerPerfettoTriggerFail, triggers_to_activate);
-    return 1;
-  }
-  return 0;
+  return finished_with_success ? 0 : 1;
 }
 
 }  // namespace perfetto
diff --git a/src/profiling/BUILD.gn b/src/profiling/BUILD.gn
index d542f96..5a929b6 100644
--- a/src/profiling/BUILD.gn
+++ b/src/profiling/BUILD.gn
@@ -16,17 +16,12 @@
 import("../../gn/test.gni")
 
 source_set("deobfuscator") {
-  sources = [
-    "deobfuscator.cc",
-    "deobfuscator.h",
-  ]
+  sources = [ "deobfuscator.cc" ]
   deps = [
     "../../gn:default_deps",
     "../../include/perfetto/ext/base:base",
-    "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/profiling:zero",
-    "../../src/protozero:protozero",
   ]
+  public_deps = [ "../../include/perfetto/profiling:deobfuscator" ]
 }
 
 perfetto_unittest_source_set("unittests") {
diff --git a/src/profiling/common/BUILD.gn b/src/profiling/common/BUILD.gn
index 583edc6..e999f29 100644
--- a/src/profiling/common/BUILD.gn
+++ b/src/profiling/common/BUILD.gn
@@ -76,50 +76,19 @@
   ]
 }
 
-source_set("producer_support") {
-  deps = [
-    "../../../gn:default_deps",
-    "../../base",
-    "../../traced/probes/packages_list:packages_list_parser",
-    "../../tracing/core",
-  ]
-  sources = [
-    "producer_support.cc",
-    "producer_support.h",
-  ]
-}
-
-source_set("profiler_guardrails") {
-  deps = [
-    ":proc_utils",
-    "../../../gn:default_deps",
-    "../../../include/perfetto/ext/tracing/core",
-    "../../base",
-  ]
-  sources = [
-    "profiler_guardrails.cc",
-    "profiler_guardrails.h",
-  ]
-}
-
 perfetto_unittest_source_set("unittests") {
   testonly = true
   deps = [
     ":interner",
     ":proc_utils",
-    ":producer_support",
-    ":profiler_guardrails",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
     "../../../include/perfetto/profiling:normalize",
     "../../base",
     "../../base:test_support",
-    "../../tracing/core",
   ]
   sources = [
     "interner_unittest.cc",
     "proc_utils_unittest.cc",
-    "producer_support_unittest.cc",
-    "profiler_guardrails_unittest.cc",
   ]
 }
diff --git a/src/profiling/common/callstack_trie.cc b/src/profiling/common/callstack_trie.cc
index 81d0063..01541e9 100644
--- a/src/profiling/common/callstack_trie.cc
+++ b/src/profiling/common/callstack_trie.cc
@@ -28,9 +28,9 @@
 GlobalCallstackTrie::Node* GlobalCallstackTrie::GetOrCreateChild(
     Node* self,
     const Interned<Frame>& loc) {
-  Node* child = self->GetChild(loc);
+  Node* child = self->children_.Get(loc);
   if (!child)
-    child = self->AddChild(loc, ++next_callstack_id_, self);
+    child = self->children_.Emplace(loc, ++next_callstack_id_, self);
   return child;
 }
 
@@ -45,19 +45,13 @@
 }
 
 GlobalCallstackTrie::Node* GlobalCallstackTrie::CreateCallsite(
-    const std::vector<unwindstack::FrameData>& callstack,
-    const std::vector<std::string>& build_ids) {
-  PERFETTO_CHECK(callstack.size() == build_ids.size());
+    const std::vector<FrameData>& callstack) {
   Node* node = &root_;
   // libunwindstack gives the frames top-first, but we want to bookkeep and
   // emit as bottom first.
-  auto callstack_it = callstack.crbegin();
-  auto build_id_it = build_ids.crbegin();
-  for (; callstack_it != callstack.crend() && build_id_it != build_ids.crend();
-       ++callstack_it, ++build_id_it) {
-    const unwindstack::FrameData& loc = *callstack_it;
-    const std::string& build_id = *build_id_it;
-    node = GetOrCreateChild(node, InternCodeLocation(loc, build_id));
+  for (auto it = callstack.crbegin(); it != callstack.crend(); ++it) {
+    const FrameData& loc = *it;
+    node = GetOrCreateChild(node, InternCodeLocation(loc));
   }
   return node;
 }
@@ -88,7 +82,7 @@
   Node* prev = nullptr;
   while (node != nullptr) {
     if (delete_prev)
-      node->RemoveChild(prev);
+      node->children_.Remove(*prev);
     node->ref_count_ -= 1;
     delete_prev = node->ref_count_ == 0;
     prev = node;
@@ -96,21 +90,20 @@
   }
 }
 
-Interned<Frame> GlobalCallstackTrie::InternCodeLocation(
-    const unwindstack::FrameData& loc,
-    const std::string& build_id) {
-  Mapping map(string_interner_.Intern(build_id));
-  map.exact_offset = loc.map_exact_offset;
-  map.start_offset = loc.map_elf_start_offset;
-  map.start = loc.map_start;
-  map.end = loc.map_end;
-  map.load_bias = loc.map_load_bias;
-  base::StringSplitter sp(loc.map_name, '/');
+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.start = loc.frame.map_start;
+  map.end = loc.frame.map_end;
+  map.load_bias = loc.frame.map_load_bias;
+  base::StringSplitter sp(loc.frame.map_name, '/');
   while (sp.Next())
     map.path_components.emplace_back(string_interner_.Intern(sp.cur_token()));
 
   Frame frame(mapping_interner_.Intern(std::move(map)),
-              string_interner_.Intern(loc.function_name), loc.rel_pc);
+              string_interner_.Intern(loc.frame.function_name),
+              loc.frame.rel_pc);
 
   return frame_interner_.Intern(frame);
 }
@@ -124,30 +117,5 @@
   return frame_interner_.Intern(frame);
 }
 
-GlobalCallstackTrie::Node* GlobalCallstackTrie::Node::AddChild(
-    const Interned<Frame>& loc,
-    uint64_t callstack_id,
-    Node* parent) {
-  auto it = children_.emplace(loc, callstack_id, parent);
-  return const_cast<Node*>(&(*it.first));
-}
-void GlobalCallstackTrie::Node::RemoveChild(Node* node) {
-  children_.erase(*node);
-}
-
-GlobalCallstackTrie::Node* GlobalCallstackTrie::Node::GetChild(
-    const Interned<Frame>& loc) {
-  // 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 Node from the key.
-  Node node(loc);
-  auto it = children_.find(node);
-  if (it == children_.end())
-    return nullptr;
-  return const_cast<Node*>(&(*it));
-}
-
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/common/callstack_trie.h b/src/profiling/common/callstack_trie.h
index f8ca304..d711cf5 100644
--- a/src/profiling/common/callstack_trie.h
+++ b/src/profiling/common/callstack_trie.h
@@ -17,13 +17,11 @@
 #ifndef SRC_PROFILING_COMMON_CALLSTACK_TRIE_H_
 #define SRC_PROFILING_COMMON_CALLSTACK_TRIE_H_
 
-#include <set>
 #include <string>
 #include <typeindex>
 #include <vector>
 
-#include <unwindstack/Unwinder.h>
-
+#include "perfetto/ext/base/lookup_set.h"
 #include "src/profiling/common/interner.h"
 #include "src/profiling/common/unwind_support.h"
 
@@ -31,7 +29,7 @@
 namespace profiling {
 
 struct Mapping {
-  explicit Mapping(Interned<std::string> b) : build_id(std::move(b)) {}
+  Mapping(Interned<std::string> b) : build_id(std::move(b)) {}
 
   Interned<std::string> build_id;
   uint64_t exact_offset = 0;
@@ -105,11 +103,8 @@
     // This is opaque except to GlobalCallstackTrie.
     friend class GlobalCallstackTrie;
 
-    // Allow building a node out of a frame for GetChild.
-    explicit Node(Interned<Frame> frame) : Node(frame, 0, nullptr) {}
-    Node(const Node&) = default;
-    Node(Node&&) = default;
-
+    // Allow building a node out of a frame for base::LookupSet.
+    Node(Interned<Frame> frame) : Node(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)
@@ -122,26 +117,13 @@
    private:
     Node* GetOrCreateChild(const Interned<Frame>& loc);
     // Deletes all descendant nodes, regardless of |ref_count_|.
-    void DeleteChildren() { children_.clear(); }
+    void DeleteChildren() { children_.Clear(); }
 
     uint64_t ref_count_ = 0;
     uint64_t id_;
     Node* const parent_;
     const Interned<Frame> location_;
-
-    class NodeComparator {
-     public:
-      bool operator()(const Node& one, const Node& other) const {
-        return one.location_ < other.location_;
-      }
-    };
-    Node* AddChild(const Interned<Frame>& loc,
-                   uint64_t next_callstack_id_,
-                   Node* parent);
-    void RemoveChild(Node* node);
-    Node* GetChild(const Interned<Frame>& loc);
-
-    std::set<Node, NodeComparator> children_;
+    base::LookupSet<Node, const Interned<Frame>, &Node::location_> children_;
   };
 
   GlobalCallstackTrie() = default;
@@ -153,11 +135,9 @@
   GlobalCallstackTrie(GlobalCallstackTrie&&) = delete;
   GlobalCallstackTrie& operator=(GlobalCallstackTrie&&) = delete;
 
-  Interned<Frame> InternCodeLocation(const unwindstack::FrameData& loc,
-                                     const std::string& build_id);
+  Interned<Frame> InternCodeLocation(const FrameData& loc);
 
-  Node* CreateCallsite(const std::vector<unwindstack::FrameData>& callstack,
-                       const std::vector<std::string>& build_ids);
+  Node* CreateCallsite(const std::vector<FrameData>& callstack);
   Node* CreateCallsite(const std::vector<Interned<Frame>>& callstack);
 
   static void IncrementNode(Node* node);
diff --git a/src/profiling/common/interner.h b/src/profiling/common/interner.h
index 636b103..7490ef2 100644
--- a/src/profiling/common/interner.h
+++ b/src/profiling/common/interner.h
@@ -57,7 +57,7 @@
   class Interned {
    public:
     friend class Interner<T>;
-    explicit Interned(Entry* entry) : entry_(entry) {}
+    Interned(Entry* entry) : entry_(entry) {}
     Interned(const Interned& other) : entry_(other.entry_) {
       if (entry_ != nullptr)
         entry_->ref_count++;
diff --git a/src/profiling/common/interning_output.cc b/src/profiling/common/interning_output.cc
index f5ec251..778f61e 100644
--- a/src/profiling/common/interning_output.cc
+++ b/src/profiling/common/interning_output.cc
@@ -33,8 +33,7 @@
 
 // static
 void InterningOutputTracker::WriteFixedInterningsPacket(
-    TraceWriter* trace_writer,
-    uint32_t sequence_flags) {
+    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.
@@ -52,9 +51,7 @@
   interned_string->set_iid(0);
   interned_string->set_str(kEmptyString, 0);
 
-  if (sequence_flags) {
-    packet->set_sequence_flags(sequence_flags);
-  }
+  packet->set_incremental_state_cleared(true);
 }
 
 void InterningOutputTracker::WriteMap(const Interned<Mapping> map,
@@ -81,8 +78,6 @@
 
 void InterningOutputTracker::WriteFrame(Interned<Frame> frame,
                                         protos::pbzero::InternedData* out) {
-  // Trace processor depends on the map being written before the
-  // frame. See StackProfileTracker::AddFrame.
   WriteMap(frame->mapping, out);
   WriteFunctionNameString(frame->function_name, out);
   bool inserted;
diff --git a/src/profiling/common/interning_output.h b/src/profiling/common/interning_output.h
index 0674a61..cb92e52 100644
--- a/src/profiling/common/interning_output.h
+++ b/src/profiling/common/interning_output.h
@@ -34,8 +34,9 @@
 class InterningOutputTracker {
  public:
   // Writes out a full packet containing the "empty" (zero) internings.
-  static void WriteFixedInterningsPacket(TraceWriter* trace_writer,
-                                         uint32_t sequence_flags);
+  // NB: resulting packet has |incremental_state_cleared| set.
+  static void WriteFixedInterningsPacket(TraceWriter* trace_writer);
+
   void WriteMap(const Interned<Mapping> map, protos::pbzero::InternedData* out);
   void WriteFrame(Interned<Frame> frame, protos::pbzero::InternedData* out);
   void WriteBuildIDString(const Interned<std::string>& str,
diff --git a/src/profiling/common/proc_utils.cc b/src/profiling/common/proc_utils.cc
index c2d1e55..155d091 100644
--- a/src/profiling/common/proc_utils.cc
+++ b/src/profiling/common/proc_utils.cc
@@ -193,35 +193,5 @@
   }
 }
 
-base::Optional<Uids> GetUids(const std::string& status) {
-  auto entry_idx = status.find("Uid:");
-  if (entry_idx == std::string::npos)
-    return base::nullopt;
-
-  Uids uids;
-  const char* str = &status[entry_idx + 4];
-  char* endptr;
-
-  uids.real = strtoull(str, &endptr, 10);
-  if (*endptr != ' ' && *endptr != '\t')
-    return base::nullopt;
-
-  str = endptr;
-  uids.effective = strtoull(str, &endptr, 10);
-  if (*endptr != ' ' && *endptr != '\t')
-    return base::nullopt;
-
-  str = endptr;
-  uids.saved_set = strtoull(str, &endptr, 10);
-  if (*endptr != ' ' && *endptr != '\t')
-    return base::nullopt;
-
-  str = endptr;
-  uids.filesystem = strtoull(str, &endptr, 10);
-  if (*endptr != '\n' && *endptr != '\0')
-    return base::nullopt;
-  return uids;
-}
-
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/common/proc_utils.h b/src/profiling/common/proc_utils.h
index facd10e..61c35b4 100644
--- a/src/profiling/common/proc_utils.h
+++ b/src/profiling/common/proc_utils.h
@@ -17,9 +17,7 @@
 #ifndef SRC_PROFILING_COMMON_PROC_UTILS_H_
 #define SRC_PROFILING_COMMON_PROC_UTILS_H_
 
-#include <inttypes.h>
 #include <sys/types.h>
-
 #include <set>
 #include <vector>
 
@@ -29,13 +27,6 @@
 namespace perfetto {
 namespace profiling {
 
-struct Uids {
-  uint64_t real;
-  uint64_t effective;
-  uint64_t saved_set;
-  uint64_t filesystem;
-};
-
 template <typename Fn>
 void ForEachPid(Fn callback) {
   base::ScopedDir proc_dir(opendir("/proc"));
@@ -67,8 +58,6 @@
 // entries satisfying the minimum size criteria for anonymous memory.
 void RemoveUnderAnonThreshold(uint32_t min_size_kb, std::set<pid_t>* pids);
 
-base::Optional<Uids> GetUids(const std::string&);
-
 }  // namespace profiling
 }  // namespace perfetto
 
diff --git a/src/profiling/common/proc_utils_unittest.cc b/src/profiling/common/proc_utils_unittest.cc
index cec73d8..f16c834 100644
--- a/src/profiling/common/proc_utils_unittest.cc
+++ b/src/profiling/common/proc_utils_unittest.cc
@@ -15,7 +15,6 @@
  */
 
 #include "src/profiling/common/proc_utils.h"
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/profiling/normalize.h"
 
 #include "perfetto/ext/base/utils.h"
@@ -136,35 +135,6 @@
   EXPECT_EQ(GetRssAnonAndSwap("RssAnon: 10000 kB"), base::nullopt);
   EXPECT_EQ(GetRssAnonAndSwap("VmSwap: 10000"), base::nullopt);
 }
-
-TEST(ProcUtilsTest, GetUids) {
-  std::string status =
-      "Name: foo\nRssAnon:  10000 kB\nVmSwap:\t10000 kB\n"
-      "Uid: 1 2 3 4\n";
-  auto uids = GetUids(status);
-  ASSERT_NE(uids, base::nullopt);
-  EXPECT_EQ(uids->real, 1u);
-  EXPECT_EQ(uids->effective, 2u);
-  EXPECT_EQ(uids->saved_set, 3u);
-  EXPECT_EQ(uids->filesystem, 4u);
-}
-
-TEST(ProcUtilsTest, GetUidsInvalidInt) {
-  std::string status =
-      "Name: foo\nRssAnon:  10000 kB\nVmSwap:\t10000 kB\n"
-      "Uid: 1a 2 3 4\n";
-  auto uids = GetUids(status);
-  EXPECT_EQ(uids, base::nullopt);
-}
-
-TEST(ProcUtilsTest, GetUidsInvalidTooFew) {
-  std::string status =
-      "Name: foo\nRssAnon:  10000 kB\nVmSwap:\t10000 kB\n"
-      "Uid: 1 2 3\n";
-  auto uids = GetUids(status);
-  EXPECT_EQ(uids, base::nullopt);
-}
-
 }  // namespace
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/common/producer_support.cc b/src/profiling/common/producer_support.cc
deleted file mode 100644
index 2347edd..0000000
--- a/src/profiling/common/producer_support.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/common/producer_support.h"
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/tracing/core/data_source_config.h"
-
-#include "perfetto/tracing/core/forward_decls.h"
-#include "src/traced/probes/packages_list/packages_list_parser.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/system_properties.h>
-#endif
-
-namespace perfetto {
-namespace profiling {
-
-bool CanProfile(const DataSourceConfig& ds_config,
-                uint64_t uid,
-                const std::vector<std::string>& installed_by) {
-// We restrict by !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) because a
-// sideloaded heapprofd should not be restricted by this. Do note though that,
-// at the moment, there isn't really a way to sideload a functioning heapprofd
-// onto user builds.
-#if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) || \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  base::ignore_result(ds_config);
-  base::ignore_result(uid);
-  base::ignore_result(installed_by);
-  return true;
-#else
-  char buf[PROP_VALUE_MAX + 1] = {};
-  int ret = __system_property_get("ro.build.type", buf);
-  PERFETTO_CHECK(ret >= 0);
-  return CanProfileAndroid(ds_config, uid, installed_by, std::string(buf),
-                           "/data/system/packages.list");
-#endif
-}
-
-bool CanProfileAndroid(const DataSourceConfig& ds_config,
-                       uint64_t uid,
-                       const std::vector<std::string>& installed_by,
-                       const std::string& build_type,
-                       const std::string& packages_list_path) {
-  // These are replicated constants from libcutils android_filesystem_config.h
-  constexpr auto kAidAppStart = 10000;     // AID_APP_START
-  constexpr auto kAidAppEnd = 19999;       // AID_APP_END
-  constexpr auto kAidUserOffset = 100000;  // AID_USER_OFFSET
-
-  if (build_type != "user") {
-    return true;
-  }
-
-  uint64_t uid_without_profile = uid % kAidUserOffset;
-  if (uid_without_profile < kAidAppStart || kAidAppEnd < uid_without_profile) {
-    // TODO(fmayer): relax this.
-    return false;  // no native services on user.
-  }
-
-  std::string content;
-  if (!base::ReadFile(packages_list_path, &content)) {
-    PERFETTO_ELOG("Failed to read %s.", packages_list_path.c_str());
-    return false;
-  }
-  for (base::StringSplitter ss(std::move(content), '\n'); ss.Next();) {
-    Package pkg;
-    if (!ReadPackagesListLine(ss.cur_token(), &pkg)) {
-      PERFETTO_ELOG("Failed to parse packages.list.");
-      return false;
-    }
-    if (pkg.uid != uid_without_profile)
-      continue;
-    if (!installed_by.empty()) {
-      if (pkg.installed_by.empty()) {
-        PERFETTO_ELOG(
-            "installed_by given in TraceConfig, but cannot parse "
-            "installer from packages.list.");
-        return false;
-      }
-      if (std::find(installed_by.cbegin(), installed_by.cend(),
-                    pkg.installed_by) == installed_by.cend()) {
-        return false;
-      }
-    }
-    switch (ds_config.session_initiator()) {
-      case DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED:
-        return pkg.profileable_from_shell || pkg.debuggable;
-      case DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM:
-        return pkg.profileable || pkg.debuggable;
-    }
-  }
-  // Did not find package.
-  return false;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/common/producer_support.h b/src/profiling/common/producer_support.h
deleted file mode 100644
index 4e6b856..0000000
--- a/src/profiling/common/producer_support.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_COMMON_PRODUCER_SUPPORT_H_
-#define SRC_PROFILING_COMMON_PRODUCER_SUPPORT_H_
-
-#include <inttypes.h>
-#include <string>
-
-#include "perfetto/tracing/core/forward_decls.h"
-
-namespace perfetto {
-namespace profiling {
-
-bool CanProfile(const DataSourceConfig& ds_config,
-                uint64_t uid,
-                const std::vector<std::string>& installed_by);
-bool CanProfileAndroid(const DataSourceConfig& ds_config,
-                       uint64_t uid,
-                       const std::vector<std::string>& installed_by,
-                       const std::string& build_type,
-                       const std::string& packages_list_path);
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_COMMON_PRODUCER_SUPPORT_H_
diff --git a/src/profiling/common/producer_support_unittest.cc b/src/profiling/common/producer_support_unittest.cc
deleted file mode 100644
index 33fdf28..0000000
--- a/src/profiling/common/producer_support_unittest.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/common/producer_support.h"
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-TEST(CanProfileAndroidTest, NonUserSystemExtraGuardrails) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(true);
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 1, {}, "userdebug", "/dev/null"));
-}
-
-TEST(CanProfileAndroidTest, NonUserNonProfileableApp) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(false);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 0 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 0 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 10001, {}, "userdebug", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, NonUserNonProfileableAppExtraGuardrails) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(true);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 0 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 0 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 10001, {}, "userdebug", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableApp) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(false);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 0 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 1 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 10001, {}, "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableAppMultiuser) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(false);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 0 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 1 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 210001, {}, "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserNonProfileableApp) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(false);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 0 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 0 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_FALSE(CanProfileAndroid(ds_config, 10001, {}, "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserDebuggableApp) {
-  DataSourceConfig ds_config;
-  ds_config.set_enable_extra_guardrails(false);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example.profileable 10001 1 "
-      "/data/user/0/invalid.example.profileable default:targetSdkVersion=10000 "
-      "none 0 1\n";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 10001, {}, "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableMatchingInstallerStatsd) {
-  DataSourceConfig ds_config;
-  ds_config.set_session_initiator(
-      DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example 10001 0 /data/user/0/invalid.example "
-      "default:targetSdkVersion=29 3002,3003 0 13030407 1 invalid.store";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_TRUE(CanProfileAndroid(ds_config, 10001, {"invalid.store"}, "user",
-                                tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableMatchingInstallerShell) {
-  DataSourceConfig ds_config;
-  ds_config.set_session_initiator(
-      DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example 10001 0 /data/user/0/invalid.example "
-      "default:targetSdkVersion=29 3002,3003 0 13030407 1 invalid.store";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_FALSE(CanProfileAndroid(ds_config, 10001, {"invalid.store"}, "user",
-                                 tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableNonMatchingInstallerStatsd) {
-  DataSourceConfig ds_config;
-  ds_config.set_session_initiator(
-      DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example 10001 0 /data/user/0/invalid.example "
-      "default:targetSdkVersion=29 3002,3003 0 13030407 1 invalid.store";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_FALSE(CanProfileAndroid(ds_config, 10001, {"invalid.otherstore"},
-                                 "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableNonMatchingInstallerShell) {
-  DataSourceConfig ds_config;
-  ds_config.set_session_initiator(
-      DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example 10001 0 /data/user/0/invalid.example "
-      "default:targetSdkVersion=29 3002,3003 0 13030407 1 invalid.store";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_FALSE(CanProfileAndroid(ds_config, 10001, {"invalid.otherstore"},
-                                 "user", tmp.path()));
-}
-
-TEST(CanProfileAndroidTest, UserProfileableFromShellWithInstallerOldPackages) {
-  DataSourceConfig ds_config;
-  ds_config.set_session_initiator(
-      DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
-  auto tmp = base::TempFile::Create();
-  constexpr char content[] =
-      "invalid.example 10001 0 /data/user/0/invalid.example "
-      "default:targetSdkVersion=29 3002,3003 1 13030407";
-  base::WriteAll(tmp.fd(), content, sizeof(content));
-  EXPECT_FALSE(CanProfileAndroid(ds_config, 10001, {"invalid.otherstore"},
-                                 "user", tmp.path()));
-}
-
-}  // namespace
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/common/profiler_guardrails.cc b/src/profiling/common/profiler_guardrails.cc
deleted file mode 100644
index a7f5dad..0000000
--- a/src/profiling/common/profiler_guardrails.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/common/profiler_guardrails.h"
-
-#include <unistd.h>
-
-#include <algorithm>
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/watchdog_posix.h"
-
-namespace perfetto {
-namespace profiling {
-
-base::Optional<uint64_t> GetCputimeSecForCurrentProcess() {
-  return GetCputimeSecForCurrentProcess(
-      base::OpenFile("/proc/self/stat", O_RDONLY));
-}
-
-base::Optional<uint64_t> GetCputimeSecForCurrentProcess(
-    base::ScopedFile stat_fd) {
-  if (!stat_fd)
-    return base::nullopt;
-  base::ProcStat stat;
-  if (!ReadProcStat(stat_fd.get(), &stat)) {
-    PERFETTO_ELOG("Failed to read stat file to enforce guardrails.");
-    return base::nullopt;
-  }
-  return (stat.utime + stat.stime) /
-         static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
-}
-
-ProfilerMemoryGuardrails::ProfilerMemoryGuardrails()
-    : ProfilerMemoryGuardrails(base::OpenFile("/proc/self/status", O_RDONLY)) {}
-
-ProfilerMemoryGuardrails::ProfilerMemoryGuardrails(base::ScopedFile status_fd) {
-  std::string status;
-  if (base::ReadFileDescriptor(*status_fd, &status))
-    anon_and_swap_ = GetRssAnonAndSwap(status);
-
-  if (!anon_and_swap_) {
-    PERFETTO_ELOG("Failed to read memory usage.");
-    return;
-  }
-}
-
-bool ProfilerMemoryGuardrails::IsOverMemoryThreshold(
-    const GuardrailConfig& ds) {
-  uint32_t ds_max_mem = ds.memory_guardrail_kb;
-  if (!ds_max_mem || !anon_and_swap_)
-    return false;
-
-  if (ds_max_mem > 0 && *anon_and_swap_ > ds_max_mem) {
-    PERFETTO_ELOG("Exceeded data-source memory guardrail (%" PRIu32
-                  " > %" PRIu32 "). Shutting down.",
-                  *anon_and_swap_, ds_max_mem);
-    return true;
-  }
-  return false;
-}
-
-ProfilerCpuGuardrails::ProfilerCpuGuardrails() {
-  opt_cputime_sec_ = GetCputimeSecForCurrentProcess();
-  if (!opt_cputime_sec_) {
-    PERFETTO_ELOG("Failed to get CPU time.");
-  }
-}
-
-// For testing.
-ProfilerCpuGuardrails::ProfilerCpuGuardrails(base::ScopedFile stat_fd) {
-  opt_cputime_sec_ = GetCputimeSecForCurrentProcess(std::move(stat_fd));
-  if (!opt_cputime_sec_) {
-    PERFETTO_ELOG("Failed to get CPU time.");
-  }
-}
-
-bool ProfilerCpuGuardrails::IsOverCpuThreshold(const GuardrailConfig& ds) {
-  uint64_t ds_max_cpu = ds.cpu_guardrail_sec;
-  if (!ds_max_cpu || !opt_cputime_sec_)
-    return false;
-  uint64_t cputime_sec = *opt_cputime_sec_;
-
-  auto start_cputime_sec = ds.cpu_start_secs;
-  // We reject data-sources with CPU guardrails if we cannot read the
-  // initial value, which means we get a non-nullopt value here.
-  PERFETTO_CHECK(start_cputime_sec);
-  uint64_t cpu_diff = cputime_sec - *start_cputime_sec;
-  if (cputime_sec > *start_cputime_sec && cpu_diff > ds_max_cpu) {
-    PERFETTO_ELOG("Exceeded data-source CPU guardrail (%" PRIu64 " > %" PRIu64
-                  "). Shutting down.",
-                  cpu_diff, ds_max_cpu);
-    return true;
-  }
-  return false;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/common/profiler_guardrails.h b/src/profiling/common/profiler_guardrails.h
deleted file mode 100644
index f89c0c2..0000000
--- a/src/profiling/common/profiler_guardrails.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_COMMON_PROFILER_GUARDRAILS_H_
-#define SRC_PROFILING_COMMON_PROFILER_GUARDRAILS_H_
-
-#include <fcntl.h>
-#include <inttypes.h>
-#include <unistd.h>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "src/profiling/common/proc_utils.h"
-
-namespace perfetto {
-namespace profiling {
-
-base::Optional<uint64_t> GetCputimeSecForCurrentProcess();
-// For testing.
-base::Optional<uint64_t> GetCputimeSecForCurrentProcess(
-    base::ScopedFile stat_fd);
-
-struct GuardrailConfig {
-  uint64_t cpu_guardrail_sec = 0;
-  base::Optional<uint64_t> cpu_start_secs;
-  uint32_t memory_guardrail_kb = 0;
-};
-
-class ProfilerCpuGuardrails {
- public:
-  ProfilerCpuGuardrails();
-  // Allows to supply custom stat fd for testing.
-  explicit ProfilerCpuGuardrails(base::ScopedFile stat_fd);
-
-  bool IsOverCpuThreshold(const GuardrailConfig& ds);
-
- private:
-  base::Optional<uint64_t> opt_cputime_sec_;
-};
-
-class ProfilerMemoryGuardrails {
- public:
-  ProfilerMemoryGuardrails();
-  // Allows to supply custom status fd for testing.
-  explicit ProfilerMemoryGuardrails(base::ScopedFile status_fd);
-
-  bool IsOverMemoryThreshold(const GuardrailConfig& ds);
-
- private:
-  base::Optional<uint32_t> anon_and_swap_;
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_COMMON_PROFILER_GUARDRAILS_H_
diff --git a/src/profiling/common/profiler_guardrails_unittest.cc b/src/profiling/common/profiler_guardrails_unittest.cc
deleted file mode 100644
index ef8a450..0000000
--- a/src/profiling/common/profiler_guardrails_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/common/profiler_guardrails.h"
-
-#include <inttypes.h>
-#include <unistd.h>
-
-#include <map>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-TEST(ProfilerCpuGuardrailsTest, Exceeded) {
-  const auto clk = static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
-  base::TempFile f = base::TempFile::CreateUnlinked();
-  constexpr const char stat[] =
-      "2965981 (zsh) S 2965977 2965981 2965981 34822 2966607 4194304 6632 6697 "
-      "0 0 1000000 6000000 4 1 20 0 1 0 227163466 15839232 2311 "
-      "18446744073709551615 "
-      "94823961161728 94823961762781 140722993535472 0 0 0 2 3686400 134295555 "
-      "0 0 0 17 2 0 0 0 0 0 94823961905904 94823961935208 94823993954304 "
-      "140722993543678 140722993543691 140722993543691 140722993545195 0";
-  base::WriteAll(f.fd(), stat, sizeof(stat));
-  ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
-  ProfilerCpuGuardrails gr(f.ReleaseFD());
-
-  GuardrailConfig gc;
-  gc.cpu_guardrail_sec = 5000000 / clk;
-  gc.cpu_start_secs = 1000000 / clk;
-  EXPECT_TRUE(gr.IsOverCpuThreshold(gc));
-}
-
-TEST(ProfilerCpuGuardrailsTest, NotExceeded) {
-  const auto clk = static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
-  base::TempFile f = base::TempFile::CreateUnlinked();
-  constexpr const char stat[] =
-      "2965981 (zsh) S 2965977 2965981 2965981 34822 2966607 4194304 6632 6697 "
-      "0 0 1000000 6000000 4 1 20 0 1 0 227163466 15839232 2311 "
-      "18446744073709551615 "
-      "94823961161728 94823961762781 140722993535472 0 0 0 2 3686400 134295555 "
-      "0 0 0 17 2 0 0 0 0 0 94823961905904 94823961935208 94823993954304 "
-      "140722993543678 140722993543691 140722993543691 140722993545195 0";
-  base::WriteAll(f.fd(), stat, sizeof(stat));
-  ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
-  ProfilerCpuGuardrails gr(f.ReleaseFD());
-
-  GuardrailConfig gc;
-  gc.cpu_guardrail_sec = 7000000 / clk;
-  gc.cpu_start_secs = 1000000 / clk;
-  EXPECT_FALSE(gr.IsOverCpuThreshold(gc));
-}
-
-TEST(ProfilerMemoryGuardrailsTest, Exceeded) {
-  base::TempFile f = base::TempFile::CreateUnlinked();
-  constexpr const char status[] =
-      "VmPeak:\t    5432 kB\n"
-      "VmSize:\t    5432 kB\n"
-      "VmLck:\t       0 kB\n"
-      "VmPin:\t       0 kB\n"
-      "VmHWM:\t     584 kB\n"
-      "VmRSS:\t     80 kB\n"
-      "RssAnon:\t      68 kB\n"
-      "RssFile:\t     516 kB\n"
-      "RssShmem:\t       0 kB\n"
-      "VmData:\t     316 kB\n"
-      "VmStk:\t     132 kB\n"
-      "VmExe:\t      20 kB\n"
-      "VmLib:\t    1460 kB\n"
-      "VmPTE:\t      44 kB\n"
-      "VmSwap:\t       10 kB\n";
-
-  base::WriteAll(f.fd(), status, sizeof(status));
-  ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
-  ProfilerMemoryGuardrails gr(f.ReleaseFD());
-
-  GuardrailConfig gc;
-  gc.memory_guardrail_kb = 77;
-  EXPECT_TRUE(gr.IsOverMemoryThreshold(gc));
-}
-
-TEST(ProfilerMemoryGuardrailsTest, NotExceeded) {
-  base::TempFile f = base::TempFile::CreateUnlinked();
-  constexpr const char status[] =
-      "VmPeak:\t    5432 kB\n"
-      "VmSize:\t    5432 kB\n"
-      "VmLck:\t       0 kB\n"
-      "VmPin:\t       0 kB\n"
-      "VmHWM:\t     584 kB\n"
-      "VmRSS:\t     80 kB\n"
-      "RssAnon:\t      68 kB\n"
-      "RssFile:\t     516 kB\n"
-      "RssShmem:\t       0 kB\n"
-      "VmData:\t     316 kB\n"
-      "VmStk:\t     132 kB\n"
-      "VmExe:\t      20 kB\n"
-      "VmLib:\t    1460 kB\n"
-      "VmPTE:\t      44 kB\n"
-      "VmSwap:\t       10 kB\n";
-
-  base::WriteAll(f.fd(), status, sizeof(status));
-  ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
-  ProfilerMemoryGuardrails gr(f.ReleaseFD());
-  GuardrailConfig gc;
-  gc.memory_guardrail_kb = 100;
-  EXPECT_FALSE(gr.IsOverMemoryThreshold(gc));
-}
-
-}  // namespace
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/common/unwind_support.cc b/src/profiling/common/unwind_support.cc
index 5302015..606d54c 100644
--- a/src/profiling/common/unwind_support.cc
+++ b/src/profiling/common/unwind_support.cc
@@ -47,9 +47,8 @@
 
 size_t FDMemory::Read(uint64_t addr, void* dst, size_t size) {
   ssize_t rd = pread64(*mem_fd_, dst, size, static_cast<off64_t>(addr));
-  if (PERFETTO_UNLIKELY(rd == -1)) {
-    PERFETTO_PLOG("Failed remote pread of %zu bytes at address %" PRIx64, size,
-                  addr);
+  if (rd == -1) {
+    PERFETTO_DPLOG("read of %zu at offset %" PRIu64, size, addr);
     return 0;
   }
   return static_cast<size_t>(rd);
@@ -67,24 +66,18 @@
   if (!base::ReadFileDescriptor(*fd_, &content))
     return false;
 
-  unwindstack::SharedString name("");
   unwindstack::MapInfo* prev_map = nullptr;
   unwindstack::MapInfo* prev_real_map = nullptr;
   return android::procinfo::ReadMapFileContent(
-      &content[0], [&](const android::procinfo::MapInfo& mapinfo) {
+      &content[0], [&](uint64_t start, uint64_t end, uint16_t flags,
+                       uint64_t pgoff, ino_t, const char* name) {
         // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
-        auto flags = mapinfo.flags;
-        if (strncmp(mapinfo.name.c_str(), "/dev/", 5) == 0 &&
-            strncmp(mapinfo.name.c_str() + 5, "ashmem/", 7) != 0) {
+        if (strncmp(name, "/dev/", 5) == 0 &&
+            strncmp(name + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
         }
-        // Share the string if it matches for consecutive maps.
-        if (name != mapinfo.name) {
-          name = unwindstack::SharedString(mapinfo.name);
-        }
         maps_.emplace_back(new unwindstack::MapInfo(
-            prev_map, prev_real_map, mapinfo.start, mapinfo.end, mapinfo.pgoff,
-            flags, name));
+            prev_map, prev_real_map, start, end, pgoff, flags, name));
         prev_map = maps_.back().get();
         if (!prev_map->IsBlank()) {
           prev_real_map = prev_map;
@@ -99,7 +92,15 @@
 UnwindingMetadata::UnwindingMetadata(base::ScopedFile maps_fd,
                                      base::ScopedFile mem_fd)
     : fd_maps(std::move(maps_fd)),
-      fd_mem(std::make_shared<FDMemory>(std::move(mem_fd))) {
+      fd_mem(std::make_shared<FDMemory>(std::move(mem_fd)))
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+      ,
+      jit_debug(std::unique_ptr<unwindstack::JitDebug>(
+          new unwindstack::JitDebug(fd_mem))),
+      dex_files(std::unique_ptr<unwindstack::DexFiles>(
+          new unwindstack::DexFiles(fd_mem)))
+#endif
+{
   if (!fd_maps.Parse())
     PERFETTO_DLOG("Failed initial maps parse");
 }
@@ -109,38 +110,22 @@
   fd_maps.Reset();
   fd_maps.Parse();
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  jit_debug.reset();
-  dex_files.reset();
+  jit_debug =
+      std::unique_ptr<unwindstack::JitDebug>(new unwindstack::JitDebug(fd_mem));
+  dex_files =
+      std::unique_ptr<unwindstack::DexFiles>(new unwindstack::DexFiles(fd_mem));
 #endif
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-unwindstack::JitDebug* UnwindingMetadata::GetJitDebug(unwindstack::ArchEnum arch) {
-  if (jit_debug.get() == nullptr) {
-    std::vector<std::string> search_libs{"libart.so", "libartd.so"};
-    jit_debug = unwindstack::CreateJitDebug(arch, fd_mem, search_libs);
-  }
-  return jit_debug.get();
-}
-
-unwindstack::DexFiles* UnwindingMetadata::GetDexFiles(unwindstack::ArchEnum arch) {
-  if (dex_files.get() == nullptr) {
-    std::vector<std::string> search_libs{"libart.so", "libartd.so"};
-    dex_files = unwindstack::CreateDexFiles(arch, fd_mem, search_libs);
-  }
-  return dex_files.get();
-}
-#endif
-
-const std::string& UnwindingMetadata::GetBuildId(
-    const unwindstack::FrameData& frame) {
+FrameData UnwindingMetadata::AnnotateFrame(unwindstack::FrameData frame) {
+  std::string build_id;
   if (!frame.map_name.empty()) {
     unwindstack::MapInfo* map_info = fd_maps.Find(frame.pc);
     if (map_info)
-      return map_info->GetBuildID();
+      build_id = map_info->GetBuildID();
   }
 
-  return empty_string_;
+  return FrameData{std::move(frame), std::move(build_id)};
 }
 
 std::string StringifyLibUnwindstackError(unwindstack::ErrorCode e) {
@@ -161,12 +146,6 @@
       return "REPEATED_FRAME";
     case unwindstack::ERROR_INVALID_ELF:
       return "INVALID_ELF";
-    case unwindstack::ERROR_SYSTEM_CALL:
-      return "SYSTEM_CALL";
-    case unwindstack::ERROR_THREAD_DOES_NOT_EXIST:
-      return "THREAD_DOES_NOT_EXIST";
-    case unwindstack::ERROR_THREAD_TIMEOUT:
-      return "THREAD_TIMEOUT";
   }
 }
 
diff --git a/src/profiling/common/unwind_support.h b/src/profiling/common/unwind_support.h
index 4aafc18..76a2652 100644
--- a/src/profiling/common/unwind_support.h
+++ b/src/profiling/common/unwind_support.h
@@ -37,11 +37,20 @@
 namespace perfetto {
 namespace profiling {
 
+// libunwindstack's FrameData annotated with the build_id.
+struct FrameData {
+  FrameData(unwindstack::FrameData f, std::string id)
+      : frame(std::move(f)), build_id(std::move(id)) {}
+
+  unwindstack::FrameData frame;
+  std::string build_id;
+};
+
 // Read /proc/[pid]/maps from an open file descriptor.
 // TODO(fmayer): Figure out deduplication to other maps.
 class FDMaps : public unwindstack::Maps {
  public:
-  explicit FDMaps(base::ScopedFile fd);
+  FDMaps(base::ScopedFile fd);
 
   FDMaps(const FDMaps&) = delete;
   FDMaps& operator=(const FDMaps&) = delete;
@@ -66,7 +75,7 @@
 
 class FDMemory : public unwindstack::Memory {
  public:
-  explicit FDMemory(base::ScopedFile mem_fd);
+  FDMemory(base::ScopedFile mem_fd);
   size_t Read(uint64_t addr, void* dst, size_t size) override;
 
  private:
@@ -103,14 +112,8 @@
 
   void ReparseMaps();
 
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  unwindstack::JitDebug* GetJitDebug(unwindstack::ArchEnum arch);
-  unwindstack::DexFiles* GetDexFiles(unwindstack::ArchEnum arch);
-#endif
+  FrameData AnnotateFrame(unwindstack::FrameData frame);
 
-  const std::string& GetBuildId(const unwindstack::FrameData& frame);
-
-  std::string empty_string_;
   FDMaps fd_maps;
   // The API of libunwindstack expects shared_ptr for Memory.
   std::shared_ptr<unwindstack::Memory> fd_mem;
diff --git a/src/profiling/deobfuscator.cc b/src/profiling/deobfuscator.cc
index ba58dfa..a8b7652 100644
--- a/src/profiling/deobfuscator.cc
+++ b/src/profiling/deobfuscator.cc
@@ -14,29 +14,17 @@
  * limitations under the License.
  */
 
-#include "src/profiling/deobfuscator.h"
-
-#include "perfetto/base/status.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/profiling/deobfuscator.h"
 #include "perfetto/ext/base/string_splitter.h"
 
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace profiling {
 namespace {
 
-struct ProguardClass {
-  std::string obfuscated_name;
-  std::string deobfuscated_name;
-};
-
-base::Optional<ProguardClass> ParseClass(std::string line) {
+base::Optional<std::pair<std::string, std::string>> ParseClass(
+    std::string line) {
   base::StringSplitter ss(std::move(line), ' ');
 
   if (!ss.Next()) {
@@ -56,7 +44,7 @@
     return base::nullopt;
   }
   std::string obfuscated_name(ss.cur_token(), ss.cur_token_size());
-  if (obfuscated_name.empty()) {
+  if (obfuscated_name.size() == 0) {
     PERFETTO_ELOG("Empty obfuscated name.");
     return base::nullopt;
   }
@@ -70,22 +58,12 @@
     PERFETTO_ELOG("Unexpected data.");
     return base::nullopt;
   }
-  return ProguardClass{std::move(obfuscated_name),
-                       std::move(deobfuscated_name)};
+  return std::make_pair(std::move(obfuscated_name),
+                        std::move(deobfuscated_name));
 }
 
-enum class ProguardMemberType {
-  kField,
-  kMethod,
-};
-
-struct ProguardMember {
-  ProguardMemberType type;
-  std::string obfuscated_name;
-  std::string deobfuscated_name;
-};
-
-base::Optional<ProguardMember> ParseMember(std::string line) {
+base::Optional<std::pair<std::string, std::string>> ParseMember(
+    std::string line) {
   base::StringSplitter ss(std::move(line), ' ');
 
   if (!ss.Next()) {
@@ -116,187 +94,57 @@
     PERFETTO_ELOG("Unexpected data.");
     return base::nullopt;
   }
-
-  ProguardMemberType member_type;
-  auto paren_idx = deobfuscated_name.find('(');
-  if (paren_idx != std::string::npos) {
-    member_type = ProguardMemberType::kMethod;
-    deobfuscated_name = deobfuscated_name.substr(0, paren_idx);
-    auto colon_idx = type_name.find(':');
-    if (colon_idx != std::string::npos) {
-      type_name = type_name.substr(colon_idx + 1);
-    }
-  } else {
-    member_type = ProguardMemberType::kField;
-  }
-  return ProguardMember{member_type, std::move(obfuscated_name),
-                        std::move(deobfuscated_name)};
-}
-
-std::string FlattenMethods(const std::vector<std::string>& v) {
-  if (v.size() == 1) {
-    return v[0];
-  }
-  return "[ambiguous]";
+  return std::make_pair(std::move(obfuscated_name),
+                        std::move(deobfuscated_name));
 }
 
 }  // namespace
 
-std::string FlattenClasses(
-    const std::map<std::string, std::vector<std::string>>& m) {
-  std::string result;
-  bool first = true;
-  for (const auto& p : m) {
-    if (!first) {
-      result += " | ";
-    }
-    result += p.first + "." + FlattenMethods(p.second);
-    first = false;
-  }
-  return result;
-}
-
-// See https://www.guardsquare.com/en/products/proguard/manual/retrace for the
-// file format we are parsing.
-base::Status ProguardParser::AddLine(std::string line) {
-  if (line.length() == 0 || line[0] == '#')
-    return base::Status();
+bool ProguardParser::AddLine(std::string line) {
+  if (line.length() == 0)
+    return true;
   bool is_member = line[0] == ' ';
   if (is_member && !current_class_) {
-    return base::Status(
-        "Failed to parse proguard map. Saw member before class.");
+    PERFETTO_ELOG("Failed to parse proguard map. Saw member before class.");
+    return false;
   }
   if (!is_member) {
-    auto opt_cls = ParseClass(std::move(line));
-    if (!opt_cls)
-      return base::Status("Class not found.");
-    auto p = mapping_.emplace(std::move(opt_cls->obfuscated_name),
-                              std::move(opt_cls->deobfuscated_name));
+    std::string obfuscated_name;
+    std::string deobfuscated_name;
+    auto opt_pair = ParseClass(std::move(line));
+    if (!opt_pair)
+      return false;
+    std::tie(obfuscated_name, deobfuscated_name) = *opt_pair;
+    auto p = mapping_.emplace(std::move(obfuscated_name),
+                              std::move(deobfuscated_name));
     if (!p.second) {
-      return base::Status("Duplicate class.");
+      PERFETTO_ELOG("Duplicate class.");
+      return false;
     }
     current_class_ = &p.first->second;
   } else {
-    auto opt_member = ParseMember(std::move(line));
-    if (!opt_member)
-      return base::Status("Failed to parse member.");
-    switch (opt_member->type) {
-      case (ProguardMemberType::kField): {
-        if (!current_class_->AddField(opt_member->obfuscated_name,
-                                      opt_member->deobfuscated_name)) {
-          return base::Status(std::string("Member redefinition: ") +
-                              current_class_->deobfuscated_name().c_str() +
-                              "." + opt_member->deobfuscated_name.c_str() +
-                              " Proguard map invalid");
-        }
-        break;
-      }
-      case (ProguardMemberType::kMethod): {
-        current_class_->AddMethod(opt_member->obfuscated_name,
-                                  opt_member->deobfuscated_name);
-        break;
-      }
+    std::string obfuscated_name;
+    std::string deobfuscated_name;
+    auto opt_pair = ParseMember(std::move(line));
+    if (!opt_pair)
+      return false;
+    std::tie(obfuscated_name, deobfuscated_name) = *opt_pair;
+    // TODO(fmayer): Teach this to properly parse methods.
+    if (deobfuscated_name.find("(") != std::string::npos) {
+      // Skip functions, as they will trigger the "Duplicate member" below.
+      return true;
     }
-  }
-  return base::Status();
-}
-
-bool ProguardParser::AddLines(std::string contents) {
-  size_t lineno = 1;
-  for (base::StringSplitter lines(std::move(contents), '\n'); lines.Next();) {
-    auto status = AddLine(lines.cur_token());
-    if (!status.ok()) {
-      PERFETTO_ELOG("Failed to parse proguard map (line %zu): %s", lineno,
-                    status.c_message());
+    auto p = current_class_->deobfuscated_fields.emplace(obfuscated_name,
+                                                         deobfuscated_name);
+    if (!p.second && p.first->second != deobfuscated_name) {
+      PERFETTO_ELOG("Member redefinition: %s.%s",
+                    current_class_->deobfuscated_name.c_str(),
+                    deobfuscated_name.c_str());
       return false;
     }
-    lineno++;
   }
   return true;
 }
 
-void MakeDeobfuscationPackets(
-    const std::string& package_name,
-    const std::map<std::string, profiling::ObfuscatedClass>& mapping,
-    std::function<void(const std::string&)> callback) {
-  protozero::HeapBuffered<perfetto::protos::pbzero::Trace> trace;
-  auto* packet = trace->add_packet();
-  // TODO(fmayer): Add handling for package name and version code here so we
-  // can support multiple dumps in the same trace.
-  auto* proto_mapping = packet->set_deobfuscation_mapping();
-  proto_mapping->set_package_name(package_name);
-  for (const auto& p : mapping) {
-    const std::string& obfuscated_class_name = p.first;
-    const profiling::ObfuscatedClass& cls = p.second;
-
-    auto* proto_class = proto_mapping->add_obfuscated_classes();
-    proto_class->set_obfuscated_name(obfuscated_class_name);
-    proto_class->set_deobfuscated_name(cls.deobfuscated_name());
-    for (const auto& field_p : cls.deobfuscated_fields()) {
-      const std::string& obfuscated_field_name = field_p.first;
-      const std::string& deobfuscated_field_name = field_p.second;
-      auto* proto_member = proto_class->add_obfuscated_members();
-      proto_member->set_obfuscated_name(obfuscated_field_name);
-      proto_member->set_deobfuscated_name(deobfuscated_field_name);
-    }
-    for (const auto& field_p : cls.deobfuscated_methods()) {
-      const std::string& obfuscated_method_name = field_p.first;
-      const std::string& deobfuscated_method_name = field_p.second;
-      auto* proto_member = proto_class->add_obfuscated_methods();
-      proto_member->set_obfuscated_name(obfuscated_method_name);
-      proto_member->set_deobfuscated_name(deobfuscated_method_name);
-    }
-  }
-  callback(trace.SerializeAsString());
-}
-
-bool ReadProguardMapsToDeobfuscationPackets(
-    const std::vector<ProguardMap>& maps,
-    std::function<void(std::string)> fn) {
-  for (const ProguardMap& map : maps) {
-    const char* filename = map.filename.c_str();
-    base::ScopedFstream f(fopen(filename, "re"));
-    if (!f) {
-      PERFETTO_ELOG("Failed to open %s", filename);
-      return false;
-    }
-    profiling::ProguardParser parser;
-    std::string contents;
-    PERFETTO_CHECK(base::ReadFileStream(*f, &contents));
-    if (!parser.AddLines(std::move(contents))) {
-      PERFETTO_ELOG("Failed to parse %s", filename);
-      return false;
-    }
-    std::map<std::string, profiling::ObfuscatedClass> obfuscation_map =
-        parser.ConsumeMapping();
-
-    // TODO(fmayer): right now, we don't use the profile we are given. We can
-    // filter the output to only contain the classes actually seen in the
-    // profile.
-    MakeDeobfuscationPackets(map.package, obfuscation_map, fn);
-  }
-  return true;
-}
-
-std::vector<ProguardMap> GetPerfettoProguardMapPath() {
-  const char* env = getenv("PERFETTO_PROGUARD_MAP");
-  if (env == nullptr)
-    return {};
-  std::vector<ProguardMap> res;
-  for (base::StringSplitter sp(std::string(env), ':'); sp.Next();) {
-    std::string token(sp.cur_token(), sp.cur_token_size());
-    size_t eq = token.find('=');
-    if (eq == std::string::npos) {
-      PERFETTO_ELOG(
-          "Invalid PERFETTO_PROGUARD_MAP. "
-          "Expected format packagename=filename[:packagename=filename...], "
-          "e.g. com.example.package1=foo.txt:com.example.package2=bar.txt.");
-      return {};
-    }
-    res.emplace_back(ProguardMap{token.substr(0, eq), token.substr(eq + 1)});
-  }
-  return res;  // for Wreturn-std-move-in-c++11.
-}
-
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/deobfuscator.h b/src/profiling/deobfuscator.h
deleted file mode 100644
index b96f292..0000000
--- a/src/profiling/deobfuscator.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_DEOBFUSCATOR_H_
-#define SRC_PROFILING_DEOBFUSCATOR_H_
-
-#include <functional>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-#include "perfetto/base/status.h"
-
-namespace perfetto {
-namespace profiling {
-
-std::string FlattenClasses(
-    const std::map<std::string, std::vector<std::string>>& m);
-
-class ObfuscatedClass {
- public:
-  explicit ObfuscatedClass(std::string d) : deobfuscated_name_(std::move(d)) {}
-  ObfuscatedClass(
-      std::string d,
-      std::map<std::string, std::string> f,
-      std::map<std::string, std::map<std::string, std::vector<std::string>>> m)
-      : deobfuscated_name_(std::move(d)),
-        deobfuscated_fields_(std::move(f)),
-        deobfuscated_methods_(std::move(m)) {}
-
-  const std::string& deobfuscated_name() const { return deobfuscated_name_; }
-
-  const std::map<std::string, std::string>& deobfuscated_fields() const {
-    return deobfuscated_fields_;
-  }
-
-  std::map<std::string, std::string> deobfuscated_methods() const {
-    std::map<std::string, std::string> result;
-    for (const auto& p : deobfuscated_methods_) {
-      result.emplace(p.first, FlattenClasses(p.second));
-    }
-    return result;
-  }
-
-  bool redefined_methods() const { return redefined_methods_; }
-
-  bool AddField(std::string obfuscated_name, std::string deobfuscated_name) {
-    auto p = deobfuscated_fields_.emplace(std::move(obfuscated_name),
-                                          deobfuscated_name);
-    return p.second || p.first->second == deobfuscated_name;
-  }
-
-  void AddMethod(std::string obfuscated_name, std::string deobfuscated_name) {
-    std::string cls = deobfuscated_name_;
-    auto dot = deobfuscated_name.rfind('.');
-    if (dot != std::string::npos) {
-      cls = deobfuscated_name.substr(0, dot);
-      deobfuscated_name = deobfuscated_name.substr(dot + 1);
-    }
-    auto& deobfuscated_names_for_cls =
-        deobfuscated_methods_[std::move(obfuscated_name)][std::move(cls)];
-    deobfuscated_names_for_cls.push_back(std::move(deobfuscated_name));
-    if (deobfuscated_names_for_cls.size() > 1 ||
-        deobfuscated_methods_.size() > 1) {
-      redefined_methods_ = true;
-    }
-  }
-
- private:
-  std::string deobfuscated_name_;
-  std::map<std::string, std::string> deobfuscated_fields_;
-  std::map<std::string, std::map<std::string, std::vector<std::string>>>
-      deobfuscated_methods_;
-  bool redefined_methods_ = false;
-};
-
-class ProguardParser {
- public:
-  // A return value of false means this line failed to parse. This leaves the
-  // parser in an undefined state and it should no longer be used.
-  base::Status AddLine(std::string line);
-  bool AddLines(std::string contents);
-
-  std::map<std::string, ObfuscatedClass> ConsumeMapping() {
-    return std::move(mapping_);
-  }
-
- private:
-  std::map<std::string, ObfuscatedClass> mapping_;
-  ObfuscatedClass* current_class_ = nullptr;
-};
-
-struct ProguardMap {
-  std::string package;
-  std::string filename;
-};
-
-void MakeDeobfuscationPackets(
-    const std::string& package_name,
-    const std::map<std::string, profiling::ObfuscatedClass>& mapping,
-    std::function<void(const std::string&)> callback);
-
-std::vector<ProguardMap> GetPerfettoProguardMapPath();
-
-bool ReadProguardMapsToDeobfuscationPackets(
-    const std::vector<ProguardMap>& maps,
-    std::function<void(std::string)> fn);
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_DEOBFUSCATOR_H_
diff --git a/src/profiling/deobfuscator_unittest.cc b/src/profiling/deobfuscator_unittest.cc
index 02a0e8d..0d9619a 100644
--- a/src/profiling/deobfuscator_unittest.cc
+++ b/src/profiling/deobfuscator_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/profiling/deobfuscator.h"
+#include "perfetto/profiling/deobfuscator.h"
 
 #include "test/gtest_and_gmock.h"
 
@@ -23,24 +23,18 @@
 
 bool operator==(const ObfuscatedClass& a, const ObfuscatedClass& b);
 bool operator==(const ObfuscatedClass& a, const ObfuscatedClass& b) {
-  return a.deobfuscated_name() == b.deobfuscated_name() &&
-         a.deobfuscated_fields() == b.deobfuscated_fields() &&
-         a.deobfuscated_methods() == b.deobfuscated_methods();
+  return a.deobfuscated_name == b.deobfuscated_name &&
+         a.deobfuscated_fields == b.deobfuscated_fields;
 }
 
 namespace {
 
-using ::testing::_;
 using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::Pair;
 
 TEST(ProguardParserTest, ReadClass) {
   ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
+  ASSERT_TRUE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:"));
   ASSERT_THAT(p.ConsumeMapping(),
               ElementsAre(std::pair<std::string, ObfuscatedClass>(
                   "android.arch.a.a.a",
@@ -49,179 +43,53 @@
 
 TEST(ProguardParserTest, MissingColon) {
   ProguardParser p;
-  ASSERT_FALSE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a")
-          .ok());
+  ASSERT_FALSE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a"));
 }
 
 TEST(ProguardParserTest, UnexpectedMember) {
   ProguardParser p;
   ASSERT_FALSE(
-      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b")
-          .ok());
+      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b"));
 }
 
 TEST(ProguardParserTest, Member) {
   ProguardParser p;
+  ASSERT_TRUE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:"));
   ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(
-      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b")
-          .ok());
+      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b"));
   std::map<std::string, std::string> deobfuscated_fields{{"b", "mDelegate"}};
   ASSERT_THAT(
       p.ConsumeMapping(),
       ElementsAre(std::pair<std::string, ObfuscatedClass>(
           "android.arch.a.a.a", {"android.arch.core.executor.ArchTaskExecutor",
-                                 std::move(deobfuscated_fields),
-                                 {}})));
+                                 std::move(deobfuscated_fields)})));
 }
 
 TEST(ProguardParserTest, Method) {
   ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  auto mapping = p.ConsumeMapping();
-  ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
-  EXPECT_THAT(
-      mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
-      ElementsAre(Pair(
-          "b", "android.arch.core.executor.ArchTaskExecutor.isMainThread")));
-}
-
-TEST(ProguardParserTest, AmbiguousMethodSameCls) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean somethingDifferent(int):116:116 -> b").ok());
-  auto mapping = p.ConsumeMapping();
-  ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
-  EXPECT_THAT(
-      mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
-      ElementsAre(Pair(
-          "b", "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
-}
-
-TEST(ProguardParserTest, AmbiguousMethodDifferentCls) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
-          .ok());
-  auto mapping = p.ConsumeMapping();
-  ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
-  EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
-              ElementsAre(Pair(
-                  "b",
-                  "Foo.somethingDifferent | "
-                  "android.arch.core.executor.ArchTaskExecutor.isMainThread")));
-}
-
-TEST(ProguardParserTest, AmbiguousMethodSameAndDifferentCls) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean what(String):116:116 -> b").ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
-          .ok());
-  auto mapping = p.ConsumeMapping();
-  ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
-  EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
-              ElementsAre(Pair(
-                  "b",
-                  "Foo.somethingDifferent | "
-                  "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
-}
-
-TEST(ProguardParserTest, AmbiguousMethodSameAndDifferentCls2) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean what(String):116:116 -> b").ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
-          .ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean Foo.third(int,int):116:116 -> b").ok());
-  auto mapping = p.ConsumeMapping();
-  ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
-  EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
-              ElementsAre(Pair(
-                  "b",
-                  "Foo.[ambiguous] | "
-                  "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
+  ASSERT_TRUE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:"));
+  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b"));
 }
 
 TEST(ProguardParserTest, DuplicateClass) {
   ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_FALSE(p.AddLine("android.arch.core.executor.ArchTaskExecutor2 -> "
-                         "android.arch.a.a.a:")
-                   .ok());
+  ASSERT_TRUE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:"));
+  ASSERT_FALSE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor2 -> android.arch.a.a.a:"));
 }
 
 TEST(ProguardParserTest, DuplicateField) {
   ProguardParser p;
+  ASSERT_TRUE(p.AddLine(
+      "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:"));
   ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(
-      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b")
-          .ok());
+      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b"));
   ASSERT_FALSE(
-      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate2 -> b")
-          .ok());
-}
-
-TEST(ProguardParserTest, DuplicateMethod) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(p.AddLine("    15:15:boolean isMainThread():116:116 -> b").ok());
-  ASSERT_TRUE(
-      p.AddLine("    15:15:boolean doSomething(boolean):116:116 -> b").ok());
-}
-
-TEST(ProguardParserTest, DuplicateFieldSame) {
-  ProguardParser p;
-  ASSERT_TRUE(
-      p.AddLine(
-           "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
-          .ok());
-  ASSERT_TRUE(
-      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate -> b")
-          .ok());
-  ASSERT_TRUE(
-      p.AddLine(
-           "    1:1:android.arch.core.executor.TaskExecutor mDelegate -> b")
-          .ok());
+      p.AddLine("    android.arch.core.executor.TaskExecutor mDelegate2 -> b"));
 }
 
 }  // namespace
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index f0e350f..18f81b3 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -46,147 +46,31 @@
   shared_library("heapprofd_client") {
     configs -= [ "//gn/standalone:android_liblog" ]
     cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
-    deps = [
-      ":heapprofd_client_api",
-      ":malloc_interceptor_bionic_hooks",
-    ]
+    deps = [ ":malloc_hooks" ]
   }
 
-  # This will export publicly visible symbols for the
-  # malloc_interceptor_bionic_hooks.
-  source_set("malloc_interceptor_bionic_hooks") {
+  # This will export publicly visible symbols for the malloc_hooks.
+  source_set("malloc_hooks") {
     deps = [
-      ":bionic_libc_platform_headers_on_android",
-      ":wrap_allocators",
+      ":client",
+      ":scoped_spinlock",
+      ":wire_protocol",
       "../../../gn:default_deps",
       "../../base",
+      "../../base:unix_socket",
+      "../common:proc_utils",
     ]
     cflags = [
       "-isystem",
       rebase_path("../../../buildtools/bionic/libc", root_build_dir),
     ]
-    sources = [ "malloc_interceptor_bionic_hooks.cc" ]
+    sources = [ "malloc_hooks.cc" ]
   }
 }  # if (perfetto_build_with_android)
 
-executable("heapprofd_standalone_client_example") {
-  deps = [
-    ":heapprofd_standalone_client",
-    "../../../gn:default_deps",
-  ]
-  sources = [ "heapprofd_standalone_client_example.cc" ]
-}
-
-source_set("client_api_standalone") {
-  deps = [
-    ":client",
-    ":client_api",
-    ":daemon",
-    "../../../gn:default_deps",
-    "../../../include/perfetto/ext/tracing/ipc",
-    "../../base",
-    "../common:proc_utils",
-  ]
-  sources = [ "client_api_factory_standalone.cc" ]
-}
-
-# This can be used to instrument custom allocators to report their allocations
-# to Perfetto. This bundles a copy of heapprofd in the library, in contrast to
-# heapprofd_client_api (see below), which expects one to be present in the
-# Android platform.
-shared_library("heapprofd_standalone_client") {
-  deps = [
-    ":client_api_standalone",
-    "../../../gn:default_deps",
-  ]
-  ldflags = [
-    "-Wl,--version-script",
-    rebase_path("heapprofd_client_api.map.txt", root_build_dir),
-  ]
-}
-
-shared_library("heapprofd_api_noop") {
-  deps = [ "../../../gn:default_deps" ]
-  ldflags = [
-    "-Wl,--version-script",
-    rebase_path("heapprofd_client_api.map.txt", root_build_dir),
-  ]
-
-  # This target does absolutely nothing, so we do not want to depend on
-  # liblog.
-  configs -= [ "//gn/standalone:android_liblog" ]
-  sources = [ "client_api_noop.cc" ]
-}
-
-shared_library("heapprofd_client_api") {
-  configs -= [ "//gn/standalone:android_liblog" ]
-  if (perfetto_build_with_android) {
-    cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
-  } else {
-    # We don't have async safe logging for non-Android, so disable all
-    # logging in the client.
-    # TODO(fmayer): Add async-safe logging for non-Android.
-    cflags = [ "-DPERFETTO_DISABLE_LOG" ]
-  }
-  deps = [ ":client_api" ]
-  if (perfetto_build_with_android) {
-    sources = [ "client_api_factory_android.cc" ]
-  }
-}
-
-# On GLibc Linux, this can be used to override the allocators using
-# LD_PRELOAD. On non-GLibc, this will probably fail to link.
-shared_library("heapprofd_glibc_preload") {
-  deps = [
-    ":client_api_standalone",
-    ":wrap_allocators",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-  ldflags = [
-    "-Wl,--version-script",
-    rebase_path("heapprofd_preload.map.txt", root_build_dir),
-  ]
-  sources = [ "malloc_interceptor_glibc_preload.cc" ]
-}
-
-# On Android builds, this is converted to
-# header_libs: ["bionic_libc_platform_headers"].
-source_set("bionic_libc_platform_headers_on_android") {
-}
-
-source_set("client_api") {
-  if (perfetto_build_with_android) {
-    cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
-  } else {
-    # We don't have async safe logging for non-Android, so disable all
-    # logging in the client.
-    # TODO(fmayer): Add async-safe logging for non-Android.
-    cflags = [ "-DPERFETTO_DISABLE_LOG" ]
-  }
-  deps = [
-    ":client",
-    ":scoped_spinlock",
-    ":wire_protocol",
-    "../../../gn:default_deps",
-    "../../base",
-    "../common:proc_utils",
-  ]
-  sources = [ "client_api.cc" ]
-}
-
-source_set("wrap_allocators") {
-  deps = [
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-  sources = [ "wrap_allocators.cc" ]
-}
-
 source_set("wire_protocol") {
   public_deps = [ "../../../gn:libunwindstack" ]
   deps = [
-    ":bionic_libc_platform_headers_on_android",
     ":ring_buffer",
     "../../../gn:default_deps",
     "../../base",
@@ -247,8 +131,6 @@
     "../common:interner",
     "../common:interning_output",
     "../common:proc_utils",
-    "../common:producer_support",
-    "../common:profiler_guardrails",
     "../common:unwind_support",
   ]
   public_deps = [
@@ -267,8 +149,8 @@
     "heapprofd_producer.h",
     "java_hprof_producer.cc",
     "java_hprof_producer.h",
-    "log_histogram.cc",
-    "log_histogram.h",
+    "page_idle_checker.cc",
+    "page_idle_checker.h",
     "system_property.cc",
     "system_property.h",
     "unwinding.cc",
@@ -291,7 +173,6 @@
   sources = [
     "client.cc",
     "client.h",
-    "sampler.cc",
     "sampler.h",
   ]
 }
@@ -301,7 +182,6 @@
   deps = [
     ":client",
     ":daemon",
-    ":ring_buffer",
     ":wire_protocol",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
@@ -316,19 +196,13 @@
     "bookkeeping_unittest.cc",
     "client_unittest.cc",
     "heapprofd_producer_unittest.cc",
+    "page_idle_checker_unittest.cc",
     "parse_smaps_unittest.cc",
     "sampler_unittest.cc",
     "system_property_unittest.cc",
     "unwinding_unittest.cc",
     "wire_protocol_unittest.cc",
   ]
-
-  # Do not build with Android to avoid applying PERFETTO_ANDROID_ASYNC_SAFE_LOG
-  # to the whole perfetto_unittests target.
-  if (!perfetto_build_with_android) {
-    sources += [ "client_api_unittest.cc" ]
-    deps += [ ":client_api" ]
-  }
 }
 
 source_set("end_to_end_tests") {
@@ -341,19 +215,12 @@
     "../../../gn:gtest_and_gmock",
     "../../../gn:libunwindstack",
     "../../../protos/perfetto/config/profiling:cpp",
-    "../../../protos/perfetto/trace/interned_data:cpp",
     "../../../protos/perfetto/trace/profiling:cpp",
     "../../../test:test_helper",
     "../../base",
     "../../base:test_support",
-    "../../trace_processor:lib",
   ]
   sources = [ "heapprofd_end_to_end_test.cc" ]
-  if (perfetto_build_with_android) {
-    deps += [ ":heapprofd_client_api" ]
-  } else {
-    deps += [ ":heapprofd_standalone_client" ]
-  }
   if (start_daemons_for_testing) {
     defines = [ "PERFETTO_START_DAEMONS_FOR_TESTING" ]
   }
@@ -392,18 +259,3 @@
     "../../base",
   ]
 }
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":client",
-      ":client_api",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
-      "../../base",
-      "../../base:test_support",
-    ]
-    sources = [ "client_api_benchmark.cc" ]
-  }
-}
diff --git a/src/profiling/memory/CHANGELOG.md b/src/profiling/memory/CHANGELOG.md
index 28be84f..31a35bb 100644
--- a/src/profiling/memory/CHANGELOG.md
+++ b/src/profiling/memory/CHANGELOG.md
@@ -1,18 +1,4 @@
-# In Android 12 (upcoming)
-
-## New features
-* Support Custom Allocators. This allows developers to instrument their
-  applications to report memory allocations / frees that are not done
-  through the malloc-based system allocators.
-
-## Bugfixes
-* Fix problems with allocations done in signal handlers using SA_ONSTACK.
-* Fixed heapprofd for multi API. A 64-bit heapprofd service can now correctly
-  profile a 32-bit target.
-* Fixed a bug where specifying a sampling rate of 0 would crash the target
-  process.
-
-# In Android 11
+# Changes from Android 10
 
 ## New features
 * Allow to specify whether profiling should only be done for existing processes
@@ -20,16 +6,8 @@
   `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 using
-  `dump_at_max` in `HeapprofdConfig`.
-* Allow to specify timeout (`block_client_timeout_us`) when blocking mode is
-  used. This will tear down the profile if the client would be blocked for
-  longer than this.
-* Try to auto-detect if a process uses `vfork(2)` or `clone(2)` with
-  `CLONE_VM`. In Android 10, doing memory operations in a vfork-ed child (in
-  violation of POSIX) would tear down the parent's profiling session early.
+* Allow to dump the maximum, rather than at the time of the dump.
 
 ## Bugfixes
 * Fixed heapprofd on x86.
 * Fixed issue with calloc being incorrectly sampled.
-* Remove benign `ERROR 2` bottom-most frame on ARM32.
diff --git a/src/profiling/memory/README.md b/src/profiling/memory/README.md
index 770cc30..2fa5747 100644
--- a/src/profiling/memory/README.md
+++ b/src/profiling/memory/README.md
@@ -3,88 +3,6 @@
 heapprofd allows you to attribute memory usage to functions for Android services
 and apps.
 
-For documentation, see https://perfetto.dev/docs/data-sources/native-heap-profiler.
+For documentation, see https://docs.perfetto.dev/#/heapprofd.
 
-For design doc, see https://perfetto.dev/docs/design-docs/heapprofd-design.
-
-## GN Targets
-### Factories
-android: connects to the system heapprofd. The client API will need to have
-         been built at *exactly* the same version. This means this can only
-         be used by the API shipped in the platform.
-
-standalone: executes an in-process heapprofd. Can be used on old platform
-            versions.
-
-noop: ignores all calls to the client API. This can be used as a stand-in when
-      compiling, or when executing without profiling.
-
-### Interceptors
-bionic: uses bionic [malloc dispatch](
-https://cs.android.com/android/platform/superproject/+/master:bionic/libc/private/bionic_malloc_dispatch.h)
-to intercept allocation functions on Android. This works by placing a library
-on a pre-defined path, which gets [loaded by Bionic](
-https://cs.android.com/android/platform/superproject/+/master:bionic/libc/bionic/malloc_heapprofd.cpp).
-
-glibc: generates a library exposing the allocation functions. This library
-       should be used for `LD_PRELOAD` and uses the glibc specific symbols
-       like `__libc_malloc` to use the system allocator.
-
-### Shared libraries
-
-| GN target                   | factory    | interceptor | distribution |
-|-----------------------------|------------|-------------|--------------|
-| heapprofd_client            | android    | bionic      | platform     |
-| heapprofd_client_api        | android    | none        | platform     |
-| heapprofd_glibc_preload     | standalone | glibc       | unbundled    |
-| heapprofd_standalone_client | standalone | none        | unbundled    |
-| heapprofd_api_noop          | noop       | none        | unbundled    |
-
-
-## Heap profile heapprofd
-
-For development, you might want to get a heap profile of heapprofd while it
-is profiling something else. For that reason, we allow two heapprofds to run
-on the system. The secondary heapprofd can then profile your primary one.
-
-To do this, first make sure that heapprofd is running by setting the property
-
-```
-adb shell su root setprop persist.heapprofd.enable 1
-```
-
-Take note of its PID.
-
-```
-adb shell ps -e | grep heapprofd
-```
-
-Then, move away the primary heapprofd socket to make space for the secondary
-one
-
-```
-adb shell su root mv /dev/socket/heapprofd /dev/socket/heapprofd_primary
-```
-
-Start the secondary heapprofd
-
-```
-adb shell su root start heapprofd_secondary
-```
-
-Now we can start the profile of the primary heapprofd (using the secondary).
-Leave this session running.
-
-```
-tools/heap_profile -p ${PID_FROM_ABOVE}
-```
-
-Now move back the original socket
-
-```
-adb shell su root unlink /dev/socket/heapprofd
-adb shell su root mv /dev/socket/heapprofd_primary /dev/socket/heapprofd
-```
-
-Now all subsequent profiles will be done on the primary heapprofd again, with
-the secondary observing it.
+Googlers, for design doc see: http://goto.google.com/heapprofd-design.
diff --git a/src/profiling/memory/bookkeeping.cc b/src/profiling/memory/bookkeeping.cc
index 3439db4..93c9c17 100644
--- a/src/profiling/memory/bookkeeping.cc
+++ b/src/profiling/memory/bookkeeping.cc
@@ -29,26 +29,21 @@
 namespace perfetto {
 namespace profiling {
 
-void HeapTracker::RecordMalloc(
-    const std::vector<unwindstack::FrameData>& callstack,
-    const std::vector<std::string>& build_ids,
-    uint64_t address,
-    uint64_t sample_size,
-    uint64_t alloc_size,
-    uint64_t sequence_number,
-    uint64_t timestamp) {
-  PERFETTO_CHECK(callstack.size() == build_ids.size());
+void HeapTracker::RecordMalloc(const std::vector<FrameData>& callstack,
+                               uint64_t address,
+                               uint64_t sample_size,
+                               uint64_t alloc_size,
+                               uint64_t sequence_number,
+                               uint64_t timestamp) {
   std::vector<Interned<Frame>> frames;
   frames.reserve(callstack.size());
-  for (size_t i = 0; i < callstack.size(); ++i) {
-    const unwindstack::FrameData& loc = callstack[i];
-    const std::string& build_id = build_ids[i];
-    auto frame_it = frame_cache_.find(loc.pc);
+  for (const FrameData& loc : callstack) {
+    auto frame_it = frame_cache_.find(loc.frame.pc);
     if (frame_it != frame_cache_.end()) {
       frames.emplace_back(frame_it->second);
     } else {
-      frames.emplace_back(callsites_->InternCodeLocation(loc, build_id));
-      frame_cache_.emplace(loc.pc, frames.back());
+      frames.emplace_back(callsites_->InternCodeLocation(loc));
+      frame_cache_.emplace(loc.frame.pc, frames.back());
     }
   }
 
@@ -110,8 +105,7 @@
 void HeapTracker::CommitOperation(uint64_t sequence_number,
                                   const PendingOperation& operation) {
   committed_sequence_number_++;
-  if (operation.timestamp)
-    committed_timestamp_ = operation.timestamp;
+  committed_timestamp_ = operation.timestamp;
 
   uint64_t address = operation.allocation_address;
 
@@ -135,12 +129,9 @@
   //  be treated as a no-op.
 }
 
-uint64_t HeapTracker::GetSizeForTesting(
-    const std::vector<unwindstack::FrameData>& stack,
-    std::vector<std::string> build_ids) {
+uint64_t HeapTracker::GetSizeForTesting(const std::vector<FrameData>& stack) {
   PERFETTO_DCHECK(!dump_at_max_mode_);
-  GlobalCallstackTrie::Node* node =
-      callsites_->CreateCallsite(stack, build_ids);
+  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);
@@ -153,12 +144,9 @@
   return alloc.value.totals.allocated - alloc.value.totals.freed;
 }
 
-uint64_t HeapTracker::GetMaxForTesting(
-    const std::vector<unwindstack::FrameData>& stack,
-    std::vector<std::string> build_ids) {
+uint64_t HeapTracker::GetMaxForTesting(const std::vector<FrameData>& stack) {
   PERFETTO_DCHECK(dump_at_max_mode_);
-  GlobalCallstackTrie::Node* node =
-      callsites_->CreateCallsite(stack, build_ids);
+  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);
@@ -171,23 +159,6 @@
   return alloc.value.retain_max.max;
 }
 
-uint64_t HeapTracker::GetMaxCountForTesting(
-    const std::vector<unwindstack::FrameData>& stack,
-    std::vector<std::string> build_ids) {
-  PERFETTO_DCHECK(dump_at_max_mode_);
-  GlobalCallstackTrie::Node* node =
-      callsites_->CreateCallsite(stack, build_ids);
-  // 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_count;
-}
 
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/bookkeeping.h b/src/profiling/memory/bookkeeping.h
index 6aa9086..9568d4b 100644
--- a/src/profiling/memory/bookkeeping.h
+++ b/src/profiling/memory/bookkeeping.h
@@ -96,22 +96,19 @@
   struct CallstackMaxAllocations {
     uint64_t max;
     uint64_t cur;
-    uint64_t max_count;
-    uint64_t cur_count;
   };
   struct CallstackTotalAllocations {
     uint64_t allocated;
     uint64_t freed;
-    uint64_t allocation_count;
-    uint64_t free_count;
   };
 
   // Sum of all the allocations for a given callstack.
   struct CallstackAllocations {
-    explicit CallstackAllocations(GlobalCallstackTrie::Node* n) : node(n) {}
+    CallstackAllocations(GlobalCallstackTrie::Node* n) : node(n) {}
 
     uint64_t allocs = 0;
-
+    uint64_t allocation_count = 0;
+    uint64_t free_count = 0;
     union {
       CallstackMaxAllocations retain_max;
       CallstackTotalAllocations totals;
@@ -130,8 +127,7 @@
   explicit HeapTracker(GlobalCallstackTrie* callsites, bool dump_at_max_mode)
       : callsites_(callsites), dump_at_max_mode_(dump_at_max_mode) {}
 
-  void RecordMalloc(const std::vector<unwindstack::FrameData>& callstack,
-                    const std::vector<std::string>& build_ids,
+  void RecordMalloc(const std::vector<FrameData>& stack,
                     uint64_t address,
                     uint64_t sample_size,
                     uint64_t alloc_size,
@@ -149,14 +145,7 @@
       auto& it = it_and_alloc.first;
       uint64_t allocated = it_and_alloc.second;
       const CallstackAllocations& alloc = it->second;
-      // For non-dump-at-max, we need to check, even if there are still no
-      // allocations referencing this callstack, whether there were any
-      // allocations that happened but were freed again. If that was the case,
-      // we need to keep the callsite, because the next dump will indicate a
-      // different self_alloc and self_freed.
-      if (alloc.allocs == 0 &&
-          (dump_at_max_mode_ ||
-           alloc.value.totals.allocation_count == allocated)) {
+      if (alloc.allocs == 0 && alloc.allocation_count == allocated) {
         // TODO(fmayer): We could probably be smarter than throw away
         // our whole frames cache.
         ClearFrameCache();
@@ -171,8 +160,7 @@
       fn(alloc);
 
       if (alloc.allocs == 0)
-        dead_callstack_allocations_.emplace_back(
-            it, !dump_at_max_mode_ ? alloc.value.totals.allocation_count : 0);
+        dead_callstack_allocations_.emplace_back(it, alloc.allocation_count);
     }
   }
 
@@ -196,14 +184,8 @@
   uint64_t committed_timestamp() { return committed_timestamp_; }
   uint64_t max_timestamp() { return max_timestamp_; }
 
-  uint64_t GetSizeForTesting(const std::vector<unwindstack::FrameData>& stack,
-                             std::vector<std::string> build_ids);
-  uint64_t GetMaxForTesting(const std::vector<unwindstack::FrameData>& stack,
-                            std::vector<std::string> build_ids);
-  uint64_t GetMaxCountForTesting(
-      const std::vector<unwindstack::FrameData>& stack,
-      std::vector<std::string> build_ids);
-
+  uint64_t GetSizeForTesting(const std::vector<FrameData>& stack);
+  uint64_t GetMaxForTesting(const std::vector<FrameData>& stack);
   uint64_t GetTimestampForTesting() { return committed_timestamp_; }
 
  private:
@@ -281,21 +263,19 @@
                        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;
-      alloc.callstack_allocations()->value.retain_max.cur_count++;
 
       if (current_unfreed_ <= max_unfreed_)
         return;
 
       if (max_sequence_number_ == alloc.sequence_number - 1) {
-        // We know the only CallstackAllocation that has max != cur is the
-        // one we just updated.
         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;
-        alloc.callstack_allocations()->value.retain_max.max_count =
-            alloc.callstack_allocations()->value.retain_max.cur_count;
       } else {
         for (auto& p : callstack_allocations_) {
           // We need to reset max = cur for every CallstackAllocation, as we
@@ -303,7 +283,6 @@
           // TODO(fmayer): Add an index to speed this up
           CallstackAllocations& csa = p.second;
           csa.value.retain_max.max = csa.value.retain_max.cur;
-          csa.value.retain_max.max_count = csa.value.retain_max.cur_count;
         }
       }
       max_sequence_number_ = alloc.sequence_number;
@@ -312,18 +291,16 @@
     } else {
       alloc.callstack_allocations()->value.totals.allocated +=
           alloc.sample_size;
-      alloc.callstack_allocations()->value.totals.allocation_count++;
     }
   }
 
   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;
-      alloc.callstack_allocations()->value.retain_max.cur_count--;
     } else {
       alloc.callstack_allocations()->value.totals.freed += alloc.sample_size;
-      alloc.callstack_allocations()->value.totals.free_count++;
     }
   }
 
diff --git a/src/profiling/memory/bookkeeping_dump.cc b/src/profiling/memory/bookkeeping_dump.cc
index 7ce4a8c..514424b 100644
--- a/src/profiling/memory/bookkeeping_dump.cc
+++ b/src/profiling/memory/bookkeeping_dump.cc
@@ -58,14 +58,16 @@
   sample->set_callstack_id(alloc.node->id());
   if (dump_at_max_mode) {
     sample->set_self_max(alloc.value.retain_max.max);
-    sample->set_self_max_count(alloc.value.retain_max.max_count);
   } else {
     sample->set_self_allocated(alloc.value.totals.allocated);
     sample->set_self_freed(alloc.value.totals.freed);
-
-    sample->set_alloc_count(alloc.value.totals.allocation_count);
-    sample->set_free_count(alloc.value.totals.free_count);
   }
+  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) {
@@ -85,6 +87,10 @@
   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_)
diff --git a/src/profiling/memory/bookkeeping_dump.h b/src/profiling/memory/bookkeeping_dump.h
index 9c37676..bf19133 100644
--- a/src/profiling/memory/bookkeeping_dump.h
+++ b/src/profiling/memory/bookkeeping_dump.h
@@ -56,6 +56,8 @@
   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);
@@ -108,6 +110,7 @@
       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;
 };
diff --git a/src/profiling/memory/bookkeeping_unittest.cc b/src/profiling/memory/bookkeeping_unittest.cc
index 79e0183..b3d6a4e 100644
--- a/src/profiling/memory/bookkeeping_unittest.cc
+++ b/src/profiling/memory/bookkeeping_unittest.cc
@@ -25,62 +25,43 @@
 using ::testing::AnyOf;
 using ::testing::Eq;
 
-std::vector<unwindstack::FrameData> stack() {
-  std::vector<unwindstack::FrameData> res;
+std::vector<FrameData> stack() {
+  std::vector<FrameData> res;
 
   unwindstack::FrameData data{};
   data.function_name = "fun1";
   data.map_name = "map1";
   data.pc = 1;
-  res.emplace_back(std::move(data));
+  res.emplace_back(std::move(data), "dummy_buildid");
   data = {};
   data.function_name = "fun2";
   data.map_name = "map2";
   data.pc = 2;
-  res.emplace_back(std::move(data));
+  res.emplace_back(std::move(data), "dummy_buildid");
   return res;
 }
 
-std::vector<unwindstack::FrameData> stack2() {
-  std::vector<unwindstack::FrameData> res;
+std::vector<FrameData> stack2() {
+  std::vector<FrameData> res;
   unwindstack::FrameData data{};
   data.function_name = "fun1";
   data.map_name = "map1";
   data.pc = 1;
-  res.emplace_back(std::move(data));
+  res.emplace_back(std::move(data), "dummy_buildid");
   data = {};
   data.function_name = "fun3";
   data.map_name = "map3";
   data.pc = 3;
-  res.emplace_back(std::move(data));
+  res.emplace_back(std::move(data), "dummy_buildid");
   return res;
 }
 
-std::vector<unwindstack::FrameData> stack3() {
-  std::vector<unwindstack::FrameData> res;
-  unwindstack::FrameData data{};
-  data.function_name = "fun1";
-  data.map_name = "map1";
-  data.pc = 1;
-  res.emplace_back(std::move(data));
-  data = {};
-  data.function_name = "fun4";
-  data.map_name = "map4";
-  data.pc = 4;
-  res.emplace_back(std::move(data));
-  return res;
-}
-
-std::vector<std::string> DummyBuildIds(size_t n) {
-  return std::vector<std::string>(n, "dummy_buildid");
-}
-
 TEST(BookkeepingTest, EmptyStack) {
   uint64_t sequence_number = 1;
   GlobalCallstackTrie c;
   HeapTracker hd(&c, false);
 
-  hd.RecordMalloc({}, {}, 0x1, 5, 5, sequence_number, 100 * sequence_number);
+  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&) {});
@@ -91,11 +72,9 @@
   GlobalCallstackTrie c;
   HeapTracker hd(&c, false);
 
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 1, 5, 5,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 1, 5, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 1, 2, 2,
-                  sequence_number, 100 * 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&) {});
@@ -107,24 +86,22 @@
   GlobalCallstackTrie c;
   HeapTracker hd(&c, false);
 
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 5, 5,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x2, 2, 2,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack2(), 0x2, 2, 2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 5u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2(), DummyBuildIds(stack2().size())), 2u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 2u);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
   hd.RecordFree(0x2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 5u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2(), DummyBuildIds(stack2().size())), 0u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0u);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
   hd.RecordFree(0x1, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 0u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2(), DummyBuildIds(stack2().size())), 0u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 0u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0u);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
 }
 
@@ -133,54 +110,17 @@
   GlobalCallstackTrie c;
   HeapTracker hd(&c, true);
 
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 5, 5,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x2, 2, 2,
-                  sequence_number, 100 * 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++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x2, 1, 2,
-                  sequence_number, 100 * sequence_number);
   ASSERT_EQ(hd.max_timestamp(), 200u);
-  ASSERT_EQ(hd.GetMaxForTesting(stack(), DummyBuildIds(stack().size())), 5u);
-  ASSERT_EQ(hd.GetMaxForTesting(stack2(), DummyBuildIds(stack2().size())), 2u);
-  ASSERT_EQ(hd.GetMaxCountForTesting(stack(), DummyBuildIds(stack().size())),
-            1u);
-  ASSERT_EQ(hd.GetMaxCountForTesting(stack2(), DummyBuildIds(stack2().size())),
-            1u);
-}
-
-TEST(BookkeepingTest, Max2) {
-  uint64_t sequence_number = 1;
-  GlobalCallstackTrie c;
-  HeapTracker hd(&c, true);
-
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 10u, 10u,
-                  sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordFree(0x1, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x2, 15u, 15u,
-                  sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordMalloc(stack3(), DummyBuildIds(stack3().size()), 0x3, 15u, 15u,
-                  sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordFree(0x2, sequence_number, 100 * sequence_number);
-  EXPECT_EQ(hd.max_timestamp(), 400u);
-  EXPECT_EQ(hd.GetMaxForTesting(stack(), DummyBuildIds(stack().size())), 0u);
-  EXPECT_EQ(hd.GetMaxForTesting(stack2(), DummyBuildIds(stack2().size())), 15u);
-  EXPECT_EQ(hd.GetMaxForTesting(stack3(), DummyBuildIds(stack3().size())), 15u);
-  EXPECT_EQ(hd.GetMaxCountForTesting(stack(), DummyBuildIds(stack().size())),
-            0u);
-  EXPECT_EQ(hd.GetMaxCountForTesting(stack2(), DummyBuildIds(stack2().size())),
-            1u);
-  EXPECT_EQ(hd.GetMaxCountForTesting(stack3(), DummyBuildIds(stack3().size())),
-            1u);
+  ASSERT_EQ(hd.GetMaxForTesting(stack()), 5u);
+  ASSERT_EQ(hd.GetMaxForTesting(stack2()), 2u);
 }
 
 TEST(BookkeepingTest, TwoHeapTrackers) {
@@ -190,17 +130,15 @@
   {
     HeapTracker hd2(&c, false);
 
-    hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 5, 5,
-                    sequence_number, 100 * sequence_number);
-    hd2.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x2, 2, 2,
-                     sequence_number, 100 * sequence_number);
+    hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
+    hd2.RecordMalloc(stack(), 0x2, 2, 2, sequence_number,
+                     100 * sequence_number);
     sequence_number++;
-    ASSERT_EQ(hd2.GetSizeForTesting(stack(), DummyBuildIds(stack().size())),
-              2u);
-    ASSERT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 5u);
+    ASSERT_EQ(hd2.GetSizeForTesting(stack()), 2u);
+    ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
     ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
   }
-  ASSERT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 5u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
 }
 
 TEST(BookkeepingTest, ReplaceAlloc) {
@@ -208,14 +146,12 @@
   GlobalCallstackTrie c;
   HeapTracker hd(&c, false);
 
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 5, 5,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x1, 2, 2,
-                  sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack2(), 0x1, 2, 2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  EXPECT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 0u);
-  EXPECT_EQ(hd.GetSizeForTesting(stack2(), DummyBuildIds(stack2().size())), 2u);
+  EXPECT_EQ(hd.GetSizeForTesting(stack()), 0u);
+  EXPECT_EQ(hd.GetSizeForTesting(stack2()), 2u);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
 }
 
@@ -223,10 +159,10 @@
   GlobalCallstackTrie c;
   HeapTracker hd(&c, false);
 
-  hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), 0x1, 5, 5, 2, 2);
-  hd.RecordMalloc(stack2(), DummyBuildIds(stack2().size()), 0x1, 2, 2, 1, 1);
-  EXPECT_EQ(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())), 5u);
-  EXPECT_EQ(hd.GetSizeForTesting(stack2(), DummyBuildIds(stack2().size())), 0u);
+  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);
 }
 
 TEST(BookkeepingTest, ManyAllocations) {
@@ -243,21 +179,16 @@
     }
 
     uint64_t addr = sequence_number;
-    hd.RecordMalloc(stack(), DummyBuildIds(stack().size()), addr, 5, 5,
-                    sequence_number, sequence_number);
+    hd.RecordMalloc(stack(), addr, 5, 5, sequence_number, sequence_number);
     sequence_number++;
     batch_frees.emplace_back(addr, sequence_number++);
-    ASSERT_THAT(hd.GetSizeForTesting(stack(), DummyBuildIds(stack().size())),
-                AnyOf(Eq(0u), Eq(5u)));
+    ASSERT_THAT(hd.GetSizeForTesting(stack()), AnyOf(Eq(0u), Eq(5u)));
   }
 }
 
 TEST(BookkeepingTest, ArbitraryOrder) {
-  std::vector<unwindstack::FrameData> s = stack();
-  std::vector<unwindstack::FrameData> s2 = stack2();
-
-  std::vector<std::string> s_b = DummyBuildIds(s.size());
-  std::vector<std::string> s2_b = DummyBuildIds(s2.size());
+  std::vector<FrameData> s = stack();
+  std::vector<FrameData> s2 = stack2();
 
   enum OperationType { kAlloc, kFree, kDump };
 
@@ -266,22 +197,21 @@
     OperationType type;
     uint64_t address;
     uint64_t bytes;                       // 0 for free
-    const std::vector<unwindstack::FrameData>* stack;  // nullptr for free
-    const std::vector<std::string>* build_ids;         // nullptr for free
+    const std::vector<FrameData>* stack;  // nullptr for free
 
     // For std::next_permutation.
     bool operator<(const Operation& other) const {
       return sequence_number < other.sequence_number;
     }
   } operations[] = {
-      {1, kAlloc, 0x1, 5, &s, &s_b},          //
-      {2, kAlloc, 0x1, 10, &s2, &s2_b},       //
-      {3, kFree, 0x01, 0, nullptr, nullptr},  //
-      {4, kFree, 0x02, 0, nullptr, nullptr},  //
-      {5, kFree, 0x03, 0, nullptr, nullptr},  //
-      {6, kAlloc, 0x3, 2, &s, &s_b},          //
-      {7, kAlloc, 0x4, 3, &s2, &s2_b},        //
-      {0, kDump, 0x00, 0, nullptr, nullptr},  //
+      {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},  //
   };
 
   uint64_t s_size = 2;
@@ -298,17 +228,16 @@
         hd.RecordFree(operation.address, operation.sequence_number,
                       100 * operation.sequence_number);
       } else if (operation.type == OperationType::kAlloc) {
-        hd.RecordMalloc(*operation.stack, DummyBuildIds(stack().size()),
-                        operation.address, operation.bytes, operation.bytes,
-                        operation.sequence_number,
+        hd.RecordMalloc(*operation.stack, operation.address, operation.bytes,
+                        operation.bytes, operation.sequence_number,
                         100 * operation.sequence_number);
       } else {
         hd.GetCallstackAllocations(
             [](const HeapTracker::CallstackAllocations&) {});
       }
     }
-    ASSERT_EQ(hd.GetSizeForTesting(s, s_b), s_size);
-    ASSERT_EQ(hd.GetSizeForTesting(s2, s2_b), s2_size);
+    ASSERT_EQ(hd.GetSizeForTesting(s), s_size);
+    ASSERT_EQ(hd.GetSizeForTesting(s2), s2_size);
   } while (std::next_permutation(std::begin(operations), std::end(operations)));
 }
 
diff --git a/src/profiling/memory/client.cc b/src/profiling/memory/client.cc
index 4a84a20..d7ea370 100644
--- a/src/profiling/memory/client.cc
+++ b/src/profiling/memory/client.cc
@@ -17,12 +17,10 @@
 #include "src/profiling/memory/client.h"
 
 #include <inttypes.h>
-#include <signal.h>
 #include <sys/prctl.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
-
 #include <unwindstack/MachineArm.h>
 #include <unwindstack/MachineArm64.h>
 #include <unwindstack/MachineMips.h>
@@ -36,17 +34,14 @@
 #include <atomic>
 #include <new>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/thread_utils.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/utils.h"
 #include "src/profiling/memory/sampler.h"
 #include "src/profiling/memory/scoped_spinlock.h"
-#include "src/profiling/memory/shared_ring_buffer.h"
 #include "src/profiling/memory/wire_protocol.h"
 
 namespace perfetto {
@@ -54,21 +49,43 @@
 namespace {
 
 const char kSingleByte[1] = {'x'};
+constexpr std::chrono::seconds kLockTimeout{1};
 constexpr auto kResendBackoffUs = 100;
 
 inline bool IsMainThread() {
   return getpid() == base::GetThreadId();
 }
 
+// The implementation of pthread_getattr_np for the main thread uses malloc,
+// so we cannot use it in GetStackBase, which we use inside of RecordMalloc
+// (which is called from malloc). We would re-enter malloc if we used it.
+//
+// This is why we find the stack base for the main-thread when constructing
+// the client and remember it.
+char* FindMainThreadStack() {
+  base::ScopedFstream maps(fopen("/proc/self/maps", "r"));
+  if (!maps) {
+    return nullptr;
+  }
+  while (!feof(*maps)) {
+    char line[1024];
+    char* data = fgets(line, sizeof(line), *maps);
+    if (data != nullptr && strstr(data, "[stack]")) {
+      char* sep = strstr(data, "-");
+      if (sep == nullptr)
+        continue;
+      sep++;
+      return reinterpret_cast<char*>(strtoll(sep, nullptr, 16));
+    }
+  }
+  return nullptr;
+}
+
 int UnsetDumpable(int) {
   prctl(PR_SET_DUMPABLE, 0);
   return 0;
 }
 
-bool Contained(const StackRange& base, const char* ptr) {
-  return (ptr >= base.begin && ptr < base.end);
-}
-
 }  // namespace
 
 uint64_t GetMaxTries(const ClientConfiguration& client_config) {
@@ -80,10 +97,10 @@
       1ul, client_config.block_client_timeout_us / kResendBackoffUs);
 }
 
-StackRange GetThreadStackRange() {
+const char* GetThreadStackBase() {
   pthread_attr_t attr;
   if (pthread_getattr_np(pthread_self(), &attr) != 0)
-    return {nullptr, nullptr};
+    return nullptr;
   base::ScopedResource<pthread_attr_t*, pthread_attr_destroy, nullptr> cleanup(
       &attr);
 
@@ -91,51 +108,8 @@
   size_t stacksize;
   if (pthread_attr_getstack(&attr, reinterpret_cast<void**>(&stackaddr),
                             &stacksize) != 0)
-    return {nullptr, nullptr};
-  return {stackaddr, stackaddr + stacksize};
-}
-
-StackRange GetSigAltStackRange() {
-  stack_t altstack;
-
-  if (sigaltstack(nullptr, &altstack) == -1) {
-    PERFETTO_PLOG("sigaltstack");
-    return {nullptr, nullptr};
-  }
-
-  if ((altstack.ss_flags & SS_ONSTACK) == 0) {
-    return {nullptr, nullptr};
-  }
-
-  return {static_cast<char*>(altstack.ss_sp),
-          static_cast<char*>(altstack.ss_sp) + altstack.ss_size};
-}
-
-// The implementation of pthread_getattr_np for the main thread uses malloc,
-// so we cannot use it in GetStackEnd, which we use inside of RecordMalloc
-// (which is called from malloc). We would re-enter malloc if we used it.
-//
-// This is why we find the stack base for the main-thread when constructing
-// the client and remember it.
-StackRange GetMainThreadStackRange() {
-  base::ScopedFstream maps(fopen("/proc/self/maps", "re"));
-  if (!maps) {
-    return {nullptr, nullptr};
-  }
-  while (!feof(*maps)) {
-    char line[1024];
-    char* data = fgets(line, sizeof(line), *maps);
-    if (data != nullptr && strstr(data, "[stack]")) {
-      char* sep = strstr(data, "-");
-      if (sep == nullptr)
-        continue;
-
-      char* min = reinterpret_cast<char*>(strtoll(data, nullptr, 16));
-      char* max = reinterpret_cast<char*>(strtoll(sep + 1, nullptr, 16));
-      return {min, max};
-    }
-  }
-  return {nullptr, nullptr};
+    return nullptr;
+  return stackaddr + stacksize;
 }
 
 // static
@@ -167,7 +141,7 @@
     return nullptr;
   }
 
-  sock.DcheckIsBlocking(true);
+  PERFETTO_DCHECK(sock.IsBlocking());
 
   // We might be running in a process that is not dumpable (such as app
   // processes on user builds), in which case the /proc/self/mem will be chown'd
@@ -183,6 +157,8 @@
     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");
@@ -194,16 +170,23 @@
     return nullptr;
   }
 
+  base::ScopedFile page_idle(base::OpenFile("/proc/self/page_idle", O_RDWR));
+  if (!page_idle) {
+    PERFETTO_DLOG("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, kHandshakeSize) !=
+  if (sock.Send(kSingleByte, sizeof(kSingleByte), fds, num_send_fds) !=
       sizeof(kSingleByte)) {
     PERFETTO_DFATAL_OR_ELOG("Failed to send file descriptors.");
     return nullptr;
@@ -243,22 +226,27 @@
     return nullptr;
   }
 
+  PERFETTO_DCHECK(client_config.interval >= 1);
   sock.SetBlocking(false);
+  Sampler sampler{client_config.interval};
   // note: the shared_ptr will retain a copy of the unhooked_allocator
   return std::allocate_shared<Client>(unhooked_allocator, std::move(sock),
                                       client_config, std::move(shmem.value()),
-                                      getpid(), GetMainThreadStackRange());
+                                      std::move(sampler), getpid(),
+                                      FindMainThreadStack());
 }
 
 Client::Client(base::UnixSocketRaw sock,
                ClientConfiguration client_config,
                SharedRingBuffer shmem,
+               Sampler sampler,
                pid_t pid_at_creation,
-               StackRange main_thread_stack_range)
+               const char* main_thread_stack_base)
     : client_config_(client_config),
       max_shmem_tries_(GetMaxTries(client_config_)),
+      sampler_(std::move(sampler)),
       sock_(std::move(sock)),
-      main_thread_stack_range_(main_thread_stack_range),
+      main_thread_stack_base_(main_thread_stack_base),
       shmem_(std::move(shmem)),
       pid_at_creation_(pid_at_creation) {}
 
@@ -276,29 +264,15 @@
     close(fd);
 }
 
-const char* Client::GetStackEnd(const char* stackptr) {
-  StackRange thread_stack_range;
-  bool is_main_thread = IsMainThread();
-  if (is_main_thread) {
-    thread_stack_range = main_thread_stack_range_;
-  } else {
-    thread_stack_range = GetThreadStackRange();
+const char* Client::GetStackBase() {
+  if (IsMainThread()) {
+    if (!main_thread_stack_base_)
+      // Because pthread_attr_getstack reads and parses /proc/self/maps and
+      // /proc/self/stat, we have to cache the result here.
+      main_thread_stack_base_ = GetThreadStackBase();
+    return main_thread_stack_base_;
   }
-  if (Contained(thread_stack_range, stackptr)) {
-    return thread_stack_range.end;
-  }
-  StackRange sigalt_stack_range = GetSigAltStackRange();
-  if (Contained(sigalt_stack_range, stackptr)) {
-    return sigalt_stack_range.end;
-  }
-  // The main thread might have expanded since we read its bounds. We now know
-  // it is not the sigaltstack, so it has to be the main stack.
-  // TODO(fmayer): We should reparse maps here, because now we will keep
-  //               hitting the slow-path that calls the sigaltstack syscall.
-  if (is_main_thread && stackptr < thread_stack_range.end) {
-    return thread_stack_range.end;
-  }
-  return nullptr;
+  return GetThreadStackBase();
 }
 
 // Best-effort detection of whether we're continuing work in a forked child of
@@ -350,15 +324,14 @@
 //
 //               +------------+
 //               |SendWireMsg |
-// stackptr +--> +------------+ 0x1000
+// stacktop +--> +------------+ 0x1000
 //               |RecordMalloc|    +
 //               +------------+    |
 //               | malloc     |    |
 //               +------------+    |
 //               |  main      |    v
-// stackend  +-> +------------+ 0xffff
-bool Client::RecordMalloc(uint32_t heap_id,
-                          uint64_t sample_size,
+// stackbase +-> +------------+ 0xffff
+bool Client::RecordMalloc(uint64_t sample_size,
                           uint64_t alloc_size,
                           uint64_t alloc_address) {
   if (PERFETTO_UNLIKELY(IsPostFork())) {
@@ -366,23 +339,24 @@
   }
 
   AllocMetadata metadata;
-  const char* stackptr = reinterpret_cast<char*>(__builtin_frame_address(0));
+  const char* stackbase = GetStackBase();
+  const char* stacktop = reinterpret_cast<char*>(__builtin_frame_address(0));
   unwindstack::AsmGetRegs(metadata.register_data);
-  const char* stackend = GetStackEnd(stackptr);
-  if (!stackend) {
-    PERFETTO_ELOG("Failed to find stackend.");
-    shmem_.SetErrorState(SharedRingBuffer::kInvalidStackBounds);
+
+  if (PERFETTO_UNLIKELY(stackbase < stacktop)) {
+    PERFETTO_DFATAL_OR_ELOG("Stackbase >= stacktop.");
     return false;
   }
-  uint64_t stack_size = static_cast<uint64_t>(stackend - stackptr);
+
+  uint64_t stack_size = static_cast<uint64_t>(stackbase - stacktop);
   metadata.sample_size = sample_size;
   metadata.alloc_size = alloc_size;
   metadata.alloc_address = alloc_address;
-  metadata.stack_pointer = reinterpret_cast<uint64_t>(stackptr);
+  metadata.stack_pointer = reinterpret_cast<uint64_t>(stacktop);
+  metadata.stack_pointer_offset = sizeof(AllocMetadata);
   metadata.arch = unwindstack::Regs::CurrentArch();
   metadata.sequence_number =
-      1 + sequence_number_[heap_id].fetch_add(1, std::memory_order_acq_rel);
-  metadata.heap_id = heap_id;
+      1 + sequence_number_.fetch_add(1, std::memory_order_acq_rel);
 
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
@@ -395,25 +369,20 @@
   WireMessage msg{};
   msg.record_type = RecordType::Malloc;
   msg.alloc_header = &metadata;
-  msg.payload = const_cast<char*>(stackptr);
+  msg.payload = const_cast<char*>(stacktop);
   msg.payload_size = static_cast<size_t>(stack_size);
 
-  if (SendWireMessageWithRetriesIfBlocking(msg) == -1)
+  if (!SendWireMessageWithRetriesIfBlocking(msg))
     return false;
 
-  if (!shmem_.GetAndResetReaderPaused())
-    return true;
   return SendControlSocketByte();
 }
 
-int64_t Client::SendWireMessageWithRetriesIfBlocking(const WireMessage& msg) {
+bool Client::SendWireMessageWithRetriesIfBlocking(const WireMessage& msg) {
   for (uint64_t i = 0;
        max_shmem_tries_ == kInfiniteTries || i < max_shmem_tries_; ++i) {
-    if (shmem_.shutting_down())
-      return -1;
-    int64_t res = SendWireMessage(&shmem_, msg);
-    if (PERFETTO_LIKELY(res >= 0))
-      return res;
+    if (PERFETTO_LIKELY(SendWireMessage(&shmem_, msg)))
+      return true;
     // retry if in blocking mode and still connected
     if (client_config_.block_client && base::IsAgain(errno) && IsConnected()) {
       usleep(kResendBackoffUs);
@@ -421,60 +390,53 @@
       break;
     }
   }
-  if (IsConnected())
-    shmem_.SetErrorState(SharedRingBuffer::kHitTimeout);
   PERFETTO_PLOG("Failed to write to shared ring buffer. Disconnecting.");
-  return -1;
+  return false;
 }
 
-bool Client::RecordFree(uint32_t heap_id, const uint64_t alloc_address) {
+bool Client::RecordFree(const uint64_t alloc_address) {
   if (PERFETTO_UNLIKELY(IsPostFork())) {
     return postfork_return_value_;
   }
 
-  FreeEntry current_entry;
-  current_entry.sequence_number =
-      1 + sequence_number_[heap_id].fetch_add(1, std::memory_order_acq_rel);
-  current_entry.addr = alloc_address;
-  current_entry.heap_id = heap_id;
-  WireMessage msg = {};
-  msg.record_type = RecordType::Free;
-  msg.free_header = &current_entry;
-  // Do not send control socket byte, as frees are very cheap to handle, so we
-  // just delay to the next alloc. Sending the control socket byte is ~10x the
-  // rest of the client overhead.
-  int64_t bytes_free = SendWireMessageWithRetriesIfBlocking(msg);
-  if (bytes_free == -1)
+  uint64_t sequence_number =
+      1 + sequence_number_.fetch_add(1, std::memory_order_acq_rel);
+
+  std::unique_lock<std::timed_mutex> l(free_batch_lock_, kLockTimeout);
+  if (!l.owns_lock())
     return false;
-  // Seems like we are filling up the shmem with frees. Flush.
-  if (static_cast<uint64_t>(bytes_free) < shmem_.size() / 2 &&
-      shmem_.GetAndResetReaderPaused()) {
-    return SendControlSocketByte();
+  if (free_batch_.num_entries == kFreeBatchSize) {
+    if (!FlushFreesLocked())
+      return false;
+    // Flushed the contents of the buffer, reset it for reuse.
+    free_batch_.num_entries = 0;
   }
+  FreeBatchEntry& current_entry =
+      free_batch_.entries[free_batch_.num_entries++];
+  current_entry.sequence_number = sequence_number;
+  current_entry.addr = alloc_address;
   return true;
 }
 
-bool Client::RecordHeapInfo(uint32_t heap_id,
-                            const char* heap_name,
-                            uint64_t interval) {
-  if (PERFETTO_UNLIKELY(IsPostFork())) {
-    return postfork_return_value_;
+bool Client::FlushFreesLocked() {
+  WireMessage msg = {};
+  msg.record_type = RecordType::Free;
+  msg.free_header = &free_batch_;
+  struct timespec ts;
+  if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
+    free_batch_.clock_monotonic_coarse_timestamp =
+        static_cast<uint64_t>(base::FromPosixTimespec(ts).count());
+  } else {
+    free_batch_.clock_monotonic_coarse_timestamp = 0;
   }
 
-  HeapName hnr;
-  hnr.heap_id = heap_id;
-  strncpy(&hnr.heap_name[0], heap_name, sizeof(hnr.heap_name));
-  hnr.heap_name[sizeof(hnr.heap_name) - 1] = '\0';
-  hnr.sample_interval = interval;
-
-  WireMessage msg = {};
-  msg.record_type = RecordType::HeapName;
-  msg.heap_name_header = &hnr;
-  return SendWireMessageWithRetriesIfBlocking(msg);
+  if (!SendWireMessageWithRetriesIfBlocking(msg))
+    return false;
+  return SendControlSocketByte();
 }
 
 bool Client::IsConnected() {
-  sock_.DcheckIsBlocking(false);
+  PERFETTO_DCHECK(!sock_.IsBlocking());
   char buf[1];
   ssize_t recv_bytes = sock_.Receive(buf, sizeof(buf), nullptr, 0);
   if (recv_bytes == 0)
@@ -493,11 +455,7 @@
   // is how the service signals the tracing session was torn down.
   if (sock_.Send(kSingleByte, sizeof(kSingleByte)) == -1 &&
       !base::IsAgain(errno)) {
-    if (shmem_.shutting_down()) {
-      PERFETTO_LOG("Profiling session ended.");
-    } else {
-      PERFETTO_PLOG("Failed to send control socket byte.");
-    }
+    PERFETTO_PLOG("Failed to send control socket byte.");
     return false;
   }
   return true;
diff --git a/src/profiling/memory/client.h b/src/profiling/memory/client.h
index 498cf9d..0ef00be 100644
--- a/src/profiling/memory/client.h
+++ b/src/profiling/memory/client.h
@@ -35,21 +35,12 @@
 namespace perfetto {
 namespace profiling {
 
-struct StackRange {
-  const char* begin;
-  // One past the highest address part of the stack.
-  const char* end;
-};
-
-StackRange GetThreadStackRange();
-StackRange GetSigAltStackRange();
-StackRange GetMainThreadStackRange();
+uint64_t GetMaxTries(const ClientConfiguration& client_config);
+const char* GetThreadStackBase();
 
 constexpr uint64_t kInfiniteTries = 0;
 constexpr uint32_t kClientSockTimeoutMs = 1000;
 
-uint64_t GetMaxTries(const ClientConfiguration& client_config);
-
 // Profiling client, used to sample and record the malloc/free family of calls,
 // and communicate the necessary state to a separate profiling daemon process.
 //
@@ -77,20 +68,21 @@
   static base::Optional<base::UnixSocketRaw> ConnectToHeapprofd(
       const std::string& sock_name);
 
-  bool RecordMalloc(uint32_t heap_id,
-                    uint64_t sample_size,
+  bool RecordMalloc(uint64_t sample_size,
                     uint64_t alloc_size,
                     uint64_t alloc_address) PERFETTO_WARN_UNUSED_RESULT;
 
   // Add address to buffer of deallocations. Flushes the buffer if necessary.
-  bool RecordFree(uint32_t heap_id,
-                  uint64_t alloc_address) PERFETTO_WARN_UNUSED_RESULT;
-  bool RecordHeapInfo(uint32_t heap_id,
-                      const char* heap_name,
-                      uint64_t interval);
+  bool RecordFree(uint64_t alloc_address) PERFETTO_WARN_UNUSED_RESULT;
 
-  void AddClientSpinlockBlockedUs(size_t n) {
-    shmem_.AddClientSpinlockBlockedUs(n);
+  // Returns the number of bytes to assign to an allocation with the given
+  // |alloc_size|, based on the current sampling rate. A return value of zero
+  // means that the allocation should not be recorded. Not idempotent, each
+  // invocation mutates the sampler state.
+  //
+  // Not thread-safe.
+  size_t GetSampleSizeLocked(size_t alloc_size) {
+    return sampler_.SampleSize(alloc_size);
   }
 
   // Public for std::allocate_shared. Use CreateAndHandshake() to create
@@ -98,38 +90,40 @@
   Client(base::UnixSocketRaw sock,
          ClientConfiguration client_config,
          SharedRingBuffer shmem,
+         Sampler sampler,
          pid_t pid_at_creation,
-         StackRange main_thread_stack_range);
+         const char* main_thread_stack_base);
 
   ~Client();
 
-  const ClientConfiguration& client_config() { return client_config_; }
-  uint64_t adaptive_sampling_shmem_threshold() {
-    return client_config_.adaptive_sampling_shmem_threshold;
-  }
-  uint64_t adaptive_sampling_max_sampling_interval_bytes() {
-    return client_config_.adaptive_sampling_max_sampling_interval_bytes;
-  }
-  uint64_t write_avail() { return shmem_.write_avail(); }
-
-  bool IsConnected();
+  ClientConfiguration client_config_for_testing() { return client_config_; }
 
  private:
-  const char* GetStackEnd(const char* stacktop);
+  const char* GetStackBase();
+  // Flush the contents of free_batch_. Must hold free_batch_lock_.
+  bool FlushFreesLocked() PERFETTO_WARN_UNUSED_RESULT;
   bool SendControlSocketByte() PERFETTO_WARN_UNUSED_RESULT;
-  int64_t SendWireMessageWithRetriesIfBlocking(const WireMessage&)
+  bool SendWireMessageWithRetriesIfBlocking(const WireMessage&)
       PERFETTO_WARN_UNUSED_RESULT;
 
   bool IsPostFork();
 
+  // This is only valid for non-blocking sockets. This is when
+  // client_config_.block_client is true.
+  bool IsConnected();
 
   ClientConfiguration client_config_;
   uint64_t max_shmem_tries_;
+  // sampler_ operations are not thread-safe.
+  Sampler sampler_;
   base::UnixSocketRaw sock_;
 
-  StackRange main_thread_stack_range_{nullptr, nullptr};
-  std::atomic<uint64_t>
-      sequence_number_[base::ArraySize(ClientConfiguration{}.heaps)] = {};
+  // Protected by free_batch_lock_.
+  FreeBatch free_batch_;
+  std::timed_mutex free_batch_lock_;
+
+  const char* main_thread_stack_base_{nullptr};
+  std::atomic<uint64_t> sequence_number_{0};
   SharedRingBuffer shmem_;
 
   // Used to detect (during the slow path) the situation where the process has
diff --git a/src/profiling/memory/client_api.cc b/src/profiling/memory/client_api.cc
deleted file mode 100644
index bdede0d..0000000
--- a/src/profiling/memory/client_api.cc
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-
-#include <inttypes.h>
-#include <malloc.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <memory>
-#include <tuple>
-#include <type_traits>
-
-#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 "src/profiling/common/proc_utils.h"
-#include "src/profiling/memory/client.h"
-#include "src/profiling/memory/client_api_factory.h"
-#include "src/profiling/memory/scoped_spinlock.h"
-#include "src/profiling/memory/unhooked_allocator.h"
-#include "src/profiling/memory/wire_protocol.h"
-
-struct AHeapInfo {
-  // Fields set by user.
-  char heap_name[HEAPPROFD_HEAP_NAME_SZ];
-  void (*enabled_callback)(void*, const AHeapProfileEnableCallbackInfo*);
-  void (*disabled_callback)(void*, const AHeapProfileDisableCallbackInfo*);
-  void* enabled_callback_data;
-  void* disabled_callback_data;
-
-  // Internal fields.
-  perfetto::profiling::Sampler sampler;
-  std::atomic<bool> ready;
-  std::atomic<bool> enabled;
-  std::atomic<uint64_t> adaptive_sampling_shmem_threshold;
-  std::atomic<uint64_t> adaptive_sampling_max_sampling_interval_bytes;
-};
-
-struct AHeapProfileEnableCallbackInfo {
-  uint64_t sampling_interval;
-};
-
-struct AHeapProfileDisableCallbackInfo {};
-
-namespace {
-
-using perfetto::profiling::ScopedSpinlock;
-using perfetto::profiling::UnhookedAllocator;
-
-#if defined(__GLIBC__)
-const char* getprogname() {
-  return program_invocation_short_name;
-}
-#elif !defined(__BIONIC__)
-const char* getprogname() {
-  return "";
-}
-#endif
-
-// Holds the active profiling client. Is empty at the start, or after we've
-// started shutting down a profiling session. Hook invocations take shared_ptr
-// copies (ensuring that the client stays alive until no longer needed), and do
-// nothing if this primary pointer is empty.
-//
-// This shared_ptr itself is protected by g_client_lock. Note that shared_ptr
-// handles are not thread-safe by themselves:
-// https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
-//
-// To avoid on-destruction re-entrancy issues, this shared_ptr needs to be
-// constructed with an allocator that uses the unhooked malloc & free functions.
-// See UnhookedAllocator.
-//
-// We initialize this storage the first time GetClientLocked is called. We
-// cannot use a static initializer because that leads to ordering problems
-// of the ELF's constructors.
-
-alignas(std::shared_ptr<perfetto::profiling::Client>) char g_client_arr[sizeof(
-    std::shared_ptr<perfetto::profiling::Client>)];
-
-bool g_client_init;
-
-std::shared_ptr<perfetto::profiling::Client>* GetClientLocked() {
-  if (!g_client_init) {
-    new (g_client_arr) std::shared_ptr<perfetto::profiling::Client>;
-    g_client_init = true;
-  }
-  return reinterpret_cast<std::shared_ptr<perfetto::profiling::Client>*>(
-      &g_client_arr);
-}
-
-constexpr auto kMinHeapId = 1;
-
-AHeapInfo g_heaps[256];
-
-AHeapInfo& GetHeap(uint32_t id) {
-  return g_heaps[id];
-}
-
-// Protects g_client, and serves as an external lock for sampling decisions (see
-// perfetto::profiling::Sampler).
-//
-// We rely on this atomic's destuction being a nop, as it is possible for the
-// hooks to attempt to acquire the spinlock after its destructor should have run
-// (technically a use-after-destruct scenario).
-static_assert(
-    std::is_trivially_destructible<perfetto::profiling::Spinlock>::value,
-    "lock must be trivially destructible.");
-perfetto::profiling::Spinlock g_client_lock{};
-
-std::atomic<uint32_t> g_next_heap_id{kMinHeapId};
-
-void DisableAllHeaps() {
-  for (uint32_t i = kMinHeapId; i < g_next_heap_id.load(); ++i) {
-    AHeapInfo& info = GetHeap(i);
-    if (!info.ready.load(std::memory_order_acquire))
-      continue;
-    if (info.enabled.load(std::memory_order_acquire)) {
-      info.enabled.store(false, std::memory_order_release);
-      if (info.disabled_callback) {
-        AHeapProfileDisableCallbackInfo disable_info;
-        info.disabled_callback(info.disabled_callback_data, &disable_info);
-      }
-    }
-  }
-}
-
-void OnSpinlockTimeout() {
-  // Give up on profiling the process but leave it running.
-  // The process enters into a poisoned state and will reject all
-  // subsequent profiling requests.  The current session is kept
-  // running but no samples are reported to it.
-  PERFETTO_ELOG(
-      "Timed out on the spinlock - something is horribly wrong. "
-      "Leaking heapprofd client.");
-  DisableAllHeaps();
-  perfetto::profiling::PoisonSpinlock(&g_client_lock);
-}
-
-// Note: g_client can be reset by AHeapProfile_initSession without calling this
-// function.
-void ShutdownLazy(const std::shared_ptr<perfetto::profiling::Client>& client) {
-  ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-  if (PERFETTO_UNLIKELY(!s.locked())) {
-    OnSpinlockTimeout();
-    return;
-  }
-
-  // other invocation already initiated shutdown
-  if (*GetClientLocked() != client)
-    return;
-
-  DisableAllHeaps();
-  // Clear primary shared pointer, such that later hook invocations become nops.
-  GetClientLocked()->reset();
-}
-
-uint64_t MaybeToggleHeap(uint32_t heap_id,
-                         perfetto::profiling::Client* client) {
-  AHeapInfo& heap = GetHeap(heap_id);
-  if (!heap.ready.load(std::memory_order_acquire))
-    return 0;
-  auto interval =
-      GetHeapSamplingInterval(client->client_config(), heap.heap_name);
-  // The callbacks must be called while NOT LOCKED. Because they run
-  // arbitrary code, it would be very easy to build a deadlock.
-  if (interval) {
-    AHeapProfileEnableCallbackInfo session_info{interval};
-    if (!heap.enabled.load(std::memory_order_acquire) &&
-        heap.enabled_callback) {
-      heap.enabled_callback(heap.enabled_callback_data, &session_info);
-    }
-    heap.adaptive_sampling_shmem_threshold.store(
-        client->client_config().adaptive_sampling_shmem_threshold,
-        std::memory_order_relaxed);
-    heap.adaptive_sampling_max_sampling_interval_bytes.store(
-        client->client_config().adaptive_sampling_max_sampling_interval_bytes,
-        std::memory_order_relaxed);
-    heap.enabled.store(true, std::memory_order_release);
-    client->RecordHeapInfo(heap_id, &heap.heap_name[0], interval);
-  } else if (heap.enabled.load(std::memory_order_acquire)) {
-    heap.enabled.store(false, std::memory_order_release);
-    if (heap.disabled_callback) {
-      AHeapProfileDisableCallbackInfo info;
-      heap.disabled_callback(heap.disabled_callback_data, &info);
-    }
-  }
-  return interval;
-}
-
-// We're a library loaded into a potentially-multithreaded process, which might
-// not be explicitly aware of this possiblity. Deadling with forks/clones is
-// extremely complicated in such situations, but we attempt to handle certain
-// cases.
-//
-// There are two classes of forking processes to consider:
-//  * well-behaved processes that fork only when their threads (if any) are at a
-//    safe point, and therefore not in the middle of our hooks/client.
-//  * processes that fork with other threads in an arbitrary state. Though
-//    technically buggy, such processes exist in practice.
-//
-// This atfork handler follows a crude lowest-common-denominator approach, where
-// to handle the latter class of processes, we systematically leak any |Client|
-// state (present only when actively profiling at the time of fork) in the
-// postfork-child path.
-//
-// The alternative with acquiring all relevant locks in the prefork handler, and
-// releasing the state postfork handlers, poses a separate class of edge cases,
-// and is not deemed to be better as a result.
-//
-// Notes:
-// * this atfork handler fires only for the |fork| libc entrypoint, *not*
-//   |clone|. See client.cc's |IsPostFork| for some best-effort detection
-//   mechanisms for clone/vfork.
-// * it should be possible to start a new profiling session in this child
-//   process, modulo the bionic's heapprofd-loading state machine being in the
-//   right state.
-// * we cannot avoid leaks in all cases anyway (e.g. during shutdown sequence,
-//   when only individual straggler threads hold onto the Client).
-void AtForkChild() {
-  PERFETTO_LOG("heapprofd_client: handling atfork.");
-
-  // A thread (that has now disappeared across the fork) could have been holding
-  // the spinlock. We're now the only thread post-fork, so we can reset the
-  // spinlock, though the state it protects (the |g_client| shared_ptr) might
-  // not be in a consistent state.
-  g_client_lock.locked.store(false);
-  g_client_lock.poisoned.store(false);
-
-  // We must not call the disabled callbacks here, because they might require
-  // locks that are being held at the fork point.
-  for (uint32_t i = kMinHeapId; i < g_next_heap_id.load(); ++i) {
-    AHeapInfo& info = GetHeap(i);
-    info.enabled.store(false);
-  }
-  // Leak the existing shared_ptr contents, including the profiling |Client| if
-  // profiling was active at the time of the fork.
-  // Note: this code assumes that the creation of the empty shared_ptr does not
-  // allocate, which should be the case for all implementations as the
-  // constructor has to be noexcept.
-  new (g_client_arr) std::shared_ptr<perfetto::profiling::Client>();
-}
-
-}  // namespace
-
-__attribute__((visibility("default"))) uint64_t
-AHeapProfileEnableCallbackInfo_getSamplingInterval(
-    const AHeapProfileEnableCallbackInfo* session_info) {
-  return session_info->sampling_interval;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_create(
-    const char* heap_name) {
-  size_t len = strlen(heap_name);
-  if (len >= sizeof(AHeapInfo::heap_name)) {
-    return nullptr;
-  }
-
-  uint32_t next_id = g_next_heap_id.fetch_add(1);
-  if (next_id >= perfetto::base::ArraySize(g_heaps)) {
-    return nullptr;
-  }
-
-  if (next_id == kMinHeapId)
-    perfetto::profiling::StartHeapprofdIfStatic();
-
-  AHeapInfo& info = GetHeap(next_id);
-  strncpy(info.heap_name, heap_name, sizeof(info.heap_name));
-  return &info;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setEnabledCallback(
-    AHeapInfo* info,
-    void (*callback)(void*, const AHeapProfileEnableCallbackInfo*),
-    void* data) {
-  if (info == nullptr)
-    return nullptr;
-  if (info->ready.load(std::memory_order_relaxed)) {
-    PERFETTO_ELOG(
-        "AHeapInfo_setEnabledCallback called after heap was registered. "
-        "This is always a bug.");
-    return nullptr;
-  }
-  info->enabled_callback = callback;
-  info->enabled_callback_data = data;
-  return info;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setDisabledCallback(
-    AHeapInfo* info,
-    void (*callback)(void*, const AHeapProfileDisableCallbackInfo*),
-    void* data) {
-  if (info == nullptr)
-    return nullptr;
-  if (info->ready.load(std::memory_order_relaxed)) {
-    PERFETTO_ELOG(
-        "AHeapInfo_setDisabledCallback called after heap was registered. "
-        "This is always a bug.");
-    return nullptr;
-  }
-  info->disabled_callback = callback;
-  info->disabled_callback_data = data;
-  return info;
-}
-
-__attribute__((visibility("default"))) uint32_t AHeapProfile_registerHeap(
-    AHeapInfo* info) {
-  if (info == nullptr)
-    return 0;
-  info->ready.store(true, std::memory_order_release);
-  auto heap_id = static_cast<uint32_t>(info - &g_heaps[0]);
-  std::shared_ptr<perfetto::profiling::Client> client;
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return 0;
-    }
-
-    client = *GetClientLocked();
-  }
-
-  // Enable the heap immediately if there's a matching ongoing session.
-  if (client) {
-    uint64_t interval = MaybeToggleHeap(heap_id, client.get());
-    if (interval) {
-      ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-      if (PERFETTO_UNLIKELY(!s.locked())) {
-        OnSpinlockTimeout();
-        return 0;
-      }
-      info->sampler.SetSamplingInterval(interval);
-    }
-  }
-  return heap_id;
-}
-
-__attribute__((visibility("default"))) bool
-AHeapProfile_reportAllocation(uint32_t heap_id, uint64_t id, uint64_t size) {
-  AHeapInfo& heap = GetHeap(heap_id);
-  if (!heap.enabled.load(std::memory_order_acquire)) {
-    return false;
-  }
-  size_t sampled_alloc_sz = 0;
-  std::shared_ptr<perfetto::profiling::Client> client;
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return false;
-    }
-
-    auto* g_client_ptr = GetClientLocked();
-    if (!*g_client_ptr)  // no active client (most likely shutting down)
-      return false;
-    auto& client_ptr = *g_client_ptr;
-
-    if (s.blocked_us()) {
-      client_ptr->AddClientSpinlockBlockedUs(s.blocked_us());
-    }
-
-    sampled_alloc_sz = heap.sampler.SampleSize(static_cast<size_t>(size));
-    if (sampled_alloc_sz == 0)  // not sampling
-      return false;
-    if (client_ptr->write_avail() <
-        client_ptr->adaptive_sampling_shmem_threshold()) {
-      bool should_increment = true;
-      if (client_ptr->adaptive_sampling_max_sampling_interval_bytes() != 0) {
-        should_increment =
-            heap.sampler.sampling_interval() <
-            client_ptr->adaptive_sampling_max_sampling_interval_bytes();
-      }
-      if (should_increment) {
-        uint64_t new_interval = 2 * heap.sampler.sampling_interval();
-        heap.sampler.SetSamplingInterval(2 * heap.sampler.sampling_interval());
-        client_ptr->RecordHeapInfo(heap_id, "", new_interval);
-      }
-    }
-
-    client = client_ptr;  // owning copy
-  }                       // unlock
-
-  if (!client->RecordMalloc(heap_id, sampled_alloc_sz, size, id)) {
-    ShutdownLazy(client);
-    return false;
-  }
-  return true;
-}
-
-__attribute__((visibility("default"))) bool
-AHeapProfile_reportSample(uint32_t heap_id, uint64_t id, uint64_t size) {
-  const AHeapInfo& heap = GetHeap(heap_id);
-  if (!heap.enabled.load(std::memory_order_acquire)) {
-    return false;
-  }
-  std::shared_ptr<perfetto::profiling::Client> client;
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return false;
-    }
-
-    auto* g_client_ptr = GetClientLocked();
-    if (!*g_client_ptr)  // no active client (most likely shutting down)
-      return false;
-
-    if (s.blocked_us()) {
-      (*g_client_ptr)->AddClientSpinlockBlockedUs(s.blocked_us());
-    }
-
-    client = *g_client_ptr;  // owning copy
-  }                          // unlock
-
-  if (!client->RecordMalloc(heap_id, size, size, id)) {
-    ShutdownLazy(client);
-    return false;
-  }
-  return true;
-}
-
-__attribute__((visibility("default"))) void AHeapProfile_reportFree(
-    uint32_t heap_id,
-    uint64_t id) {
-  const AHeapInfo& heap = GetHeap(heap_id);
-  if (!heap.enabled.load(std::memory_order_acquire)) {
-    return;
-  }
-  std::shared_ptr<perfetto::profiling::Client> client;
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return;
-    }
-
-    client = *GetClientLocked();  // owning copy (or empty)
-    if (!client)
-      return;
-
-    if (s.blocked_us()) {
-      client->AddClientSpinlockBlockedUs(s.blocked_us());
-    }
-  }
-
-  if (!client->RecordFree(heap_id, id))
-    ShutdownLazy(client);
-}
-
-__attribute__((visibility("default"))) bool AHeapProfile_initSession(
-    void* (*malloc_fn)(size_t),
-    void (*free_fn)(void*)) {
-  static bool first_init = true;
-  // Install an atfork handler to deal with *some* cases of the host forking.
-  // The handler will be unpatched automatically if we're dlclosed.
-  if (first_init && pthread_atfork(/*prepare=*/nullptr, /*parent=*/nullptr,
-                                   &AtForkChild) != 0) {
-    PERFETTO_PLOG("%s: pthread_atfork failed, not installing hooks.",
-                  getprogname());
-    return false;
-  }
-  first_init = false;
-
-  // TODO(fmayer): Check other destructions of client and make a decision
-  // whether we want to ban heap objects in the client or not.
-  std::shared_ptr<perfetto::profiling::Client> old_client;
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return false;
-    }
-
-    auto* g_client_ptr = GetClientLocked();
-    if (*g_client_ptr && (*g_client_ptr)->IsConnected()) {
-      PERFETTO_LOG("%s: Rejecting concurrent profiling initialization.",
-                   getprogname());
-      return true;  // success as we're in a valid state
-    }
-    old_client = *g_client_ptr;
-    g_client_ptr->reset();
-  }
-
-  old_client.reset();
-
-  // The dispatch table never changes, so let the custom allocator retain the
-  // function pointers directly.
-  UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator(malloc_fn,
-                                                                    free_fn);
-
-  // These factory functions use heap objects, so we need to run them without
-  // the spinlock held.
-  std::shared_ptr<perfetto::profiling::Client> client =
-      perfetto::profiling::ConstructClient(unhooked_allocator);
-
-  if (!client) {
-    PERFETTO_LOG("%s: heapprofd_client not initialized, not installing hooks.",
-                 getprogname());
-    return false;
-  }
-
-  uint64_t heap_intervals[perfetto::base::ArraySize(g_heaps)] = {};
-  uint32_t max_heap = g_next_heap_id.load();
-  for (uint32_t i = kMinHeapId; i < max_heap; ++i) {
-    heap_intervals[i] = MaybeToggleHeap(i, client.get());
-  }
-
-  PERFETTO_LOG("%s: heapprofd_client initialized.", getprogname());
-  {
-    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
-    if (PERFETTO_UNLIKELY(!s.locked())) {
-      OnSpinlockTimeout();
-      return false;
-    }
-
-    // This needs to happen under the lock for mutual exclusion regarding the
-    // random engine.
-    for (uint32_t i = kMinHeapId; i < max_heap; ++i) {
-      AHeapInfo& heap = GetHeap(i);
-      if (heap_intervals[i]) {
-        heap.sampler.SetSamplingInterval(heap_intervals[i]);
-      }
-    }
-
-    // This cannot have been set in the meantime. There are never two concurrent
-    // calls to this function, as Bionic uses atomics to guard against that.
-    PERFETTO_DCHECK(*GetClientLocked() == nullptr);
-    *GetClientLocked() = std::move(client);
-  }
-  return true;
-}
diff --git a/src/profiling/memory/client_api_benchmark.cc b/src/profiling/memory/client_api_benchmark.cc
deleted file mode 100644
index 0f19e98..0000000
--- a/src/profiling/memory/client_api_benchmark.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 "perfetto/heap_profile.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-
-#include "src/profiling/memory/client.h"
-#include "src/profiling/memory/client_api_factory.h"
-
-namespace perfetto {
-namespace profiling {
-
-namespace {
-uint32_t GetHeapId() {
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_create("dev.perfetto.benchmark"));
-  return heap_id;
-}
-
-ClientConfiguration g_client_config;
-int g_shmem_fd;
-
-base::UnixSocketRaw& GlobalServerSocket() {
-  static base::UnixSocketRaw* srv_sock = new base::UnixSocketRaw;
-  return *srv_sock;
-}
-
-void DisconnectGlobalServerSocket() {
-  base::UnixSocketRaw destroy;
-  std::swap(destroy, GlobalServerSocket());
-}
-
-}  // namespace
-
-// This is called by AHeapProfile_initSession (client_api.cc) to construct a
-// client. The Client API requires to be linked against another compliation
-// unit that provides this function. This way, it can be used in different
-// circumstances (central heapprofd, fork heapprofd) and be agnostic about the
-// details. This is is used to create a test Client here.
-void StartHeapprofdIfStatic() {}
-std::shared_ptr<Client> ConstructClient(
-    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
-  base::UnixSocketRaw cli_sock;
-  base::UnixSocketRaw& srv_sock = GlobalServerSocket();
-  std::tie(cli_sock, srv_sock) = base::UnixSocketRaw::CreatePairPosix(
-      base::SockFamily::kUnix, base::SockType::kStream);
-  auto ringbuf = SharedRingBuffer::Create(8 * 1048576);
-  ringbuf->InfiniteBufferForTesting();
-  PERFETTO_CHECK(ringbuf);
-  PERFETTO_CHECK(cli_sock);
-  PERFETTO_CHECK(srv_sock);
-  g_shmem_fd = ringbuf->fd();
-  return std::allocate_shared<Client>(unhooked_allocator, std::move(cli_sock),
-                                      g_client_config, std::move(*ringbuf),
-                                      getpid(), GetMainThreadStackRange());
-}
-
-static void BM_ClientApiOneTenthAllocation(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = true;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportAllocation(heap_id, 0x123, 3200);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiOneTenthAllocation);
-
-static void BM_ClientApiOneHundrethAllocation(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = true;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportAllocation(heap_id, 0x123, 320);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiOneHundrethAllocation);
-
-static void BM_ClientApiAlmostNoAllocation(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 10000000000000000;
-  client_config.all_heaps = true;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportAllocation(heap_id, 0x123, 1);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiAlmostNoAllocation);
-
-static void BM_ClientApiSample(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = true;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportSample(heap_id, 0x123, 20);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiSample);
-
-static void BM_ClientApiDisabledHeapAllocation(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = false;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportAllocation(heap_id, 0x123, 20);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiDisabledHeapAllocation);
-
-static void BM_ClientApiDisabledHeapFree(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = false;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportFree(heap_id, 0x123);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiDisabledHeapFree);
-
-static void BM_ClientApiEnabledHeapFree(benchmark::State& state) {
-  const uint32_t heap_id = GetHeapId();
-
-  ClientConfiguration client_config{};
-  client_config.default_interval = 32000;
-  client_config.all_heaps = true;
-  g_client_config = client_config;
-  PERFETTO_CHECK(AHeapProfile_initSession(malloc, free));
-
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-
-  for (auto _ : state) {
-    AHeapProfile_reportFree(heap_id, 0x123);
-  }
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-}
-
-BENCHMARK(BM_ClientApiEnabledHeapFree);
-
-static void BM_ClientApiMallocFree(benchmark::State& state) {
-  for (auto _ : state) {
-    volatile char* x = static_cast<char*>(malloc(100));
-    if (x) {
-      x[0] = 'x';
-      free(const_cast<char*>(x));
-    }
-  }
-}
-
-BENCHMARK(BM_ClientApiMallocFree);
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/client_api_factory.h b/src/profiling/memory/client_api_factory.h
deleted file mode 100644
index f6b983f..0000000
--- a/src/profiling/memory/client_api_factory.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_MEMORY_CLIENT_API_FACTORY_H_
-#define SRC_PROFILING_MEMORY_CLIENT_API_FACTORY_H_
-
-#include <memory>
-
-#include "src/profiling/memory/unhooked_allocator.h"
-
-namespace perfetto {
-namespace profiling {
-
-class Client;
-
-void StartHeapprofdIfStatic();
-
-std::shared_ptr<Client> ConstructClient(
-    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator);
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_CLIENT_API_FACTORY_H_
diff --git a/src/profiling/memory/client_api_factory_android.cc b/src/profiling/memory/client_api_factory_android.cc
deleted file mode 100644
index 370dd60..0000000
--- a/src/profiling/memory/client_api_factory_android.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/memory/client_api_factory.h"
-
-#include <string>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "src/profiling/common/proc_utils.h"
-#include "src/profiling/memory/client.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#error "Must be built on Android."
-#endif
-
-namespace perfetto {
-namespace profiling {
-
-void StartHeapprofdIfStatic() {}
-
-std::shared_ptr<Client> ConstructClient(
-    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
-  PERFETTO_LOG("Constructing client for central daemon.");
-  using perfetto::profiling::Client;
-
-  perfetto::base::Optional<perfetto::base::UnixSocketRaw> sock =
-      Client::ConnectToHeapprofd(perfetto::profiling::kHeapprofdSocketFile);
-  if (!sock) {
-    PERFETTO_ELOG("Failed to connect to %s. This is benign on user builds.",
-                  perfetto::profiling::kHeapprofdSocketFile);
-    return nullptr;
-  }
-  return Client::CreateAndHandshake(std::move(sock.value()),
-                                    unhooked_allocator);
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/client_api_factory_standalone.cc b/src/profiling/memory/client_api_factory_standalone.cc
deleted file mode 100644
index f21ce0d..0000000
--- a/src/profiling/memory/client_api_factory_standalone.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/memory/client_api_factory.h"
-
-#include "perfetto/ext/base/scoped_file.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/watchdog.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/heap_profile.h"
-#include "src/profiling/common/proc_utils.h"
-#include "src/profiling/memory/client.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-#include "src/profiling/memory/heapprofd_producer.h"
-
-#include <string>
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-// General approach:
-// On loading this library, we fork off a process that runs heapprofd. We
-// share a control socket pair (g_child_sock in client, srv_sock in service)
-// which is used to:
-// * Signal a new profiling session was started by sending a byte to
-//   g_child_sock. This signal gets received in MonitorFd.
-// * For each profiling session, send a new socket from the client to the
-//   service. This happens in CreateClient.
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-base::UnixSocketRaw* g_client_sock;
-
-void MonitorFd() {
-  g_client_sock->DcheckIsBlocking(true);
-  for (;;) {
-    char buf[1];
-    ssize_t r = g_client_sock->Receive(buf, sizeof(buf));
-    if (r >= 1) {
-      AHeapProfile_initSession(malloc, free);
-    } else if (r == 0) {
-      PERFETTO_ELOG("Server disconneced.");
-      break;
-    } else {
-      PERFETTO_PLOG("Receive failed.");
-    }
-  }
-}
-
-}  // namespace
-
-void StartHeapprofdIfStatic() {
-  pid_t pid = getpid();
-  std::string cmdline;
-
-  if (!GetCmdlineForPID(pid, &cmdline)) {
-    PERFETTO_ELOG("Failed to get cmdline.");
-  }
-
-  g_client_sock = new base::UnixSocketRaw();
-  base::UnixSocketRaw srv_sock;
-  base::UnixSocketRaw cli_sock;
-
-  std::tie(cli_sock, srv_sock) = base::UnixSocketRaw::CreatePairPosix(
-      base::SockFamily::kUnix, base::SockType::kStream);
-
-  if (!cli_sock || !srv_sock) {
-    PERFETTO_ELOG("Failed to create socket pair.");
-    return;
-  }
-  pid_t f = fork();
-
-  if (f == -1) {
-    PERFETTO_PLOG("fork");
-    return;
-  }
-
-  if (f != 0) {
-    int wstatus;
-    if (PERFETTO_EINTR(waitpid(f, &wstatus, 0)) == -1)
-      PERFETTO_PLOG("waitpid");
-
-    *g_client_sock = std::move(cli_sock);
-    std::thread th(MonitorFd);
-    th.detach();
-    return;
-  }
-
-  daemon(/* nochdir= */ 0, /* noclose= */ 1);
-
-  cli_sock.ReleaseFd();
-
-  // Leave stderr open for logging.
-  int null = open("/dev/null", O_RDWR);  // NOLINT(android-cloexec-open)
-  dup2(null, STDIN_FILENO);
-  dup2(null, STDOUT_FILENO);
-  if (null > STDERR_FILENO)
-    close(null);
-
-  for (int i = STDERR_FILENO + 1; i < 512; ++i) {
-    if (i != srv_sock.fd())
-      close(i);
-  }
-
-  srv_sock.SetBlocking(false);
-
-  base::UnixTaskRunner task_runner;
-  base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
-  HeapprofdProducer producer(HeapprofdMode::kChild, &task_runner,
-                             /* exit_when_done= */ false);
-  producer.SetTargetProcess(pid, cmdline);
-  producer.ConnectWithRetries(GetProducerSocket());
-  // Signal MonitorFd in the parent process to start a session.
-  producer.SetDataSourceCallback([&srv_sock] { srv_sock.Send("x", 1); });
-  task_runner.AddFileDescriptorWatch(
-      srv_sock.fd(), [&task_runner, &producer, &srv_sock] {
-        base::ScopedFile fd;
-        char buf[1];
-        ssize_t r = srv_sock.Receive(buf, sizeof(buf), &fd, 1);
-        if (r == 0) {
-          PERFETTO_LOG("Child disconnected.");
-          producer.TerminateWhenDone();
-          task_runner.RemoveFileDescriptorWatch(srv_sock.fd());
-        }
-        if (r == -1 && !base::IsAgain(errno)) {
-          PERFETTO_PLOG("Receive");
-        }
-        if (fd) {
-          producer.AdoptSocket(std::move(fd));
-        }
-      });
-  task_runner.Run();
-}
-
-// This is called by AHeapProfile_initSession (client_api.cc) to construct a
-// client.
-std::shared_ptr<Client> ConstructClient(
-    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
-  if (!g_client_sock)
-    return nullptr;
-
-  std::shared_ptr<perfetto::profiling::Client> client;
-  base::UnixSocketRaw srv_session_sock;
-  base::UnixSocketRaw client_session_sock;
-
-  std::tie(srv_session_sock, client_session_sock) =
-      base::UnixSocketRaw::CreatePairPosix(base::SockFamily::kUnix,
-                                           base::SockType::kStream);
-  if (!client_session_sock || !srv_session_sock) {
-    PERFETTO_ELOG("Failed to create socket pair.");
-    return nullptr;
-  }
-  base::ScopedFile srv_fd = srv_session_sock.ReleaseFd();
-  int fd = srv_fd.get();
-  // Send the session socket to the service.
-  g_client_sock->Send(" ", 1, &fd, 1);
-  return perfetto::profiling::Client::CreateAndHandshake(
-      std::move(client_session_sock), unhooked_allocator);
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/client_api_noop.cc b/src/profiling/memory/client_api_noop.cc
deleted file mode 100644
index 0f3732f..0000000
--- a/src/profiling/memory/client_api_noop.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-
-#include <inttypes.h>
-
-__attribute__((visibility("default"))) uint64_t
-AHeapProfileEnableCallbackInfo_getSamplingInterval(
-    const AHeapProfileEnableCallbackInfo*) {
-  return 0;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_create(
-    const char*) {
-  return nullptr;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setEnabledCallback(
-    AHeapInfo*,
-    void (*)(void*, const AHeapProfileEnableCallbackInfo*),
-    void*) {
-  return nullptr;
-}
-
-__attribute__((visibility("default"))) AHeapInfo* AHeapInfo_setDisabledCallback(
-    AHeapInfo*,
-    void (*)(void*, const AHeapProfileDisableCallbackInfo*),
-    void*) {
-  return nullptr;
-}
-
-__attribute__((visibility("default"))) uint32_t AHeapProfile_registerHeap(
-    AHeapInfo*) {
-  return 0;
-}
-
-__attribute__((visibility("default"))) bool
-AHeapProfile_reportAllocation(uint32_t, uint64_t, uint64_t) {
-  return false;
-}
-
-__attribute__((visibility("default"))) bool
-AHeapProfile_reportSample(uint32_t, uint64_t, uint64_t) {
-  return false;
-}
-
-__attribute__((visibility("default"))) void AHeapProfile_reportFree(uint32_t,
-                                                                    uint64_t) {}
-
-__attribute__((visibility("default"))) bool AHeapProfile_initSession(
-    void* (*)(size_t),
-    void (*)(void*)) {
-  return false;
-}
diff --git a/src/profiling/memory/client_api_unittest.cc b/src/profiling/memory/client_api_unittest.cc
deleted file mode 100644
index ce4d1b2..0000000
--- a/src/profiling/memory/client_api_unittest.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-
-#include "src/profiling/memory/client.h"
-#include "src/profiling/memory/client_api_factory.h"
-#include "src/profiling/memory/shared_ring_buffer.h"
-#include "src/profiling/memory/wire_protocol.h"
-#include "test/gtest_and_gmock.h"
-
-#include <memory>
-
-namespace perfetto {
-namespace profiling {
-
-namespace {
-
-ClientConfiguration g_client_config;
-int g_shmem_fd;
-
-base::UnixSocketRaw& GlobalServerSocket() {
-  static base::UnixSocketRaw* srv_sock = new base::UnixSocketRaw;
-  return *srv_sock;
-}
-
-void DisconnectGlobalServerSocket() {
-  base::UnixSocketRaw destroy;
-  std::swap(destroy, GlobalServerSocket());
-}
-
-}  // namespace
-
-// This is called by AHeapProfile_initSession (client_api.cc) to construct a
-// client. The Client API requires to be linked against another compliation
-// unit that provides this function. This way, it can be used in different
-// circumstances (central heapprofd, fork heapprofd) and be agnostic about the
-// details. This is is used to create a test Client here.
-void StartHeapprofdIfStatic() {}
-std::shared_ptr<Client> ConstructClient(
-    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
-  base::UnixSocketRaw cli_sock;
-  base::UnixSocketRaw& srv_sock = GlobalServerSocket();
-  std::tie(cli_sock, srv_sock) = base::UnixSocketRaw::CreatePairPosix(
-      base::SockFamily::kUnix, base::SockType::kStream);
-  auto ringbuf = SharedRingBuffer::Create(8 * 1048576);
-  PERFETTO_CHECK(ringbuf);
-  PERFETTO_CHECK(cli_sock);
-  PERFETTO_CHECK(srv_sock);
-  g_shmem_fd = ringbuf->fd();
-  return std::allocate_shared<Client>(unhooked_allocator, std::move(cli_sock),
-                                      g_client_config, std::move(*ringbuf),
-                                      getpid(), GetMainThreadStackRange());
-}
-
-namespace {
-
-TEST(ClientApiTest, NoClient) {
-  uint32_t heap_id = AHeapProfile_registerHeap(AHeapInfo_create("NoClient"));
-  EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
-}
-
-TEST(ClientApiTest, ClientEnabledHeap) {
-  uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_create("ClientEnabledHeap"));
-  ClientConfiguration client_config{};
-  client_config.default_interval = 1;
-  strcpy(&client_config.heaps[0].name[0], "ClientEnabledHeap");
-  client_config.heaps[0].interval = 1;
-  client_config.num_heaps = 1;
-
-  g_client_config = client_config;
-
-  AHeapProfile_initSession(malloc, free);
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-  g_shmem_fd = 0;
-  PERFETTO_CHECK(ringbuf);
-  EXPECT_TRUE(AHeapProfile_reportAllocation(heap_id, 1, 1));
-  // Check that the service received something on the shmem.
-  EXPECT_TRUE(ringbuf->BeginRead());
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-  EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
-}
-
-TEST(ClientApiTest, ClientAllHeaps) {
-  uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_create("ClientAllHeaps"));
-  ClientConfiguration client_config{};
-  client_config.default_interval = 1;
-  client_config.all_heaps = true;
-
-  g_client_config = client_config;
-
-  AHeapProfile_initSession(malloc, free);
-  PERFETTO_CHECK(g_shmem_fd);
-  auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
-  g_shmem_fd = 0;
-  PERFETTO_CHECK(ringbuf);
-  EXPECT_TRUE(AHeapProfile_reportAllocation(heap_id, 1, 1));
-  // Check that the service received something on the shmem.
-  EXPECT_TRUE(ringbuf->BeginRead());
-  DisconnectGlobalServerSocket();
-  ringbuf->SetShuttingDown();
-  EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
-}
-
-}  // namespace
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/client_unittest.cc b/src/profiling/memory/client_unittest.cc
index fce06fd..62f0909 100644
--- a/src/profiling/memory/client_unittest.cc
+++ b/src/profiling/memory/client_unittest.cc
@@ -16,8 +16,6 @@
 
 #include "src/profiling/memory/client.h"
 
-#include <signal.h>
-
 #include <thread>
 
 #include "perfetto/base/thread_utils.h"
@@ -29,72 +27,18 @@
 namespace profiling {
 namespace {
 
-TEST(ClientTest, GetThreadStackRangeBase) {
+TEST(ClientTest, GetThreadStackBase) {
   std::thread th([] {
-    StackRange stackrange = GetThreadStackRange();
-    ASSERT_NE(stackrange.begin, nullptr);
-    ASSERT_NE(stackrange.end, nullptr);
+    const char* stackbase = GetThreadStackBase();
+    ASSERT_NE(stackbase, nullptr);
     // The implementation assumes the stack grows from higher addresses to
     // lower. We will need to rework once we encounter architectures where the
     // stack grows the other way.
-    EXPECT_LT(stackrange.begin, __builtin_frame_address(0));
-    EXPECT_GT(stackrange.end, __builtin_frame_address(0));
+    EXPECT_GT(stackbase, __builtin_frame_address(0));
   });
   th.join();
 }
 
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_GetSigaltStackRange DISABLED_GetSigaltStackRange
-#else
-#define MAYBE_GetSigaltStackRange GetSigaltStackRange
-#endif
-
-TEST(ClientTest, MAYBE_GetSigaltStackRange) {
-  char stack[4096];
-  stack_t altstack{};
-  stack_t old_altstack{};
-  altstack.ss_sp = stack;
-  altstack.ss_size = sizeof(stack);
-  ASSERT_NE(sigaltstack(&altstack, &old_altstack), -1);
-
-  struct sigaction oldact;
-  struct sigaction newact {};
-
-  static StackRange stackrange;
-  static const char* stackptr;
-  newact.sa_handler = [](int) {
-    stackrange = GetSigAltStackRange();
-    stackptr = static_cast<char*>(__builtin_frame_address(0));
-  };
-  newact.sa_flags = SA_ONSTACK;
-  int res = sigaction(SIGUSR1, &newact, &oldact);
-  ASSERT_NE(res, -1);
-
-  raise(SIGUSR1);
-
-  PERFETTO_CHECK(sigaction(SIGUSR1, &oldact, nullptr) != -1);
-  PERFETTO_CHECK(sigaltstack(&old_altstack, nullptr) != -1);
-
-  ASSERT_EQ(stackrange.begin, stack);
-  ASSERT_EQ(stackrange.end, &stack[4096]);
-  ASSERT_LT(stackrange.begin, stackptr);
-  ASSERT_GT(stackrange.end, stackptr);
-}
-
-TEST(ClientTest, GetMainThreadStackRange) {
-  if (getpid() != base::GetThreadId())
-    GTEST_SKIP() << "This test has to run on the main thread.";
-
-  StackRange stackrange = GetMainThreadStackRange();
-  ASSERT_NE(stackrange.begin, nullptr);
-  ASSERT_NE(stackrange.end, nullptr);
-  // The implementation assumes the stack grows from higher addresses to
-  // lower. We will need to rework once we encounter architectures where the
-  // stack grows the other way.
-  EXPECT_LT(stackrange.begin, __builtin_frame_address(0));
-  EXPECT_GT(stackrange.end, __builtin_frame_address(0));
-}
-
 TEST(ClientTest, IsMainThread) {
   // Our code relies on the fact that getpid() == GetThreadId() if this
   // process/thread is the main thread of the process. This test ensures that is
diff --git a/src/profiling/memory/heap_profile_internal.h b/src/profiling/memory/heap_profile_internal.h
deleted file mode 100644
index 8e9a980..0000000
--- a/src/profiling/memory/heap_profile_internal.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_MEMORY_HEAP_PROFILE_INTERNAL_H_
-#define SRC_PROFILING_MEMORY_HEAP_PROFILE_INTERNAL_H_
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#pragma GCC diagnostic push
-
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wnullability-extension"
-#else
-#define _Nullable
-#define _Nonnull
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Called by the standalone client or libc upon receipt of the profiling
-// signal.
-bool AHeapProfile_initSession(void* _Nullable (*_Nonnull malloc_fn)(size_t),
-                              void (*_Nonnull free_fn)(void* _Nullable));
-
-#ifdef __cplusplus
-}
-#endif
-
-#pragma GCC diagnostic pop
-
-#endif  // SRC_PROFILING_MEMORY_HEAP_PROFILE_INTERNAL_H_
diff --git a/src/profiling/memory/heapprofd_client_api.map.txt b/src/profiling/memory/heapprofd_client_api.map.txt
deleted file mode 100644
index 11d8d58..0000000
--- a/src/profiling/memory/heapprofd_client_api.map.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-HEAPPROFD_API_S { # introduced=S
-  global:
-    AHeapProfileEnableCallbackInfo_getSamplingInterval; # apex
-    AHeapProfile_reportSample; # apex
-    AHeapProfile_reportFree; # apex
-    AHeapProfile_reportAllocation; # apex
-    AHeapProfile_registerHeap; # apex
-    AHeapInfo_setEnabledCallback; # apex
-    AHeapInfo_setDisabledCallback; # apex
-    AHeapInfo_create; # apex
-};
-
-PRIVATE {
-  global:
-    AHeapProfile_initSession;
-  local:
-    *;
-} HEAPPROFD_API_S;
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index 97c9876..20c01e7 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -14,29 +14,16 @@
  * limitations under the License.
  */
 
-#include <atomic>
-#include <string>
-#include <vector>
-
 #include <fcntl.h>
-#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/subprocess.h"
 #include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/heap_profile.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "protos/perfetto/trace/trace.gen.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/profiling/memory/heapprofd_producer.h"
 #include "test/gtest_and_gmock.h"
@@ -47,7 +34,6 @@
 #endif
 
 #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
-#include "protos/perfetto/trace/interned_data/interned_data.gen.h"
 #include "protos/perfetto/trace/profiling/profile_common.gen.h"
 #include "protos/perfetto/trace/profiling/profile_packet.gen.h"
 
@@ -59,498 +45,107 @@
 
 constexpr auto kTracingDisabledTimeoutMs = 30000;
 constexpr auto kWaitForReadDataTimeoutMs = 10000;
-constexpr size_t kStartupAllocSize = 10;
-constexpr size_t kFirstIterationBytes = 5;
-constexpr size_t kSecondIterationBytes = 7;
 
-enum class TestMode { kCentral, kStatic };
-enum class AllocatorMode { kMalloc, kCustom };
-
-using ::testing::AllOf;
 using ::testing::AnyOf;
 using ::testing::Bool;
-using ::testing::Contains;
 using ::testing::Eq;
-using ::testing::Field;
-using ::testing::HasSubstr;
-using ::testing::Values;
 
-constexpr const char* kOnlyFlamegraph =
-    "SELECT id, name, map_name, count, cumulative_count, size, "
-    "cumulative_size, "
-    "alloc_count, cumulative_alloc_count, alloc_size, cumulative_alloc_size, "
-    "parent_id "
-    "FROM experimental_flamegraph WHERE "
-    "(ts, upid) IN (SELECT distinct ts, upid from heap_profile_allocation) AND "
-    "profile_type = 'native' order by abs(cumulative_size) desc;";
+constexpr const char* kHeapprofdModeProperty = "heapprofd.userdebug.mode";
 
-struct FlamegraphNode {
-  int64_t id;
-  std::string name;
-  std::string map_name;
-  int64_t count;
-  int64_t cumulative_count;
-  int64_t size;
-  int64_t cumulative_size;
-  int64_t alloc_count;
-  int64_t cumulative_alloc_count;
-  int64_t alloc_size;
-  int64_t cumulative_alloc_size;
-  base::Optional<int64_t> parent_id;
-};
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 
-std::vector<FlamegraphNode> GetFlamegraph(trace_processor::TraceProcessor* tp) {
-  std::vector<FlamegraphNode> result;
-  auto it = tp->ExecuteQuery(kOnlyFlamegraph);
-  while (it.Next()) {
-    result.push_back({
-        it.Get(0).AsLong(),
-        it.Get(1).AsString(),
-        it.Get(2).AsString(),
-        it.Get(3).AsLong(),
-        it.Get(4).AsLong(),
-        it.Get(5).AsLong(),
-        it.Get(6).AsLong(),
-        it.Get(7).AsLong(),
-        it.Get(8).AsLong(),
-        it.Get(9).AsLong(),
-        it.Get(10).AsLong(),
-        it.Get(11).is_null() ? base::nullopt
-                             : base::Optional<int64_t>(it.Get(11).AsLong()),
-    });
+std::string ReadProperty(const std::string& name, std::string def) {
+  const prop_info* pi = __system_property_find(name.c_str());
+  if (pi) {
+    __system_property_read_callback(
+        pi,
+        [](void* cookie, const char*, const char* value, uint32_t) {
+          *reinterpret_cast<std::string*>(cookie) = value;
+        },
+        &def);
   }
-  PERFETTO_CHECK(it.Status().ok());
-  return result;
+  return def;
 }
 
-std::string AllocatorName(AllocatorMode mode) {
-  switch (mode) {
-    case AllocatorMode::kMalloc:
-      return "libc.malloc";
-    case AllocatorMode::kCustom:
-      return "test";
+int SetModeProperty(std::string* value) {
+  if (value) {
+    __system_property_set(kHeapprofdModeProperty, value->c_str());
+    delete value;
   }
+  return 0;
 }
 
-AllocatorMode AllocatorModeFromNameOrDie(std::string s) {
-  if (s == "libc.malloc")
-    return AllocatorMode::kMalloc;
-  if (s == "test")
-    return AllocatorMode::kCustom;
-  PERFETTO_FATAL("Invalid allocator mode [malloc | test]: %s", s.c_str());
+base::ScopedResource<std::string*, SetModeProperty, nullptr> EnableFork() {
+  std::string prev_property_value = ReadProperty(kHeapprofdModeProperty, "");
+  __system_property_set(kHeapprofdModeProperty, "fork");
+  return base::ScopedResource<std::string*, SetModeProperty, nullptr>(
+      new std::string(prev_property_value));
 }
 
-void ContinuousDump(HeapprofdConfig* cfg) {
-  auto* cont_config = cfg->mutable_continuous_dump_config();
-  cont_config->set_dump_phase_ms(0);
-  cont_config->set_dump_interval_ms(100);
+base::ScopedResource<std::string*, SetModeProperty, nullptr> DisableFork() {
+  std::string prev_property_value = ReadProperty(kHeapprofdModeProperty, "");
+  __system_property_set(kHeapprofdModeProperty, "");
+  return base::ScopedResource<std::string*, SetModeProperty, nullptr>(
+      new std::string(prev_property_value));
 }
 
-template <typename F>
-TraceConfig MakeTraceConfig(F fn) {
-  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);
-
-  protos::gen::HeapprofdConfig heapprofd_config;
-  fn(&heapprofd_config);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
-  return trace_config;
+#else
+std::string ReadProperty(const std::string&, std::string) {
+  PERFETTO_FATAL("Only works on Android.");
 }
 
-void CustomAllocateAndFree(size_t bytes) {
-  static uint32_t heap_id = AHeapProfile_registerHeap(AHeapInfo_create("test"));
-  AHeapProfile_reportAllocation(heap_id, 0x1234abc, bytes);
-  AHeapProfile_reportFree(heap_id, 0x1234abc);
+int SetModeProperty(std::string*) {
+  PERFETTO_FATAL("Only works on Android.");
 }
 
-void SecondaryAllocAndFree(size_t bytes) {
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_create("secondary"));
-  AHeapProfile_reportAllocation(heap_id, 0x1234abc, bytes);
-  AHeapProfile_reportFree(heap_id, 0x1234abc);
+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) {
   // This volatile is needed to prevent the compiler from trying to be
   // helpful and compiling a "useless" malloc + free into a noop.
   volatile char* x = static_cast<char*>(malloc(bytes));
   if (x) {
-    if (bytes > 0)
-      x[0] = 'x';
+    x[1] = 'x';
     free(const_cast<char*>(x));
   }
 }
 
-void DoAllocation(AllocatorMode mode, size_t bytes) {
-  switch (mode) {
-    case AllocatorMode::kMalloc:
-      AllocateAndFree(bytes);
-      break;
-    case AllocatorMode::kCustom:
-      // We need to run malloc(0) even if we want to test the custom allocator,
-      // as the init mechanism assumes the application uses malloc.
-      AllocateAndFree(1);
-      CustomAllocateAndFree(bytes);
-      break;
-  }
-}
-
-void ContinuousMalloc(AllocatorMode mode,
-                      size_t primary_bytes,
-                      size_t secondary_bytes,
-                      ssize_t max_iter = -1) {
-  for (ssize_t i = 0; max_iter == -1 || i < max_iter; ++i) {
-    DoAllocation(mode, primary_bytes);
-    if (secondary_bytes)
-      SecondaryAllocAndFree(secondary_bytes);
+void __attribute__((noreturn)) ContinuousMalloc(size_t bytes) {
+  for (;;) {
+    AllocateAndFree(bytes);
     usleep(10 * kMsToUs);
   }
 }
 
-void StartAndWaitForHandshake(base::Subprocess* child) {
-  // We cannot use base::Pipe because that assumes we want CLOEXEC.
-  // We do NOT want CLOEXEC as this gets used by the RunReInit in the child.
-  int ready_pipe[2];
-  PERFETTO_CHECK(pipe(ready_pipe) == 0);  // NOLINT(android-cloexec-pipe)
-
-  int ready_pipe_rd = ready_pipe[0];
-  int ready_pipe_wr = ready_pipe[1];
-  child->args.preserve_fds.push_back(ready_pipe_wr);
-  child->args.env.push_back("HEAPPROFD_TESTING_READY_PIPE=" +
-                            std::to_string(ready_pipe_wr));
-  child->Start();
-  close(ready_pipe_wr);
-  // Wait for libc to initialize the signal handler. If we signal before the
-  // handler is installed, we can kill the process.
-  char buf[1];
-  PERFETTO_CHECK(PERFETTO_EINTR(read(ready_pipe_rd, buf, sizeof(buf))) == 0);
-  close(ready_pipe_rd);
+base::Subprocess ForkContinuousMalloc(size_t bytes) {
+  base::Subprocess proc;
+  proc.args.entrypoint_for_testing = [bytes] { ContinuousMalloc(bytes); };
+  proc.Start();
+  return proc;
 }
 
-void ChildFinishHandshake() {
-  const char* ready_pipe = getenv("HEAPPROFD_TESTING_READY_PIPE");
-  if (ready_pipe != nullptr) {
-    close(static_cast<int>(base::StringToInt64(ready_pipe).value()));
-  }
+void __attribute__((constructor)) RunContinuousMalloc() {
+  if (getenv("HEAPPROFD_TESTING_RUN_MALLOC") != nullptr)
+    ContinuousMalloc(kStartupAllocSize);
 }
 
-base::Subprocess ForkContinuousAlloc(AllocatorMode mode,
-                                     size_t primary_bytes,
-                                     size_t secondary_bytes = 0,
-                                     ssize_t max_iter = -1) {
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           AllocatorName(mode));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(primary_bytes));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::to_string(secondary_bytes));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG3=" +
-                           std::to_string(max_iter));
-
-  StartAndWaitForHandshake(&child);
-  return child;
-}
-
-void __attribute__((constructor(1024))) RunContinuousMalloc() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_MALLOC_ARG0");
-  const char* a1 = getenv("HEAPPROFD_TESTING_RUN_MALLOC_ARG1");
-  const char* a2 = getenv("HEAPPROFD_TESTING_RUN_MALLOC_ARG2");
-  const char* a3 = getenv("HEAPPROFD_TESTING_RUN_MALLOC_ARG3");
-  if (a0 == nullptr)
-    return;
-
-  AllocatorMode arg0 = AllocatorModeFromNameOrDie(a0);
-  uint32_t arg1 = a1 ? base::StringToUInt32(a1).value() : 0;
-  uint32_t arg2 = a2 ? base::StringToUInt32(a2).value() : 0;
-  int32_t arg3 = a3 ? base::StringToInt32(a3).value() : -1;
-
-  ChildFinishHandshake();
-
-  ContinuousMalloc(arg0, arg1, arg2, arg3);
-  exit(0);
-}
-
-void __attribute__((constructor(1024))) RunAccurateMalloc() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC");
-  if (a0 == nullptr)
-    return;
-
-  static std::atomic<bool> initialized{false};
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_setEnabledCallback(
-          AHeapInfo_create("test"),
-          [](void*, const AHeapProfileEnableCallbackInfo*) {
-            initialized = true;
-          },
-          nullptr));
-
-  ChildFinishHandshake();
-
-  // heapprofd_client needs malloc to see the signal.
-  while (!initialized)
-    AllocateAndFree(1);
-  // We call the callback before setting enabled=true on the heap, so we
-  // wait a bit for the assignment to happen.
-  usleep(100000);
-  if (!AHeapProfile_reportAllocation(heap_id, 0x1, 10u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x1);
-  if (!AHeapProfile_reportAllocation(heap_id, 0x2, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  if (!AHeapProfile_reportAllocation(heap_id, 0x3, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x2);
-
-  // Wait around so we can verify it did't crash.
-  for (;;) {
-  }
-}
-
-void __attribute__((noreturn)) RunAccurateMallocWithVforkCommon() {
-  static std::atomic<bool> initialized{false};
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_setEnabledCallback(
-          AHeapInfo_create("test"),
-          [](void*, const AHeapProfileEnableCallbackInfo*) {
-            initialized = true;
-          },
-          nullptr));
-
-  ChildFinishHandshake();
-
-  // heapprofd_client needs malloc to see the signal.
-  while (!initialized)
-    AllocateAndFree(1);
-  // We call the callback before setting enabled=true on the heap, so we
-  // wait a bit for the assignment to happen.
-  usleep(100000);
-  if (!AHeapProfile_reportAllocation(heap_id, 0x1, 10u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x1);
-  pid_t pid = vfork();
-  PERFETTO_CHECK(pid != -1);
-  if (pid == 0) {
-    AHeapProfile_reportAllocation(heap_id, 0x2, 15u);
-    AHeapProfile_reportAllocation(heap_id, 0x3, 15u);
-    exit(0);
-  }
-  if (!AHeapProfile_reportAllocation(heap_id, 0x2, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  if (!AHeapProfile_reportAllocation(heap_id, 0x3, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x2);
-
-  // Wait around so we can verify it did't crash.
-  for (;;) {
-  }
-}
-
-void __attribute__((constructor(1024))) RunAccurateSample() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_ACCURATE_SAMPLE");
-  if (a0 == nullptr)
-    return;
-
-  static std::atomic<bool> initialized{false};
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_setEnabledCallback(
-          AHeapInfo_create("test"),
-          [](void*, const AHeapProfileEnableCallbackInfo*) {
-            initialized = true;
-          },
-          nullptr));
-
-  ChildFinishHandshake();
-
-  // heapprofd_client needs malloc to see the signal.
-  while (!initialized)
-    AllocateAndFree(1);
-  // We call the callback before setting enabled=true on the heap, so we
-  // wait a bit for the assignment to happen.
-  usleep(100000);
-  if (!AHeapProfile_reportSample(heap_id, 0x1, 10u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x1);
-  if (!AHeapProfile_reportSample(heap_id, 0x2, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  if (!AHeapProfile_reportSample(heap_id, 0x3, 15u))
-    PERFETTO_FATAL("Expected allocation to be sampled.");
-  AHeapProfile_reportFree(heap_id, 0x2);
-
-  // Wait around so we can verify it did't crash.
-  for (;;) {
-  }
-}
-
-void __attribute__((constructor(1024))) RunAccurateMallocWithVfork() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC_WITH_VFORK");
-  if (a0 == nullptr)
-    return;
-  RunAccurateMallocWithVforkCommon();
-}
-
-void __attribute__((constructor(1024))) RunAccurateMallocWithVforkThread() {
-  const char* a0 =
-      getenv("HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC_WITH_VFORK_THREAD");
-  if (a0 == nullptr)
-    return;
-  std::thread th(RunAccurateMallocWithVforkCommon);
-  th.join();
-}
-
-void __attribute__((constructor(1024))) RunReInit() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_REINIT_ARG0");
-  if (a0 == nullptr)
-    return;
-
-  AllocatorMode mode = AllocatorModeFromNameOrDie(a0);
-  const char* a1 = getenv("HEAPPROFD_TESTING_RUN_REINIT_ARG1");
-  const char* a2 = getenv("HEAPPROFD_TESTING_RUN_REINIT_ARG2");
-  PERFETTO_CHECK(a1 != nullptr && a2 != nullptr);
-  int signal_pipe_rd = static_cast<int>(base::StringToInt64(a1).value());
-  int ack_pipe_wr = static_cast<int>(base::StringToInt64(a2).value());
-
-  ChildFinishHandshake();
-
-  size_t bytes = kFirstIterationBytes;
-  bool signalled = false;
-  for (;;) {
-    DoAllocation(mode, bytes);
-    char buf[1];
-    if (!signalled && read(signal_pipe_rd, buf, sizeof(buf)) == 1) {
-      signalled = true;
-      close(signal_pipe_rd);
-
-      // make sure the client has noticed that the session has stopped
-      DoAllocation(mode, bytes);
-
-      bytes = kSecondIterationBytes;
-      PERFETTO_CHECK(PERFETTO_EINTR(write(ack_pipe_wr, "1", 1)) == 1);
-      close(ack_pipe_wr);
-    }
-    usleep(10 * kMsToUs);
-  }
-  PERFETTO_FATAL("Should be unreachable");
-}
-
-void __attribute__((constructor(1024))) RunCustomLifetime() {
-  const char* a0 = getenv("HEAPPROFD_TESTING_RUN_LIFETIME_ARG0");
-  const char* a1 = getenv("HEAPPROFD_TESTING_RUN_LIFETIME_ARG1");
-  if (a0 == nullptr)
-    return;
-  uint64_t arg0 = a0 ? base::StringToUInt64(a0).value() : 0;
-  uint64_t arg1 = a0 ? base::StringToUInt64(a1).value() : 0;
-
-  PERFETTO_CHECK(arg1);
-
-  static std::atomic<bool> initialized{false};
-  static std::atomic<bool> disabled{false};
-  static std::atomic<uint64_t> sampling_interval;
-
-  auto enabled_callback = [](void*,
-                             const AHeapProfileEnableCallbackInfo* info) {
-    sampling_interval =
-        AHeapProfileEnableCallbackInfo_getSamplingInterval(info);
-    initialized = true;
-  };
-  auto disabled_callback = [](void*, const AHeapProfileDisableCallbackInfo*) {
-    disabled = true;
-  };
-  static uint32_t heap_id =
-      AHeapProfile_registerHeap(AHeapInfo_setDisabledCallback(
-          AHeapInfo_setEnabledCallback(AHeapInfo_create("test"),
-                                       enabled_callback, nullptr),
-          disabled_callback, nullptr));
-
-  ChildFinishHandshake();
-
-  // heapprofd_client needs malloc to see the signal.
-  while (!initialized)
-    AllocateAndFree(1);
-
-  if (sampling_interval.load() != arg0) {
-    PERFETTO_FATAL("%" PRIu64 " != %" PRIu64, sampling_interval.load(), arg0);
-  }
-
-  while (!disabled)
-    AHeapProfile_reportFree(heap_id, 0x2);
-
-  char x = 'x';
-  PERFETTO_CHECK(base::WriteAll(static_cast<int>(arg1), &x, sizeof(x)) == 1);
-  close(static_cast<int>(arg1));
-
-  // Wait around so we can verify it didn't crash.
-  for (;;) {
-  }
-}
-
-class TraceProcessorTestHelper : public TestHelper {
- public:
-  explicit TraceProcessorTestHelper(base::TestTaskRunner* task_runner)
-      : TestHelper(task_runner),
-        tp_(trace_processor::TraceProcessor::CreateInstance({})) {}
-
-  void ReadTraceData(std::vector<TracePacket> packets) override {
-    for (auto& packet : packets) {
-      auto preamble = packet.GetProtoPreamble();
-      std::string payload = packet.GetRawBytesForTesting();
-      char* preamble_payload = std::get<0>(preamble);
-      size_t preamble_size = std::get<1>(preamble);
-      size_t buf_size = preamble_size + payload.size();
-      std::unique_ptr<uint8_t[]> buf =
-          std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
-      memcpy(&buf[0], preamble_payload, preamble_size);
-      memcpy(&buf[preamble_size], payload.data(), payload.size());
-      PERFETTO_CHECK(tp_->Parse(std::move(buf), buf_size).ok());
-    }
-    TestHelper::ReadTraceData(std::move(packets));
-  }
-
-  trace_processor::TraceProcessor& tp() { return *tp_; }
-
- private:
-  std::unique_ptr<trace_processor::TraceProcessor> tp_;
-};
-
-std::unique_ptr<TraceProcessorTestHelper> GetHelper(
-    base::TestTaskRunner* task_runner) {
-  std::unique_ptr<TraceProcessorTestHelper> helper(
-      new TraceProcessorTestHelper(task_runner));
-  helper->StartServiceIfRequired();
-
+std::unique_ptr<TestHelper> GetHelper(base::TestTaskRunner* task_runner) {
+  std::unique_ptr<TestHelper> helper(new TestHelper(task_runner));
   helper->ConnectConsumer();
   helper->WaitForConsumerConnect();
   return helper;
 }
 
-void ReadAndWait(TraceProcessorTestHelper* helper) {
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
-  helper->tp().NotifyEndOfFile();
-}
-
-std::string ToTraceString(
-    const std::vector<protos::gen::TracePacket>& packets) {
-  protos::gen::Trace trace;
-  for (const protos::gen::TracePacket& packet : packets) {
-    *trace.add_packet() = packet;
-  }
-  return trace.SerializeAsString();
-}
-
-#define WRITE_TRACE(trace)                 \
-  do {                                     \
-    WriteTrace(trace, __FILE__, __LINE__); \
-  } while (0)
-
 std::string FormatHistogram(const protos::gen::ProfilePacket_Histogram& hist) {
   std::string out;
   std::string prev_upper_limit = "-inf";
@@ -576,86 +171,45 @@
          "unwinding_time_us: " + FormatHistogram(stats.unwinding_time_us());
 }
 
-std::string Suffix(const std::tuple<TestMode, AllocatorMode>& param) {
-  TestMode tm = std::get<0>(param);
-  AllocatorMode am = std::get<1>(param);
-
-  std::string result;
-  switch (tm) {
-    case TestMode::kCentral:
-      result += "CentralMode";
-      break;
-    case TestMode::kStatic:
-      result += "StaticMode";
-      break;
-  }
-  switch (am) {
-    case AllocatorMode::kMalloc:
-      result += "Malloc";
-      break;
-    case AllocatorMode::kCustom:
-      result += "Custom";
-      break;
-  }
-  return result;
+std::string TestSuffix(const ::testing::TestParamInfo<bool>& info) {
+  return info.param ? "ForkMode" : "CentralMode";
 }
 
-__attribute__((unused)) std::string TestSuffix(
-    const ::testing::TestParamInfo<std::tuple<TestMode, AllocatorMode>>& info) {
-  return Suffix(info.param);
-}
+class HeapprofdEndToEnd : public ::testing::TestWithParam<bool> {
+ public:
+  HeapprofdEndToEnd() {
+    // This is not needed for correctness, but works around a init behavior that
+    // makes this test take much longer. If persist.heapprofd.enable is set to 0
+    // 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, "") == "");
+    }
+  }
 
-class HeapprofdEndToEnd
-    : public ::testing::TestWithParam<std::tuple<TestMode, AllocatorMode>> {
  protected:
   base::TestTaskRunner task_runner;
+  base::ScopedResource<std::string*, SetModeProperty, nullptr> fork_prop_{
+      nullptr};
 
-  TestMode test_mode() { return std::get<0>(GetParam()); }
-  AllocatorMode allocator_mode() { return std::get<1>(GetParam()); }
-  std::string allocator_name() { return AllocatorName(allocator_mode()); }
-
-  void WriteTrace(const std::vector<protos::gen::TracePacket>& packets,
-                  const char* filename,
-                  uint64_t lineno) {
-    const char* outdir = getenv("HEAPPROFD_TEST_PROFILE_OUT");
-    if (!outdir)
-      return;
-    const std::string fq_filename =
-        std::string(outdir) + "/" + basename(filename) + ":" +
-        std::to_string(lineno) + "_" + Suffix(GetParam());
-    base::ScopedFile fd(base::OpenFile(fq_filename, O_WRONLY | O_CREAT, 0666));
-    PERFETTO_CHECK(*fd);
-    std::string trace_string = ToTraceString(packets);
-    PERFETTO_CHECK(
-        base::WriteAll(*fd, trace_string.data(), trace_string.size()) >= 0);
-  }
-
-  std::unique_ptr<TraceProcessorTestHelper> Trace(
-      const TraceConfig& trace_config) {
+  std::unique_ptr<TestHelper> Trace(const TraceConfig& trace_config) {
     auto helper = GetHelper(&task_runner);
 
     helper->StartTracing(trace_config);
+    helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
 
-    ReadAndWait(helper.get());
+    helper->ReadData();
+    helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
     return helper;
   }
 
-  std::vector<std::string> GetUnwindingErrors(
-      TraceProcessorTestHelper* helper) {
-    std::vector<std::string> out;
-    const auto& packets = helper->trace();
-    for (const protos::gen::TracePacket& packet : packets) {
-      for (const protos::gen::InternedString& fn :
-           packet.interned_data().function_names()) {
-        if (fn.str().find("ERROR ") == 0) {
-          out.push_back(fn.str());
-        }
-      }
-    }
-    return out;
-  }
-
-  void PrintStats(TraceProcessorTestHelper* helper) {
+  void PrintStats(TestHelper* helper) {
     const auto& packets = helper->trace();
     for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
@@ -664,23 +218,16 @@
                      FormatStats(dump.stats()).c_str());
       }
     }
-    std::vector<std::string> errors = GetUnwindingErrors(helper);
-    for (const std::string& err : errors) {
-      PERFETTO_LOG("Unwinding error: %s", err.c_str());
-    }
   }
 
-  void ValidateSampleSizes(TraceProcessorTestHelper* helper,
+  void ValidateSampleSizes(TestHelper* helper,
                            uint64_t pid,
-                           uint64_t alloc_size,
-                           const std::string& heap_name = "") {
+                           uint64_t alloc_size) {
     const auto& packets = helper->trace();
     for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
-        if (dump.pid() != pid ||
-            (!heap_name.empty() && heap_name != dump.heap_name())) {
+        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);
@@ -691,7 +238,7 @@
     }
   }
 
-  void ValidateFromStartup(TraceProcessorTestHelper* helper,
+  void ValidateFromStartup(TestHelper* helper,
                            uint64_t pid,
                            bool from_startup) {
     const auto& packets = helper->trace();
@@ -704,7 +251,7 @@
     }
   }
 
-  void ValidateRejectedConcurrent(TraceProcessorTestHelper* helper,
+  void ValidateRejectedConcurrent(TestHelper* helper,
                                   uint64_t pid,
                                   bool rejected_concurrent) {
     const auto& packets = helper->trace();
@@ -717,23 +264,7 @@
     }
   }
 
-  void ValidateNoSamples(TraceProcessorTestHelper* helper, uint64_t pid) {
-    const auto& packets = helper->trace();
-    size_t samples = 0;
-    for (const protos::gen::TracePacket& packet : packets) {
-      for (const auto& dump : packet.profile_packet().process_dumps()) {
-        if (dump.pid() != pid)
-          continue;
-        samples += dump.samples().size();
-      }
-    }
-    EXPECT_EQ(samples, 0u);
-  }
-
-  void ValidateHasSamples(TraceProcessorTestHelper* helper,
-                          uint64_t pid,
-                          const std::string& heap_name,
-                          uint64_t sampling_interval) {
+  void ValidateHasSamples(TestHelper* helper, uint64_t pid) {
     const auto& packets = helper->trace();
     ASSERT_GT(packets.size(), 0u);
     size_t profile_packets = 0;
@@ -742,9 +273,8 @@
     uint64_t last_freed = 0;
     for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
-        if (dump.pid() != pid || dump.heap_name() != heap_name)
+        if (dump.pid() != pid)
           continue;
-        EXPECT_EQ(dump.sampling_interval_bytes(), sampling_interval);
         for (const auto& sample : dump.samples()) {
           last_allocated = sample.self_allocated();
           last_freed = sample.self_freed();
@@ -753,13 +283,13 @@
         profile_packets++;
       }
     }
-    EXPECT_GT(profile_packets, 0u) << heap_name;
-    EXPECT_GT(samples, 0u) << heap_name;
-    EXPECT_GT(last_allocated, 0u) << heap_name;
-    EXPECT_GT(last_freed, 0u) << heap_name;
+    EXPECT_GT(profile_packets, 0u);
+    EXPECT_GT(samples, 0u);
+    EXPECT_GT(last_allocated, 0u);
+    EXPECT_GT(last_freed, 0u);
   }
 
-  void ValidateOnlyPID(TraceProcessorTestHelper* helper, uint64_t pid) {
+  void ValidateOnlyPID(TestHelper* helper, uint64_t pid) {
     size_t dumps = 0;
     const auto& packets = helper->trace();
     for (const protos::gen::TracePacket& packet : packets) {
@@ -775,447 +305,125 @@
 // This checks that the child is still running (to ensure it didn't crash
 // unxpectedly) and then kills it.
 void KillAssertRunning(base::Subprocess* child) {
-  ASSERT_EQ(child->Poll(), base::Subprocess::kRunning)
-      << "Target process not running. CHECK CRASH LOGS.";
-  PERFETTO_LOG("Shutting down profile target.");
+  ASSERT_EQ(child->Poll(), base::Subprocess::kRunning);
   child->KillAndWaitForTermination();
 }
 
-TEST_P(HeapprofdEndToEnd, Disabled) {
-  constexpr size_t kAllocSize = 1024;
-
-  base::Subprocess child = ForkContinuousAlloc(allocator_mode(), kAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps("invalid");
-    ContinuousDump(cfg);
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  ValidateNoSamples(helper.get(), pid);
-}
-
 TEST_P(HeapprofdEndToEnd, Smoke) {
   constexpr size_t kAllocSize = 1024;
-  constexpr size_t kSamplingInterval = 1;
 
-  base::Subprocess child = ForkContinuousAlloc(allocator_mode(), kAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
+  base::Subprocess child = ForkContinuousMalloc(kAllocSize);
+  const auto pid = child.pid();
 
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-    ContinuousDump(cfg);
-  });
+  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);
+
+  protos::gen::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.mutable_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 = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
   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);
+
   KillAssertRunning(&child);
-
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kAllocSize);
-}
-
-TEST_P(HeapprofdEndToEnd, TwoAllocators) {
-  constexpr size_t kCustomAllocSize = 1024;
-  constexpr size_t kAllocSize = 7;
-  constexpr size_t kSamplingInterval = 1;
-
-  base::Subprocess child =
-      ForkContinuousAlloc(allocator_mode(), kAllocSize, kCustomAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-    cfg->add_heaps("secondary");
-    ContinuousDump(cfg);
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  ValidateHasSamples(helper.get(), pid, "secondary", kSamplingInterval);
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kCustomAllocSize, "secondary");
-  ValidateSampleSizes(helper.get(), pid, kAllocSize, allocator_name());
-}
-
-TEST_P(HeapprofdEndToEnd, TwoAllocatorsAll) {
-  constexpr size_t kCustomAllocSize = 1024;
-  constexpr size_t kAllocSize = 7;
-  constexpr size_t kSamplingInterval = 1;
-
-  base::Subprocess child =
-      ForkContinuousAlloc(allocator_mode(), kAllocSize, kCustomAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->set_all_heaps(true);
-    ContinuousDump(cfg);
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  ValidateHasSamples(helper.get(), pid, "secondary", kSamplingInterval);
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kCustomAllocSize, "secondary");
-  ValidateSampleSizes(helper.get(), pid, kAllocSize, allocator_name());
-}
-
-TEST_P(HeapprofdEndToEnd, AccurateCustomReportAllocation) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC=1");
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  auto flamegraph = GetFlamegraph(&helper->tp());
-  EXPECT_THAT(flamegraph,
-              Contains(AllOf(
-                  Field(&FlamegraphNode::name, HasSubstr("RunAccurateMalloc")),
-                  Field(&FlamegraphNode::cumulative_size, Eq(15)),
-                  Field(&FlamegraphNode::cumulative_alloc_size, Eq(40)))));
-
-  ValidateOnlyPID(helper.get(), pid);
-
-  size_t total_alloc = 0;
-  size_t total_freed = 0;
-  for (const protos::gen::TracePacket& packet : helper->trace()) {
-    for (const auto& dump : packet.profile_packet().process_dumps()) {
-      for (const auto& sample : dump.samples()) {
-        total_alloc += sample.self_allocated();
-        total_freed += sample.self_freed();
-      }
-    }
-  }
-  EXPECT_EQ(total_alloc, 40u);
-  EXPECT_EQ(total_freed, 25u);
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#define MAYBE_AccurateCustomReportAllocationWithVfork \
-  AccurateCustomReportAllocationWithVfork
-#define MAYBE_AccurateCustomReportAllocationWithVforkThread \
-  AccurateCustomReportAllocationWithVforkThread
-#else
-#define MAYBE_AccurateCustomReportAllocationWithVfork \
-  DISABLED_AccurateCustomReportAllocationWithVfork
-#define MAYBE_AccurateCustomReportAllocationWithVforkThread \
-  DISABLED_AccurateCustomReportAllocationWithVforkThread
-#endif
-
-TEST_P(HeapprofdEndToEnd, MAYBE_AccurateCustomReportAllocationWithVfork) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back(
-      "HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC_WITH_VFORK=1");
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  auto flamegraph = GetFlamegraph(&helper->tp());
-  EXPECT_THAT(flamegraph,
-              Contains(AllOf(
-                  Field(&FlamegraphNode::name, HasSubstr("RunAccurateMalloc")),
-                  Field(&FlamegraphNode::cumulative_size, Eq(15)),
-                  Field(&FlamegraphNode::cumulative_alloc_size, Eq(40)))));
-
-  ValidateOnlyPID(helper.get(), pid);
-
-  size_t total_alloc = 0;
-  size_t total_freed = 0;
-  for (const protos::gen::TracePacket& packet : helper->trace()) {
-    for (const auto& dump : packet.profile_packet().process_dumps()) {
-      EXPECT_FALSE(dump.disconnected());
-      for (const auto& sample : dump.samples()) {
-        total_alloc += sample.self_allocated();
-        total_freed += sample.self_freed();
-      }
-    }
-  }
-  EXPECT_EQ(total_alloc, 40u);
-  EXPECT_EQ(total_freed, 25u);
-}
-
-TEST_P(HeapprofdEndToEnd, MAYBE_AccurateCustomReportAllocationWithVforkThread) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back(
-      "HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC_WITH_VFORK_THREAD=1");
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  auto flamegraph = GetFlamegraph(&helper->tp());
-  EXPECT_THAT(flamegraph,
-              Contains(AllOf(
-                  Field(&FlamegraphNode::name, HasSubstr("RunAccurateMalloc")),
-                  Field(&FlamegraphNode::cumulative_size, Eq(15)),
-                  Field(&FlamegraphNode::cumulative_alloc_size, Eq(40)))));
-
-  ValidateOnlyPID(helper.get(), pid);
-
-  size_t total_alloc = 0;
-  size_t total_freed = 0;
-  for (const protos::gen::TracePacket& packet : helper->trace()) {
-    for (const auto& dump : packet.profile_packet().process_dumps()) {
-      EXPECT_FALSE(dump.disconnected());
-      for (const auto& sample : dump.samples()) {
-        total_alloc += sample.self_allocated();
-        total_freed += sample.self_freed();
-      }
-    }
-  }
-  EXPECT_EQ(total_alloc, 40u);
-  EXPECT_EQ(total_freed, 25u);
-}
-
-TEST_P(HeapprofdEndToEnd, AccurateCustomReportSample) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_ACCURATE_SAMPLE=1");
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1000000);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  ValidateOnlyPID(helper.get(), pid);
-
-  size_t total_alloc = 0;
-  size_t total_freed = 0;
-  for (const protos::gen::TracePacket& packet : helper->trace()) {
-    for (const auto& dump : packet.profile_packet().process_dumps()) {
-      for (const auto& sample : dump.samples()) {
-        total_alloc += sample.self_allocated();
-        total_freed += sample.self_freed();
-      }
-    }
-  }
-  EXPECT_EQ(total_alloc, 40u);
-  EXPECT_EQ(total_freed, 25u);
-}
-
-TEST_P(HeapprofdEndToEnd, AccurateDumpAtMaxCustom) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_ACCURATE_MALLOC=1");
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-    cfg->set_dump_at_max(true);
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  KillAssertRunning(&child);
-
-  ValidateOnlyPID(helper.get(), pid);
-
-  size_t total_alloc = 0;
-  size_t total_count = 0;
-  for (const protos::gen::TracePacket& packet : helper->trace()) {
-    for (const auto& dump : packet.profile_packet().process_dumps()) {
-      for (const auto& sample : dump.samples()) {
-        total_alloc += sample.self_max();
-        total_count += sample.self_max_count();
-      }
-    }
-  }
-  EXPECT_EQ(total_alloc, 30u);
-  EXPECT_EQ(total_count, 2u);
-}
-
-TEST_P(HeapprofdEndToEnd, CustomLifetime) {
-  if (allocator_mode() != AllocatorMode::kCustom)
-    GTEST_SKIP();
-
-  int disabled_pipe[2];
-  PERFETTO_CHECK(pipe(disabled_pipe) == 0);  // NOLINT(android-cloexec-pipe)
-
-  int disabled_pipe_rd = disabled_pipe[0];
-  int disabled_pipe_wr = disabled_pipe[1];
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_LIFETIME_ARG0=1000000");
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_LIFETIME_ARG1=" +
-                           std::to_string(disabled_pipe_wr));
-  child.args.preserve_fds.push_back(disabled_pipe_wr);
-  StartAndWaitForHandshake(&child);
-  close(disabled_pipe_wr);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  TraceConfig trace_config = MakeTraceConfig([pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1000000);
-    cfg->add_pid(pid);
-    cfg->add_heaps("test");
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-  PrintStats(helper.get());
-  // Give client some time to notice the disconnect.
-  sleep(2);
-  KillAssertRunning(&child);
-
-  char x;
-  EXPECT_EQ(base::Read(disabled_pipe_rd, &x, sizeof(x)), 1);
-  close(disabled_pipe_rd);
 }
 
 TEST_P(HeapprofdEndToEnd, TwoProcesses) {
   constexpr size_t kAllocSize = 1024;
   constexpr size_t kAllocSize2 = 7;
-  constexpr size_t kSamplingInterval = 1;
 
-  base::Subprocess child = ForkContinuousAlloc(allocator_mode(), kAllocSize);
-  base::Subprocess child2 = ForkContinuousAlloc(allocator_mode(), kAllocSize2);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
+  base::Subprocess child = ForkContinuousMalloc(kAllocSize);
+  base::Subprocess child2 = ForkContinuousMalloc(kAllocSize2);
+  const auto pid = child.pid();
   const auto pid2 = child2.pid();
 
-  TraceConfig trace_config =
-      MakeTraceConfig([this, pid, pid2](HeapprofdConfig* cfg) {
-        cfg->set_sampling_interval_bytes(kSamplingInterval);
-        cfg->add_pid(pid);
-        cfg->add_pid(static_cast<uint64_t>(pid2));
-        cfg->add_heaps(allocator_name());
-      });
+  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);
+
+  protos::gen::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 helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
   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);
 
   KillAssertRunning(&child);
   KillAssertRunning(&child2);
-
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateSampleSizes(helper.get(), pid, kAllocSize);
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid2),
-                     allocator_name(), kSamplingInterval);
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid2), kAllocSize2);
 }
 
 TEST_P(HeapprofdEndToEnd, FinalFlush) {
   constexpr size_t kAllocSize = 1024;
-  constexpr size_t kSamplingInterval = 1;
 
-  base::Subprocess child = ForkContinuousAlloc(allocator_mode(), kAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-  });
+  base::Subprocess child = ForkContinuousMalloc(kAllocSize);
+  const auto pid = child.pid();
+
+  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);
+
+  protos::gen::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);
-  WRITE_TRACE(helper->full_trace());
   PrintStats(helper.get());
-  KillAssertRunning(&child);
+  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);
 
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kAllocSize);
+  KillAssertRunning(&child);
 }
 
 TEST_P(HeapprofdEndToEnd, NativeStartup) {
-  if (test_mode() == TestMode::kStatic)
-    GTEST_SKIP();
-
   auto helper = GetHelper(&task_runner);
 
-  TraceConfig trace_config = MakeTraceConfig([this](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_process_cmdline("heapprofd_continuous_malloc");
-    cfg->add_heaps(allocator_name());
-  });
+  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");
+
+  protos::gen::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());
 
   helper->StartTracing(trace_config);
 
@@ -1227,17 +435,16 @@
   sleep(1);
 
   base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(kStartupAllocSize));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::string("0"));
-  StartAndWaitForHandshake(&child);
+  child.args.argv0_override = "heapprofd_continuous_malloc";
+  child.args.stdout_mode = base::Subprocess::kDevNull;
+  child.args.stderr_mode = base::Subprocess::kDevNull;
+  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC=1");
+  child.Start();
 
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+
+  helper->ReadData();
+  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
 
   KillAssertRunning(&child);
 
@@ -1249,7 +456,7 @@
   uint64_t total_freed = 0;
   for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
-        !packet.profile_packet().process_dumps().empty()) {
+        packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
       ASSERT_EQ(dumps.size(), 1u);
       const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
@@ -1269,17 +476,21 @@
 }
 
 TEST_P(HeapprofdEndToEnd, NativeStartupDenormalizedCmdline) {
-  if (test_mode() == TestMode::kStatic)
-    GTEST_SKIP();
-
   auto helper = GetHelper(&task_runner);
 
-  TraceConfig trace_config = MakeTraceConfig([this](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-    cfg->add_heaps(allocator_name());
-  });
+  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");
+
+  protos::gen::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());
 
   helper->StartTracing(trace_config);
 
@@ -1291,18 +502,16 @@
   sleep(1);
 
   base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(kStartupAllocSize));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::string("0"));
+  child.args.argv0_override = "heapprofd_continuous_malloc";
+  child.args.stdout_mode = base::Subprocess::kDevNull;
+  child.args.stderr_mode = base::Subprocess::kDevNull;
+  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC=1");
+  child.Start();
 
-  StartAndWaitForHandshake(&child);
+  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
 
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  helper->ReadData();
+  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
 
   KillAssertRunning(&child);
 
@@ -1314,7 +523,7 @@
   uint64_t total_freed = 0;
   for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
-        !packet.profile_packet().process_dumps().empty()) {
+        packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
       ASSERT_EQ(dumps.size(), 1u);
       const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
@@ -1336,31 +545,36 @@
 TEST_P(HeapprofdEndToEnd, DiscoverByName) {
   auto helper = GetHelper(&task_runner);
 
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(kStartupAllocSize));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::string("0"));
+  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);
 
-  StartAndWaitForHandshake(&child);
+  auto* ds_config = trace_config.add_data_sources()->mutable_config();
+  ds_config->set_name("android.heapprofd");
+
+  protos::gen::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());
+
+  base::Subprocess child({"/proc/self/exe"});
+  child.args.argv0_override = "heapprofd_continuous_malloc";
+  child.args.stdout_mode = base::Subprocess::kDevNull;
+  child.args.stderr_mode = base::Subprocess::kDevNull;
+  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC=1");
+  child.Start();
 
   // Wait to make sure process is fully initialized, so we do not accidentally
   // match it by the startup logic.
   sleep(1);
 
-  TraceConfig trace_config = MakeTraceConfig([this](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_process_cmdline("heapprofd_continuous_malloc");
-    cfg->add_heaps(allocator_name());
-  });
-  trace_config.set_duration_ms(5000);
-
   helper->StartTracing(trace_config);
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+
+  helper->ReadData();
+  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
 
   KillAssertRunning(&child);
 
@@ -1372,7 +586,7 @@
   uint64_t total_freed = 0;
   for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
-        !packet.profile_packet().process_dumps().empty()) {
+        packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
       ASSERT_EQ(dumps.size(), 1u);
       const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
@@ -1394,32 +608,37 @@
 TEST_P(HeapprofdEndToEnd, 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);
+
+  auto* ds_config = trace_config.add_data_sources()->mutable_config();
+  ds_config->set_name("android.heapprofd");
+
+  protos::gen::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());
+
   // Make sure the forked process does not get reparented to init.
   base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(kStartupAllocSize));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::string("0"));
-
-  StartAndWaitForHandshake(&child);
+  child.args.argv0_override = "heapprofd_continuous_malloc";
+  child.args.stdout_mode = base::Subprocess::kDevNull;
+  child.args.stderr_mode = base::Subprocess::kDevNull;
+  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC=1");
+  child.Start();
 
   // Wait to make sure process is fully initialized, so we do not accidentally
   // match it by the startup logic.
   sleep(1);
 
-  TraceConfig trace_config = MakeTraceConfig([this](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-    cfg->add_heaps(allocator_name());
-  });
-  trace_config.set_duration_ms(5000);
-
   helper->StartTracing(trace_config);
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+
+  helper->ReadData();
+  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
 
   KillAssertRunning(&child);
 
@@ -1431,7 +650,7 @@
   uint64_t total_freed = 0;
   for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
-        !packet.profile_packet().process_dumps().empty()) {
+        packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
       ASSERT_EQ(dumps.size(), 1u);
       const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
@@ -1451,274 +670,198 @@
 }
 
 TEST_P(HeapprofdEndToEnd, ReInit) {
-  constexpr size_t kSamplingInterval = 1;
+  constexpr size_t kFirstIterationBytes = 5;
+  constexpr size_t kSecondIterationBytes = 7;
 
-  // We cannot use base::Pipe because that assumes we want CLOEXEC.
-  // We do NOT want CLOEXEC as this gets used by the RunReInit in the child.
-  int signal_pipe[2];
-  int ack_pipe[2];
+  base::Pipe signal_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
+  base::Pipe ack_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
 
-  PERFETTO_CHECK(pipe(signal_pipe) == 0);  // NOLINT(android-cloexec-pipe)
-  PERFETTO_CHECK(pipe(ack_pipe) == 0);     // NOLINT(android-cloexec-pipe)
-
-  int cur_flags = fcntl(signal_pipe[0], F_GETFL, 0);
-  PERFETTO_CHECK(cur_flags >= 0);
-  PERFETTO_CHECK(fcntl(signal_pipe[0], F_SETFL, cur_flags | O_NONBLOCK) == 0);
-  cur_flags = fcntl(signal_pipe[1], F_GETFL, 0);
-  PERFETTO_CHECK(cur_flags >= 0);
-  PERFETTO_CHECK(fcntl(signal_pipe[1], F_SETFL, cur_flags | O_NONBLOCK) == 0);
-
-  int signal_pipe_rd = signal_pipe[0];
-  int signal_pipe_wr = signal_pipe[1];
-  int ack_pipe_rd = ack_pipe[0];
-  int ack_pipe_wr = ack_pipe[1];
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
+  base::Subprocess child;
+  int signal_pipe_rd = *signal_pipe.rd;
+  int ack_pipe_wr = *ack_pipe.wr;
   child.args.preserve_fds.push_back(signal_pipe_rd);
   child.args.preserve_fds.push_back(ack_pipe_wr);
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG1=" +
-                           std::to_string(signal_pipe_rd));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG2=" +
-                           std::to_string(ack_pipe_wr));
-  StartAndWaitForHandshake(&child);
+  child.args.entrypoint_for_testing = [signal_pipe_rd, ack_pipe_wr] {
+    // The Subprocess harness takes care of closing all the unused pipe ends.
+    size_t bytes = kFirstIterationBytes;
+    bool signalled = false;
+    for (;;) {
+      AllocateAndFree(bytes);
+      char buf[1];
+      if (!signalled && read(signal_pipe_rd, buf, sizeof(buf)) == 1) {
+        signalled = true;
+        close(signal_pipe_rd);
 
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
+        // make sure the client has noticed that the session has stopped
+        AllocateAndFree(bytes);
 
-  close(signal_pipe_rd);
-  close(ack_pipe_wr);
+        bytes = kSecondIterationBytes;
+        PERFETTO_CHECK(PERFETTO_EINTR(write(ack_pipe_wr, "1", 1)) == 1);
+        close(ack_pipe_wr);
+      }
+      usleep(10 * kMsToUs);
+    }
+    PERFETTO_FATAL("Should be unreachable");
+  };
+  child.Start();
+  auto pid = child.pid();
 
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-  });
+  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);
+
+  protos::gen::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);
-  WRITE_TRACE(helper->full_trace());
-
   PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kFirstIterationBytes);
+  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);
 
-  PERFETTO_CHECK(PERFETTO_EINTR(write(signal_pipe_wr, "1", 1)) == 1);
-  close(signal_pipe_wr);
+  PERFETTO_CHECK(PERFETTO_EINTR(write(*signal_pipe.wr, "1", 1)) == 1);
+  signal_pipe.wr.reset();
   char buf[1];
-  ASSERT_EQ(PERFETTO_EINTR(read(ack_pipe_rd, buf, sizeof(buf))), 1);
-  close(ack_pipe_rd);
+  ASSERT_EQ(PERFETTO_EINTR(read(*ack_pipe.rd, buf, sizeof(buf))), 1);
+  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");
-
-  // We must keep alive the original helper because it owns the service thread.
-  std::unique_ptr<TraceProcessorTestHelper> helper2 =
-      std::unique_ptr<TraceProcessorTestHelper>(
-          new TraceProcessorTestHelper(&task_runner));
-
-  helper2->ConnectConsumer();
-  helper2->WaitForConsumerConnect();
-  helper2->StartTracing(trace_config);
-  ReadAndWait(helper2.get());
-  WRITE_TRACE(helper2->trace());
-
-  PrintStats(helper2.get());
-  KillAssertRunning(&child);
-
-  ValidateHasSamples(helper2.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper2.get(), pid);
-  ValidateSampleSizes(helper2.get(), pid, kSecondIterationBytes);
-}
-
-TEST_P(HeapprofdEndToEnd, ReInitAfterInvalid) {
-  constexpr size_t kSamplingInterval = 1;
-
-  // We cannot use base::Pipe because that assumes we want CLOEXEC.
-  // We do NOT want CLOEXEC as this gets used by the RunReInit in the child.
-  int signal_pipe[2];
-  int ack_pipe[2];
-
-  PERFETTO_CHECK(pipe(signal_pipe) == 0);  // NOLINT(android-cloexec-pipe)
-  PERFETTO_CHECK(pipe(ack_pipe) == 0);     // NOLINT(android-cloexec-pipe)
-
-  int cur_flags = fcntl(signal_pipe[0], F_GETFL, 0);
-  PERFETTO_CHECK(cur_flags >= 0);
-  PERFETTO_CHECK(fcntl(signal_pipe[0], F_SETFL, cur_flags | O_NONBLOCK) == 0);
-  cur_flags = fcntl(signal_pipe[1], F_GETFL, 0);
-  PERFETTO_CHECK(cur_flags >= 0);
-  PERFETTO_CHECK(fcntl(signal_pipe[1], F_SETFL, cur_flags | O_NONBLOCK) == 0);
-
-  int signal_pipe_rd = signal_pipe[0];
-  int signal_pipe_wr = signal_pipe[1];
-  int ack_pipe_rd = ack_pipe[0];
-  int ack_pipe_wr = ack_pipe[1];
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.preserve_fds.push_back(signal_pipe_rd);
-  child.args.preserve_fds.push_back(ack_pipe_wr);
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG1=" +
-                           std::to_string(signal_pipe_rd));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_REINIT_ARG2=" +
-                           std::to_string(ack_pipe_wr));
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
-
-  close(signal_pipe_rd);
-  close(ack_pipe_wr);
-
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-  });
-
-  auto helper = Trace(trace_config);
-  WRITE_TRACE(helper->full_trace());
-
+  helper = Trace(trace_config);
   PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kFirstIterationBytes);
+  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(PERFETTO_EINTR(write(signal_pipe_wr, "1", 1)) == 1);
-  close(signal_pipe_wr);
-  char buf[1];
-  ASSERT_EQ(PERFETTO_EINTR(read(ack_pipe_rd, buf, sizeof(buf))), 1);
-  close(ack_pipe_rd);
-
-  // 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");
-
-  // We must keep alive the original helper because it owns the service thread.
-  std::unique_ptr<TraceProcessorTestHelper> helper2 =
-      std::unique_ptr<TraceProcessorTestHelper>(
-          new TraceProcessorTestHelper(&task_runner));
-
-  helper2->ConnectConsumer();
-  helper2->WaitForConsumerConnect();
-  helper2->StartTracing(trace_config);
-  ReadAndWait(helper2.get());
-
-  WRITE_TRACE(helper2->trace());
-
-  PrintStats(helper2.get());
   KillAssertRunning(&child);
-
-  ValidateHasSamples(helper2.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper2.get(), pid);
-  ValidateSampleSizes(helper2.get(), pid, kSecondIterationBytes);
 }
 
 TEST_P(HeapprofdEndToEnd, ConcurrentSession) {
   constexpr size_t kAllocSize = 1024;
-  constexpr size_t kSamplingInterval = 1;
 
-  base::Subprocess child = ForkContinuousAlloc(allocator_mode(), kAllocSize);
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
+  base::Subprocess child = ForkContinuousMalloc(kAllocSize);
+  const auto pid = child.pid();
 
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(kSamplingInterval);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-    ContinuousDump(cfg);
-  });
+  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);
+
+  protos::gen::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.mutable_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);
-
-  PERFETTO_LOG("Starting concurrent.");
-  std::unique_ptr<TraceProcessorTestHelper> helper_concurrent(
-      new TraceProcessorTestHelper(&task_runner));
-  helper_concurrent->ConnectConsumer();
-  helper_concurrent->WaitForConsumerConnect();
+  auto helper_concurrent = GetHelper(&task_runner);
   helper_concurrent->StartTracing(trace_config);
 
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  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);
 
-  ReadAndWait(helper_concurrent.get());
-  WRITE_TRACE(helper_concurrent->trace());
-  PrintStats(helper_concurrent.get());
+  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);
+
   KillAssertRunning(&child);
-
-  ValidateHasSamples(helper.get(), pid, allocator_name(), kSamplingInterval);
-  ValidateOnlyPID(helper.get(), pid);
-  ValidateSampleSizes(helper.get(), pid, kAllocSize);
-  ValidateRejectedConcurrent(helper.get(), pid, false);
-
-  ValidateOnlyPID(helper_concurrent.get(), pid);
-  ValidateRejectedConcurrent(helper_concurrent.get(), pid, true);
 }
 
 TEST_P(HeapprofdEndToEnd, NativeProfilingActiveAtProcessExit) {
   constexpr uint64_t kTestAllocSize = 128;
   base::Pipe start_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
+  base::Subprocess child;
   int start_pipe_wr = *start_pipe.wr;
-
-  base::Subprocess child({"/proc/self/exe"});
-  child.args.posix_argv0_override_for_testing = "heapprofd_continuous_malloc";
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG0=" +
-                           allocator_name());
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG1=" +
-                           std::to_string(kTestAllocSize));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG2=" +
-                           std::to_string(0));
-  child.args.env.push_back("HEAPPROFD_TESTING_RUN_MALLOC_ARG3=" +
-                           std::to_string(200));
   child.args.preserve_fds.push_back(start_pipe_wr);
-  child.args.posix_entrypoint_for_testing = [start_pipe_wr] {
+  child.args.entrypoint_for_testing = [start_pipe_wr] {
     PERFETTO_CHECK(PERFETTO_EINTR(write(start_pipe_wr, "1", 1)) == 1);
     PERFETTO_CHECK(close(start_pipe_wr) == 0 || errno == EINTR);
+
+    // The subprocess harness will take care of closing
+    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);
+    }
   };
-
-  StartAndWaitForHandshake(&child);
-
-  const uint64_t pid = static_cast<uint64_t>(child.pid());
+  child.Start();
+  auto pid = child.pid();
   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_data_source_stop_timeout_ms(10000);
+
+  auto* ds_config = trace_config.add_data_sources()->mutable_config();
+  ds_config->set_name("android.heapprofd");
+
+  protos::gen::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))), 1);
   start_pipe.rd.reset();
 
-  TraceConfig trace_config = MakeTraceConfig([this, pid](HeapprofdConfig* cfg) {
-    cfg->set_sampling_interval_bytes(1);
-    cfg->add_pid(pid);
-    cfg->add_heaps(allocator_name());
-  });
-  trace_config.set_duration_ms(5000);
-
   // Trace until child exits.
   helper->StartTracing(trace_config);
 
   // Wait for the child and assert that it exited successfully.
   EXPECT_TRUE(child.Wait(30000));
-  EXPECT_EQ(child.status(), base::Subprocess::kTerminated);
+  EXPECT_EQ(child.status(), base::Subprocess::kExited);
   EXPECT_EQ(child.returncode(), 0);
 
   // Assert that we did profile the process.
   helper->FlushAndWait(2000);
   helper->DisableTracing();
-  ReadAndWait(helper.get());
-  WRITE_TRACE(helper->full_trace());
+  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+  helper->ReadData();
+  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
 
   const auto& packets = helper->trace();
   ASSERT_GT(packets.size(), 0u);
@@ -1727,11 +870,11 @@
   uint64_t total_allocated = 0;
   for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
-        !packet.profile_packet().process_dumps().empty()) {
+        packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
       ASSERT_EQ(dumps.size(), 1u);
       const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
-      EXPECT_EQ(dump.pid(), pid);
+      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
         samples++;
@@ -1744,26 +887,13 @@
   EXPECT_GT(total_allocated, 0u);
 }
 
-// On in-tree Android, we use the system heapprofd in fork or central mode.
-// For Linux and out-of-tree Android, we statically include a copy of
-// heapprofd and use that. This one does not support intercepting malloc.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#if !PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-#error "Need to start daemons for Linux test."
-#endif
-
-INSTANTIATE_TEST_CASE_P(DISABLED_Run,
-                        HeapprofdEndToEnd,
-                        Values(std::make_tuple(TestMode::kStatic,
-                                               AllocatorMode::kCustom)),
-                        TestSuffix);
-#elif !PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-INSTANTIATE_TEST_CASE_P(
-    Run,
-    HeapprofdEndToEnd,
-    Values(std::make_tuple(TestMode::kCentral, AllocatorMode::kMalloc),
-           std::make_tuple(TestMode::kCentral, AllocatorMode::kCustom)),
-    TestSuffix);
+// 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
 
 }  // namespace
diff --git a/src/profiling/memory/heapprofd_preload.map.txt b/src/profiling/memory/heapprofd_preload.map.txt
deleted file mode 100644
index ca2ffbb..0000000
--- a/src/profiling/memory/heapprofd_preload.map.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  global:
-    malloc;
-    free;
-    calloc;
-    realloc;
-    posix_memalign;
-    aligned_alloc;
-    memalign;
-    pvalloc;
-    valloc;
-    reallocarray;
-  local:
-    *;
-};
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index dfc6922..267f300 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -17,8 +17,6 @@
 #include "src/profiling/memory/heapprofd_producer.h"
 
 #include <algorithm>
-#include <functional>
-#include <string>
 
 #include <inttypes.h>
 #include <signal.h>
@@ -26,30 +24,15 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/logging.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/thread_task_runner.h"
 #include "perfetto/ext/base/watchdog_posix.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/trace_writer.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 "perfetto/tracing/core/forward_decls.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "src/profiling/common/producer_support.h"
-#include "src/profiling/common/profiler_guardrails.h"
-#include "src/profiling/memory/shared_ring_buffer.h"
-#include "src/profiling/memory/unwound_messages.h"
-#include "src/profiling/memory/wire_protocol.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/system_properties.h>
-#endif
 
 namespace perfetto {
 namespace profiling {
@@ -76,8 +59,7 @@
                                                   size_t n) {
   std::vector<UnwindingWorker> ret;
   for (size_t i = 0; i < n; ++i) {
-    ret.emplace_back(delegate,
-                     base::ThreadTaskRunner::CreateAndStart("heapprofdunwind"));
+    ret.emplace_back(delegate, base::ThreadTaskRunner::CreateAndStart());
   }
   return ret;
 }
@@ -101,141 +83,77 @@
   return false;
 }
 
-
-bool IsFile(int fd, const char* fn) {
-  struct stat fdstat;
-  struct stat fnstat;
-  if (fstat(fd, &fdstat) == -1) {
-    PERFETTO_PLOG("fstat");
-    return false;
+// Return largest n such that pow(2, n) < value.
+size_t Log2LessThan(uint64_t value) {
+  size_t i = 0;
+  while (value) {
+    i++;
+    value >>= 1;
   }
-  if (lstat(fn, &fnstat) == -1) {
-    PERFETTO_PLOG("lstat");
-    return false;
-  }
-  return fdstat.st_ino == fnstat.st_ino;
-}
-
-protos::pbzero::ProfilePacket::ProcessHeapSamples::ClientError
-ErrorStateToProto(SharedRingBuffer::ErrorState state) {
-  switch (state) {
-    case (SharedRingBuffer::kNoError):
-      return protos::pbzero::ProfilePacket::ProcessHeapSamples::
-          CLIENT_ERROR_NONE;
-    case (SharedRingBuffer::kHitTimeout):
-      return protos::pbzero::ProfilePacket::ProcessHeapSamples::
-          CLIENT_ERROR_HIT_TIMEOUT;
-    case (SharedRingBuffer::kInvalidStackBounds):
-      return protos::pbzero::ProfilePacket::ProcessHeapSamples::
-          CLIENT_ERROR_INVALID_STACK_BOUNDS;
-  }
+  return i;
 }
 
 }  // namespace
 
-bool HeapprofdConfigToClientConfiguration(
-    const HeapprofdConfig& heapprofd_config,
-    ClientConfiguration* cli_config) {
-  cli_config->default_interval = heapprofd_config.sampling_interval_bytes();
-  cli_config->block_client = heapprofd_config.block_client();
-  cli_config->disable_fork_teardown = heapprofd_config.disable_fork_teardown();
-  cli_config->disable_vfork_detection =
-      heapprofd_config.disable_vfork_detection();
-  cli_config->block_client_timeout_us =
-      heapprofd_config.block_client_timeout_us();
-  cli_config->all_heaps = heapprofd_config.all_heaps();
-  cli_config->adaptive_sampling_shmem_threshold =
-      heapprofd_config.adaptive_sampling_shmem_threshold();
-  cli_config->adaptive_sampling_max_sampling_interval_bytes =
-      heapprofd_config.adaptive_sampling_max_sampling_interval_bytes();
-  size_t n = 0;
-  const std::vector<std::string>& exclude_heaps = heapprofd_config.exclude_heaps();
-  // heaps[i] and heaps_interval[i] represent that the heap named in heaps[i]
-  // should be sampled with sampling interval of heap_interval[i].
-  std::vector<std::string> heaps = heapprofd_config.heaps();
-  std::vector<uint64_t> heap_intervals =
-      heapprofd_config.heap_sampling_intervals();
-  if (heaps.empty() && !cli_config->all_heaps) {
-    heaps.push_back("libc.malloc");
-  }
+const uint64_t LogHistogram::kMaxBucket = 0;
 
-  if (heap_intervals.empty()) {
-    heap_intervals.assign(heaps.size(),
-                          heapprofd_config.sampling_interval_bytes());
+std::vector<std::pair<uint64_t, uint64_t>> LogHistogram::GetData() {
+  std::vector<std::pair<uint64_t, uint64_t>> data;
+  data.reserve(kBuckets);
+  for (size_t i = 0; i < kBuckets; ++i) {
+    if (i == kBuckets - 1)
+      data.emplace_back(kMaxBucket, values_[i]);
+    else
+      data.emplace_back(1 << i, values_[i]);
   }
-  if (heap_intervals.size() != heaps.size()) {
-    PERFETTO_ELOG("heap_sampling_intervals and heaps length mismatch.");
-    return false;
-  }
-  if (std::find(heap_intervals.begin(), heap_intervals.end(), 0u) !=
-      heap_intervals.end()) {
-    PERFETTO_ELOG("zero sampling interval.");
-    return false;
-  }
-  if (!exclude_heaps.empty()) {
-    // For disabled heaps, we add explicit entries but with sampling interval
-    // 0. The consumer of the sampling intervals in ClientConfiguration,
-    // GetSamplingInterval in wire_protocol.h, uses 0 to signal a heap is
-    // disabled, either because it isn't enabled (all_heaps is not set, and the
-    // heap isn't named), or because we explicitely set it here.
-    heaps.insert(heaps.end(), exclude_heaps.cbegin(), exclude_heaps.cend());
-    heap_intervals.insert(heap_intervals.end(), exclude_heaps.size(), 0u);
-  }
-  if (heaps.size() > base::ArraySize(cli_config->heaps)) {
-    heaps.resize(base::ArraySize(cli_config->heaps));
-    PERFETTO_ELOG("Too many heaps requested. Truncating.");
-  }
-  for (size_t i = 0; i < heaps.size(); ++i) {
-    const std::string& heap = heaps[i];
-    const uint64_t interval = heap_intervals[i];
-    // -1 for the \0 byte.
-    if (heap.size() > HEAPPROFD_HEAP_NAME_SZ - 1) {
-      PERFETTO_ELOG("Invalid heap name %s (larger than %d)", heap.c_str(),
-                    HEAPPROFD_HEAP_NAME_SZ - 1);
-      continue;
-    }
-    strncpy(&cli_config->heaps[n].name[0], heap.c_str(),
-            sizeof(cli_config->heaps[0].name));
-    cli_config->heaps[n].name[sizeof(cli_config->heaps[0].name) - 1] = '\0';
-    cli_config->heaps[n].interval = interval;
-    n++;
-  }
-  cli_config->num_heaps = n;
-  return true;
+  return data;
+}
+
+size_t LogHistogram::GetBucket(uint64_t value) {
+  if (value == 0)
+    return 0;
+
+  size_t hibit = Log2LessThan(value);
+  if (hibit >= kBuckets)
+    return kBuckets - 1;
+  return hibit;
 }
 
 // We create kUnwinderThreads unwinding threads. Bookkeeping is done on the main
 // thread.
 HeapprofdProducer::HeapprofdProducer(HeapprofdMode mode,
-                                     base::TaskRunner* task_runner,
-                                     bool exit_when_done)
+                                     base::TaskRunner* task_runner)
     : task_runner_(task_runner),
       mode_(mode),
-      exit_when_done_(exit_when_done),
       unwinding_workers_(MakeUnwindingWorkers(this, kUnwinderThreads)),
       socket_delegate_(this),
       weak_factory_(this) {
-  CheckDataSourceCpuTask();
-  CheckDataSourceMemoryTask();
+  CheckDataSourceMemory();  // Kick off guardrail task.
+  stat_fd_.reset(open("/proc/self/stat", O_RDONLY));
+  if (!stat_fd_) {
+    PERFETTO_ELOG(
+        "Failed to open /proc/self/stat. Cannot accept profiles "
+        "with CPU guardrails.");
+  } else {
+    CheckDataSourceCpu();  // Kick off guardrail task.
+  }
 }
 
 HeapprofdProducer::~HeapprofdProducer() = default;
 
 void HeapprofdProducer::SetTargetProcess(pid_t target_pid,
-                                         std::string target_cmdline) {
+                                         std::string target_cmdline,
+                                         base::ScopedFile inherited_socket) {
   target_process_.pid = target_pid;
   target_process_.cmdline = target_cmdline;
+  inherited_fd_ = std::move(inherited_socket);
 }
 
-void HeapprofdProducer::SetDataSourceCallback(std::function<void()> fn) {
-  data_source_callback_ = fn;
-}
-
-void HeapprofdProducer::AdoptSocket(base::ScopedFile fd) {
+void HeapprofdProducer::AdoptTargetProcessSocket() {
   PERFETTO_DCHECK(mode_ == HeapprofdMode::kChild);
   auto socket = base::UnixSocket::AdoptConnected(
-      std::move(fd), &socket_delegate_, task_runner_, base::SockFamily::kUnix,
-      base::SockType::kStream);
+      std::move(inherited_fd_), &socket_delegate_, task_runner_,
+      base::SockFamily::kUnix, base::SockType::kStream);
 
   HandleClientConnection(std::move(socket), target_process_);
 }
@@ -258,7 +176,7 @@
   PERFETTO_LOG("Disconnected from tracing service");
 
   // Do not attempt to reconnect if we're a process-private process, just quit.
-  if (exit_when_done_) {
+  if (mode_ == HeapprofdMode::kChild) {
     TerminateProcess(/*exit_status=*/1);  // does not return
   }
 
@@ -319,22 +237,38 @@
   // be error prone. What we do here is simply destroy the instance and
   // recreate it again.
 
-  // Oneshot producer should not attempt restarts.
-  if (exit_when_done_)
-    PERFETTO_FATAL("Attempting to restart a one shot producer.");
+  // Child mode producer should not attempt restarts. Note that this also means
+  // the rest of this method doesn't have to handle child-specific state.
+  if (mode_ == HeapprofdMode::kChild)
+    PERFETTO_FATAL("Attempting to restart a child mode producer.");
 
   HeapprofdMode mode = mode_;
   base::TaskRunner* task_runner = task_runner_;
   const char* socket_name = producer_sock_name_;
-  const bool exit_when_done = exit_when_done_;
 
   // Invoke destructor and then the constructor again.
   this->~HeapprofdProducer();
-  new (this) HeapprofdProducer(mode, task_runner, exit_when_done);
+  new (this) HeapprofdProducer(mode, task_runner);
 
   ConnectWithRetries(socket_name);
 }
 
+void HeapprofdProducer::ScheduleActiveDataSourceWatchdog() {
+  PERFETTO_DCHECK(mode_ == HeapprofdMode::kChild);
+
+  // Post the first check after a delay, to let the freshly forked heapprofd
+  // to receive the active data sources from traced. The checks will reschedule
+  // themselves from that point onwards.
+  auto weak_producer = weak_factory_.GetWeakPtr();
+  task_runner_->PostDelayedTask(
+      [weak_producer]() {
+        if (!weak_producer)
+          return;
+        weak_producer->ActiveDataSourceWatchdogCheck();
+      },
+      kChildModeWatchdogPeriodMs);
+}
+
 void HeapprofdProducer::ActiveDataSourceWatchdogCheck() {
   PERFETTO_DCHECK(mode_ == HeapprofdMode::kChild);
 
@@ -364,34 +298,14 @@
 __attribute__((noreturn)) void HeapprofdProducer::TerminateProcess(
     int exit_status) {
   PERFETTO_CHECK(mode_ == HeapprofdMode::kChild);
-  PERFETTO_LOG("Shutting down child heapprofd (status %d).", exit_status);
   exit(exit_status);
 }
 
 void HeapprofdProducer::OnTracingSetup() {}
 
-void HeapprofdProducer::WriteRejectedConcurrentSession(BufferID buffer_id,
-                                                       pid_t pid) {
-  auto trace_writer = endpoint_->CreateTraceWriter(buffer_id);
-  auto trace_packet = trace_writer->NewTracePacket();
-  trace_packet->set_timestamp(
-      static_cast<uint64_t>(base::GetBootTimeNs().count()));
-  auto profile_packet = trace_packet->set_profile_packet();
-  auto process_dump = profile_packet->add_process_dumps();
-  process_dump->set_pid(static_cast<uint64_t>(pid));
-  process_dump->set_rejected_concurrent(true);
-  trace_packet->Finalize();
-  trace_writer->Flush();
-}
-
 void HeapprofdProducer::SetupDataSource(DataSourceInstanceID id,
                                         const DataSourceConfig& ds_config) {
-  if (ds_config.session_initiator() ==
-      DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM) {
-    PERFETTO_LOG("Setting up datasource: statsd initiator.");
-  } else {
-    PERFETTO_LOG("Setting up datasource: non-statsd initiator.");
-  }
+  PERFETTO_DLOG("Setting up data source.");
   if (mode_ == HeapprofdMode::kChild && ds_config.enable_extra_guardrails()) {
     PERFETTO_ELOG("enable_extra_guardrails is not supported on user.");
     return;
@@ -437,14 +351,23 @@
 
       // Manually write one ProfilePacket about the rejected session.
       auto buffer_id = static_cast<BufferID>(ds_config.target_buffer());
-      WriteRejectedConcurrentSession(buffer_id, target_process_.pid);
+      auto trace_writer = endpoint_->CreateTraceWriter(buffer_id);
+      auto trace_packet = trace_writer->NewTracePacket();
+      trace_packet->set_timestamp(
+          static_cast<uint64_t>(base::GetBootTimeNs().count()));
+      auto profile_packet = trace_packet->set_profile_packet();
+      auto process_dump = profile_packet->add_process_dumps();
+      process_dump->set_pid(static_cast<uint64_t>(target_process_.pid));
+      process_dump->set_rejected_concurrent(true);
+      trace_packet->Finalize();
+      trace_writer->Flush();
       return;
     }
   }
 
   base::Optional<uint64_t> start_cputime_sec;
   if (heapprofd_config.max_heapprofd_cpu_secs() > 0) {
-    start_cputime_sec = GetCputimeSecForCurrentProcess();
+    start_cputime_sec = GetCputimeSec();
 
     if (!start_cputime_sec) {
       PERFETTO_ELOG("Failed to enforce CPU guardrail. Rejecting config.");
@@ -456,37 +379,48 @@
   DataSource data_source(endpoint_->CreateTraceWriter(buffer_id));
   data_source.id = id;
   auto& cli_config = data_source.client_configuration;
-  if (!HeapprofdConfigToClientConfiguration(heapprofd_config, &cli_config))
-    return;
+  cli_config.interval = heapprofd_config.sampling_interval_bytes();
+  cli_config.block_client = heapprofd_config.block_client();
+  cli_config.disable_fork_teardown = heapprofd_config.disable_fork_teardown();
+  cli_config.disable_vfork_detection =
+      heapprofd_config.disable_vfork_detection();
+  cli_config.block_client_timeout_us =
+      heapprofd_config.block_client_timeout_us();
   data_source.config = heapprofd_config;
-  data_source.ds_config = ds_config;
   data_source.normalized_cmdlines = std::move(normalized_cmdlines.value());
-  data_source.stop_timeout_ms = ds_config.stop_timeout_ms()
-                                    ? ds_config.stop_timeout_ms()
-                                    : 5000 /* kDataSourceStopTimeoutMs */;
-  data_source.guardrail_config.cpu_start_secs = start_cputime_sec;
-  data_source.guardrail_config.memory_guardrail_kb =
-      heapprofd_config.max_heapprofd_memory_kb();
-  data_source.guardrail_config.cpu_guardrail_sec =
-      heapprofd_config.max_heapprofd_cpu_secs();
+  data_source.stop_timeout_ms = ds_config.stop_timeout_ms();
+  data_source.start_cputime_sec = start_cputime_sec;
 
   InterningOutputTracker::WriteFixedInterningsPacket(
-      data_source.trace_writer.get(),
-      protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
+      data_source.trace_writer.get());
   data_sources_.emplace(id, std::move(data_source));
   PERFETTO_DLOG("Set up data source.");
 
-  if (mode_ == HeapprofdMode::kChild && data_source_callback_)
-    (*data_source_callback_)();
+  if (mode_ == HeapprofdMode::kChild)
+    AdoptTargetProcessSocket();
 }
 
 bool HeapprofdProducer::IsPidProfiled(pid_t pid) {
-  return std::any_of(
-      data_sources_.cbegin(), data_sources_.cend(),
-      [pid](const std::pair<const DataSourceInstanceID, DataSource>& p) {
-        const DataSource& ds = p.second;
-        return ds.process_states.count(pid) > 0;
-      });
+  for (const auto& pair : data_sources_) {
+    const DataSource& ds = pair.second;
+    if (ds.process_states.find(pid) != ds.process_states.cend())
+      return true;
+  }
+  return false;
+}
+
+base::Optional<uint64_t> HeapprofdProducer::GetCputimeSec() {
+  if (!stat_fd_) {
+    return base::nullopt;
+  }
+  lseek(stat_fd_.get(), 0, SEEK_SET);
+  base::ProcStat stat;
+  if (!ReadProcStat(stat_fd_.get(), &stat)) {
+    PERFETTO_ELOG("Failed to read stat file to enforce guardrails.");
+    return base::nullopt;
+  }
+  return (stat.utime + stat.stime) /
+         static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
 }
 
 void HeapprofdProducer::SetStartupProperties(DataSource* data_source) {
@@ -538,7 +472,7 @@
 
 void HeapprofdProducer::StartDataSource(DataSourceInstanceID id,
                                         const DataSourceConfig&) {
-  PERFETTO_DLOG("Starting data source %" PRIu64, id);
+  PERFETTO_DLOG("Start DataSource");
 
   auto it = data_sources_.find(id);
   if (it == data_sources_.end()) {
@@ -598,8 +532,6 @@
     return;
   }
 
-  PERFETTO_DLOG("Stopping data source %" PRIu64, id);
-
   DataSource& data_source = it->second;
   data_source.was_stopped = true;
   ShutdownDataSource(&data_source);
@@ -655,11 +587,8 @@
 
 void HeapprofdProducer::DoContinuousDump(DataSourceInstanceID id,
                                          uint32_t dump_interval) {
-  auto it = data_sources_.find(id);
-  if (it == data_sources_.end())
+  if (!DumpProcessesInDataSource(id))
     return;
-  DataSource& data_source = it->second;
-  DumpProcessesInDataSource(&data_source);
   auto weak_producer = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
       [weak_producer, id, dump_interval] {
@@ -670,95 +599,98 @@
       dump_interval);
 }
 
-// static
-void HeapprofdProducer::SetStats(
-    protos::pbzero::ProfilePacket::ProcessStats* stats,
-    const ProcessState& process_state) {
-  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);
-  stats->set_client_spinlock_blocked_us(
-      process_state.client_spinlock_blocked_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);
-  }
-}
-
 void HeapprofdProducer::DumpProcessState(DataSource* data_source,
                                          pid_t pid,
                                          ProcessState* process_state) {
-  for (auto& heap_id_and_heap_info : process_state->heap_infos) {
-    ProcessState::HeapInfo& heap_info = heap_id_and_heap_info.second;
+  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_info.heap_tracker.max_timestamp();
-    else
-      dump_timestamp = heap_info.heap_tracker.committed_timestamp();
+  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,
+                          data_source](
+                             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);
+    proto->set_hit_guardrail(data_source->hit_guardrail);
+    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);
+    }
+  };
 
-    const char* heap_name = nullptr;
-    if (!heap_info.heap_name.empty())
-      heap_name = heap_info.heap_name.c_str();
-    uint64_t sampling_interval = heap_info.sampling_interval;
-    uint64_t orig_sampling_interval = heap_info.orig_sampling_interval;
+  DumpState dump_state(data_source->trace_writer.get(),
+                       std::move(new_heapsamples), &data_source->intern_state);
 
-    auto new_heapsamples =
-        [pid, from_startup, dump_timestamp, process_state, data_source,
-         heap_name, sampling_interval,
-         orig_sampling_interval](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->error_state ==
-                                    SharedRingBuffer::kHitTimeout);
-          proto->set_client_error(
-              ErrorStateToProto(process_state->error_state));
-          proto->set_buffer_corrupted(process_state->buffer_corrupted);
-          proto->set_hit_guardrail(data_source->hit_guardrail);
-          if (heap_name)
-            proto->set_heap_name(heap_name);
-          proto->set_sampling_interval_bytes(sampling_interval);
-          proto->set_orig_sampling_interval_bytes(orig_sampling_interval);
-          auto* stats = proto->set_stats();
-          SetStats(stats, *process_state);
-        };
-
-    DumpState dump_state(data_source->trace_writer.get(),
-                         std::move(new_heapsamples),
-                         &data_source->intern_state);
-
-    heap_info.heap_tracker.GetCallstackAllocations(
-        [&dump_state,
-         &data_source](const HeapTracker::CallstackAllocations& alloc) {
-          dump_state.WriteAllocation(alloc, data_source->config.dump_at_max());
-        });
-    dump_state.DumpCallstacks(&callsites_);
+  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_);
 }
 
-void HeapprofdProducer::DumpProcessesInDataSource(DataSource* ds) {
+bool HeapprofdProducer::DumpProcessesInDataSource(DataSourceInstanceID id) {
+  auto it = data_sources_.find(id);
+  if (it == data_sources_.end()) {
+    PERFETTO_LOG(
+        "Data source not found (harmless if using continuous_dump_config).");
+    return false;
+  }
+  DataSource& data_source = it->second;
+
   for (std::pair<const pid_t, ProcessState>& pid_and_process_state :
-       ds->process_states) {
+       data_source.process_states) {
     pid_t pid = pid_and_process_state.first;
     ProcessState& process_state = pid_and_process_state.second;
-    DumpProcessState(ds, pid, &process_state);
+    DumpProcessState(&data_source, pid, &process_state);
   }
+
+  return true;
 }
 
 void HeapprofdProducer::DumpAll() {
-  PERFETTO_LOG("Received signal. Dumping all data sources.");
-  for (auto& id_and_data_source : data_sources_)
-    DumpProcessesInDataSource(&id_and_data_source.second);
+  for (const auto& id_and_data_source : data_sources_) {
+    if (!DumpProcessesInDataSource(id_and_data_source.first))
+      PERFETTO_DLOG("Failed to dump %" PRIu64, id_and_data_source.first);
+  }
 }
 
 void HeapprofdProducer::Flush(FlushRequestID flush_id,
@@ -810,7 +742,7 @@
 }
 
 void HeapprofdProducer::SocketDelegate::OnDisconnect(base::UnixSocket* self) {
-  auto it = producer_->pending_processes_.find(self->peer_pid_linux());
+  auto it = producer_->pending_processes_.find(self->peer_pid());
   if (it == producer_->pending_processes_.end()) {
     PERFETTO_DFATAL_OR_ELOG("Unexpected disconnect.");
     return;
@@ -824,7 +756,7 @@
     base::UnixSocket*,
     std::unique_ptr<base::UnixSocket> new_connection) {
   Process peer_process;
-  peer_process.pid = new_connection->peer_pid_linux();
+  peer_process.pid = new_connection->peer_pid();
   if (!GetCmdlineForPID(peer_process.pid, &peer_process.cmdline))
     PERFETTO_PLOG("Failed to get cmdline for %d", peer_process.pid);
 
@@ -833,7 +765,7 @@
 
 void HeapprofdProducer::SocketDelegate::OnDataAvailable(
     base::UnixSocket* self) {
-  auto it = producer_->pending_processes_.find(self->peer_pid_linux());
+  auto it = producer_->pending_processes_.find(self->peer_pid());
   if (it == producer_->pending_processes_.end()) {
     PERFETTO_DFATAL_OR_ELOG("Unexpected data.");
     return;
@@ -845,7 +777,9 @@
   char buf[1];
   self->Receive(buf, sizeof(buf), fds, base::ArraySize(fds));
 
-  static_assert(kHandshakeSize == 2, "change if and else if below.");
+  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.
   if (fds[kHandshakeMaps] && fds[kHandshakeMem]) {
     auto ds_it =
         producer_->data_sources_.find(pending_process.data_source_instance_id);
@@ -861,28 +795,25 @@
       return;
     }
 
-    std::string maps_file =
-        "/proc/" + std::to_string(self->peer_pid_linux()) + "/maps";
-    if (!IsFile(*fds[kHandshakeMaps], maps_file.c_str())) {
-      producer_->pending_processes_.erase(it);
-      PERFETTO_ELOG("Received invalid maps FD.");
-      return;
-    }
-
-    std::string mem_file =
-        "/proc/" + std::to_string(self->peer_pid_linux()) + "/mem";
-    if (!IsFile(*fds[kHandshakeMem], mem_file.c_str())) {
-      producer_->pending_processes_.erase(it);
-      PERFETTO_ELOG("Received invalid mem FD.");
-      return;
-    }
-
-    data_source.process_states.emplace(
-        std::piecewise_construct, std::forward_as_tuple(self->peer_pid_linux()),
+    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()));
 
-    PERFETTO_DLOG("%d: Received FDs.", self->peer_pid_linux());
+    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.");
+      }
+    }
+
+    PERFETTO_DLOG("%d: Received FDs.", self->peer_pid());
     int raw_fd = pending_process.shmem.fd();
     // TODO(fmayer): Full buffer could deadlock us here.
     if (!self->Send(&data_source.client_configuration,
@@ -901,17 +832,16 @@
     handoff_data.mem_fd = std::move(fds[kHandshakeMem]);
     handoff_data.shmem = std::move(pending_process.shmem);
     handoff_data.client_config = data_source.client_configuration;
-    handoff_data.stream_allocations = data_source.config.stream_allocations();
 
-    producer_->UnwinderForPID(self->peer_pid_linux())
+    producer_->UnwinderForPID(self->peer_pid())
         .PostHandoffSocket(std::move(handoff_data));
     producer_->pending_processes_.erase(it);
-  } else if (fds[kHandshakeMaps] || fds[kHandshakeMem]) {
-    PERFETTO_DFATAL_OR_ELOG("%d: Received partial FDs.",
-                            self->peer_pid_linux());
+  } else if (fds[kHandshakeMaps] || fds[kHandshakeMem] ||
+             fds[kHandshakePageIdle]) {
+    PERFETTO_DFATAL_OR_ELOG("%d: Received partial FDs.", self->peer_pid());
     producer_->pending_processes_.erase(it);
   } else {
-    PERFETTO_ELOG("%d: Received no FDs.", self->peer_pid_linux());
+    PERFETTO_ELOG("%d: Received no FDs.", self->peer_pid());
   }
 }
 
@@ -945,25 +875,11 @@
   }
   RecordOtherSourcesAsRejected(data_source, process);
 
-  // In fork mode, right now we check whether the target is not profileable
-  // in the client, because we cannot read packages.list there.
-  if (mode_ == HeapprofdMode::kCentral &&
-      !CanProfile(data_source->ds_config, new_connection->peer_uid_posix(),
-                  data_source->config.target_installed_by())) {
-    PERFETTO_ELOG("%d (%s) is not profileable.", process.pid,
-                  process.cmdline.c_str());
-    return;
-  }
-
   uint64_t shmem_size = data_source->config.shmem_size_bytes();
   if (!shmem_size)
     shmem_size = kDefaultShmemSize;
-  if (shmem_size > kMaxShmemSize) {
-    PERFETTO_LOG("Specified shared memory size of %" PRIu64
-                 " exceeds maximum size of %" PRIu64 ". Reducing.",
-                 shmem_size, kMaxShmemSize);
+  if (shmem_size > kMaxShmemSize)
     shmem_size = kMaxShmemSize;
-  }
 
   auto shmem = SharedRingBuffer::Create(static_cast<size_t>(shmem_size));
   if (!shmem || !shmem->is_valid()) {
@@ -971,7 +887,7 @@
     return;
   }
 
-  pid_t peer_pid = new_connection->peer_pid_linux();
+  pid_t peer_pid = new_connection->peer_pid();
   if (peer_pid != process.pid) {
     PERFETTO_DFATAL_OR_ELOG("Invalid PID connected.");
     return;
@@ -984,48 +900,29 @@
   pending_processes_.emplace(peer_pid, std::move(pending_process));
 }
 
-void HeapprofdProducer::PostAllocRecord(
-    UnwindingWorker* worker,
-    std::unique_ptr<AllocRecord> alloc_rec) {
+void HeapprofdProducer::PostAllocRecord(AllocRecord alloc_rec) {
   // Once we can use C++14, this should be std::moved into the lambda instead.
-  auto* raw_alloc_rec = alloc_rec.release();
+  AllocRecord* raw_alloc_rec = new AllocRecord(std::move(alloc_rec));
   auto weak_this = weak_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_this, raw_alloc_rec, worker] {
-    std::unique_ptr<AllocRecord> unique_alloc_ref =
-        std::unique_ptr<AllocRecord>(raw_alloc_rec);
-    if (weak_this) {
-      weak_this->HandleAllocRecord(unique_alloc_ref.get());
-      worker->ReturnAllocRecord(std::move(unique_alloc_ref));
-    }
-  });
-}
-
-void HeapprofdProducer::PostFreeRecord(UnwindingWorker*,
-                                       std::vector<FreeRecord> free_recs) {
-  // Once we can use C++14, this should be std::moved into the lambda instead.
-  std::vector<FreeRecord>* raw_free_recs =
-      new std::vector<FreeRecord>(std::move(free_recs));
-  auto weak_this = weak_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_this, raw_free_recs] {
-    if (weak_this) {
-      for (FreeRecord& free_rec : *raw_free_recs)
-        weak_this->HandleFreeRecord(std::move(free_rec));
-    }
-    delete raw_free_recs;
-  });
-}
-
-void HeapprofdProducer::PostHeapNameRecord(UnwindingWorker*,
-                                           HeapNameRecord rec) {
-  auto weak_this = weak_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_this, rec] {
+  task_runner_->PostTask([weak_this, raw_alloc_rec] {
     if (weak_this)
-      weak_this->HandleHeapNameRecord(rec);
+      weak_this->HandleAllocRecord(std::move(*raw_alloc_rec));
+    delete raw_alloc_rec;
   });
 }
 
-void HeapprofdProducer::PostSocketDisconnected(UnwindingWorker*,
-                                               DataSourceInstanceID ds_id,
+void HeapprofdProducer::PostFreeRecord(FreeRecord free_rec) {
+  // Once we can use C++14, this should be std::moved into the lambda instead.
+  FreeRecord* raw_free_rec = new FreeRecord(std::move(free_rec));
+  auto weak_this = weak_factory_.GetWeakPtr();
+  task_runner_->PostTask([weak_this, raw_free_rec] {
+    if (weak_this)
+      weak_this->HandleFreeRecord(std::move(*raw_free_rec));
+    delete raw_free_rec;
+  });
+}
+
+void HeapprofdProducer::PostSocketDisconnected(DataSourceInstanceID ds_id,
                                                pid_t pid,
                                                SharedRingBuffer::Stats stats) {
   auto weak_this = weak_factory_.GetWeakPtr();
@@ -1035,72 +932,59 @@
   });
 }
 
-void HeapprofdProducer::HandleAllocRecord(AllocRecord* alloc_rec) {
-  const AllocMetadata& alloc_metadata = alloc_rec->alloc_metadata;
-  auto it = data_sources_.find(alloc_rec->data_source_instance_id);
+void HeapprofdProducer::HandleAllocRecord(AllocRecord alloc_rec) {
+  const AllocMetadata& alloc_metadata = alloc_rec.alloc_metadata;
+  auto it = data_sources_.find(alloc_rec.data_source_instance_id);
   if (it == data_sources_.end()) {
     PERFETTO_LOG("Invalid data source in alloc record.");
     return;
   }
 
   DataSource& ds = it->second;
-  auto process_state_it = ds.process_states.find(alloc_rec->pid);
+  auto process_state_it = ds.process_states.find(alloc_rec.pid);
   if (process_state_it == ds.process_states.end()) {
     PERFETTO_LOG("Invalid PID in alloc record.");
     return;
   }
 
-  if (ds.config.stream_allocations()) {
-    auto packet = ds.trace_writer->NewTracePacket();
-    auto* streaming_alloc = packet->set_streaming_allocation();
-    streaming_alloc->add_address(alloc_metadata.alloc_address);
-    streaming_alloc->add_size(alloc_metadata.alloc_size);
-    streaming_alloc->add_sample_size(alloc_metadata.sample_size);
-    streaming_alloc->add_clock_monotonic_coarse_timestamp(
-        alloc_metadata.clock_monotonic_coarse_timestamp);
-    streaming_alloc->add_heap_id(alloc_metadata.heap_id);
-    streaming_alloc->add_sequence_number(alloc_metadata.sequence_number);
-    return;
-  }
-
   const auto& prefixes = ds.config.skip_symbol_prefix();
   if (!prefixes.empty()) {
-    for (unwindstack::FrameData& frame_data : alloc_rec->frames) {
-      const std::string& map = frame_data.map_name;
+    for (FrameData& frame_data : alloc_rec.frames) {
+      const std::string& map = frame_data.frame.map_name;
       if (std::find_if(prefixes.cbegin(), prefixes.cend(),
                        [&map](const std::string& prefix) {
                          return base::StartsWith(map, prefix);
                        }) != prefixes.cend()) {
-        frame_data.function_name = "FILTERED";
+        frame_data.frame.function_name = "FILTERED";
       }
     }
   }
 
   ProcessState& process_state = process_state_it->second;
-  HeapTracker& heap_tracker =
-      process_state.GetHeapTracker(alloc_rec->alloc_metadata.heap_id);
+  HeapTracker& heap_tracker = process_state.heap_tracker;
 
-  if (alloc_rec->error)
+  if (alloc_rec.error)
     process_state.unwinding_errors++;
-  if (alloc_rec->reparsed_map)
+  if (alloc_rec.reparsed_map)
     process_state.map_reparses++;
   process_state.heap_samples++;
-  process_state.unwinding_time_us.Add(alloc_rec->unwinding_time_us);
-  process_state.total_unwinding_time_us += alloc_rec->unwinding_time_us;
+  process_state.unwinding_time_us.Add(alloc_rec.unwinding_time_us);
+  process_state.total_unwinding_time_us += alloc_rec.unwinding_time_us;
 
   // abspc may no longer refer to the same functions, as we had to reparse
   // maps. Reset the cache.
-  if (alloc_rec->reparsed_map)
+  if (alloc_rec.reparsed_map)
     heap_tracker.ClearFrameCache();
 
-  heap_tracker.RecordMalloc(
-      alloc_rec->frames, alloc_rec->build_ids, alloc_metadata.alloc_address,
-      alloc_metadata.sample_size, alloc_metadata.alloc_size,
-      alloc_metadata.sequence_number,
-      alloc_metadata.clock_monotonic_coarse_timestamp);
+  heap_tracker.RecordMalloc(alloc_rec.frames, alloc_metadata.alloc_address,
+                            alloc_metadata.sample_size,
+                            alloc_metadata.alloc_size,
+                            alloc_metadata.sequence_number,
+                            alloc_metadata.clock_monotonic_coarse_timestamp);
 }
 
 void HeapprofdProducer::HandleFreeRecord(FreeRecord free_rec) {
+  const FreeBatch& free_batch = free_rec.free_batch;
   auto it = data_sources_.find(free_rec.data_source_instance_id);
   if (it == data_sources_.end()) {
     PERFETTO_LOG("Invalid data source in free record.");
@@ -1114,63 +998,20 @@
     return;
   }
 
-  if (ds.config.stream_allocations()) {
-    auto packet = ds.trace_writer->NewTracePacket();
-    auto* streaming_free = packet->set_streaming_free();
-    streaming_free->add_address(free_rec.entry.addr);
-    streaming_free->add_heap_id(free_rec.entry.heap_id);
-    streaming_free->add_sequence_number(free_rec.entry.sequence_number);
-    return;
-  }
-
   ProcessState& process_state = process_state_it->second;
+  HeapTracker& heap_tracker = process_state.heap_tracker;
 
-  const FreeEntry& entry = free_rec.entry;
-  HeapTracker& heap_tracker = process_state.GetHeapTracker(entry.heap_id);
-  heap_tracker.RecordFree(entry.addr, entry.sequence_number, 0);
-}
-
-void HeapprofdProducer::HandleHeapNameRecord(HeapNameRecord rec) {
-  auto it = data_sources_.find(rec.data_source_instance_id);
-  if (it == data_sources_.end()) {
-    PERFETTO_LOG("Invalid data source in free record.");
+  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.");
     return;
   }
-
-  DataSource& ds = it->second;
-  auto process_state_it = ds.process_states.find(rec.pid);
-  if (process_state_it == ds.process_states.end()) {
-    PERFETTO_LOG("Invalid PID in free record.");
-    return;
+  for (size_t i = 0; i < num_entries; ++i) {
+    const FreeBatchEntry& entry = entries[i];
+    heap_tracker.RecordFree(entry.addr, entry.sequence_number,
+                            free_batch.clock_monotonic_coarse_timestamp);
   }
-
-  ProcessState& process_state = process_state_it->second;
-  const HeapName& entry = rec.entry;
-  if (entry.heap_name[0] != '\0') {
-    std::string heap_name = entry.heap_name;
-    if (entry.heap_id == 0) {
-      PERFETTO_ELOG("Invalid zero heap ID.");
-      return;
-    }
-    ProcessState::HeapInfo& hi = process_state.GetHeapInfo(entry.heap_id);
-    if (!hi.heap_name.empty() && hi.heap_name != heap_name) {
-      PERFETTO_ELOG("Overriding heap name %s with %s", hi.heap_name.c_str(),
-                    heap_name.c_str());
-    }
-    hi.heap_name = entry.heap_name;
-  }
-  if (entry.sample_interval != 0) {
-    ProcessState::HeapInfo& hi = process_state.GetHeapInfo(entry.heap_id);
-    if (!hi.sampling_interval)
-      hi.orig_sampling_interval = entry.sample_interval;
-    hi.sampling_interval = entry.sample_interval;
-  }
-}
-
-void HeapprofdProducer::TerminateWhenDone() {
-  if (data_sources_.empty())
-    TerminateProcess(0);
-  exit_when_done_ = true;
 }
 
 bool HeapprofdProducer::MaybeFinishDataSource(DataSource* ds) {
@@ -1182,8 +1023,7 @@
   bool was_stopped = ds->was_stopped;
   DataSourceInstanceID ds_id = ds->id;
   auto weak_producer = weak_factory_.GetWeakPtr();
-  bool exit_when_done = exit_when_done_;
-  ds->trace_writer->Flush([weak_producer, exit_when_done, ds_id, was_stopped] {
+  ds->trace_writer->Flush([weak_producer, ds_id, was_stopped] {
     if (!weak_producer)
       return;
 
@@ -1191,7 +1031,7 @@
       weak_producer->endpoint_->NotifyDataSourceStopped(ds_id);
     weak_producer->data_sources_.erase(ds_id);
 
-    if (exit_when_done) {
+    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)
@@ -1214,18 +1054,12 @@
   DataSource& ds = it->second;
 
   auto process_state_it = ds.process_states.find(pid);
-  if (process_state_it == ds.process_states.end()) {
-    PERFETTO_ELOG("Unexpected disconnect from %d", pid);
+  if (process_state_it == ds.process_states.end())
     return;
-  }
-
-  PERFETTO_LOG("%d disconnected from heapprofd (ds shutting down: %d).", pid,
-               ds.shutting_down);
-
   ProcessState& process_state = process_state_it->second;
   process_state.disconnected = !ds.shutting_down;
-  process_state.error_state = stats.error_state;
-  process_state.client_spinlock_blocked_us = stats.client_spinlock_blocked_us;
+  process_state.buffer_overran =
+      stats.num_writes_overflow > 0 && !ds.config.block_client();
   process_state.buffer_corrupted =
       stats.num_writes_corrupt > 0 || stats.num_reads_corrupt > 0;
 
@@ -1234,39 +1068,89 @@
   MaybeFinishDataSource(&ds);
 }
 
-void HeapprofdProducer::CheckDataSourceCpuTask() {
+void HeapprofdProducer::CheckDataSourceCpu() {
   auto weak_producer = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
       [weak_producer] {
         if (!weak_producer)
           return;
-        weak_producer->CheckDataSourceCpuTask();
+        weak_producer->CheckDataSourceCpu();
       },
       kGuardrailIntervalMs);
 
-  ProfilerCpuGuardrails gr;
-  for (auto& p : data_sources_) {
-    DataSource& ds = p.second;
-    if (gr.IsOverCpuThreshold(ds.guardrail_config)) {
-      ds.hit_guardrail = true;
-      ShutdownDataSource(&ds);
+  bool any_guardrail = false;
+  for (auto& id_and_ds : data_sources_) {
+    DataSource& ds = id_and_ds.second;
+    if (ds.config.max_heapprofd_cpu_secs() > 0)
+      any_guardrail = true;
+  }
+
+  if (!any_guardrail)
+    return;
+
+  base::Optional<uint64_t> cputime_sec = GetCputimeSec();
+  if (!cputime_sec) {
+    PERFETTO_ELOG("Failed to get CPU time.");
+    return;
+  }
+
+  for (auto& id_and_ds : data_sources_) {
+    DataSource& ds = id_and_ds.second;
+    uint64_t ds_max_cpu = ds.config.max_heapprofd_cpu_secs();
+    if (ds_max_cpu > 0) {
+      // We reject data-sources with CPU guardrails if we cannot read the
+      // initial value.
+      PERFETTO_CHECK(ds.start_cputime_sec);
+      uint64_t cpu_diff = *cputime_sec - *ds.start_cputime_sec;
+      if (*cputime_sec > *ds.start_cputime_sec && cpu_diff > ds_max_cpu) {
+        PERFETTO_ELOG(
+            "Exceeded data-source CPU guardrail "
+            "(%" PRIu64 " > %" PRIu64 "). Shutting down.",
+            cpu_diff, ds_max_cpu);
+        ds.hit_guardrail = true;
+        ShutdownDataSource(&ds);
+      }
     }
   }
 }
 
-void HeapprofdProducer::CheckDataSourceMemoryTask() {
+void HeapprofdProducer::CheckDataSourceMemory() {
   auto weak_producer = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
       [weak_producer] {
         if (!weak_producer)
           return;
-        weak_producer->CheckDataSourceMemoryTask();
+        weak_producer->CheckDataSourceMemory();
       },
       kGuardrailIntervalMs);
-  ProfilerMemoryGuardrails gr;
-  for (auto& p : data_sources_) {
-    DataSource& ds = p.second;
-    if (gr.IsOverMemoryThreshold(ds.guardrail_config)) {
+
+  bool any_guardrail = false;
+  for (auto& id_and_ds : data_sources_) {
+    DataSource& ds = id_and_ds.second;
+    if (ds.config.max_heapprofd_memory_kb() > 0)
+      any_guardrail = true;
+  }
+
+  if (!any_guardrail)
+    return;
+
+  base::Optional<uint32_t> anon_and_swap;
+  base::Optional<std::string> status = ReadStatus(getpid());
+  if (status)
+    anon_and_swap = GetRssAnonAndSwap(*status);
+
+  if (!anon_and_swap) {
+    PERFETTO_ELOG("Failed to read heapprofd memory.");
+    return;
+  }
+
+  for (auto& id_and_ds : data_sources_) {
+    DataSource& ds = id_and_ds.second;
+    uint32_t ds_max_mem = ds.config.max_heapprofd_memory_kb();
+    if (ds_max_mem > 0 && *anon_and_swap > ds_max_mem) {
+      PERFETTO_ELOG("Exceeded data-source memory guardrail (%" PRIu32
+                    " > %" PRIu32 "). Shutting down.",
+                    *anon_and_swap, ds_max_mem);
       ds.hit_guardrail = true;
       ShutdownDataSource(&ds);
     }
diff --git a/src/profiling/memory/heapprofd_producer.h b/src/profiling/memory/heapprofd_producer.h
index b8e9c53..7cf3367 100644
--- a/src/profiling/memory/heapprofd_producer.h
+++ b/src/profiling/memory/heapprofd_producer.h
@@ -22,8 +22,6 @@
 #include <map>
 #include <vector>
 
-#include <inttypes.h>
-
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/unix_socket.h"
@@ -35,17 +33,13 @@
 #include "perfetto/ext/tracing/core/tracing_service.h"
 #include "perfetto/tracing/core/data_source_config.h"
 
-#include "perfetto/tracing/core/forward_decls.h"
 #include "src/profiling/common/interning_output.h"
 #include "src/profiling/common/proc_utils.h"
-#include "src/profiling/common/profiler_guardrails.h"
 #include "src/profiling/memory/bookkeeping.h"
 #include "src/profiling/memory/bookkeeping_dump.h"
-#include "src/profiling/memory/log_histogram.h"
-#include "src/profiling/memory/shared_ring_buffer.h"
+#include "src/profiling/memory/page_idle_checker.h"
 #include "src/profiling/memory/system_property.h"
 #include "src/profiling/memory/unwinding.h"
-#include "src/profiling/memory/unwound_messages.h"
 
 #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
 
@@ -59,15 +53,25 @@
   std::string cmdline;
 };
 
+class LogHistogram {
+ public:
+  static const uint64_t kMaxBucket;
+  static constexpr size_t kBuckets = 20;
+
+  void Add(uint64_t value) { values_[GetBucket(value)]++; }
+  std::vector<std::pair<uint64_t, uint64_t>> GetData();
+
+ private:
+  size_t GetBucket(uint64_t value);
+
+  std::array<uint64_t, kBuckets> values_ = {};
+};
+
 // TODO(rsavitski): central daemon can do less work if it knows that the global
 // operating mode is fork-based, as it then will not be interacting with the
 // clients. This can be implemented as an additional mode here.
 enum class HeapprofdMode { kCentral, kChild };
 
-bool HeapprofdConfigToClientConfiguration(
-    const HeapprofdConfig& heapprofd_config,
-    ClientConfiguration* cli_config);
-
 // Heap profiling producer. Can be instantiated in two modes, central and
 // child (also referred to as fork mode).
 //
@@ -95,8 +99,7 @@
   // Alternatively, find a better name for this.
   class SocketDelegate : public base::UnixSocket::EventListener {
    public:
-    explicit SocketDelegate(HeapprofdProducer* producer)
-        : producer_(producer) {}
+    SocketDelegate(HeapprofdProducer* producer) : producer_(producer) {}
 
     void OnDisconnect(base::UnixSocket* self) override;
     void OnNewIncomingConnection(
@@ -108,9 +111,7 @@
     HeapprofdProducer* producer_;
   };
 
-  HeapprofdProducer(HeapprofdMode mode,
-                    base::TaskRunner* task_runner,
-                    bool exit_when_done);
+  HeapprofdProducer(HeapprofdMode mode, base::TaskRunner* task_runner);
   ~HeapprofdProducer() override;
 
   // Producer Impl:
@@ -131,24 +132,27 @@
   void DumpAll();
 
   // UnwindingWorker::Delegate impl:
-  void PostAllocRecord(UnwindingWorker*, std::unique_ptr<AllocRecord>) override;
-  void PostFreeRecord(UnwindingWorker*, std::vector<FreeRecord>) override;
-  void PostHeapNameRecord(UnwindingWorker*, HeapNameRecord) override;
-  void PostSocketDisconnected(UnwindingWorker*,
-                              DataSourceInstanceID,
+  void PostAllocRecord(AllocRecord) override;
+  void PostFreeRecord(FreeRecord) override;
+  void PostSocketDisconnected(DataSourceInstanceID,
                               pid_t,
                               SharedRingBuffer::Stats) override;
 
-  void HandleAllocRecord(AllocRecord*);
+  void HandleAllocRecord(AllocRecord);
   void HandleFreeRecord(FreeRecord);
-  void HandleHeapNameRecord(HeapNameRecord);
   void HandleSocketDisconnected(DataSourceInstanceID,
                                 pid_t,
                                 SharedRingBuffer::Stats);
 
   // Valid only if mode_ == kChild.
-  void SetTargetProcess(pid_t target_pid, std::string target_cmdline);
-  void SetDataSourceCallback(std::function<void()> fn);
+  void SetTargetProcess(pid_t target_pid,
+                        std::string target_cmdline,
+                        base::ScopedFile inherited_socket);
+  // Valid only if mode_ == kChild. Kicks off a periodic check that the child
+  // heapprofd is actively working on a data source (which should correspond to
+  // the target process). The first check is delayed to let the freshly spawned
+  // producer get the data sources from the tracing service (i.e. traced).
+  void ScheduleActiveDataSourceWatchdog();
 
   // Exposed for testing.
   void SetProducerEndpoint(
@@ -158,13 +162,6 @@
     return socket_delegate_;
   }
 
-  // Adopts the (connected) sockets inherited from the target process, invoking
-  // the on-connection callback.
-  // Specific to mode_ == kChild
-  void AdoptSocket(base::ScopedFile fd);
-
-  void TerminateWhenDone();
-
  private:
   // State of the connection to tracing service (traced).
   enum State {
@@ -175,19 +172,10 @@
   };
 
   struct ProcessState {
-    struct HeapInfo {
-      HeapInfo(GlobalCallstackTrie* cs, bool dam) : heap_tracker(cs, dam) {}
-
-      HeapTracker heap_tracker;
-      std::string heap_name;
-      uint64_t sampling_interval = 0u;
-      uint64_t orig_sampling_interval = 0u;
-    };
-    ProcessState(GlobalCallstackTrie* c, bool d)
-        : callsites(c), dump_at_max_mode(d) {}
+    ProcessState(GlobalCallstackTrie* callsites, bool dump_at_max_mode)
+        : heap_tracker(callsites, dump_at_max_mode) {}
     bool disconnected = false;
-    SharedRingBuffer::ErrorState error_state =
-        SharedRingBuffer::ErrorState::kNoError;
+    bool buffer_overran = false;
     bool buffer_corrupted = false;
 
     uint64_t heap_samples = 0;
@@ -195,37 +183,17 @@
     uint64_t unwinding_errors = 0;
 
     uint64_t total_unwinding_time_us = 0;
-    uint64_t client_spinlock_blocked_us = 0;
-    GlobalCallstackTrie* callsites;
-    bool dump_at_max_mode;
     LogHistogram unwinding_time_us;
-    std::map<uint32_t, HeapInfo> heap_infos;
+    HeapTracker heap_tracker;
 
-    HeapInfo& GetHeapInfo(uint32_t heap_id) {
-      auto it = heap_infos.find(heap_id);
-      if (it == heap_infos.end()) {
-        std::tie(it, std::ignore) = heap_infos.emplace(
-            std::piecewise_construct, std::forward_as_tuple(heap_id),
-            std::forward_as_tuple(callsites, dump_at_max_mode));
-      }
-      return it->second;
-    }
-
-    HeapTracker& GetHeapTracker(uint32_t heap_id) {
-      return GetHeapInfo(heap_id).heap_tracker;
-    }
+    base::Optional<PageIdleChecker> page_idle_checker;
   };
 
   struct DataSource {
-    explicit DataSource(std::unique_ptr<TraceWriter> tw)
-        : trace_writer(std::move(tw)) {
-      // Make MSAN happy.
-      memset(&client_configuration, 0, sizeof(client_configuration));
-    }
+    DataSource(std::unique_ptr<TraceWriter> tw) : trace_writer(std::move(tw)) {}
 
     DataSourceInstanceID id;
     std::unique_ptr<TraceWriter> trace_writer;
-    DataSourceConfig ds_config;
     HeapprofdConfig config;
     ClientConfiguration client_configuration;
     std::vector<SystemProperties::Handle> properties;
@@ -239,7 +207,7 @@
     bool hit_guardrail = false;
     bool was_stopped = false;
     uint32_t stop_timeout_ms;
-    GuardrailConfig guardrail_config;
+    base::Optional<uint64_t> start_cputime_sec;
   };
 
   struct PendingProcess {
@@ -256,14 +224,14 @@
   void ResetConnectionBackoff();
   void IncreaseConnectionBackoff();
 
-  void CheckDataSourceMemoryTask();
-  void CheckDataSourceCpuTask();
+  base::Optional<uint64_t> GetCputimeSec();
+
+  void CheckDataSourceMemory();
+  void CheckDataSourceCpu();
 
   void FinishDataSourceFlush(FlushRequestID flush_id);
-  void DumpProcessesInDataSource(DataSource* ds);
+  bool DumpProcessesInDataSource(DataSourceInstanceID id);
   void DumpProcessState(DataSource* ds, pid_t pid, ProcessState* process);
-  static void SetStats(protos::pbzero::ProfilePacket::ProcessStats* stats,
-                       const ProcessState& process_state);
 
   void DoContinuousDump(DataSourceInstanceID id, uint32_t dump_interval);
 
@@ -279,21 +247,19 @@
   void TerminateProcess(int exit_status);
   // Specific to mode_ == kChild
   void ActiveDataSourceWatchdogCheck();
+  // Adopts the (connected) sockets inherited from the target process, invoking
+  // the on-connection callback.
+  // Specific to mode_ == kChild
+  void AdoptTargetProcessSocket();
 
   void ShutdownDataSource(DataSource* ds);
   bool MaybeFinishDataSource(DataSource* ds);
 
-  void WriteRejectedConcurrentSession(BufferID buffer_id, pid_t pid);
-
   // Class state:
 
   // Task runner is owned by the main thread.
   base::TaskRunner* const task_runner_;
   const HeapprofdMode mode_;
-  // TODO(fmayer): Refactor to make this boolean unnecessary.
-  // Whether to terminate this producer after the first data-source has
-  // finished.
-  bool exit_when_done_;
 
   // State of connection to the tracing service.
   State state_ = kNotStarted;
@@ -322,9 +288,13 @@
 
   // Specific to mode_ == kChild
   Process target_process_{base::kInvalidPid, ""};
-  base::Optional<std::function<void()>> data_source_callback_;
+  // This is a valid FD only between SetTargetProcess and
+  // AdoptTargetProcessSocket.
+  // Specific to mode_ == kChild
+  base::ScopedFile inherited_fd_;
 
   SocketDelegate socket_delegate_;
+  base::ScopedFile stat_fd_;
 
   base::WeakPtrFactory<HeapprofdProducer> weak_factory_;  // Keep last.
 };
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index fa08e95..dd5b0d1 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -16,8 +16,6 @@
 
 #include "src/profiling/memory/heapprofd_producer.h"
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/commit_data_request.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
@@ -28,8 +26,8 @@
 namespace profiling {
 
 using ::testing::Contains;
-using ::testing::Eq;
 using ::testing::Pair;
+using ::testing::Eq;
 using ::testing::Property;
 
 class MockProducerEndpoint : public TracingService::ProducerEndpoint {
@@ -70,8 +68,7 @@
 
 TEST(HeapprofdProducerTest, ExposesDataSource) {
   base::TestTaskRunner task_runner;
-  HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner,
-                             /* exit_when_done= */ false);
+  HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner);
 
   std::unique_ptr<MockProducerEndpoint> endpoint(new MockProducerEndpoint());
   EXPECT_CALL(*endpoint,
@@ -82,162 +79,5 @@
   producer.OnConnect();
 }
 
-TEST(HeapprofdConfigToClientConfigurationTest, Smoke) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.set_sampling_interval_bytes(4096);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, DefaultHeap) {
-  HeapprofdConfig cfg;
-  cfg.set_sampling_interval_bytes(4096);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "libc.malloc");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, TwoHeaps) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.add_heaps("bar");
-  cfg.set_sampling_interval_bytes(4096);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 2u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_STREQ(cli_config.heaps[1].name, "bar");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-  EXPECT_EQ(cli_config.heaps[1].interval, 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, TwoHeapsIntervals) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.add_heap_sampling_intervals(4096u);
-  cfg.add_heaps("bar");
-  cfg.add_heap_sampling_intervals(1u);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 2u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_STREQ(cli_config.heaps[1].name, "bar");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-  EXPECT_EQ(cli_config.heaps[1].interval, 1u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, OverflowHeapName) {
-  std::string large_name(100, 'a');
-  HeapprofdConfig cfg;
-  cfg.add_heaps(large_name);
-  cfg.set_sampling_interval_bytes(1);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 0u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, OverflowHeapNameAndValid) {
-  std::string large_name(100, 'a');
-  HeapprofdConfig cfg;
-  cfg.add_heaps(large_name);
-  cfg.add_heaps("foo");
-  cfg.set_sampling_interval_bytes(1);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, ZeroSampling) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.set_sampling_interval_bytes(0);
-  ClientConfiguration cli_config;
-  EXPECT_FALSE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, ZeroSamplingMultiple) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.add_heap_sampling_intervals(4096u);
-  cfg.add_heaps("bar");
-  cfg.add_heap_sampling_intervals(0);
-  ClientConfiguration cli_config;
-  EXPECT_FALSE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, AdaptiveSampling) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.set_sampling_interval_bytes(4096);
-  cfg.set_adaptive_sampling_shmem_threshold(1024u);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-  EXPECT_EQ(cli_config.adaptive_sampling_shmem_threshold, 1024u);
-  EXPECT_EQ(cli_config.adaptive_sampling_max_sampling_interval_bytes, 0u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, AdaptiveSamplingWithMax) {
-  HeapprofdConfig cfg;
-  cfg.add_heaps("foo");
-  cfg.set_sampling_interval_bytes(4096);
-  cfg.set_adaptive_sampling_shmem_threshold(1024u);
-  cfg.set_adaptive_sampling_max_sampling_interval_bytes(4 * 4096u);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_EQ(cli_config.heaps[0].interval, 4096u);
-  EXPECT_EQ(cli_config.adaptive_sampling_shmem_threshold, 1024u);
-  EXPECT_EQ(cli_config.adaptive_sampling_max_sampling_interval_bytes,
-            4 * 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, AllHeaps) {
-  HeapprofdConfig cfg;
-  cfg.set_all_heaps(true);
-  cfg.set_sampling_interval_bytes(4096);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 0u);
-  EXPECT_EQ(cli_config.default_interval, 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndExplicit) {
-  HeapprofdConfig cfg;
-  cfg.set_all_heaps(true);
-  cfg.set_sampling_interval_bytes(4096);
-  cfg.add_heaps("foo");
-  cfg.add_heap_sampling_intervals(1024u);
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_EQ(cli_config.heaps[0].interval, 1024u);
-  EXPECT_EQ(cli_config.default_interval, 4096u);
-}
-
-TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndDisabled) {
-  HeapprofdConfig cfg;
-  cfg.set_all_heaps(true);
-  cfg.set_sampling_interval_bytes(4096);
-  cfg.add_exclude_heaps("foo");
-  ClientConfiguration cli_config;
-  ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config));
-  EXPECT_EQ(cli_config.num_heaps, 1u);
-  EXPECT_STREQ(cli_config.heaps[0].name, "foo");
-  EXPECT_EQ(cli_config.heaps[0].interval, 0u);
-  EXPECT_EQ(cli_config.default_interval, 4096u);
-}
-
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/heapprofd_standalone_client_example.cc b/src/profiling/memory/heapprofd_standalone_client_example.cc
deleted file mode 100644
index ccae01b..0000000
--- a/src/profiling/memory/heapprofd_standalone_client_example.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/heap_profile.h"
-
-#include <unistd.h>
-
-namespace {
-
-void OtherFn(uint32_t heap_id, uint64_t i) {
-  AHeapProfile_reportAllocation(heap_id, i, i);
-}
-
-}  // namespace
-
-int main(int, char**) {
-  uint32_t heap_id = AHeapProfile_registerHeap(AHeapInfo_create("test"));
-  for (uint64_t i = 0; i < 100000; ++i) {
-    OtherFn(heap_id, i);
-    sleep(1);
-  }
-}
diff --git a/src/profiling/memory/include/perfetto/heap_profile.h b/src/profiling/memory/include/perfetto/heap_profile.h
deleted file mode 100644
index 8f03a63..0000000
--- a/src/profiling/memory/include/perfetto/heap_profile.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// API to report allocations to heapprofd. This allows users to see the
-// callstacks causing these allocations in heap profiles.
-//
-// In the context of this API, a "heap" is memory associated with an allocator.
-// An example of an allocator is the malloc-family of libc functions (malloc /
-// calloc / posix_memalign).
-//
-// A very simple custom allocator would look like this:
-//
-// void* my_malloc(size_t size) {
-//   void* ptr = [code to somehow allocate get size bytes];
-//   return ptr;
-// }
-//
-// void my_free(void* ptr) {
-//   [code to somehow free ptr]
-// }
-//
-// To find out where in a program these two functions get called, we instrument
-// the allocator using this API:
-//
-// static uint32_t g_heap_id =
-//   AHeapProfile_registerHeap(AHeapInfo_create("invalid.example"));
-//
-// void* my_malloc(size_t size) {
-//   void* ptr = [code to somehow allocate get size bytes];
-//   AHeapProfile_reportAllocation(g_heap_id, static_cast<uintptr_t>(ptr),
-//                                 size);
-//   return ptr;
-// }
-//
-// void my_free(void* ptr) {
-//   AHeapProfile_reportFree(g_heap_id, static_cast<uintptr_t>(ptr));
-//   [code to somehow free ptr]
-// }
-//
-// This will allow users to get a flamegraph of the callstacks calling into
-// these functions.
-//
-// See https://perfetto.dev/docs/data-sources/native-heap-profiler for more
-// information on heapprofd in general.
-
-#ifndef SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
-#define SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#pragma GCC diagnostic push
-
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wnullability-extension"
-#else
-#define _Nullable
-#define _Nonnull
-#endif
-
-// Maximum size of heap name, including NUL-byte.
-#define HEAPPROFD_HEAP_NAME_SZ 64
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct AHeapInfo AHeapInfo;
-typedef struct AHeapProfileEnableCallbackInfo AHeapProfileEnableCallbackInfo;
-typedef struct AHeapProfileDisableCallbackInfo AHeapProfileDisableCallbackInfo;
-
-// Get sampling interval (in bytes) of the profiling session that was started.
-uint64_t AHeapProfileEnableCallbackInfo_getSamplingInterval(
-    const AHeapProfileEnableCallbackInfo* _Nonnull session_info);
-
-// Create new AHeapInfo, a struct describing a heap.
-//
-// Takes name of the heap, up to 64 bytes including null terminator. To
-// guarantee uniqueness, this should include the caller's domain name,
-// e.g. "dev.perfetto.largeobjects".
-//
-// On error, returns NULL.
-// Errors are:
-//  * Empty or too long (larger than 64 bytes including null terminator)
-//    heap_name.
-//  * Too many heaps have been registered in this process already.
-//
-// Must eventually be passed to AHeapProfile_registerHeap.
-AHeapInfo* _Nullable AHeapInfo_create(const char* _Nonnull heap_name);
-
-// Set enabled callback in AHeapInfo.
-//
-// If info is NULL, do nothing.
-//
-// After this AHeapInfo is registered via AHeapProfile_registerHeap,
-// this callback is called when profiling of the heap is requested.
-AHeapInfo* _Nullable AHeapInfo_setEnabledCallback(
-    AHeapInfo* _Nullable info,
-    void (*_Nonnull callback)(
-        void* _Nullable,
-        const AHeapProfileEnableCallbackInfo* _Nonnull session_info),
-    void* _Nullable data);
-
-// Set disabled callback in AHeapInfo.
-//
-// If info is NULL, do nothing.
-//
-// After this AHeapInfo is registered via AHeapProfile_registerHeap,
-// this callback is called when profiling of the heap ends.
-AHeapInfo* _Nullable AHeapInfo_setDisabledCallback(
-    AHeapInfo* _Nullable info,
-    void (*_Nonnull callback)(
-        void* _Nullable,
-        const AHeapProfileDisableCallbackInfo* _Nonnull session_info),
-    void* _Nullable data);
-
-// Register heap described in AHeapInfo.
-//
-// If info is NULL, return a no-op heap_id.
-//
-// The returned heap_id can be used in AHeapProfile_reportAllocation and
-// AHeapProfile_reportFree.
-//
-// Takes ownership of |info|.
-uint32_t AHeapProfile_registerHeap(AHeapInfo* _Nullable info);
-
-// Reports an allocation of |size| on the given |heap_id|.
-//
-// The |alloc_id| needs to be a unique identifier for the allocation, and can
-// can be used in AHeapProfile_reportFree to report the allocation has been
-// freed.
-//
-// If a profiling session is active, this function decides whether the reported
-// allocation should be sampled. If the allocation is sampled, it will be
-// associated to the current callstack in the profile.
-//
-// Returns whether the allocation was sampled.
-bool AHeapProfile_reportAllocation(uint32_t heap_id,
-                                   uint64_t alloc_id,
-                                   uint64_t size);
-
-// Reports a sample of |size| on the given |heap_id|.
-//
-// If a profiling session is active, this function associates the sample with
-// the current callstack in the profile.
-//
-// Returns whether the profiling session was active.
-//
-// THIS IS GENERALLY NOT WHAT YOU WANT. THIS IS ONLY NEEDED IF YOU NEED TO
-// DO THE SAMPLING YOURSELF FOR PERFORMANCE REASONS.
-// USE AHeapProfile_reportAllocation TO REPORT AN ALLOCATION AND LET
-// HEAPPROFD DO THE SAMPLING.
-//
-// TODO(fmayer): Make this unavailable to non-Mainline.
-bool AHeapProfile_reportSample(uint32_t heap_id,
-                               uint64_t alloc_id,
-                               uint64_t size);
-
-// Report allocation was freed on the given heap.
-//
-// If |alloc_id| was sampled in a previous call to
-// AHeapProfile_reportAllocation, this allocation is marked as freed in the
-// profile.
-//
-// It is allowed to call with an |alloc_id| that was either not sampled or never
-// passed to AHeapProfile_reportAllocation, in which case the call will not
-// change the output.
-void AHeapProfile_reportFree(uint32_t heap_id, uint64_t alloc_id);
-
-#ifdef __cplusplus
-}
-#endif
-
-#pragma GCC diagnostic pop
-
-#endif  // SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
diff --git a/src/profiling/memory/java_hprof.h b/src/profiling/memory/java_hprof.h
new file mode 100644
index 0000000..2e1d5f6
--- /dev/null
+++ b/src/profiling/memory/java_hprof.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_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
index aef9b5b..4d015c2 100644
--- a/src/profiling/memory/java_hprof_producer.cc
+++ b/src/profiling/memory/java_hprof_producer.cc
@@ -17,12 +17,10 @@
 #include "src/profiling/memory/java_hprof_producer.h"
 
 #include <signal.h>
-#include <limits>
 
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "src/profiling/common/proc_utils.h"
-#include "src/profiling/common/producer_support.h"
 
 namespace perfetto {
 namespace profiling {
@@ -56,32 +54,9 @@
 void JavaHprofProducer::SignalDataSource(const DataSource& ds) {
   const std::set<pid_t>& pids = ds.pids;
   for (pid_t pid : pids) {
-    auto opt_status = ReadStatus(pid);
-    if (!opt_status) {
-      PERFETTO_PLOG("Failed to read /proc/%d/status. Not signalling.", pid);
-      continue;
-    }
-    auto uids = GetUids(*opt_status);
-    if (!uids) {
-      PERFETTO_ELOG(
-          "Failed to read Uid from /proc/%d/status. "
-          "Not signalling.",
-          pid);
-      continue;
-    }
-    if (!CanProfile(ds.ds_config, uids->effective,
-                    ds.config.target_installed_by())) {
-      PERFETTO_ELOG("%d (UID %" PRIu64 ") not profileable.", pid,
-                    uids->effective);
-      continue;
-    }
     PERFETTO_DLOG("Sending %d to %d", kJavaHeapprofdSignal, pid);
-    union sigval signal_value;
-    signal_value.sival_int =
-        static_cast<int32_t>(ds.ds_config.tracing_session_id() %
-                             std::numeric_limits<int32_t>::max());
-    if (sigqueue(pid, kJavaHeapprofdSignal, signal_value) != 0) {
-      PERFETTO_DPLOG("sigqueue");
+    if (kill(pid, kJavaHeapprofdSignal) != 0) {
+      PERFETTO_DPLOG("kill");
     }
   }
 }
@@ -119,7 +94,6 @@
     RemoveUnderAnonThreshold(config.min_anonymous_memory_kb(), &ds.pids);
 
   ds.config = std::move(config);
-  ds.ds_config = std::move(ds_config);
   data_sources_.emplace(id, std::move(ds));
 }
 
diff --git a/src/profiling/memory/java_hprof_producer.h b/src/profiling/memory/java_hprof_producer.h
index 97ac07d..d584f44 100644
--- a/src/profiling/memory/java_hprof_producer.h
+++ b/src/profiling/memory/java_hprof_producer.h
@@ -23,14 +23,12 @@
 
 #include "perfetto/ext/base/unix_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 "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 "perfetto/tracing/core/forward_decls.h"
 #include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
 
 namespace perfetto {
@@ -40,7 +38,7 @@
 
 class JavaHprofProducer : public Producer {
  public:
-  explicit JavaHprofProducer(base::TaskRunner* task_runner)
+  JavaHprofProducer(base::TaskRunner* task_runner)
       : task_runner_(task_runner), weak_factory_(this) {}
 
   // Producer Impl:
@@ -73,7 +71,6 @@
     DataSourceInstanceID id;
     std::set<pid_t> pids;
     JavaHprofConfig config;
-    DataSourceConfig ds_config;
   };
 
   void ConnectService();
diff --git a/src/profiling/memory/log_histogram.cc b/src/profiling/memory/log_histogram.cc
deleted file mode 100644
index 3db734f..0000000
--- a/src/profiling/memory/log_histogram.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/memory/log_histogram.h"
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#include <utility>
-#include <vector>
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-// Return largest n such that pow(2, n) < value.
-size_t Log2LessThan(uint64_t value) {
-  size_t i = 0;
-  while (value) {
-    i++;
-    value >>= 1;
-  }
-  return i;
-}
-
-}  // namespace
-
-const uint64_t LogHistogram::kMaxBucket = 0;
-
-std::vector<std::pair<uint64_t, uint64_t>> LogHistogram::GetData() const {
-  std::vector<std::pair<uint64_t, uint64_t>> data;
-  data.reserve(kBuckets);
-  for (size_t i = 0; i < kBuckets; ++i) {
-    if (i == kBuckets - 1)
-      data.emplace_back(kMaxBucket, values_[i]);
-    else
-      data.emplace_back(1 << i, values_[i]);
-  }
-  return data;
-}
-
-size_t LogHistogram::GetBucket(uint64_t value) {
-  if (value == 0)
-    return 0;
-
-  size_t hibit = Log2LessThan(value);
-  if (hibit >= kBuckets)
-    return kBuckets - 1;
-  return hibit;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/log_histogram.h b/src/profiling/memory/log_histogram.h
deleted file mode 100644
index 9b16b86..0000000
--- a/src/profiling/memory/log_histogram.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_MEMORY_LOG_HISTOGRAM_H_
-#define SRC_PROFILING_MEMORY_LOG_HISTOGRAM_H_
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#include <array>
-#include <utility>
-#include <vector>
-
-namespace perfetto {
-namespace profiling {
-
-class LogHistogram {
- public:
-  static const uint64_t kMaxBucket;
-  static constexpr size_t kBuckets = 20;
-
-  void Add(uint64_t value) { values_[GetBucket(value)]++; }
-  std::vector<std::pair<uint64_t, uint64_t>> GetData() const;
-
- private:
-  size_t GetBucket(uint64_t value);
-
-  std::array<uint64_t, kBuckets> values_ = {};
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_LOG_HISTOGRAM_H_
diff --git a/src/profiling/memory/main.cc b/src/profiling/memory/main.cc
index f0bb47b..ff5ac97 100644
--- a/src/profiling/memory/main.cc
+++ b/src/profiling/memory/main.cc
@@ -20,10 +20,10 @@
 #include <memory>
 #include <vector>
 
+#include <getopt.h>
 #include <signal.h>
 
 #include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/watchdog.h"
@@ -41,6 +41,9 @@
 namespace profiling {
 namespace {
 
+int StartChildHeapprofd(pid_t target_pid,
+                        std::string target_cmdline,
+                        base::ScopedFile inherited_sock_fd);
 int StartCentralHeapprofd();
 
 int GetListeningSocket() {
@@ -59,17 +62,42 @@
 
 int HeapprofdMain(int argc, char** argv) {
   bool cleanup_crash = false;
+  pid_t target_pid = base::kInvalidPid;
+  std::string target_cmdline;
+  base::ScopedFile inherited_sock_fd;
 
   enum { kCleanupCrash = 256, kTargetPid, kTargetCmd, kInheritFd };
-  static option long_options[] = {
+  static struct option long_options[] = {
       {"cleanup-after-crash", no_argument, nullptr, kCleanupCrash},
+      {"exclusive-for-pid", required_argument, nullptr, kTargetPid},
+      {"exclusive-for-cmdline", required_argument, nullptr, kTargetCmd},
+      {"inherit-socket-fd", required_argument, nullptr, kInheritFd},
       {nullptr, 0, nullptr, 0}};
+  int option_index;
   int c;
-  while ((c = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
+  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
     switch (c) {
       case kCleanupCrash:
         cleanup_crash = true;
         break;
+      case kTargetPid:
+        if (target_pid != base::kInvalidPid)
+          PERFETTO_FATAL("Duplicate exclusive-for-pid");
+        target_pid = static_cast<pid_t>(atoi(optarg));
+        break;
+      case kTargetCmd:  // assumed to be already normalized
+        if (!target_cmdline.empty())
+          PERFETTO_FATAL("Duplicate exclusive-for-cmdline");
+        target_cmdline = std::string(optarg);
+        break;
+      case kInheritFd:  // repetition not supported
+        if (inherited_sock_fd)
+          PERFETTO_FATAL("Duplicate inherit-socket-fd");
+        inherited_sock_fd = base::ScopedFile(atoi(optarg));
+        break;
+      default:
+        PERFETTO_ELOG("Usage: %s [--cleanup-after-crash]", argv[0]);
+        return 1;
     }
   }
 
@@ -85,10 +113,42 @@
     return 0;
   }
 
-  // start as a central daemon.
+  // If |target_pid| is given, we're supposed to be operating as a private
+  // heapprofd for that process. Note that we might not be a direct child due to
+  // reparenting.
+  bool tpid_set = target_pid != base::kInvalidPid;
+  bool tcmd_set = !target_cmdline.empty();
+  bool fds_set = !!inherited_sock_fd;
+  if (tpid_set || tcmd_set || fds_set) {
+    if (!tpid_set || !tcmd_set || !fds_set) {
+      PERFETTO_ELOG(
+          "If starting in child mode, requires all of: {--exclusive-for-pid, "
+          "--exclusive-for-cmdline, --inherit_socket_fd}");
+      return 1;
+    }
+
+    return StartChildHeapprofd(target_pid, target_cmdline,
+                               std::move(inherited_sock_fd));
+  }
+
+  // Otherwise start as a central daemon.
   return StartCentralHeapprofd();
 }
 
+int StartChildHeapprofd(pid_t target_pid,
+                        std::string target_cmdline,
+                        base::ScopedFile inherited_sock_fd) {
+  base::UnixTaskRunner task_runner;
+  base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
+  HeapprofdProducer producer(HeapprofdMode::kChild, &task_runner);
+  producer.SetTargetProcess(target_pid, target_cmdline,
+                            std::move(inherited_sock_fd));
+  producer.ConnectWithRetries(GetProducerSocket());
+  producer.ScheduleActiveDataSourceWatchdog();
+  task_runner.Run();
+  return 0;
+}
+
 int StartCentralHeapprofd() {
   // We set this up before launching any threads, so we do not have to use a
   // std::atomic for g_dump_evt.
@@ -96,8 +156,7 @@
 
   base::UnixTaskRunner task_runner;
   base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
-  HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner,
-                             /* exit_when_done= */ false);
+  HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner);
 
   int listening_raw_socket = GetListeningSocket();
   auto listening_socket = base::UnixSocket::Listen(
diff --git a/src/profiling/memory/malloc_hooks.cc b/src/profiling/memory/malloc_hooks.cc
new file mode 100644
index 0000000..d2c3894
--- /dev/null
+++ b/src/profiling/memory/malloc_hooks.cc
@@ -0,0 +1,699 @@
+/*
+ * 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 <android/fdsan.h>
+#include <bionic/malloc.h>
+#include <inttypes.h>
+#include <malloc.h>
+#include <private/bionic_malloc_dispatch.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/system_properties.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <tuple>
+
+#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 "src/profiling/common/proc_utils.h"
+#include "src/profiling/memory/client.h"
+#include "src/profiling/memory/scoped_spinlock.h"
+#include "src/profiling/memory/unhooked_allocator.h"
+#include "src/profiling/memory/wire_protocol.h"
+
+using perfetto::profiling::ScopedSpinlock;
+using perfetto::profiling::UnhookedAllocator;
+
+// This is so we can make an so that we can swap out with the existing
+// libc_malloc_hooks.so
+#ifndef HEAPPROFD_PREFIX
+#define HEAPPROFD_PREFIX heapprofd
+#endif
+
+#define HEAPPROFD_ADD_PREFIX(name) \
+  PERFETTO_BUILDFLAG_CAT(HEAPPROFD_PREFIX, name)
+
+#pragma GCC visibility push(default)
+extern "C" {
+
+bool HEAPPROFD_ADD_PREFIX(_initialize)(const MallocDispatch* malloc_dispatch,
+                                       bool* zygote_child,
+                                       const char* options);
+void HEAPPROFD_ADD_PREFIX(_finalize)();
+void HEAPPROFD_ADD_PREFIX(_dump_heap)(const char* file_name);
+void HEAPPROFD_ADD_PREFIX(_get_malloc_leak_info)(uint8_t** info,
+                                                 size_t* overall_size,
+                                                 size_t* info_size,
+                                                 size_t* total_memory,
+                                                 size_t* backtrace_size);
+bool HEAPPROFD_ADD_PREFIX(_write_malloc_leak_info)(FILE* fp);
+ssize_t HEAPPROFD_ADD_PREFIX(_malloc_backtrace)(void* pointer,
+                                                uintptr_t* frames,
+                                                size_t frame_count);
+void HEAPPROFD_ADD_PREFIX(_free_malloc_leak_info)(uint8_t* info);
+size_t HEAPPROFD_ADD_PREFIX(_malloc_usable_size)(void* pointer);
+void* HEAPPROFD_ADD_PREFIX(_malloc)(size_t size);
+void HEAPPROFD_ADD_PREFIX(_free)(void* pointer);
+void* HEAPPROFD_ADD_PREFIX(_aligned_alloc)(size_t alignment, size_t size);
+void* HEAPPROFD_ADD_PREFIX(_memalign)(size_t alignment, size_t bytes);
+void* HEAPPROFD_ADD_PREFIX(_realloc)(void* pointer, size_t bytes);
+void* HEAPPROFD_ADD_PREFIX(_calloc)(size_t nmemb, size_t bytes);
+struct mallinfo HEAPPROFD_ADD_PREFIX(_mallinfo)();
+int HEAPPROFD_ADD_PREFIX(_mallopt)(int param, int value);
+int HEAPPROFD_ADD_PREFIX(_malloc_info)(int options, FILE* fp);
+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);
+void HEAPPROFD_ADD_PREFIX(_malloc_disable)();
+void HEAPPROFD_ADD_PREFIX(_malloc_enable)();
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+void* HEAPPROFD_ADD_PREFIX(_pvalloc)(size_t bytes);
+void* HEAPPROFD_ADD_PREFIX(_valloc)(size_t size);
+#endif
+}
+#pragma GCC visibility pop
+
+namespace {
+
+// The real malloc function pointers we get in initialize. Set once in the first
+// initialize invocation, and never changed afterwards. Because bionic does a
+// release write after initialization and an acquire read to retrieve the hooked
+// malloc functions, we can use relaxed memory mode for both writing and
+// reading.
+std::atomic<const MallocDispatch*> g_dispatch{nullptr};
+
+// Holds the active profiling client. Is empty at the start, or after we've
+// started shutting down a profiling session. Hook invocations take shared_ptr
+// copies (ensuring that the client stays alive until no longer needed), and do
+// nothing if this master pointer is empty.
+//
+// This shared_ptr itself is protected by g_client_lock. Note that shared_ptr
+// handles are not thread-safe by themselves:
+// https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
+//
+// To avoid on-destruction re-entrancy issues, this shared_ptr needs to be
+// constructed with an allocator that uses the unhooked malloc & free functions.
+// See UnhookedAllocator.
+//
+// NoDestructor<> wrapper is used to avoid destructing the shared_ptr at program
+// exit. The rationale is:
+// * Avoiding the atexit destructor racing against other threads that are
+//   possibly running within the hooks.
+// * Making sure that atexit handlers running after this global's destructor
+//   can still safely enter the hooks.
+perfetto::base::NoDestructor<std::shared_ptr<perfetto::profiling::Client>>
+    g_client;
+
+// Protects g_client, and serves as an external lock for sampling decisions (see
+// perfetto::profiling::Sampler).
+//
+// We rely on this atomic's destuction being a nop, as it is possible for the
+// hooks to attempt to acquire the spinlock after its destructor should have run
+// (technically a use-after-destruct scenario).
+std::atomic<bool> g_client_lock{false};
+
+constexpr char kHeapprofdBinPath[] = "/system/bin/heapprofd";
+
+const MallocDispatch* GetDispatch() {
+  return g_dispatch.load(std::memory_order_relaxed);
+}
+
+int CloneWithoutSigchld() {
+  auto ret = clone(nullptr, nullptr, 0, nullptr);
+  if (ret == 0)
+    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+  return ret;
+}
+
+int ForklikeClone() {
+  auto ret = clone(nullptr, nullptr, SIGCHLD, nullptr);
+  if (ret == 0)
+    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+  return ret;
+}
+
+// Like daemon(), but using clone to avoid invoking pthread_atfork(3) handlers.
+int Daemonize() {
+  switch (ForklikeClone()) {
+    case -1:
+      PERFETTO_PLOG("Daemonize.clone");
+      return -1;
+      break;
+    case 0:
+      break;
+    default:
+      _exit(0);
+      break;
+  }
+  if (setsid() == -1) {
+    PERFETTO_PLOG("Daemonize.setsid");
+    return -1;
+  }
+  // best effort chdir & fd close
+  chdir("/");
+  int fd = open("/dev/null", O_RDWR, 0);
+  if (fd != -1) {
+    dup2(fd, STDIN_FILENO);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+    if (fd > STDERR_FILENO)
+      close(fd);
+  }
+  return 0;
+}
+
+// Called only if |g_client_lock| acquisition fails, which shouldn't happen
+// unless we're in a completely unexpected state (which we won't know how to
+// recover from). Tries to abort (SIGABRT) the whole process to serve as an
+// explicit indication of a bug.
+//
+// Doesn't use PERFETTO_FATAL as that is a single attempt to self-signal (in
+// practice - SIGTRAP), while abort() tries to make sure the process has
+// exited one way or another.
+__attribute__((noreturn, noinline)) void AbortOnSpinlockTimeout() {
+  PERFETTO_ELOG(
+      "Timed out on the spinlock - something is horribly wrong. "
+      "Aborting whole process.");
+  abort();
+}
+
+std::string ReadSystemProperty(const char* key) {
+  std::string prop_value;
+  const prop_info* prop = __system_property_find(key);
+  if (!prop) {
+    return prop_value;  // empty
+  }
+  __system_property_read_callback(
+      prop,
+      [](void* cookie, const char* name, const char* value, uint32_t) {
+        std::string* prop_value = reinterpret_cast<std::string*>(cookie);
+        *prop_value = value;
+      },
+      &prop_value);
+  return prop_value;
+}
+
+bool ForceForkPrivateDaemon() {
+  // Note: if renaming the property, also update system_property.cc
+  std::string mode = ReadSystemProperty("heapprofd.userdebug.mode");
+  return mode == "fork";
+}
+
+std::shared_ptr<perfetto::profiling::Client> CreateClientForCentralDaemon(
+    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
+  PERFETTO_LOG("Constructing client for central daemon.");
+  using perfetto::profiling::Client;
+
+  perfetto::base::Optional<perfetto::base::UnixSocketRaw> sock =
+      Client::ConnectToHeapprofd(perfetto::profiling::kHeapprofdSocketFile);
+  if (!sock) {
+    PERFETTO_ELOG("Failed to connect to %s. This is benign on user builds.",
+                  perfetto::profiling::kHeapprofdSocketFile);
+    return nullptr;
+  }
+  return Client::CreateAndHandshake(std::move(sock.value()),
+                                    unhooked_allocator);
+}
+
+std::shared_ptr<perfetto::profiling::Client> CreateClientAndPrivateDaemon(
+    UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
+  PERFETTO_LOG("Setting up fork mode profiling.");
+  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);
+
+  if (!parent_sock || !child_sock) {
+    PERFETTO_PLOG("Failed to create socketpair.");
+    return nullptr;
+  }
+
+  child_sock.RetainOnExec();
+
+  // Record own pid and cmdline, to pass down to the forked heapprofd.
+  pid_t target_pid = getpid();
+  std::string target_cmdline;
+  if (!perfetto::profiling::GetCmdlineForPID(target_pid, &target_cmdline)) {
+    target_cmdline = "failed-to-read-cmdline";
+    PERFETTO_ELOG(
+        "Failed to read own cmdline, proceeding as this might be a by-pid "
+        "profiling request (which will still work).");
+  }
+
+  // Prepare arguments for heapprofd.
+  std::string pid_arg =
+      std::string("--exclusive-for-pid=") + std::to_string(target_pid);
+  std::string cmd_arg =
+      std::string("--exclusive-for-cmdline=") + target_cmdline;
+  std::string fd_arg =
+      std::string("--inherit-socket-fd=") + std::to_string(child_sock.fd());
+  const char* argv[] = {kHeapprofdBinPath, pid_arg.c_str(), cmd_arg.c_str(),
+                        fd_arg.c_str(), nullptr};
+
+  // Use fork-like clone to avoid invoking the host's pthread_atfork(3)
+  // handlers. Also avoid sending the current process a SIGCHILD to further
+  // reduce our interference.
+  pid_t clone_pid = CloneWithoutSigchld();
+  if (clone_pid == -1) {
+    PERFETTO_PLOG("Failed to clone.");
+    return nullptr;
+  }
+  if (clone_pid == 0) {  // child
+    // Daemonize clones again, terminating the calling thread (i.e. the direct
+    // child of the original process). So the rest of this codepath will be
+    // executed in a new reparented process.
+    if (Daemonize() == -1) {
+      PERFETTO_PLOG("Daemonization failed.");
+      _exit(1);
+    }
+    execv(kHeapprofdBinPath, const_cast<char**>(argv));
+    PERFETTO_PLOG("Failed to execute private heapprofd.");
+    _exit(1);
+  }  // else - parent continuing the client setup
+
+  child_sock.ReleaseFd().reset();  // close child socket's fd
+  if (!parent_sock.SetTxTimeout(perfetto::profiling::kClientSockTimeoutMs)) {
+    PERFETTO_PLOG("Failed to set socket transmit timeout.");
+    return nullptr;
+  }
+
+  if (!parent_sock.SetRxTimeout(perfetto::profiling::kClientSockTimeoutMs)) {
+    PERFETTO_PLOG("Failed to set socket receive timeout.");
+    return nullptr;
+  }
+
+  // Wait on the immediate child to exit (allow for ECHILD in the unlikely case
+  // we're in a process that has made its children unwaitable).
+  int unused = 0;
+  if (PERFETTO_EINTR(waitpid(clone_pid, &unused, __WCLONE)) == -1 &&
+      errno != ECHILD) {
+    PERFETTO_PLOG("Failed to waitpid on immediate child.");
+    return nullptr;
+  }
+
+  return perfetto::profiling::Client::CreateAndHandshake(std::move(parent_sock),
+                                                         unhooked_allocator);
+}
+
+// Note: android_mallopt(M_RESET_HOOKS) is mutually exclusive with
+// heapprofd_initialize. Concurrent calls get discarded, which might be our
+// unpatching attempt if there is a concurrent re-initialization running due to
+// a new signal.
+//
+// Note: g_client can be reset by heapprofd_initialize without calling this
+// function.
+void ShutdownLazy() {
+  ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+  if (PERFETTO_UNLIKELY(!s.locked()))
+    AbortOnSpinlockTimeout();
+
+  if (!g_client.ref())  // other invocation already initiated shutdown
+    return;
+
+  // Clear primary shared pointer, such that later hook invocations become nops.
+  g_client.ref().reset();
+
+  if (!android_mallopt(M_RESET_HOOKS, nullptr, 0))
+    PERFETTO_PLOG("Unpatching heapprofd hooks failed.");
+}
+
+// We're a library loaded into a potentially-multithreaded process, which might
+// not be explicitly aware of this possiblity. Deadling with forks/clones is
+// extremely complicated in such situations, but we attempt to handle certain
+// cases.
+//
+// There are two classes of forking processes to consider:
+//  * well-behaved processes that fork only when their threads (if any) are at a
+//    safe point, and therefore not in the middle of our hooks/client.
+//  * processes that fork with other threads in an arbitrary state. Though
+//    technically buggy, such processes exist in practice.
+//
+// This atfork handler follows a crude lowest-common-denominator approach, where
+// to handle the latter class of processes, we systematically leak any |Client|
+// state (present only when actively profiling at the time of fork) in the
+// postfork-child path.
+//
+// The alternative with acquiring all relevant locks in the prefork handler, and
+// releasing the state postfork handlers, poses a separate class of edge cases,
+// and is not deemed to be better as a result.
+//
+// Notes:
+// * this atfork handler fires only for the |fork| libc entrypoint, *not*
+//   |clone|. See client.cc's |IsPostFork| for some best-effort detection
+//   mechanisms for clone/vfork.
+// * it should be possible to start a new profiling session in this child
+//   process, modulo the bionic's heapprofd-loading state machine being in the
+//   right state.
+// * we cannot avoid leaks in all cases anyway (e.g. during shutdown sequence,
+//   when only individual straggler threads hold onto the Client).
+void AtForkChild() {
+  PERFETTO_LOG("heapprofd_client: handling atfork.");
+
+  // A thread (that has now disappeared across the fork) could have been holding
+  // the spinlock. We're now the only thread post-fork, so we can reset the
+  // spinlock, though the state it protects (the |g_client| shared_ptr) might
+  // not be in a consistent state.
+  g_client_lock.store(false);
+
+  // Leak the existing shared_ptr contents, including the profiling |Client| if
+  // profiling was active at the time of the fork.
+  // Note: this code assumes that the creation of the empty shared_ptr does not
+  // allocate, which should be the case for all implementations as the
+  // constructor has to be noexcept.
+  std::shared_ptr<perfetto::profiling::Client>& ref = g_client.ref();
+  new (&ref) std::shared_ptr<perfetto::profiling::Client>();
+}
+
+}  // namespace
+
+// Setup for the rest of profiling. The first time profiling is triggered in a
+// process, this is called after this client library is dlopened, but before the
+// rest of the hooks are patched in. However, as we support multiple profiling
+// sessions within a process' lifetime, this function can also be legitimately
+// called any number of times afterwards (note: bionic guarantees that at most
+// one initialize call is active at a time).
+//
+// Note: if profiling is triggered at runtime, this runs on a dedicated pthread
+// (which is safe to block). If profiling is triggered at startup, then this
+// code runs synchronously.
+bool HEAPPROFD_ADD_PREFIX(_initialize)(const MallocDispatch* malloc_dispatch,
+                                       bool*,
+                                       const char*) {
+  using ::perfetto::profiling::Client;
+
+  // Table of pointers to backing implementation.
+  bool first_init = g_dispatch.load() == nullptr;
+  g_dispatch.store(malloc_dispatch);
+
+  // Install an atfork handler to deal with *some* cases of the host forking.
+  // The handler will be unpatched automatically if we're dlclosed.
+  if (first_init && pthread_atfork(/*prepare=*/nullptr, /*parent=*/nullptr,
+                                   &AtForkChild) != 0) {
+    PERFETTO_PLOG("%s: pthread_atfork failed, not installing hooks.",
+                  getprogname());
+    return false;
+  }
+
+  // TODO(fmayer): Check other destructions of client and make a decision
+  // whether we want to ban heap objects in the client or not.
+  std::shared_ptr<Client> old_client;
+  {
+    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+    if (PERFETTO_UNLIKELY(!s.locked()))
+      AbortOnSpinlockTimeout();
+
+    if (g_client.ref()) {
+      PERFETTO_LOG("%s: Rejecting concurrent profiling initialization.",
+                   getprogname());
+      return true;  // success as we're in a valid state
+    }
+    old_client = g_client.ref();
+    g_client.ref().reset();
+  }
+
+  old_client.reset();
+
+  // The dispatch table never changes, so let the custom allocator retain the
+  // function pointers directly.
+  UnhookedAllocator<Client> unhooked_allocator(malloc_dispatch->malloc,
+                                               malloc_dispatch->free);
+
+  // These factory functions use heap objects, so we need to run them without
+  // the spinlock held.
+  std::shared_ptr<Client> client;
+  if (!ForceForkPrivateDaemon())
+    client = CreateClientForCentralDaemon(unhooked_allocator);
+  if (!client)
+    client = CreateClientAndPrivateDaemon(unhooked_allocator);
+
+  if (!client) {
+    PERFETTO_LOG("%s: heapprofd_client not initialized, not installing hooks.",
+                 getprogname());
+    return false;
+  }
+  PERFETTO_LOG("%s: heapprofd_client initialized.", getprogname());
+  {
+    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+    if (PERFETTO_UNLIKELY(!s.locked()))
+      AbortOnSpinlockTimeout();
+
+    // This cannot have been set in the meantime. There are never two concurrent
+    // calls to this function, as Bionic uses atomics to guard against that.
+    PERFETTO_DCHECK(g_client.ref() == nullptr);
+    g_client.ref() = std::move(client);
+  }
+  return true;
+}
+
+void HEAPPROFD_ADD_PREFIX(_finalize)() {
+  // At the time of writing, invoked only as an atexit handler. We don't have
+  // any specific action to take, and cleanup can be left to the OS.
+}
+
+// Decides whether an allocation with the given address and size needs to be
+// sampled, and if so, records it. Performs the necessary synchronization (holds
+// |g_client_lock| spinlock) while accessing the shared sampler, and obtaining a
+// profiling client handle (shared_ptr).
+//
+// If the allocation is to be sampled, the recording is done without holding
+// |g_client_lock|. The client handle is guaranteed to not be invalidated while
+// the allocation is being recorded.
+//
+// If the attempt to record the allocation fails, initiates lazy shutdown of the
+// client & hooks.
+static void MaybeSampleAllocation(size_t size, void* addr) {
+  size_t sampled_alloc_sz = 0;
+  std::shared_ptr<perfetto::profiling::Client> client;
+  {
+    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+    if (PERFETTO_UNLIKELY(!s.locked()))
+      AbortOnSpinlockTimeout();
+
+    if (!g_client.ref())  // no active client (most likely shutting down)
+      return;
+
+    sampled_alloc_sz = g_client.ref()->GetSampleSizeLocked(size);
+    if (sampled_alloc_sz == 0)  // not sampling
+      return;
+
+    client = g_client.ref();  // owning copy
+  }                           // unlock
+
+  if (!client->RecordMalloc(sampled_alloc_sz, size,
+                            reinterpret_cast<uint64_t>(addr))) {
+    ShutdownLazy();
+  }
+}
+
+void* HEAPPROFD_ADD_PREFIX(_malloc)(size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  void* addr = dispatch->malloc(size);
+  MaybeSampleAllocation(size, addr);
+  return addr;
+}
+
+void* HEAPPROFD_ADD_PREFIX(_calloc)(size_t nmemb, size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  void* addr = dispatch->calloc(nmemb, size);
+  MaybeSampleAllocation(nmemb * size, addr);
+  return addr;
+}
+
+void* HEAPPROFD_ADD_PREFIX(_aligned_alloc)(size_t alignment, size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  void* addr = dispatch->aligned_alloc(alignment, size);
+  MaybeSampleAllocation(size, addr);
+  return addr;
+}
+
+void* HEAPPROFD_ADD_PREFIX(_memalign)(size_t alignment, size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  void* addr = dispatch->memalign(alignment, size);
+  MaybeSampleAllocation(size, addr);
+  return addr;
+}
+
+int HEAPPROFD_ADD_PREFIX(_posix_memalign)(void** memptr,
+                                          size_t alignment,
+                                          size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  int res = dispatch->posix_memalign(memptr, alignment, size);
+  if (res != 0)
+    return res;
+
+  MaybeSampleAllocation(size, *memptr);
+  return 0;
+}
+
+// Note: we record the free before calling the backing implementation to make
+// sure that the address is not reused before we've processed the deallocation
+// (which includes assigning a sequence id to it).
+void HEAPPROFD_ADD_PREFIX(_free)(void* pointer) {
+  // free on a nullptr is valid but has no effect. Short circuit here, for
+  // various advantages:
+  // * More efficient
+  // * Notably printf calls free(nullptr) even when it is used in a way
+  //   malloc-free way, as it unconditionally frees the pointer even if
+  //   it was never written to.
+  //   Short circuiting here makes it less likely to accidentally build
+  //   infinite recursion.
+  if (pointer == nullptr)
+    return;
+
+  const MallocDispatch* dispatch = GetDispatch();
+  std::shared_ptr<perfetto::profiling::Client> client;
+  {
+    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+    if (PERFETTO_UNLIKELY(!s.locked()))
+      AbortOnSpinlockTimeout();
+
+    client = g_client.ref();  // owning copy (or empty)
+  }
+
+  if (client) {
+    if (!client->RecordFree(reinterpret_cast<uint64_t>(pointer)))
+      ShutdownLazy();
+  }
+  return dispatch->free(pointer);
+}
+
+// Approach to recording realloc: under the initial lock, get a safe copy of the
+// client, and make the sampling decision in advance. Then record the
+// deallocation, call the real realloc, and finally record the sample if one is
+// necessary.
+//
+// As with the free, we record the deallocation before calling the backing
+// implementation to make sure the address is still exclusive while we're
+// processing it.
+void* HEAPPROFD_ADD_PREFIX(_realloc)(void* pointer, size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+
+  size_t sampled_alloc_sz = 0;
+  std::shared_ptr<perfetto::profiling::Client> client;
+  {
+    ScopedSpinlock s(&g_client_lock, ScopedSpinlock::Mode::Try);
+    if (PERFETTO_UNLIKELY(!s.locked()))
+      AbortOnSpinlockTimeout();
+
+    // If there is no active client, we still want to reach the backing realloc,
+    // so keep going.
+    if (g_client.ref()) {
+      client = g_client.ref();  // owning copy
+      sampled_alloc_sz = g_client.ref()->GetSampleSizeLocked(size);
+    }
+  }  // unlock
+
+  if (client && pointer) {
+    if (!client->RecordFree(reinterpret_cast<uint64_t>(pointer)))
+      ShutdownLazy();
+  }
+  void* addr = dispatch->realloc(pointer, size);
+
+  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,
+                            reinterpret_cast<uint64_t>(addr))) {
+    ShutdownLazy();
+  }
+  return addr;
+}
+
+void HEAPPROFD_ADD_PREFIX(_dump_heap)(const char*) {}
+
+void HEAPPROFD_ADD_PREFIX(
+    _get_malloc_leak_info)(uint8_t**, size_t*, size_t*, size_t*, size_t*) {}
+
+bool HEAPPROFD_ADD_PREFIX(_write_malloc_leak_info)(FILE*) {
+  return false;
+}
+
+ssize_t HEAPPROFD_ADD_PREFIX(_malloc_backtrace)(void*, uintptr_t*, size_t) {
+  return -1;
+}
+
+void HEAPPROFD_ADD_PREFIX(_free_malloc_leak_info)(uint8_t*) {}
+
+size_t HEAPPROFD_ADD_PREFIX(_malloc_usable_size)(void* pointer) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->malloc_usable_size(pointer);
+}
+
+struct mallinfo HEAPPROFD_ADD_PREFIX(_mallinfo)() {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->mallinfo();
+}
+
+int HEAPPROFD_ADD_PREFIX(_mallopt)(int param, int value) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->mallopt(param, value);
+}
+
+int HEAPPROFD_ADD_PREFIX(_malloc_info)(int options, FILE* fp) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->malloc_info(options, fp);
+}
+
+int HEAPPROFD_ADD_PREFIX(_malloc_iterate)(uintptr_t base,
+                                          size_t size,
+                                          void (*callback)(uintptr_t base,
+                                                   size_t size,
+                                                   void* arg),
+                                          void* arg) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->malloc_iterate(base, size, callback, arg);
+}
+
+void HEAPPROFD_ADD_PREFIX(_malloc_disable)() {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->malloc_disable();
+}
+
+void HEAPPROFD_ADD_PREFIX(_malloc_enable)() {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->malloc_enable();
+}
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+void* HEAPPROFD_ADD_PREFIX(_pvalloc)(size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->pvalloc(size);
+}
+
+void* HEAPPROFD_ADD_PREFIX(_valloc)(size_t size) {
+  const MallocDispatch* dispatch = GetDispatch();
+  return dispatch->valloc(size);
+}
+
+#endif
diff --git a/src/profiling/memory/malloc_interceptor_bionic_hooks.cc b/src/profiling/memory/malloc_interceptor_bionic_hooks.cc
deleted file mode 100644
index 2e63f23..0000000
--- a/src/profiling/memory/malloc_interceptor_bionic_hooks.cc
+++ /dev/null
@@ -1,242 +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 <bionic/malloc.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <private/bionic_malloc_dispatch.h>
-
-#include <atomic>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/heap_profile_internal.h"
-
-#include "src/profiling/memory/wrap_allocators.h"
-
-#pragma GCC visibility push(default)
-extern "C" {
-
-bool heapprofd_initialize(const MallocDispatch* malloc_dispatch,
-                          bool* zygote_child,
-                          const char* options);
-void heapprofd_finalize();
-void heapprofd_dump_heap(const char* file_name);
-void heapprofd_get_malloc_leak_info(uint8_t** info,
-                                    size_t* overall_size,
-                                    size_t* info_size,
-                                    size_t* total_memory,
-                                    size_t* backtrace_size);
-bool heapprofd_write_malloc_leak_info(FILE* fp);
-ssize_t heapprofd_malloc_backtrace(void* pointer,
-                                   uintptr_t* frames,
-                                   size_t frame_count);
-void heapprofd_free_malloc_leak_info(uint8_t* info);
-size_t heapprofd_malloc_usable_size(void* pointer);
-void* heapprofd_malloc(size_t size);
-void heapprofd_free(void* pointer);
-void* heapprofd_aligned_alloc(size_t alignment, size_t size);
-void* heapprofd_memalign(size_t alignment, size_t bytes);
-void* heapprofd_realloc(void* pointer, size_t bytes);
-void* heapprofd_calloc(size_t nmemb, size_t bytes);
-struct mallinfo heapprofd_mallinfo();
-int heapprofd_mallopt(int param, int value);
-int heapprofd_malloc_info(int options, FILE* fp);
-int heapprofd_posix_memalign(void** memptr, size_t alignment, size_t size);
-int heapprofd_malloc_iterate(uintptr_t base,
-                             size_t size,
-                             void (*callback)(uintptr_t base,
-                                              size_t size,
-                                              void* arg),
-                             void* arg);
-void heapprofd_malloc_disable();
-void heapprofd_malloc_enable();
-
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-void* heapprofd_pvalloc(size_t bytes);
-void* heapprofd_valloc(size_t size);
-#endif
-}
-#pragma GCC visibility pop
-
-namespace {
-
-// The real malloc function pointers we get in initialize. Set once in the first
-// initialize invocation, and never changed afterwards. Because bionic does a
-// release write after initialization and an acquire read to retrieve the hooked
-// malloc functions, we can use relaxed memory mode for both writing and
-// reading.
-std::atomic<const MallocDispatch*> g_dispatch{nullptr};
-
-const MallocDispatch* GetDispatch() {
-  return g_dispatch.load(std::memory_order_relaxed);
-}
-
-// Note: android_mallopt(M_RESET_HOOKS) is mutually exclusive with
-// heapprofd_initialize. Concurrent calls get discarded, which might be our
-// unpatching attempt if there is a concurrent re-initialization running due to
-// a new signal.
-void ProfileDisabledCallback(void*, const AHeapProfileDisableCallbackInfo*) {
-  if (!android_mallopt(M_RESET_HOOKS, nullptr, 0))
-    PERFETTO_PLOG("Unpatching heapprofd hooks failed.");
-}
-
-uint32_t g_heap_id = AHeapProfile_registerHeap(
-    AHeapInfo_setDisabledCallback(AHeapInfo_create("libc.malloc"),
-                                  ProfileDisabledCallback,
-                                  nullptr));
-
-}  // namespace
-
-// Setup for the rest of profiling. The first time profiling is triggered in a
-// process, this is called after this client library is dlopened, but before the
-// rest of the hooks are patched in. However, as we support multiple profiling
-// sessions within a process' lifetime, this function can also be legitimately
-// called any number of times afterwards (note: bionic guarantees that at most
-// one initialize call is active at a time).
-//
-// Note: if profiling is triggered at runtime, this runs on a dedicated pthread
-// (which is safe to block). If profiling is triggered at startup, then this
-// code runs synchronously.
-bool heapprofd_initialize(const MallocDispatch* malloc_dispatch,
-                          bool*,
-                          const char*) {
-  // Table of pointers to backing implementation.
-  g_dispatch.store(malloc_dispatch);
-  return AHeapProfile_initSession(malloc_dispatch->malloc,
-                                  malloc_dispatch->free);
-}
-
-void heapprofd_finalize() {
-  // At the time of writing, invoked only as an atexit handler. We don't have
-  // any specific action to take, and cleanup can be left to the OS.
-}
-
-void* heapprofd_malloc(size_t size) {
-  return perfetto::profiling::wrap_malloc(g_heap_id, GetDispatch()->malloc,
-                                          size);
-}
-
-void* heapprofd_calloc(size_t nmemb, size_t size) {
-  return perfetto::profiling::wrap_calloc(g_heap_id, GetDispatch()->calloc,
-                                          nmemb, size);
-}
-
-void* heapprofd_aligned_alloc(size_t alignment, size_t size) {
-  // aligned_alloc is the same as memalign.
-  return perfetto::profiling::wrap_memalign(
-      g_heap_id, GetDispatch()->aligned_alloc, alignment, size);
-}
-
-void* heapprofd_memalign(size_t alignment, size_t size) {
-  return perfetto::profiling::wrap_memalign(g_heap_id, GetDispatch()->memalign,
-                                            alignment, size);
-}
-
-int heapprofd_posix_memalign(void** memptr, size_t alignment, size_t size) {
-  return perfetto::profiling::wrap_posix_memalign(
-      g_heap_id, GetDispatch()->posix_memalign, memptr, alignment, size);
-}
-
-void heapprofd_free(void* pointer) {
-  return perfetto::profiling::wrap_free(g_heap_id, GetDispatch()->free,
-                                        pointer);
-}
-
-// Approach to recording realloc: under the initial lock, get a safe copy of the
-// client, and make the sampling decision in advance. Then record the
-// deallocation, call the real realloc, and finally record the sample if one is
-// necessary.
-//
-// As with the free, we record the deallocation before calling the backing
-// implementation to make sure the address is still exclusive while we're
-// processing it.
-void* heapprofd_realloc(void* pointer, size_t size) {
-  return perfetto::profiling::wrap_realloc(g_heap_id, GetDispatch()->realloc,
-                                           pointer, size);
-}
-
-void heapprofd_dump_heap(const char*) {}
-
-void heapprofd_get_malloc_leak_info(uint8_t**,
-                                    size_t*,
-                                    size_t*,
-                                    size_t*,
-                                    size_t*) {}
-
-bool heapprofd_write_malloc_leak_info(FILE*) {
-  return false;
-}
-
-ssize_t heapprofd_malloc_backtrace(void*, uintptr_t*, size_t) {
-  return -1;
-}
-
-void heapprofd_free_malloc_leak_info(uint8_t*) {}
-
-size_t heapprofd_malloc_usable_size(void* pointer) {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->malloc_usable_size(pointer);
-}
-
-struct mallinfo heapprofd_mallinfo() {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->mallinfo();
-}
-
-int heapprofd_mallopt(int param, int value) {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->mallopt(param, value);
-}
-
-int heapprofd_malloc_info(int options, FILE* fp) {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->malloc_info(options, fp);
-}
-
-int heapprofd_malloc_iterate(uintptr_t base,
-                             size_t size,
-                             void (*callback)(uintptr_t base,
-                                              size_t size,
-                                              void* arg),
-                             void* arg) {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->malloc_iterate(base, size, callback, arg);
-}
-
-void heapprofd_malloc_disable() {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->malloc_disable();
-}
-
-void heapprofd_malloc_enable() {
-  const MallocDispatch* dispatch = GetDispatch();
-  return dispatch->malloc_enable();
-}
-
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-void* heapprofd_pvalloc(size_t size) {
-  return perfetto::profiling::wrap_pvalloc(g_heap_id, GetDispatch()->pvalloc,
-                                           size);
-}
-
-void* heapprofd_valloc(size_t size) {
-  return perfetto::profiling::wrap_valloc(g_heap_id, GetDispatch()->valloc,
-                                          size);
-}
-
-#endif
diff --git a/src/profiling/memory/malloc_interceptor_glibc_preload.cc b/src/profiling/memory/malloc_interceptor_glibc_preload.cc
deleted file mode 100644
index 61e77ab..0000000
--- a/src/profiling/memory/malloc_interceptor_glibc_preload.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <malloc.h>
-#include <unistd.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/wrap_allocators.h"
-
-namespace {
-// AHeapProfile_registerHeap is guaranteed to be safe to call from global
-// constructors.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wglobal-constructors"
-uint32_t g_heap_id = AHeapProfile_registerHeap(AHeapInfo_create("libc.malloc"));
-#pragma GCC diagnostic pop
-
-bool IsPowerOfTwo(size_t v) {
-  return (v != 0 && ((v & (v - 1)) == 0));
-}
-
-}  // namespace
-
-extern "C" {
-
-// These are exported by GLibc to be used by functions overwriting malloc
-// to call back to the real implementation.
-extern void* __libc_malloc(size_t);
-extern void __libc_free(void*);
-extern void* __libc_calloc(size_t, size_t);
-extern void* __libc_realloc(void*, size_t);
-extern void* __libc_memalign(size_t, size_t);
-extern void* __libc_pvalloc(size_t);
-extern void* __libc_valloc(size_t);
-extern void* __libc_reallocarray(void*, size_t, size_t);
-
-#pragma GCC visibility push(default)
-
-void* malloc(size_t size) {
-  return perfetto::profiling::wrap_malloc(g_heap_id, __libc_malloc, size);
-}
-
-void free(void* ptr) {
-  return perfetto::profiling::wrap_free(g_heap_id, __libc_free, ptr);
-}
-
-void* calloc(size_t nmemb, size_t size) {
-  return perfetto::profiling::wrap_calloc(g_heap_id, __libc_calloc, nmemb,
-                                          size);
-}
-
-void* realloc(void* ptr, size_t size) {
-  return perfetto::profiling::wrap_realloc(g_heap_id, __libc_realloc, ptr,
-                                           size);
-}
-
-int posix_memalign(void** memptr, size_t alignment, size_t size) {
-  if (alignment % sizeof(void*) || !IsPowerOfTwo(alignment / sizeof(void*))) {
-    return EINVAL;
-  }
-  void* alloc = perfetto::profiling::wrap_memalign(g_heap_id, __libc_memalign,
-                                                   alignment, size);
-  if (!alloc) {
-    return ENOMEM;
-  }
-  *memptr = alloc;
-  return 0;
-}
-
-void* aligned_alloc(size_t alignment, size_t size) {
-  return perfetto::profiling::wrap_memalign(g_heap_id, __libc_memalign,
-                                            alignment, size);
-}
-
-void* memalign(size_t alignment, size_t size) {
-  return perfetto::profiling::wrap_memalign(g_heap_id, __libc_memalign,
-                                            alignment, size);
-}
-
-void* pvalloc(size_t size) {
-  return perfetto::profiling::wrap_pvalloc(g_heap_id, __libc_pvalloc, size);
-}
-
-void* valloc(size_t size) {
-  return perfetto::profiling::wrap_valloc(g_heap_id, __libc_valloc, size);
-}
-
-void* reallocarray(void* ptr, size_t nmemb, size_t size) {
-  return perfetto::profiling::wrap_reallocarray(g_heap_id, __libc_reallocarray,
-                                                ptr, nmemb, size);
-}
-
-#pragma GCC visibility pop
-}
diff --git a/src/profiling/memory/page_idle_checker.cc b/src/profiling/memory/page_idle_checker.cc
new file mode 100644
index 0000000..a5ac79e
--- /dev/null
+++ b/src/profiling/memory/page_idle_checker.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <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 (pwrite64(*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 (pread64(*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
new file mode 100644
index 0000000..f9c73cd
--- /dev/null
+++ b/src/profiling/memory/page_idle_checker.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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
new file mode 100644
index 0000000..ee751e9
--- /dev/null
+++ b/src/profiling/memory/page_idle_checker_unittest.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/parse_smaps_unittest.cc b/src/profiling/memory/parse_smaps_unittest.cc
index 5708a2c..9ee4c82 100644
--- a/src/profiling/memory/parse_smaps_unittest.cc
+++ b/src/profiling/memory/parse_smaps_unittest.cc
@@ -38,7 +38,7 @@
 TEST(ParseSmapsTest, Smoke) {
   base::ScopedFstream fd(fopen(
       base::GetTestDataPath("src/profiling/memory/test/data/cat_smaps").c_str(),
-      "re"));
+      "r"));
   std::vector<SmapsEntry> entries;
   EXPECT_TRUE(ParseSmaps(
       *fd, [&entries](const SmapsEntry& e) { entries.emplace_back(e); }));
@@ -65,7 +65,7 @@
   base::ScopedFstream fd(fopen(
       base::GetTestDataPath("src/profiling/memory/test/data/cat_smaps_noeol")
           .c_str(),
-      "re"));
+      "r"));
   std::vector<SmapsEntry> entries;
   EXPECT_TRUE(ParseSmaps(
       *fd, [&entries](const SmapsEntry& e) { entries.emplace_back(e); }));
diff --git a/src/profiling/memory/sampler.cc b/src/profiling/memory/sampler.cc
deleted file mode 100644
index a5e59db..0000000
--- a/src/profiling/memory/sampler.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/memory/sampler.h"
-
-namespace perfetto {
-namespace profiling {
-
-namespace {
-
-// If the probability of getting less than one sample is less than this,
-// sidestep the sampler and treat the allocation as a sample.
-constexpr double kPassthroughError = 0.01;
-
-}  // namespace
-
-uint64_t GetPassthroughThreshold(uint64_t interval) {
-  if (interval <= 1)
-    return interval;
-  // (1 - 1 / interval)^x = kPassthroughError
-  // x = log_(1 - 1/interval)(kPassthroughError)
-  return 1 + uint64_t(log(kPassthroughError) / log(1.0 - 1 / double(interval)));
-}
-
-std::default_random_engine& GetGlobalRandomEngineLocked() {
-  static std::default_random_engine engine;
-  return engine;
-}
-
-void Sampler::SetSamplingInterval(uint64_t sampling_interval) {
-  sampling_interval_ = sampling_interval;
-  passthrough_threshold_ = GetPassthroughThreshold(sampling_interval_);
-  sampling_rate_ = 1.0 / static_cast<double>(sampling_interval_);
-  interval_to_next_sample_ = NextSampleInterval();
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/sampler.h b/src/profiling/memory/sampler.h
index d462190..6740d17 100644
--- a/src/profiling/memory/sampler.h
+++ b/src/profiling/memory/sampler.h
@@ -29,10 +29,6 @@
 
 constexpr uint64_t kSamplerSeed = 1;
 
-uint64_t GetPassthroughThreshold(uint64_t interval);
-
-std::default_random_engine& GetGlobalRandomEngineLocked();
-
 // Poisson sampler for memory allocations. We apply sampling individually to
 // each byte. The whole allocation gets accounted as often as the number of
 // sampled bytes it contains.
@@ -44,7 +40,11 @@
 // NB: not thread-safe, requires external synchronization.
 class Sampler {
  public:
-  void SetSamplingInterval(uint64_t sampling_interval);
+  Sampler(uint64_t sampling_interval)
+      : sampling_interval_(sampling_interval),
+        sampling_rate_(1.0 / static_cast<double>(sampling_interval)),
+        random_engine_(kSamplerSeed),
+        interval_to_next_sample_(NextSampleInterval()) {}
 
   // Returns number of bytes that should be be attributed to the sample.
   // If returned size is 0, the allocation should not be sampled.
@@ -52,21 +52,17 @@
   // Due to how the poission sampling works, some samples should be accounted
   // multiple times.
   size_t SampleSize(size_t alloc_sz) {
-    if (PERFETTO_UNLIKELY(alloc_sz >= passthrough_threshold_))
+    if (PERFETTO_UNLIKELY(alloc_sz >= sampling_interval_))
       return alloc_sz;
     return static_cast<size_t>(sampling_interval_ * NumberOfSamples(alloc_sz));
   }
 
-  uint64_t sampling_interval() const { return sampling_interval_; }
-
  private:
   int64_t NextSampleInterval() {
     std::exponential_distribution<double> dist(sampling_rate_);
-    int64_t next = static_cast<int64_t>(dist(GetGlobalRandomEngineLocked()));
-    // We approximate the geometric distribution using an exponential
-    // distribution.
-    // We need to add 1 because that gives us the number of failures before
-    // the next success, while our interval includes the next success.
+    int64_t next = static_cast<int64_t>(dist(random_engine_));
+    // The +1 corrects the distribution of the first value in the interval.
+    // TODO(fmayer): Figure out why.
     return next + 1;
   }
 
@@ -83,8 +79,8 @@
   }
 
   uint64_t sampling_interval_;
-  uint64_t passthrough_threshold_;
   double sampling_rate_;
+  std::default_random_engine random_engine_;
   int64_t interval_to_next_sample_;
 };
 
diff --git a/src/profiling/memory/sampler_unittest.cc b/src/profiling/memory/sampler_unittest.cc
index b3eca7b..db903ff 100644
--- a/src/profiling/memory/sampler_unittest.cc
+++ b/src/profiling/memory/sampler_unittest.cc
@@ -25,34 +25,22 @@
 namespace {
 
 TEST(SamplerTest, TestLarge) {
-  GetGlobalRandomEngineLocked().seed(1);
-  Sampler sampler;
-  sampler.SetSamplingInterval(32768);
-  EXPECT_EQ(sampler.SampleSize(160000u), 160000u);
+  Sampler sampler(512);
+  EXPECT_EQ(sampler.SampleSize(1024), 1024u);
 }
 
 TEST(SamplerTest, TestSmall) {
-  GetGlobalRandomEngineLocked().seed(1);
-  Sampler sampler;
-  sampler.SetSamplingInterval(512);
+  Sampler sampler(512);
   EXPECT_EQ(sampler.SampleSize(511), 512u);
 }
 
 TEST(SamplerTest, TestSequence) {
-  GetGlobalRandomEngineLocked().seed(1);
-  Sampler sampler;
-  sampler.SetSamplingInterval(1);
+  Sampler sampler(1);
   EXPECT_EQ(sampler.SampleSize(3), 3u);
   EXPECT_EQ(sampler.SampleSize(7), 7u);
   EXPECT_EQ(sampler.SampleSize(5), 5u);
 }
 
-TEST(SamplerTest, TestGetPassthroughThreshold) {
-  EXPECT_EQ(GetPassthroughThreshold(32768u), 150900u);
-  EXPECT_EQ(GetPassthroughThreshold(1u), 1u);
-  EXPECT_EQ(GetPassthroughThreshold(2u), 7u);
-}
-
 }  // namespace
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/scoped_spinlock.cc b/src/profiling/memory/scoped_spinlock.cc
index 0d19957..c306d79 100644
--- a/src/profiling/memory/scoped_spinlock.cc
+++ b/src/profiling/memory/scoped_spinlock.cc
@@ -23,44 +23,27 @@
 #include "perfetto/ext/base/utils.h"
 
 namespace {
-constexpr bool IsPowerOfTwo(size_t v) {
-  return (v != 0 && ((v & (v - 1)) == 0));
-}
 // Wait for ~1s before timing out (+- spurious wakeups from the sleeps).
 constexpr unsigned kSleepAttempts = 1000;
-constexpr unsigned kLockAttemptsPerSleep = 1024;
+constexpr unsigned kLockAttemptsPerSleep = 1000;
 constexpr unsigned kSleepDurationUs = 1000;
-
-static_assert(IsPowerOfTwo(kLockAttemptsPerSleep),
-              "lock attempts of power of 2 produce faster code.");
 }  // namespace
 
 namespace perfetto {
 namespace profiling {
 
-void PoisonSpinlock(Spinlock* lock) {
-  lock->poisoned.store(true, std::memory_order_relaxed);
-}
-
 void ScopedSpinlock::LockSlow(Mode mode) {
-  size_t sleeps = 0;
-  // We need to start with attempt = 1, otherwise
-  // attempt % kLockAttemptsPerSleep is zero for the first iteration.
-  for (size_t attempt = 1; mode == Mode::Blocking ||
+  for (size_t attempt = 0; mode == Mode::Blocking ||
                            attempt < kLockAttemptsPerSleep * kSleepAttempts;
        attempt++) {
-    if (!lock_->locked.load(std::memory_order_relaxed) &&
-        PERFETTO_LIKELY(
-            !lock_->locked.exchange(true, std::memory_order_acquire))) {
+    if (!lock_->load(std::memory_order_relaxed) &&
+        PERFETTO_LIKELY(!lock_->exchange(true, std::memory_order_acquire))) {
       locked_ = true;
-      break;
+      return;
     }
-    if (attempt % kLockAttemptsPerSleep == 0) {
+    if (attempt && attempt % kLockAttemptsPerSleep == 0)
       usleep(kSleepDurationUs);
-      sleeps++;
-    }
   }
-  blocked_us_ = kSleepDurationUs * sleeps;
 }
 
 }  // namespace profiling
diff --git a/src/profiling/memory/scoped_spinlock.h b/src/profiling/memory/scoped_spinlock.h
index 90aaf71..67d8bd1 100644
--- a/src/profiling/memory/scoped_spinlock.h
+++ b/src/profiling/memory/scoped_spinlock.h
@@ -17,7 +17,6 @@
 #ifndef SRC_PROFILING_MEMORY_SCOPED_SPINLOCK_H_
 #define SRC_PROFILING_MEMORY_SCOPED_SPINLOCK_H_
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/utils.h"
 
@@ -28,15 +27,6 @@
 namespace perfetto {
 namespace profiling {
 
-struct Spinlock {
-  std::atomic<uint8_t> locked;
-  std::atomic<uint8_t> poisoned;
-};
-
-static_assert(sizeof(Spinlock) == 2, "spinlock size must be ABI independent");
-
-void PoisonSpinlock(Spinlock* lock);
-
 class ScopedSpinlock {
  public:
   enum class Mode {
@@ -46,12 +36,8 @@
     Blocking
   };
 
-  ScopedSpinlock(Spinlock* lock, Mode mode) : lock_(lock) {
-    if (PERFETTO_UNLIKELY(lock_->poisoned.load(std::memory_order_relaxed))) {
-      return;
-    }
-    if (PERFETTO_LIKELY(
-            !lock_->locked.exchange(true, std::memory_order_acquire))) {
+  ScopedSpinlock(std::atomic<bool>* lock, Mode mode) : lock_(lock) {
+    if (PERFETTO_LIKELY(!lock_->exchange(true, std::memory_order_acquire))) {
       locked_ = true;
       return;
     }
@@ -78,19 +64,17 @@
 
   void Unlock() {
     if (locked_) {
-      PERFETTO_DCHECK(lock_->locked.load());
-      lock_->locked.store(false, std::memory_order_release);
+      PERFETTO_DCHECK(lock_->load());
+      lock_->store(false, std::memory_order_release);
     }
     locked_ = false;
   }
 
   bool locked() const { return locked_; }
-  size_t blocked_us() const { return blocked_us_; }
 
  private:
   void LockSlow(Mode mode);
-  Spinlock* lock_;
-  size_t blocked_us_ = 0;
+  std::atomic<bool>* lock_;
   bool locked_ = false;
 };
 
diff --git a/src/profiling/memory/shared_ring_buffer.cc b/src/profiling/memory/shared_ring_buffer.cc
index bc56327..0eee59d 100644
--- a/src/profiling/memory/shared_ring_buffer.cc
+++ b/src/profiling/memory/shared_ring_buffer.cc
@@ -20,7 +20,6 @@
 #include <type_traits>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -175,7 +174,7 @@
     munmap(region, outer_size);
     return;
   }
-  set_size(size);
+  size_ = size;
   meta_ = reinterpret_cast<MetadataPage*>(region);
   mem_ = region + kMetaPageSize;
   mem_fd_ = std::move(mem_fd);
@@ -214,7 +213,6 @@
 
   result.size = size;
   result.data = wr_ptr + kHeaderSize;
-  result.bytes_free = write_avail(pos);
   meta_->stats.bytes_written += size;
   meta_->stats.num_writes_succeeded++;
 
@@ -285,7 +283,7 @@
 
   rd_ptr += kHeaderSize;
   PERFETTO_DCHECK(reinterpret_cast<uintptr_t>(rd_ptr) % kAlignment == 0);
-  return Buffer(rd_ptr, size, write_avail(pos));
+  return Buffer(rd_ptr, size);
 }
 
 void SharedRingBuffer::EndRead(Buffer buf) {
@@ -311,13 +309,11 @@
   *this = std::move(other);
 }
 
-SharedRingBuffer& SharedRingBuffer::operator=(
-    SharedRingBuffer&& other) noexcept {
+SharedRingBuffer& SharedRingBuffer::operator=(SharedRingBuffer&& other) {
   mem_fd_ = std::move(other.mem_fd_);
-  std::tie(meta_, mem_, size_, size_mask_) =
-      std::tie(other.meta_, other.mem_, other.size_, other.size_mask_);
-  std::tie(other.meta_, other.mem_, other.size_, other.size_mask_) =
-      std::make_tuple(nullptr, nullptr, 0, 0);
+  std::tie(meta_, mem_, size_) = std::tie(other.meta_, other.mem_, other.size_);
+  std::tie(other.meta_, other.mem_, other.size_) =
+      std::make_tuple(nullptr, nullptr, 0);
   return *this;
 }
 
diff --git a/src/profiling/memory/shared_ring_buffer.h b/src/profiling/memory/shared_ring_buffer.h
index d4279a9..0c5492f 100644
--- a/src/profiling/memory/shared_ring_buffer.h
+++ b/src/profiling/memory/shared_ring_buffer.h
@@ -21,13 +21,10 @@
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/utils.h"
 #include "src/profiling/memory/scoped_spinlock.h"
-#include "src/profiling/memory/util.h"
 
 #include <atomic>
-#include <limits>
 #include <map>
 #include <memory>
-#include <type_traits>
 
 #include <stdint.h>
 
@@ -59,8 +56,7 @@
   class Buffer {
    public:
     Buffer() {}
-    Buffer(uint8_t* d, size_t s, uint64_t f)
-        : data(d), size(s), bytes_free(f) {}
+    Buffer(uint8_t* d, size_t s) : data(d), size(s) {}
 
     Buffer(const Buffer&) = delete;
     Buffer& operator=(const Buffer&) = delete;
@@ -68,33 +64,24 @@
     Buffer(Buffer&&) = default;
     Buffer& operator=(Buffer&&) = default;
 
-    explicit operator bool() const { return data != nullptr; }
+    operator bool() const { return data != nullptr; }
 
     uint8_t* data = nullptr;
     size_t size = 0;
-    uint64_t bytes_free = 0;
-  };
-
-  enum ErrorState : uint64_t {
-    kNoError = 0,
-    kHitTimeout = 1,
-    kInvalidStackBounds = 2,
   };
 
   struct Stats {
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) bytes_written;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_succeeded;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_corrupt;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_overflow;
+    uint64_t bytes_written;
+    uint64_t num_writes_succeeded;
+    uint64_t num_writes_corrupt;
+    uint64_t num_writes_overflow;
 
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_succeeded;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_corrupt;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_nodata;
+    uint64_t num_reads_succeeded;
+    uint64_t num_reads_corrupt;
+    uint64_t num_reads_nodata;
 
     // Fields below get set by GetStats as copies of atomics in MetadataPage.
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) failed_spinlocks;
-    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) client_spinlock_blocked_us;
-    PERFETTO_CROSS_ABI_ALIGNED(ErrorState) error_state;
+    uint64_t failed_spinlocks;
   };
 
   static base::Optional<SharedRingBuffer> Create(size_t);
@@ -104,17 +91,11 @@
   SharedRingBuffer() = default;
 
   SharedRingBuffer(SharedRingBuffer&&) noexcept;
-  SharedRingBuffer& operator=(SharedRingBuffer&&) noexcept;
+  SharedRingBuffer& operator=(SharedRingBuffer&&);
 
   bool is_valid() const { return !!mem_; }
   size_t size() const { return size_; }
   int fd() const { return *mem_fd_; }
-  size_t write_avail() {
-    auto pos = GetPointerPositions();
-    if (!pos)
-      return 0;
-    return write_avail(*pos);
-  }
 
   Buffer BeginWrite(const ScopedSpinlock& spinlock, size_t size);
   void EndWrite(Buffer buf);
@@ -127,14 +108,9 @@
     Stats stats = meta_->stats;
     stats.failed_spinlocks =
         meta_->failed_spinlocks.load(std::memory_order_relaxed);
-    stats.error_state = meta_->error_state.load(std::memory_order_relaxed);
-    stats.client_spinlock_blocked_us =
-        meta_->client_spinlock_blocked_us.load(std::memory_order_relaxed);
     return stats;
   }
 
-  void SetErrorState(ErrorState error) { meta_->error_state.store(error); }
-
   // This is used by the caller to be able to hold the SpinLock after
   // BeginWrite has returned. This is so that additional bookkeeping can be
   // done under the lock. This will be used to increment the sequence_number.
@@ -145,62 +121,22 @@
     return lock;
   }
 
-  void AddClientSpinlockBlockedUs(size_t n) {
-    meta_->client_spinlock_blocked_us.fetch_add(n, std::memory_order_relaxed);
-  }
-
-  uint64_t client_spinlock_blocked_us() {
-    return meta_->client_spinlock_blocked_us;
-  }
-
-  void SetShuttingDown() {
-    meta_->shutting_down.store(true, std::memory_order_relaxed);
-  }
-
-  bool shutting_down() {
-    return meta_->shutting_down.load(std::memory_order_relaxed);
-  }
-
-  void SetReaderPaused() {
-    meta_->reader_paused.store(true, std::memory_order_relaxed);
-  }
-
-  bool GetAndResetReaderPaused() {
-    return meta_->reader_paused.exchange(false, std::memory_order_relaxed);
-  }
-
-  void InfiniteBufferForTesting() {
-    // Pretend this buffer is really large, while keeping size_mask_ as
-    // original so it keeps wrapping in circles.
-    size_ = std::numeric_limits<size_t>::max() / 2;
-  }
-
   // Exposed for fuzzers.
   struct MetadataPage {
-    static_assert(std::is_trivially_constructible<Spinlock>::value,
-                  "Spinlock needs to be trivially constructible.");
-    alignas(8) Spinlock spinlock;
-    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) read_pos;
-    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) write_pos;
+    alignas(uint64_t) std::atomic<bool> spinlock;
+    std::atomic<uint64_t> read_pos;
+    std::atomic<uint64_t> write_pos;
 
-    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>)
-    client_spinlock_blocked_us;
-    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) failed_spinlocks;
-    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<ErrorState>) error_state;
-    alignas(sizeof(uint64_t)) std::atomic<bool> shutting_down;
-    alignas(sizeof(uint64_t)) std::atomic<bool> reader_paused;
+    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.
-    alignas(sizeof(uint64_t)) Stats stats;
+    Stats stats;
   };
 
-  static_assert(sizeof(MetadataPage) == 144,
-                "metadata page size needs to be ABI independent");
-
  private:
   struct PointerPositions {
     uint64_t read_pos;
@@ -237,11 +173,6 @@
     return result;
   }
 
-  inline void set_size(size_t size) {
-    size_ = size;
-    size_mask_ = size - 1;
-  }
-
   inline size_t read_avail(const PointerPositions& pos) {
     PERFETTO_DCHECK(pos.write_pos >= pos.read_pos);
     auto res = static_cast<size_t>(pos.write_pos - pos.read_pos);
@@ -253,7 +184,7 @@
     return size_ - read_avail(pos);
   }
 
-  inline uint8_t* at(uint64_t pos) { return mem_ + (pos & size_mask_); }
+  inline uint8_t* at(uint64_t pos) { return mem_ + (pos & (size_ - 1)); }
 
   base::ScopedFile mem_fd_;
   MetadataPage* meta_ = nullptr;  // Start of the mmaped region.
@@ -262,7 +193,6 @@
   // Size of the ring buffer contents, without including metadata or the 2nd
   // mmap.
   size_t size_ = 0;
-  size_t size_mask_ = 0;
 
   // Remember to update the move ctor when adding new fields.
 };
diff --git a/src/profiling/memory/shared_ring_buffer_fuzzer.cc b/src/profiling/memory/shared_ring_buffer_fuzzer.cc
index 2a597a9..0fd03ce 100644
--- a/src/profiling/memory/shared_ring_buffer_fuzzer.cc
+++ b/src/profiling/memory/shared_ring_buffer_fuzzer.cc
@@ -16,7 +16,6 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include <unistd.h>
 
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/temp_file.h"
@@ -64,8 +63,7 @@
   // defaults to indefinite blocking mode).
   SharedRingBuffer::MetadataPage header = {};
   memcpy(&header, data, sizeof(header));
-  header.spinlock.locked = false;
-  header.spinlock.poisoned = false;
+  header.spinlock = 0;
 
   PERFETTO_CHECK(ftruncate(*fd, static_cast<off_t>(total_size_pages *
                                                    base::kPageSize)) == 0);
diff --git a/src/profiling/memory/shared_ring_buffer_unittest.cc b/src/profiling/memory/shared_ring_buffer_unittest.cc
index 7f58b90..df1bc5c 100644
--- a/src/profiling/memory/shared_ring_buffer_unittest.cc
+++ b/src/profiling/memory/shared_ring_buffer_unittest.cc
@@ -225,9 +225,10 @@
           // Failing to read after the writers are done means that there is no
           // data left in the ring buffer.
           return;
+        } else {
+          std::this_thread::yield();
+          continue;
         }
-        std::this_thread::yield();
-        continue;
       }
       ASSERT_GT(buf_and_size.size, 0u);
       std::string data = ToString(buf_and_size);
diff --git a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
index 486033e..be5bbb9 100644
--- a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
+++ b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
@@ -16,7 +16,6 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include <unistd.h>
 
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/temp_file.h"
@@ -69,7 +68,7 @@
   FuzzingInputHeader header = {};
   memcpy(&header, data, sizeof(header));
   SharedRingBuffer::MetadataPage& metadata_page = header.metadata_page;
-  metadata_page.spinlock.locked = false;
+  metadata_page.spinlock = 0;
 
   PERFETTO_CHECK(ftruncate(*fd, static_cast<off_t>(total_size_pages *
                                                    base::kPageSize)) == 0);
diff --git a/src/profiling/memory/system_property.cc b/src/profiling/memory/system_property.cc
index 6272cf8..a2fda64 100644
--- a/src/profiling/memory/system_property.cc
+++ b/src/profiling/memory/system_property.cc
@@ -26,15 +26,14 @@
 namespace perfetto {
 namespace profiling {
 
-SystemProperties::Handle::Handle(Handle&& other) noexcept {
+SystemProperties::Handle::Handle(Handle&& other) {
   system_properties_ = other.system_properties_;
   property_ = std::move(other.property_);
   all_ = other.all_;
   other.system_properties_ = nullptr;
 }
 
-SystemProperties::Handle& SystemProperties::Handle::operator=(
-    Handle&& other) noexcept {
+SystemProperties::Handle& SystemProperties::Handle::operator=(Handle&& other) {
   // Construct this temporary because the RHS could be an lvalue cast to an
   // rvalue reference whose lifetime we do not know.
   Handle tmp(std::move(other));
diff --git a/src/profiling/memory/system_property.h b/src/profiling/memory/system_property.h
index 2b1e32f..38aa35e 100644
--- a/src/profiling/memory/system_property.h
+++ b/src/profiling/memory/system_property.h
@@ -45,12 +45,12 @@
     Handle(const Handle&) = delete;
     Handle& operator=(const Handle&) = delete;
 
-    Handle(Handle&&) noexcept;
-    Handle& operator=(Handle&&) noexcept;
+    Handle(Handle&&);
+    Handle& operator=(Handle&&);
 
     friend class SystemProperties;
     ~Handle();
-    explicit operator bool();
+    operator bool();
 
    private:
     explicit Handle(SystemProperties* system_properties, std::string property);
diff --git a/src/profiling/memory/unhooked_allocator.h b/src/profiling/memory/unhooked_allocator.h
index b379e36..45a6262 100644
--- a/src/profiling/memory/unhooked_allocator.h
+++ b/src/profiling/memory/unhooked_allocator.h
@@ -49,8 +49,7 @@
       : unhooked_malloc_(unhooked_malloc), unhooked_free_(unhooked_free) {}
 
   template <typename U>
-  constexpr explicit UnhookedAllocator(
-      const UnhookedAllocator<U>& other) noexcept
+  constexpr UnhookedAllocator(const UnhookedAllocator<U>& other) noexcept
       : unhooked_malloc_(other.unhooked_malloc_),
         unhooked_free_(other.unhooked_free_) {}
 
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 5021949..c9e43fe 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -51,7 +51,6 @@
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/thread_task_runner.h"
 
-#include "src/profiling/memory/unwound_messages.h"
 #include "src/profiling/memory/wire_protocol.h"
 
 namespace perfetto {
@@ -59,23 +58,19 @@
 namespace {
 
 constexpr base::TimeMillis kMapsReparseInterval{500};
-constexpr uint32_t kRetryDelayMs = 100;
 
-constexpr size_t kMaxFrames = 500;
+constexpr size_t kMaxFrames = 1000;
 
 // We assume average ~300us per unwind. If we handle up to 1000 unwinds, this
 // makes sure other tasks get to be run at least every 300ms if the unwinding
 // saturates this thread.
 constexpr size_t kUnwindBatchSize = 1000;
-constexpr size_t kRecordBatchSize = 1024;
-constexpr size_t kMaxAllocRecordArenaSize = 2 * kRecordBatchSize;
 
 #pragma GCC diagnostic push
 // We do not care about deterministic destructor order.
 #pragma GCC diagnostic ignored "-Wglobal-constructors"
 #pragma GCC diagnostic ignored "-Wexit-time-destructors"
-static std::vector<std::string> kSkipMaps{"heapprofd_client.so",
-                                          "heapprofd_client_api.so"};
+static std::vector<std::string> kSkipMaps{"heapprofd_client.so"};
 #pragma GCC diagnostic pop
 
 size_t GetRegsSize(unwindstack::Regs* regs) {
@@ -131,10 +126,7 @@
     frame_data.function_name = "ERROR READING REGISTERS";
     frame_data.map_name = "ERROR";
 
-    out->frames.clear();
-    out->build_ids.clear();
-    out->frames.emplace_back(std::move(frame_data));
-    out->build_ids.emplace_back("");
+    out->frames.emplace_back(frame_data, "");
     out->error = true;
     return false;
   }
@@ -147,8 +139,8 @@
   unwindstack::Unwinder unwinder(kMaxFrames, &metadata->fd_maps, regs.get(),
                                  mems);
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  unwinder.SetJitDebug(metadata->GetJitDebug(regs->Arch()));
-  unwinder.SetDexFiles(metadata->GetDexFiles(regs->Arch()));
+  unwinder.SetJitDebug(metadata->jit_debug.get(), regs->Arch());
+  unwinder.SetDexFiles(metadata->dex_files.get(), regs->Arch());
 #endif
   // Suppress incorrect "variable may be uninitialized" error for if condition
   // after this loop. error_code = LastErrorCode gets run at least once.
@@ -168,22 +160,18 @@
       ReadFromRawData(regs.get(), alloc_metadata->register_data);
       out->reparsed_map = true;
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-      unwinder.SetJitDebug(metadata->GetJitDebug(regs->Arch()));
-      unwinder.SetDexFiles(metadata->GetDexFiles(regs->Arch()));
+      unwinder.SetJitDebug(metadata->jit_debug.get(), regs->Arch());
+      unwinder.SetDexFiles(metadata->dex_files.get(), regs->Arch());
 #endif
     }
-    out->frames.swap(unwinder.frames());  // Provide the unwinder buffer to use.
     unwinder.Unwind(&kSkipMaps, /*map_suffixes_to_ignore=*/nullptr);
-    out->frames.swap(unwinder.frames());  // Take the buffer back.
     error_code = unwinder.LastErrorCode();
-    if (error_code != unwindstack::ERROR_INVALID_MAP &&
-        (unwinder.warnings() & unwindstack::WARNING_DEX_PC_NOT_IN_MAP) == 0) {
+    if (error_code != unwindstack::ERROR_INVALID_MAP)
       break;
-    }
   }
-  out->build_ids.resize(out->frames.size());
-  for (size_t i = 0; i < out->frames.size(); ++i) {
-    out->build_ids[i] = metadata->GetBuildId(out->frames[i]);
+  std::vector<unwindstack::FrameData> frames = unwinder.ConsumeFrames();
+  for (unwindstack::FrameData& fd : frames) {
+    out->frames.emplace_back(metadata->AnnotateFrame(std::move(fd)));
   }
 
   if (error_code != unwindstack::ERROR_NONE) {
@@ -193,30 +181,22 @@
         "ERROR " + StringifyLibUnwindstackError(error_code);
     frame_data.map_name = "ERROR";
 
-    out->frames.emplace_back(std::move(frame_data));
-    out->build_ids.emplace_back("");
+    out->frames.emplace_back(std::move(frame_data), "");
     out->error = true;
   }
   return true;
 }
 
 void UnwindingWorker::OnDisconnect(base::UnixSocket* self) {
-  pid_t peer_pid = self->peer_pid_linux();
-  auto it = client_data_.find(peer_pid);
+  // 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.");
     return;
   }
-
   ClientData& client_data = it->second;
-  ReadAndUnwindBatch(&client_data);
   SharedRingBuffer& shmem = client_data.shmem;
 
-  if (!client_data.free_records.empty()) {
-    delegate_->PostFreeRecord(this, std::move(client_data.free_records));
-    client_data.free_records.clear();
-  }
-
   SharedRingBuffer::Stats stats = {};
   {
     auto lock = shmem.AcquireLock(ScopedSpinlock::Mode::Try);
@@ -226,57 +206,21 @@
       PERFETTO_ELOG("Failed to log shmem to get stats.");
   }
   DataSourceInstanceID ds_id = client_data.data_source_instance_id;
-
+  pid_t peer_pid = self->peer_pid();
   client_data_.erase(it);
-  if (client_data_.empty()) {
-    // We got rid of the last client. Flush and destruct AllocRecords in
-    // arena. Disable the arena (will not accept returning borrowed records)
-    // in case there are pending AllocRecords on the main thread.
-    alloc_record_arena_.Disable();
-  }
   // The erase invalidates the self pointer.
   self = nullptr;
-  delegate_->PostSocketDisconnected(this, ds_id, peer_pid, stats);
+  delegate_->PostSocketDisconnected(ds_id, peer_pid, stats);
 }
 
 void UnwindingWorker::OnDataAvailable(base::UnixSocket* self) {
   // Drain buffer to clear the notification.
   char recv_buf[kUnwindBatchSize];
   self->Receive(recv_buf, sizeof(recv_buf));
-  BatchUnwindJob(self->peer_pid_linux());
+  HandleUnwindBatch(self->peer_pid());
 }
 
-UnwindingWorker::ReadAndUnwindBatchResult UnwindingWorker::ReadAndUnwindBatch(
-    ClientData* client_data) {
-  SharedRingBuffer& shmem = client_data->shmem;
-  SharedRingBuffer::Buffer buf;
-
-  size_t i;
-  for (i = 0; i < kUnwindBatchSize; ++i) {
-    uint64_t reparses_before = client_data->metadata.reparses;
-    buf = shmem.BeginRead();
-    if (!buf)
-      break;
-    HandleBuffer(this, &alloc_record_arena_, buf, client_data,
-                 client_data->sock->peer_pid_linux(), delegate_);
-    shmem.EndRead(std::move(buf));
-    // Reparsing takes time, so process the rest in a new batch to avoid timing
-    // out.
-    if (reparses_before < client_data->metadata.reparses) {
-      return ReadAndUnwindBatchResult::kHasMore;
-    }
-  }
-
-  if (i == kUnwindBatchSize) {
-    return ReadAndUnwindBatchResult::kHasMore;
-  } else if (i > 0) {
-    return ReadAndUnwindBatchResult::kReadSome;
-  } else {
-    return ReadAndUnwindBatchResult::kReadNone;
-  }
-}
-
-void UnwindingWorker::BatchUnwindJob(pid_t peer_pid) {
+void UnwindingWorker::HandleUnwindBatch(pid_t peer_pid) {
   auto it = client_data_.find(peer_pid);
   if (it == client_data_.end()) {
     // This can happen if the client disconnected before the buffer was fully
@@ -285,44 +229,45 @@
     return;
   }
 
-  bool job_reposted = false;
-  bool reader_paused = false;
   ClientData& client_data = it->second;
-  switch (ReadAndUnwindBatch(&client_data)) {
-    case ReadAndUnwindBatchResult::kHasMore:
-      thread_task_runner_.get()->PostTask(
-          [this, peer_pid] { BatchUnwindJob(peer_pid); });
-      job_reposted = true;
+  SharedRingBuffer& shmem = client_data.shmem;
+  SharedRingBuffer::Buffer buf;
+
+  size_t i;
+  bool repost_task = false;
+  for (i = 0; i < kUnwindBatchSize; ++i) {
+    uint64_t reparses_before = client_data.metadata.reparses;
+    buf = shmem.BeginRead();
+    if (!buf)
       break;
-    case ReadAndUnwindBatchResult::kReadSome:
-      thread_task_runner_.get()->PostDelayedTask(
-          [this, peer_pid] { BatchUnwindJob(peer_pid); }, kRetryDelayMs);
-      job_reposted = true;
+    HandleBuffer(buf, &client_data.metadata,
+                 client_data.data_source_instance_id,
+                 client_data.sock->peer_pid(), delegate_);
+    shmem.EndRead(std::move(buf));
+    // Reparsing takes time, so process the rest in a new batch to avoid timing
+    // out.
+    if (reparses_before < client_data.metadata.reparses) {
+      repost_task = true;
       break;
-    case ReadAndUnwindBatchResult::kReadNone:
-      client_data.shmem.SetReaderPaused();
-      reader_paused = true;
-      break;
+    }
   }
 
-  // We need to either repost the job, or set the reader paused bit. By
-  // setting that bit, we inform the client that we want to be notified when
-  // new data is written to the shared memory buffer.
-  // If we do neither of these things, we will not read from the shared memory
-  // buffer again.
-  PERFETTO_CHECK(job_reposted || reader_paused);
+  // Always repost if we have gone through the whole batch.
+  if (i == kUnwindBatchSize)
+    repost_task = true;
+
+  if (repost_task) {
+    thread_task_runner_.get()->PostTask(
+        [this, peer_pid] { HandleUnwindBatch(peer_pid); });
+  }
 }
 
 // static
-void UnwindingWorker::HandleBuffer(UnwindingWorker* self,
-                                   AllocRecordArena* alloc_record_arena,
-                                   const SharedRingBuffer::Buffer& buf,
-                                   ClientData* client_data,
+void UnwindingWorker::HandleBuffer(const SharedRingBuffer::Buffer& buf,
+                                   UnwindingMetadata* unwinding_metadata,
+                                   DataSourceInstanceID data_source_instance_id,
                                    pid_t peer_pid,
                                    Delegate* delegate) {
-  UnwindingMetadata* unwinding_metadata = &client_data->metadata;
-  DataSourceInstanceID data_source_instance_id =
-      client_data->data_source_instance_id;
   WireMessage msg;
   // TODO(fmayer): standardise on char* or uint8_t*.
   // char* has stronger guarantees regarding aliasing.
@@ -333,35 +278,22 @@
   }
 
   if (msg.record_type == RecordType::Malloc) {
-    std::unique_ptr<AllocRecord> rec = alloc_record_arena->BorrowAllocRecord();
-    rec->alloc_metadata = *msg.alloc_header;
-    rec->pid = peer_pid;
-    rec->data_source_instance_id = data_source_instance_id;
+    AllocRecord rec;
+    rec.alloc_metadata = *msg.alloc_header;
+    rec.pid = peer_pid;
+    rec.data_source_instance_id = data_source_instance_id;
     auto start_time_us = base::GetWallTimeNs() / 1000;
-    if (!client_data->stream_allocations)
-      DoUnwind(&msg, unwinding_metadata, rec.get());
-    rec->unwinding_time_us = static_cast<uint64_t>(
+    DoUnwind(&msg, unwinding_metadata, &rec);
+    rec.unwinding_time_us = static_cast<uint64_t>(
         ((base::GetWallTimeNs() / 1000) - start_time_us).count());
-    delegate->PostAllocRecord(self, std::move(rec));
+    delegate->PostAllocRecord(std::move(rec));
   } else if (msg.record_type == RecordType::Free) {
     FreeRecord rec;
     rec.pid = peer_pid;
     rec.data_source_instance_id = data_source_instance_id;
     // We need to copy this, so we can return the memory to the shmem buffer.
-    memcpy(&rec.entry, msg.free_header, sizeof(*msg.free_header));
-    client_data->free_records.emplace_back(std::move(rec));
-    if (client_data->free_records.size() == kRecordBatchSize) {
-      delegate->PostFreeRecord(self, std::move(client_data->free_records));
-      client_data->free_records.clear();
-      client_data->free_records.reserve(kRecordBatchSize);
-    }
-  } else if (msg.record_type == RecordType::HeapName) {
-    HeapNameRecord rec;
-    rec.pid = peer_pid;
-    rec.data_source_instance_id = data_source_instance_id;
-    memcpy(&rec.entry, msg.heap_name_header, sizeof(*msg.heap_name_header));
-    rec.entry.heap_name[sizeof(rec.entry.heap_name) - 1] = '\0';
-    delegate->PostHeapNameRecord(self, std::move(rec));
+    memcpy(&rec.free_batch, msg.free_header, sizeof(*msg.free_header));
+    delegate->PostFreeRecord(std::move(rec));
   } else {
     PERFETTO_DFATAL_OR_ELOG("Invalid record type.");
   }
@@ -384,7 +316,7 @@
   auto sock = base::UnixSocket::AdoptConnected(
       handoff_data.sock.ReleaseFd(), this, this->thread_task_runner_.get(),
       base::SockFamily::kUnix, base::SockType::kStream);
-  pid_t peer_pid = sock->peer_pid_linux();
+  pid_t peer_pid = sock->peer_pid();
 
   UnwindingMetadata metadata(std::move(handoff_data.maps_fd),
                              std::move(handoff_data.mem_fd));
@@ -394,13 +326,8 @@
       std::move(metadata),
       std::move(handoff_data.shmem),
       std::move(handoff_data.client_config),
-      handoff_data.stream_allocations,
-      {},
   };
-  client_data.free_records.reserve(kRecordBatchSize);
-  client_data.shmem.SetReaderPaused();
   client_data_.emplace(peer_pid, std::move(client_data));
-  alloc_record_arena_.Enable();
 }
 
 void UnwindingWorker::PostDisconnectSocket(pid_t pid) {
@@ -413,44 +340,14 @@
 void UnwindingWorker::HandleDisconnectSocket(pid_t pid) {
   auto it = client_data_.find(pid);
   if (it == client_data_.end()) {
-    // This is expected if the client voluntarily disconnects before the
-    // profiling session ended. In that case, there is a race between the main
-    // thread learning about the disconnect and it calling back here.
+    PERFETTO_DFATAL_OR_ELOG("Trying to disconnect unknown socket.");
     return;
   }
   ClientData& client_data = it->second;
   // Shutdown and call OnDisconnect handler.
-  client_data.shmem.SetShuttingDown();
   client_data.sock->Shutdown(/* notify= */ true);
 }
 
-std::unique_ptr<AllocRecord> AllocRecordArena::BorrowAllocRecord() {
-  std::lock_guard<std::mutex> l(*alloc_records_mutex_);
-  if (!alloc_records_.empty()) {
-    std::unique_ptr<AllocRecord> result = std::move(alloc_records_.back());
-    alloc_records_.pop_back();
-    return result;
-  }
-  return std::unique_ptr<AllocRecord>(new AllocRecord());
-}
-
-void AllocRecordArena::ReturnAllocRecord(std::unique_ptr<AllocRecord> record) {
-  std::lock_guard<std::mutex> l(*alloc_records_mutex_);
-  if (enabled_ && record && alloc_records_.size() < kMaxAllocRecordArenaSize)
-    alloc_records_.emplace_back(std::move(record));
-}
-
-void AllocRecordArena::Disable() {
-  std::lock_guard<std::mutex> l(*alloc_records_mutex_);
-  alloc_records_.clear();
-  enabled_ = false;
-}
-
-void AllocRecordArena::Enable() {
-  std::lock_guard<std::mutex> l(*alloc_records_mutex_);
-  enabled_ = true;
-}
-
 UnwindingWorker::Delegate::~Delegate() = default;
 
 }  // namespace profiling
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index 6b5bcdb..82ec111 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -37,35 +37,13 @@
 
 bool DoUnwind(WireMessage*, UnwindingMetadata* metadata, AllocRecord* out);
 
-// AllocRecords are expensive to construct and destruct. We have seen up to
-// 10 % of total CPU of heapprofd being used to destruct them. That is why
-// we re-use them to cut CPU usage significantly.
-class AllocRecordArena {
- public:
-  AllocRecordArena() : alloc_records_mutex_(new std::mutex()) {}
-
-  void ReturnAllocRecord(std::unique_ptr<AllocRecord>);
-  std::unique_ptr<AllocRecord> BorrowAllocRecord();
-
-  void Enable();
-  void Disable();
-
- private:
-  std::unique_ptr<std::mutex> alloc_records_mutex_;
-  std::vector<std::unique_ptr<AllocRecord>> alloc_records_;
-  bool enabled_ = true;
-};
-
 class UnwindingWorker : public base::UnixSocket::EventListener {
  public:
   class Delegate {
    public:
-    virtual void PostAllocRecord(UnwindingWorker*,
-                                 std::unique_ptr<AllocRecord>) = 0;
-    virtual void PostFreeRecord(UnwindingWorker*, std::vector<FreeRecord>) = 0;
-    virtual void PostHeapNameRecord(UnwindingWorker*, HeapNameRecord rec) = 0;
-    virtual void PostSocketDisconnected(UnwindingWorker*,
-                                        DataSourceInstanceID,
+    virtual void PostAllocRecord(AllocRecord) = 0;
+    virtual void PostFreeRecord(FreeRecord) = 0;
+    virtual void PostSocketDisconnected(DataSourceInstanceID,
                                         pid_t pid,
                                         SharedRingBuffer::Stats stats) = 0;
     virtual ~Delegate();
@@ -78,7 +56,6 @@
     base::ScopedFile mem_fd;
     SharedRingBuffer shmem;
     ClientConfiguration client_config;
-    bool stream_allocations;
   };
 
   UnwindingWorker(Delegate* delegate, base::ThreadTaskRunner thread_task_runner)
@@ -88,9 +65,6 @@
   // Public API safe to call from other threads.
   void PostDisconnectSocket(pid_t pid);
   void PostHandoffSocket(HandoffData);
-  void ReturnAllocRecord(std::unique_ptr<AllocRecord> record) {
-    alloc_record_arena_.ReturnAllocRecord(std::move(record));
-  }
 
   // Implementation of UnixSocket::EventListener.
   // Do not call explicitly.
@@ -102,39 +76,27 @@
   void OnDataAvailable(base::UnixSocket* self) override;
 
  public:
-  // public for testing/fuzzer
-  struct ClientData {
-    DataSourceInstanceID data_source_instance_id;
-    std::unique_ptr<base::UnixSocket> sock;
-    UnwindingMetadata metadata;
-    SharedRingBuffer shmem;
-    ClientConfiguration client_config;
-    bool stream_allocations;
-    std::vector<FreeRecord> free_records;
-  };
-
-  // public for testing/fuzzing
-  static void HandleBuffer(UnwindingWorker* self,
-                           AllocRecordArena* alloc_record_arena,
-                           const SharedRingBuffer::Buffer& buf,
-                           ClientData* client_data,
+  // static and public for testing/fuzzing
+  static void HandleBuffer(const SharedRingBuffer::Buffer& buf,
+                           UnwindingMetadata* unwinding_metadata,
+                           DataSourceInstanceID data_source_instance_id,
                            pid_t peer_pid,
                            Delegate* delegate);
 
  private:
   void HandleHandoffSocket(HandoffData data);
   void HandleDisconnectSocket(pid_t pid);
-  std::unique_ptr<AllocRecord> BorrowAllocRecord();
 
-  enum class ReadAndUnwindBatchResult {
-    kHasMore,
-    kReadSome,
-    kReadNone,
+  void HandleUnwindBatch(pid_t);
+
+  struct ClientData {
+    DataSourceInstanceID data_source_instance_id;
+    std::unique_ptr<base::UnixSocket> sock;
+    UnwindingMetadata metadata;
+    SharedRingBuffer shmem;
+    ClientConfiguration client_config;
   };
-  ReadAndUnwindBatchResult ReadAndUnwindBatch(ClientData* client_data);
-  void BatchUnwindJob(pid_t);
 
-  AllocRecordArena alloc_record_arena_;
   std::map<pid_t, ClientData> client_data_;
   Delegate* delegate_;
 
diff --git a/src/profiling/memory/unwinding_fuzzer.cc b/src/profiling/memory/unwinding_fuzzer.cc
index e24ce4f..e87202e 100644
--- a/src/profiling/memory/unwinding_fuzzer.cc
+++ b/src/profiling/memory/unwinding_fuzzer.cc
@@ -17,7 +17,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "src/profiling/common/unwind_support.h"
@@ -30,18 +29,15 @@
 namespace {
 
 class NopDelegate : public UnwindingWorker::Delegate {
-  void PostAllocRecord(UnwindingWorker*,
-                       std::unique_ptr<AllocRecord>) override {}
-  void PostFreeRecord(UnwindingWorker*, std::vector<FreeRecord>) override {}
-  void PostHeapNameRecord(UnwindingWorker*, HeapNameRecord) override {}
-  void PostSocketDisconnected(UnwindingWorker*,
-                              DataSourceInstanceID,
+  void PostAllocRecord(AllocRecord) override {}
+  void PostFreeRecord(FreeRecord) override {}
+  void PostSocketDisconnected(DataSourceInstanceID,
                               pid_t,
                               SharedRingBuffer::Stats) override {}
 };
 
 int FuzzUnwinding(const uint8_t* data, size_t size) {
-  SharedRingBuffer::Buffer buf(const_cast<uint8_t*>(data), size, 0u);
+  SharedRingBuffer::Buffer buf(const_cast<uint8_t*>(data), size);
 
   pid_t self_pid = getpid();
   DataSourceInstanceID id = 0;
@@ -49,13 +45,7 @@
                              base::OpenFile("/proc/self/mem", O_RDONLY));
 
   NopDelegate nop_delegate;
-  UnwindingWorker::ClientData client_data{
-      id, {}, std::move(metadata), {}, {}, {}, {},
-  };
-
-  AllocRecordArena arena;
-  UnwindingWorker::HandleBuffer(nullptr, &arena, buf, &client_data, self_pid,
-                                &nop_delegate);
+  UnwindingWorker::HandleBuffer(buf, &metadata, id, self_pid, &nop_delegate);
   return 0;
 }
 
diff --git a/src/profiling/memory/unwinding_unittest.cc b/src/profiling/memory/unwinding_unittest.cc
index 40cfc08..99fe08b 100644
--- a/src/profiling/memory/unwinding_unittest.cc
+++ b/src/profiling/memory/unwinding_unittest.cc
@@ -22,7 +22,6 @@
 #include <sys/types.h>
 #include <unwindstack/RegsGetLocal.h>
 
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "src/profiling/common/unwind_support.h"
 #include "src/profiling/memory/client.h"
@@ -67,7 +66,7 @@
   unwindstack::MapInfo* map_info =
       maps.Find(reinterpret_cast<uint64_t>(&proc_maps));
   ASSERT_NE(map_info, nullptr);
-  ASSERT_EQ(map_info->name(), "[stack]");
+  ASSERT_EQ(map_info->name, "[stack]");
 }
 
 void __attribute__((noinline)) AssertFunctionOffset() {
@@ -106,27 +105,28 @@
   std::unique_ptr<AllocMetadata> metadata(new AllocMetadata);
   *metadata = {};
 
-  const char* stackend = GetThreadStackRange().end;
-  const char* stackptr = reinterpret_cast<char*>(__builtin_frame_address(0));
+  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 (stackend < stackptr) {
-    PERFETTO_FATAL("Stacktop >= stackend.");
+  if (stackbase < stacktop) {
+    PERFETTO_FATAL("Stacktop >= stackbase.");
     return {nullptr, nullptr};
   }
-  size_t stack_size = static_cast<size_t>(stackend - stackptr);
+  size_t stack_size = static_cast<size_t>(stackbase - stacktop);
 
   metadata->alloc_size = 10;
   metadata->alloc_address = 0x10;
-  metadata->stack_pointer = reinterpret_cast<uint64_t>(stackptr);
+  metadata->stack_pointer = reinterpret_cast<uint64_t>(stacktop);
+  metadata->stack_pointer_offset = sizeof(AllocMetadata);
   metadata->arch = unwindstack::Regs::CurrentArch();
   metadata->sequence_number = 1;
 
   std::unique_ptr<uint8_t[]> payload(new uint8_t[stack_size]);
-  UnsafeMemcpy(&payload[0], stackptr, stack_size);
+  UnsafeMemcpy(&payload[0], stacktop, stack_size);
 
   *msg = {};
   msg->alloc_header = metadata.get();
@@ -147,7 +147,7 @@
   ASSERT_GT(out.frames.size(), 0u);
   int st;
   std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
-      out.frames[0].function_name.c_str(), nullptr, nullptr, &st));
+      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(),
@@ -169,7 +169,7 @@
   ASSERT_GT(out.frames.size(), 0u);
   int st;
   std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
-      out.frames[0].function_name.c_str(), nullptr, nullptr, &st));
+      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(),
@@ -177,13 +177,6 @@
                "namespace)::GetRecord(perfetto::profiling::WireMessage*)");
 }
 
-TEST(AllocRecordArenaTest, Smoke) {
-  AllocRecordArena a;
-  auto borrowed = a.BorrowAllocRecord();
-  EXPECT_NE(borrowed, nullptr);
-  a.ReturnAllocRecord(std::move(borrowed));
-}
-
 }  // namespace
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/unwound_messages.h b/src/profiling/memory/unwound_messages.h
index cf0401d..b7101af 100644
--- a/src/profiling/memory/unwound_messages.h
+++ b/src/profiling/memory/unwound_messages.h
@@ -35,8 +35,7 @@
   uint64_t data_source_instance_id;
   uint64_t timestamp;
   AllocMetadata alloc_metadata;
-  std::vector<unwindstack::FrameData> frames;
-  std::vector<std::string> build_ids;
+  std::vector<FrameData> frames;
 };
 
 // Batch of deallocations.
@@ -44,13 +43,7 @@
   pid_t pid;
   uint64_t data_source_instance_id;
   uint64_t timestamp;
-  FreeEntry entry;
-};
-
-struct HeapNameRecord {
-  pid_t pid;
-  uint64_t data_source_instance_id;
-  HeapName entry;
+  FreeBatch free_batch;
 };
 
 }  // namespace profiling
diff --git a/src/profiling/memory/util.h b/src/profiling/memory/util.h
deleted file mode 100644
index 1eaf369..0000000
--- a/src/profiling/memory/util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_UTIL_H_
-#define SRC_PROFILING_MEMORY_UTIL_H_
-
-// Make sure the alignment is the same on 32 and 64 bit architectures. This
-// is to ensure the structs below are laid out in exactly the same way for
-// both of those, at the same build.
-// The maximum alignment of every type T is sizeof(T), so we overalign that.
-// E.g., the alignment for uint64_t is 4 bytes on 32, and 8 bytes on 64 bit.
-#define PERFETTO_CROSS_ABI_ALIGNED(type) alignas(sizeof(type)) type
-
-#endif  // SRC_PROFILING_MEMORY_UTIL_H_
diff --git a/src/profiling/memory/wire_protocol.cc b/src/profiling/memory/wire_protocol.cc
index 29ea042..6d561c3 100644
--- a/src/profiling/memory/wire_protocol.cc
+++ b/src/profiling/memory/wire_protocol.cc
@@ -19,25 +19,14 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/utils.h"
-#include "src/profiling/memory/shared_ring_buffer.h"
 
 #include <sys/socket.h>
 #include <sys/types.h>
 
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include <bionic/mte.h>
-#else
-struct ScopedDisableMTE {
-  // Silence unused variable warnings in non-Android builds.
-  ScopedDisableMTE() {}
-};
-#endif
-
 namespace perfetto {
 namespace profiling {
 
 namespace {
-
 template <typename T>
 bool ViewAndAdvance(char** ptr, T** out, const char* end) {
   if (end - sizeof(T) < *ptr)
@@ -50,77 +39,72 @@
 // We need this to prevent crashes due to FORTIFY_SOURCE.
 void UnsafeMemcpy(char* dest, const char* src, size_t n)
     __attribute__((no_sanitize("address", "hwaddress"))) {
-  ScopedDisableMTE m;
   for (size_t i = 0; i < n; ++i) {
     dest[i] = src[i];
   }
 }
+}  // namespace
 
-template <typename F>
-int64_t WithBuffer(SharedRingBuffer* shmem, size_t total_size, F fn) {
+bool SendWireMessage(SharedRingBuffer* shmem, const WireMessage& msg) {
+  uint64_t total_size;
+  struct iovec iovecs[3] = {};
+  // TODO(fmayer): Maye pack these two.
+  iovecs[0].iov_base = const_cast<RecordType*>(&msg.record_type);
+  iovecs[0].iov_len = sizeof(msg.record_type);
+  if (msg.alloc_header) {
+    PERFETTO_DCHECK(msg.record_type == RecordType::Malloc);
+    iovecs[1].iov_base = msg.alloc_header;
+    iovecs[1].iov_len = sizeof(*msg.alloc_header);
+  } else if (msg.free_header) {
+    PERFETTO_DCHECK(msg.record_type == RecordType::Free);
+    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.");
+    errno = EINVAL;
+    return false;
+  }
+
+  iovecs[2].iov_base = msg.payload;
+  iovecs[2].iov_len = msg.payload_size;
+
+  struct msghdr hdr = {};
+  hdr.msg_iov = iovecs;
+  if (msg.payload) {
+    hdr.msg_iovlen = base::ArraySize(iovecs);
+    total_size = iovecs[0].iov_len + iovecs[1].iov_len + iovecs[2].iov_len;
+  } else {
+    // If we are not sending payload, just ignore that iovec.
+    hdr.msg_iovlen = base::ArraySize(iovecs) - 1;
+    total_size = iovecs[0].iov_len + iovecs[1].iov_len;
+  }
+
   SharedRingBuffer::Buffer buf;
   {
     ScopedSpinlock lock = shmem->AcquireLock(ScopedSpinlock::Mode::Try);
     if (!lock.locked()) {
       PERFETTO_DLOG("Failed to acquire spinlock.");
       errno = EAGAIN;
-      return -1;
+      return false;
     }
-    buf = shmem->BeginWrite(lock, total_size);
+    buf = shmem->BeginWrite(lock, static_cast<size_t>(total_size));
   }
   if (!buf) {
     PERFETTO_DLOG("Buffer overflow.");
     shmem->EndWrite(std::move(buf));
     errno = EAGAIN;
-    return -1;
+    return false;
   }
 
-  fn(&buf);
-
-  auto bytes_free = buf.bytes_free;
+  size_t offset = 0;
+  for (size_t i = 0; i < hdr.msg_iovlen; ++i) {
+    UnsafeMemcpy(reinterpret_cast<char*>(buf.data + offset),
+                 reinterpret_cast<const char*>(hdr.msg_iov[i].iov_base),
+                 hdr.msg_iov[i].iov_len);
+    offset += hdr.msg_iov[i].iov_len;
+  }
   shmem->EndWrite(std::move(buf));
-  return static_cast<int64_t>(bytes_free);
-}
-
-}  // namespace
-
-int64_t SendWireMessage(SharedRingBuffer* shmem, const WireMessage& msg) {
-  switch (msg.record_type) {
-    case RecordType::Malloc: {
-      size_t total_size = sizeof(msg.record_type) + sizeof(*msg.alloc_header) +
-                          msg.payload_size;
-      return WithBuffer(
-          shmem, total_size, [msg](SharedRingBuffer::Buffer* buf) {
-            memcpy(buf->data, &msg.record_type, sizeof(msg.record_type));
-            memcpy(buf->data + sizeof(msg.record_type), msg.alloc_header,
-                   sizeof(*msg.alloc_header));
-            UnsafeMemcpy(reinterpret_cast<char*>(buf->data) +
-                             sizeof(msg.record_type) +
-                             sizeof(*msg.alloc_header),
-                         msg.payload, msg.payload_size);
-          });
-    }
-    case RecordType::Free: {
-      constexpr size_t total_size =
-          sizeof(msg.record_type) + sizeof(*msg.free_header);
-      return WithBuffer(
-          shmem, total_size, [msg](SharedRingBuffer::Buffer* buf) {
-            memcpy(buf->data, &msg.record_type, sizeof(msg.record_type));
-            memcpy(buf->data + sizeof(msg.record_type), msg.free_header,
-                   sizeof(*msg.free_header));
-          });
-    }
-    case RecordType::HeapName: {
-      constexpr size_t total_size =
-          sizeof(msg.record_type) + sizeof(*msg.heap_name_header);
-      return WithBuffer(
-          shmem, total_size, [msg](SharedRingBuffer::Buffer* buf) {
-            memcpy(buf->data, &msg.record_type, sizeof(msg.record_type));
-            memcpy(buf->data + sizeof(msg.record_type), msg.heap_name_header,
-                   sizeof(*msg.heap_name_header));
-          });
-    }
-  }
+  return true;
 }
 
 bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out) {
@@ -147,12 +131,7 @@
     }
     out->payload_size = static_cast<size_t>(end - buf);
   } else if (*record_type == RecordType::Free) {
-    if (!ViewAndAdvance<FreeEntry>(&buf, &out->free_header, end)) {
-      PERFETTO_DFATAL_OR_ELOG("Cannot read free header.");
-      return false;
-    }
-  } else if (*record_type == RecordType::HeapName) {
-    if (!ViewAndAdvance<HeapName>(&buf, &out->heap_name_header, end)) {
+    if (!ViewAndAdvance<FreeBatch>(&buf, &out->free_header, end)) {
       PERFETTO_DFATAL_OR_ELOG("Cannot read free header.");
       return false;
     }
@@ -163,21 +142,5 @@
   return true;
 }
 
-uint64_t GetHeapSamplingInterval(const ClientConfiguration& cli_config,
-                                 const char* heap_name) {
-  for (uint32_t i = 0; i < cli_config.num_heaps; ++i) {
-    const ClientConfigurationHeap& heap = cli_config.heaps[i];
-    static_assert(sizeof(heap.name) == HEAPPROFD_HEAP_NAME_SZ,
-                  "correct heap name size");
-    if (strncmp(&heap.name[0], heap_name, HEAPPROFD_HEAP_NAME_SZ) == 0) {
-      return heap.interval;
-    }
-  }
-  if (cli_config.all_heaps) {
-    return cli_config.default_interval;
-  }
-  return 0;
-}
-
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index f1989b7..f1208d7 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -29,9 +29,7 @@
 #include <unwindstack/MachineX86.h>
 #include <unwindstack/MachineX86_64.h>
 
-#include "perfetto/heap_profile.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
-#include "src/profiling/memory/util.h"
 
 namespace perfetto {
 
@@ -41,6 +39,26 @@
 
 namespace profiling {
 
+struct ClientConfiguration {
+  // On average, sample one allocation every interval bytes,
+  // If interval == 1, sample every allocation.
+  // Must be >= 1.
+  uint64_t interval;
+  bool block_client;
+  uint64_t block_client_timeout_us;
+  bool disable_fork_teardown;
+  bool disable_vfork_detection;
+};
+
+// Types needed for the wire format used for communication between the client
+// and heapprofd. The basic format of a record is
+// record size (uint64_t) | record type (RecordType = uint64_t) | record
+// If record type is malloc, the record format is AllocMetdata | raw stack.
+// If the record type is free, the record is a sequence of FreeBatchEntry.
+
+// Use uint64_t to make sure the following data is aligned as 64bit is the
+// strongest alignment requirement.
+
 // C++11 std::max is not constexpr.
 constexpr size_t constexpr_max(size_t x, size_t y) {
   return x > y ? x : y;
@@ -63,92 +81,48 @@
   );
 // clang-format on
 
-// Types needed for the wire format used for communication between the client
-// and heapprofd. The basic format of a record sent by the client is
-// record size (uint64_t) | record type (RecordType = uint64_t) | record
-// If record type is Malloc, the record format is AllocMetdata | raw stack.
-// If the record type is Free, the record is a FreeEntry.
-// If record type is HeapName, the record is a HeapName.
-// On connect, heapprofd sends one ClientConfiguration struct over the control
-// socket.
-
-// Use uint64_t to make sure the following data is aligned as 64bit is the
-// strongest alignment requirement.
-
-struct ClientConfigurationHeap {
-  char name[HEAPPROFD_HEAP_NAME_SZ];
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) interval;
-};
-
-struct ClientConfiguration {
-  // On average, sample one allocation every interval bytes,
-  // If interval == 1, sample every allocation.
-  // Must be >= 1.
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) default_interval;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) block_client_timeout_us;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_heaps;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) adaptive_sampling_shmem_threshold;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t)
-  adaptive_sampling_max_sampling_interval_bytes;
-  alignas(8) ClientConfigurationHeap heaps[64];
-  PERFETTO_CROSS_ABI_ALIGNED(bool) block_client;
-  PERFETTO_CROSS_ABI_ALIGNED(bool) disable_fork_teardown;
-  PERFETTO_CROSS_ABI_ALIGNED(bool) disable_vfork_detection;
-  PERFETTO_CROSS_ABI_ALIGNED(bool) all_heaps;
-  // Just double check that the array sizes are in correct order.
-};
+constexpr size_t kFreeBatchSize = 1024;
 
 enum class RecordType : uint64_t {
   Free = 0,
   Malloc = 1,
-  HeapName = 2,
 };
 
-// Make the whole struct 8-aligned. This is to make sizeof(AllocMetdata)
-// the same on 32 and 64-bit.
-struct alignas(8) AllocMetadata {
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
+struct AllocMetadata {
+  uint64_t sequence_number;
   // Size of the allocation that was made.
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_size;
+  uint64_t alloc_size;
   // Total number of bytes attributed to this allocation.
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_size;
+  uint64_t sample_size;
   // Pointer returned by malloc(2) for this allocation.
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_address;
+  uint64_t alloc_address;
   // Current value of the stack pointer.
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) stack_pointer;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) clock_monotonic_coarse_timestamp;
-  // unwindstack::AsmGetRegs assumes this is aligned.
-  alignas(8) char register_data[kMaxRegisterDataSize];
-  PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
+  uint64_t stack_pointer;
+  // Offset of the data at stack_pointer from the start of this record.
+  uint64_t stack_pointer_offset;
+  uint64_t clock_monotonic_coarse_timestamp;
+  alignas(uint64_t) char register_data[kMaxRegisterDataSize];
   // CPU architecture of the client.
-  PERFETTO_CROSS_ABI_ALIGNED(unwindstack::ArchEnum) arch;
+  unwindstack::ArchEnum arch;
 };
 
-struct FreeEntry {
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) addr;
-  PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
+struct FreeBatchEntry {
+  uint64_t sequence_number;
+  uint64_t addr;
 };
 
-struct HeapName {
-  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_interval;
-  PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
-  PERFETTO_CROSS_ABI_ALIGNED(char) heap_name[HEAPPROFD_HEAP_NAME_SZ];
-};
+struct FreeBatch {
+  uint64_t num_entries;
+  uint64_t clock_monotonic_coarse_timestamp;
+  FreeBatchEntry entries[kFreeBatchSize];
 
-// Make sure the sizes do not change on different architectures.
-static_assert(sizeof(AllocMetadata) == 328,
-              "AllocMetadata needs to be the same size across ABIs.");
-static_assert(sizeof(FreeEntry) == 24,
-              "FreeEntry needs to be the same size across ABIs.");
-static_assert(sizeof(HeapName) == 80,
-              "HeapName needs to be the same size across ABIs.");
-static_assert(sizeof(ClientConfiguration) == 4656,
-              "ClientConfiguration needs to be the same size across ABIs.");
+  FreeBatch() { num_entries = 0; }
+};
 
 enum HandshakeFDs : size_t {
   kHandshakeMaps = 0,
   kHandshakeMem,
+  kHandshakePageIdle,
   kHandshakeSize,
 };
 
@@ -156,23 +130,19 @@
   RecordType record_type;
 
   AllocMetadata* alloc_header;
-  FreeEntry* free_header;
-  HeapName* heap_name_header;
+  FreeBatch* free_header;
 
   char* payload;
   size_t payload_size;
 };
 
-int64_t SendWireMessage(SharedRingBuffer* buf, const WireMessage& msg);
+bool SendWireMessage(SharedRingBuffer* buf, const WireMessage& msg);
 
 // Parse message received over the wire.
 // |buf| has to outlive |out|.
 // If buf is not a valid message, return false.
 bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out);
 
-uint64_t GetHeapSamplingInterval(const ClientConfiguration& cli_config,
-                                 const char* heap_name);
-
 constexpr const char* kHeapprofdSocketEnvVar = "ANDROID_SOCKET_heapprofd";
 constexpr const char* kHeapprofdSocketFile = "/dev/socket/heapprofd";
 
diff --git a/src/profiling/memory/wire_protocol_unittest.cc b/src/profiling/memory/wire_protocol_unittest.cc
index 3f7e494..462ea06 100644
--- a/src/profiling/memory/wire_protocol_unittest.cc
+++ b/src/profiling/memory/wire_protocol_unittest.cc
@@ -29,22 +29,25 @@
 
 bool operator==(const AllocMetadata& one, const AllocMetadata& other);
 bool operator==(const AllocMetadata& one, const AllocMetadata& other) {
-  return std::tie(one.sequence_number, one.alloc_size, one.sample_size,
-                  one.alloc_address, one.stack_pointer,
-                  one.clock_monotonic_coarse_timestamp, one.heap_id,
-                  one.arch) == std::tie(other.sequence_number, other.alloc_size,
-                                        other.sample_size, other.alloc_address,
-                                        other.stack_pointer,
-                                        other.clock_monotonic_coarse_timestamp,
-                                        other.heap_id, other.arch) &&
+  return std::tie(one.sequence_number, one.alloc_size, one.alloc_address,
+                  one.stack_pointer, one.stack_pointer_offset, one.arch) ==
+             std::tie(other.sequence_number, other.alloc_size,
+                      other.alloc_address, other.stack_pointer,
+                      other.stack_pointer_offset, other.arch) &&
          memcmp(one.register_data, other.register_data, kMaxRegisterDataSize) ==
              0;
 }
 
-bool operator==(const FreeEntry& one, const FreeEntry& other);
-bool operator==(const FreeEntry& one, const FreeEntry& other) {
-  return (std::tie(one.sequence_number, one.addr, one.heap_id) ==
-          std::tie(other.sequence_number, other.addr, other.heap_id));
+bool operator==(const FreeBatch& one, const FreeBatch& other);
+bool operator==(const FreeBatch& one, const FreeBatch& other) {
+  if (one.num_entries != other.num_entries)
+    return false;
+  for (size_t i = 0; i < one.num_entries; ++i) {
+    if (std::tie(one.entries[i].sequence_number, one.entries[i].addr) !=
+        std::tie(other.entries[i].sequence_number, other.entries[i].addr))
+      return false;
+  }
+  return true;
 }
 
 namespace {
@@ -76,6 +79,7 @@
   metadata.alloc_size = 0xB1B2B3B4B5B6B7B8;
   metadata.alloc_address = 0xC1C2C3C4C5C6C7C8;
   metadata.stack_pointer = 0xD1D2D3D4D5D6D7D8;
+  metadata.stack_pointer_offset = 0xE1E2E3E4E5E6E7E8;
   metadata.arch = unwindstack::ARCH_X86;
   for (size_t i = 0; i < kMaxRegisterDataSize; ++i)
     metadata.register_data[i] = 0x66;
@@ -88,7 +92,7 @@
   ASSERT_TRUE(shmem_client->is_valid());
   auto shmem_server = SharedRingBuffer::Attach(CopyFD(shmem_client->fd()));
 
-  ASSERT_GE(SendWireMessage(&shmem_client.value(), msg), 0);
+  ASSERT_TRUE(SendWireMessage(&shmem_client.value(), msg));
 
   auto buf = shmem_server->BeginRead();
   ASSERT_TRUE(buf);
@@ -106,17 +110,20 @@
 TEST(WireProtocolTest, FreeMessage) {
   WireMessage msg = {};
   msg.record_type = RecordType::Free;
-  FreeEntry entry = {};
-  entry.sequence_number = 0x111111111111111;
-  entry.addr = 0x222222222222222;
-  msg.free_header = &entry;
+  FreeBatch batch = {};
+  batch.num_entries = kFreeBatchSize;
+  for (size_t i = 0; i < kFreeBatchSize; ++i) {
+    batch.entries[i].sequence_number = 0x111111111111111;
+    batch.entries[i].addr = 0x222222222222222;
+  }
+  msg.free_header = &batch;
 
   auto shmem_client = SharedRingBuffer::Create(kShmemSize);
   ASSERT_TRUE(shmem_client);
   ASSERT_TRUE(shmem_client->is_valid());
   auto shmem_server = SharedRingBuffer::Attach(CopyFD(shmem_client->fd()));
 
-  ASSERT_GE(SendWireMessage(&shmem_client.value(), msg), 0);
+  ASSERT_TRUE(SendWireMessage(&shmem_client.value(), msg));
 
   auto buf = shmem_server->BeginRead();
   ASSERT_TRUE(buf);
@@ -130,47 +137,6 @@
   ASSERT_EQ(recv_msg.payload_size, msg.payload_size);
 }
 
-TEST(GetHeapSamplingInterval, Default) {
-  ClientConfiguration cli_config{};
-  cli_config.all_heaps = true;
-  cli_config.num_heaps = 0;
-  cli_config.default_interval = 4096u;
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
-}
-
-TEST(GetHeapSamplingInterval, Selected) {
-  ClientConfiguration cli_config{};
-  cli_config.all_heaps = false;
-  cli_config.num_heaps = 1;
-  cli_config.default_interval = 1;
-  memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
-  cli_config.heaps[0].interval = 4096u;
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 0u);
-}
-
-TEST(GetHeapSamplingInterval, SelectedAndDefault) {
-  ClientConfiguration cli_config{};
-  cli_config.all_heaps = true;
-  cli_config.num_heaps = 1;
-  cli_config.default_interval = 1;
-  memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
-  cli_config.heaps[0].interval = 4096u;
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
-}
-
-TEST(GetHeapSamplingInterval, DisabledAndDefault) {
-  ClientConfiguration cli_config{};
-  cli_config.all_heaps = true;
-  cli_config.num_heaps = 1;
-  cli_config.default_interval = 1;
-  memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
-  cli_config.heaps[0].interval = 0u;
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 0u);
-  EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
-}
-
 }  // namespace
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/wrap_allocators.cc b/src/profiling/memory/wrap_allocators.cc
deleted file mode 100644
index 696337a..0000000
--- a/src/profiling/memory/wrap_allocators.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/heap_profile.h"
-#include "src/profiling/memory/wrap_allocators.h"
-
-namespace perfetto {
-namespace profiling {
-
-namespace {
-size_t RoundUpToSysPageSize(size_t req_size) {
-  const size_t page_size = base::GetSysPageSize();
-  return (req_size + page_size - 1) & ~(page_size - 1);
-}
-}  // namespace
-
-void* wrap_malloc(uint32_t heap_id, void* (*fn)(size_t), size_t size) {
-  void* addr = fn(size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                size);
-  return addr;
-}
-
-void* wrap_calloc(uint32_t heap_id,
-                  void* (*fn)(size_t, size_t),
-                  size_t nmemb,
-                  size_t size) {
-  void* addr = fn(nmemb, size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                nmemb * size);
-  return addr;
-}
-
-void* wrap_memalign(uint32_t heap_id,
-                    void* (*fn)(size_t, size_t),
-                    size_t alignment,
-                    size_t size) {
-  void* addr = fn(alignment, size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                size);
-  return addr;
-}
-
-int wrap_posix_memalign(uint32_t heap_id,
-                        int (*fn)(void**, size_t, size_t),
-                        void** memptr,
-                        size_t alignment,
-                        size_t size) {
-  int res = fn(memptr, alignment, size);
-  if (res != 0)
-    return res;
-
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(*memptr),
-                                size);
-  return 0;
-}
-
-// Note: we record the free before calling the backing implementation to make
-// sure that the address is not reused before we've processed the deallocation
-// (which includes assigning a sequence id to it).
-void wrap_free(uint32_t heap_id, void (*fn)(void*), void* pointer) {
-  // free on a nullptr is valid but has no effect. Short circuit here, for
-  // various advantages:
-  // * More efficient
-  // * Notably printf calls free(nullptr) even when it is used in a way
-  //   malloc-free way, as it unconditionally frees the pointer even if
-  //   it was never written to.
-  //   Short circuiting here makes it less likely to accidentally build
-  //   infinite recursion.
-  if (pointer == nullptr)
-    return;
-
-  AHeapProfile_reportFree(heap_id, reinterpret_cast<uint64_t>(pointer));
-  return fn(pointer);
-}
-
-// As with the free, we record the deallocation before calling the backing
-// implementation to make sure the address is still exclusive while we're
-// processing it.
-void* wrap_realloc(uint32_t heap_id,
-                   void* (*fn)(void*, size_t),
-                   void* pointer,
-                   size_t size) {
-  if (pointer)
-    AHeapProfile_reportFree(heap_id, reinterpret_cast<uint64_t>(pointer));
-  void* addr = fn(pointer, size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                size);
-  return addr;
-}
-
-void* wrap_pvalloc(uint32_t heap_id, void* (*fn)(size_t), size_t size) {
-  void* addr = fn(size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                RoundUpToSysPageSize(size));
-  return addr;
-}
-
-void* wrap_valloc(uint32_t heap_id, void* (*fn)(size_t), size_t size) {
-  void* addr = fn(size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                size);
-  return addr;
-}
-
-void* wrap_reallocarray(uint32_t heap_id,
-                        void* (*fn)(void*, size_t, size_t),
-                        void* pointer,
-                        size_t nmemb,
-                        size_t size) {
-  if (pointer)
-    AHeapProfile_reportFree(heap_id, reinterpret_cast<uint64_t>(pointer));
-  void* addr = fn(pointer, nmemb, size);
-  AHeapProfile_reportAllocation(heap_id, reinterpret_cast<uint64_t>(addr),
-                                nmemb * size);
-  return addr;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/wrap_allocators.h b/src/profiling/memory/wrap_allocators.h
deleted file mode 100644
index ce9fb3e..0000000
--- a/src/profiling/memory/wrap_allocators.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_MEMORY_WRAP_ALLOCATORS_H_
-#define SRC_PROFILING_MEMORY_WRAP_ALLOCATORS_H_
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-namespace perfetto {
-namespace profiling {
-
-void* wrap_malloc(uint32_t heap_id, void* (*fn)(size_t), size_t size);
-void* wrap_calloc(uint32_t heap_id,
-                  void* (*fn)(size_t, size_t),
-                  size_t nmemb,
-                  size_t size);
-void* wrap_memalign(uint32_t heap_id,
-                    void* (*fn)(size_t, size_t),
-                    size_t alignment,
-                    size_t size);
-int wrap_posix_memalign(uint32_t heap_id,
-                        int (*fn)(void**, size_t, size_t),
-                        void** memptr,
-                        size_t alignment,
-                        size_t size);
-void wrap_free(uint32_t heap_id, void (*fn)(void*), void* pointer);
-void* wrap_realloc(uint32_t heap_id,
-                   void* (*fn)(void*, size_t),
-                   void* pointer,
-                   size_t size);
-void* wrap_pvalloc(uint32_t heap_id, void* (*fn)(size_t), size_t size);
-void* wrap_valloc(uint32_t heap_id, void* (*fn)(size_t), size_t size);
-
-void* wrap_reallocarray(uint32_t heap_id,
-                        void* (*fn)(void*, size_t, size_t),
-                        void* pointer,
-                        size_t nmemb,
-                        size_t size);
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_WRAP_ALLOCATORS_H_
diff --git a/src/profiling/perf/BUILD.gn b/src/profiling/perf/BUILD.gn
index 899e09c..b715de1 100644
--- a/src/profiling/perf/BUILD.gn
+++ b/src/profiling/perf/BUILD.gn
@@ -52,22 +52,17 @@
     ":proc_descriptors",
     "../../../gn:default_deps",
     "../../../include/perfetto/profiling:normalize",
-    "../../../protos/perfetto/common:cpp",
-    "../../../protos/perfetto/common:zero",
     "../../../protos/perfetto/config:cpp",
-    "../../../protos/perfetto/config/profiling:cpp",
+    "../../../protos/perfetto/config/profiling:zero",
     "../../../protos/perfetto/trace:zero",
     "../../../protos/perfetto/trace/profiling:zero",
     "../../../src/base",
     "../../../src/base:unix_socket",
-    "../../../src/traced/probes/ftrace:ftrace_procfs",
     "../../../src/tracing/ipc/producer",
     "../common:callstack_trie",
     "../common:interner",
     "../common:interning_output",
     "../common:proc_utils",
-    "../common:producer_support",
-    "../common:profiler_guardrails",
   ]
   sources = [
     "event_config.cc",
@@ -98,7 +93,6 @@
     "../../../gn:default_deps",
     "../../../include/perfetto/ext/tracing/core",
     "../../../src/base",
-    "../../../src/kallsyms",
     "../common:unwind_support",
   ]
   sources = [
@@ -139,7 +133,6 @@
     ":unwinding",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
-    "../../../protos/perfetto/common:cpp",
     "../../../protos/perfetto/config:cpp",
     "../../../protos/perfetto/config/profiling:cpp",
     "../../../protos/perfetto/trace:zero",
diff --git a/src/profiling/perf/common_types.h b/src/profiling/perf/common_types.h
index b201995..80a6105 100644
--- a/src/profiling/perf/common_types.h
+++ b/src/profiling/perf/common_types.h
@@ -31,16 +31,6 @@
 namespace perfetto {
 namespace profiling {
 
-// Data present in all types of samples.
-struct CommonSampleData {
-  uint16_t cpu_mode = PERF_RECORD_MISC_CPUMODE_UNKNOWN;
-  uint32_t cpu = 0;
-  pid_t pid = 0;
-  pid_t tid = 0;
-  uint64_t timestamp = 0;
-  uint64_t timebase_count = 0;
-};
-
 // A parsed perf sample record (PERF_RECORD_SAMPLE from the kernel buffer).
 // Self-contained, used as as input to the callstack unwinding.
 struct ParsedSample {
@@ -51,11 +41,13 @@
   ParsedSample(ParsedSample&&) noexcept = default;
   ParsedSample& operator=(ParsedSample&&) noexcept = default;
 
-  CommonSampleData common;
+  uint16_t cpu_mode = PERF_RECORD_MISC_CPUMODE_UNKNOWN;
+  uint32_t cpu = 0;
+  pid_t pid = 0;
+  pid_t tid = 0;
+  uint64_t timestamp = 0;
   std::unique_ptr<unwindstack::Regs> regs;
   std::vector<char> stack;
-  bool stack_maxed = false;
-  std::vector<uint64_t> kernel_ips;
 };
 
 // Entry in an unwinding queue. Either a sample that requires unwinding, or a
@@ -84,9 +76,12 @@
   CompletedSample(CompletedSample&&) noexcept = default;
   CompletedSample& operator=(CompletedSample&&) noexcept = default;
 
-  CommonSampleData common;
-  std::vector<unwindstack::FrameData> frames;
-  std::vector<std::string> build_ids;
+  uint16_t cpu_mode = PERF_RECORD_MISC_CPUMODE_UNKNOWN;
+  uint32_t cpu = 0;
+  pid_t pid = 0;
+  pid_t tid = 0;
+  uint64_t timestamp = 0;
+  std::vector<FrameData> frames;
   unwindstack::ErrorCode unwind_error = unwindstack::ERROR_NONE;
 };
 
diff --git a/src/profiling/perf/event_config.cc b/src/profiling/perf/event_config.cc
index a7b6533..eee209f 100644
--- a/src/profiling/perf/event_config.cc
+++ b/src/profiling/perf/event_config.cc
@@ -20,16 +20,13 @@
 #include <time.h>
 
 #include <unwindstack/Regs.h>
-#include <vector>
 
 #include "perfetto/base/flat_set.h"
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/profiling/normalize.h"
 #include "src/profiling/perf/regs_parsing.h"
 
-#include "protos/perfetto/common/perf_events.gen.h"
-#include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+#include "protos/perfetto/config/profiling/perf_event_config.pbzero.h"
 
 namespace perfetto {
 namespace profiling {
@@ -40,11 +37,11 @@
 constexpr uint32_t kDefaultReadTickPeriodMs = 100;
 constexpr uint32_t kDefaultRemoteDescriptorTimeoutMs = 100;
 
-base::Optional<std::string> Normalize(const std::string& src) {
+base::Optional<std::string> Normalize(const protozero::ConstChars& src) {
   // Construct a null-terminated string that will be mutated by the normalizer.
-  std::vector<char> base(src.size() + 1);
-  memcpy(base.data(), src.data(), src.size());
-  base[src.size()] = '\0';
+  std::vector<char> base(src.size + 1);
+  memcpy(base.data(), src.data, src.size);
+  base[src.size] = '\0';
 
   char* new_start = base.data();
   ssize_t new_sz = NormalizeCmdLine(&new_start, base.size());
@@ -57,82 +54,31 @@
                                           static_cast<size_t>(new_sz));
 }
 
-// Acceptable forms: "sched/sched_switch" or "sched:sched_switch".
-std::pair<std::string, std::string> SplitTracepointString(
-    const std::string& input) {
-  auto slash_pos = input.find("/");
-  if (slash_pos != std::string::npos)
-    return std::make_pair(input.substr(0, slash_pos),
-                          input.substr(slash_pos + 1));
-
-  auto colon_pos = input.find(":");
-  if (colon_pos != std::string::npos)
-    return std::make_pair(input.substr(0, colon_pos),
-                          input.substr(colon_pos + 1));
-
-  return std::make_pair("", input);
-}
-
-// If set, the returned id is guaranteed to be non-zero.
-base::Optional<uint32_t> ParseTracepointAndResolveId(
-    const protos::gen::PerfEvents::Tracepoint& tracepoint,
-    EventConfig::tracepoint_id_fn_t tracepoint_id_lookup) {
-  std::string full_name = tracepoint.name();
-  std::string tp_group;
-  std::string tp_name;
-  std::tie(tp_group, tp_name) = SplitTracepointString(full_name);
-  if (tp_group.empty() || tp_name.empty()) {
-    PERFETTO_ELOG(
-        "Invalid tracepoint format: %s. Should be a full path like "
-        "sched:sched_switch or sched/sched_switch.",
-        full_name.c_str());
-    return base::nullopt;
-  }
-
-  uint32_t tracepoint_id = tracepoint_id_lookup(tp_group, tp_name);
-  if (!tracepoint_id) {
-    PERFETTO_ELOG(
-        "Failed to resolve tracepoint %s to its id. Check that tracefs is "
-        "accessible and the event exists.",
-        full_name.c_str());
-    return base::nullopt;
-  }
-  return base::make_optional(tracepoint_id);
-}
-
-// Returns |base::nullopt| if any of the input cmdlines couldn't be normalized.
-// |T| is either gen::PerfEventConfig or gen::PerfEventConfig::Scope.
-template <typename T>
-base::Optional<TargetFilter> ParseTargetFilter(const T& cfg) {
+// returns |base::nullopt| if any of the input cmdlines couldn't be normalized.
+base::Optional<TargetFilter> ParseTargetFilter(
+    const protos::pbzero::PerfEventConfig::Decoder& cfg) {
   TargetFilter filter;
-  for (const auto& str : cfg.target_cmdline()) {
-    base::Optional<std::string> opt = Normalize(str);
-    if (!opt.has_value()) {
-      PERFETTO_ELOG("Failure normalizing cmdline: [%s]", str.c_str());
+  for (auto it = cfg.target_cmdline(); it; ++it) {
+    base::Optional<std::string> opt = Normalize(*it);
+    if (!opt.has_value())
       return base::nullopt;
-    }
     filter.cmdlines.insert(std::move(opt.value()));
   }
 
-  for (const auto& str : cfg.exclude_cmdline()) {
-    base::Optional<std::string> opt = Normalize(str);
-    if (!opt.has_value()) {
-      PERFETTO_ELOG("Failure normalizing cmdline: [%s]", str.c_str());
+  for (auto it = cfg.exclude_cmdline(); it; ++it) {
+    base::Optional<std::string> opt = Normalize(*it);
+    if (!opt.has_value())
       return base::nullopt;
-    }
     filter.exclude_cmdlines.insert(std::move(opt.value()));
   }
 
-  for (const int32_t pid : cfg.target_pid()) {
-    filter.pids.insert(pid);
+  for (auto it = cfg.target_pid(); it; ++it) {
+    filter.pids.insert(*it);
   }
 
-  for (const int32_t pid : cfg.exclude_pid()) {
-    filter.exclude_pids.insert(pid);
+  for (auto it = cfg.exclude_pid(); it; ++it) {
+    filter.exclude_pids.insert(*it);
   }
-
-  filter.additional_cmdline_count = cfg.additional_cmdline_count();
-
   return base::make_optional(std::move(filter));
 }
 
@@ -155,253 +101,91 @@
   return base::make_optional(config_value);
 }
 
-base::Optional<PerfCounter> ToPerfCounter(
-    protos::gen::PerfEvents::Counter pb_enum) {
-  using protos::gen::PerfEvents;
-  switch (static_cast<int>(pb_enum)) {  // cast to pacify -Wswitch-enum
-    case PerfEvents::SW_CPU_CLOCK:
-      return PerfCounter::Counter(PerfEvents::SW_CPU_CLOCK, PERF_TYPE_SOFTWARE,
-                                  PERF_COUNT_SW_CPU_CLOCK);
-    case PerfEvents::SW_PAGE_FAULTS:
-      return PerfCounter::Counter(PerfEvents::SW_PAGE_FAULTS,
-                                  PERF_TYPE_SOFTWARE,
-                                  PERF_COUNT_SW_PAGE_FAULTS);
-    case PerfEvents::HW_CPU_CYCLES:
-      return PerfCounter::Counter(PerfEvents::HW_CPU_CYCLES, PERF_TYPE_HARDWARE,
-                                  PERF_COUNT_HW_CPU_CYCLES);
-    case PerfEvents::HW_INSTRUCTIONS:
-      return PerfCounter::Counter(PerfEvents::HW_INSTRUCTIONS,
-                                  PERF_TYPE_HARDWARE,
-                                  PERF_COUNT_HW_INSTRUCTIONS);
-    default:
-      PERFETTO_ELOG("Unrecognised PerfEvents::Counter enum value: %zu",
-                    static_cast<size_t>(pb_enum));
-      return base::nullopt;
-  }
-}
-
 }  // namespace
 
 // static
-PerfCounter PerfCounter::Counter(protos::gen::PerfEvents::Counter counter,
-                                 uint32_t type,
-                                 uint32_t config) {
-  PerfCounter ret;
-  ret.counter = counter;
-  ret.type = type;
-  ret.config = config;
-  return ret;
-}
-
-// static
-PerfCounter PerfCounter::Tracepoint(
-    protos::gen::PerfEvents::Tracepoint tracepoint,
-    uint32_t id) {
-  PerfCounter ret;
-  ret.tracepoint = std::move(tracepoint);
-  ret.type = PERF_TYPE_TRACEPOINT;
-  ret.config = id;
-  return ret;
-}
-
-// static
 base::Optional<EventConfig> EventConfig::Create(
-    const DataSourceConfig& ds_config,
-    tracepoint_id_fn_t tracepoint_id_lookup) {
-  protos::gen::PerfEventConfig pb_config;
-  if (!pb_config.ParseFromString(ds_config.perf_event_config_raw()))
+    const DataSourceConfig& ds_config) {
+  protos::pbzero::PerfEventConfig::Decoder pb_config(
+      ds_config.perf_event_config_raw());
+
+  base::Optional<TargetFilter> filter = ParseTargetFilter(pb_config);
+  if (!filter.has_value())
     return base::nullopt;
 
-  return EventConfig::Create(pb_config, ds_config, tracepoint_id_lookup);
-}
-
-// static
-base::Optional<EventConfig> EventConfig::Create(
-    const protos::gen::PerfEventConfig& pb_config,
-    const DataSourceConfig& raw_ds_config,
-    tracepoint_id_fn_t tracepoint_id_lookup) {
-  // Timebase: sampling interval.
-  uint64_t sampling_frequency = 0;
-  uint64_t sampling_period = 0;
-  if (pb_config.timebase().period()) {
-    sampling_period = pb_config.timebase().period();
-  } else if (pb_config.timebase().frequency()) {
-    sampling_frequency = pb_config.timebase().frequency();
-  } else if (pb_config.sampling_frequency()) {  // backwards compatibility
-    sampling_frequency = pb_config.sampling_frequency();
-  } else {
-    sampling_frequency = kDefaultSamplingFrequencyHz;
-  }
-  PERFETTO_DCHECK(sampling_period && !sampling_frequency ||
-                  !sampling_period && sampling_frequency);
-
-  // Timebase event. Default: CPU timer.
-  PerfCounter timebase_event;
-  if (pb_config.timebase().has_counter()) {
-    auto maybe_counter = ToPerfCounter(pb_config.timebase().counter());
-    if (!maybe_counter)
-      return base::nullopt;
-    timebase_event = *maybe_counter;
-
-  } else if (pb_config.timebase().has_tracepoint()) {
-    const auto& tracepoint_pb = pb_config.timebase().tracepoint();
-    base::Optional<uint32_t> maybe_id =
-        ParseTracepointAndResolveId(tracepoint_pb, tracepoint_id_lookup);
-    if (!maybe_id)
-      return base::nullopt;
-    timebase_event = PerfCounter::Tracepoint(tracepoint_pb, *maybe_id);
-
-  } else {
-    timebase_event =
-        PerfCounter::Counter(protos::gen::PerfEvents::PerfEvents::SW_CPU_CLOCK,
-                             PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK);
-  }
-
-  // Callstack sampling.
-  bool sample_callstacks = false;
-  bool kernel_frames = false;
-  TargetFilter target_filter;
-  bool legacy_config = pb_config.all_cpus();  // all_cpus was mandatory before
-  if (pb_config.has_callstack_sampling() || legacy_config) {
-    sample_callstacks = true;
-
-    // Process scoping.
-    auto maybe_filter =
-        pb_config.callstack_sampling().has_scope()
-            ? ParseTargetFilter(pb_config.callstack_sampling().scope())
-            : ParseTargetFilter(pb_config);  // backwards compatibility
-    if (!maybe_filter.has_value())
-      return base::nullopt;
-
-    target_filter = std::move(maybe_filter.value());
-
-    // Inclusion of kernel callchains.
-    kernel_frames = pb_config.callstack_sampling().kernel_frames() ||
-                    pb_config.kernel_frames();
-  }
-
-  // Ring buffer options.
   base::Optional<uint32_t> ring_buffer_pages =
       ChooseActualRingBufferPages(pb_config.ring_buffer_pages());
   if (!ring_buffer_pages.has_value())
     return base::nullopt;
 
-  uint32_t read_tick_period_ms = pb_config.ring_buffer_read_period_ms()
-                                     ? pb_config.ring_buffer_read_period_ms()
-                                     : kDefaultReadTickPeriodMs;
-
-  // Calculate a rough upper limit for the amount of samples the producer
-  // should read per read tick, as a safeguard against getting stuck chasing the
-  // ring buffer head indefinitely.
-  uint64_t samples_per_tick_limit = 0;
-  if (sampling_frequency) {
-    // expected = rate * period, with a conversion of period from ms to s:
-    uint64_t expected_samples_per_tick =
-        1 + (sampling_frequency * read_tick_period_ms) / 1000;
-    // Double the the limit to account of actual sample rate uncertainties, as
-    // well as any other factors:
-    samples_per_tick_limit = 2 * expected_samples_per_tick;
-  } else {  // sampling_period
-    // We don't know the sample rate that a fixed period would cause, but we can
-    // still estimate how many samples will fit in one pass of the ring buffer
-    // (with the assumption that we don't want to read more than one buffer's
-    // capacity within a tick).
-    // TODO(rsavitski): for now, make an extremely conservative guess of an 8
-    // byte sample (stack sampling samples can be up to 64KB). This is most
-    // likely as good as no limit in practice.
-    samples_per_tick_limit = *ring_buffer_pages * (base::kPageSize / 8);
-  }
-  PERFETTO_DLOG("Capping samples (not records) per tick to [%" PRIu64 "]",
-                samples_per_tick_limit);
-  if (samples_per_tick_limit == 0)
-    return base::nullopt;
-
-  // Optional footprint controls.
-  uint64_t max_enqueued_footprint_bytes =
-      pb_config.max_enqueued_footprint_kb() * 1024;
-
-  // Android-specific options.
   uint32_t remote_descriptor_timeout_ms =
       pb_config.remote_descriptor_timeout_ms()
           ? pb_config.remote_descriptor_timeout_ms()
           : kDefaultRemoteDescriptorTimeoutMs;
 
-  // Build the underlying syscall config struct.
-  perf_event_attr pe = {};
-  pe.size = sizeof(perf_event_attr);
-  pe.disabled = 1;  // will be activated via ioctl
+  uint32_t read_tick_period_ms = pb_config.ring_buffer_read_period_ms()
+                                     ? pb_config.ring_buffer_read_period_ms()
+                                     : kDefaultReadTickPeriodMs;
 
-  // Sampling timebase.
-  pe.type = timebase_event.type;
-  pe.config = timebase_event.config;
-  if (sampling_frequency) {
-    pe.freq = true;
-    pe.sample_freq = sampling_frequency;
-  } else {
-    pe.sample_period = sampling_period;
-  }
+  uint32_t sampling_frequency = pb_config.sampling_frequency()
+                                    ? pb_config.sampling_frequency()
+                                    : kDefaultSamplingFrequencyHz;
 
-  // What the samples will contain.
-  pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_READ;
-  // PERF_SAMPLE_TIME:
-  // We used to use CLOCK_BOOTTIME, but that is not nmi-safe, and therefore
-  // works only for software events.
-  pe.clockid = CLOCK_MONOTONIC_RAW;
-  pe.use_clockid = true;
+  // Take the ratio of sampling and reading frequencies, which gives the
+  // upper bound on number of samples per tick (for a single per-cpu buffer).
+  // Overflow not a concern for sane inputs.
+  uint32_t expected_samples_per_tick =
+      1 + (sampling_frequency * read_tick_period_ms) / 1000;
 
-  if (sample_callstacks) {
-    pe.sample_type |= PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER;
-    // PERF_SAMPLE_STACK_USER:
-    // Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
-    // Note that the kernel still needs to make space for the other parts of the
-    // sample (up to the max record size of 64k), so the effective maximum
-    // can be lower than this.
-    pe.sample_stack_user = (1u << 16) - 256;
-    // PERF_SAMPLE_REGS_USER:
-    pe.sample_regs_user =
-        PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch());
+  // Use double the expected value as the actual guardrail (don't assume that
+  // periodic read task is as exact as the kernel).
+  uint32_t samples_per_tick_limit = 2 * expected_samples_per_tick;
+  PERFETTO_DCHECK(samples_per_tick_limit > 0);
+  PERFETTO_DLOG("Capping samples (not records) per tick to [%" PRIu32 "]",
+                samples_per_tick_limit);
 
-    // Optional kernel callchains:
-    if (kernel_frames) {
-      pe.sample_type |= PERF_SAMPLE_CALLCHAIN;
-      pe.exclude_callchain_user = true;
-    }
-  }
-
-  return EventConfig(
-      raw_ds_config, pe, timebase_event, sample_callstacks,
-      std::move(target_filter), kernel_frames, ring_buffer_pages.value(),
-      read_tick_period_ms, samples_per_tick_limit, remote_descriptor_timeout_ms,
-      pb_config.unwind_state_clear_period_ms(), max_enqueued_footprint_bytes,
-      pb_config.target_installed_by());
+  return EventConfig(pb_config, sampling_frequency, ring_buffer_pages.value(),
+                     read_tick_period_ms, samples_per_tick_limit,
+                     remote_descriptor_timeout_ms, std::move(filter.value()));
 }
 
-EventConfig::EventConfig(const DataSourceConfig& raw_ds_config,
-                         const perf_event_attr& pe,
-                         const PerfCounter& timebase_event,
-                         bool sample_callstacks,
-                         TargetFilter target_filter,
-                         bool kernel_frames,
+EventConfig::EventConfig(const protos::pbzero::PerfEventConfig::Decoder& cfg,
+                         uint32_t sampling_frequency,
                          uint32_t ring_buffer_pages,
                          uint32_t read_tick_period_ms,
-                         uint64_t samples_per_tick_limit,
+                         uint32_t samples_per_tick_limit,
                          uint32_t remote_descriptor_timeout_ms,
-                         uint32_t unwind_state_clear_period_ms,
-                         uint64_t max_enqueued_footprint_bytes,
-                         std::vector<std::string> target_installed_by)
-    : perf_event_attr_(pe),
-      timebase_event_(timebase_event),
-      sample_callstacks_(sample_callstacks),
-      target_filter_(std::move(target_filter)),
-      kernel_frames_(kernel_frames),
+                         TargetFilter target_filter)
+    : target_all_cpus_(cfg.all_cpus()),
       ring_buffer_pages_(ring_buffer_pages),
       read_tick_period_ms_(read_tick_period_ms),
       samples_per_tick_limit_(samples_per_tick_limit),
+      target_filter_(std::move(target_filter)),
       remote_descriptor_timeout_ms_(remote_descriptor_timeout_ms),
-      unwind_state_clear_period_ms_(unwind_state_clear_period_ms),
-      max_enqueued_footprint_bytes_(max_enqueued_footprint_bytes),
-      target_installed_by_(std::move(target_installed_by)),
-      raw_ds_config_(raw_ds_config) /* full copy */ {}
+      unwind_state_clear_period_ms_(cfg.unwind_state_clear_period_ms()) {
+  auto& pe = perf_event_attr_;
+  pe.size = sizeof(perf_event_attr);
+
+  pe.disabled = false;
+
+  // Ask the kernel to sample at a given frequency.
+  pe.type = PERF_TYPE_SOFTWARE;
+  pe.config = PERF_COUNT_SW_CPU_CLOCK;
+  pe.freq = true;
+  pe.sample_freq = sampling_frequency;
+
+  pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_STACK_USER |
+                   PERF_SAMPLE_REGS_USER;
+  // PERF_SAMPLE_TIME:
+  pe.clockid = CLOCK_BOOTTIME;
+  pe.use_clockid = true;
+  // PERF_SAMPLE_STACK_USER:
+  // Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
+  pe.sample_stack_user = (1u << 15);
+  // PERF_SAMPLE_REGS_USER:
+  pe.sample_regs_user =
+      PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch());
+}
 
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/perf/event_config.h b/src/profiling/perf/event_config.h
index d75c7c8..27e8915 100644
--- a/src/profiling/perf/event_config.h
+++ b/src/profiling/perf/event_config.h
@@ -17,11 +17,8 @@
 #ifndef SRC_PROFILING_PERF_EVENT_CONFIG_H_
 #define SRC_PROFILING_PERF_EVENT_CONFIG_H_
 
-#include <functional>
 #include <string>
-#include <vector>
 
-#include <inttypes.h>
 #include <linux/perf_event.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -30,48 +27,18 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/tracing/core/data_source_config.h"
 
-#include "protos/perfetto/common/perf_events.gen.h"
+#include "protos/perfetto/config/profiling/perf_event_config.pbzero.h"
 
 namespace perfetto {
-namespace protos {
-namespace gen {
-class PerfEventConfig;
-}  // namespace gen
-}  // namespace protos
-
 namespace profiling {
 
-// Parsed allow/deny-list for filtering samples.
-// An empty filter set means that all targets are allowed.
+// Parsed whitelist/blacklist for filtering samples.
+// An empty whitelist set means that all targets are allowed.
 struct TargetFilter {
   base::FlatSet<std::string> cmdlines;
   base::FlatSet<std::string> exclude_cmdlines;
   base::FlatSet<pid_t> pids;
   base::FlatSet<pid_t> exclude_pids;
-  uint32_t additional_cmdline_count = 0;
-};
-
-struct PerfCounter {
-  // Either a predefined counter, or a tracepoint:
-  protos::gen::PerfEvents::Counter counter =
-      protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
-  protos::gen::PerfEvents::Tracepoint tracepoint;
-
-  // sycall-level description of the event:
-  uint32_t type = 0;    // perf_event_attr.type
-  uint32_t config = 0;  // perf_event_attr.config
-
-  bool is_counter() const {
-    return counter != protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
-  }
-  bool is_tracepoint() const { return type == PERF_TYPE_TRACEPOINT; }
-
-  static PerfCounter Counter(protos::gen::PerfEvents::Counter counter,
-                             uint32_t type,
-                             uint32_t config);
-
-  static PerfCounter Tracepoint(protos::gen::PerfEvents::Tracepoint tracepoint,
-                                uint32_t id);
 };
 
 // Describes a single profiling configuration. Bridges the gap between the data
@@ -79,105 +46,59 @@
 // perf_event_open syscall.
 class EventConfig {
  public:
-  using tracepoint_id_fn_t =
-      std::function<uint32_t(const std::string&, const std::string&)>;
+  static base::Optional<EventConfig> Create(const DataSourceConfig& ds_config);
 
-  static base::Optional<EventConfig> Create(
-      const DataSourceConfig& ds_config,
-      tracepoint_id_fn_t tracepoint_id_lookup =
-          [](const std::string&, const std::string&) { return 0; });
-
-  static base::Optional<EventConfig> Create(
-      const protos::gen::PerfEventConfig& pb_config,
-      const DataSourceConfig& raw_ds_config,
-      tracepoint_id_fn_t tracepoint_id_lookup);
-
+  uint32_t target_all_cpus() const { return target_all_cpus_; }
   uint32_t ring_buffer_pages() const { return ring_buffer_pages_; }
   uint32_t read_tick_period_ms() const { return read_tick_period_ms_; }
-  uint64_t samples_per_tick_limit() const { return samples_per_tick_limit_; }
+  uint32_t samples_per_tick_limit() const { return samples_per_tick_limit_; }
   uint32_t remote_descriptor_timeout_ms() const {
     return remote_descriptor_timeout_ms_;
   }
   uint32_t unwind_state_clear_period_ms() const {
     return unwind_state_clear_period_ms_;
   }
-  uint64_t max_enqueued_footprint_bytes() const {
-    return max_enqueued_footprint_bytes_;
-  }
-  bool sample_callstacks() const { return sample_callstacks_; }
+
   const TargetFilter& filter() const { return target_filter_; }
-  bool kernel_frames() const { return kernel_frames_; }
+
   perf_event_attr* perf_attr() const {
     return const_cast<perf_event_attr*>(&perf_event_attr_);
   }
-  const PerfCounter& timebase_event() const { return timebase_event_; }
-  const std::vector<std::string>& target_installed_by() const {
-    return target_installed_by_;
-  }
-  const DataSourceConfig& raw_ds_config() const { return raw_ds_config_; }
 
  private:
-  EventConfig(const DataSourceConfig& raw_ds_config,
-              const perf_event_attr& pe,
-              const PerfCounter& timebase_event,
-              bool sample_callstacks,
-              TargetFilter target_filter,
-              bool kernel_frames,
+  EventConfig(const protos::pbzero::PerfEventConfig::Decoder& cfg,
+              uint32_t sampling_frequency,
               uint32_t ring_buffer_pages,
               uint32_t read_tick_period_ms,
-              uint64_t samples_per_tick_limit,
+              uint32_t samples_per_tick_limit,
               uint32_t remote_descriptor_timeout_ms,
-              uint32_t unwind_state_clear_period_ms,
-              uint64_t max_enqueued_footprint_bytes,
-              std::vector<std::string> target_installed_by);
+              TargetFilter target_filter);
 
-  // Parameter struct for the leader (timebase) perf_event_open syscall.
-  perf_event_attr perf_event_attr_ = {};
-
-  // Leader event, which is already described by |perf_event_attr_|. But this
-  // additionally carries a tracepoint filter if that needs to be set via an
-  // ioctl after creating the event.
-  const PerfCounter timebase_event_;
-
-  // TODO(rsavitski): consider adding an Optional<CallstackSampling> that
-  // contains the kernel_frames_ and target_filter, once the complexity warrants
-  // it.
-  const bool sample_callstacks_;
-
-  // Parsed allow/deny-list for filtering samples.
-  const TargetFilter target_filter_;
-
-  // If true, include kernel frames in the callstacks.
-  const bool kernel_frames_;
+  // If true, process all system-wide samples.
+  const bool target_all_cpus_;
 
   // Size (in 4k pages) of each per-cpu ring buffer shared with the kernel.
   // Must be a power of two.
   const uint32_t ring_buffer_pages_;
 
+  // Parameter struct for |perf_event_open| calls.
+  struct perf_event_attr perf_event_attr_ = {};
+
   // How often the ring buffers should be read.
   const uint32_t read_tick_period_ms_;
 
   // Guardrail for the amount of samples a given read attempt will extract from
   // *each* per-cpu buffer.
-  const uint64_t samples_per_tick_limit_;
+  const uint32_t samples_per_tick_limit_;
+
+  // Parsed whitelist/blacklist for filtering samples.
+  const TargetFilter target_filter_;
 
   // Timeout for proc-fd lookup.
   const uint32_t remote_descriptor_timeout_ms_;
 
   // Optional period for clearing cached unwinder state. Skipped if zero.
   const uint32_t unwind_state_clear_period_ms_;
-
-  const uint64_t max_enqueued_footprint_bytes_;
-
-  // Only profile target if it was installed by one of the packages given.
-  // Special values are:
-  // * @system: installed on the system partition
-  // * @product: installed on the product partition
-  // * @null: sideloaded
-  const std::vector<std::string> target_installed_by_;
-
-  // The raw data source config, as a pbzero-generated C++ class.
-  const DataSourceConfig raw_ds_config_;
 };
 
 }  // namespace profiling
diff --git a/src/profiling/perf/event_config_unittest.cc b/src/profiling/perf/event_config_unittest.cc
index c69d45d..2c69978 100644
--- a/src/profiling/perf/event_config_unittest.cc
+++ b/src/profiling/perf/event_config_unittest.cc
@@ -23,12 +23,9 @@
 #include "perfetto/ext/base/optional.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/common/perf_events.gen.h"
 #include "protos/perfetto/config/data_source_config.gen.h"
 #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
 
-using ::testing::UnorderedElementsAreArray;
-
 namespace perfetto {
 namespace profiling {
 namespace {
@@ -125,208 +122,6 @@
   }
 }
 
-TEST(EventConfigTest, EnableKernelFrames) {
-  {
-    protos::gen::PerfEventConfig cfg;
-    cfg.mutable_callstack_sampling()->set_kernel_frames(true);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_TRUE(event_config->kernel_frames());
-  }
-  {  // legacy config:
-    protos::gen::PerfEventConfig cfg;
-    cfg.set_all_cpus(true);  // used to detect compat mode
-    cfg.set_kernel_frames(true);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_TRUE(event_config->kernel_frames());
-  }
-  {  // default is false
-    protos::gen::PerfEventConfig cfg;
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_FALSE(event_config->kernel_frames());
-  }
-}
-
-TEST(EventConfigTest, SelectSamplingInterval) {
-  {  // period:
-    protos::gen::PerfEventConfig cfg;
-    cfg.mutable_timebase()->set_period(100);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_FALSE(event_config->perf_attr()->freq);
-    EXPECT_EQ(event_config->perf_attr()->sample_period, 100u);
-  }
-  {  // frequency:
-    protos::gen::PerfEventConfig cfg;
-    cfg.mutable_timebase()->set_frequency(4000);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_TRUE(event_config->perf_attr()->freq);
-    EXPECT_EQ(event_config->perf_attr()->sample_freq, 4000u);
-  }
-  {  // legacy frequency field:
-    protos::gen::PerfEventConfig cfg;
-    cfg.set_sampling_frequency(5000);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_TRUE(event_config->perf_attr()->freq);
-    EXPECT_EQ(event_config->perf_attr()->sample_freq, 5000u);
-  }
-  {  // default is 10 Hz (implementation-defined)
-    protos::gen::PerfEventConfig cfg;
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_TRUE(event_config->perf_attr()->freq);
-    EXPECT_EQ(event_config->perf_attr()->sample_freq, 10u);
-  }
-}
-
-TEST(EventConfigTest, SelectTimebaseEvent) {
-  auto id_lookup = [](const std::string& group, const std::string& name) {
-    return (group == "sched" && name == "sched_switch") ? 42 : 0;
-  };
-
-  {
-    protos::gen::PerfEventConfig cfg;
-    protos::gen::PerfEvents::Tracepoint* mutable_tracepoint =
-        cfg.mutable_timebase()->mutable_tracepoint();
-    mutable_tracepoint->set_name("sched:sched_switch");
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg), id_lookup);
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_TRACEPOINT);
-    EXPECT_EQ(event_config->perf_attr()->config, 42u);
-  }
-  {  // default is the CPU timer:
-    protos::gen::PerfEventConfig cfg;
-    cfg.mutable_timebase()->set_frequency(1000);
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_SOFTWARE);
-    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_SW_CPU_CLOCK);
-  }
-}
-
-TEST(EventConfigTest, ParseTargetfilter) {
-  {
-    protos::gen::PerfEventConfig cfg;
-    auto* mutable_scope = cfg.mutable_callstack_sampling()->mutable_scope();
-    mutable_scope->add_target_pid(42);
-    mutable_scope->add_target_cmdline("traced_probes");
-    mutable_scope->add_target_cmdline("traced");
-    mutable_scope->set_additional_cmdline_count(3);
-    mutable_scope->add_exclude_cmdline("heapprofd");
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    const auto& filter = event_config->filter();
-    EXPECT_THAT(filter.pids, UnorderedElementsAreArray({42}));
-    EXPECT_THAT(filter.cmdlines,
-                UnorderedElementsAreArray({"traced_probes", "traced"}));
-    EXPECT_EQ(filter.additional_cmdline_count, 3u);
-    EXPECT_TRUE(filter.exclude_pids.empty());
-    EXPECT_THAT(filter.exclude_cmdlines,
-                UnorderedElementsAreArray({"heapprofd"}));
-  }
-  {  // legacy:
-    protos::gen::PerfEventConfig cfg;
-    cfg.set_all_cpus(true);
-    cfg.add_target_pid(42);
-    cfg.add_target_cmdline("traced_probes");
-    cfg.add_target_cmdline("traced");
-    cfg.set_additional_cmdline_count(3);
-    cfg.add_exclude_cmdline("heapprofd");
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    const auto& filter = event_config->filter();
-    EXPECT_THAT(filter.pids, UnorderedElementsAreArray({42}));
-    EXPECT_THAT(filter.cmdlines,
-                UnorderedElementsAreArray({"traced_probes", "traced"}));
-    EXPECT_EQ(filter.additional_cmdline_count, 3u);
-    EXPECT_TRUE(filter.exclude_pids.empty());
-    EXPECT_THAT(filter.exclude_cmdlines,
-                UnorderedElementsAreArray({"heapprofd"}));
-  }
-}
-
-TEST(EventConfigTest, CounterOnlyModeDetection) {
-  {  // hardware counter:
-    protos::gen::PerfEventConfig cfg;
-    auto* mutable_timebase = cfg.mutable_timebase();
-    mutable_timebase->set_period(500);
-    mutable_timebase->set_counter(protos::gen::PerfEvents::HW_CPU_CYCLES);
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_HARDWARE);
-    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_HW_CPU_CYCLES);
-    EXPECT_EQ(event_config->perf_attr()->sample_type &
-                  (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
-              0u);
-  }
-  {  // software counter:
-    protos::gen::PerfEventConfig cfg;
-    auto* mutable_timebase = cfg.mutable_timebase();
-    mutable_timebase->set_period(500);
-    mutable_timebase->set_counter(protos::gen::PerfEvents::SW_PAGE_FAULTS);
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_EQ(event_config->perf_attr()->type, PERF_TYPE_SOFTWARE);
-    EXPECT_EQ(event_config->perf_attr()->config, PERF_COUNT_SW_PAGE_FAULTS);
-    EXPECT_EQ(event_config->perf_attr()->sample_type &
-                  (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
-              0u);
-  }
-}
-
-TEST(EventConfigTest, CallstackSamplingModeDetection) {
-  {  // set-but-empty |callstack_sampling| field enables callstacks
-    protos::gen::PerfEventConfig cfg;
-    cfg.mutable_callstack_sampling();  // set field
-
-    base::Optional<EventConfig> event_config =
-        EventConfig::Create(AsDataSourceConfig(cfg));
-
-    ASSERT_TRUE(event_config.has_value());
-    EXPECT_EQ(event_config->perf_attr()->sample_type &
-                  (PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER),
-              PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER);
-
-    EXPECT_NE(event_config->perf_attr()->sample_regs_user, 0u);
-    EXPECT_NE(event_config->perf_attr()->sample_stack_user, 0u);
-  }
-}
-
 }  // namespace
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/perf/event_reader.cc b/src/profiling/perf/event_reader.cc
index 039afa3..b5f8ca2 100644
--- a/src/profiling/perf/event_reader.cc
+++ b/src/profiling/perf/event_reader.cc
@@ -37,13 +37,6 @@
   return ptr + sizeof(T);
 }
 
-template <typename T>
-const char* ReadValues(T* out, const char* ptr, size_t num_values) {
-  size_t sz = sizeof(T) * num_values;
-  memcpy(out, reinterpret_cast<const void*>(ptr), sz);
-  return ptr + sz;
-}
-
 bool IsPowerOfTwo(size_t v) {
   return (v != 0 && ((v & (v - 1)) == 0));
 }
@@ -57,28 +50,13 @@
       syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags));
 }
 
-base::ScopedFile PerfEventOpen(uint32_t cpu,
-                               perf_event_attr* perf_attr,
-                               int group_fd = -1) {
-  base::ScopedFile perf_fd{perf_event_open(perf_attr, /*pid=*/-1,
-                                           static_cast<int>(cpu), group_fd,
-                                           PERF_FLAG_FD_CLOEXEC)};
+base::ScopedFile PerfEventOpen(uint32_t cpu, const EventConfig& event_cfg) {
+  base::ScopedFile perf_fd{
+      perf_event_open(event_cfg.perf_attr(), /*pid=*/-1, static_cast<int>(cpu),
+                      /*group_fd=*/-1, PERF_FLAG_FD_CLOEXEC)};
   return perf_fd;
 }
 
-// If counting tracepoints, set an event filter if requested.
-bool MaybeApplyTracepointFilter(int fd, const PerfCounter& event) {
-  if (event.type == PERF_TYPE_TRACEPOINT &&
-      !event.tracepoint.filter().empty()) {
-    if (ioctl(fd, PERF_EVENT_IOC_SET_FILTER,
-              event.tracepoint.filter().c_str()) != 0) {
-      PERFETTO_PLOG("Failed ioctl to set event filter");
-      return false;
-    }
-  }
-  return true;
-}
-
 }  // namespace
 
 PerfRingBuffer::PerfRingBuffer(PerfRingBuffer&& other) noexcept
@@ -147,7 +125,7 @@
 char* PerfRingBuffer::ReadRecordNonconsuming() {
   static_assert(sizeof(std::atomic<uint64_t>) == sizeof(uint64_t), "");
 
-  PERFETTO_DCHECK(valid());
+  PERFETTO_CHECK(valid());
 
   // |data_tail| is written only by this userspace thread, so we can safely read
   // it without any synchronization.
@@ -195,7 +173,7 @@
 }
 
 void PerfRingBuffer::Consume(size_t bytes) {
-  PERFETTO_DCHECK(valid());
+  PERFETTO_CHECK(valid());
 
   // Advance |data_tail|, which is written only by this thread. The store of the
   // updated value needs to have release semantics such that the preceding
@@ -216,6 +194,12 @@
       perf_fd_(std::move(perf_fd)),
       ring_buffer_(std::move(ring_buffer)) {}
 
+EventReader::EventReader(EventReader&& other) noexcept
+    : cpu_(other.cpu_),
+      event_attr_(other.event_attr_),
+      perf_fd_(std::move(other.perf_fd_)),
+      ring_buffer_(std::move(other.ring_buffer_)) {}
+
 EventReader& EventReader::operator=(EventReader&& other) noexcept {
   if (this == &other)
     return *this;
@@ -228,22 +212,20 @@
 base::Optional<EventReader> EventReader::ConfigureEvents(
     uint32_t cpu,
     const EventConfig& event_cfg) {
-  auto leader_fd = PerfEventOpen(cpu, event_cfg.perf_attr());
-  if (!leader_fd) {
-    PERFETTO_PLOG("Failed perf_event_open");
+  auto perf_fd = PerfEventOpen(cpu, event_cfg);
+  if (!perf_fd) {
+    PERFETTO_PLOG("failed perf_event_open");
     return base::nullopt;
   }
-  if (!MaybeApplyTracepointFilter(leader_fd.get(), event_cfg.timebase_event()))
-    return base::nullopt;
 
   auto ring_buffer =
-      PerfRingBuffer::Allocate(leader_fd.get(), event_cfg.ring_buffer_pages());
+      PerfRingBuffer::Allocate(perf_fd.get(), event_cfg.ring_buffer_pages());
   if (!ring_buffer.has_value()) {
     return base::nullopt;
   }
 
   return base::make_optional<EventReader>(cpu, *event_cfg.perf_attr(),
-                                          std::move(leader_fd),
+                                          std::move(perf_fd),
                                           std::move(ring_buffer.value()));
 }
 
@@ -299,8 +281,7 @@
                                             const char* record_start) {
   if (event_attr_.sample_type &
       (~uint64_t(PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_STACK_USER |
-                 PERF_SAMPLE_REGS_USER | PERF_SAMPLE_CALLCHAIN |
-                 PERF_SAMPLE_READ))) {
+                 PERF_SAMPLE_REGS_USER))) {
     PERFETTO_FATAL("Unsupported sampling option");
   }
 
@@ -308,8 +289,8 @@
   size_t sample_size = event_hdr->size;
 
   ParsedSample sample = {};
-  sample.common.cpu = cpu;
-  sample.common.cpu_mode = event_hdr->misc & PERF_RECORD_MISC_CPUMODE_MASK;
+  sample.cpu = cpu;
+  sample.cpu_mode = event_hdr->misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
   // Parse the payload, which consists of concatenated data for each
   // |attr.sample_type| flag.
@@ -320,24 +301,12 @@
     uint32_t tid = 0;
     parse_pos = ReadValue(&pid, parse_pos);
     parse_pos = ReadValue(&tid, parse_pos);
-    sample.common.pid = static_cast<pid_t>(pid);
-    sample.common.tid = static_cast<pid_t>(tid);
+    sample.pid = static_cast<pid_t>(pid);
+    sample.tid = static_cast<pid_t>(tid);
   }
 
   if (event_attr_.sample_type & PERF_SAMPLE_TIME) {
-    parse_pos = ReadValue(&sample.common.timestamp, parse_pos);
-  }
-
-  if (event_attr_.sample_type & PERF_SAMPLE_READ) {
-    parse_pos = ReadValue(&sample.common.timebase_count, parse_pos);
-  }
-
-  if (event_attr_.sample_type & PERF_SAMPLE_CALLCHAIN) {
-    uint64_t chain_len = 0;
-    parse_pos = ReadValue(&chain_len, parse_pos);
-    sample.kernel_ips.resize(static_cast<size_t>(chain_len));
-    parse_pos = ReadValues<uint64_t>(sample.kernel_ips.data(), parse_pos,
-                                     static_cast<size_t>(chain_len));
+    parse_pos = ReadValue(&sample.timestamp, parse_pos);
   }
 
   if (event_attr_.sample_type & PERF_SAMPLE_REGS_USER) {
@@ -346,10 +315,7 @@
   }
 
   if (event_attr_.sample_type & PERF_SAMPLE_STACK_USER) {
-    // Maximum possible sampled stack size for this sample. Can be lower than
-    // the requested size if there wasn't enough room in the sample (which is
-    // limited to 64k).
-    uint64_t max_stack_size;
+    uint64_t max_stack_size;  // the requested size
     parse_pos = ReadValue(&max_stack_size, parse_pos);
 
     const char* stack_start = parse_pos;
@@ -367,9 +333,6 @@
       size_t payload_sz = static_cast<size_t>(filled_stack_size);
       sample.stack.resize(payload_sz);
       memcpy(sample.stack.data(), stack_start, payload_sz);
-
-      // remember whether the stack sample is (most likely) truncated
-      sample.stack_maxed = (filled_stack_size == max_stack_size);
     }
   }
 
@@ -377,12 +340,7 @@
   return sample;
 }
 
-void EventReader::EnableEvents() {
-  int ret = ioctl(perf_fd_.get(), PERF_EVENT_IOC_ENABLE);
-  PERFETTO_CHECK(ret == 0);
-}
-
-void EventReader::DisableEvents() {
+void EventReader::PauseEvents() {
   int ret = ioctl(perf_fd_.get(), PERF_EVENT_IOC_DISABLE);
   PERFETTO_CHECK(ret == 0);
 }
diff --git a/src/profiling/perf/event_reader.h b/src/profiling/perf/event_reader.h
index 9c86fc9..a72e674 100644
--- a/src/profiling/perf/event_reader.h
+++ b/src/profiling/perf/event_reader.h
@@ -85,9 +85,7 @@
   base::Optional<ParsedSample> ReadUntilSample(
       std::function<void(uint64_t)> lost_events_callback);
 
-  void EnableEvents();
-  // Pauses the event counting, without invalidating existing samples.
-  void DisableEvents();
+  void PauseEvents();
 
   uint32_t cpu() const { return cpu_; }
 
@@ -95,8 +93,8 @@
 
   // move-only
   EventReader(const EventReader&) = delete;
-  EventReader& operator=(const EventReader&) = delete;
-  EventReader(EventReader&&) noexcept = default;
+  EventReader& operator=(const EventReader) = delete;
+  EventReader(EventReader&&) noexcept;
   EventReader& operator=(EventReader&&) noexcept;
 
  private:
diff --git a/src/profiling/perf/perf_producer.cc b/src/profiling/perf/perf_producer.cc
index b1c7e1f..e0dde42 100644
--- a/src/profiling/perf/perf_producer.cc
+++ b/src/profiling/perf/perf_producer.cc
@@ -19,6 +19,7 @@
 #include <random>
 #include <utility>
 
+#include <malloc.h>
 #include <unistd.h>
 
 #include <unwindstack/Error.h>
@@ -27,7 +28,6 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/base/weak_ptr.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/producer.h"
@@ -37,19 +37,13 @@
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "src/profiling/common/callstack_trie.h"
 #include "src/profiling/common/proc_utils.h"
-#include "src/profiling/common/producer_support.h"
-#include "src/profiling/common/profiler_guardrails.h"
 #include "src/profiling/common/unwind_support.h"
 #include "src/profiling/perf/common_types.h"
 #include "src/profiling/perf/event_reader.h"
 
-#include "protos/perfetto/common/builtin_clock.pbzero.h"
-#include "protos/perfetto/common/perf_events.gen.h"
-#include "protos/perfetto/common/perf_events.pbzero.h"
-#include "protos/perfetto/config/profiling/perf_event_config.gen.h"
+#include "protos/perfetto/config/profiling/perf_event_config.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
 
 namespace perfetto {
 namespace profiling {
@@ -68,8 +62,6 @@
 // The proper fix is in the platform, see bug for progress.
 constexpr uint32_t kProcDescriptorsAndroidDelayMs = 50;
 
-constexpr uint32_t kMemoryLimitCheckPeriodMs = 5 * 1000;
-
 constexpr uint32_t kInitialConnectionBackoffMs = 100;
 constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
 
@@ -80,54 +72,6 @@
   return static_cast<size_t>(sysconf(_SC_NPROCESSORS_CONF));
 }
 
-TraceWriter::TracePacketHandle StartTracePacket(TraceWriter* trace_writer) {
-  auto packet = trace_writer->NewTracePacket();
-  packet->set_sequence_flags(
-      protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
-  return packet;
-}
-
-void WritePerfEventDefaultsPacket(const EventConfig& event_config,
-                                  TraceWriter* trace_writer) {
-  auto packet = trace_writer->NewTracePacket();
-  packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
-  packet->set_timestamp_clock_id(protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
-
-  // start new incremental state generation:
-  packet->set_sequence_flags(
-      protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
-
-  // default packet timestamp clockid:
-  auto* defaults = packet->set_trace_packet_defaults();
-  defaults->set_timestamp_clock_id(protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW);
-  PERFETTO_DCHECK(event_config.perf_attr()->clockid == CLOCK_MONOTONIC_RAW);
-
-  auto* perf_defaults = defaults->set_perf_sample_defaults();
-  auto* timebase_pb = perf_defaults->set_timebase();
-
-  // frequency/period:
-  perf_event_attr* perf_attr = event_config.perf_attr();
-  if (perf_attr->freq) {
-    timebase_pb->set_frequency(perf_attr->sample_freq);
-  } else {
-    timebase_pb->set_period(perf_attr->sample_period);
-  }
-
-  // event:
-  const PerfCounter& timebase = event_config.timebase_event();
-  if (timebase.is_counter()) {
-    timebase_pb->set_counter(
-        static_cast<protos::pbzero::PerfEvents::Counter>(timebase.counter));
-  } else {
-    PERFETTO_DCHECK(timebase.is_tracepoint());
-    // TODO(rsavitski): reconsider using a struct with two strings instead
-    // of the ::gen::Tracepoint class in the C++ code.
-    auto* tracepoint_pb = timebase_pb->set_tracepoint();
-    tracepoint_pb->set_name(timebase.tracepoint.name());
-    tracepoint_pb->set_filter(timebase.tracepoint.filter());
-  }
-}
-
 uint32_t TimeToNextReadTickMs(DataSourceInstanceID ds_id, uint32_t period_ms) {
   // Normally, we'd schedule the next tick at the next |period_ms|
   // boundary of the boot clock. However, to avoid aligning the read tasks of
@@ -141,54 +85,41 @@
   return period_ms - ((now_ms - ds_period_offset) % period_ms);
 }
 
-bool ShouldRejectDueToFilter(pid_t pid,
-                             base::FlatSet<std::string>* additional_cmdlines,
-                             const TargetFilter& filter) {
-  PERFETTO_CHECK(additional_cmdlines);
+bool ShouldRejectDueToFilter(pid_t pid, const TargetFilter& filter) {
+  bool reject_cmd = false;
   std::string cmdline;
-  bool have_cmdline = GetCmdlineForPID(pid, &cmdline);  // normalized form
-  if (!have_cmdline) {
+  if (GetCmdlineForPID(pid, &cmdline)) {  // normalized form
+    // reject if absent from non-empty whitelist, or present in blacklist
+    reject_cmd = (filter.cmdlines.size() && !filter.cmdlines.count(cmdline)) ||
+                 filter.exclude_cmdlines.count(cmdline);
+  } else {
     PERFETTO_DLOG("Failed to look up cmdline for pid [%d]",
                   static_cast<int>(pid));
+    // reject only if there's a whitelist present
+    reject_cmd = filter.cmdlines.size() > 0;
   }
 
-  if (have_cmdline && filter.exclude_cmdlines.count(cmdline)) {
-    PERFETTO_DLOG("Explicitly rejecting samples for pid [%d] due to cmdline",
-                  static_cast<int>(pid));
+  bool reject_pid = (filter.pids.size() && !filter.pids.count(pid)) ||
+                    filter.exclude_pids.count(pid);
+
+  if (reject_cmd || reject_pid) {
+    PERFETTO_DLOG(
+        "Rejecting samples for pid [%d] due to cmdline(%d) or pid(%d)",
+        static_cast<int>(pid), reject_cmd, reject_pid);
+
     return true;
   }
-  if (filter.exclude_pids.count(pid)) {
-    PERFETTO_DLOG("Explicitly rejecting samples for pid [%d] due to pid",
-                  static_cast<int>(pid));
-    return true;
-  }
+  return false;
+}
 
-  if (have_cmdline && filter.cmdlines.count(cmdline)) {
-    return false;
-  }
-  if (filter.pids.count(pid)) {
-    return false;
-  }
-  if (filter.cmdlines.empty() && filter.pids.empty() &&
-      !filter.additional_cmdline_count) {
-    // If no filters are set allow everything.
-    return false;
-  }
-
-  // If we didn't read the command line that's a good prediction we will not be
-  // able to profile either.
-  if (have_cmdline) {
-    if (additional_cmdlines->count(cmdline)) {
-      return false;
-    }
-    if (additional_cmdlines->size() < filter.additional_cmdline_count) {
-      additional_cmdlines->insert(cmdline);
-      return false;
-    }
-  }
-
-  PERFETTO_DLOG("Rejecting samples for pid [%d]", static_cast<int>(pid));
-  return true;
+void MaybeReleaseAllocatorMemToOS() {
+#if defined(__BIONIC__)
+  // TODO(b/152414415): libunwindstack's volume of small allocations is
+  // adverarial to scudo, which doesn't automatically release small
+  // allocation regions back to the OS. Forceful purge does reclaim all size
+  // classes.
+  mallopt(M_PURGE, 0);
+#endif
 }
 
 protos::pbzero::Profiling::CpuMode ToCpuModeEnum(uint16_t perf_cpu_mode) {
@@ -229,12 +160,6 @@
       return Profiling::UNWIND_ERROR_REPEATED_FRAME;
     case unwindstack::ERROR_INVALID_ELF:
       return Profiling::UNWIND_ERROR_INVALID_ELF;
-    case unwindstack::ERROR_SYSTEM_CALL:
-      return Profiling::UNWIND_ERROR_SYSTEM_CALL;
-    case unwindstack::ERROR_THREAD_TIMEOUT:
-      return Profiling::UNWIND_ERROR_THREAD_TIMEOUT;
-    case unwindstack::ERROR_THREAD_DOES_NOT_EXIST:
-      return Profiling::UNWIND_ERROR_THREAD_DOES_NOT_EXIST;
   }
   return Profiling::UNWIND_ERROR_UNKNOWN;
 }
@@ -250,16 +175,18 @@
   proc_fd_getter->SetDelegate(this);
 }
 
+// TODO(rsavitski): consider configure at setup + enable at start instead.
 void PerfProducer::SetupDataSource(DataSourceInstanceID,
                                    const DataSourceConfig&) {}
 
-void PerfProducer::StartDataSource(DataSourceInstanceID ds_id,
+void PerfProducer::StartDataSource(DataSourceInstanceID instance_id,
                                    const DataSourceConfig& config) {
-  PERFETTO_LOG("StartDataSource(%zu, %s)", static_cast<size_t>(ds_id),
+  PERFETTO_LOG("StartDataSource(%zu, %s)", static_cast<size_t>(instance_id),
                config.name().c_str());
 
   if (config.name() == MetatraceWriter::kDataSourceName) {
-    StartMetatraceSource(ds_id, static_cast<BufferID>(config.target_buffer()));
+    StartMetatraceSource(instance_id,
+                         static_cast<BufferID>(config.target_buffer()));
     return;
   }
 
@@ -267,28 +194,17 @@
   if (config.name() != kDataSourceName)
     return;
 
-  // Tracepoint name -> id lookup in case the config asks for tracepoints:
-  auto tracepoint_id_lookup = [this](const std::string& group,
-                                     const std::string& name) {
-    if (!tracefs_)  // lazy init or retry
-      tracefs_ = FtraceProcfs::CreateGuessingMountPoint();
-    if (!tracefs_)  // still didn't find an accessible tracefs
-      return 0u;
-    return tracefs_->ReadEventId(group, name);
-  };
-
-  protos::gen::PerfEventConfig event_config_pb;
-  if (!event_config_pb.ParseFromString(config.perf_event_config_raw())) {
-    PERFETTO_ELOG("PerfEventConfig could not be parsed.");
-    return;
-  }
-  base::Optional<EventConfig> event_config =
-      EventConfig::Create(event_config_pb, config, tracepoint_id_lookup);
+  base::Optional<EventConfig> event_config = EventConfig::Create(config);
   if (!event_config.has_value()) {
     PERFETTO_ELOG("PerfEventConfig rejected.");
     return;
   }
 
+  // TODO(rsavitski): consider supporting specific cpu subsets.
+  if (!event_config->target_all_cpus()) {
+    PERFETTO_ELOG("PerfEventConfig{all_cpus} required");
+    return;
+  }
   size_t num_cpus = NumberOfCpus();
   std::vector<EventReader> per_cpu_readers;
   for (uint32_t cpu = 0; cpu < num_cpus; cpu++) {
@@ -310,100 +226,50 @@
   std::map<DataSourceInstanceID, DataSourceState>::iterator ds_it;
   bool inserted;
   std::tie(ds_it, inserted) = data_sources_.emplace(
-      std::piecewise_construct, std::forward_as_tuple(ds_id),
+      std::piecewise_construct, std::forward_as_tuple(instance_id),
       std::forward_as_tuple(event_config.value(), std::move(writer),
                             std::move(per_cpu_readers)));
   PERFETTO_CHECK(inserted);
   DataSourceState& ds = ds_it->second;
 
-  // Start the configured events.
-  for (auto& per_cpu_reader : ds.per_cpu_readers) {
-    per_cpu_reader.EnableEvents();
-  }
-
-  WritePerfEventDefaultsPacket(ds.event_config, ds.trace_writer.get());
-
+  // Write out a packet to initialize the incremental state for this sequence.
   InterningOutputTracker::WriteFixedInterningsPacket(
-      ds_it->second.trace_writer.get(),
-      protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
+      ds_it->second.trace_writer.get());
 
   // Inform unwinder of the new data source instance, and optionally start a
   // periodic task to clear its cached state.
-  unwinding_worker_->PostStartDataSource(ds_id,
-                                         ds.event_config.kernel_frames());
+  unwinding_worker_->PostStartDataSource(instance_id);
   if (ds.event_config.unwind_state_clear_period_ms()) {
     unwinding_worker_->PostClearCachedStatePeriodic(
-        ds_id, ds.event_config.unwind_state_clear_period_ms());
+        instance_id, ds.event_config.unwind_state_clear_period_ms());
   }
 
   // Kick off periodic read task.
   auto tick_period_ms = ds.event_config.read_tick_period_ms();
   auto weak_this = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
-      [weak_this, ds_id] {
+      [weak_this, instance_id] {
         if (weak_this)
-          weak_this->TickDataSourceRead(ds_id);
+          weak_this->TickDataSourceRead(instance_id);
       },
-      TimeToNextReadTickMs(ds_id, tick_period_ms));
-
-  // Optionally kick off periodic memory footprint limit check.
-  uint32_t max_daemon_memory_kb = event_config_pb.max_daemon_memory_kb();
-  if (max_daemon_memory_kb > 0) {
-    task_runner_->PostDelayedTask(
-        [weak_this, ds_id, max_daemon_memory_kb] {
-          if (weak_this)
-            weak_this->CheckMemoryFootprintPeriodic(ds_id,
-                                                    max_daemon_memory_kb);
-        },
-        kMemoryLimitCheckPeriodMs);
-  }
+      TimeToNextReadTickMs(instance_id, tick_period_ms));
 }
 
-void PerfProducer::CheckMemoryFootprintPeriodic(DataSourceInstanceID ds_id,
-                                                uint32_t max_daemon_memory_kb) {
-  auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end())
-    return;  // stop recurring
-
-  GuardrailConfig gconfig = {};
-  gconfig.memory_guardrail_kb = max_daemon_memory_kb;
-
-  ProfilerMemoryGuardrails footprint_snapshot;
-  if (footprint_snapshot.IsOverMemoryThreshold(gconfig)) {
-    PurgeDataSource(ds_id);
-    return;  // stop recurring
-  }
-
-  // repost
-  auto weak_this = weak_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      [weak_this, ds_id, max_daemon_memory_kb] {
-        if (weak_this)
-          weak_this->CheckMemoryFootprintPeriodic(ds_id, max_daemon_memory_kb);
-      },
-      kMemoryLimitCheckPeriodMs);
-}
-
-void PerfProducer::StopDataSource(DataSourceInstanceID ds_id) {
-  PERFETTO_LOG("StopDataSource(%zu)", static_cast<size_t>(ds_id));
+void PerfProducer::StopDataSource(DataSourceInstanceID instance_id) {
+  PERFETTO_LOG("StopDataSource(%zu)", static_cast<size_t>(instance_id));
 
   // Metatrace: stop immediately (will miss the events from the
   // asynchronous shutdown of the primary data source).
-  auto meta_it = metatrace_writers_.find(ds_id);
+  auto meta_it = metatrace_writers_.find(instance_id);
   if (meta_it != metatrace_writers_.end()) {
     meta_it->second.WriteAllAndFlushTraceWriter([] {});
     metatrace_writers_.erase(meta_it);
     return;
   }
 
-  auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end()) {
-    // Most likely, the source is missing due to an abrupt stop (via
-    // |PurgeDataSource|). Tell the service that we've stopped the source now,
-    // so that it doesn't wait for the ack until the timeout.
-    endpoint_->NotifyDataSourceStopped(ds_id);
+  auto ds_it = data_sources_.find(instance_id);
+  if (ds_it == data_sources_.end())
     return;
-  }
 
   // Start shutting down the reading frontend, which will propagate the stop
   // further as the intermediate buffers are cleared.
@@ -419,7 +285,7 @@
 void PerfProducer::Flush(FlushRequestID flush_id,
                          const DataSourceInstanceID* data_source_ids,
                          size_t num_data_sources) {
-  // Flush metatracing if requested.
+  bool should_ack_flush = false;
   for (size_t i = 0; i < num_data_sources; i++) {
     auto ds_id = data_source_ids[i];
     PERFETTO_DLOG("Flush(%zu)", static_cast<size_t>(ds_id));
@@ -427,10 +293,14 @@
     auto meta_it = metatrace_writers_.find(ds_id);
     if (meta_it != metatrace_writers_.end()) {
       meta_it->second.WriteAllAndFlushTraceWriter([] {});
+      should_ack_flush = true;
+    }
+    if (data_sources_.find(ds_id) != data_sources_.end()) {
+      should_ack_flush = true;
     }
   }
-
-  endpoint_->NotifyFlushComplete(flush_id);
+  if (should_ack_flush)
+    endpoint_->NotifyFlushComplete(flush_id);
 }
 
 void PerfProducer::ClearIncrementalState(
@@ -451,13 +321,9 @@
     }
     DataSourceState& ds = ds_it->second;
 
-    WritePerfEventDefaultsPacket(ds.event_config, ds.trace_writer.get());
-
     // Forget which incremental state we've emitted before.
     ds.interning_output.ClearHistory();
-    InterningOutputTracker::WriteFixedInterningsPacket(
-        ds.trace_writer.get(),
-        protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
+    InterningOutputTracker::WriteFixedInterningsPacket(ds.trace_writer.get());
 
     // Drop the cross-datasource callstack interning trie. This is not
     // necessary for correctness (the preceding step is sufficient). However,
@@ -483,7 +349,7 @@
   PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_READ_TICK);
 
   // Make a pass over all per-cpu readers.
-  uint64_t max_samples = ds.event_config.samples_per_tick_limit();
+  uint32_t max_samples = ds.event_config.samples_per_tick_limit();
   bool more_records_available = false;
   for (EventReader& reader : ds.per_cpu_readers) {
     if (ReadAndParsePerCpuBuffer(&reader, max_samples, ds_id, &ds)) {
@@ -511,7 +377,7 @@
 }
 
 bool PerfProducer::ReadAndParsePerCpuBuffer(EventReader* reader,
-                                            uint64_t max_samples,
+                                            uint32_t max_samples,
                                             DataSourceInstanceID ds_id,
                                             DataSourceState* ds) {
   PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_READ_CPU);
@@ -526,36 +392,26 @@
     });
   };
 
-  for (uint64_t i = 0; i < max_samples; i++) {
+  for (uint32_t i = 0; i < max_samples; i++) {
     base::Optional<ParsedSample> sample =
         reader->ReadUntilSample(records_lost_callback);
     if (!sample) {
       return false;  // caught up to the writer
     }
 
-    // Counter-only mode: skip the unwinding stage, enqueue the sample for
-    // output immediately.
-    if (!ds->event_config.sample_callstacks()) {
-      CompletedSample output;
-      output.common = sample->common;
-      EmitSample(ds_id, std::move(output));
-      continue;
-    }
-
-    // If sampling callstacks, we're not interested in kernel threads/workers.
     if (!sample->regs) {
-      continue;
+      continue;  // skip kernel threads/workers
     }
 
     // Request proc-fds for the process if this is the first time we see it.
-    pid_t pid = sample->common.pid;
+    pid_t pid = sample->pid;
     auto& process_state = ds->process_states[pid];  // insert if new
 
     if (process_state == ProcessTrackingStatus::kExpired) {
       PERFETTO_DLOG("Skipping sample for previously expired pid [%d]",
                     static_cast<int>(pid));
-      EmitSkippedSample(ds_id, std::move(sample.value()),
-                        SampleSkipReason::kReadStage);
+      PostEmitSkippedSample(ds_id, std::move(sample.value()),
+                            SampleSkipReason::kReadStage);
       continue;
     }
 
@@ -571,9 +427,9 @@
       PERFETTO_DLOG("New pid: [%d]", static_cast<int>(pid));
 
       // Check whether samples for this new process should be
-      // dropped due to the target filtering.
+      // dropped due to the target whitelist/blacklist.
       const TargetFilter& filter = ds->event_config.filter();
-      if (ShouldRejectDueToFilter(pid, &ds->additional_cmdlines, filter)) {
+      if (ShouldRejectDueToFilter(pid, filter)) {
         process_state = ProcessTrackingStatus::kRejected;
         continue;
       }
@@ -588,21 +444,6 @@
     PERFETTO_CHECK(process_state == ProcessTrackingStatus::kResolved ||
                    process_state == ProcessTrackingStatus::kResolving);
 
-    // Optionally: drop sample if above a given threshold of sampled stacks
-    // that are waiting in the unwinding queue.
-    uint64_t max_footprint_bytes =
-        ds->event_config.max_enqueued_footprint_bytes();
-    uint64_t sample_stack_size = sample->stack.size();
-    if (max_footprint_bytes) {
-      uint64_t footprint_bytes = unwinding_worker_->GetEnqueuedFootprint();
-      if (footprint_bytes + sample_stack_size >= max_footprint_bytes) {
-        PERFETTO_DLOG("Skipping sample enqueueing due to footprint limit.");
-        EmitSkippedSample(ds_id, std::move(sample.value()),
-                          SampleSkipReason::kUnwindEnqueue);
-        continue;
-      }
-    }
-
     // Push the sample into the unwinding queue if there is room.
     auto& queue = unwinding_worker_->unwind_queue();
     WriteView write_view = queue.BeginWrite();
@@ -610,11 +451,10 @@
       queue.at(write_view.write_pos) =
           UnwindEntry{ds_id, std::move(sample.value())};
       queue.CommitWrite();
-      unwinding_worker_->IncrementEnqueuedFootprint(sample_stack_size);
     } else {
       PERFETTO_DLOG("Unwinder queue full, skipping sample");
-      EmitSkippedSample(ds_id, std::move(sample.value()),
-                        SampleSkipReason::kUnwindEnqueue);
+      PostEmitSkippedSample(ds_id, std::move(sample.value()),
+                            SampleSkipReason::kUnwindEnqueue);
     }
   }
 
@@ -626,7 +466,6 @@
 // Note: first-fit makes descriptor request fulfillment not true FIFO. But the
 // edge-cases where it matters are very unlikely.
 void PerfProducer::OnProcDescriptors(pid_t pid,
-                                     uid_t uid,
                                      base::ScopedFile maps_fd,
                                      base::ScopedFile mem_fd) {
   // Find first-fit data source that requested descriptors for the process.
@@ -636,14 +475,6 @@
     if (proc_status_it == ds.process_states.end())
       continue;
 
-    if (!CanProfile(ds.event_config.raw_ds_config(), uid,
-                    ds.event_config.target_installed_by())) {
-      PERFETTO_DLOG("Not profileable: pid [%d], uid [%d] for DS [%zu]",
-                    static_cast<int>(pid), static_cast<int>(uid),
-                    static_cast<size_t>(it.first));
-      continue;
-    }
-
     // Match against either resolving, or expired state. In the latter
     // case, it means that the async response was slow enough that we've marked
     // the lookup as expired (but can now recover for future samples).
@@ -736,21 +567,17 @@
 void PerfProducer::EmitSample(DataSourceInstanceID ds_id,
                               CompletedSample sample) {
   auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end()) {
-    PERFETTO_DLOG("EmitSample(ds: %zu): source gone",
-                  static_cast<size_t>(ds_id));
-    return;
-  }
+  PERFETTO_CHECK(ds_it != data_sources_.end());
   DataSourceState& ds = ds_it->second;
 
   // intern callsite
   GlobalCallstackTrie::Node* callstack_root =
-      callstack_trie_.CreateCallsite(sample.frames, sample.build_ids);
+      callstack_trie_.CreateCallsite(sample.frames);
   uint64_t callstack_iid = callstack_root->id();
 
-  // start packet, timestamp domain defaults to monotonic_raw
-  auto packet = StartTracePacket(ds.trace_writer.get());
-  packet->set_timestamp(sample.common.timestamp);
+  // start packet
+  auto packet = ds.trace_writer->NewTracePacket();
+  packet->set_timestamp(sample.timestamp);
 
   // write new interning data (if any)
   protos::pbzero::InternedData* interned_out = packet->set_interned_data();
@@ -759,11 +586,10 @@
 
   // write the sample itself
   auto* perf_sample = packet->set_perf_sample();
-  perf_sample->set_cpu(sample.common.cpu);
-  perf_sample->set_pid(static_cast<uint32_t>(sample.common.pid));
-  perf_sample->set_tid(static_cast<uint32_t>(sample.common.tid));
-  perf_sample->set_cpu_mode(ToCpuModeEnum(sample.common.cpu_mode));
-  perf_sample->set_timebase_count(sample.common.timebase_count);
+  perf_sample->set_cpu(sample.cpu);
+  perf_sample->set_pid(static_cast<uint32_t>(sample.pid));
+  perf_sample->set_tid(static_cast<uint32_t>(sample.tid));
+  perf_sample->set_cpu_mode(ToCpuModeEnum(sample.cpu_mode));
   perf_sample->set_callstack_iid(callstack_iid);
   if (sample.unwind_error != unwindstack::ERROR_NONE) {
     perf_sample->set_unwind_error(ToProtoEnum(sample.unwind_error));
@@ -774,8 +600,7 @@
                                       size_t cpu,
                                       uint64_t records_lost) {
   auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(ds_it != data_sources_.end());
   DataSourceState& ds = ds_it->second;
   PERFETTO_DLOG("DataSource(%zu): cpu%zu lost [%" PRIu64 "] records",
                 static_cast<size_t>(ds_id), cpu, records_lost);
@@ -786,10 +611,8 @@
   // We timestamp the packet with the boot clock for packet ordering purposes,
   // but it no longer has a (precise) interpretation relative to the sample
   // stream from that per-cpu buffer. See the proto comments for more details.
-  auto packet = StartTracePacket(ds.trace_writer.get());
+  auto packet = ds.trace_writer->NewTracePacket();
   packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
-  packet->set_timestamp_clock_id(
-      protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
 
   auto* perf_sample = packet->set_perf_sample();
   perf_sample->set_cpu(static_cast<uint32_t>(cpu));
@@ -819,19 +642,16 @@
                                      ParsedSample sample,
                                      SampleSkipReason reason) {
   auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(ds_it != data_sources_.end());
   DataSourceState& ds = ds_it->second;
 
-  // Note: timestamp defaults to the monotonic_raw domain.
-  auto packet = StartTracePacket(ds.trace_writer.get());
-  packet->set_timestamp(sample.common.timestamp);
+  auto packet = ds.trace_writer->NewTracePacket();
+  packet->set_timestamp(sample.timestamp);
   auto* perf_sample = packet->set_perf_sample();
-  perf_sample->set_cpu(sample.common.cpu);
-  perf_sample->set_pid(static_cast<uint32_t>(sample.common.pid));
-  perf_sample->set_tid(static_cast<uint32_t>(sample.common.tid));
-  perf_sample->set_cpu_mode(ToCpuModeEnum(sample.common.cpu_mode));
-  perf_sample->set_timebase_count(sample.common.timebase_count);
+  perf_sample->set_cpu(sample.cpu);
+  perf_sample->set_pid(static_cast<uint32_t>(sample.pid));
+  perf_sample->set_tid(static_cast<uint32_t>(sample.tid));
+  perf_sample->set_cpu_mode(ToCpuModeEnum(sample.cpu_mode));
 
   using PerfSample = protos::pbzero::PerfSample;
   switch (reason) {
@@ -856,7 +676,7 @@
 
   ds->status = DataSourceState::Status::kShuttingDown;
   for (auto& event_reader : ds->per_cpu_readers) {
-    event_reader.DisableEvents();
+    event_reader.PauseEvents();
   }
 }
 
@@ -871,11 +691,7 @@
 void PerfProducer::FinishDataSourceStop(DataSourceInstanceID ds_id) {
   PERFETTO_LOG("FinishDataSourceStop(%zu)", static_cast<size_t>(ds_id));
   auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end()) {
-    PERFETTO_DLOG("FinishDataSourceStop(%zu): source gone",
-                  static_cast<size_t>(ds_id));
-    return;
-  }
+  PERFETTO_CHECK(ds_it != data_sources_.end());
   DataSourceState& ds = ds_it->second;
   PERFETTO_CHECK(ds.status == DataSourceState::Status::kShuttingDown);
 
@@ -887,49 +703,7 @@
   // Clean up resources if there are no more active sources.
   if (data_sources_.empty()) {
     callstack_trie_.ClearTrie();  // purge internings
-    base::MaybeReleaseAllocatorMemToOS();
-  }
-}
-
-// TODO(rsavitski): maybe make the tracing service respect premature
-// producer-driven stops, and then issue a NotifyDataSourceStopped here.
-// Alternatively (and at the expense of higher complexity) introduce a new data
-// source status of "tombstoned", and propagate it until the source is stopped
-// by the service (this would technically allow for stricter lifetime checking
-// of data sources, and help with discarding periodic flushes).
-// TODO(rsavitski): Purging while stopping will currently leave the stop
-// unacknowledged. Consider checking whether the DS is stopping here, and if so,
-// notifying immediately after erasing.
-void PerfProducer::PurgeDataSource(DataSourceInstanceID ds_id) {
-  auto ds_it = data_sources_.find(ds_id);
-  if (ds_it == data_sources_.end())
-    return;
-  DataSourceState& ds = ds_it->second;
-
-  PERFETTO_LOG("Stopping DataSource(%zu) prematurely",
-               static_cast<size_t>(ds_id));
-
-  unwinding_worker_->PostPurgeDataSource(ds_id);
-
-  // Write a packet indicating the abrupt stop.
-  {
-    auto packet = StartTracePacket(ds.trace_writer.get());
-    packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
-    packet->set_timestamp_clock_id(
-        protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
-    auto* perf_sample = packet->set_perf_sample();
-    auto* producer_event = perf_sample->set_producer_event();
-    producer_event->set_source_stop_reason(
-        protos::pbzero::PerfSample::ProducerEvent::PROFILER_STOP_GUARDRAIL);
-  }
-
-  ds.trace_writer->Flush();
-  data_sources_.erase(ds_it);
-
-  // Clean up resources if there are no more active sources.
-  if (data_sources_.empty()) {
-    callstack_trie_.ClearTrie();  // purge internings
-    base::MaybeReleaseAllocatorMemToOS();
+    MaybeReleaseAllocatorMemToOS();
   }
 }
 
diff --git a/src/profiling/perf/perf_producer.h b/src/profiling/perf/perf_producer.h
index b2f6bec..25fc0d2 100644
--- a/src/profiling/perf/perf_producer.h
+++ b/src/profiling/perf/perf_producer.h
@@ -44,8 +44,6 @@
 #include "src/profiling/perf/proc_descriptors.h"
 #include "src/profiling/perf/unwinding.h"
 #include "src/tracing/core/metatrace_writer.h"
-// TODO(rsavitski): move to e.g. src/tracefs/.
-#include "src/traced/probes/ftrace/ftrace_procfs.h"
 
 namespace perfetto {
 namespace profiling {
@@ -86,7 +84,6 @@
 
   // ProcDescriptorDelegate impl:
   void OnProcDescriptors(pid_t pid,
-                         uid_t uid,
                          base::ScopedFile maps_fd,
                          base::ScopedFile mem_fd) override;
 
@@ -141,10 +138,6 @@
     // in the |Unwinder|, which needs to track whether the necessary unwinding
     // inputs for a given process' samples are ready.
     std::map<pid_t, ProcessTrackingStatus> process_states;
-
-    // Command lines we have decided to unwind, up to a total of
-    // additional_cmdline_count values.
-    base::FlatSet<std::string> additional_cmdlines;
   };
 
   // For |EmitSkippedSample|.
@@ -168,7 +161,7 @@
   // on the amount of samples that will be parsed, which might be more than the
   // number of underlying records (as there might be non-sample records).
   bool ReadAndParsePerCpuBuffer(EventReader* reader,
-                                uint64_t max_samples,
+                                uint32_t max_samples,
                                 DataSourceInstanceID ds_id,
                                 DataSourceState* ds);
 
@@ -205,15 +198,6 @@
   // Destroys the state belonging to this instance, and acks the stop to the
   // tracing service.
   void FinishDataSourceStop(DataSourceInstanceID ds_id);
-  // Immediately destroys the data source state, and instructs the unwinder to
-  // do the same. This is used for abrupt stops.
-  void PurgeDataSource(DataSourceInstanceID ds_id);
-
-  // Immediately stops the data source if this daemon's overall memory footprint
-  // is above the given threshold. This periodic task is started only for data
-  // sources that specify a limit.
-  void CheckMemoryFootprintPeriodic(DataSourceInstanceID ds_id,
-                                    uint32_t max_daemon_memory_kb);
 
   void StartMetatraceSource(DataSourceInstanceID ds_id, BufferID target_buffer);
 
@@ -249,10 +233,6 @@
   // Unwinding stage, running on a dedicated thread.
   UnwinderHandle unwinding_worker_;
 
-  // Used for tracepoint name -> id lookups. Initialized lazily, and in general
-  // best effort - can be null if tracefs isn't accessible.
-  std::unique_ptr<FtraceProcfs> tracefs_;
-
   base::WeakPtrFactory<PerfProducer> weak_factory_;  // keep last
 };
 
diff --git a/src/profiling/perf/proc_descriptors.cc b/src/profiling/perf/proc_descriptors.cc
index b03d5d0..b028d85 100644
--- a/src/profiling/perf/proc_descriptors.cc
+++ b/src/profiling/perf/proc_descriptors.cc
@@ -16,7 +16,6 @@
 
 #include "src/profiling/perf/proc_descriptors.h"
 
-#include <fcntl.h>
 #include <signal.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -36,43 +35,26 @@
 }
 
 void DirectDescriptorGetter::GetDescriptorsForPid(pid_t pid) {
-  char dir_buf[128] = {};
-  snprintf(dir_buf, sizeof(dir_buf), "/proc/%d", pid);
-  auto dir_fd =
-      base::ScopedFile(open(dir_buf, O_DIRECTORY | O_RDONLY | O_CLOEXEC));
-  if (!dir_fd) {
-    if (errno != ENOENT)  // not surprising if the process has quit
-      PERFETTO_PLOG("Failed to open [%s]", dir_buf);
-
-    return;
-  }
-
-  struct stat stat_buf;
-  if (fstat(dir_fd.get(), &stat_buf) == -1) {
-    PERFETTO_PLOG("Failed to stat [%s]", dir_buf);
-    return;
-  }
-
-  auto maps_fd =
-      base::ScopedFile{openat(dir_fd.get(), "maps", O_RDONLY | O_CLOEXEC)};
+  char buf[128] = {};
+  snprintf(buf, sizeof(buf), "/proc/%d/maps", pid);
+  auto maps_fd = base::ScopedFile{open(buf, O_RDONLY | O_CLOEXEC)};
   if (!maps_fd) {
     if (errno != ENOENT)  // not surprising if the process has quit
-      PERFETTO_PLOG("Failed to open %s/maps", dir_buf);
+      PERFETTO_PLOG("Failed to open [%s]", buf);
 
     return;
   }
 
-  auto mem_fd =
-      base::ScopedFile{openat(dir_fd.get(), "mem", O_RDONLY | O_CLOEXEC)};
+  snprintf(buf, sizeof(buf), "/proc/%d/mem", pid);
+  auto mem_fd = base::ScopedFile{open(buf, O_RDONLY | O_CLOEXEC)};
   if (!mem_fd) {
     if (errno != ENOENT)  // not surprising if the process has quit
-      PERFETTO_PLOG("Failed to open %s/mem", dir_buf);
+      PERFETTO_PLOG("Failed to open [%s]", buf);
 
     return;
   }
 
-  delegate_->OnProcDescriptors(pid, stat_buf.st_uid, std::move(maps_fd),
-                               std::move(mem_fd));
+  delegate_->OnProcDescriptors(pid, std::move(maps_fd), std::move(mem_fd));
 }
 
 // AndroidRemoteDescriptorGetter:
@@ -106,14 +88,14 @@
     base::UnixSocket*,
     std::unique_ptr<base::UnixSocket> new_connection) {
   PERFETTO_DLOG("remote fds: new connection from pid [%d]",
-                static_cast<int>(new_connection->peer_pid_linux()));
+                static_cast<int>(new_connection->peer_pid()));
 
   active_connections_.emplace(new_connection.get(), std::move(new_connection));
 }
 
 void AndroidRemoteDescriptorGetter::OnDisconnect(base::UnixSocket* self) {
   PERFETTO_DLOG("remote fds: disconnect from pid [%d]",
-                static_cast<int>(self->peer_pid_linux()));
+                static_cast<int>(self->peer_pid()));
 
   auto it = active_connections_.find(self);
   PERFETTO_CHECK(it != active_connections_.end());
@@ -134,8 +116,8 @@
   if (!received_bytes)
     return;
 
-  delegate_->OnProcDescriptors(self->peer_pid_linux(), self->peer_uid_posix(),
-                               std::move(fds[0]), std::move(fds[1]));
+  delegate_->OnProcDescriptors(self->peer_pid(), std::move(fds[0]),
+                               std::move(fds[1]));
 }
 
 }  // namespace perfetto
diff --git a/src/profiling/perf/proc_descriptors.h b/src/profiling/perf/proc_descriptors.h
index 8846c01..e524b17 100644
--- a/src/profiling/perf/proc_descriptors.h
+++ b/src/profiling/perf/proc_descriptors.h
@@ -32,7 +32,6 @@
 class ProcDescriptorDelegate {
  public:
   virtual void OnProcDescriptors(pid_t pid,
-                                 uid_t uid,
                                  base::ScopedFile maps_fd,
                                  base::ScopedFile mem_fd) = 0;
 
diff --git a/src/profiling/perf/unwinding.cc b/src/profiling/perf/unwinding.cc
index 46dfc6b..6457422 100644
--- a/src/profiling/perf/unwinding.cc
+++ b/src/profiling/perf/unwinding.cc
@@ -20,15 +20,23 @@
 
 #include <inttypes.h>
 
-#include <unwindstack/Unwinder.h>
-
 #include "perfetto/ext/base/metatrace.h"
 #include "perfetto/ext/base/thread_utils.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace {
 constexpr size_t kUnwindingMaxFrames = 1000;
 constexpr uint32_t kDataSourceShutdownRetryDelayMs = 400;
+
+void MaybeReleaseAllocatorMemToOS() {
+#if defined(__BIONIC__)
+  // TODO(b/152414415): libunwindstack's volume of small allocations is
+  // adverarial to scudo, which doesn't automatically release small
+  // allocation regions back to the OS. Forceful purge does reclaim all size
+  // classes.
+  mallopt(M_PURGE, 0);
+#endif
+}
+
 }  // namespace
 
 namespace perfetto {
@@ -42,24 +50,18 @@
   base::MaybeSetThreadName("stack-unwinding");
 }
 
-void Unwinder::PostStartDataSource(DataSourceInstanceID ds_id,
-                                   bool kernel_frames) {
+void Unwinder::PostStartDataSource(DataSourceInstanceID ds_id) {
   // No need for a weak pointer as the associated task runner quits (stops
   // running tasks) strictly before the Unwinder's destruction.
-  task_runner_->PostTask(
-      [this, ds_id, kernel_frames] { StartDataSource(ds_id, kernel_frames); });
+  task_runner_->PostTask([this, ds_id] { StartDataSource(ds_id); });
 }
 
-void Unwinder::StartDataSource(DataSourceInstanceID ds_id, bool kernel_frames) {
+void Unwinder::StartDataSource(DataSourceInstanceID ds_id) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DLOG("Unwinder::StartDataSource(%zu)", static_cast<size_t>(ds_id));
 
   auto it_and_inserted = data_sources_.emplace(ds_id, DataSourceState{});
   PERFETTO_DCHECK(it_and_inserted.second);
-
-  if (kernel_frames) {
-    kernel_symbolizer_.GetOrCreateKernelSymbolMap();
-  }
 }
 
 // c++11: use shared_ptr to transfer resource handles, so that the resources get
@@ -100,8 +102,7 @@
                 maps_fd.get(), mem_fd.get());
 
   auto it = data_sources_.find(ds_id);
-  if (it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(it != data_sources_.end());
   DataSourceState& ds = it->second;
 
   ProcessState& proc_state = ds.process_states[pid];  // insert if new
@@ -128,8 +129,7 @@
                 static_cast<size_t>(ds_id), static_cast<int>(pid));
 
   auto it = data_sources_.find(ds_id);
-  if (it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(it != data_sources_.end());
   DataSourceState& ds = it->second;
 
   ProcessState& proc_state = ds.process_states[pid];  // insert if new
@@ -212,18 +212,11 @@
     if (!entry.valid)
       continue;  // already processed
 
-    uint64_t sampled_stack_bytes = entry.sample.stack.size();
-
-    // Data source might be gone due to an abrupt stop.
     auto it = data_sources_.find(entry.data_source_id);
-    if (it == data_sources_.end()) {
-      entry = UnwindEntry::Invalid();
-      DecrementEnqueuedFootprint(sampled_stack_bytes);
-      continue;
-    }
+    PERFETTO_CHECK(it != data_sources_.end());
     DataSourceState& ds = it->second;
 
-    pid_t pid = entry.sample.common.pid;
+    pid_t pid = entry.sample.pid;
     ProcessState& proc_state = ds.process_states[pid];  // insert if new
 
     // Giving up on the sample (proc-fd lookup timed out).
@@ -231,14 +224,9 @@
       PERFETTO_DLOG("Unwinder skipping sample for pid [%d]",
                     static_cast<int>(pid));
 
-      // free up the sampled stack as the main thread has no use for it
-      entry.sample.stack.clear();
-      entry.sample.stack.shrink_to_fit();
-
       delegate_->PostEmitUnwinderSkippedSample(entry.data_source_id,
                                                std::move(entry.sample));
       entry = UnwindEntry::Invalid();
-      DecrementEnqueuedFootprint(sampled_stack_bytes);
       continue;
     }
 
@@ -270,7 +258,6 @@
       delegate_->PostEmitSample(entry.data_source_id,
                                 std::move(unwound_sample));
       entry = UnwindEntry::Invalid();
-      DecrementEnqueuedFootprint(sampled_stack_bytes);
       continue;
     }
   }
@@ -303,7 +290,11 @@
   PERFETTO_DCHECK(unwind_state);
 
   CompletedSample ret;
-  ret.common = sample.common;
+  ret.cpu = sample.cpu;
+  ret.pid = sample.pid;
+  ret.tid = sample.tid;
+  ret.timestamp = sample.timestamp;
+  ret.cpu_mode = sample.cpu_mode;
 
   // Overlay the stack bytes over /proc/<pid>/mem.
   std::shared_ptr<unwindstack::Memory> overlay_memory =
@@ -312,142 +303,63 @@
           reinterpret_cast<const uint8_t*>(sample.stack.data()),
           sample.stack.size());
 
-  struct UnwindResult {
-    unwindstack::ErrorCode error_code;
-    uint64_t warnings;
-    std::vector<unwindstack::FrameData> frames;
+  // Unwindstack clobbers registers, so make a copy in case we need to retry.
+  auto regs_copy = std::unique_ptr<unwindstack::Regs>{sample.regs->Clone()};
 
-    UnwindResult(unwindstack::ErrorCode e,
-                 uint64_t w,
-                 std::vector<unwindstack::FrameData> f)
-        : error_code(e), warnings(w), frames(std::move(f)) {}
-    UnwindResult(const UnwindResult&) = delete;
-    UnwindResult& operator=(const UnwindResult&) = delete;
-    UnwindResult(UnwindResult&&) __attribute__((unused)) = default;
-    UnwindResult& operator=(UnwindResult&&) = default;
-  };
-  auto attempt_unwind = [&sample, unwind_state, pid_unwound_before,
-                         &overlay_memory]() -> UnwindResult {
+  unwindstack::ErrorCode error_code = unwindstack::ERROR_NONE;
+  unwindstack::Unwinder unwinder(kUnwindingMaxFrames, &unwind_state->fd_maps,
+                                 regs_copy.get(), overlay_memory);
+
+  // TODO(rsavitski): consider rate-limiting unwind retries.
+  for (int attempt = 0; attempt < 2; attempt++) {
     metatrace::ScopedEvent m(metatrace::TAG_PRODUCER,
                              pid_unwound_before
                                  ? metatrace::PROFILER_UNWIND_ATTEMPT
                                  : metatrace::PROFILER_UNWIND_INITIAL_ATTEMPT);
 
-    // Unwindstack clobbers registers, so make a copy in case of retries.
-    auto regs_copy = std::unique_ptr<unwindstack::Regs>{sample.regs->Clone()};
-
-    unwindstack::Unwinder unwinder(kUnwindingMaxFrames, &unwind_state->fd_maps,
-                                   regs_copy.get(), overlay_memory);
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-    unwinder.SetJitDebug(unwind_state->GetJitDebug(regs_copy->Arch()));
-    unwinder.SetDexFiles(unwind_state->GetDexFiles(regs_copy->Arch()));
+    unwinder.SetJitDebug(unwind_state->jit_debug.get(), regs_copy->Arch());
+    unwinder.SetDexFiles(unwind_state->dex_files.get(), regs_copy->Arch());
 #endif
     unwinder.Unwind(/*initial_map_names_to_skip=*/nullptr,
                     /*map_suffixes_to_ignore=*/nullptr);
-    return {unwinder.LastErrorCode(), unwinder.warnings(),
-            unwinder.ConsumeFrames()};
-  };
+    error_code = unwinder.LastErrorCode();
+    if (error_code != unwindstack::ERROR_INVALID_MAP)
+      break;
 
-  // first unwind attempt
-  UnwindResult unwind = attempt_unwind();
-
-  bool should_retry = unwind.error_code == unwindstack::ERROR_INVALID_MAP ||
-                      unwind.warnings & unwindstack::WARNING_DEX_PC_NOT_IN_MAP;
-
-  // ERROR_INVALID_MAP means that unwinding reached a point in memory without a
-  // corresponding mapping. This is possible if the parsed /proc/pid/maps is
-  // outdated. Reparse and try again.
-  //
-  // Special case: skip reparsing if the stack sample was (most likely)
-  // truncated. We perform the best-effort unwind of the sampled part, but an
-  // error around the truncated part is not unexpected.
-  //
-  // TODO(rsavitski): consider rate-limiting unwind retries.
-  if (should_retry && sample.stack_maxed) {
-    PERFETTO_DLOG("Skipping reparse/reunwind due to maxed stack for tid [%d]",
-                  static_cast<int>(sample.common.tid));
-  } else if (should_retry) {
-    {
-      PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_MAPS_REPARSE);
-      PERFETTO_DLOG("Reparsing maps for pid [%d]",
-                    static_cast<int>(sample.common.pid));
-      unwind_state->ReparseMaps();
-    }
-    // reunwind attempt
-    unwind = attempt_unwind();
+    // Otherwise, reparse the maps, and possibly retry the unwind.
+    PERFETTO_DLOG("Reparsing maps for pid [%d]", static_cast<int>(sample.pid));
+    PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_MAPS_REPARSE);
+    unwind_state->ReparseMaps();
   }
 
-  // Symbolize kernel-unwound kernel frames (if any).
-  std::vector<unwindstack::FrameData> kernel_frames =
-      SymbolizeKernelCallchain(sample);
+  PERFETTO_DLOG("Frames from unwindstack for pid [%d]:",
+                static_cast<int>(sample.pid));
+  std::vector<unwindstack::FrameData> frames = unwinder.ConsumeFrames();
+  ret.frames.reserve(frames.size());
+  for (unwindstack::FrameData& frame : frames) {
+    if (PERFETTO_DLOG_IS_ON())
+      PERFETTO_DLOG("%s", unwinder.FormatFrame(frame).c_str());
 
-  // Concatenate the kernel and userspace frames.
-  auto kernel_frames_size = kernel_frames.size();
-
-  ret.frames = std::move(kernel_frames);
-
-  ret.build_ids.reserve(kernel_frames_size + unwind.frames.size());
-  ret.frames.reserve(kernel_frames_size + unwind.frames.size());
-
-  ret.build_ids.resize(kernel_frames_size, "");
-
-  for (unwindstack::FrameData& frame : unwind.frames) {
-    ret.build_ids.emplace_back(unwind_state->GetBuildId(frame));
-    ret.frames.emplace_back(std::move(frame));
+    ret.frames.emplace_back(unwind_state->AnnotateFrame(std::move(frame)));
   }
 
-  PERFETTO_CHECK(ret.build_ids.size() == ret.frames.size());
-
   // In case of an unwinding error, add a synthetic error frame (which will
   // appear as a caller of the partially-unwound fragment), for easier
   // visualization of errors.
-  if (unwind.error_code != unwindstack::ERROR_NONE) {
-    PERFETTO_DLOG("Unwinding error %" PRIu8, unwind.error_code);
+  if (error_code != unwindstack::ERROR_NONE) {
+    PERFETTO_DLOG("Unwinding error %" PRIu8, error_code);
     unwindstack::FrameData frame_data{};
     frame_data.function_name =
-        "ERROR " + StringifyLibUnwindstackError(unwind.error_code);
+        "ERROR " + StringifyLibUnwindstackError(error_code);
     frame_data.map_name = "ERROR";
-    ret.frames.emplace_back(std::move(frame_data));
-    ret.build_ids.emplace_back("");
-    ret.unwind_error = unwind.error_code;
+    ret.frames.emplace_back(std::move(frame_data), /*build_id=*/"");
+    ret.unwind_error = error_code;
   }
 
   return ret;
 }
 
-std::vector<unwindstack::FrameData> Unwinder::SymbolizeKernelCallchain(
-    const ParsedSample& sample) {
-  std::vector<unwindstack::FrameData> ret;
-  if (sample.kernel_ips.empty())
-    return ret;
-
-  // The list of addresses contains special context marker values (inserted by
-  // the kernel's unwinding) to indicate which section of the callchain belongs
-  // to the kernel/user mode (if the kernel can successfully unwind user
-  // stacks). In our case, we request only the kernel frames.
-  if (sample.kernel_ips[0] != PERF_CONTEXT_KERNEL) {
-    PERFETTO_DFATAL_OR_ELOG(
-        "Unexpected: 0th frame of callchain is not PERF_CONTEXT_KERNEL.");
-    return ret;
-  }
-
-  auto* kernel_map = kernel_symbolizer_.GetOrCreateKernelSymbolMap();
-  PERFETTO_DCHECK(kernel_map);
-  ret.reserve(sample.kernel_ips.size());
-  for (size_t i = 1; i < sample.kernel_ips.size(); i++) {
-    std::string function_name = kernel_map->Lookup(sample.kernel_ips[i]);
-
-    // Synthesise a partially-valid libunwindstack frame struct for the kernel
-    // frame. We reuse the type for convenience. The kernel frames are marked by
-    // a magical "kernel" string as their containing mapping.
-    unwindstack::FrameData frame{};
-    frame.function_name = std::move(function_name);
-    frame.map_name = "kernel";
-    ret.emplace_back(std::move(frame));
-  }
-  return ret;
-}
-
 void Unwinder::PostInitiateDataSourceStop(DataSourceInstanceID ds_id) {
   task_runner_->PostTask([this, ds_id] { InitiateDataSourceStop(ds_id); });
 }
@@ -458,8 +370,7 @@
                 static_cast<size_t>(ds_id));
 
   auto it = data_sources_.find(ds_id);
-  if (it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(it != data_sources_.end());
   DataSourceState& ds = it->second;
 
   PERFETTO_CHECK(ds.status == DataSourceState::Status::kActive);
@@ -476,8 +387,7 @@
                 static_cast<size_t>(ds_id));
 
   auto it = data_sources_.find(ds_id);
-  if (it == data_sources_.end())
-    return;
+  PERFETTO_CHECK(it != data_sources_.end());
   DataSourceState& ds = it->second;
 
   // Drop unwinder's state tied to the source.
@@ -485,40 +395,13 @@
   data_sources_.erase(it);
 
   // Clean up state if there are no more active sources.
-  if (data_sources_.empty()) {
-    kernel_symbolizer_.Destroy();
+  if (data_sources_.empty())
     ResetAndEnableUnwindstackCache();
-  }
 
   // Inform service thread that the unwinder is done with the source.
   delegate_->PostFinishDataSourceStop(ds_id);
 }
 
-void Unwinder::PostPurgeDataSource(DataSourceInstanceID ds_id) {
-  task_runner_->PostTask([this, ds_id] { PurgeDataSource(ds_id); });
-}
-
-void Unwinder::PurgeDataSource(DataSourceInstanceID ds_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("Unwinder::PurgeDataSource(%zu)", static_cast<size_t>(ds_id));
-
-  auto it = data_sources_.find(ds_id);
-  if (it == data_sources_.end())
-    return;
-
-  data_sources_.erase(it);
-
-  // Clean up state if there are no more active sources.
-  if (data_sources_.empty()) {
-    kernel_symbolizer_.Destroy();
-    ResetAndEnableUnwindstackCache();
-    // Also purge scudo on Android, which would normally be done by the service
-    // thread in |FinishDataSourceStop|. This is important as most of the scudo
-    // overhead comes from libunwindstack.
-    base::MaybeReleaseAllocatorMemToOS();
-  }
-}
-
 void Unwinder::PostClearCachedStatePeriodic(DataSourceInstanceID ds_id,
                                             uint32_t period_ms) {
   task_runner_->PostDelayedTask(
@@ -544,7 +427,7 @@
     pid_and_process.second.unwind_state->fd_maps.Reset();
   }
   ResetAndEnableUnwindstackCache();
-  base::MaybeReleaseAllocatorMemToOS();
+  MaybeReleaseAllocatorMemToOS();
 
   PostClearCachedStatePeriodic(ds_id, period_ms);  // repost
 }
diff --git a/src/profiling/perf/unwinding.h b/src/profiling/perf/unwinding.h
index 398747a..46c3760 100644
--- a/src/profiling/perf/unwinding.h
+++ b/src/profiling/perf/unwinding.h
@@ -17,7 +17,6 @@
 #ifndef SRC_PROFILING_PERF_UNWINDING_H_
 #define SRC_PROFILING_PERF_UNWINDING_H_
 
-#include <condition_variable>
 #include <map>
 #include <thread>
 
@@ -32,8 +31,6 @@
 #include "perfetto/ext/base/thread_checker.h"
 #include "perfetto/ext/base/unix_task_runner.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
-#include "src/kallsyms/kernel_symbol_map.h"
-#include "src/kallsyms/lazy_kernel_symbolizer.h"
 #include "src/profiling/common/unwind_support.h"
 #include "src/profiling/perf/common_types.h"
 #include "src/profiling/perf/unwind_queue.h"
@@ -41,7 +38,7 @@
 namespace perfetto {
 namespace profiling {
 
-constexpr static uint32_t kUnwindQueueCapacity = 1024;
+constexpr static uint32_t kUnwindQueueCapacity = 2048;
 
 // Unwinds callstacks based on the sampled stack and register state (see
 // |ParsedSample|). Has a single unwinding ring queue, shared across
@@ -88,7 +85,7 @@
 
   ~Unwinder() { PERFETTO_DCHECK_THREAD(thread_checker_); }
 
-  void PostStartDataSource(DataSourceInstanceID ds_id, bool kernel_frames);
+  void PostStartDataSource(DataSourceInstanceID ds_id);
   void PostAdoptProcDescriptors(DataSourceInstanceID ds_id,
                                 pid_t pid,
                                 base::ScopedFile maps_fd,
@@ -96,7 +93,6 @@
   void PostRecordTimedOutProcDescriptors(DataSourceInstanceID ds_id, pid_t pid);
   void PostProcessQueue();
   void PostInitiateDataSourceStop(DataSourceInstanceID ds_id);
-  void PostPurgeDataSource(DataSourceInstanceID ds_id);
 
   void PostClearCachedStatePeriodic(DataSourceInstanceID ds_id,
                                     uint32_t period_ms);
@@ -105,22 +101,6 @@
     return unwind_queue_;
   }
 
-  uint64_t GetEnqueuedFootprint() {
-    uint64_t freed =
-        footprint_tracker_.stack_bytes_freed.load(std::memory_order_acquire);
-    uint64_t allocated = footprint_tracker_.stack_bytes_allocated.load(
-        std::memory_order_relaxed);
-
-    // overflow not a concern in practice
-    PERFETTO_DCHECK(allocated >= freed);
-    return allocated - freed;
-  }
-
-  void IncrementEnqueuedFootprint(uint64_t increment) {
-    footprint_tracker_.stack_bytes_allocated.fetch_add(
-        increment, std::memory_order_relaxed);
-  }
-
  private:
   struct ProcessState {
     enum class Status {
@@ -144,21 +124,11 @@
     std::map<pid_t, ProcessState> process_states;
   };
 
-  // Accounting for how much heap memory is attached to the enqueued samples at
-  // a given time. Read by the main thread, mutated by both threads.
-  // We track just the heap allocated for the sampled stacks, as it dominates
-  // the per-sample heap use.
-  struct QueueFootprintTracker {
-    std::atomic<uint64_t> stack_bytes_allocated;
-    std::atomic<uint64_t> stack_bytes_freed;
-  };
-
   // Must be instantiated via the |UnwinderHandle|.
   Unwinder(Delegate* delegate, base::UnixTaskRunner* task_runner);
 
   // Marks the data source as valid and active at the unwinding stage.
-  // Initializes kernel address symbolization if needed.
-  void StartDataSource(DataSourceInstanceID ds_id, bool kernel_frames);
+  void StartDataSource(DataSourceInstanceID ds_id);
 
   void AdoptProcDescriptors(DataSourceInstanceID ds_id,
                             pid_t pid,
@@ -179,10 +149,6 @@
                                UnwindingMetadata* unwind_state,
                                bool pid_unwound_before);
 
-  // Returns a list of symbolized kernel frames in the sample (if any).
-  std::vector<unwindstack::FrameData> SymbolizeKernelCallchain(
-      const ParsedSample& sample);
-
   // Marks the data source as shutting down at the unwinding stage. It is known
   // that no new samples for this source will be pushed into the queue, but we
   // need to delay the unwinder state teardown until all previously-enqueued
@@ -194,14 +160,6 @@
   // sequence.
   void FinishDataSourceStop(DataSourceInstanceID ds_id);
 
-  // Immediately destroys the data source state, used for abrupt stops.
-  void PurgeDataSource(DataSourceInstanceID ds_id);
-
-  void DecrementEnqueuedFootprint(uint64_t decrement) {
-    footprint_tracker_.stack_bytes_freed.fetch_add(decrement,
-                                                   std::memory_order_relaxed);
-  }
-
   // Clears the parsed maps for all previously-sampled processes, and resets the
   // libunwindstack cache. This has the effect of deallocating the cached Elf
   // objects within libunwindstack, which take up non-trivial amounts of memory.
@@ -237,9 +195,7 @@
   base::UnixTaskRunner* const task_runner_;
   Delegate* const delegate_;
   UnwindQueue<UnwindEntry, kUnwindQueueCapacity> unwind_queue_;
-  QueueFootprintTracker footprint_tracker_;
   std::map<DataSourceInstanceID, DataSourceState> data_sources_;
-  LazyKernelSymbolizer kernel_symbolizer_;
 
   PERFETTO_THREAD_CHECKER(thread_checker_)
 };
@@ -250,7 +206,7 @@
 // owned state, and consolidate.
 class UnwinderHandle {
  public:
-  explicit UnwinderHandle(Unwinder::Delegate* delegate) {
+  UnwinderHandle(Unwinder::Delegate* delegate) {
     std::mutex init_lock;
     std::condition_variable init_cv;
 
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn
index 6989d0a..69c9446 100644
--- a/src/profiling/symbolizer/BUILD.gn
+++ b/src/profiling/symbolizer/BUILD.gn
@@ -13,23 +13,13 @@
 # limitations under the License.
 
 import("../../../gn/perfetto.gni")
-import("../../../gn/test.gni")
 
 source_set("symbolizer") {
   public_deps = [ "../../../include/perfetto/ext/base" ]
   deps = [ "../../../gn:default_deps" ]
   sources = [
-    "filesystem.h",
-    "filesystem_posix.cc",
-    "filesystem_windows.cc",
     "local_symbolizer.cc",
     "local_symbolizer.h",
-    "scoped_read_mmap.h",
-    "scoped_read_mmap_posix.cc",
-    "scoped_read_mmap_windows.cc",
-    "subprocess.h",
-    "subprocess_posix.cc",
-    "subprocess_windows.cc",
     "symbolizer.cc",
     "symbolizer.h",
   ]
@@ -52,14 +42,3 @@
     "symbolize_database.h",
   ]
 }
-
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    ":symbolizer",
-    "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-    "../../base:test_support",
-  ]
-  sources = [ "local_symbolizer_unittest.cc" ]
-}
diff --git a/src/profiling/symbolizer/filesystem.h b/src/profiling/symbolizer/filesystem.h
deleted file mode 100644
index d9cf87c..0000000
--- a/src/profiling/symbolizer/filesystem.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_SYMBOLIZER_FILESYSTEM_H_
-#define SRC_PROFILING_SYMBOLIZER_FILESYSTEM_H_
-
-#include "src/profiling/symbolizer/local_symbolizer.h"
-
-namespace perfetto {
-namespace profiling {
-
-using FileCallback = std::function<void(const char*, size_t)>;
-size_t GetFileSize(const std::string& file_path);
-bool WalkDirectories(std::vector<std::string> dirs, FileCallback fn);
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_SYMBOLIZER_FILESYSTEM_H_
diff --git a/src/profiling/symbolizer/filesystem_posix.cc b/src/profiling/symbolizer/filesystem_posix.cc
deleted file mode 100644
index cc983e2..0000000
--- a/src/profiling/symbolizer/filesystem_posix.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/filesystem.h"
-
-#include "perfetto/base/build_config.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include <fts.h>
-#include <sys/stat.h>
-#endif
-
-#include <string>
-
-#include "perfetto/ext/base/file_utils.h"
-
-namespace perfetto {
-namespace profiling {
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-bool WalkDirectories(std::vector<std::string> dirs, FileCallback fn) {
-  std::vector<char*> dir_cstrs;
-  dir_cstrs.reserve(dirs.size());
-  for (std::string& dir : dirs)
-    dir_cstrs.emplace_back(&dir[0]);
-  dir_cstrs.push_back(nullptr);
-  base::ScopedResource<FTS*, fts_close, nullptr> fts(
-      fts_open(&dir_cstrs[0], FTS_LOGICAL | FTS_NOCHDIR, nullptr));
-  if (!fts) {
-    PERFETTO_PLOG("fts_open");
-    return false;
-  }
-  FTSENT* ent;
-  while ((ent = fts_read(*fts))) {
-    if (ent->fts_info & FTS_F)
-      fn(ent->fts_path, static_cast<size_t>(ent->fts_statp->st_size));
-  }
-  return true;
-}
-
-size_t GetFileSize(const std::string& file_path) {
-  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
-  if (!fd) {
-    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
-    return 0;
-  }
-  struct stat buf;
-  if (fstat(*fd, &buf) == -1) {
-    return 0;
-  }
-  return static_cast<size_t>(buf.st_size);
-}
-#else
-bool WalkDirectories(std::vector<std::string>, FileCallback) {
-  return false;
-}
-size_t GetFileSize(const std::string&) {
-  return 0;
-}
-#endif
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/filesystem_windows.cc b/src/profiling/symbolizer/filesystem_windows.cc
deleted file mode 100644
index bb2652c..0000000
--- a/src/profiling/symbolizer/filesystem_windows.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/filesystem.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <Windows.h>
-
-namespace perfetto {
-namespace profiling {
-
-bool WalkDirectories(std::vector<std::string> dirs, FileCallback fn) {
-  std::vector<std::string> sub_dirs;
-  for (const std::string& dir : dirs) {
-    WIN32_FIND_DATAA file;
-    HANDLE fh = FindFirstFileA((dir + "\\*").c_str(), &file);
-    if (fh != INVALID_HANDLE_VALUE) {
-      do {
-        std::string file_path = dir + "\\" + file.cFileName;
-        if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-          if (strcmp(file.cFileName, ".") != 0 &&
-              strcmp(file.cFileName, "..") != 0) {
-            sub_dirs.push_back(file_path);
-          }
-        } else {
-          ULARGE_INTEGER size;
-          size.HighPart = file.nFileSizeHigh;
-          size.LowPart = file.nFileSizeLow;
-          fn(file_path.c_str(), size.QuadPart);
-        }
-      } while (FindNextFileA(fh, &file));
-    }
-    CloseHandle(fh);
-  }
-  if (!sub_dirs.empty()) {
-    WalkDirectories(sub_dirs, fn);
-  }
-  return true;
-}
-
-size_t GetFileSize(const std::string& file_path) {
-  HANDLE file =
-      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
-                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
-  if (file == INVALID_HANDLE_VALUE) {
-    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
-    return 0;
-  }
-  LARGE_INTEGER file_size;
-  file_size.QuadPart = 0;
-  if (!GetFileSizeEx(file, &file_size)) {
-    PERFETTO_PLOG("Failed to get file size %s", file_path.c_str());
-  }
-  CloseHandle(file);
-  return static_cast<size_t>(file_size.QuadPart);
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/local_symbolizer.cc b/src/profiling/symbolizer/local_symbolizer.cc
index fa4e449..d0290da 100644
--- a/src/profiling/symbolizer/local_symbolizer.cc
+++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2019 The Android Open Source Project
  *
@@ -14,230 +15,61 @@
  * 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 "src/profiling/symbolizer/local_symbolizer.h"
 
-#include <fcntl.h>
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/logging.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_utils.h"
-#include "src/profiling/symbolizer/filesystem.h"
-#include "src/profiling/symbolizer/scoped_read_mmap.h"
-
-namespace perfetto {
-namespace profiling {
-
-// TODO(fmayer): Fix up name. This suggests it always returns a symbolizer or
-// dies, which isn't the case.
-std::unique_ptr<Symbolizer> LocalSymbolizerOrDie(
-    std::vector<std::string> binary_path,
-    const char* mode) {
-  std::unique_ptr<Symbolizer> symbolizer;
-
-  if (!binary_path.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-    std::unique_ptr<BinaryFinder> finder;
-    if (!mode || strncmp(mode, "find", 4) == 0)
-      finder.reset(new LocalBinaryFinder(std::move(binary_path)));
-    else if (strncmp(mode, "index", 5) == 0)
-      finder.reset(new LocalBinaryIndexer(std::move(binary_path)));
-    else
-      PERFETTO_FATAL("Invalid symbolizer mode [find | index]: %s", mode);
-    symbolizer.reset(new LocalSymbolizer(std::move(finder)));
-#else
-    base::ignore_result(mode);
-    PERFETTO_FATAL("This build does not support local symbolization.");
-#endif
-  }
-  return symbolizer;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
 #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 <signal.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-constexpr const char* kDefaultSymbolizer = "llvm-symbolizer.exe";
-#else
-constexpr const char* kDefaultSymbolizer = "llvm-symbolizer";
-#endif
+#include <sys/wait.h>
+#include <unistd.h>
 
 namespace perfetto {
 namespace profiling {
 
-std::vector<std::string> GetLines(
-    std::function<int64_t(char*, size_t)> fn_read) {
+namespace {
+
+std::vector<std::string> GetLines(FILE* f) {
   std::vector<std::string> lines;
-  char buffer[512];
-  int64_t rd = 0;
-  // Cache the partial line of the previous read.
-  std::string last_line;
-  while ((rd = fn_read(buffer, sizeof(buffer))) > 0) {
-    std::string data(buffer, static_cast<size_t>(rd));
-    // Create stream buffer of last partial line + new data
-    std::stringstream stream(last_line + data);
-    std::string line;
-    last_line = "";
-    while (std::getline(stream, line)) {
-      // Return from reading when we read an empty line.
-      if (line.empty()) {
-        return lines;
-      } else if (stream.eof()) {
-        // Cache off the partial line when we hit end of stream.
-        last_line += line;
-        break;
-      } else {
-        lines.push_back(line);
-      }
+  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);
     }
-  }
-  if (rd == -1) {
-    PERFETTO_ELOG("Failed to read data from subprocess.");
-  }
+    free(line);
+    line = nullptr;
+    n = 0;
+  } while (rd > 1);
   return lines;
 }
 
-namespace {
-// We cannot just include elf.h, as that only exists on Linux, and we want to
-// allow symbolization on other platforms as well. As we only need a small
-// subset, it is easiest to define the constants and structs ourselves.
-constexpr auto PT_LOAD = 1;
-constexpr auto PF_X = 1;
-constexpr auto SHT_NOTE = 7;
-constexpr auto NT_GNU_BUILD_ID = 3;
-constexpr auto ELFCLASS32 = 1;
-constexpr auto ELFCLASS64 = 2;
-constexpr auto ELFMAG0 = 0x7f;
-constexpr auto ELFMAG1 = 'E';
-constexpr auto ELFMAG2 = 'L';
-constexpr auto ELFMAG3 = 'F';
-constexpr auto EI_MAG0 = 0;
-constexpr auto EI_MAG1 = 1;
-constexpr auto EI_MAG2 = 2;
-constexpr auto EI_MAG3 = 3;
-constexpr auto EI_CLASS = 4;
-
 struct Elf32 {
-  using Addr = uint32_t;
-  using Half = uint16_t;
-  using Off = uint32_t;
-  using Sword = int32_t;
-  using Word = uint32_t;
-  struct Ehdr {
-    unsigned char e_ident[16];
-    Half e_type;
-    Half e_machine;
-    Word e_version;
-    Addr e_entry;
-    Off e_phoff;
-    Off e_shoff;
-    Word e_flags;
-    Half e_ehsize;
-    Half e_phentsize;
-    Half e_phnum;
-    Half e_shentsize;
-    Half e_shnum;
-    Half e_shstrndx;
-  };
-  struct Shdr {
-    Word sh_name;
-    Word sh_type;
-    Word sh_flags;
-    Addr sh_addr;
-    Off sh_offset;
-    Word sh_size;
-    Word sh_link;
-    Word sh_info;
-    Word sh_addralign;
-    Word sh_entsize;
-  };
-  struct Nhdr {
-    Word n_namesz;
-    Word n_descsz;
-    Word n_type;
-  };
-  struct Phdr {
-    uint32_t p_type;
-    Off p_offset;
-    Addr p_vaddr;
-    Addr p_paddr;
-    uint32_t p_filesz;
-    uint32_t p_memsz;
-    uint32_t p_flags;
-    uint32_t p_align;
-  };
+  using Ehdr = Elf32_Ehdr;
+  using Shdr = Elf32_Shdr;
+  using Nhdr = Elf32_Nhdr;
 };
 
 struct Elf64 {
-  using Addr = uint64_t;
-  using Half = uint16_t;
-  using SHalf = int16_t;
-  using Off = uint64_t;
-  using Sword = int32_t;
-  using Word = uint32_t;
-  using Xword = uint64_t;
-  using Sxword = int64_t;
-  struct Ehdr {
-    unsigned char e_ident[16];
-    Half e_type;
-    Half e_machine;
-    Word e_version;
-    Addr e_entry;
-    Off e_phoff;
-    Off e_shoff;
-    Word e_flags;
-    Half e_ehsize;
-    Half e_phentsize;
-    Half e_phnum;
-    Half e_shentsize;
-    Half e_shnum;
-    Half e_shstrndx;
-  };
-  struct Shdr {
-    Word sh_name;
-    Word sh_type;
-    Xword sh_flags;
-    Addr sh_addr;
-    Off sh_offset;
-    Xword sh_size;
-    Word sh_link;
-    Word sh_info;
-    Xword sh_addralign;
-    Xword sh_entsize;
-  };
-  struct Nhdr {
-    Word n_namesz;
-    Word n_descsz;
-    Word n_type;
-  };
-  struct Phdr {
-    uint32_t p_type;
-    uint32_t p_flags;
-    Off p_offset;
-    Addr p_vaddr;
-    Addr p_paddr;
-    uint64_t p_filesz;
-    uint64_t p_memsz;
-    uint64_t p_align;
-  };
+  using Ehdr = Elf64_Ehdr;
+  using Shdr = Elf64_Shdr;
+  using Nhdr = Elf64_Nhdr;
 };
 
 template <typename E>
@@ -246,12 +78,6 @@
       static_cast<char*>(mem) + ehdr->e_shoff + i * sizeof(typename E::Shdr));
 }
 
-template <typename E>
-typename E::Phdr* GetPhdr(void* mem, const typename E::Ehdr* ehdr, size_t i) {
-  return reinterpret_cast<typename E::Phdr*>(
-      static_cast<char*>(mem) + ehdr->e_phoff + i * sizeof(typename E::Phdr));
-}
-
 bool InRange(const void* base,
              size_t total_size,
              const void* ptr,
@@ -261,26 +87,6 @@
 }
 
 template <typename E>
-base::Optional<uint64_t> GetLoadBias(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_phnum; ++i) {
-    typename E::Phdr* phdr = GetPhdr<E>(mem, ehdr, i);
-    if (!InRange(mem, size, phdr, sizeof(typename E::Phdr))) {
-      PERFETTO_ELOG("Corrupted ELF.");
-      return base::nullopt;
-    }
-    if (phdr->p_type == PT_LOAD && phdr->p_flags & PF_X) {
-      return phdr->p_vaddr - phdr->p_offset;
-    }
-  }
-  return 0u;
-}
-
-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))) {
@@ -330,6 +136,41 @@
   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",
@@ -340,135 +181,16 @@
   return hex_build_id.substr(0, 2) + "/" + hex_build_id.substr(2);
 }
 
-bool IsElf(const char* mem, size_t size) {
-  if (size <= EI_MAG3)
-    return false;
-  return (mem[EI_MAG0] == ELFMAG0 && mem[EI_MAG1] == ELFMAG1 &&
-          mem[EI_MAG2] == ELFMAG2 && mem[EI_MAG3] == ELFMAG3);
-}
-
-struct BuildIdAndLoadBias {
-  std::string build_id;
-  uint64_t load_bias;
-};
-
-base::Optional<BuildIdAndLoadBias> GetBuildIdAndLoadBias(const char* fname,
-                                                         size_t size) {
-  static_assert(EI_CLASS > EI_MAG3, "mem[EI_MAG?] accesses are in range.");
-  if (size <= EI_CLASS)
-    return base::nullopt;
-  ScopedReadMmap map(fname, size);
-  if (!map.IsValid()) {
-    PERFETTO_PLOG("mmap");
-    return base::nullopt;
-  }
-  char* mem = static_cast<char*>(*map);
-
-  if (!IsElf(mem, size))
-    return base::nullopt;
-
-  base::Optional<std::string> build_id;
-  base::Optional<uint64_t> load_bias;
-  switch (mem[EI_CLASS]) {
-    case ELFCLASS32:
-      build_id = GetBuildId<Elf32>(mem, size);
-      load_bias = GetLoadBias<Elf32>(mem, size);
-      break;
-    case ELFCLASS64:
-      build_id = GetBuildId<Elf64>(mem, size);
-      load_bias = GetLoadBias<Elf64>(mem, size);
-      break;
-    default:
-      return base::nullopt;
-  }
-  if (build_id && load_bias) {
-    return BuildIdAndLoadBias{*build_id, *load_bias};
-  }
-  return base::nullopt;
-}
-
-std::map<std::string, FoundBinary> BuildIdIndex(std::vector<std::string> dirs) {
-  std::map<std::string, FoundBinary> result;
-  WalkDirectories(std::move(dirs), [&result](const char* fname, size_t size) {
-    char magic[EI_MAG3 + 1];
-    // Scope file access. On windows OpenFile opens an exclusive lock.
-    // This lock needs to be released before mapping the file.
-    {
-      base::ScopedFile fd(base::OpenFile(fname, O_RDONLY));
-      if (!fd) {
-        PERFETTO_PLOG("Failed to open %s", fname);
-        return;
-      }
-      ssize_t rd = base::Read(*fd, &magic, sizeof(magic));
-      if (rd != sizeof(magic)) {
-        PERFETTO_PLOG("Failed to read %s", fname);
-        return;
-      }
-      if (!IsElf(magic, static_cast<size_t>(rd))) {
-        PERFETTO_DLOG("%s not an ELF.", fname);
-        return;
-      }
-    }
-    base::Optional<BuildIdAndLoadBias> build_id_and_load_bias =
-        GetBuildIdAndLoadBias(fname, size);
-    if (build_id_and_load_bias) {
-      result.emplace(build_id_and_load_bias->build_id,
-                     FoundBinary{fname, build_id_and_load_bias->load_bias});
-    }
-  });
-  return result;
-}
-
 }  // namespace
 
-bool ParseLlvmSymbolizerLine(const std::string& line,
-                             std::string* file_name,
-                             uint32_t* line_no) {
-  size_t col_pos = line.rfind(':');
-  if (col_pos == std::string::npos || col_pos == 0)
-    return false;
-  size_t row_pos = line.rfind(':', col_pos - 1);
-  if (row_pos == std::string::npos || row_pos == 0)
-    return false;
-  *file_name = line.substr(0, row_pos);
-  auto line_no_str = line.substr(row_pos + 1, col_pos - row_pos - 1);
-
-  base::Optional<int32_t> opt_parsed_line_no = base::StringToInt32(line_no_str);
-  if (!opt_parsed_line_no || *opt_parsed_line_no < 0)
-    return false;
-  *line_no = static_cast<uint32_t>(*opt_parsed_line_no);
-  return true;
-}
-
-BinaryFinder::~BinaryFinder() = default;
-
-LocalBinaryIndexer::LocalBinaryIndexer(std::vector<std::string> roots)
-    : buildid_to_file_(BuildIdIndex(std::move(roots))) {}
-
-base::Optional<FoundBinary> LocalBinaryIndexer::FindBinary(
-    const std::string& abspath,
-    const std::string& build_id) {
-  auto it = buildid_to_file_.find(build_id);
-  if (it != buildid_to_file_.end())
-    return it->second;
-  PERFETTO_ELOG("Could not find Build ID: %s (file %s).",
-                base::ToHex(build_id).c_str(), abspath.c_str());
-  return base::nullopt;
-}
-
-LocalBinaryIndexer::~LocalBinaryIndexer() = default;
-
-LocalBinaryFinder::LocalBinaryFinder(std::vector<std::string> roots)
-    : roots_(std::move(roots)) {}
-
-base::Optional<FoundBinary> LocalBinaryFinder::FindBinary(
+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<FoundBinary>& cache_entry = 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);
@@ -480,30 +202,44 @@
   return cache_entry;
 }
 
-base::Optional<FoundBinary> LocalBinaryFinder::IsCorrectFile(
-    const std::string& symbol_file,
-    const std::string& build_id) {
-  if (!base::FileExists(symbol_file)) {
-    return base::nullopt;
-  }
-  // Openfile opens the file with an exclusive lock on windows.
-  size_t size = GetFileSize(symbol_file);
+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;
 
-  if (size == 0) {
-    return base::nullopt;
+  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;
   }
 
-  base::Optional<BuildIdAndLoadBias> build_id_and_load_bias =
-      GetBuildIdAndLoadBias(symbol_file.c_str(), size);
-  if (!build_id_and_load_bias)
-    return base::nullopt;
-  if (build_id_and_load_bias->build_id != build_id) {
-    return base::nullopt;
+  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;
   }
-  return FoundBinary{symbol_file, build_id_and_load_bias->load_bias};
 }
 
-base::Optional<FoundBinary> LocalBinaryFinder::FindBinaryInRoot(
+base::Optional<std::string> LocalBinaryFinder::FindBinaryInRoot(
     const std::string& root_str,
     const std::string& abspath,
     const std::string& build_id) {
@@ -539,35 +275,29 @@
   // * $ROOT/foo.so
   // * $ROOT/.build-id/ab/cd1234.debug
 
-  base::Optional<FoundBinary> result;
-
   std::string symbol_file = root_str + "/" + dirname + "/" + filename;
-  result = IsCorrectFile(symbol_file, build_id);
-  if (result) {
-    return result;
-  }
+  if (access(symbol_file.c_str(), F_OK) == 0 &&
+      IsCorrectFile(symbol_file, build_id))
+    return {symbol_file};
 
-  if (base::StartsWith(filename, kApkPrefix)) {
+  if (filename.find(kApkPrefix) == 0) {
     symbol_file =
         root_str + "/" + dirname + "/" + filename.substr(sizeof(kApkPrefix));
-    result = IsCorrectFile(symbol_file, build_id);
-    if (result) {
-      return result;
-    }
+    if (access(symbol_file.c_str(), F_OK) == 0 &&
+        IsCorrectFile(symbol_file, build_id))
+      return {symbol_file};
   }
 
   symbol_file = root_str + "/" + filename;
-  result = IsCorrectFile(symbol_file, build_id);
-  if (result) {
-    return result;
-  }
+  if (access(symbol_file.c_str(), F_OK) == 0 &&
+      IsCorrectFile(symbol_file, build_id))
+    return {symbol_file};
 
-  if (base::StartsWith(filename, kApkPrefix)) {
+  if (filename.find(kApkPrefix) == 0) {
     symbol_file = root_str + "/" + filename.substr(sizeof(kApkPrefix));
-    result = IsCorrectFile(symbol_file, build_id);
-    if (result) {
-      return result;
-    }
+    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());
@@ -575,40 +305,58 @@
   if (!split_hex_build_id.empty()) {
     symbol_file =
         root_str + "/" + ".build-id" + "/" + split_hex_build_id + ".debug";
-    result = IsCorrectFile(symbol_file, build_id);
-    if (result) {
-      return result;
-    }
+    if (access(symbol_file.c_str(), F_OK) == 0 &&
+        IsCorrectFile(symbol_file, build_id))
+      return {symbol_file};
   }
 
   return base::nullopt;
 }
 
-LocalBinaryFinder::~LocalBinaryFinder() = default;
+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]));
 
-LLVMSymbolizerProcess::LLVMSymbolizerProcess(const std::string& symbolizer_path)
-    :
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-      subprocess_(symbolizer_path, {}) {
+  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();
+    if (execvp(file.c_str(), &(c_str_args[0])) == -1)
+      PERFETTO_FATAL("Failed to exec %s", file.c_str());
+  }
+  PERFETTO_CHECK(pid_ != -1);
+  input_pipe_.rd.reset();
+  output_pipe_.wr.reset();
 }
-#else
-      subprocess_(symbolizer_path, {"llvm-symbolizer"}) {
+
+Subprocess::~Subprocess() {
+  if (pid_ != -1) {
+    kill(pid_, SIGKILL);
+    int wstatus;
+    PERFETTO_EINTR(waitpid(pid_, &wstatus, 0));
+  }
 }
-#endif
+
+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;
-  char buffer[1024];
-  int size = sprintf(buffer, "\"%s\" 0x%" PRIx64 "\n", binary.c_str(), address);
-  if (subprocess_.Write(buffer, static_cast<size_t>(size)) < 0) {
+
+  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([&](char* read_buffer, size_t buffer_size) {
-    return subprocess_.Read(read_buffer, buffer_size);
-  });
+  auto lines = GetLines(read_file_);
   // llvm-symbolizer writes out records in the form of
   // Foo(Bar*)
   // foo.cc:123
@@ -620,7 +368,7 @@
     if (i % 2 == 0) {
       cur.function_name = lines[i];
     } else {
-      if (!ParseLlvmSymbolizerLine(lines[i], &cur.file_name, &cur.line)) {
+      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 = "";
@@ -640,37 +388,18 @@
 std::vector<std::vector<SymbolizedFrame>> LocalSymbolizer::Symbolize(
     const std::string& mapping_name,
     const std::string& build_id,
-    uint64_t load_bias,
     const std::vector<uint64_t>& addresses) {
-  base::Optional<FoundBinary> binary =
-      finder_->FindBinary(mapping_name, build_id);
+  base::Optional<std::string> binary =
+      finder_.FindBinary(mapping_name, build_id);
   if (!binary)
     return {};
-  uint64_t load_bias_correction = 0;
-  if (binary->load_bias > load_bias) {
-    // On Android 10, there was a bug in libunwindstack that would incorrectly
-    // calculate the load_bias, and thus the relative PC. This would end up in
-    // frames that made no sense. We can fix this up after the fact if we
-    // detect this situation.
-    load_bias_correction = binary->load_bias - load_bias;
-    PERFETTO_LOG("Correcting load bias by %" PRIu64 " for %s",
-                 load_bias_correction, mapping_name.c_str());
-  }
   std::vector<std::vector<SymbolizedFrame>> result;
   result.reserve(addresses.size());
   for (uint64_t address : addresses)
-    result.emplace_back(llvm_symbolizer_.Symbolize(
-        binary->file_name, address + load_bias_correction));
+    result.emplace_back(llvm_symbolizer_.Symbolize(*binary, address));
   return result;
 }
 
-LocalSymbolizer::LocalSymbolizer(const std::string& symbolizer_path,
-                                 std::unique_ptr<BinaryFinder> finder)
-    : llvm_symbolizer_(symbolizer_path), finder_(std::move(finder)) {}
-
-LocalSymbolizer::LocalSymbolizer(std::unique_ptr<BinaryFinder> finder)
-    : LocalSymbolizer(kDefaultSymbolizer, std::move(finder)) {}
-
 LocalSymbolizer::~LocalSymbolizer() = default;
 
 }  // namespace profiling
diff --git a/src/profiling/symbolizer/local_symbolizer.h b/src/profiling/symbolizer/local_symbolizer.h
index 01d1fe4..eb3a717 100644
--- a/src/profiling/symbolizer/local_symbolizer.h
+++ b/src/profiling/symbolizer/local_symbolizer.h
@@ -18,106 +18,81 @@
 #define SRC_PROFILING_SYMBOLIZER_LOCAL_SYMBOLIZER_H_
 
 #include <map>
-#include <memory>
 #include <string>
 #include <vector>
 
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "src/profiling/symbolizer/subprocess.h"
+#include "perfetto/ext/base/pipe.h"
 #include "src/profiling/symbolizer/symbolizer.h"
 
 namespace perfetto {
 namespace profiling {
 
-bool ParseLlvmSymbolizerLine(const std::string& line,
-                             std::string* file_name,
-                             uint32_t* line_no);
-std::vector<std::string> GetLines(
-    std::function<int64_t(char*, size_t)> fn_read);
-
-struct FoundBinary {
-  std::string file_name;
-  uint64_t load_bias;
-};
-
-class BinaryFinder {
+class LocalBinaryFinder {
  public:
-  virtual ~BinaryFinder();
-  virtual base::Optional<FoundBinary> FindBinary(
-      const std::string& abspath,
-      const std::string& build_id) = 0;
-};
+  LocalBinaryFinder(std::vector<std::string> roots)
+      : roots_(std::move(roots)) {}
 
-class LocalBinaryIndexer : public BinaryFinder {
- public:
-  explicit LocalBinaryIndexer(std::vector<std::string> roots);
-
-  base::Optional<FoundBinary> FindBinary(const std::string& abspath,
-                                         const std::string& build_id) override;
-  ~LocalBinaryIndexer() override;
+  base::Optional<std::string> FindBinary(const std::string& abspath,
+                                         const std::string& build_id);
 
  private:
-  std::map<std::string, FoundBinary> buildid_to_file_;
-};
+  bool IsCorrectFile(const std::string& symbol_file,
+                     const std::string& build_id);
 
-class LocalBinaryFinder : public BinaryFinder {
- public:
-  explicit LocalBinaryFinder(std::vector<std::string> roots);
-
-  base::Optional<FoundBinary> FindBinary(const std::string& abspath,
-                                         const std::string& build_id) override;
-
-  ~LocalBinaryFinder() override;
-
- private:
-  base::Optional<FoundBinary> IsCorrectFile(const std::string& symbol_file,
-                                            const std::string& build_id);
-
-  base::Optional<FoundBinary> FindBinaryInRoot(const std::string& root_str,
+  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<FoundBinary>> cache_;
+  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:
-  explicit LLVMSymbolizerProcess(const std::string& symbolizer_path);
+  LLVMSymbolizerProcess();
 
   std::vector<SymbolizedFrame> Symbolize(const std::string& binary,
                                          uint64_t address);
 
  private:
   Subprocess subprocess_;
+  FILE* read_file_;
 };
 
 class LocalSymbolizer : public Symbolizer {
  public:
-  LocalSymbolizer(const std::string& symbolizer_path,
-                  std::unique_ptr<BinaryFinder> finder);
-
-  explicit LocalSymbolizer(std::unique_ptr<BinaryFinder> finder);
+  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,
-      uint64_t load_bias,
       const std::vector<uint64_t>& address) override;
 
   ~LocalSymbolizer() override;
 
  private:
   LLVMSymbolizerProcess llvm_symbolizer_;
-  std::unique_ptr<BinaryFinder> finder_;
+  LocalBinaryFinder finder_;
 };
 
-std::unique_ptr<Symbolizer> LocalSymbolizerOrDie(
-    std::vector<std::string> binary_path,
-    const char* mode);
-
 }  // namespace profiling
 }  // namespace perfetto
 
diff --git a/src/profiling/symbolizer/local_symbolizer_unittest.cc b/src/profiling/symbolizer/local_symbolizer_unittest.cc
deleted file mode 100644
index b96d318..0000000
--- a/src/profiling/symbolizer/local_symbolizer_unittest.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/base/build_config.h"
-#include "test/gtest_and_gmock.h"
-
-// This translation unit is built only on Linux and MacOS. See //gn/BUILD.gn.
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-
-#include "src/base/test/utils.h"
-#include "src/profiling/symbolizer/local_symbolizer.h"
-#include "src/profiling/symbolizer/subprocess.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-void RunAndValidateParseLines(std::string raw_contents) {
-  std::istringstream stream(raw_contents);
-  auto read_callback = [&stream](char* buffer, size_t size) {
-    stream.get(buffer, static_cast<int>(size), '\0');
-    return strlen(buffer);
-  };
-  std::vector<std::string> lines = GetLines(read_callback);
-  std::istringstream validation(raw_contents);
-  for (const std::string& actual : lines) {
-    std::string expected;
-    getline(validation, expected);
-    EXPECT_EQ(actual, expected);
-  }
-}
-
-TEST(LocalSymbolizerTest, ParseLineWindows) {
-  std::string file_name;
-  uint32_t lineno;
-  ASSERT_TRUE(
-      ParseLlvmSymbolizerLine("C:\\Foo\\Bar.cc:123:1", &file_name, &lineno));
-  EXPECT_EQ(file_name, "C:\\Foo\\Bar.cc");
-  EXPECT_EQ(lineno, 123u);
-}
-
-TEST(LocalSymbolizerTest, ParseLinesExpectedOutput) {
-  std::string raw_contents =
-      "FSlateRHIRenderingPolicy::DrawElements(FRHICommandListImmediate&, "
-      "FSlateBackBuffer&, TRefCountPtr<FRHITexture2D>&, "
-      "TRefCountPtr<FRHITexture2D>&, TRefCountPtr<FRHITexture2D>&, int, "
-      "TArray<FSlateRenderBatch, TSizedDefaultAllocator<32> > const&, "
-      "FSlateRenderingParams const&)\n"
-      "F:/P4/EngineReleaseA/Engine/Source/Runtime/SlateRHIRenderer/"
-      "Private\\SlateRHIRenderingPolicy.cpp:1187:19\n";
-  RunAndValidateParseLines(raw_contents);
-}
-
-TEST(LocalSymbolizerTest, ParseLinesErrorOutput) {
-  std::string raw_contents =
-      "LLVMSymbolizer: error reading file: No such file or directory\n"
-      "??\n"
-      "??:0:0\n";
-  RunAndValidateParseLines(raw_contents);
-}
-
-TEST(LocalSymbolizerTest, ParseLinesSingleCharRead) {
-  std::string raw_contents =
-      "FSlateRHIRenderingPolicy::DrawElements(FRHICommandListImmediate&, "
-      "FSlateBackBuffer&, TRefCountPtr<FRHITexture2D>&, "
-      "TRefCountPtr<FRHITexture2D>&, TRefCountPtr<FRHITexture2D>&, int, "
-      "TArray<FSlateRenderBatch, TSizedDefaultAllocator<32> > const&, "
-      "FSlateRenderingParams const&)\n"
-      "F:/P4/EngineReleaseA/Engine/Source/Runtime/SlateRHIRenderer/"
-      "Private\\SlateRHIRenderingPolicy.cpp:1187:19\n";
-  std::istringstream stream(raw_contents);
-  auto read_callback = [&stream](char* buffer, size_t) {
-    stream.get(buffer, 1, '\0');
-    return strlen(buffer);
-  };
-  std::vector<std::string> lines = GetLines(read_callback);
-  std::istringstream validation(raw_contents);
-  for (const std::string& actual : lines) {
-    std::string expected;
-    getline(validation, expected);
-    EXPECT_EQ(actual, expected);
-  }
-}
-
-}  // namespace
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif
diff --git a/src/profiling/symbolizer/scoped_read_mmap.h b/src/profiling/symbolizer/scoped_read_mmap.h
deleted file mode 100644
index 69a028a..0000000
--- a/src/profiling/symbolizer/scoped_read_mmap.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_
-#define SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_
-
-#include "perfetto/ext/base/scoped_file.h"
-
-namespace perfetto {
-namespace profiling {
-
-class ScopedReadMmap {
- public:
-  ScopedReadMmap(const char* fname, size_t length);
-  virtual ~ScopedReadMmap();
-
-  void* operator*() { return ptr_; }
-
-  bool IsValid();
-
- private:
-  size_t length_;
-  void* ptr_;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  void* file_ = nullptr;
-  void* map_ = nullptr;
-#else
-  base::ScopedFile fd_;
-#endif
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_
diff --git a/src/profiling/symbolizer/scoped_read_mmap_posix.cc b/src/profiling/symbolizer/scoped_read_mmap_posix.cc
deleted file mode 100644
index f6c3276..0000000
--- a/src/profiling/symbolizer/scoped_read_mmap_posix.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/scoped_read_mmap.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-
-#include <sys/mman.h>
-
-namespace perfetto {
-namespace profiling {
-
-ScopedReadMmap::ScopedReadMmap(const char* fname, size_t length)
-    : length_(length), fd_(base::OpenFile(fname, O_RDONLY)) {
-  if (!fd_) {
-    PERFETTO_PLOG("Failed to open %s", fname);
-    return;
-  }
-  ptr_ = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, *fd_, 0);
-}
-
-ScopedReadMmap::~ScopedReadMmap() {
-  if (ptr_ != MAP_FAILED)
-    munmap(ptr_, length_);
-}
-
-bool ScopedReadMmap::IsValid() {
-  return ptr_ != MAP_FAILED;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/scoped_read_mmap_windows.cc b/src/profiling/symbolizer/scoped_read_mmap_windows.cc
deleted file mode 100644
index d56d913..0000000
--- a/src/profiling/symbolizer/scoped_read_mmap_windows.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/scoped_read_mmap.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <Windows.h>
-
-namespace perfetto {
-namespace profiling {
-
-ScopedReadMmap::ScopedReadMmap(const char* fName, size_t length)
-    : length_(length), ptr_(nullptr) {
-  file_ = CreateFileA(fName, GENERIC_READ, FILE_SHARE_READ, nullptr,
-                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
-  if (file_ == INVALID_HANDLE_VALUE) {
-    PERFETTO_DLOG("Failed to open file: %s", fName);
-    return;
-  }
-  map_ = CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, nullptr);
-  if (map_ == INVALID_HANDLE_VALUE) {
-    PERFETTO_DLOG("Failed to mmap file");
-    return;
-  }
-  ptr_ = MapViewOfFile(map_, FILE_MAP_READ, 0, 0, length_);
-  if (ptr_ == nullptr) {
-    PERFETTO_DLOG("Failed to map view of file");
-  }
-}
-
-ScopedReadMmap::~ScopedReadMmap() {
-  if (ptr_ != nullptr) {
-    UnmapViewOfFile(ptr_);
-  }
-  if (map_ != nullptr && map_ != INVALID_HANDLE_VALUE) {
-    CloseHandle(map_);
-  }
-  if (file_ != nullptr && file_ != INVALID_HANDLE_VALUE) {
-    CloseHandle(file_);
-  }
-}
-
-bool ScopedReadMmap::IsValid() {
-  return ptr_ != nullptr;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/subprocess.h b/src/profiling/symbolizer/subprocess.h
deleted file mode 100644
index 09f0bac..0000000
--- a/src/profiling/symbolizer/subprocess.h
+++ /dev/null
@@ -1,60 +0,0 @@
-
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_PROFILING_SYMBOLIZER_SUBPROCESS_H_
-#define SRC_PROFILING_SYMBOLIZER_SUBPROCESS_H_
-
-#include <string>
-#include <vector>
-
-#include "perfetto/base/build_config.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <sys/types.h>
-#include <unistd.h>
-#include "perfetto/ext/base/pipe.h"
-#endif
-
-namespace perfetto {
-namespace profiling {
-
-class Subprocess {
- public:
-  Subprocess(const std::string& file, std::vector<std::string> args);
-  ~Subprocess();
-
-  int64_t Write(const char* buffer, size_t size);
-  int64_t Read(char* buffer, size_t size);
-
- private:
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  void* child_pipe_in_read_ = nullptr;
-  void* child_pipe_in_write_ = nullptr;
-  void* child_pipe_out_read_ = nullptr;
-  void* child_pipe_out_write_ = nullptr;
-#else
-  base::Pipe input_pipe_;
-  base::Pipe output_pipe_;
-
-  pid_t pid_ = -1;
-#endif
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_SYMBOLIZER_SUBPROCESS_H_
diff --git a/src/profiling/symbolizer/subprocess_posix.cc b/src/profiling/symbolizer/subprocess_posix.cc
deleted file mode 100644
index 691aa1b..0000000
--- a/src/profiling/symbolizer/subprocess_posix.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/subprocess.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace profiling {
-
-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;
-  c_str_args.reserve(args.size());
-  for (std::string& arg : args)
-    c_str_args.push_back(&(arg[0]));
-  c_str_args.push_back(nullptr);
-
-  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();
-    if (execvp(file.c_str(), c_str_args.data()) == -1)
-      PERFETTO_FATAL("Failed to exec %s", file.c_str());
-  }
-  PERFETTO_CHECK(pid_ != -1);
-  input_pipe_.rd.reset();
-  output_pipe_.wr.reset();
-}
-
-Subprocess::~Subprocess() {
-  if (pid_ != -1) {
-    kill(pid_, SIGKILL);
-    int wstatus;
-    PERFETTO_EINTR(waitpid(pid_, &wstatus, 0));
-  }
-}
-
-int64_t Subprocess::Write(const char* buffer, size_t size) {
-  if (!input_pipe_.wr) {
-    return -1;
-  }
-  return PERFETTO_EINTR(write(input_pipe_.wr.get(), buffer, size));
-}
-
-int64_t Subprocess::Read(char* buffer, size_t size) {
-  if (!output_pipe_.rd) {
-    return -1;
-  }
-  return PERFETTO_EINTR(read(output_pipe_.rd.get(), buffer, size));
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/subprocess_windows.cc b/src/profiling/symbolizer/subprocess_windows.cc
deleted file mode 100644
index 7f28ea4..0000000
--- a/src/profiling/symbolizer/subprocess_windows.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/profiling/symbolizer/subprocess.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <sstream>
-#include <string>
-
-#include <Windows.h>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace profiling {
-
-Subprocess::Subprocess(const std::string& file, std::vector<std::string> args) {
-  std::stringstream cmd;
-  cmd << file;
-  for (auto arg : args) {
-    cmd << " " << arg;
-  }
-  SECURITY_ATTRIBUTES attr;
-  attr.nLength = sizeof(SECURITY_ATTRIBUTES);
-  attr.bInheritHandle = true;
-  attr.lpSecurityDescriptor = nullptr;
-  // Create a pipe for the child process's STDOUT.
-  if (!CreatePipe(&child_pipe_out_read_, &child_pipe_out_write_, &attr, 0) ||
-      !SetHandleInformation(child_pipe_out_read_, HANDLE_FLAG_INHERIT, 0)) {
-    PERFETTO_ELOG("Failed to create stdout pipe");
-    return;
-  }
-  if (!CreatePipe(&child_pipe_in_read_, &child_pipe_in_write_, &attr, 0) ||
-      !SetHandleInformation(child_pipe_in_write_, HANDLE_FLAG_INHERIT, 0)) {
-    PERFETTO_ELOG("Failed to create stdin pipe");
-    return;
-  }
-
-  PROCESS_INFORMATION proc_info;
-  STARTUPINFOA start_info;
-  bool success = false;
-  // Set up members of the PROCESS_INFORMATION structure.
-  ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION));
-
-  // Set up members of the STARTUPINFO structure.
-  // This structure specifies the STDIN and STDOUT handles for redirection.
-  ZeroMemory(&start_info, sizeof(STARTUPINFOA));
-  start_info.cb = sizeof(STARTUPINFOA);
-  start_info.hStdError = child_pipe_out_write_;
-  start_info.hStdOutput = child_pipe_out_write_;
-  start_info.hStdInput = child_pipe_in_read_;
-  start_info.dwFlags |= STARTF_USESTDHANDLES;
-
-  // Create the child process.
-  success = CreateProcessA(nullptr,
-                           &(cmd.str()[0]),  // command line
-                           nullptr,          // process security attributes
-                           nullptr,      // primary thread security attributes
-                           TRUE,         // handles are inherited
-                           0,            // creation flags
-                           nullptr,      // use parent's environment
-                           nullptr,      // use parent's current directory
-                           &start_info,  // STARTUPINFO pointer
-                           &proc_info);  // receives PROCESS_INFORMATION
-
-  // If an error occurs, exit the application.
-  if (success) {
-    CloseHandle(proc_info.hProcess);
-    CloseHandle(proc_info.hThread);
-
-    // Close handles to the stdin and stdout pipes no longer needed by the child
-    // process. If they are not explicitly closed, there is no way to recognize
-    // that the child process has ended.
-
-    CloseHandle(child_pipe_out_write_);
-    CloseHandle(child_pipe_in_read_);
-  } else {
-    PERFETTO_ELOG("Failed to launch: %s", cmd.str().c_str());
-    child_pipe_in_read_ = nullptr;
-    child_pipe_in_write_ = nullptr;
-    child_pipe_out_write_ = nullptr;
-    child_pipe_out_read_ = nullptr;
-  }
-}
-
-Subprocess::~Subprocess() {
-  CloseHandle(child_pipe_out_read_);
-  CloseHandle(child_pipe_in_write_);
-}
-
-int64_t Subprocess::Write(const char* buffer, size_t size) {
-  if (child_pipe_in_write_ == nullptr) {
-    return -1;
-  }
-  DWORD bytes_written;
-  if (WriteFile(child_pipe_in_write_, buffer, static_cast<DWORD>(size),
-                &bytes_written, nullptr)) {
-    return static_cast<int64_t>(bytes_written);
-  }
-  return -1;
-}
-
-int64_t Subprocess::Read(char* buffer, size_t size) {
-  if (child_pipe_out_read_ == nullptr) {
-    return -1;
-  }
-  DWORD bytes_read;
-  if (ReadFile(child_pipe_out_read_, buffer, static_cast<DWORD>(size),
-               &bytes_read, nullptr)) {
-    return static_cast<int64_t>(bytes_read);
-  }
-  return -1;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/symbolize_database.cc b/src/profiling/symbolizer/symbolize_database.cc
index a002aea..462e836 100644
--- a/src/profiling/symbolizer/symbolize_database.cc
+++ b/src/profiling/symbolizer/symbolize_database.cc
@@ -21,7 +21,8 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_splitter.h"
+
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/trace_processor/trace_processor.h"
 
@@ -33,10 +34,10 @@
 namespace profiling {
 
 namespace {
-using trace_processor::Iterator;
+using Iterator = trace_processor::TraceProcessor::Iterator;
 
 constexpr const char* kQueryUnsymbolized =
-    "select spm.name, spm.build_id, spf.rel_pc, spm.load_bias "
+    "select spm.name, spm.build_id, spf.rel_pc "
     "from stack_profile_frame spf "
     "join stack_profile_mapping spm "
     "on spf.mapping = spm.id "
@@ -44,16 +45,6 @@
 
 using NameAndBuildIdPair = std::pair<std::string, std::string>;
 
-struct UnsymbolizedMapping {
-  std::string name;
-  std::string build_id;
-  uint64_t load_bias;
-  bool operator<(const UnsymbolizedMapping& o) const {
-    return std::tie(name, build_id, load_bias) <
-           std::tie(o.name, o.build_id, o.load_bias);
-  }
-};
-
 std::string FromHex(const char* str, size_t size) {
   if (size % 2) {
     PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
@@ -80,18 +71,15 @@
   return FromHex(str.c_str(), str.size());
 }
 
-std::map<UnsymbolizedMapping, std::vector<uint64_t>> GetUnsymbolizedFrames(
+std::map<NameAndBuildIdPair, std::vector<uint64_t>> GetUnsymbolizedFrames(
     trace_processor::TraceProcessor* tp) {
-  std::map<UnsymbolizedMapping, std::vector<uint64_t>> res;
+  std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> res;
   Iterator it = tp->ExecuteQuery(kQueryUnsymbolized);
   while (it.Next()) {
-    int64_t load_bias = it.Get(3).AsLong();
-    PERFETTO_CHECK(load_bias >= 0);
-    UnsymbolizedMapping unsymbolized_mapping{it.Get(0).AsString(),
-                                             FromHex(it.Get(1).AsString()),
-                                             static_cast<uint64_t>(load_bias)};
+    auto name_and_buildid =
+        std::make_pair(it.Get(0).AsString(), FromHex(it.Get(1).AsString()));
     int64_t rel_pc = it.Get(2).AsLong();
-    res[unsymbolized_mapping].emplace_back(rel_pc);
+    res[name_and_buildid].emplace_back(rel_pc);
   }
   if (!it.Status().ok()) {
     PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
@@ -108,19 +96,18 @@
   PERFETTO_CHECK(symbolizer);
   auto unsymbolized = GetUnsymbolizedFrames(tp);
   for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
-    const auto& unsymbolized_mapping = it->first;
+    const auto& name_and_buildid = it->first;
     const std::vector<uint64_t>& rel_pcs = it->second;
-    auto res = symbolizer->Symbolize(unsymbolized_mapping.name,
-                                     unsymbolized_mapping.build_id,
-                                     unsymbolized_mapping.load_bias, rel_pcs);
+    auto res = symbolizer->Symbolize(name_and_buildid.first,
+                                     name_and_buildid.second, rel_pcs);
     if (res.empty())
       continue;
 
     protozero::HeapBuffered<perfetto::protos::pbzero::Trace> trace;
     auto* packet = trace->add_packet();
     auto* module_symbols = packet->set_module_symbols();
-    module_symbols->set_path(unsymbolized_mapping.name);
-    module_symbols->set_build_id(unsymbolized_mapping.build_id);
+    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();
@@ -137,10 +124,13 @@
 }
 
 std::vector<std::string> GetPerfettoBinaryPath() {
+  std::vector<std::string> roots;
   const char* root = getenv("PERFETTO_BINARY_PATH");
-  if (root != nullptr)
-    return base::SplitString(root, ":");
-  return {};
+  if (root != nullptr) {
+    for (base::StringSplitter sp(std::string(root), ':'); sp.Next();)
+      roots.emplace_back(sp.cur_token(), sp.cur_token_size());
+  }
+  return roots;
 }
 
 }  // namespace profiling
diff --git a/src/profiling/symbolizer/symbolizer.h b/src/profiling/symbolizer/symbolizer.h
index 3e96142..ff4ee50 100644
--- a/src/profiling/symbolizer/symbolizer.h
+++ b/src/profiling/symbolizer/symbolizer.h
@@ -40,7 +40,6 @@
   virtual std::vector<std::vector<SymbolizedFrame>> Symbolize(
       const std::string& mapping_name,
       const std::string& build_id,
-      uint64_t load_bias,
       const std::vector<uint64_t>& address) = 0;
   virtual ~Symbolizer();
 };
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index 69d911a..18f8e7e 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -14,12 +14,10 @@
 
 import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_cc_proto_descriptor.gni")
-import("../../gn/perfetto_component.gni")
 import("../../gn/proto_library.gni")
 import("../../gn/test.gni")
 
-perfetto_component("protozero") {
+source_set("protozero") {
   public_configs = [ "../../gn:default_config" ]
   public_deps = [
     "../../include/perfetto/base",
@@ -32,7 +30,6 @@
   sources = [
     "field.cc",
     "message.cc",
-    "message_arena.cc",
     "message_handle.cc",
     "packed_repeated_fields.cc",
     "proto_decoder.cc",
@@ -44,6 +41,11 @@
   ]
 }
 
+static_library("libprotozero") {
+  complete_static_lib = true
+  deps = [ ":protozero" ]
+}
+
 perfetto_unittest_source_set("unittests") {
   testonly = true
   deps = [
@@ -55,7 +57,6 @@
     "../../gn:gtest_and_gmock",
     "../base",
     "../base:test_support",
-    "filtering:unittests",
   ]
   sources = [
     "copyable_ptr_unittest.cc",
@@ -75,7 +76,6 @@
 
 perfetto_proto_library("testing_messages_@TYPE@") {
   sources = [
-    "test/example_proto/extensions.proto",
     "test/example_proto/library.proto",
     "test/example_proto/library_internals/galaxies.proto",
     "test/example_proto/test_messages.proto",
@@ -84,13 +84,6 @@
   proto_path = perfetto_root_path
 }
 
-perfetto_proto_library("test_messages_descriptor") {
-  proto_generators = [ "descriptor" ]
-  generate_descriptor = "test_messages.descriptor"
-  sources = [ "test/example_proto/test_messages.proto" ]
-  deps = [ ":testing_messages_source_set" ]
-}
-
 perfetto_fuzzer_test("protozero_decoder_fuzzer") {
   sources = [ "proto_decoder_fuzzer.cc" ]
   deps = [
diff --git a/src/protozero/field.cc b/src/protozero/field.cc
index 8f94182..be16482 100644
--- a/src/protozero/field.cc
+++ b/src/protozero/field.cc
@@ -16,10 +16,9 @@
 
 #include "perfetto/protozero/field.h"
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 
-#if !PERFETTO_IS_LITTLE_ENDIAN()
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
 // The memcpy() for fixed32/64 below needs to be adjusted if we want to
 // support big endian CPUs. There doesn't seem to be a compelling need today.
 #error Unimplemented for big endian archs.
diff --git a/src/protozero/filtering/BUILD.gn b/src/protozero/filtering/BUILD.gn
deleted file mode 100644
index b438929..0000000
--- a/src/protozero/filtering/BUILD.gn
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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/fuzzer.gni")
-import("../../../gn/perfetto_host_executable.gni")
-import("../../../gn/proto_library.gni")
-import("../../../gn/test.gni")
-
-source_set("message_filter") {
-  sources = [
-    "message_filter.cc",
-    "message_filter.h",
-    "message_tokenizer.h",
-  ]
-  deps = [
-    ":bytecode_parser",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-}
-
-source_set("bytecode_common") {
-  sources = [ "filter_bytecode_common.h" ]
-  deps = [ "../../../gn:default_deps" ]
-}
-
-source_set("bytecode_parser") {
-  sources = [
-    "filter_bytecode_parser.cc",
-    "filter_bytecode_parser.h",
-  ]
-  deps = [
-    ":bytecode_common",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-}
-
-source_set("bytecode_generator") {
-  sources = [
-    "filter_bytecode_generator.cc",
-    "filter_bytecode_generator.h",
-  ]
-  deps = [
-    ":bytecode_common",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-}
-
-source_set("filter_util") {
-  testonly = true
-  sources = [
-    "filter_util.cc",
-    "filter_util.h",
-  ]
-  deps = [
-    ":bytecode_generator",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../../gn:protobuf_full",
-    "../../base",
-  ]
-}
-
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    ":bytecode_common",
-    ":bytecode_generator",
-    ":bytecode_parser",
-    ":filter_util",
-    ":message_filter",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-    "../../../protos/perfetto/trace:lite",
-    "../../base",
-    "../../base:test_support",
-  ]
-  sources = [
-    "filter_bytecode_generator_unittest.cc",
-    "filter_bytecode_parser_unittest.cc",
-    "filter_util_unittest.cc",
-    "message_filter_unittest.cc",
-    "message_tokenizer_unittest.cc",
-  ]
-}
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":message_filter",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
-      "../../base",
-      "../../base:test_support",
-    ]
-    sources = [ "message_filter_benchmark.cc" ]
-  }
-}
-
-perfetto_fuzzer_test("protozero_bytecode_parser_fuzzer") {
-  sources = [ "filter_bytecode_parser_fuzzer.cc" ]
-  deps = [
-    ":bytecode_parser",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-}
-
-perfetto_fuzzer_test("protozero_message_filter_fuzzer") {
-  sources = [ "message_filter_fuzzer.cc" ]
-  deps = [
-    ":message_filter",
-    "..:protozero",
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-}
diff --git a/src/protozero/filtering/filter_bytecode_common.h b/src/protozero/filtering/filter_bytecode_common.h
deleted file mode 100644
index 9c0e6f2..0000000
--- a/src/protozero/filtering/filter_bytecode_common.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_FILTER_BYTECODE_COMMON_H_
-#define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_COMMON_H_
-
-#include <stdint.h>
-
-namespace protozero {
-
-enum FilterOpcode : uint32_t {
-  // The immediate value is 0 in this case.
-  kFilterOpcode_EndOfMessage = 0,
-
-  // The immediate value is the id of the allowed field.
-  kFilterOpcode_SimpleField = 1,
-
-  // The immediate value is the start of the range. The next word (without
-  // any shifting) is the length of the range.
-  kFilterOpcode_SimpleFieldRange = 2,
-
-  // The immediate value is the id of the allowed field. The next word
-  // (without any shifting) is the index of the filter that should be used to
-  // recurse into the nested message.
-  kFilterOpcode_NestedField = 3,
-};
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_COMMON_H_
diff --git a/src/protozero/filtering/filter_bytecode_generator.cc b/src/protozero/filtering/filter_bytecode_generator.cc
deleted file mode 100644
index 9362869..0000000
--- a/src/protozero/filtering/filter_bytecode_generator.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/filtering/filter_bytecode_generator.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/protozero/filtering/filter_bytecode_common.h"
-
-namespace protozero {
-
-FilterBytecodeGenerator::FilterBytecodeGenerator() = default;
-FilterBytecodeGenerator::~FilterBytecodeGenerator() = default;
-
-void FilterBytecodeGenerator::EndMessage() {
-  endmessage_called_ = true;
-  bytecode_.push_back(kFilterOpcode_EndOfMessage);
-  last_field_id_ = 0;
-  ++num_messages_;
-}
-
-// Allows a simple field (varint, fixed32/64, string or bytes).
-void FilterBytecodeGenerator::AddSimpleField(uint32_t field_id) {
-  PERFETTO_CHECK(field_id > last_field_id_);
-  bytecode_.push_back(field_id << 3 | kFilterOpcode_SimpleField);
-  last_field_id_ = field_id;
-  endmessage_called_ = false;
-}
-
-// Allows a range of simple fields. |range_start| is the id of the first field
-// in range, |range_len| the number of fields in the range.
-// AddSimpleFieldRange(N,1) is semantically equivalent to AddSimpleField(N).
-void FilterBytecodeGenerator::AddSimpleFieldRange(uint32_t range_start,
-                                                  uint32_t range_len) {
-  PERFETTO_CHECK(range_start > last_field_id_);
-  PERFETTO_CHECK(range_len > 0);
-  bytecode_.push_back(range_start << 3 | kFilterOpcode_SimpleFieldRange);
-  bytecode_.push_back(range_len);
-  last_field_id_ = range_start + range_len - 1;
-  endmessage_called_ = false;
-}
-
-// Adds a nested field. |message_index| is the index of the message that the
-// parser must recurse into. This implies that at least |message_index| + 1
-// calls to EndMessage() will be made.
-// The Serialize() method will fail if any field points to an out of range
-// index.
-void FilterBytecodeGenerator::AddNestedField(uint32_t field_id,
-                                             uint32_t message_index) {
-  PERFETTO_CHECK(field_id > last_field_id_);
-  bytecode_.push_back(field_id << 3 | kFilterOpcode_NestedField);
-  bytecode_.push_back(message_index);
-  last_field_id_ = field_id;
-  max_msg_index_ = std::max(max_msg_index_, message_index);
-  endmessage_called_ = false;
-}
-
-// Returns the bytes that can be used into TraceConfig.trace_filter.bytecode.
-// The returned bytecode is a binary buffer which consists of a sequence of
-// varints (the opcodes) and a checksum.
-// The returned string can be passed as-is to FilterBytecodeParser.Load().
-std::string FilterBytecodeGenerator::Serialize() {
-  PERFETTO_CHECK(endmessage_called_);
-  PERFETTO_CHECK(max_msg_index_ < num_messages_);
-  protozero::PackedVarInt words;
-  perfetto::base::Hash hasher;
-  for (uint32_t word : bytecode_) {
-    words.Append(word);
-    hasher.Update(word);
-  }
-  words.Append(static_cast<uint32_t>(hasher.digest()));
-  return std::string(reinterpret_cast<const char*>(words.data()), words.size());
-}
-
-}  // namespace protozero
diff --git a/src/protozero/filtering/filter_bytecode_generator.h b/src/protozero/filtering/filter_bytecode_generator.h
deleted file mode 100644
index 809799c..0000000
--- a/src/protozero/filtering/filter_bytecode_generator.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_FILTER_BYTECODE_GENERATOR_H_
-#define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_GENERATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-namespace protozero {
-
-// Creates a filter bytecode that can be passed to the FilterBytecodeParser.
-// This class is typically only used by offline tools (e.g. the proto_filter
-// cmdline tool). See go/trace-filtering for the full filtering design.
-class FilterBytecodeGenerator {
- public:
-  FilterBytecodeGenerator();
-  ~FilterBytecodeGenerator();
-
-  // Call at the end of every message. It implicitly starts a new message, there
-  // is no corresponding BeginMessage().
-  void EndMessage();
-
-  // All the methods below must be called in monotonic field_id order or the
-  // generator will CHECK() and crash.
-
-  // Allows a simple field (varint, fixed32/64, string or bytes).
-  void AddSimpleField(uint32_t field_id);
-
-  // Allows a range of simple fields. |range_start| is the id of the first field
-  // in range, |range_len| the number of fields in the range.
-  // AddSimpleFieldRange(N,1) is semantically equivalent to AddSimpleField(N)
-  // (but it takes 2 words to encode, rather than just one).
-  void AddSimpleFieldRange(uint32_t range_start, uint32_t range_len);
-
-  // Adds a nested field. |message_index| is the index of the message that the
-  // parser must recurse into. This implies that at least |message_index| calls
-  // to Begin/EndMessage will be made.
-  // The Serialize() method will fail if any field points to an index that is
-  // out of range (e.g., if message_index = 5 but only 3 EndMessage() calls were
-  // made).
-  void AddNestedField(uint32_t field_id, uint32_t message_index);
-
-  // Returns the filter bytecode, which is a buffer containing a sequence of
-  // varints and a checksum. The returned string can be passed to
-  // FilterBytecodeParser.Load().
-  std::string Serialize();
-
- private:
-  uint32_t num_messages_ = 0;
-  uint32_t last_field_id_ = 0;
-  uint32_t max_msg_index_ = 0;
-  bool endmessage_called_ = false;
-
-  std::vector<uint32_t> bytecode_;
-};
-
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_GENERATOR_H_
diff --git a/src/protozero/filtering/filter_bytecode_generator_unittest.cc b/src/protozero/filtering/filter_bytecode_generator_unittest.cc
deleted file mode 100644
index 650120b..0000000
--- a/src/protozero/filtering/filter_bytecode_generator_unittest.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/gtest_and_gmock.h"
-
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/protozero/filtering/filter_bytecode_generator.h"
-#include "src/protozero/filtering/filter_bytecode_parser.h"
-
-// This file tests the generator, assuming the parser is good.
-// The parser is tested separately (without the generator) in
-// filter_bytecode_parser_unittest.cc
-
-namespace protozero {
-
-namespace {
-
-TEST(FilterBytecodeGeneratorTest, SimpleFields) {
-  FilterBytecodeGenerator gen;
-  gen.AddSimpleField(1u);
-  gen.AddSimpleField(127u);
-  gen.AddSimpleField(128u);
-  gen.AddSimpleField(1000u);
-  gen.EndMessage();
-
-  FilterBytecodeParser parser;
-  std::string bytecode = gen.Serialize();
-  ASSERT_TRUE(parser.Load(reinterpret_cast<const uint8_t*>(bytecode.data()),
-                          bytecode.size()));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_FALSE(parser.Query(0, 126).allowed);
-  EXPECT_TRUE(parser.Query(0, 127).allowed);
-  EXPECT_TRUE(parser.Query(0, 128).allowed);
-  EXPECT_FALSE(parser.Query(0, 129).allowed);
-  EXPECT_TRUE(parser.Query(0, 1000).allowed);
-  EXPECT_FALSE(parser.Query(0, 1001).allowed);
-}
-
-TEST(FilterBytecodeGeneratorTest, SimpleAndRanges) {
-  FilterBytecodeGenerator gen;
-  gen.AddSimpleField(1u);
-  gen.AddSimpleFieldRange(10, 10);
-  gen.AddSimpleField(30u);
-  gen.AddSimpleFieldRange(120, 20);
-  gen.AddSimpleField(1000u);
-  gen.EndMessage();
-
-  FilterBytecodeParser parser;
-  std::string bytecode = gen.Serialize();
-  ASSERT_TRUE(parser.Load(reinterpret_cast<const uint8_t*>(bytecode.data()),
-                          bytecode.size()));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_FALSE(parser.Query(0, 9).allowed);
-  for (uint32_t i = 10; i <= 19; ++i)
-    EXPECT_TRUE(parser.Query(0, i).allowed);
-  EXPECT_TRUE(parser.Query(0, 30).allowed);
-  for (uint32_t i = 120; i <= 139; ++i)
-    EXPECT_TRUE(parser.Query(0, i).allowed);
-  EXPECT_FALSE(parser.Query(0, 140).allowed);
-  EXPECT_FALSE(parser.Query(0, 999).allowed);
-  EXPECT_TRUE(parser.Query(0, 1000).allowed);
-  EXPECT_FALSE(parser.Query(0, 1001).allowed);
-}
-
-TEST(FilterBytecodeGeneratorTest, Nested) {
-  FilterBytecodeGenerator gen;
-  // Message 0.
-  gen.AddSimpleField(1u);
-  gen.AddSimpleFieldRange(10, 1);
-  gen.AddNestedField(11, 3);
-  gen.AddNestedField(12, 1);
-  gen.EndMessage();
-
-  // Message 1.
-  gen.AddNestedField(11, 1);  // Recursive
-  gen.AddNestedField(12, 2);  // Recursive
-  gen.AddNestedField(13, 3);  // Recursive
-  gen.EndMessage();
-
-  // Message 2.
-  gen.AddSimpleField(21);
-  gen.EndMessage();
-
-  // Message 3.
-  gen.AddNestedField(1, 0);  // Recurse in the root message (sneaky).
-  gen.AddSimpleField(31);
-  gen.EndMessage();
-
-  FilterBytecodeParser parser;
-  std::string bytecode = gen.Serialize();
-  ASSERT_TRUE(parser.Load(reinterpret_cast<const uint8_t*>(bytecode.data()),
-                          bytecode.size()));
-
-  // Check root message.
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_TRUE(parser.Query(0, 1).simple_field());
-  EXPECT_TRUE(parser.Query(0, 10).allowed);
-  EXPECT_TRUE(parser.Query(0, 10).simple_field());
-  EXPECT_TRUE(parser.Query(0, 11).allowed);
-  EXPECT_EQ(parser.Query(0, 11).nested_msg_index, 3u);
-  EXPECT_TRUE(parser.Query(0, 12).allowed);
-  EXPECT_EQ(parser.Query(0, 12).nested_msg_index, 1u);
-  EXPECT_FALSE(parser.Query(0, 13).allowed);
-
-  // Check message 1.
-  EXPECT_FALSE(parser.Query(1, 10).allowed);
-  EXPECT_TRUE(parser.Query(1, 11).allowed);
-  EXPECT_EQ(parser.Query(1, 11).nested_msg_index, 1u);
-  EXPECT_TRUE(parser.Query(1, 12).allowed);
-  EXPECT_EQ(parser.Query(1, 12).nested_msg_index, 2u);
-  EXPECT_TRUE(parser.Query(1, 13).allowed);
-  EXPECT_EQ(parser.Query(1, 13).nested_msg_index, 3u);
-
-  // Check message 2.
-  EXPECT_FALSE(parser.Query(2, 11).allowed);
-  EXPECT_TRUE(parser.Query(2, 21).allowed);
-  EXPECT_TRUE(parser.Query(2, 21).simple_field());
-
-  // Check message 3.
-  EXPECT_TRUE(parser.Query(3, 1).allowed);
-  EXPECT_EQ(parser.Query(3, 1).nested_msg_index, 0u);
-  EXPECT_TRUE(parser.Query(3, 31).allowed);
-  EXPECT_TRUE(parser.Query(3, 31).simple_field());
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/filtering/filter_bytecode_parser.cc b/src/protozero/filtering/filter_bytecode_parser.cc
deleted file mode 100644
index 39c8bb6..0000000
--- a/src/protozero/filtering/filter_bytecode_parser.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/filtering/filter_bytecode_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "src/protozero/filtering/filter_bytecode_common.h"
-
-namespace protozero {
-
-void FilterBytecodeParser::Reset() {
-  bool suppress = suppress_logs_for_fuzzer_;
-  *this = FilterBytecodeParser();
-  suppress_logs_for_fuzzer_ = suppress;
-}
-
-bool FilterBytecodeParser::Load(const void* filter_data, size_t len) {
-  Reset();
-  bool res = LoadInternal(static_cast<const uint8_t*>(filter_data), len);
-  // If load fails, don't leave the parser in a half broken state.
-  if (!res)
-    Reset();
-  return res;
-}
-
-bool FilterBytecodeParser::LoadInternal(const uint8_t* bytecode_data,
-                                        size_t len) {
-  // First unpack the varints into a plain uint32 vector, so it's easy to
-  // iterate through them and look ahead.
-  std::vector<uint32_t> words;
-  bool packed_parse_err = false;
-  words.reserve(len);  // An overestimation, but avoids reallocations.
-  using BytecodeDecoder =
-      PackedRepeatedFieldIterator<proto_utils::ProtoWireType::kVarInt,
-                                  uint32_t>;
-  for (BytecodeDecoder it(bytecode_data, len, &packed_parse_err); it; ++it)
-    words.emplace_back(*it);
-
-  if (packed_parse_err || words.empty())
-    return false;
-
-  perfetto::base::Hash hasher;
-  for (size_t i = 0; i < words.size() - 1; ++i)
-    hasher.Update(words[i]);
-
-  uint32_t expected_csum = static_cast<uint32_t>(hasher.digest());
-  if (expected_csum != words.back()) {
-    if (!suppress_logs_for_fuzzer_) {
-      PERFETTO_ELOG("Filter bytecode checksum failed. Expected: %x, actual: %x",
-                    expected_csum, words.back());
-    }
-    return false;
-  }
-
-  words.pop_back();  // Pop the checksum.
-
-  // Temporay storage for each message. Cleared on every END_OF_MESSAGE.
-  std::vector<uint32_t> direct_indexed_fields;
-  std::vector<uint32_t> ranges;
-  uint32_t max_msg_index = 0;
-
-  auto add_directly_indexed_field = [&](uint32_t field_id, uint32_t msg_id) {
-    PERFETTO_DCHECK(field_id > 0 && field_id < kDirectlyIndexLimit);
-    direct_indexed_fields.resize(std::max(direct_indexed_fields.size(),
-                                          static_cast<size_t>(field_id) + 1));
-    direct_indexed_fields[field_id] = kAllowed | msg_id;
-  };
-
-  auto add_range = [&](uint32_t id_start, uint32_t id_end, uint32_t msg_id) {
-    PERFETTO_DCHECK(id_end > id_start);
-    PERFETTO_DCHECK(id_start >= kDirectlyIndexLimit);
-    ranges.emplace_back(id_start);
-    ranges.emplace_back(id_end);
-    ranges.emplace_back(kAllowed | msg_id);
-  };
-
-  for (size_t i = 0; i < words.size(); ++i) {
-    const uint32_t word = words[i];
-    const bool has_next_word = i < words.size() - 1;
-    const uint32_t opcode = word & 0x7u;
-    const uint32_t field_id = word >> 3;
-
-    if (field_id == 0 && opcode != kFilterOpcode_EndOfMessage) {
-      PERFETTO_DLOG("bytecode error @ word %zu, invalid field id (0)", i);
-      return false;
-    }
-
-    if (opcode == kFilterOpcode_SimpleField ||
-        opcode == kFilterOpcode_NestedField) {
-      // Field words are organized as follow:
-      // MSB: 1 if allowed, 0 if not allowed.
-      // Remaining bits:
-      //   Message index in the case of nested (non-simple) messages.
-      //   0x7f..f in the case of simple messages.
-      uint32_t msg_id;
-      if (opcode == kFilterOpcode_SimpleField) {
-        msg_id = kSimpleField;
-      } else {  // FILTER_OPCODE_NESTED_FIELD
-        // The next word in the bytecode contains the message index.
-        if (!has_next_word) {
-          PERFETTO_DLOG("bytecode error @ word %zu: unterminated nested field",
-                        i);
-          return false;
-        }
-        msg_id = words[++i];
-        max_msg_index = std::max(max_msg_index, msg_id);
-      }
-
-      if (field_id < kDirectlyIndexLimit) {
-        add_directly_indexed_field(field_id, msg_id);
-      } else {
-        // In the case of a large field id (rare) we waste an extra word and
-        // represent it as a range. Doesn't make sense to introduce extra
-        // complexity to deal with rare cases like this.
-        add_range(field_id, field_id + 1, msg_id);
-      }
-    } else if (opcode == kFilterOpcode_SimpleFieldRange) {
-      if (!has_next_word) {
-        PERFETTO_DLOG("bytecode error @ word %zu: unterminated range", i);
-        return false;
-      }
-      const uint32_t range_len = words[++i];
-      const uint32_t range_end = field_id + range_len;  // STL-style, excl.
-      uint32_t id = field_id;
-
-      // Here's the subtle complexity: at the bytecode level, we don't know
-      // anything about the kDirectlyIndexLimit. It is legit to define a range
-      // that spans across the direct-indexing threshold (e.g. 126-132). In that
-      // case we want to add all the elements < the indexing to the O(1) bucket
-      // and add only the remaining range as a non-indexed range.
-      for (; id < range_end && id < kDirectlyIndexLimit; ++id)
-        add_directly_indexed_field(id, kAllowed | kSimpleField);
-      PERFETTO_DCHECK(id >= kDirectlyIndexLimit || id == range_end);
-      if (id < range_end)
-        add_range(id, range_end, kSimpleField);
-    } else if (opcode == kFilterOpcode_EndOfMessage) {
-      // For each message append:
-      // 1. The "header" word telling how many directly indexed fields there
-      //    are.
-      // 2. The words for the directly indexed fields (id < 128).
-      // 3. The rest of the fields, encoded as ranges.
-      // Also update the |message_offset_| index to remember the word offset for
-      // the current message.
-      message_offset_.emplace_back(static_cast<uint32_t>(words_.size()));
-      words_.emplace_back(static_cast<uint32_t>(direct_indexed_fields.size()));
-      words_.insert(words_.end(), direct_indexed_fields.begin(),
-                    direct_indexed_fields.end());
-      words_.insert(words_.end(), ranges.begin(), ranges.end());
-      direct_indexed_fields.clear();
-      ranges.clear();
-    } else {
-      PERFETTO_DLOG("bytecode error @ word %zu: invalid opcode (%x)", i, word);
-      return false;
-    }
-  }  // (for word in bytecode).
-
-  if (max_msg_index > 0 && max_msg_index >= message_offset_.size()) {
-    PERFETTO_DLOG(
-        "bytecode error: a message index (%u) is out of range "
-        "(num_messages=%zu)",
-        max_msg_index, message_offset_.size());
-    return false;
-  }
-
-  // Add a final entry to |message_offset_| so we can tell where the last
-  // message ends without an extra branch in the Query() hotpath.
-  message_offset_.emplace_back(static_cast<uint32_t>(words_.size()));
-
-  return true;
-}
-
-FilterBytecodeParser::QueryResult FilterBytecodeParser::Query(
-    uint32_t msg_index,
-    uint32_t field_id) {
-  FilterBytecodeParser::QueryResult res{false, 0u};
-  if (static_cast<uint64_t>(msg_index) + 1 >=
-      static_cast<uint64_t>(message_offset_.size())) {
-    return res;
-  }
-  const uint32_t start_offset = message_offset_[msg_index];
-  // These are DCHECKs and not just CHECKS because the |words_| is populated
-  // by the LoadInternal call above. These cannot be violated with a malformed
-  // bytecode.
-  PERFETTO_DCHECK(start_offset < words_.size());
-  const uint32_t* word = &words_[start_offset];
-  const uint32_t end_off = message_offset_[msg_index + 1];
-  const uint32_t* const end = words_.data() + end_off;
-  PERFETTO_DCHECK(end > word && end <= words_.data() + words_.size());
-  const uint32_t num_directly_indexed = *(word++);
-  PERFETTO_DCHECK(num_directly_indexed <= kDirectlyIndexLimit);
-  PERFETTO_DCHECK(word + num_directly_indexed <= end);
-  uint32_t field_state = 0;
-  if (PERFETTO_LIKELY(field_id < num_directly_indexed)) {
-    PERFETTO_DCHECK(&word[field_id] < end);
-    field_state = word[field_id];
-  } else {
-    for (word = word + num_directly_indexed; word + 2 < end;) {
-      const uint32_t range_start = *(word++);
-      const uint32_t range_end = *(word++);
-      const uint32_t range_state = *(word++);
-      if (field_id >= range_start && field_id < range_end) {
-        field_state = range_state;
-        break;
-      }
-    }  // for (word in ranges)
-  }    // if (field_id >= num_directly_indexed)
-
-  res.allowed = (field_state & kAllowed) != 0;
-  res.nested_msg_index = field_state & ~kAllowed;
-  PERFETTO_DCHECK(res.simple_field() ||
-                  res.nested_msg_index < message_offset_.size() - 1);
-  return res;
-}
-
-}  // namespace protozero
diff --git a/src/protozero/filtering/filter_bytecode_parser.h b/src/protozero/filtering/filter_bytecode_parser.h
deleted file mode 100644
index b2378ca..0000000
--- a/src/protozero/filtering/filter_bytecode_parser.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_FILTER_BYTECODE_PARSER_H_
-#define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_PARSER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-namespace protozero {
-
-// Loads the proto-encoded bytecode in memory and allows fast lookups for tuples
-// (msg_index, field_id) to tell if a given field should be allowed or not and,
-// in the case of nested fields, what is the next message index to recurse into.
-// This class does two things:
-// 1. Expands the array of varint from the proto into a vector<uint32_t>. This
-//    is to avoid performing varint decoding on every lookup, at the cost of
-//    some extra memory (2KB-4KB). Note that the expanded vector is not just a
-//    1:1 copy of the proto one (more below). This is to avoid O(Fields) linear
-//    lookup complexity.
-// 2. Creates an index of offsets to remember the start word for each message.
-//    This is so we can jump to O(1) to the N-th message when recursing into a
-//    nested fields, without having to scan and find the (N-1)-th END_OF_MESSAGE
-//    marker.
-// Overall lookups are O(1) for field ids < 128 (kDirectlyIndexLimit) and O(N),
-// with N being the number of allowed field ranges for other fields.
-// See comments around |word_| below for the structure of the word vector.
-class FilterBytecodeParser {
- public:
-  // Result of a Query() operation
-  struct QueryResult {
-    bool allowed;  // Whether the field is allowed at all or no.
-
-    // If |allowed|==true && simple_field()==false, this tells the message index
-    // of the nested field that should be used when recursing in the parser.
-    uint32_t nested_msg_index;
-
-    // If |allowed|==true, specifies if the field is of a simple type (varint,
-    // fixed32/64, string or byte) or a nested field that needs recursion.
-    // In the latter case the caller is expected to use |nested_msg_index| for
-    // the next Query() calls.
-    bool simple_field() const { return nested_msg_index == kSimpleField; }
-  };
-
-  // Loads a filter. The filter data consists of a sequence of varints which
-  // contains the filter opcodes and a final checksum.
-  bool Load(const void* filter_data, size_t len);
-
-  // Checks wheter a given field is allowed or not.
-  // msg_index = 0 is the index of the root message, where all queries should
-  // start from (typically perfetto.protos.Trace).
-  QueryResult Query(uint32_t msg_index, uint32_t field_id);
-
-  void Reset();
-  void set_suppress_logs_for_fuzzer(bool x) { suppress_logs_for_fuzzer_ = x; }
-
- private:
-  static constexpr uint32_t kDirectlyIndexLimit = 128;
-  static constexpr uint32_t kAllowed = 1u << 31u;
-  static constexpr uint32_t kSimpleField = 0x7fffffff;
-
-  bool LoadInternal(const uint8_t* filter_data, size_t len);
-
-  // The state of all fields for all messages is stored in one contiguous array.
-  // This is to avoid memory fragmentation and allocator overhead.
-  // We expect a high number of messages (hundreds), but each message is small.
-  // For each message we store two sets of uint32:
-  // 1. A set of "directly indexed" fields, for field ids < 128.
-  // 2. The remainder is a set of ranges.
-  // So each message descriptor consists of a sequence of words as follows:
-  //
-  // [0] -> how many directly indexed fields are stored next (up to 128)
-  //
-  // [1..N] -> One word per field id (See "field state" below).
-  //
-  // [N + 1] -> Start of field id range 1
-  // [N + 2] -> End of field id range 1 (exclusive, STL-style).
-  // [N + 3] -> Field state for fields in range 1 (below)
-  //
-  // [N + 4] -> Start of field id range 2
-  // [N + 5] -> End of field id range 2 (exclusive, STL-style).
-  // [N + 6] -> Field state for fields in range 2 (below)
-
-  // The "field state" word is as follows:
-  // Bit 31: 0 if the field is disallowed, 1 if allowed.
-  //         Only directly indexed fields can be 0 (it doesn't make sense to add
-  //         a range and then say "btw it's NOT allowed".. don't add it then.
-  //         0 is only used for filling gaps in the directly indexed bucket.
-  // Bits [30..0] (only when MSB == allowed):
-  //  0x7fffffff: The field is "simple" (varint, fixed32/64, string, bytes) and
-  //      can be directly passed through in output. No recursion is needed.
-  //  [0, 7ffffffe]: The field is a nested submessage. The value is the index
-  //     that must be passed as first argument to the next Query() calls.
-  //     Note that the message index is purely a monotonic counter in the
-  //     filter bytecode, has no proto-equivalent match (unlike field ids).
-  std::vector<uint32_t> words_;
-
-  // One entry for each message index stored in the filter plus a sentinel at
-  // the end. Maps each message index to the offset in |words_| where the the
-  // Nth message start.
-  // message_offset_.size() - 2 == the max message id that can be parsed.
-  std::vector<uint32_t> message_offset_;
-
-  bool suppress_logs_for_fuzzer_ = false;
-};
-
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_PARSER_H_
diff --git a/src/protozero/filtering/filter_bytecode_parser_fuzzer.cc b/src/protozero/filtering/filter_bytecode_parser_fuzzer.cc
deleted file mode 100644
index 578f6c9..0000000
--- a/src/protozero/filtering/filter_bytecode_parser_fuzzer.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <string.h>
-
-#include "perfetto/ext/base/hash.h"
-
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "src/protozero/filtering/filter_bytecode_parser.h"
-
-namespace protozero {
-namespace {
-
-// This function gives a little help to the fuzzer. The bytecode is really a
-// sequence of varint-encoded uint32 words, with a FNV1a checksum at the end.
-// It's very unlikely that the fuzzer on its own can work out the checksum, so
-// most fuzzer inputs are doomed to fail the checksum verification.
-// This takes the fuzzer input and builds a more plausible bytecode.
-void LoadBytecodeWithChecksum(FilterBytecodeParser* parser,
-                              const uint8_t* data,
-                              size_t size) {
-  protozero::PackedVarInt words;
-  perfetto::base::Hash hasher;
-  for (size_t i = 0; i < size; i += sizeof(uint32_t)) {
-    uint32_t word = 0;
-    memcpy(&word, data, sizeof(uint32_t));
-    words.Append(word);
-    hasher.Update(word);
-  }
-  words.Append(static_cast<uint32_t>(hasher.digest()));
-  parser->Load(words.data(), words.size());
-}
-
-int FuzzBytecodeParser(const uint8_t* data, size_t size) {
-  FilterBytecodeParser parser;
-  parser.set_suppress_logs_for_fuzzer(true);
-
-  if (size > 4 && data[0] < 192) {
-    // 75% of the times use the LoadBytecodeWithChecksum() which helps the
-    // fuzzer passing the checksum verification.
-    LoadBytecodeWithChecksum(&parser, data + 1, size - 1);
-  } else {
-    // In the remaining 25%, pass completely arbitrary inputs.
-    parser.Load(data, size);
-  }
-
-  // Smoke testing with known problematic values
-  for (uint32_t msg_index = 0; msg_index < 3; ++msg_index) {
-    parser.Query(msg_index, 0);
-    parser.Query(msg_index, 1);
-    parser.Query(msg_index, 127);
-    parser.Query(msg_index, 128);
-    parser.Query(msg_index, 129);
-    parser.Query(msg_index, 65536);
-    parser.Query(msg_index, 65536);
-    parser.Query(msg_index, 1u << 28);
-    parser.Query(msg_index, 1u << 31);
-  }
-
-  // Query using the random data at the end of the random buffer.
-  if (size > 8) {
-    uint32_t msg_index = 0;
-    uint32_t field_id = 0;
-    memcpy(&msg_index, &data[size - 8], 4);
-    memcpy(&field_id, &data[size - 4], 4);
-    parser.Query(msg_index, field_id);
-  }
-
-  return 0;
-}
-
-}  // namespace
-}  // namespace protozero
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  return protozero::FuzzBytecodeParser(data, size);
-}
diff --git a/src/protozero/filtering/filter_bytecode_parser_unittest.cc b/src/protozero/filtering/filter_bytecode_parser_unittest.cc
deleted file mode 100644
index 5b67ded..0000000
--- a/src/protozero/filtering/filter_bytecode_parser_unittest.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/gtest_and_gmock.h"
-
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/protozero/filtering/filter_bytecode_common.h"
-#include "src/protozero/filtering/filter_bytecode_parser.h"
-
-namespace protozero {
-
-namespace {
-
-
-bool LoadBytecode(FilterBytecodeParser* parser,
-                  std::initializer_list<uint32_t> bytecode) {
-  perfetto::base::Hash hasher;
-  protozero::PackedVarInt words;
-  for (uint32_t w : bytecode) {
-    words.Append(w);
-    hasher.Update(w);
-  }
-  words.Append(static_cast<uint32_t>(hasher.digest()));
-  return parser->Load(words.data(), words.size());
-}
-
-TEST(FilterBytecodeParserTest, ParserSimpleFields) {
-  FilterBytecodeParser parser;
-  EXPECT_FALSE(parser.Load(nullptr, 0));
-  EXPECT_FALSE(parser.Query(42, 42).allowed);
-
-  EXPECT_TRUE(LoadBytecode(&parser, {}));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_FALSE(parser.Query(0, 0xffffffff).allowed);
-  EXPECT_FALSE(parser.Query(1, 0).allowed);
-  EXPECT_FALSE(parser.Query(0, 1).allowed);
-  EXPECT_FALSE(parser.Query(1, 1).allowed);
-  EXPECT_FALSE(parser.Query(42, 42).allowed);
-
-  // An invalid field_id (0) in bytecode should cause a parse failure.
-  EXPECT_FALSE(LoadBytecode(
-      &parser, {kFilterOpcode_SimpleField | 0, kFilterOpcode_EndOfMessage}));
-
-  // A valid bytecode that has only one field.
-  EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (2u << 3),
-                                     kFilterOpcode_EndOfMessage}));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_FALSE(parser.Query(0, 1).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).simple_field());
-  EXPECT_TRUE(parser.Query(0, 2).allowed);
-  EXPECT_FALSE(parser.Query(0, 3).allowed);
-  EXPECT_FALSE(parser.Query(1, 1).allowed);
-  EXPECT_FALSE(parser.Query(1, 2).allowed);
-  EXPECT_FALSE(parser.Query(1, 3).allowed);
-
-  // A valid bytecode that has few sparse fields < 128.
-  EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (1u << 3),
-                                     kFilterOpcode_SimpleField | (7u << 3),
-                                     kFilterOpcode_SimpleField | (8u << 3),
-                                     kFilterOpcode_SimpleField | (127u << 3),
-                                     kFilterOpcode_EndOfMessage}));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_FALSE(parser.Query(0, 2).allowed);
-  EXPECT_FALSE(parser.Query(0, 3).allowed);
-  EXPECT_FALSE(parser.Query(0, 6).allowed);
-  EXPECT_TRUE(parser.Query(0, 7).allowed);
-  EXPECT_TRUE(parser.Query(0, 8).allowed);
-  EXPECT_FALSE(parser.Query(0, 9).allowed);
-  EXPECT_FALSE(parser.Query(0, 126).allowed);
-  EXPECT_TRUE(parser.Query(0, 127).allowed);
-  EXPECT_FALSE(parser.Query(0, 128).allowed);
-
-  // A valid bytecode that has only fields > 128.
-  EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (1000u << 3),
-                                     kFilterOpcode_SimpleField | (1001u << 3),
-                                     kFilterOpcode_SimpleField | (2000u << 3),
-                                     kFilterOpcode_EndOfMessage}));
-  for (uint32_t i = 0; i < 1000; ++i)
-    EXPECT_FALSE(parser.Query(0, i).allowed);
-  EXPECT_TRUE(parser.Query(0, 1000).allowed);
-  EXPECT_TRUE(parser.Query(0, 1001).allowed);
-  EXPECT_FALSE(parser.Query(0, 1002).allowed);
-  EXPECT_FALSE(parser.Query(0, 1999).allowed);
-  EXPECT_TRUE(parser.Query(0, 2000).allowed);
-  EXPECT_FALSE(parser.Query(0, 2001).allowed);
-}
-
-TEST(FilterBytecodeParserTest, ParserSimpleRanges) {
-  FilterBytecodeParser parser;
-
-  // Invalid, range length missing.
-  EXPECT_FALSE(
-      LoadBytecode(&parser, {
-                                kFilterOpcode_SimpleFieldRange | (2u << 3),
-                            }));
-
-  // Borderline valid: range length = 0.
-  EXPECT_TRUE(
-      LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (2u << 3), 0u,
-                             kFilterOpcode_SimpleFieldRange | (127u << 3), 0u,
-                             kFilterOpcode_SimpleFieldRange | (128u << 3), 0u,
-                             kFilterOpcode_SimpleFieldRange | (128u << 3), 0u,
-                             kFilterOpcode_EndOfMessage}));
-  for (uint32_t i = 0; i < 130; ++i)
-    EXPECT_FALSE(parser.Query(0, i).allowed) << i;
-
-  // A valid bytecode with two ranges [2,2], [10, 14].
-  EXPECT_TRUE(
-      LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (2u << 3),
-                             1u,  // length of the range,
-                             kFilterOpcode_SimpleFieldRange | (10u << 3),
-                             5u,  // length of the range,
-                             kFilterOpcode_EndOfMessage}));
-  EXPECT_FALSE(parser.Query(0, 0).allowed);
-  EXPECT_FALSE(parser.Query(0, 1).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).simple_field());
-  EXPECT_FALSE(parser.Query(0, 3).allowed);
-  EXPECT_FALSE(parser.Query(0, 9).allowed);
-  for (uint32_t i = 10; i <= 14; ++i)
-    EXPECT_TRUE(parser.Query(0, i).allowed);
-  EXPECT_FALSE(parser.Query(0, 15).allowed);
-}
-
-TEST(FilterBytecodeParserTest, ParserSimpleFieldsAndRanges) {
-  FilterBytecodeParser parser;
-
-  // Borderline valid: range length = 0.
-  EXPECT_TRUE(
-      LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (1u << 3),
-                             2u,  // [1,2]
-
-                             kFilterOpcode_SimpleField | (4u << 3),
-
-                             kFilterOpcode_SimpleFieldRange | (126u << 3),
-                             4u,  // [126, 129]
-
-                             kFilterOpcode_SimpleField | (150u << 3),
-
-                             kFilterOpcode_EndOfMessage}));
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).allowed);
-  EXPECT_FALSE(parser.Query(0, 3).allowed);
-  EXPECT_TRUE(parser.Query(0, 4).allowed);
-  EXPECT_FALSE(parser.Query(0, 5).allowed);
-  EXPECT_FALSE(parser.Query(0, 125).allowed);
-  for (uint32_t i = 126; i <= 129; ++i)
-    EXPECT_TRUE(parser.Query(0, i).allowed) << i;
-  EXPECT_FALSE(parser.Query(0, 130).allowed);
-  EXPECT_TRUE(parser.Query(0, 150).allowed);
-}
-
-TEST(FilterBytecodeParserTest, ParserNestedMessages) {
-  FilterBytecodeParser parser;
-
-  // Invalid because there are 1 messages in total, and message index 1 is
-  // out of range.
-  EXPECT_FALSE(LoadBytecode(&parser, {kFilterOpcode_NestedField | (4u << 3),
-                                      1u,  // message index
-                                      kFilterOpcode_EndOfMessage}));
-
-  // A valid bytecode consisting of 4 message, with recursive / cylical
-  // dependencies between them.
-  EXPECT_TRUE(LoadBytecode(
-      &parser, {
-                   // Message 0 (root).
-                   kFilterOpcode_SimpleFieldRange | (1u << 3),
-                   2u,  // [1,2]
-                   kFilterOpcode_NestedField | (4u << 3),
-                   3u,  // message index
-                   kFilterOpcode_SimpleField | (10u << 3),
-                   kFilterOpcode_NestedField | (127u << 3),
-                   1u,  // message index
-                   kFilterOpcode_NestedField | (128u << 3),
-                   2u,  // message index
-                   kFilterOpcode_EndOfMessage,
-
-                   // Message 1.
-                   kFilterOpcode_NestedField | (2u << 3),
-                   1u,  // message index (recurse onto itself),
-                   kFilterOpcode_SimpleField | (11u << 3),
-                   kFilterOpcode_EndOfMessage,
-
-                   // Message 2.
-                   kFilterOpcode_NestedField | (2u << 3),
-                   3u,  // message index.
-                   kFilterOpcode_EndOfMessage,
-
-                   // Message 3.
-                   kFilterOpcode_NestedField | (2u << 3),
-                   2u,  // message index (create a cycle, 2->3, 3->2).
-                   kFilterOpcode_EndOfMessage,
-               }));
-
-  // Query message 0 fields.
-  EXPECT_TRUE(parser.Query(0, 1).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).allowed);
-  EXPECT_TRUE(parser.Query(0, 2).simple_field());
-  EXPECT_TRUE(parser.Query(0, 4).allowed);
-  EXPECT_FALSE(parser.Query(0, 4).simple_field());
-  EXPECT_EQ(parser.Query(0, 4).nested_msg_index, 3u);
-  EXPECT_TRUE(parser.Query(0, 10).allowed);
-  EXPECT_TRUE(parser.Query(0, 10).simple_field());
-  EXPECT_TRUE(parser.Query(0, 127).allowed);
-  EXPECT_EQ(parser.Query(0, 127).nested_msg_index, 1u);
-  EXPECT_TRUE(parser.Query(0, 128).allowed);
-  EXPECT_EQ(parser.Query(0, 128).nested_msg_index, 2u);
-  EXPECT_FALSE(parser.Query(0, 129).allowed);
-
-  // Query message 1 fields.
-  EXPECT_FALSE(parser.Query(1, 1).allowed);
-  EXPECT_TRUE(parser.Query(1, 2).allowed);
-  EXPECT_EQ(parser.Query(1, 2).nested_msg_index, 1u);
-  EXPECT_FALSE(parser.Query(1, 3).allowed);
-  EXPECT_TRUE(parser.Query(1, 11).allowed);
-  EXPECT_TRUE(parser.Query(1, 11).simple_field());
-
-  // Query message 2 fields.
-  EXPECT_FALSE(parser.Query(2, 0).allowed);
-  EXPECT_FALSE(parser.Query(2, 1).allowed);
-  EXPECT_TRUE(parser.Query(2, 2).allowed);
-  EXPECT_EQ(parser.Query(2, 2).nested_msg_index, 3u);
-  EXPECT_FALSE(parser.Query(2, 4).allowed);
-
-  // Query message 3 fields.
-  EXPECT_FALSE(parser.Query(3, 0).allowed);
-  EXPECT_FALSE(parser.Query(3, 1).allowed);
-  EXPECT_TRUE(parser.Query(3, 2).allowed);
-  EXPECT_EQ(parser.Query(3, 2).nested_msg_index, 2u);
-  EXPECT_FALSE(parser.Query(3, 4).allowed);
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/filtering/filter_util.cc b/src/protozero/filtering/filter_util.cc
deleted file mode 100644
index 94d436e..0000000
--- a/src/protozero/filtering/filter_util.cc
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/filtering/filter_util.h"
-
-#include <algorithm>
-#include <map>
-#include <memory>
-#include <set>
-
-#include <google/protobuf/compiler/importer.h>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/version.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "src/protozero/filtering/filter_bytecode_generator.h"
-
-namespace protozero {
-
-namespace {
-
-class MultiFileErrorCollectorImpl
-    : public google::protobuf::compiler::MultiFileErrorCollector {
- public:
-  ~MultiFileErrorCollectorImpl() override;
-  void AddError(const std::string&, int, int, const std::string&) override;
-  void AddWarning(const std::string&, int, int, const std::string&) 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("Warning %s %d:%d: %s", filename.c_str(), line, column,
-                message.c_str());
-}
-
-}  // namespace
-
-FilterUtil::FilterUtil() = default;
-FilterUtil::~FilterUtil() = default;
-
-bool FilterUtil::LoadMessageDefinition(const std::string& proto_file,
-                                       const std::string& root_message,
-                                       const std::string& proto_dir_path) {
-  // The protobuf compiler doesn't like backslashes and prints an error like:
-  // Error C:\it7mjanpw3\perfetto-a16500 -1:0: Backslashes, consecutive slashes,
-  // ".", or ".." are not allowed in the virtual path.
-  // Given that C:\foo\bar is a legit path on windows, fix it at this level
-  // because the problem is really the protobuf compiler being too picky.
-  static auto normalize_for_win = [](const std::string& path) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    return perfetto::base::ReplaceAll(path, "\\", "/");
-#else
-    return path;
-#endif
-  };
-
-  google::protobuf::compiler::DiskSourceTree dst;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // If the path is absolute, maps "C:/" -> "C:/" (without hardcoding 'C').
-  if (proto_file.size() > 3 && proto_file[1] == ':') {
-    char win_drive[4];
-    sprintf(win_drive, "%c:/", proto_file[0]);
-    dst.MapPath(win_drive, win_drive);
-  }
-#endif
-  dst.MapPath("/", "/");  // We might still need this on Win under cygwin.
-  dst.MapPath("", normalize_for_win(proto_dir_path));
-  MultiFileErrorCollectorImpl mfe;
-  google::protobuf::compiler::Importer importer(&dst, &mfe);
-  const google::protobuf::FileDescriptor* root_file =
-      importer.Import(normalize_for_win(proto_file));
-  const google::protobuf::Descriptor* root_msg = nullptr;
-  if (!root_message.empty()) {
-    root_msg = importer.pool()->FindMessageTypeByName(root_message);
-  } else if (root_file->message_type_count() > 0) {
-    // The user didn't specfy the root type. Pick the first type in the file,
-    // most times it's the right guess.
-    root_msg = root_file->message_type(0);
-    if (root_msg)
-      PERFETTO_LOG(
-          "The guessed root message name is \"%s\". Pass -r com.MyName to "
-          "override",
-          root_msg->full_name().c_str());
-  }
-
-  if (!root_msg) {
-    PERFETTO_ELOG("Could not find the root message \"%s\" in %s",
-                  root_message.c_str(), proto_file.c_str());
-    return false;
-  }
-
-  // |descriptors_by_full_name| is passed by argument rather than being a member
-  // field so that we don't risk leaving it out of sync (and depending on it in
-  // future without realizing) when performing the Dedupe() pass.
-  DescriptorsByNameMap descriptors_by_full_name;
-  ParseProtoDescriptor(root_msg, &descriptors_by_full_name);
-  return true;
-}
-
-// Generates a Message object for the given libprotobuf message descriptor.
-// Recurses as needed into nested fields.
-FilterUtil::Message* FilterUtil::ParseProtoDescriptor(
-    const google::protobuf::Descriptor* proto,
-    DescriptorsByNameMap* descriptors_by_full_name) {
-  auto descr_it = descriptors_by_full_name->find(proto->full_name());
-  if (descr_it != descriptors_by_full_name->end())
-    return descr_it->second;
-
-  descriptors_.emplace_back();
-  Message* msg = &descriptors_.back();
-  msg->full_name = proto->full_name();
-  (*descriptors_by_full_name)[msg->full_name] = msg;
-  for (int i = 0; i < proto->field_count(); ++i) {
-    const auto* proto_field = proto->field(i);
-    const uint32_t field_id = static_cast<uint32_t>(proto_field->number());
-    PERFETTO_CHECK(msg->fields.count(field_id) == 0);
-    auto& field = msg->fields[field_id];
-    field.name = proto_field->name();
-    field.type = proto_field->type_name();
-    if (proto_field->message_type()) {
-      msg->has_nested_fields = true;
-      // Recurse.
-      field.nested_type = ParseProtoDescriptor(proto_field->message_type(),
-                                               descriptors_by_full_name);
-    }
-  }
-  return msg;
-}
-
-void FilterUtil::Dedupe() {
-  std::map<std::string /*identity*/, Message*> index;
-
-  std::map<Message*, Message*> dupe_graph;  // K,V: K shall be duped against V.
-
-  // As a first pass, generate an |identity| string for each leaf message. The
-  // identity is simply the comma-separated stringification of its field ids.
-  // If another message with the same identity exists, add an edge to the graph.
-  const size_t initial_count = descriptors_.size();
-  size_t field_count = 0;
-  for (auto& descr : descriptors_) {
-    if (descr.has_nested_fields)
-      continue;  // Dedupe only leaf messages without nested fields.
-    std::string identity;
-    for (const auto& id_and_field : descr.fields)
-      identity.append(std::to_string(id_and_field.first) + ",");
-    auto it_and_inserted = index.emplace(identity, &descr);
-    if (!it_and_inserted.second) {
-      // insertion failed, a dupe exists already.
-      Message* dupe_against = it_and_inserted.first->second;
-      dupe_graph.emplace(&descr, dupe_against);
-    }
-  }
-
-  // Now apply de-duplications by re-directing the nested_type pointer to the
-  // equivalent descriptors that have the same set of allowed field ids.
-  std::set<Message*> referenced_descriptors;
-  referenced_descriptors.emplace(&descriptors_.front());  // The root.
-  for (auto& descr : descriptors_) {
-    for (auto& id_and_field : descr.fields) {
-      Message* target = id_and_field.second.nested_type;
-      if (!target)
-        continue;  // Only try to dedupe nested types.
-      auto it = dupe_graph.find(target);
-      if (it == dupe_graph.end()) {
-        referenced_descriptors.emplace(target);
-        continue;
-      }
-      ++field_count;
-      // Replace with the dupe.
-      id_and_field.second.nested_type = it->second;
-    }  // for (nested_fields).
-  }    // for (descriptors_).
-
-  // Remove unreferenced descriptors. We should much rather crash in the case of
-  // a logic bug rathern than trying to use them but don't emit them.
-  size_t removed_count = 0;
-  for (auto it = descriptors_.begin(); it != descriptors_.end();) {
-    if (referenced_descriptors.count(&*it)) {
-      ++it;
-    } else {
-      ++removed_count;
-      it = descriptors_.erase(it);
-    }
-  }
-  PERFETTO_LOG(
-      "Deduplication removed %zu duped descriptors out of %zu descriptors from "
-      "%zu fields",
-      removed_count, initial_count, field_count);
-}
-
-// Prints the list of messages and fields in a diff-friendly text format.
-void FilterUtil::PrintAsText() {
-  using perfetto::base::StripPrefix;
-  const std::string& root_name = descriptors_.front().full_name;
-  std::string root_prefix = root_name.substr(0, root_name.rfind('.'));
-  if (!root_prefix.empty())
-    root_prefix.append(".");
-
-  for (const auto& descr : descriptors_) {
-    for (const auto& id_and_field : descr.fields) {
-      const uint32_t field_id = id_and_field.first;
-      const auto& field = id_and_field.second;
-      const Message* nested_type = id_and_field.second.nested_type;
-      auto stripped_name = StripPrefix(descr.full_name, root_prefix);
-      std::string stripped_nested =
-          nested_type ? StripPrefix(nested_type->full_name, root_prefix) : "";
-      printf("%-60s %3u %-8s %-32s %s\n", stripped_name.c_str(), field_id,
-             field.type.c_str(), field.name.c_str(), stripped_nested.c_str());
-    }
-  }
-}
-
-std::string FilterUtil::GenerateFilterBytecode() {
-  protozero::FilterBytecodeGenerator bytecode_gen;
-
-  // Assign indexes to descriptors, simply by counting them in order;
-  std::map<Message*, uint32_t> descr_to_idx;
-  for (auto& descr : descriptors_)
-    descr_to_idx[&descr] = static_cast<uint32_t>(descr_to_idx.size());
-
-  for (auto& descr : descriptors_) {
-    for (auto it = descr.fields.begin(); it != descr.fields.end();) {
-      uint32_t field_id = it->first;
-      const Message::Field& field = it->second;
-      if (field.nested_type) {
-        // Append the index of the target submessage.
-        PERFETTO_CHECK(descr_to_idx.count(field.nested_type));
-        uint32_t nested_msg_index = descr_to_idx[field.nested_type];
-        bytecode_gen.AddNestedField(field_id, nested_msg_index);
-        ++it;
-        continue;
-      }
-      // Simple field. Lookahead to see if we have a range of contiguous simple
-      // fields.
-      for (uint32_t range_len = 1;; ++range_len) {
-        ++it;
-        if (it != descr.fields.end() && it->first == field_id + range_len &&
-            it->second.is_simple()) {
-          continue;
-        }
-        // At this point it points to either the end() of the vector or a
-        // non-contiguous or non-simple field (which will be picked up by the
-        // next iteration).
-        if (range_len == 1) {
-          bytecode_gen.AddSimpleField(field_id);
-        } else {
-          bytecode_gen.AddSimpleFieldRange(field_id, range_len);
-        }
-        break;
-      }  // for (range_len)
-    }    // for (descr.fields)
-    bytecode_gen.EndMessage();
-  }  // for (descriptors)
-  return bytecode_gen.Serialize();
-}
-
-std::string FilterUtil::LookupField(const std::string& varint_encoded_path) {
-  const uint8_t* ptr =
-      reinterpret_cast<const uint8_t*>(varint_encoded_path.data());
-  const uint8_t* const end = ptr + varint_encoded_path.size();
-
-  std::vector<uint32_t> fields;
-  while (ptr < end) {
-    uint64_t varint;
-    const uint8_t* next = proto_utils::ParseVarInt(ptr, end, &varint);
-    PERFETTO_CHECK(next != ptr);
-    fields.emplace_back(static_cast<uint32_t>(varint));
-    ptr = next;
-  }
-  return LookupField(fields.data(), fields.size());
-}
-
-std::string FilterUtil::LookupField(const uint32_t* field_ids,
-                                    size_t num_fields) {
-  const Message* msg = descriptors_.empty() ? nullptr : &descriptors_.front();
-  std::string res;
-  for (size_t i = 0; i < num_fields; ++i) {
-    const uint32_t field_id = field_ids[i];
-    const Message::Field* field = nullptr;
-    if (msg) {
-      auto it = msg->fields.find(field_id);
-      field = it == msg->fields.end() ? nullptr : &it->second;
-    }
-    res.append(".");
-    if (field) {
-      res.append(field->name);
-      msg = field->nested_type;
-    } else {
-      res.append(std::to_string(field_id));
-    }
-  }
-  return res;
-}
-
-}  // namespace protozero
diff --git a/src/protozero/filtering/filter_util.h b/src/protozero/filtering/filter_util.h
deleted file mode 100644
index 3cc7655..0000000
--- a/src/protozero/filtering/filter_util.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_FILTER_UTIL_H_
-#define SRC_PROTOZERO_FILTERING_FILTER_UTIL_H_
-
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <string>
-
-namespace google {
-namespace protobuf {
-class Descriptor;
-}
-}  // namespace google
-
-namespace protozero {
-
-// Parses a .proto message definition, recursing into its sub-messages, and
-// builds up a set of Messages and Field definitions.
-// Depends on libprotobuf-full and should be used only in host tools.
-// See the //tools/proto_filter for an executable that wraps this class with
-// a cmdline interface.
-class FilterUtil {
- public:
-  FilterUtil();
-  ~FilterUtil();
-
-  // Loads a message schema from a .proto file, recursing into nested types.
-  // Args:
-  // proto_file: path to the .proto file.
-  // root_message: fully qualified message name (e.g., perfetto.protos.Trace).
-  //     If empty, the first message in the file will be used.
-  // proto_dir_path: the root for .proto includes. If empty uses CWD.
-  bool LoadMessageDefinition(const std::string& proto_file,
-                             const std::string& root_message,
-                             const std::string& proto_dir_path);
-
-  // Deduplicates leaf messages having the same sets of field ids.
-  // It changes the internal state and affects the behavior of next calls to
-  // GenerateFilterBytecode() and PrintAsText().
-  void Dedupe();
-
-  // Generates the filter bytecode for the root message previously loaded by
-  // LoadMessageDefinition() using FilterBytecodeGenerator.
-  // The returned string is a binary-encoded proto message of type
-  // perfetto.protos.ProtoFilter (see proto_filter.proto).
-  std::string GenerateFilterBytecode();
-
-  // Prints the list of messages and fields onto stdout in a diff-friendly text
-  // format. Example:
-  // PowerRails                 2 message  energy_data     PowerRails.EnergyData
-  // PowerRails.RailDescriptor  1 uint32   index
-  void PrintAsText();
-
-  // Resolves an array of field ids into a dot-concatenated field names.
-  // E.g., [2,5,1] -> ".trace.packet.timestamp".
-  std::string LookupField(const uint32_t* field_ids, size_t num_fields);
-
-  // Like the above but the array of field is passed as a buffer containing
-  // varints, e.g. "\x02\x05\0x01".
-  std::string LookupField(const std::string& varint_encoded_path);
-
- private:
-  struct Message {
-    struct Field {
-      std::string name;
-      std::string type;  // "uint32", "string", "message"
-      // Only when type == "message". Note that when using Dedupe() this can
-      // be aliased against a different submessage which happens to have the
-      // same set of field ids.
-      Message* nested_type = nullptr;
-      bool is_simple() const { return nested_type == nullptr; }
-    };
-    std::string full_name;  // e.g., "perfetto.protos.Foo.Bar";
-    std::map<uint32_t /*field_id*/, Field> fields;
-
-    // True if at least one field has a non-null |nestd_type|.
-    bool has_nested_fields = false;
-  };
-
-  using DescriptorsByNameMap = std::map<std::string, Message*>;
-  Message* ParseProtoDescriptor(const google::protobuf::Descriptor*,
-                                DescriptorsByNameMap*);
-
-  // list<> because pointers need to be stable.
-  std::list<Message> descriptors_;
-};
-
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_FILTER_UTIL_H_
diff --git a/src/protozero/filtering/filter_util_unittest.cc b/src/protozero/filtering/filter_util_unittest.cc
deleted file mode 100644
index 9c7cf0d..0000000
--- a/src/protozero/filtering/filter_util_unittest.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/gtest_and_gmock.h"
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "src/protozero/filtering/filter_bytecode_parser.h"
-#include "src/protozero/filtering/filter_util.h"
-
-namespace protozero {
-
-namespace {
-
-perfetto::base::TempFile MkTemp(const char* str) {
-  auto tmp = perfetto::base::TempFile::Create();
-  perfetto::base::WriteAll(*tmp, str, strlen(str));
-  perfetto::base::FlushFile(*tmp);
-  return tmp;
-}
-
-TEST(SchemaParserTest, SchemaToBytecode_Simple) {
-  auto schema = MkTemp(R"(
-  syntax = "proto2";
-  message Root {
-    optional int32 i32 = 13;
-    optional fixed64 f64 = 5;
-    optional string str = 71;
-  }
-  )");
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "Root", ""));
-  std::string bytecode = filter.GenerateFilterBytecode();
-  FilterBytecodeParser fbp;
-  ASSERT_TRUE(fbp.Load(bytecode.data(), bytecode.size()));
-  EXPECT_TRUE(fbp.Query(0, 13).allowed);
-  EXPECT_TRUE(fbp.Query(0, 13).simple_field());
-  EXPECT_TRUE(fbp.Query(0, 5).allowed);
-  EXPECT_TRUE(fbp.Query(0, 5).simple_field());
-  EXPECT_TRUE(fbp.Query(0, 71).allowed);
-  EXPECT_TRUE(fbp.Query(0, 71).simple_field());
-  EXPECT_FALSE(fbp.Query(0, 1).allowed);
-  EXPECT_FALSE(fbp.Query(0, 12).allowed);
-  EXPECT_FALSE(fbp.Query(0, 70).allowed);
-}
-
-TEST(SchemaParserTest, SchemaToBytecode_Nested) {
-  auto schema = MkTemp(R"(
-  syntax = "proto2";
-  message Root {
-    message Child {
-      repeated fixed64 f64 = 3;
-      optional Child recurse = 4;
-    }
-    oneof xxx { int32 i32 = 1; }
-    optional Child chld = 2;
-  }
-  )");
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "", ""));
-  std::string bytecode = filter.GenerateFilterBytecode();
-  FilterBytecodeParser fbp;
-  ASSERT_TRUE(fbp.Load(bytecode.data(), bytecode.size()));
-  EXPECT_TRUE(fbp.Query(0, 1).allowed);
-  EXPECT_TRUE(fbp.Query(0, 1).simple_field());
-  EXPECT_TRUE(fbp.Query(0, 2).allowed);
-  EXPECT_FALSE(fbp.Query(0, 2).simple_field());
-  // False as those fields exist only in Child, not in the root (0).
-  EXPECT_FALSE(fbp.Query(0, 3).allowed);
-  EXPECT_FALSE(fbp.Query(0, 4).allowed);
-
-  EXPECT_TRUE(fbp.Query(1, 3).allowed);
-  EXPECT_TRUE(fbp.Query(1, 3).simple_field());
-  EXPECT_TRUE(fbp.Query(1, 4).allowed);
-  EXPECT_FALSE(fbp.Query(1, 4).simple_field());
-  EXPECT_EQ(fbp.Query(1, 4).nested_msg_index, 1u);  // Self
-}
-
-TEST(SchemaParserTest, SchemaToBytecode_Dedupe) {
-  auto schema = MkTemp(R"(
-  syntax = "proto2";
-  message Root {
-    message Nested {
-      message Child1 {
-        optional int32 f1 = 3;
-        optional int64 f2 = 4;
-      }
-      message Child2 {
-        optional string f1 = 3;
-        optional bytes f2 = 4;
-      }
-      message ChildNonDedupe {
-        optional string f1 = 3;
-        optional bytes f2 = 4;
-        optional int32 extra = 1;
-      }
-      optional Child1 chld1 = 1;
-      optional Child2 chld2 = 2;
-      optional ChildNonDedupe chld3 = 3;
-    }
-    repeated Nested nested = 1;
-  }
-  )");
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "Root", ""));
-  filter.Dedupe();
-  std::string bytecode = filter.GenerateFilterBytecode();
-  FilterBytecodeParser fbp;
-  ASSERT_TRUE(fbp.Load(bytecode.data(), bytecode.size()));
-
-  // 0: Root
-  EXPECT_TRUE(fbp.Query(0, 1).allowed);
-  EXPECT_FALSE(fbp.Query(0, 1).simple_field());
-
-  // 1: Nested
-  EXPECT_TRUE(fbp.Query(1, 1).allowed);
-  EXPECT_FALSE(fbp.Query(1, 1).simple_field());
-  EXPECT_TRUE(fbp.Query(1, 2).allowed);
-  EXPECT_FALSE(fbp.Query(1, 2).simple_field());
-  EXPECT_TRUE(fbp.Query(1, 3).allowed);
-  EXPECT_FALSE(fbp.Query(1, 3).simple_field());
-
-  // Check deduping.
-  // Fields chld1 and chld2 should point to the same sub-filter because they
-  // have the same field ids.
-  EXPECT_EQ(fbp.Query(1, 1).nested_msg_index, fbp.Query(1, 2).nested_msg_index);
-
-  // Field chld3 should point to a different one because it has an extra field.
-  EXPECT_NE(fbp.Query(1, 1).nested_msg_index, fbp.Query(1, 3).nested_msg_index);
-}
-
-TEST(SchemaParserTest, FieldLookup) {
-  auto schema = MkTemp(R"(
-  syntax = "proto2";
-  message Root {
-    message Nested {
-      message Child1 {
-        optional int32 f1 = 3;
-        optional int64 f2 = 4;
-        repeated Child2 c2 = 5;
-      }
-      message Child2 {
-        optional string f3 = 6;
-        optional bytes f4 = 7;
-        repeated Child1 c1 = 8;
-      }
-      optional Child1 x1 = 1;
-      optional Child2 x2 = 2;
-    }
-    repeated Nested n = 1;
-  }
-  )");
-
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "Root", ""));
-  std::vector<uint32_t> fld;
-
-  fld = {1, 1, 3};
-  ASSERT_EQ(filter.LookupField(fld.data(), fld.size()), ".n.x1.f1");
-
-  fld = {1, 2, 7};
-  ASSERT_EQ(filter.LookupField(fld.data(), fld.size()), ".n.x2.f4");
-
-  fld = {1, 2, 8, 5, 8, 5, 7};
-  ASSERT_EQ(filter.LookupField(fld.data(), fld.size()), ".n.x2.c1.c2.c1.c2.f4");
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/filtering/message_filter.cc b/src/protozero/filtering/message_filter.cc
deleted file mode 100644
index a971dfa..0000000
--- a/src/protozero/filtering/message_filter.cc
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/filtering/message_filter.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace protozero {
-
-namespace {
-
-// Inline helpers to append proto fields in output. They are the equivalent of
-// the protozero::Message::AppendXXX() fields but don't require building and
-// maintaining a full protozero::Message object or dealing with scattered
-// output slices.
-// All these functions assume there is enough space in the output buffer, which
-// should be always the case assuming that we don't end up generating more
-// output than input.
-
-inline void AppendVarInt(uint32_t field_id, uint64_t value, uint8_t** out) {
-  *out = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), *out);
-  *out = proto_utils::WriteVarInt(value, *out);
-}
-
-// For fixed32 / fixed64.
-template <typename INT_T /* uint32_t | uint64_t*/>
-inline void AppendFixed(uint32_t field_id, INT_T value, uint8_t** out) {
-  *out = proto_utils::WriteVarInt(proto_utils::MakeTagFixed<INT_T>(field_id),
-                                  *out);
-  memcpy(*out, &value, sizeof(value));
-  *out += sizeof(value);
-}
-
-// For length-delimited (string, bytes) fields. Note: this function appends only
-// the proto preamble and the varint field that states the length of the payload
-// not the payload itself.
-// In the case of submessages, the caller needs to re-write the length at the
-// end in the in the returned memory area.
-// The problem here is that, because of filtering, the length of a submessage
-// might be < original length (the original length is still an upper-bound).
-// Returns a pair with: (1) the pointer where the final length should be written
-// into, (2) the length of the size field.
-// The caller must write a redundant varint to match the original size (i.e.
-// needs to use WriteRedundantVarInt()).
-inline std::pair<uint8_t*, uint32_t> AppendLenDelim(uint32_t field_id,
-                                                    uint32_t len,
-                                                    uint8_t** out) {
-  *out = proto_utils::WriteVarInt(proto_utils::MakeTagLengthDelimited(field_id),
-                                  *out);
-  uint8_t* size_field_start = *out;
-  *out = proto_utils::WriteVarInt(len, *out);
-  const size_t size_field_len = static_cast<size_t>(*out - size_field_start);
-  return std::make_pair(size_field_start, size_field_len);
-}
-}  // namespace
-
-MessageFilter::MessageFilter() {
-  // Push a state on the stack for the implicit root message.
-  stack_.emplace_back();
-}
-
-MessageFilter::~MessageFilter() = default;
-
-bool MessageFilter::LoadFilterBytecode(const void* filter_data, size_t len) {
-  return filter_.Load(filter_data, len);
-}
-
-bool MessageFilter::SetFilterRoot(const uint32_t* field_ids,
-                                  size_t num_fields) {
-  uint32_t root_msg_idx = 0;
-  for (const uint32_t* it = field_ids; it < field_ids + num_fields; ++it) {
-    uint32_t field_id = *it;
-    auto res = filter_.Query(root_msg_idx, field_id);
-    if (!res.allowed || res.simple_field())
-      return false;
-    root_msg_idx = res.nested_msg_index;
-  }
-  root_msg_index_ = root_msg_idx;
-  return true;
-}
-
-MessageFilter::FilteredMessage MessageFilter::FilterMessageFragments(
-    const InputSlice* slices,
-    size_t num_slices) {
-  // First compute the upper bound for the output. The filtered message cannot
-  // be > the original message.
-  uint32_t total_len = 0;
-  for (size_t i = 0; i < num_slices; ++i)
-    total_len += slices[i].len;
-  out_buf_.reset(new uint8_t[total_len]);
-  out_ = out_buf_.get();
-  out_end_ = out_ + total_len;
-
-  // Reset the parser state.
-  tokenizer_ = MessageTokenizer();
-  error_ = false;
-  stack_.clear();
-  stack_.resize(2);
-  // stack_[0] is a sentinel and should never be hit in nominal cases. If we
-  // end up there we will just keep consuming the input stream and detecting
-  // at the end, without hurting the fastpath.
-  stack_[0].in_bytes_limit = UINT32_MAX;
-  stack_[0].eat_next_bytes = UINT32_MAX;
-  // stack_[1] is the actual root message.
-  stack_[1].in_bytes_limit = total_len;
-  stack_[1].msg_index = root_msg_index_;
-
-  // Process the input data and write the output.
-  for (size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) {
-    const InputSlice& slice = slices[slice_idx];
-    const uint8_t* data = static_cast<const uint8_t*>(slice.data);
-    for (size_t i = 0; i < slice.len; ++i)
-      FilterOneByte(data[i]);
-  }
-
-  // Construct the output object.
-  PERFETTO_CHECK(out_ >= out_buf_.get() && out_ <= out_end_);
-  auto used_size = static_cast<size_t>(out_ - out_buf_.get());
-  FilteredMessage res{std::move(out_buf_), used_size};
-  res.error = error_;
-  if (stack_.size() != 1 || !tokenizer_.idle() ||
-      stack_[0].in_bytes != total_len) {
-    res.error = true;
-  }
-  return res;
-}
-
-void MessageFilter::FilterOneByte(uint8_t octet) {
-  PERFETTO_DCHECK(!stack_.empty());
-
-  auto* state = &stack_.back();
-  StackState next_state{};
-  bool push_next_state = false;
-
-  if (state->eat_next_bytes > 0) {
-    // This is the case where the previous tokenizer_.Push() call returned a
-    // length delimited message which is NOT a submessage (a string or a bytes
-    // field). We just want to consume it, and pass it through in output
-    // if the field was allowed.
-    --state->eat_next_bytes;
-    if (state->passthrough_eaten_bytes)
-      *(out_++) = octet;
-  } else {
-    MessageTokenizer::Token token = tokenizer_.Push(octet);
-    // |token| will not be valid() in most cases and this is WAI. When pushing
-    // a varint field, only the last byte yields a token, all the other bytes
-    // return an invalid token, they just update the internal tokenizer state.
-    if (token.valid()) {
-      auto filter = filter_.Query(state->msg_index, token.field_id);
-      switch (token.type) {
-        case proto_utils::ProtoWireType::kVarInt:
-          if (filter.allowed && filter.simple_field())
-            AppendVarInt(token.field_id, token.value, &out_);
-          break;
-        case proto_utils::ProtoWireType::kFixed32:
-          if (filter.allowed && filter.simple_field())
-            AppendFixed(token.field_id, static_cast<uint32_t>(token.value),
-                        &out_);
-          break;
-        case proto_utils::ProtoWireType::kFixed64:
-          if (filter.allowed && filter.simple_field())
-            AppendFixed(token.field_id, static_cast<uint64_t>(token.value),
-                        &out_);
-          break;
-        case proto_utils::ProtoWireType::kLengthDelimited:
-          // Here we have two cases:
-          // A. A simple string/bytes field: we just want to consume the next
-          //    bytes (the string payload), optionally passing them through in
-          //    output if the field is allowed.
-          // B. This is a nested submessage. In this case we want to recurse and
-          //    push a new state on the stack.
-          // Note that we can't tell the difference between a
-          // "non-allowed string" and a "non-allowed submessage". But it doesn't
-          // matter because in both cases we just want to skip the next N bytes.
-          const auto submessage_len = static_cast<uint32_t>(token.value);
-          auto in_bytes_left = state->in_bytes_limit - state->in_bytes - 1;
-          if (PERFETTO_UNLIKELY(submessage_len > in_bytes_left)) {
-            // This is a malicious / malformed string/bytes/submessage that
-            // claims to be larger than the outer message that contains it.
-            return SetUnrecoverableErrorState();
-          }
-
-          if (filter.allowed && !filter.simple_field() && submessage_len > 0) {
-            // submessage_len == 0 is the edge case of a message with a 0-len
-            // (but present) submessage. In this case, if allowed, we don't want
-            // to push any further state (doing so would desync the FSM) but we
-            // still want to emit it.
-            // At this point |submessage_len| is only an upper bound. The
-            // final message written in output can be <= the one in input,
-            // only some of its fields might be allowed (also remember that
-            // this class implicitly removes redundancy varint encoding of
-            // len-delimited field lengths). The final length varint (the
-            // return value of AppendLenDelim()) will be filled when popping
-            // from |stack_|.
-            auto size_field =
-                AppendLenDelim(token.field_id, submessage_len, &out_);
-            push_next_state = true;
-            next_state.field_id = token.field_id;
-            next_state.msg_index = filter.nested_msg_index;
-            next_state.in_bytes_limit = submessage_len;
-            next_state.size_field = size_field.first;
-            next_state.size_field_len = size_field.second;
-            next_state.out_bytes_written_at_start = out_written();
-          } else {
-            // A string or bytes field, or a 0 length submessage.
-            state->eat_next_bytes = submessage_len;
-            state->passthrough_eaten_bytes = filter.allowed;
-            if (filter.allowed)
-              AppendLenDelim(token.field_id, submessage_len, &out_);
-          }
-          break;
-      }  // switch(type)
-
-      if (PERFETTO_UNLIKELY(track_field_usage_)) {
-        IncrementCurrentFieldUsage(token.field_id, filter.allowed);
-      }
-    }  // if (token.valid)
-  }    // if (eat_next_bytes == 0)
-
-  ++state->in_bytes;
-  while (state->in_bytes >= state->in_bytes_limit) {
-    PERFETTO_DCHECK(state->in_bytes == state->in_bytes_limit);
-    push_next_state = false;
-
-    // We can't possibly write more than we read.
-    const uint32_t msg_bytes_written = static_cast<uint32_t>(
-        out_written() - state->out_bytes_written_at_start);
-    PERFETTO_DCHECK(msg_bytes_written <= state->in_bytes_limit);
-
-    // Backfill the length field of the
-    proto_utils::WriteRedundantVarInt(msg_bytes_written, state->size_field,
-                                      state->size_field_len);
-
-    const uint32_t in_bytes_processes_for_last_msg = state->in_bytes;
-    stack_.pop_back();
-    PERFETTO_CHECK(!stack_.empty());
-    state = &stack_.back();
-    state->in_bytes += in_bytes_processes_for_last_msg;
-    if (PERFETTO_UNLIKELY(!tokenizer_.idle())) {
-      // If we hit this case, it means that we got to the end of a submessage
-      // while decoding a field. We can't recover from this and we don't want to
-      // propagate a broken sub-message.
-      return SetUnrecoverableErrorState();
-    }
-  }
-
-  if (push_next_state) {
-    PERFETTO_DCHECK(tokenizer_.idle());
-    stack_.emplace_back(std::move(next_state));
-    state = &stack_.back();
-  }
-}
-
-void MessageFilter::SetUnrecoverableErrorState() {
-  error_ = true;
-  stack_.clear();
-  stack_.resize(1);
-  auto& state = stack_[0];
-  state.eat_next_bytes = UINT32_MAX;
-  state.in_bytes_limit = UINT32_MAX;
-  state.passthrough_eaten_bytes = false;
-  out_ = out_buf_.get();  // Reset the write pointer.
-}
-
-void MessageFilter::IncrementCurrentFieldUsage(uint32_t field_id,
-                                               bool allowed) {
-  // Slowpath. Used mainly in offline tools and tests to workout used fields in
-  // a proto.
-  PERFETTO_DCHECK(track_field_usage_);
-
-  // Field path contains a concatenation of varints, one for each nesting level.
-  // e.g. y in message Root { Sub x = 2; }; message Sub { SubSub y = 7; }
-  // is encoded as [varint(2) + varint(7)].
-  // We use varint to take the most out of SSO (small string opt). In most cases
-  // the path will fit in the on-stack 22 bytes, requiring no heap.
-  std::string field_path;
-
-  auto append_field_id = [&field_path](uint32_t id) {
-    uint8_t buf[10];
-    uint8_t* end = proto_utils::WriteVarInt(id, buf);
-    field_path.append(reinterpret_cast<char*>(buf),
-                      static_cast<size_t>(end - buf));
-  };
-
-  // Append all the ancestors IDs from the state stack.
-  // The first entry of the stack has always ID 0 and we skip it (we don't know
-  // the ID of the root message itself).
-  PERFETTO_DCHECK(stack_.size() >= 2 && stack_[1].field_id == 0);
-  for (size_t i = 2; i < stack_.size(); ++i)
-    append_field_id(stack_[i].field_id);
-  // Append the id of the field in the current message.
-  append_field_id(field_id);
-  field_usage_[field_path] += allowed ? 1 : -1;
-}
-
-}  // namespace protozero
diff --git a/src/protozero/filtering/message_filter.h b/src/protozero/filtering/message_filter.h
deleted file mode 100644
index 37dc9b5..0000000
--- a/src/protozero/filtering/message_filter.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_MESSAGE_FILTER_H_
-#define SRC_PROTOZERO_FILTERING_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-
-#include "src/protozero/filtering/filter_bytecode_parser.h"
-#include "src/protozero/filtering/message_tokenizer.h"
-
-namespace protozero {
-
-// A class to filter binary-encoded proto messages using an allow-list of field
-// ids, also known as "filter bytecode". The filter determines which fields are
-// allowed to be passed through in output and strips all the other fields.
-// See go/trace-filtering for full design.
-// This class takes in input:
-// 1) The filter bytecode, loaded once via the LoadFilterBytecode() method.
-// 2) A proto-encoded binary message. The message doesn't have to be contiguous,
-//    it can be passed as an array of arbitrarily chunked fragments.
-// The FilterMessage*() method returns in output a proto message, stripping out
-// all unknown fields. If the input is malformed (e.g., unknown proto field wire
-// types, lengths out of bound) the whole filtering failed and the |error| flag
-// of the FilteredMessage object is set to true.
-// The filtering operation is based on rewriting a copy of the message into a
-// self-allocated buffer, which is then returned in the output. The input buffer
-// is NOT altered.
-// Note also that the process of rewriting the protos gets rid of most redundant
-// varint encoding (if present). So even if all fields are allow-listed, the
-// output might NOT be bitwise identical to the input (but it will be
-// semantically equivalent).
-// Furthermore the enable_field_usage_tracking() method allows to keep track of
-// a histogram of allowed / denied fields. It slows down filtering and is
-// intended only on host tools.
-class MessageFilter {
- public:
-  MessageFilter();
-  ~MessageFilter();
-
-  struct InputSlice {
-    const void* data;
-    size_t len;
-  };
-
-  struct FilteredMessage {
-    FilteredMessage(std::unique_ptr<uint8_t[]> d, size_t s)
-        : data(std::move(d)), size(s) {}
-    std::unique_ptr<uint8_t[]> data;
-    size_t size;  // The used bytes in |data|. This is <= sizeof(data).
-    bool error = false;
-  };
-
-  // Loads the filter bytecode that will be used to filter any subsequent
-  // message. Must be called before the first call to FilterMessage*().
-  // |filter_data| must point to a byte buffer for a proto-encoded ProtoFilter
-  // message (see proto_filter.proto).
-  bool LoadFilterBytecode(const void* filter_data, size_t len);
-
-  // This affects the filter starting point of the subsequent FilterMessage*()
-  // calls. By default the filtering process starts from the message @ index 0,
-  // the root message passed to proto_filter when generating the bytecode
-  // (in typical tracing use-cases, this is perfetto.protos.Trace). However, the
-  // caller (TracingServiceImpl) might want to filter packets from the 2nd level
-  // (perfetto.protos.TracePacket) because the root level is pre-pended after
-  // the fact. This call allows to change the root message for the filter.
-  // The argument |field_ids| is an array of proto field ids and determines the
-  // path to the new root. For instance, in the case of [1,2,3] SetFilterRoot
-  // will identify the sub-message for the field "root.1.2.3" and use that.
-  // In order for this to succeed all the fields in the path must be allowed
-  // in the filter and must be a nested message type.
-  bool SetFilterRoot(const uint32_t* field_ids, size_t num_fields);
-
-  // Takes an input message, fragmented in arbitrary slices, and returns a
-  // filtered message in output.
-  FilteredMessage FilterMessageFragments(const InputSlice*, size_t num_slices);
-
-  // Helper for tests, where the input is a contiguous buffer.
-  FilteredMessage FilterMessage(const void* data, size_t len) {
-    InputSlice slice{data, len};
-    return FilterMessageFragments(&slice, 1);
-  }
-
-  // When enabled returns a map of "field path" to "usage counter".
-  // The key (std::string) is a binary buffer (i.e. NOT an ASCII/UTF-8 string)
-  // which contains a varint for each field. Consider the following:
-  // message Root { Sub1 f1 = 1; };
-  // message Sub1 { Sub2 f2 = 7;}
-  // message Sub2 { string f3 = 5; }
-  // The field .f1.f2.f3 will be encoded as \x01\0x07\x05.
-  // The value is the number of times that field has been encountered. If the
-  // field is not allow-listed in the bytecode (the field is stripped in output)
-  // the count will be negative.
-  void enable_field_usage_tracking(bool x) { track_field_usage_ = x; }
-  const std::unordered_map<std::string, int32_t>& field_usage() const {
-    return field_usage_;
-  }
-
-  // Exposed only for DCHECKS in TracingServiceImpl.
-  uint32_t root_msg_index() { return root_msg_index_; }
-
- private:
-  // This is called by FilterMessageFragments().
-  // Inlining allows the compiler turn the per-byte call/return into a for loop,
-  // while, at the same time, keeping the code easy to read and reason about.
-  // It gives a 20-25% speedup (265ms vs 215ms for a 25MB trace).
-  void FilterOneByte(uint8_t octet) PERFETTO_ALWAYS_INLINE;
-
-  // No-inline because this is a slowpath (only when usage tracking is enabled).
-  void IncrementCurrentFieldUsage(uint32_t field_id,
-                                  bool allowed) PERFETTO_NO_INLINE;
-
-  // Gets into an error state which swallows all the input and emits no output.
-  void SetUnrecoverableErrorState();
-
-  // We keep track of the the nest of messages in a stack. Each StackState
-  // object corresponds to a level of nesting in the proto message structure.
-  // Every time a new field of type len-delimited that has a corresponding
-  // sub-message in the bytecode is encountered, a new StackState is pushed in
-  // |stack_|. stack_[0] is a sentinel to prevent over-popping without adding
-  // extra branches in the fastpath.
-  // |stack_|. stack_[1] is the state of the root message.
-  struct StackState {
-    uint32_t in_bytes = 0;  // Number of input bytes processed.
-
-    // When |in_bytes| reaches this value, the current state should be popped.
-    // This is set when recursing into nested submessages. This is 0 only for
-    // stack_[0] (we don't know the size of the root message upfront).
-    uint32_t in_bytes_limit = 0;
-
-    // This is set when a len-delimited message is encountered, either a string
-    // or a nested submessage that is NOT allow-listed in the bytecode.
-    // This causes input bytes to be consumed without being parsed from the
-    // input stream. If |passthrough_eaten_bytes| == true, they will be copied
-    // as-is in output (e.g. in the case of an allowed string/bytes field).
-    uint32_t eat_next_bytes = 0;
-
-    // Keeps tracks of the stream_writer output counter (out_.written()) then
-    // the StackState is pushed. This is used to work out, when popping, how
-    // many bytes have been written for the current submessage.
-    uint32_t out_bytes_written_at_start = 0;
-
-    uint32_t field_id = 0;   // The proto field id for the current message.
-    uint32_t msg_index = 0;  // The index of the message filter in the bytecode.
-
-    // This is a pointer to the proto preamble for the current submessage
-    // (it's nullptr for stack_[0] and non-null elsewhere). This will be filled
-    // with the actual size of the message (out_.written() -
-    // |out_bytes_written_at_start|) when finishing (popping) the message.
-    // This must be filled using WriteRedundantVarint(). Note that the
-    // |size_field_len| is variable and depends on the actual length of the
-    // input message. If the output message has roughly the same size of the
-    // input message, the length will not be redundant.
-    // In other words: the length of the field is reserved when the submessage
-    // starts. At that point we know the upper-bound for the output message
-    // (a filtered submessage can be <= the original one, but not >). So we
-    // reserve as many bytes it takes to write the input length in varint.
-    // Then, when the message is finalized and we know the actual output size
-    // we backfill the field.
-    // Consider the example of a submessage where the input size = 130 (>127,
-    // 2 varint bytes) and the output is 120 bytes. The length will be 2 bytes
-    // wide even though could have been encoded with just one byte.
-    uint8_t* size_field = nullptr;
-    uint32_t size_field_len = 0;
-
-    // When true the next |eat_next_bytes| are copied as-is in output.
-    // It seems that keeping this field at the end rather than next to
-    // |eat_next_bytes| makes the filter a little (but measurably) faster.
-    // (likely something related with struct layout vs cache sizes).
-    bool passthrough_eaten_bytes = false;
-  };
-
-  uint32_t out_written() { return static_cast<uint32_t>(out_ - &out_buf_[0]); }
-
-  std::unique_ptr<uint8_t[]> out_buf_;
-  uint8_t* out_ = nullptr;
-  uint8_t* out_end_ = nullptr;
-  uint32_t root_msg_index_ = 0;
-
-  FilterBytecodeParser filter_;
-  MessageTokenizer tokenizer_;
-  std::vector<StackState> stack_;
-
-  bool error_ = false;
-  bool track_field_usage_ = false;
-  std::unordered_map<std::string, int32_t> field_usage_;
-};
-
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_MESSAGE_FILTER_H_
diff --git a/src/protozero/filtering/message_filter_benchmark.cc b/src/protozero/filtering/message_filter_benchmark.cc
deleted file mode 100644
index c800c82..0000000
--- a/src/protozero/filtering/message_filter_benchmark.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 <algorithm>
-#include <string>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "src/base/test/utils.h"
-#include "src/protozero/filtering/message_filter.h"
-
-static void BM_ProtozeroMessageFilter(benchmark::State& state) {
-  std::string trace_data;
-  static const char kTestTrace[] = "test/data/example_android_trace_30s.pb";
-  perfetto::base::ReadFile(perfetto::base::GetTestDataPath(kTestTrace),
-                           &trace_data);
-  PERFETTO_CHECK(!trace_data.empty());
-
-  std::string filter;
-  static const char kFullTraceFilter[] = "test/data/full_trace_filter.bytecode";
-  perfetto::base::ReadFile(kFullTraceFilter, &filter);
-  PERFETTO_CHECK(!filter.empty());
-
-  protozero::MessageFilter filt;
-  filt.LoadFilterBytecode(filter.data(), filter.size());
-
-  for (auto _ : state) {
-    auto res = filt.FilterMessage(trace_data.data(), trace_data.size());
-    benchmark::DoNotOptimize(res);
-    benchmark::ClobberMemory();
-  }
-  state.SetBytesProcessed(
-      static_cast<int64_t>(state.iterations() * trace_data.size()));
-}
-
-BENCHMARK(BM_ProtozeroMessageFilter);
diff --git a/src/protozero/filtering/message_filter_fuzzer.cc b/src/protozero/filtering/message_filter_fuzzer.cc
deleted file mode 100644
index 60cfe5c..0000000
--- a/src/protozero/filtering/message_filter_fuzzer.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <string.h>
-
-#include "perfetto/base/logging.h"
-#include "src/protozero/filtering/message_filter.h"
-
-namespace protozero {
-namespace {
-
-// A valid filter bytecode obtained from a perfetto.protos.Trace message.
-uint8_t kValidFilter[] = {
-    0x0b, 0x01, 0x12, 0x04, 0x00, 0x0b, 0x02, 0x13, 0x0f, 0x19, 0x23, 0x13,
-    0x33, 0x14, 0x3b, 0x15, 0x41, 0x4b, 0x11, 0x51, 0x5b, 0x16, 0x63, 0x3b,
-    0x69, 0x8b, 0x02, 0x21, 0x93, 0x02, 0x2a, 0x9b, 0x02, 0x2c, 0xab, 0x02,
-    0x2e, 0xb3, 0x02, 0x09, 0xc3, 0x02, 0x30, 0xca, 0x02, 0x02, 0xdb, 0x02,
-    0x31, 0xe3, 0x02, 0x26, 0xeb, 0x02, 0x32, 0xf3, 0x02, 0x07, 0xfb, 0x02,
-    0x33, 0x8b, 0x03, 0x0a, 0x9b, 0x03, 0x34, 0xb3, 0x03, 0x06, 0xc3, 0x03,
-    0x37, 0xd1, 0x03, 0xdb, 0x03, 0x3c, 0xe3, 0x03, 0x39, 0x93, 0x04, 0x38,
-    0x9b, 0x04, 0x3a, 0x00, 0x09, 0x13, 0x03, 0x19, 0x00, 0x0a, 0x02, 0x1b,
-    0x04, 0x23, 0x05, 0x5b, 0x06, 0x6b, 0x06, 0x83, 0x01, 0x07, 0x8b, 0x01,
-    0x08, 0x93, 0x01, 0x07, 0x9b, 0x01, 0x07, 0xa3, 0x01, 0x08, 0x9b, 0x02,
-    0x08, 0xcb, 0x02, 0x08, 0xd3, 0x02, 0x08, 0xdb, 0x02, 0x09, 0xe3, 0x02,
-    0x07, 0xeb, 0x02, 0x0a, 0xf3, 0x02, 0x07, 0xfb, 0x02, 0x0b, 0x83, 0x03,
-    0x06, 0x8b, 0x03, 0x0b, 0x93, 0x03, 0x05, 0x9b, 0x03, 0x0b, 0xab, 0x03,
-    0x0c, 0xb3, 0x03, 0x0c, 0xbb, 0x03, 0x0c, 0x9b, 0x04, 0x0d, 0xa3, 0x04,
-    0x07, 0xab, 0x04, 0x06, 0xb3, 0x04, 0x07, 0xc3, 0x04, 0x06, 0xcb, 0x04,
-    0x07, 0xd3, 0x04, 0x07, 0xdb, 0x04, 0x06, 0x93, 0x07, 0x08, 0xeb, 0x07,
-    0x08, 0xcb, 0x09, 0x07, 0xd3, 0x09, 0x05, 0xf3, 0x0b, 0x06, 0xdb, 0x0e,
-    0x09, 0xe3, 0x0e, 0x09, 0xeb, 0x0e, 0x07, 0xf3, 0x0e, 0x09, 0xfb, 0x0e,
-    0x09, 0x83, 0x0f, 0x07, 0x8b, 0x0f, 0x06, 0x93, 0x0f, 0x07, 0xb3, 0x0f,
-    0x0a, 0xc3, 0x0f, 0x0e, 0xfb, 0x0f, 0x0e, 0x83, 0x10, 0x08, 0xfb, 0x10,
-    0x08, 0x8b, 0x11, 0x08, 0xcb, 0x13, 0x06, 0xd3, 0x13, 0x07, 0xdb, 0x13,
-    0x07, 0xb3, 0x14, 0x07, 0x00, 0x11, 0x00, 0x0a, 0x07, 0x00, 0x0a, 0x02,
-    0x00, 0x0a, 0x03, 0x00, 0x0a, 0x05, 0x00, 0x0a, 0x04, 0x00, 0x0a, 0x06,
-    0x00, 0x09, 0x00, 0x00, 0x0a, 0x03, 0x29, 0x00, 0x0a, 0x08, 0x00, 0x0b,
-    0x10, 0x13, 0x07, 0x19, 0x00, 0x0a, 0x03, 0x23, 0x07, 0x29, 0x00, 0x0b,
-    0x12, 0x11, 0x00, 0x0a, 0x0a, 0x5b, 0x07, 0x00, 0x0a, 0x02, 0x1b, 0x07,
-    0x00, 0x0b, 0x09, 0x11, 0x00, 0x0b, 0x06, 0x13, 0x06, 0x1b, 0x0e, 0x22,
-    0x02, 0x33, 0x06, 0x39, 0x43, 0x06, 0x49, 0x00, 0x0a, 0x03, 0x2b, 0x0b,
-    0x33, 0x20, 0x42, 0x05, 0x82, 0x01, 0x02, 0xa1, 0x01, 0xc3, 0x01, 0x17,
-    0xcb, 0x01, 0x04, 0xd3, 0x01, 0x0b, 0xdb, 0x01, 0x06, 0xe3, 0x01, 0x1e,
-    0xeb, 0x01, 0x1f, 0xf2, 0x01, 0x02, 0x00, 0x0b, 0x18, 0x12, 0x0c, 0x73,
-    0x1a, 0x7b, 0x1c, 0x83, 0x01, 0x1d, 0x8b, 0x01, 0x05, 0x00, 0x0b, 0x08,
-    0x13, 0x19, 0x00, 0x0a, 0x2e, 0x00, 0x0a, 0x03, 0x23, 0x1b, 0x2b, 0x1b,
-    0x33, 0x05, 0x00, 0x0a, 0x09, 0x53, 0x09, 0x00, 0x09, 0x13, 0x1b, 0x00,
-    0x0a, 0x03, 0x23, 0x1b, 0x00, 0x09, 0x19, 0x00, 0x0a, 0x03, 0x23, 0x06,
-    0x2a, 0x02, 0x00, 0x0a, 0x04, 0x31, 0x42, 0x08, 0x92, 0x01, 0x02, 0x00,
-    0x0b, 0x22, 0x13, 0x23, 0x1a, 0x03, 0x33, 0x07, 0x3b, 0x09, 0x42, 0x03,
-    0x5b, 0x0b, 0x62, 0x03, 0x81, 0x01, 0x8b, 0x01, 0x29, 0x92, 0x01, 0x02,
-    0xa3, 0x01, 0x07, 0xab, 0x01, 0x0b, 0xb2, 0x01, 0x03, 0xcb, 0x01, 0x09,
-    0xda, 0x01, 0x02, 0x00, 0x09, 0x21, 0x00, 0x0b, 0x24, 0x11, 0x00, 0x0a,
-    0x04, 0x31, 0xa3, 0x06, 0x25, 0xbb, 0x06, 0x26, 0xc3, 0x06, 0x0a, 0xcb,
-    0x06, 0x27, 0xd3, 0x06, 0x06, 0xeb, 0x06, 0x0b, 0x00, 0x0a, 0x03, 0x52,
-    0x02, 0x00, 0x0a, 0x04, 0x32, 0x03, 0x00, 0x0a, 0x02, 0x22, 0x02, 0x33,
-    0x28, 0x3a, 0x02, 0x00, 0x2a, 0x02, 0x00, 0x09, 0x13, 0x07, 0x19, 0x00,
-    0x09, 0x13, 0x2b, 0x00, 0x0a, 0x09, 0x00, 0x0b, 0x2d, 0x12, 0x08, 0x00,
-    0x0a, 0x12, 0x00, 0x0b, 0x06, 0x13, 0x09, 0x1b, 0x06, 0x23, 0x05, 0x2b,
-    0x2f, 0x32, 0x02, 0x00, 0x09, 0x13, 0x0a, 0x00, 0x0b, 0x09, 0x13, 0x07,
-    0x00, 0x09, 0x1a, 0x03, 0x00, 0x0b, 0x09, 0x12, 0x02, 0x00, 0x0b, 0x08,
-    0x12, 0x02, 0x00, 0x0b, 0x35, 0x11, 0x00, 0x0b, 0x36, 0x13, 0x36, 0x00,
-    0x09, 0x13, 0x07, 0x1b, 0x0b, 0x00, 0x09, 0x13, 0x08, 0x1b, 0x06, 0x23,
-    0x06, 0x2a, 0x02, 0x3b, 0x06, 0x00, 0x0a, 0x05, 0x82, 0x01, 0x03, 0x00,
-    0x09, 0x1b, 0x31, 0x23, 0x26, 0x29, 0x33, 0x09, 0x3b, 0x06, 0x43, 0x31,
-    0x00, 0x0b, 0x06, 0x00, 0x0b, 0x06, 0x13, 0x06, 0x23, 0x09, 0x2b, 0x06,
-    0x33, 0x09, 0x3b, 0x06, 0x83, 0x01, 0x06, 0x8b, 0x01, 0x06, 0x93, 0x01,
-    0x06, 0x9b, 0x01, 0x05, 0x00, 0x5b, 0x3d, 0xd1, 0x03, 0x00, 0x59, 0xf9,
-    0x01, 0x00, 0x8f, 0xf8, 0xf5, 0xcb, 0x06};
-
-int FuzzMessageFilter(const uint8_t* data, size_t size) {
-  MessageFilter filter;
-  PERFETTO_CHECK(filter.LoadFilterBytecode(kValidFilter, sizeof(kValidFilter)));
-
-  auto res = filter.FilterMessage(data, size);
-
-  // Either parsing fails or if it succeeds, the output data must be <= input.
-  PERFETTO_CHECK(res.error || res.size <= size);
-  return 0;
-}
-
-}  // namespace
-}  // namespace protozero
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  return protozero::FuzzMessageFilter(data, size);
-}
diff --git a/src/protozero/filtering/message_filter_unittest.cc b/src/protozero/filtering/message_filter_unittest.cc
deleted file mode 100644
index 83cb911..0000000
--- a/src/protozero/filtering/message_filter_unittest.cc
+++ /dev/null
@@ -1,810 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/gtest_and_gmock.h"
-
-#include <random>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "src/protozero/filtering/filter_util.h"
-#include "src/protozero/filtering/message_filter.h"
-
-namespace protozero {
-
-namespace {
-
-TEST(MessageFilterTest, EndToEnd) {
-  auto schema = perfetto::base::TempFile::Create();
-  static const char kSchema[] = R"(
-  syntax = "proto2";
-  message FilterSchema {
-    message Nested {
-      optional fixed32 f32 = 2;
-      repeated string ss = 5;
-    }
-    optional int32 i32 = 1;
-    optional string str = 3;
-    repeated Nested nest = 6;
-    repeated int32 f11 = 11;
-    repeated int64 f12 = 12;
-    repeated sint32 f13 = 13;
-    repeated sint64 f14 = 14;
-    repeated fixed32 f15 = 15;
-    repeated fixed32 f16 = 16;
-    repeated fixed64 f17 = 17;
-    repeated fixed64 f18 = 18;
-    repeated float f19 = 19;
-    repeated double f20 = 20;
-  };
-  )";
-
-  perfetto::base::WriteAll(*schema, kSchema, strlen(kSchema));
-  perfetto::base::FlushFile(*schema);
-
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "", ""));
-  std::string bytecode = filter.GenerateFilterBytecode();
-  ASSERT_GT(bytecode.size(), 0u);
-
-  HeapBuffered<Message> msg;
-  msg->AppendVarInt(/*field_id=*/1, -1000000000ll);
-  msg->AppendVarInt(/*field_id=*/2, 42);
-  msg->AppendString(/*field_id=*/3, "foobar");
-  msg->AppendFixed(/*field_id=*/4, 10);
-  msg->AppendVarInt(/*field_id=*/11, INT32_MIN);
-  msg->AppendVarInt(/*field_id=*/12, INT64_MIN);
-  msg->AppendSignedVarInt(/*field_id=*/13, INT32_MIN);
-  msg->AppendSignedVarInt(/*field_id=*/14, INT64_MIN);
-  msg->AppendFixed(/*field_id=*/15, static_cast<int32_t>(INT32_MIN));
-  msg->AppendFixed(/*field_id=*/16, static_cast<int32_t>(INT32_MAX));
-  msg->AppendFixed(/*field_id=*/17, static_cast<int64_t>(INT64_MIN));
-  msg->AppendFixed(/*field_id=*/18, static_cast<int64_t>(INT64_MAX));
-  msg->AppendFixed(/*field_id=*/19, FLT_EPSILON);
-  msg->AppendFixed(/*field_id=*/20, DBL_EPSILON);
-
-  auto* nest = msg->BeginNestedMessage<Message>(/*field_id=*/6);
-  nest->AppendFixed(/*field_id=*/1, 10);
-  nest->AppendFixed(/*field_id=*/2, static_cast<int32_t>(-2000000000ll));
-  nest->AppendString(/*field_id=*/4, "stripped");
-  nest->AppendString(/*field_id=*/5, "");
-  nest->Finalize();
-
-  MessageFilter flt;
-  ASSERT_TRUE(flt.LoadFilterBytecode(bytecode.data(), bytecode.size()));
-
-  std::vector<uint8_t> encoded = msg.SerializeAsArray();
-
-  for (int repetitions = 0; repetitions < 3; ++repetitions) {
-    auto filtered = flt.FilterMessage(encoded.data(), encoded.size());
-    ASSERT_LT(filtered.size, encoded.size());
-
-    ProtoDecoder dec(filtered.data.get(), filtered.size);
-    EXPECT_TRUE(dec.FindField(1).valid());
-    EXPECT_EQ(dec.FindField(1).as_int64(), -1000000000ll);
-    EXPECT_FALSE(dec.FindField(2).valid());
-    EXPECT_TRUE(dec.FindField(3).valid());
-    EXPECT_EQ(dec.FindField(3).as_std_string(), "foobar");
-    EXPECT_FALSE(dec.FindField(4).valid());
-    EXPECT_TRUE(dec.FindField(6).valid());
-    for (uint32_t i = 11; i <= 20; ++i)
-      EXPECT_TRUE(dec.FindField(i).valid());
-
-    EXPECT_EQ(dec.FindField(11).as_int32(), INT32_MIN);
-    EXPECT_EQ(dec.FindField(12).as_int64(), INT64_MIN);
-    EXPECT_EQ(dec.FindField(13).as_sint32(), INT32_MIN);
-    EXPECT_EQ(dec.FindField(14).as_sint64(), INT64_MIN);
-    EXPECT_EQ(dec.FindField(15).as_int32(), INT32_MIN);
-    EXPECT_EQ(dec.FindField(16).as_int32(), INT32_MAX);
-    EXPECT_EQ(dec.FindField(17).as_int64(), INT64_MIN);
-    EXPECT_EQ(dec.FindField(18).as_int64(), INT64_MAX);
-    EXPECT_EQ(dec.FindField(19).as_float(), FLT_EPSILON);
-    EXPECT_EQ(dec.FindField(20).as_double(), DBL_EPSILON);
-
-    ProtoDecoder nest_dec(dec.FindField(6).as_bytes());
-    EXPECT_FALSE(nest_dec.FindField(1).valid());
-    EXPECT_TRUE(nest_dec.FindField(2).valid());
-    EXPECT_EQ(nest_dec.FindField(2).as_int32(), -2000000000ll);
-    EXPECT_TRUE(nest_dec.FindField(5).valid());
-    EXPECT_EQ(nest_dec.FindField(5).as_bytes().size, 0u);
-  }
-}
-
-TEST(MessageFilterTest, ChangeRoot) {
-  auto schema = perfetto::base::TempFile::Create();
-  static const char kSchema[] = R"(
-  syntax = "proto2";
-  message FilterSchema {
-    message Nested {
-      message Nested2 {
-        optional int32 e = 5;
-      }
-      optional int32 c = 3;
-      repeated Nested2 d = 4;
-    }
-    optional int32 a = 1;
-    optional Nested b = 2;
-  };
-  )";
-
-  perfetto::base::WriteAll(*schema, kSchema, strlen(kSchema));
-  perfetto::base::FlushFile(*schema);
-
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "", ""));
-  std::string bytecode = filter.GenerateFilterBytecode();
-  ASSERT_GT(bytecode.size(), 0u);
-
-  HeapBuffered<Message> msg;
-  msg->AppendVarInt(/*field_id=*/1, 101);
-  msg->AppendVarInt(/*field_id=*/3, 103);
-  msg->AppendVarInt(/*field_id=*/5, 105);
-  auto* nest = msg->BeginNestedMessage<Message>(/*field_id=*/4);  // Nested b.
-  nest->AppendVarInt(/*field_id=*/5, 205);
-  nest->Finalize();
-  std::vector<uint8_t> encoded = msg.SerializeAsArray();
-
-  MessageFilter flt;
-  ASSERT_TRUE(flt.LoadFilterBytecode(bytecode.data(), bytecode.size()));
-  uint32_t roots[2]{2, 4};
-
-  // First set the root to field id ".2" (.b). The fliter should happen treating
-  // |Nested| as rot, so allowing only field 3 and 4 (Nested2) through.
-  {
-    flt.SetFilterRoot(roots, 1);
-    auto filtered = flt.FilterMessage(encoded.data(), encoded.size());
-    ASSERT_LT(filtered.size, encoded.size());
-    ProtoDecoder dec(filtered.data.get(), filtered.size);
-    EXPECT_FALSE(dec.FindField(1).valid());
-    EXPECT_TRUE(dec.FindField(3).valid());
-    EXPECT_EQ(dec.FindField(3).as_int32(), 103);
-    EXPECT_FALSE(dec.FindField(5).valid());
-    EXPECT_TRUE(dec.FindField(4).valid());
-    EXPECT_EQ(dec.FindField(4).as_std_string(), "(\xCD\x01");
-  }
-
-  // Now set the root to ".2.4" (.b.d). This should allow only the field "e"
-  // to pass through.
-  {
-    flt.SetFilterRoot(roots, 2);
-    auto filtered = flt.FilterMessage(encoded.data(), encoded.size());
-    ASSERT_LT(filtered.size, encoded.size());
-    ProtoDecoder dec(filtered.data.get(), filtered.size);
-    EXPECT_FALSE(dec.FindField(1).valid());
-    EXPECT_FALSE(dec.FindField(3).valid());
-    EXPECT_FALSE(dec.FindField(4).valid());
-    EXPECT_TRUE(dec.FindField(5).valid());
-    EXPECT_EQ(dec.FindField(5).as_int32(), 105);
-  }
-}
-
-TEST(MessageFilterTest, MalformedInput) {
-  // Create and load a simple filter.
-  auto schema = perfetto::base::TempFile::Create();
-  static const char kSchema[] = R"(
-  syntax = "proto2";
-  message FilterSchema {
-    message Nested {
-      optional fixed32 f32 = 4;
-      repeated string ss = 5;
-    }
-    optional int32 i32 = 1;
-    optional string str = 2;
-    repeated Nested nest = 3;
-  };
-  )";
-  perfetto::base::WriteAll(*schema, kSchema, strlen(kSchema));
-  perfetto::base::FlushFile(*schema);
-  FilterUtil filter;
-  ASSERT_TRUE(filter.LoadMessageDefinition(schema.path(), "", ""));
-  std::string bytecode = filter.GenerateFilterBytecode();
-  ASSERT_GT(bytecode.size(), 0u);
-  MessageFilter flt;
-  ASSERT_TRUE(flt.LoadFilterBytecode(bytecode.data(), bytecode.size()));
-
-  {
-    // A malformed message found by the fuzzer.
-    static const uint8_t kData[]{
-        0x52, 0x21,  // ID=10, type=len-delimited, len=33.
-        0xa0, 0xa4,  // Early terminating payload.
-    };
-    auto res = flt.FilterMessage(kData, sizeof(kData));
-    EXPECT_TRUE(res.error);
-  }
-
-  {
-    // A malformed message which contains a non-terminated varint.
-    static const uint8_t kData[]{
-        0x08, 0x2A,  // A valid varint field id=1 value=42 (0x2A).
-        0x08, 0xFF,  // An unterminated varint.
-    };
-    auto res = flt.FilterMessage(kData, sizeof(kData));
-    EXPECT_TRUE(res.error);
-  }
-
-  {
-    // A malformed message which contains a sub-message with a field that brings
-    // it out of the outer size.
-    static const uint8_t kData[]{
-        0x08, 0x2A,  // A valid varint field id=1 value=42 (0x2A).
-        0x1A, 0x04,  // A len-delim field, id=3, length=4.
-        // The nested message |nest| starts here.
-        0x25, 0x0, 0x0, 0x0, 0x01,  // A fixed32 field, id=4.
-        // Note that the fixed32 field has an expected length of 4 but that
-        // overflows the size of the |nest| method, because with its 0x25
-        // preamble it becomes 5 bytes. At this point this should cause a
-        // persistent failure.
-    };
-    auto res = flt.FilterMessage(kData, sizeof(kData));
-    EXPECT_TRUE(res.error);
-  }
-
-  // A parsing failure shoulnd't affect the ability to filter the following
-  // message. Try again but this time with a valid message.
-  {
-    static const uint8_t kData[]{
-        0x08, 0x2A,  // A valid varint field id=1 value=42 (0x2A).
-        0x1A, 0x05,  // A len-delim field, id=3, length=5.
-        0x25, 0x0,  0x0, 0x0, 0x01,  // A fixed32 field, id=4.
-        0x38, 0x42,  // A valid but not allowed varint field id=7.
-    };
-    auto res = flt.FilterMessage(kData, sizeof(kData));
-    EXPECT_FALSE(res.error);
-    EXPECT_EQ(res.size, sizeof(kData) - 2);  // last 2 bytes should be skipped.
-    EXPECT_EQ(memcmp(kData, res.data.get(), res.size), 0);
-  }
-}
-
-// It processes a real test trace with a real filter. The filter has been
-// obtained from the full upstream perfetto proto (+ re-adding the for_testing
-// field which got removed after adding most test traces). This covers the most
-// complex case of filtering a real trace with a filter that allows all possible
-// fields, hence re-entering deeply in most nested fields.
-TEST(MessageFilterTest, RealTracePassthrough) {
-  // This is test/data/android_log_ring_buffer_mode.pb. It's re-encoded as a
-  // constant because unittests cannot depend on test/data/, only integration
-  // tests can.
-  static const uint8_t kTraceData[]{
-      0x0a, 0x16, 0x18, 0x8f, 0x4e, 0xa2, 0x02, 0x10, 0x82, 0x47, 0x7a, 0x76,
-      0xb2, 0x8d, 0x42, 0xba, 0x81, 0xdc, 0x33, 0x32, 0x6d, 0x57, 0xa0, 0x79,
-      0x0a, 0x5f, 0x18, 0x8f, 0x4e, 0x32, 0x5a, 0x0a, 0x09, 0x08, 0x06, 0x10,
-      0xf4, 0xd3, 0xea, 0xbb, 0xba, 0x55, 0x0a, 0x0c, 0x08, 0x02, 0x10, 0xf9,
-      0xcc, 0xb4, 0xd1, 0xe8, 0xdc, 0xa5, 0xbc, 0x15, 0x0a, 0x09, 0x08, 0x04,
-      0x10, 0x86, 0xb9, 0x9c, 0xba, 0xba, 0x55, 0x0a, 0x0c, 0x08, 0x01, 0x10,
-      0xeb, 0xe9, 0x82, 0xd3, 0xe8, 0xdc, 0xa5, 0xbc, 0x15, 0x0a, 0x09, 0x08,
-      0x03, 0x10, 0xac, 0xd6, 0xea, 0xbb, 0xba, 0x55, 0x0a, 0x09, 0x08, 0x05,
-      0x10, 0x9b, 0xe1, 0xd8, 0xbb, 0xba, 0x55, 0x0a, 0x07, 0x08, 0x07, 0x10,
-      0xf5, 0xe6, 0xd9, 0x55, 0x0a, 0x07, 0x08, 0x08, 0x10, 0xc1, 0xcc, 0xa7,
-      0x41, 0x0a, 0x27, 0x18, 0x8f, 0x4e, 0x9a, 0x02, 0x21, 0x0a, 0x13, 0x08,
-      0xf0, 0x1f, 0x10, 0x01, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00,
-      0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x10, 0x01, 0x18, 0x07, 0x20, 0x06,
-      0x28, 0x0b, 0x30, 0x01, 0x38, 0x01, 0x0a, 0xd5, 0x01, 0x18, 0x8f, 0x4e,
-      0x8a, 0x02, 0xce, 0x01, 0x0a, 0x06, 0x08, 0x80, 0x80, 0x02, 0x20, 0x00,
-      0x12, 0xa5, 0x01, 0x0a, 0xa2, 0x01, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
-      0x6f, 0x69, 0x64, 0x2e, 0x6c, 0x6f, 0x67, 0x10, 0x00, 0x18, 0x00, 0x20,
-      0x00, 0xa2, 0x06, 0x04, 0x50, 0x00, 0x58, 0x00, 0xaa, 0x06, 0x02, 0x0a,
-      0x00, 0xb2, 0x06, 0x08, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00,
-      0xba, 0x06, 0x06, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0xc2, 0x06, 0x06,
-      0x08, 0x00, 0x18, 0x00, 0x28, 0x00, 0xca, 0x06, 0x0a, 0x08, 0x00, 0x28,
-      0x00, 0x32, 0x04, 0x28, 0x00, 0x30, 0x00, 0xd2, 0x06, 0x02, 0x08, 0x00,
-      0xda, 0x06, 0x02, 0x18, 0x00, 0xc2, 0x3e, 0x00, 0xfa, 0xff, 0xff, 0xff,
-      0x07, 0x46, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00,
-      0x32, 0x3a, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x29, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00,
-      0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
-      0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x60, 0x00, 0x6a, 0x00, 0x72, 0x00,
-      0x18, 0xe0, 0xd4, 0x03, 0x20, 0x00, 0x28, 0x00, 0x3a, 0x06, 0x08, 0x00,
-      0x10, 0x00, 0x18, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0x00, 0x5a, 0x02,
-      0x08, 0x00, 0x60, 0x00, 0x68, 0x00, 0x0a, 0x94, 0x01, 0x40, 0xd9, 0xf4,
-      0x98, 0x96, 0xbe, 0x54, 0xba, 0x02, 0x84, 0x81, 0x80, 0x00, 0x0a, 0xff,
-      0x80, 0x80, 0x00, 0x38, 0x04, 0x32, 0x08, 0x70, 0x65, 0x72, 0x66, 0x65,
-      0x74, 0x74, 0x6f, 0x42, 0x5d, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-      0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f,
-      0x75, 0x72, 0x63, 0x65, 0x2e, 0x63, 0x63, 0x3a, 0x31, 0x35, 0x35, 0x20,
-      0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x6e, 0x64,
-      0x72, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x64, 0x61, 0x74,
-      0x61, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x20, 0x73, 0x74,
-      0x72, 0x65, 0x61, 0x6d, 0x20, 0x74, 0x61, 0x69, 0x6c, 0x3d, 0x31, 0x20,
-      0x6c, 0x69, 0x64, 0x73, 0x3d, 0x30, 0x2c, 0x32, 0x2c, 0x33, 0x2c, 0x34,
-      0x2c, 0x37, 0x28, 0xdb, 0xe6, 0x9b, 0xfb, 0xeb, 0xdb, 0xa5, 0xbc, 0x15,
-      0x08, 0x00, 0x10, 0xb5, 0x58, 0x18, 0xb5, 0x58, 0x20, 0x00, 0x18, 0x8f,
-      0x4e, 0x0a, 0xf4, 0x0a, 0x40, 0xb2, 0x84, 0xde, 0xdd, 0x8f, 0x55, 0xba,
-      0x02, 0xe4, 0x8a, 0x80, 0x00, 0x0a, 0xe4, 0x80, 0x80, 0x00, 0x38, 0x04,
-      0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74,
-      0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x38, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f,
-      0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x63, 0x6c,
-      0x6e, 0x74, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x34, 0x20, 0x63, 0x6f,
-      0x6e, 0x6e, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x37, 0x32, 0x31, 0x64, 0x61,
-      0x30, 0x37, 0x31, 0x30, 0x30, 0x0a, 0x28, 0x92, 0xad, 0xf6, 0xf0, 0xbd,
-      0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06,
-      0x20, 0x00, 0x0a, 0xf3, 0x80, 0x80, 0x00, 0x38, 0x06, 0x32, 0x0b, 0x72,
-      0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x4e,
-      0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f,
-      0x72, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x77, 0x5f, 0x69, 0x6f, 0x76, 0x65,
-      0x63, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20,
-      0x69, 0x6f, 0x76, 0x65, 0x63, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
-      0x74, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x66,
-      0x6f, 0x72, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64,
-      0x65, 0x6d, 0x5f, 0x66, 0x73, 0x63, 0x28, 0x9e, 0xa1, 0xea, 0xf0, 0xbd,
-      0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x07, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06,
-      0x20, 0x00, 0x0a, 0xfd, 0x80, 0x80, 0x00, 0x38, 0x06, 0x32, 0x0b, 0x72,
-      0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x58,
-      0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f,
-      0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
-      0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x43, 0x61, 0x6c, 0x6c,
-      0x69, 0x6e, 0x67, 0x20, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x5b, 0x6f,
-      0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x30, 0x2c, 0x20, 0x73, 0x69, 0x7a,
-      0x65, 0x3d, 0x36, 0x35, 0x35, 0x33, 0x36, 0x5d, 0x66, 0x6f, 0x72, 0x20,
-      0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f,
-      0x66, 0x73, 0x63, 0x21, 0x28, 0xe6, 0xc4, 0x80, 0xf1, 0xbd, 0xdc, 0xa5,
-      0xbc, 0x15, 0x08, 0x07, 0x10, 0xf6, 0x0b, 0x18, 0xf6, 0x0b, 0x20, 0x00,
-      0x0a, 0x80, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e,
-      0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72,
-      0x61, 0x67, 0x65, 0x42, 0x54, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f,
-      0x72, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x77, 0x5f, 0x69, 0x6f, 0x76, 0x65,
-      0x63, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f,
-      0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x63, 0x3a, 0x20, 0x72,
-      0x65, 0x71, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x34, 0x20, 0x6d, 0x73,
-      0x67, 0x5f, 0x69, 0x64, 0x3d, 0x33, 0x3a, 0x20, 0x52, 0x2f, 0x57, 0x20,
-      0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x63, 0x65,
-      0x69, 0x76, 0x65, 0x64, 0x0a, 0x28, 0xc3, 0xe0, 0xf9, 0xf0, 0xbd, 0xdc,
-      0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06, 0x20,
-      0x00, 0x0a, 0xc1, 0x80, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65,
-      0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f,
-      0x72, 0x61, 0x67, 0x65, 0x42, 0x15, 0x77, 0x61, 0x6b, 0x65, 0x6c, 0x6f,
-      0x63, 0x6b, 0x20, 0x61, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x3a,
-      0x20, 0x31, 0x0a, 0x28, 0xb4, 0xc7, 0x8a, 0xf1, 0xbd, 0xdc, 0xa5, 0xbc,
-      0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06, 0x20, 0x00, 0x0a,
-      0x84, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64,
-      0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61,
-      0x67, 0x65, 0x42, 0x58, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72,
-      0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74,
-      0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74,
-      0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x63, 0x3a, 0x20,
-      0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x77, 0x6f, 0x72, 0x6b,
-      0x65, 0x72, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x28, 0x74,
-      0x68, 0x5f, 0x69, 0x64, 0x3a, 0x20, 0x34, 0x39, 0x30, 0x31, 0x31, 0x34,
-      0x39, 0x35, 0x34, 0x34, 0x36, 0x34, 0x29, 0x0a, 0x28, 0x8e, 0xe0, 0x8e,
-      0xf1, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18,
-      0xf6, 0x0b, 0x20, 0x00, 0x0a, 0x83, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32,
-      0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f,
-      0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x57, 0x72, 0x6d, 0x74,
-      0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69,
-      0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20,
-      0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f,
-      0x66, 0x73, 0x63, 0x3a, 0x20, 0x72, 0x65, 0x71, 0x5f, 0x68, 0x3d, 0x30,
-      0x78, 0x31, 0x34, 0x20, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x3d, 0x33,
-      0x3a, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x77, 0x72, 0x69, 0x74,
-      0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x36, 0x35, 0x35, 0x33, 0x36, 0x0a,
-      0x28, 0x8a, 0xe1, 0xa0, 0xf2, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00,
-      0x10, 0xe9, 0x06, 0x18, 0xf6, 0x0b, 0x20, 0x00, 0x0a, 0x88, 0x81, 0x80,
-      0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e,
-      0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42,
-      0x5c, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
-      0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65,
-      0x61, 0x64, 0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f,
-      0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x63, 0x3a, 0x20, 0x72, 0x65, 0x71,
-      0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x34, 0x20, 0x6d, 0x73, 0x67, 0x5f,
-      0x69, 0x64, 0x3d, 0x33, 0x3a, 0x20, 0x53, 0x65, 0x6e, 0x64, 0x20, 0x72,
-      0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x3a, 0x20, 0x72, 0x65, 0x73,
-      0x3d, 0x30, 0x20, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x0a, 0x28, 0xf8, 0x89,
-      0xa2, 0xf2, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06,
-      0x18, 0xf6, 0x0b, 0x20, 0x00, 0x0a, 0xae, 0x81, 0x80, 0x00, 0x38, 0x04,
-      0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74,
-      0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x81, 0x01, 0x72,
-      0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63,
-      0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
-      0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65,
-      0x6d, 0x5f, 0x66, 0x73, 0x63, 0x3a, 0x20, 0x41, 0x62, 0x6f, 0x75, 0x74,
-      0x20, 0x74, 0x6f, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6c,
-      0x69, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20,
-      0x28, 0x74, 0x68, 0x5f, 0x69, 0x64, 0x3a, 0x20, 0x34, 0x39, 0x30, 0x31,
-      0x31, 0x34, 0x39, 0x35, 0x34, 0x34, 0x36, 0x34, 0x29, 0x20, 0x77, 0x61,
-      0x6b, 0x65, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x61,
-      0x73, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x0a, 0x0a, 0x28, 0xb9, 0xcb, 0xa9,
-      0xf2, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18,
-      0xf6, 0x0b, 0x20, 0x00, 0x0a, 0xf4, 0x80, 0x80, 0x00, 0x38, 0x06, 0x32,
-      0x0b, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
-      0x42, 0x4f, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x72, 0x6d, 0x74, 0x5f, 0x73,
-      0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
-      0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x44, 0x6f,
-      0x6e, 0x65, 0x20, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x28, 0x62, 0x79,
-      0x74, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x36, 0x35, 0x35, 0x33, 0x36, 0x29,
-      0x20, 0x66, 0x6f, 0x72, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d,
-      0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x63, 0x21, 0x28, 0xd6, 0xbd,
-      0x8f, 0xf2, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x07, 0x10, 0xf6, 0x0b,
-      0x18, 0xf6, 0x0b, 0x20, 0x00, 0x0a, 0xe7, 0x80, 0x80, 0x00, 0x38, 0x04,
-      0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74,
-      0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x3b, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69,
-      0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x62, 0x3a,
-      0x20, 0x63, 0x6c, 0x6e, 0x74, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x34,
-      0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x37, 0x32,
-      0x31, 0x64, 0x61, 0x30, 0x37, 0x31, 0x30, 0x30, 0x0a, 0x28, 0x92, 0xd5,
-      0xc7, 0xf2, 0xbd, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06,
-      0x18, 0xe9, 0x06, 0x20, 0x00, 0x18, 0x8f, 0x4e, 0x0a, 0x70, 0x40, 0x92,
-      0xaf, 0xd5, 0x8d, 0x90, 0x55, 0xba, 0x02, 0xe0, 0x80, 0x80, 0x00, 0x0a,
-      0xdb, 0x80, 0x80, 0x00, 0x38, 0x04, 0x32, 0x08, 0x70, 0x65, 0x72, 0x66,
-      0x65, 0x74, 0x74, 0x6f, 0x42, 0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-      0x64, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73,
-      0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x63, 0x63, 0x3a, 0x32, 0x39, 0x31,
-      0x20, 0x53, 0x65, 0x65, 0x6e, 0x20, 0x31, 0x31, 0x20, 0x41, 0x6e, 0x64,
-      0x72, 0x6f, 0x69, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x65, 0x76, 0x65,
-      0x6e, 0x74, 0x73, 0x28, 0xd0, 0x8f, 0xfa, 0xf4, 0xbd, 0xdc, 0xa5, 0xbc,
-      0x15, 0x08, 0x00, 0x10, 0xb5, 0x58, 0x18, 0xb5, 0x58, 0x20, 0x00, 0x18,
-      0x8f, 0x4e, 0x0a, 0xfa, 0x0a, 0x40, 0x9c, 0xc7, 0xf8, 0xbc, 0x90, 0x55,
-      0xba, 0x02, 0xea, 0x8a, 0x80, 0x00, 0x0a, 0xe4, 0x80, 0x80, 0x00, 0x38,
-      0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x38, 0x72,
-      0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63,
-      0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x63,
-      0x6c, 0x6e, 0x74, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x35, 0x20, 0x63,
-      0x6f, 0x6e, 0x6e, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x37, 0x32, 0x31, 0x64,
-      0x61, 0x30, 0x37, 0x31, 0x30, 0x30, 0x0a, 0x28, 0xb4, 0xa2, 0x8b, 0xa5,
-      0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9,
-      0x06, 0x20, 0x00, 0x0a, 0x80, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12,
-      0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73,
-      0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x54, 0x72, 0x6d, 0x74, 0x5f,
-      0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x77, 0x5f, 0x69,
-      0x6f, 0x76, 0x65, 0x63, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x2f, 0x62, 0x6f,
-      0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31,
-      0x3a, 0x20, 0x72, 0x65, 0x71, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x35,
-      0x20, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x3d, 0x33, 0x3a, 0x20, 0x52,
-      0x2f, 0x57, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x72,
-      0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x0a, 0x28, 0x87, 0xf1, 0x8e,
-      0xa5, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18,
-      0xe9, 0x06, 0x20, 0x00, 0x0a, 0xc1, 0x80, 0x80, 0x00, 0x38, 0x04, 0x32,
-      0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f,
-      0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x15, 0x77, 0x61, 0x6b,
-      0x65, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x63, 0x71, 0x75, 0x69, 0x72,
-      0x65, 0x64, 0x3a, 0x20, 0x31, 0x0a, 0x28, 0x8e, 0x8e, 0x9e, 0xa5, 0xbe,
-      0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06,
-      0x20, 0x00, 0x0a, 0x84, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76,
-      0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74,
-      0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x58, 0x72, 0x6d, 0x74, 0x5f, 0x73,
-      0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
-      0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x2f, 0x62,
-      0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73,
-      0x31, 0x3a, 0x20, 0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x77,
-      0x6f, 0x72, 0x6b, 0x65, 0x72, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
-      0x20, 0x28, 0x74, 0x68, 0x5f, 0x69, 0x64, 0x3a, 0x20, 0x34, 0x39, 0x30,
-      0x31, 0x32, 0x38, 0x37, 0x30, 0x30, 0x36, 0x34, 0x30, 0x29, 0x0a, 0x28,
-      0x9a, 0xa4, 0xa1, 0xa5, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10,
-      0xe9, 0x06, 0x18, 0xf1, 0x0b, 0x20, 0x00, 0x0a, 0xf3, 0x80, 0x80, 0x00,
-      0x38, 0x06, 0x32, 0x0b, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72,
-      0x61, 0x67, 0x65, 0x42, 0x4e, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x77,
-      0x5f, 0x69, 0x6f, 0x76, 0x65, 0x63, 0x5f, 0x63, 0x62, 0x3a, 0x20, 0x57,
-      0x72, 0x69, 0x74, 0x65, 0x20, 0x69, 0x6f, 0x76, 0x65, 0x63, 0x20, 0x72,
-      0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69,
-      0x76, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2f, 0x62, 0x6f, 0x6f,
-      0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31, 0x28,
-      0x8e, 0xb1, 0xff, 0xa4, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x07, 0x10,
-      0xe9, 0x06, 0x18, 0xe9, 0x06, 0x20, 0x00, 0x0a, 0xff, 0x80, 0x80, 0x00,
-      0x38, 0x06, 0x32, 0x0b, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72,
-      0x61, 0x67, 0x65, 0x42, 0x5a, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x72, 0x6d,
-      0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c,
-      0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a,
-      0x20, 0x43, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x72, 0x69,
-      0x74, 0x65, 0x20, 0x5b, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x30,
-      0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x32, 0x30, 0x39, 0x37, 0x31,
-      0x35, 0x32, 0x5d, 0x66, 0x6f, 0x72, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74,
-      0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31, 0x21, 0x28,
-      0xe6, 0xae, 0x92, 0xa5, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x07, 0x10,
-      0xf1, 0x0b, 0x18, 0xf1, 0x0b, 0x20, 0x00, 0x0a, 0x85, 0x81, 0x80, 0x00,
-      0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72,
-      0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x59,
-      0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f,
-      0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61,
-      0x64, 0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64,
-      0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31, 0x3a, 0x20, 0x72, 0x65, 0x71, 0x5f,
-      0x68, 0x3d, 0x30, 0x78, 0x31, 0x35, 0x20, 0x6d, 0x73, 0x67, 0x5f, 0x69,
-      0x64, 0x3d, 0x33, 0x3a, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x77,
-      0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x32, 0x30, 0x39,
-      0x37, 0x31, 0x35, 0x32, 0x0a, 0x28, 0x96, 0x87, 0xd7, 0xb3, 0xbe, 0xdc,
-      0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xf1, 0x0b, 0x20,
-      0x00, 0x0a, 0x88, 0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65,
-      0x6e, 0x64, 0x6f, 0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f,
-      0x72, 0x61, 0x67, 0x65, 0x42, 0x5c, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74,
-      0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
-      0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x2f, 0x62, 0x6f,
-      0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31,
-      0x3a, 0x20, 0x72, 0x65, 0x71, 0x5f, 0x68, 0x3d, 0x30, 0x78, 0x31, 0x35,
-      0x20, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x3d, 0x33, 0x3a, 0x20, 0x53,
-      0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-      0x3a, 0x20, 0x72, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x65, 0x72, 0x72, 0x3d,
-      0x30, 0x0a, 0x28, 0xda, 0xb3, 0xd8, 0xb3, 0xbe, 0xdc, 0xa5, 0xbc, 0x15,
-      0x08, 0x00, 0x10, 0xe9, 0x06, 0x18, 0xf1, 0x0b, 0x20, 0x00, 0x0a, 0xae,
-      0x81, 0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f,
-      0x72, 0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
-      0x65, 0x42, 0x81, 0x01, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72,
-      0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74,
-      0x68, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74,
-      0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f, 0x66, 0x73, 0x31, 0x3a, 0x20,
-      0x41, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x6c, 0x6f,
-      0x63, 0x6b, 0x20, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61,
-      0x67, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68,
-      0x72, 0x65, 0x61, 0x64, 0x20, 0x28, 0x74, 0x68, 0x5f, 0x69, 0x64, 0x3a,
-      0x20, 0x34, 0x39, 0x30, 0x31, 0x32, 0x38, 0x37, 0x30, 0x30, 0x36, 0x34,
-      0x30, 0x29, 0x20, 0x77, 0x61, 0x6b, 0x65, 0x6c, 0x6f, 0x63, 0x6b, 0x20,
-      0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x0a,
-      0x0a, 0x28, 0xe4, 0xa2, 0xe0, 0xb3, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08,
-      0x00, 0x10, 0xe9, 0x06, 0x18, 0xf1, 0x0b, 0x20, 0x00, 0x0a, 0xe7, 0x80,
-      0x80, 0x00, 0x38, 0x04, 0x32, 0x12, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72,
-      0x2e, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
-      0x42, 0x3b, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
-      0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
-      0x5f, 0x63, 0x62, 0x3a, 0x20, 0x63, 0x6c, 0x6e, 0x74, 0x5f, 0x68, 0x3d,
-      0x30, 0x78, 0x31, 0x35, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x5f, 0x68, 0x3d,
-      0x30, 0x78, 0x37, 0x32, 0x31, 0x64, 0x61, 0x30, 0x37, 0x31, 0x30, 0x30,
-      0x0a, 0x28, 0xeb, 0xea, 0x8f, 0xb4, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08,
-      0x00, 0x10, 0xe9, 0x06, 0x18, 0xe9, 0x06, 0x20, 0x00, 0x0a, 0xf6, 0x80,
-      0x80, 0x00, 0x38, 0x06, 0x32, 0x0b, 0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74,
-      0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x51, 0x49, 0x4e, 0x46, 0x4f, 0x3a,
-      0x72, 0x6d, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f,
-      0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61,
-      0x64, 0x3a, 0x20, 0x44, 0x6f, 0x6e, 0x65, 0x20, 0x57, 0x72, 0x69, 0x74,
-      0x65, 0x20, 0x28, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x32,
-      0x30, 0x39, 0x37, 0x31, 0x35, 0x32, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20,
-      0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x5f,
-      0x66, 0x73, 0x31, 0x21, 0x28, 0x9e, 0xa9, 0xc5, 0xb3, 0xbe, 0xdc, 0xa5,
-      0xbc, 0x15, 0x08, 0x07, 0x10, 0xf1, 0x0b, 0x18, 0xf1, 0x0b, 0x20, 0x00,
-      0x18, 0x8f, 0x4e, 0x0a, 0x70, 0x40, 0xd2, 0x9f, 0x8f, 0xed, 0x90, 0x55,
-      0xba, 0x02, 0xe0, 0x80, 0x80, 0x00, 0x0a, 0xdb, 0x80, 0x80, 0x00, 0x38,
-      0x04, 0x32, 0x08, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x42,
-      0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6f, 0x67,
-      0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-      0x2e, 0x63, 0x63, 0x3a, 0x32, 0x39, 0x31, 0x20, 0x53, 0x65, 0x65, 0x6e,
-      0x20, 0x31, 0x31, 0x20, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20,
-      0x6c, 0x6f, 0x67, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x28, 0xf4,
-      0x9d, 0x96, 0xd4, 0xbe, 0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xb5,
-      0x58, 0x18, 0xb5, 0x58, 0x20, 0x00, 0x18, 0x8f, 0x4e, 0x0a, 0x4e, 0x40,
-      0xfe, 0xf3, 0x83, 0xd1, 0x9e, 0x55, 0xba, 0x02, 0xbe, 0x80, 0x80, 0x00,
-      0x0a, 0xb9, 0x80, 0x80, 0x00, 0x38, 0x06, 0x32, 0x00, 0x42, 0x1f, 0x74,
-      0x75, 0x69, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x3a, 0x73, 0x75, 0x69, 0x73,
-      0x76, 0x63, 0x20, 0x20, 0x65, 0x78, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x72,
-      0x65, 0x61, 0x64, 0x79, 0x20, 0x30, 0x28, 0x9f, 0x92, 0xdf, 0xdf, 0xcc,
-      0xdc, 0xa5, 0xbc, 0x15, 0x08, 0x00, 0x10, 0xd9, 0x06, 0x18, 0xd9, 0x06,
-      0x20, 0x00, 0x18, 0x8f, 0x4e, 0x0a, 0x1b, 0x40, 0x9b, 0x83, 0xa7, 0xba,
-      0xba, 0x55, 0xba, 0x02, 0x8b, 0x80, 0x80, 0x00, 0x12, 0x86, 0x80, 0x80,
-      0x00, 0x08, 0x1a, 0x18, 0x00, 0x10, 0x00, 0x18, 0x8f, 0x4e};
-
-  static const uint8_t kFilterBytecode[]{
-      0x0b, 0x01, 0x00, 0x0b, 0x60, 0x13, 0x02, 0x19, 0x23, 0x08, 0x2b, 0x09,
-      0x33, 0x0f, 0x3b, 0x10, 0x41, 0x4b, 0x05, 0x51, 0x5b, 0x12, 0x63, 0x72,
-      0x69, 0x8b, 0x02, 0x21, 0x93, 0x02, 0x33, 0x9b, 0x02, 0x35, 0xa1, 0x02,
-      0xab, 0x02, 0x37, 0xb3, 0x02, 0x07, 0xbb, 0x02, 0x3e, 0xc3, 0x02, 0x3d,
-      0xca, 0x02, 0x02, 0xdb, 0x02, 0x1b, 0xe3, 0x02, 0x11, 0xeb, 0x02, 0x40,
-      0xf3, 0x02, 0x04, 0xfb, 0x02, 0x41, 0x83, 0x03, 0x34, 0x8b, 0x03, 0x42,
-      0x91, 0x03, 0x9b, 0x03, 0x43, 0xa3, 0x03, 0x46, 0xab, 0x03, 0x49, 0xb3,
-      0x03, 0x04, 0xbb, 0x03, 0x07, 0xc3, 0x03, 0x4b, 0xcb, 0x03, 0x4c, 0xd1,
-      0x03, 0xdb, 0x03, 0x73, 0xe3, 0x03, 0x5f, 0xeb, 0x03, 0x5b, 0xf3, 0x03,
-      0x4d, 0xfb, 0x03, 0x04, 0x83, 0x04, 0x5d, 0x8b, 0x04, 0x4e, 0x93, 0x04,
-      0x4f, 0x9b, 0x04, 0x50, 0xa3, 0x04, 0x51, 0xab, 0x04, 0x3c, 0xb3, 0x04,
-      0x0e, 0xbb, 0x04, 0x04, 0xc3, 0x04, 0x69, 0xcb, 0x04, 0x53, 0xd3, 0x04,
-      0x3c, 0xdb, 0x04, 0x04, 0xe3, 0x04, 0x56, 0xeb, 0x04, 0x58, 0xf3, 0x04,
-      0x5a, 0xa3, 0x38, 0x70, 0x00, 0x0b, 0x03, 0x13, 0x04, 0x19, 0x00, 0x0a,
-      0x03, 0x23, 0x04, 0x29, 0x00, 0x0a, 0x03, 0x00, 0x0b, 0x06, 0x11, 0x00,
-      0x0a, 0x0a, 0x5b, 0x07, 0x62, 0x03, 0x00, 0x0a, 0x04, 0x00, 0x0a, 0x02,
-      0x1b, 0x04, 0x00, 0x0b, 0x0a, 0x13, 0x0d, 0x1b, 0x0e, 0x21, 0x2b, 0x0e,
-      0x00, 0x0a, 0x0d, 0x73, 0x0b, 0x7a, 0x02, 0x00, 0x0a, 0x09, 0x53, 0x0c,
-      0x00, 0x0a, 0x02, 0x1b, 0x0c, 0x23, 0x0c, 0x2a, 0x04, 0x00, 0x0a, 0x05,
-      0x00, 0x0a, 0x02, 0x00, 0x0b, 0x07, 0x11, 0x00, 0x0b, 0x0e, 0x13, 0x0e,
-      0x1b, 0x11, 0x22, 0x02, 0x33, 0x0e, 0x39, 0x43, 0x0e, 0x49, 0x53, 0x0e,
-      0x00, 0x0a, 0x08, 0x00, 0x0a, 0x03, 0x23, 0x13, 0x2b, 0x15, 0x33, 0x20,
-      0x42, 0x05, 0x82, 0x01, 0x02, 0xa1, 0x01, 0xab, 0x01, 0x0e, 0xb2, 0x01,
-      0x02, 0xc3, 0x01, 0x16, 0xcb, 0x01, 0x0e, 0xd3, 0x01, 0x15, 0xdb, 0x01,
-      0x0e, 0xe3, 0x01, 0x07, 0xeb, 0x01, 0x1e, 0xf2, 0x01, 0x02, 0x83, 0x02,
-      0x1f, 0x8b, 0x02, 0x07, 0x91, 0x02, 0x9b, 0x02, 0x0e, 0xa1, 0x02, 0xb3,
-      0x02, 0x04, 0xbb, 0x02, 0x15, 0xc3, 0x02, 0x15, 0xcb, 0x02, 0x04, 0xd1,
-      0x02, 0xdb, 0x02, 0x15, 0xe2, 0x02, 0x03, 0x00, 0x0a, 0x07, 0x43, 0x14,
-      0x4a, 0x02, 0x5b, 0x13, 0x63, 0x13, 0x00, 0x0a, 0x02, 0x1b, 0x14, 0x23,
-      0x14, 0x2a, 0x04, 0x00, 0x09, 0x00, 0x0b, 0x17, 0x12, 0x0c, 0x73, 0x19,
-      0x7b, 0x1c, 0x83, 0x01, 0x1d, 0x8b, 0x01, 0x1b, 0x00, 0x0b, 0x0d, 0x13,
-      0x18, 0x00, 0x0a, 0x2e, 0x00, 0x0a, 0x03, 0x23, 0x1a, 0x2b, 0x1a, 0x33,
-      0x1b, 0x00, 0x0a, 0x09, 0x53, 0x07, 0x00, 0x0a, 0x07, 0x00, 0x09, 0x13,
-      0x1a, 0x00, 0x0a, 0x03, 0x23, 0x1a, 0x00, 0x0a, 0x03, 0x23, 0x0e, 0x2a,
-      0x02, 0x00, 0x0a, 0x0a, 0x00, 0x0a, 0x04, 0x32, 0x0a, 0x92, 0x01, 0x02,
-      0x00, 0x0b, 0x22, 0x13, 0x23, 0x1a, 0x03, 0x33, 0x04, 0x3b, 0x07, 0x42,
-      0x03, 0x5b, 0x15, 0x62, 0x03, 0x81, 0x01, 0x8b, 0x01, 0x32, 0x92, 0x01,
-      0x02, 0xa3, 0x01, 0x1b, 0xab, 0x01, 0x15, 0xb2, 0x01, 0x03, 0xcb, 0x01,
-      0x0d, 0xda, 0x01, 0x05, 0x83, 0x02, 0x15, 0x00, 0x09, 0x21, 0x00, 0x0b,
-      0x24, 0x12, 0x02, 0x00, 0x0a, 0x04, 0x32, 0x03, 0xa3, 0x06, 0x25, 0xab,
-      0x06, 0x0d, 0xb3, 0x06, 0x26, 0xbb, 0x06, 0x27, 0xc3, 0x06, 0x1b, 0xcb,
-      0x06, 0x28, 0xd3, 0x06, 0x07, 0xdb, 0x06, 0x2b, 0xe3, 0x06, 0x07, 0xeb,
-      0x06, 0x15, 0xf3, 0x06, 0x2a, 0xfb, 0x06, 0x2c, 0x83, 0x07, 0x0e, 0x8b,
-      0x07, 0x07, 0x93, 0x07, 0x15, 0x9b, 0x07, 0x2f, 0xc1, 0x3e, 0xcb, 0x3e,
-      0x30, 0xf9, 0xff, 0xff, 0xff, 0x07, 0x00, 0x0a, 0x03, 0x52, 0x02, 0x63,
-      0x15, 0x6a, 0x02, 0x00, 0x0a, 0x05, 0x33, 0x0e, 0x00, 0x0a, 0x04, 0x32,
-      0x03, 0x00, 0x0a, 0x02, 0x22, 0x02, 0x33, 0x29, 0x3a, 0x05, 0x6a, 0x0e,
-      0x00, 0x2a, 0x02, 0x00, 0x0a, 0x02, 0x1b, 0x0e, 0x22, 0x04, 0x00, 0x09,
-      0x1a, 0x02, 0x00, 0x0a, 0x0d, 0x7b, 0x2d, 0x83, 0x01, 0x2e, 0x8a, 0x01,
-      0x02, 0x00, 0x0a, 0x02, 0x1b, 0x0e, 0x21, 0x00, 0x0b, 0x0d, 0x11, 0x00,
-      0x09, 0xa3, 0x06, 0x0e, 0x00, 0x0a, 0x05, 0x33, 0x31, 0x00, 0x0a, 0x0e,
-      0x00, 0x09, 0x13, 0x0d, 0x19, 0x00, 0x09, 0x13, 0x34, 0x1a, 0x02, 0x00,
-      0x0a, 0x09, 0x00, 0x0b, 0x36, 0x12, 0x09, 0x5b, 0x0d, 0x00, 0x0a, 0x13,
-      0x00, 0x0b, 0x0e, 0x13, 0x07, 0x1b, 0x0e, 0x23, 0x11, 0x2b, 0x38, 0x32,
-      0x02, 0x00, 0x09, 0x13, 0x3b, 0x1a, 0x02, 0x2b, 0x39, 0x32, 0x09, 0x00,
-      0x0a, 0x03, 0x23, 0x3a, 0x2a, 0x02, 0x00, 0x0b, 0x04, 0x00, 0x0a, 0x06,
-      0x42, 0x02, 0x00, 0x0a, 0x06, 0x00, 0x0b, 0x07, 0x13, 0x04, 0x00, 0x0b,
-      0x3f, 0x13, 0x04, 0x00, 0x0a, 0x08, 0x4b, 0x07, 0x00, 0x0b, 0x07, 0x12,
-      0x02, 0x00, 0x0b, 0x0d, 0x12, 0x02, 0x00, 0x0a, 0x06, 0x3b, 0x0e, 0x42,
-      0x02, 0x00, 0x0b, 0x44, 0x12, 0x02, 0x00, 0x0b, 0x45, 0x13, 0x45, 0x00,
-      0x09, 0x13, 0x04, 0x1b, 0x0e, 0x00, 0x0b, 0x47, 0x13, 0x04, 0x19, 0x00,
-      0x0b, 0x48, 0x13, 0x0d, 0x1a, 0x03, 0x00, 0x0a, 0x03, 0x2a, 0x06, 0x00,
-      0x0a, 0x05, 0x33, 0x0e, 0x3b, 0x4a, 0x42, 0x08, 0x00, 0x0b, 0x0e, 0x13,
-      0x0e, 0x1b, 0x0e, 0x00, 0x09, 0x13, 0x1b, 0x23, 0x0e, 0x2a, 0x02, 0x3b,
-      0x0e, 0x43, 0x0e, 0x4b, 0x11, 0x00, 0x0b, 0x0d, 0x00, 0x0a, 0x08, 0x4b,
-      0x07, 0x82, 0x01, 0x05, 0x00, 0x0b, 0x0d, 0x13, 0x3c, 0x00, 0x0a, 0x06,
-      0x82, 0x01, 0x03, 0x9b, 0x01, 0x15, 0x00, 0x0b, 0x0e, 0x00, 0x09, 0x13,
-      0x52, 0x00, 0x0a, 0x0f, 0x00, 0x0a, 0x02, 0x1b, 0x54, 0x00, 0x09, 0x13,
-      0x55, 0x1b, 0x07, 0x00, 0x0a, 0x04, 0x2b, 0x07, 0x00, 0x0b, 0x04, 0x13,
-      0x11, 0x1b, 0x0d, 0x23, 0x57, 0x2b, 0x15, 0x00, 0x0a, 0x0b, 0x00, 0x0b,
-      0x59, 0x12, 0x02, 0x23, 0x0e, 0x00, 0x0b, 0x07, 0x00, 0x0a, 0x02, 0x1b,
-      0x0e, 0x00, 0x0a, 0x02, 0x1b, 0x5c, 0x00, 0x09, 0x13, 0x04, 0x00, 0x0a,
-      0x02, 0x1b, 0x5e, 0x00, 0x0a, 0x02, 0x1b, 0x0e, 0x23, 0x0e, 0x00, 0x0a,
-      0x02, 0x1b, 0x1b, 0x23, 0x11, 0x29, 0x33, 0x0d, 0x3b, 0x0e, 0x43, 0x3c,
-      0x00, 0x09, 0x13, 0x61, 0x19, 0x23, 0x57, 0x00, 0x0a, 0x02, 0x1b, 0x0e,
-      0x23, 0x1b, 0x5b, 0x0e, 0x63, 0x04, 0x6b, 0x0e, 0x73, 0x04, 0x7b, 0x04,
-      0x83, 0x01, 0x04, 0x8b, 0x01, 0x0d, 0x93, 0x01, 0x04, 0x9b, 0x01, 0x04,
-      0xa3, 0x01, 0x0d, 0xab, 0x01, 0x15, 0xb3, 0x01, 0x15, 0xbb, 0x01, 0x0e,
-      0xc3, 0x01, 0x15, 0xcb, 0x01, 0x15, 0xd3, 0x01, 0x15, 0xdb, 0x01, 0x0d,
-      0xe3, 0x01, 0x3c, 0xeb, 0x01, 0x04, 0xf3, 0x01, 0x3c, 0xfb, 0x01, 0x0d,
-      0x83, 0x02, 0x3c, 0x8b, 0x02, 0x1b, 0x93, 0x02, 0x3c, 0x9b, 0x02, 0x0d,
-      0xa3, 0x02, 0x04, 0xab, 0x02, 0x0e, 0xb3, 0x02, 0x0e, 0xbb, 0x02, 0x0e,
-      0xc3, 0x02, 0x04, 0xcb, 0x02, 0x0d, 0xd3, 0x02, 0x0d, 0xdb, 0x02, 0x07,
-      0xe3, 0x02, 0x04, 0xeb, 0x02, 0x1b, 0xf3, 0x02, 0x04, 0xfb, 0x02, 0x15,
-      0x83, 0x03, 0x0e, 0x8b, 0x03, 0x15, 0x93, 0x03, 0x1b, 0x9b, 0x03, 0x15,
-      0xa3, 0x03, 0x0d, 0xab, 0x03, 0x15, 0xb3, 0x03, 0x15, 0xbb, 0x03, 0x15,
-      0xc3, 0x03, 0x15, 0xcb, 0x03, 0x15, 0xd3, 0x03, 0x0e, 0xdb, 0x03, 0x0d,
-      0xe3, 0x03, 0x15, 0xeb, 0x03, 0x15, 0xf3, 0x03, 0x15, 0xfb, 0x03, 0x15,
-      0x83, 0x04, 0x15, 0x8b, 0x04, 0x04, 0x93, 0x04, 0x0e, 0x9b, 0x04, 0x0d,
-      0xa3, 0x04, 0x04, 0xab, 0x04, 0x04, 0xb3, 0x04, 0x04, 0xbb, 0x04, 0x0d,
-      0xc3, 0x04, 0x04, 0xcb, 0x04, 0x04, 0xd3, 0x04, 0x04, 0xdb, 0x04, 0x04,
-      0xe3, 0x04, 0x0e, 0xeb, 0x04, 0x07, 0xf3, 0x04, 0x07, 0xfb, 0x04, 0x62,
-      0x83, 0x05, 0x04, 0x8b, 0x05, 0x07, 0x93, 0x05, 0x11, 0x9b, 0x05, 0x0d,
-      0xa3, 0x05, 0x62, 0xab, 0x05, 0x0e, 0xb3, 0x05, 0x04, 0xbb, 0x05, 0x1b,
-      0xc3, 0x05, 0x04, 0xcb, 0x05, 0x15, 0xd3, 0x05, 0x15, 0xdb, 0x05, 0x11,
-      0xe3, 0x05, 0x0e, 0xeb, 0x05, 0x0e, 0xf3, 0x05, 0x1f, 0xfb, 0x05, 0x04,
-      0x83, 0x06, 0x15, 0x8b, 0x06, 0x0d, 0x93, 0x06, 0x0d, 0x9b, 0x06, 0x0d,
-      0xa3, 0x06, 0x3c, 0xab, 0x06, 0x3c, 0xb3, 0x06, 0x3c, 0xbb, 0x06, 0x3c,
-      0xc3, 0x06, 0x07, 0xcb, 0x06, 0x07, 0xd3, 0x06, 0x07, 0xdb, 0x06, 0x15,
-      0xe3, 0x06, 0x04, 0xeb, 0x06, 0x0e, 0xf3, 0x06, 0x07, 0xfb, 0x06, 0x04,
-      0x83, 0x07, 0x04, 0x8b, 0x07, 0x04, 0x93, 0x07, 0x0d, 0x9b, 0x07, 0x0d,
-      0xa3, 0x07, 0x0d, 0xab, 0x07, 0x0d, 0xb3, 0x07, 0x0d, 0xbb, 0x07, 0x0d,
-      0xc3, 0x07, 0x3c, 0xcb, 0x07, 0x04, 0xd3, 0x07, 0x0d, 0xdb, 0x07, 0x15,
-      0xe3, 0x07, 0x3c, 0xeb, 0x07, 0x3c, 0xf3, 0x07, 0x1b, 0x83, 0x08, 0x1b,
-      0x8b, 0x08, 0x3c, 0x93, 0x08, 0x0d, 0x9b, 0x08, 0x0d, 0xa3, 0x08, 0x04,
-      0xab, 0x08, 0x0e, 0xb3, 0x08, 0x07, 0xbb, 0x08, 0x57, 0xc3, 0x08, 0x07,
-      0xcb, 0x08, 0x04, 0xd3, 0x08, 0x07, 0xdb, 0x08, 0x11, 0xe3, 0x08, 0x1b,
-      0xeb, 0x08, 0x34, 0xf3, 0x08, 0x1f, 0xfb, 0x08, 0x0d, 0x83, 0x09, 0x0d,
-      0x8b, 0x09, 0x3c, 0x93, 0x09, 0x04, 0x9b, 0x09, 0x0e, 0xa3, 0x09, 0x04,
-      0xab, 0x09, 0x3c, 0xb3, 0x09, 0x04, 0xbb, 0x09, 0x3c, 0xc3, 0x09, 0x3c,
-      0xcb, 0x09, 0x04, 0xd3, 0x09, 0x1b, 0xdb, 0x09, 0x07, 0xe3, 0x09, 0x0d,
-      0xeb, 0x09, 0x04, 0xf3, 0x09, 0x04, 0xfb, 0x09, 0x04, 0x83, 0x0a, 0x04,
-      0x8b, 0x0a, 0x1b, 0x93, 0x0a, 0x1f, 0x9b, 0x0a, 0x11, 0xa3, 0x0a, 0x07,
-      0xab, 0x0a, 0x07, 0xb3, 0x0a, 0x0d, 0xbb, 0x0a, 0x11, 0xc3, 0x0a, 0x0d,
-      0xcb, 0x0a, 0x0d, 0xd3, 0x0a, 0x1b, 0xdb, 0x0a, 0x04, 0xe3, 0x0a, 0x1b,
-      0xeb, 0x0a, 0x0d, 0xf3, 0x0a, 0x3c, 0xfb, 0x0a, 0x0d, 0x83, 0x0b, 0x1b,
-      0x8b, 0x0b, 0x0d, 0x93, 0x0b, 0x3c, 0x9b, 0x0b, 0x3c, 0xa3, 0x0b, 0x3c,
-      0xab, 0x0b, 0x07, 0xb3, 0x0b, 0x0d, 0xbb, 0x0b, 0x11, 0xc3, 0x0b, 0x07,
-      0xcb, 0x0b, 0x0d, 0xd3, 0x0b, 0x0d, 0xdb, 0x0b, 0x04, 0xe3, 0x0b, 0x0d,
-      0xeb, 0x0b, 0x0d, 0xf3, 0x0b, 0x0e, 0xfb, 0x0b, 0x0e, 0x83, 0x0c, 0x04,
-      0x8b, 0x0c, 0x0e, 0x93, 0x0c, 0x0e, 0x9b, 0x0c, 0x0e, 0xa3, 0x0c, 0x0d,
-      0xab, 0x0c, 0x0d, 0xb3, 0x0c, 0x04, 0xbb, 0x0c, 0x07, 0xc3, 0x0c, 0x63,
-      0xcb, 0x0c, 0x0d, 0xd3, 0x0c, 0x0d, 0xdb, 0x0c, 0x1f, 0xe3, 0x0c, 0x3c,
-      0xeb, 0x0c, 0x0d, 0xf3, 0x0c, 0x0e, 0xfb, 0x0c, 0x04, 0x83, 0x0d, 0x04,
-      0x8b, 0x0d, 0x11, 0x93, 0x0d, 0x1f, 0x9b, 0x0d, 0x04, 0xa3, 0x0d, 0x0e,
-      0xab, 0x0d, 0x0d, 0xb3, 0x0d, 0x0d, 0xbb, 0x0d, 0x04, 0xc3, 0x0d, 0x04,
-      0xcb, 0x0d, 0x07, 0xd3, 0x0d, 0x04, 0xdb, 0x0d, 0x0d, 0xb3, 0x0e, 0x0d,
-      0xbb, 0x0e, 0x04, 0xc3, 0x0e, 0x1f, 0xcb, 0x0e, 0x1b, 0xd3, 0x0e, 0x0d,
-      0xdb, 0x0e, 0x07, 0xe3, 0x0e, 0x07, 0xeb, 0x0e, 0x04, 0xf3, 0x0e, 0x07,
-      0xfb, 0x0e, 0x07, 0x83, 0x0f, 0x04, 0x8b, 0x0f, 0x0e, 0x93, 0x0f, 0x04,
-      0x9b, 0x0f, 0x0d, 0xa3, 0x0f, 0x11, 0xab, 0x0f, 0x11, 0xb3, 0x0f, 0x3c,
-      0xbb, 0x0f, 0x1f, 0xc3, 0x0f, 0x11, 0xcb, 0x0f, 0x04, 0xd3, 0x0f, 0x04,
-      0xdb, 0x0f, 0x0d, 0xe3, 0x0f, 0x04, 0xeb, 0x0f, 0x3c, 0xf3, 0x0f, 0x0d,
-      0xfb, 0x0f, 0x11, 0x83, 0x10, 0x0d, 0x8b, 0x10, 0x04, 0x93, 0x10, 0x11,
-      0x9b, 0x10, 0x0d, 0xa3, 0x10, 0x04, 0xab, 0x10, 0x0d, 0xb3, 0x10, 0x0d,
-      0xbb, 0x10, 0x04, 0xc3, 0x10, 0x07, 0xcb, 0x10, 0x07, 0xd3, 0x10, 0x04,
-      0xdb, 0x10, 0x0d, 0xe3, 0x10, 0x0d, 0xeb, 0x10, 0x04, 0xf3, 0x10, 0x3c,
-      0xfb, 0x10, 0x0d, 0x83, 0x11, 0x04, 0x8b, 0x11, 0x0d, 0x93, 0x11, 0x0e,
-      0x9b, 0x11, 0x0e, 0xa3, 0x11, 0x0e, 0xab, 0x11, 0x0e, 0xb3, 0x11, 0x0e,
-      0xbb, 0x11, 0x0e, 0xc3, 0x11, 0x15, 0xcb, 0x11, 0x07, 0xd3, 0x11, 0x0d,
-      0xdb, 0x11, 0x0d, 0xe3, 0x11, 0x0d, 0xeb, 0x11, 0x3c, 0xf3, 0x11, 0x3c,
-      0xfb, 0x11, 0x0d, 0x83, 0x12, 0x15, 0x8b, 0x12, 0x07, 0x93, 0x12, 0x07,
-      0x9b, 0x12, 0x15, 0xa3, 0x12, 0x04, 0xab, 0x12, 0x04, 0xb3, 0x12, 0x07,
-      0xbb, 0x12, 0x07, 0xc3, 0x12, 0x0e, 0xcb, 0x12, 0x0e, 0xd3, 0x12, 0x0e,
-      0xdb, 0x12, 0x0d, 0xe3, 0x12, 0x3c, 0xeb, 0x12, 0x0d, 0xf3, 0x12, 0x3c,
-      0xfb, 0x12, 0x0e, 0x83, 0x13, 0x15, 0x8b, 0x13, 0x15, 0x93, 0x13, 0x15,
-      0x9b, 0x13, 0x0d, 0xa3, 0x13, 0x1b, 0xab, 0x13, 0x07, 0xb3, 0x13, 0x04,
-      0xbb, 0x13, 0x04, 0xc3, 0x13, 0x07, 0xcb, 0x13, 0x07, 0xd3, 0x13, 0x04,
-      0xdb, 0x13, 0x04, 0xe3, 0x13, 0x07, 0xeb, 0x13, 0x07, 0xf3, 0x13, 0x07,
-      0xfb, 0x13, 0x07, 0x83, 0x14, 0x15, 0x8b, 0x14, 0x15, 0x93, 0x14, 0x0e,
-      0x9b, 0x14, 0x04, 0xa3, 0x14, 0x04, 0xab, 0x14, 0x3c, 0xb3, 0x14, 0x04,
-      0xbb, 0x14, 0x64, 0xc3, 0x14, 0x07, 0xcb, 0x14, 0x15, 0xd3, 0x14, 0x0e,
-      0xdb, 0x14, 0x07, 0xe3, 0x14, 0x0e, 0xeb, 0x14, 0x0d, 0xf3, 0x14, 0x15,
-      0xfb, 0x14, 0x04, 0x83, 0x15, 0x0e, 0x8b, 0x15, 0x0e, 0x93, 0x15, 0x04,
-      0x9b, 0x15, 0x66, 0xa3, 0x15, 0x04, 0xab, 0x15, 0x07, 0xb3, 0x15, 0x0e,
-      0xbb, 0x15, 0x07, 0xc3, 0x15, 0x07, 0xcb, 0x15, 0x07, 0xd3, 0x15, 0x07,
-      0xdb, 0x15, 0x04, 0xe3, 0x15, 0x3c, 0xeb, 0x15, 0x67, 0xf3, 0x15, 0x07,
-      0xfb, 0x15, 0x04, 0x83, 0x16, 0x07, 0x8b, 0x16, 0x07, 0x93, 0x16, 0x04,
-      0x9b, 0x16, 0x11, 0xa3, 0x16, 0x68, 0xab, 0x16, 0x3c, 0xb3, 0x16, 0x07,
-      0x00, 0x0a, 0x10, 0x00, 0x0a, 0x14, 0x00, 0x09, 0x13, 0x65, 0x00, 0x09,
-      0x1a, 0x03, 0x00, 0x00, 0x09, 0x22, 0x03, 0x00, 0x0a, 0x0c, 0x00, 0x0b,
-      0x6a, 0x00, 0x0b, 0x6b, 0x00, 0x0a, 0x03, 0x23, 0x6c, 0x2b, 0x6e, 0x3b,
-      0x6d, 0x52, 0x02, 0x00, 0x09, 0x13, 0x6d, 0x1b, 0x6c, 0x23, 0x6e, 0x33,
-      0x6d, 0x43, 0x6f, 0x4b, 0x0e, 0x51, 0x00, 0x0a, 0x07, 0x49, 0x00, 0x09,
-      0x13, 0x0e, 0x29, 0x00, 0x09, 0x13, 0x66, 0x00, 0x0a, 0x04, 0x2b, 0x71,
-      0x00, 0x09, 0x13, 0x71, 0x1a, 0x04, 0x00, 0x0b, 0x0e, 0x13, 0x0e, 0x1b,
-      0x0e, 0x23, 0x07, 0x2b, 0x0e, 0x33, 0x07, 0x3b, 0x0e, 0x83, 0x01, 0x0e,
-      0x8b, 0x01, 0x0e, 0x93, 0x01, 0x0e, 0x9b, 0x01, 0x11, 0xa3, 0x01, 0x0e,
-      0xab, 0x01, 0x07, 0xb3, 0x01, 0x0e, 0xbb, 0x01, 0x04, 0xc3, 0x01, 0x07,
-      0xcb, 0x01, 0x0e, 0xd3, 0x01, 0x0e, 0x00, 0x5b, 0x74, 0x63, 0x75, 0xd1,
-      0x03, 0x00, 0x59, 0xf9, 0x01, 0xe9, 0x02, 0x00, 0x0b, 0x2d, 0x00, 0x89,
-      0x8c, 0xb0, 0x80, 0x08};
-
-  MessageFilter filt;
-  ASSERT_TRUE(
-      filt.LoadFilterBytecode(kFilterBytecode, sizeof(kFilterBytecode)));
-
-  // Pass the trace in input splitting it in slices of arbitrary size.
-  std::vector<MessageFilter::InputSlice> input_slices;
-  for (size_t i = 0; i < sizeof(kTraceData);) {
-    std::minstd_rand0 rnd_engine(0);
-    size_t slice_size = rnd_engine() % 4096;
-    slice_size = std::min(slice_size, sizeof(kTraceData) - i);
-    input_slices.emplace_back(
-        MessageFilter::InputSlice{kTraceData + i, slice_size});
-    i += slice_size;
-  }
-
-  auto filtered_data =
-      filt.FilterMessageFragments(input_slices.data(), input_slices.size());
-
-  EXPECT_GT(filtered_data.size, 0u);
-  EXPECT_LE(filtered_data.size, sizeof(kTraceData));
-
-  perfetto::protos::Trace original_trace;
-  ASSERT_TRUE(original_trace.ParseFromArray(kTraceData, sizeof(kTraceData)));
-
-  perfetto::protos::Trace filtered_trace;
-  ASSERT_TRUE(filtered_trace.ParseFromArray(
-      filtered_data.data.get(), static_cast<int>(filtered_data.size)));
-
-  // Check that the re-serialized traces are identical.
-  std::string original_ser = original_trace.SerializeAsString();
-  std::string filter_ser = filtered_trace.SerializeAsString();
-
-  EXPECT_EQ(filtered_trace.packet_size(), original_trace.packet_size());
-
-  // Don't use EXPECT_EQ, the string is too big. If this check fails, the gtest
-  // diffing algorithm will take several minutes to compute the diff.
-  // That would mistakenly look like a CI or timing-related issue as the gtest
-  // would fail due to timeout.
-  // If this check fails, use base::HexDump() to investigate.
-  EXPECT_TRUE(original_ser == filter_ser);
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/filtering/message_tokenizer.h b/src/protozero/filtering/message_tokenizer.h
deleted file mode 100644
index 124b461..0000000
--- a/src/protozero/filtering/message_tokenizer.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FILTERING_MESSAGE_TOKENIZER_H_
-#define SRC_PROTOZERO_FILTERING_MESSAGE_TOKENIZER_H_
-
-#include <stdint.h>
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace protozero {
-
-// A helper class for schema-less tokenizing of protobuf messages.
-// This class takes a stream of proto-encoded bytes, pushed one by one in input
-// via Push(octet), and returns a stream of tokens (each Push() call can return
-// 0 or 1 token).
-// A "token" contains metadata about a field, specifically: its ID, its wire
-// type and:
-//  - For varint and fixed32/64 fields: its payload.
-//  - For string and bytes fields: the length of its payload.
-//    In this case the caller is supposed to "eat" those N bytes before calling
-//    Push() again.
-// Note that this class cannot differentiate between a string/bytes field or
-// a submessage, because they are encoded in the same way. The caller is
-// supposed to know whether a field can be recursed into by just keep calling
-// Push() or is a string that should be skipped.
-// This is inline to allow the compiler to see through the Push method and
-// avoid a function call for each byte.
-class MessageTokenizer {
- public:
-  struct Token {
-    uint32_t field_id;  // 0 == not valid.
-    proto_utils::ProtoWireType type;
-
-    // For kLengthDelimited, |value| represent the length of the payload.
-    uint64_t value;
-
-    inline bool valid() const { return field_id != 0; }
-    bool operator==(const Token& o) const {
-      return field_id == o.field_id && type == o.type && value == o.value;
-    }
-  };
-
-  // Pushes a byte in input and returns a token, only when getting to the last
-  // byte of each field. Specifically:
-  // - For varint and fixed32 fields, the Token is returned after the last byte
-  //   of the numeric payload is pushed.
-  // - For length-delimited fields, this returns after the last byte of the
-  //   length is pushed (i.e. right before the payload starts). The caller is
-  //   expected to either skip the next |value| bytes (in the case of a string
-  //   or bytes fields) or keep calling Push, in the case of a submessage.
-  inline Token Push(uint8_t octet) {
-    using protozero::proto_utils::ProtoWireType;
-
-    // Parsing a fixed32/64 field is the only case where we don't have to do
-    // any varint decoding. This is why this block is before the remaining
-    // switch statement below (all the rest is a varint).
-    if (PERFETTO_UNLIKELY(state_ == kFixedIntValue)) {
-      PERFETTO_DCHECK(fixed_int_bits_ == 32 || fixed_int_bits_ == 64);
-      fixed_int_value_ |= static_cast<uint64_t>(octet) << fixed_int_shift_;
-      fixed_int_shift_ += 8;
-      if (fixed_int_shift_ < fixed_int_bits_)
-        return Token{};  // Intermediate byte of a fixed32/64.
-      auto wire_type = fixed_int_bits_ == 32 ? ProtoWireType::kFixed32
-                                             : ProtoWireType::kFixed64;
-      uint64_t fixed_int_value = fixed_int_value_;
-      fixed_int_value_ = fixed_int_shift_ = fixed_int_bits_ = 0;
-      state_ = kFieldPreamble;
-      return Token{field_id_, wire_type, fixed_int_value};
-    }
-
-    // At this point either we are: (i) parsing a field preamble; (ii) parsing a
-    // varint field paylod; (iii) parsing the length of a length-delimited
-    // field. In all cases, we need to decode a varint before proceeding.
-    varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
-    if (octet & 0x80) {
-      varint_shift_ += 7;
-      if (PERFETTO_UNLIKELY(varint_shift_ >= 64)) {
-        varint_shift_ = 0;
-        state_ = kInvalidVarInt;
-      }
-      return Token{};  // Still parsing a varint.
-    }
-
-    uint64_t varint = varint_;
-    varint_ = 0;
-    varint_shift_ = 0;
-
-    switch (state_) {
-      case kFieldPreamble: {
-        auto field_type = static_cast<uint32_t>(varint & 7u);  // 7 = 0..0111
-        field_id_ = static_cast<uint32_t>(varint >> 3);
-
-        // The field type is legit, now check it's well formed and within
-        // boundaries.
-        if (field_type == static_cast<uint32_t>(ProtoWireType::kVarInt)) {
-          state_ = kVarIntValue;
-        } else if (field_type ==
-                       static_cast<uint32_t>(ProtoWireType::kFixed32) ||
-                   field_type ==
-                       static_cast<uint32_t>(ProtoWireType::kFixed64)) {
-          state_ = kFixedIntValue;
-          fixed_int_shift_ = 0;
-          fixed_int_value_ = 0;
-          fixed_int_bits_ =
-              field_type == static_cast<uint32_t>(ProtoWireType::kFixed32) ? 32
-                                                                           : 64;
-        } else if (field_type ==
-                   static_cast<uint32_t>(ProtoWireType::kLengthDelimited)) {
-          state_ = kLenDelimited;
-        } else {
-          state_ = kInvalidFieldType;
-        }
-        return Token{};
-      }
-
-      case kVarIntValue: {
-        // Return the varint field payload and go back to the next field.
-        state_ = kFieldPreamble;
-        return Token{field_id_, ProtoWireType::kVarInt, varint};
-      }
-
-      case kLenDelimited: {
-        const auto payload_len = varint;
-        if (payload_len > protozero::proto_utils::kMaxMessageLength) {
-          state_ = kMessageTooBig;
-          return Token{};
-        }
-        state_ = kFieldPreamble;
-        // At this point the caller is expected to consume the next
-        // |payload_len| bytes.
-        return Token{field_id_, ProtoWireType::kLengthDelimited, payload_len};
-      }
-
-      case kFixedIntValue:
-        // Unreacheable because of the if before the switch.
-        PERFETTO_DCHECK(false);
-        break;
-
-      // Unrecoverable error states.
-      case kInvalidFieldType:
-      case kMessageTooBig:
-      case kInvalidVarInt:
-        break;
-    }  // switch(state_)
-
-    return Token{};  // Keep GCC happy.
-  }
-
-  // Returns true if the tokenizer FSM has reached quiescence (i.e. if we are
-  // NOT in the middle of parsing a field).
-  bool idle() const {
-    return state_ == kFieldPreamble && varint_shift_ == 0 &&
-           fixed_int_shift_ == 0;
-  }
-
-  // Only for reporting parser errors in the trace.
-  uint32_t state() const { return static_cast<uint32_t>(state_); }
-
- private:
-  enum State {
-    kFieldPreamble = 0,  // Parsing the varint for the field preamble.
-    kVarIntValue = 1,    // Parsing the payload of a varint field.
-    kFixedIntValue = 2,  // Parsing the payload of a fixed32/64 field.
-    kLenDelimited = 3,   // Parsing the length of a length-delimited field.
-
-    // Unrecoverable error states:
-    kInvalidFieldType = 4,  // Encountered an invalid field type.
-    kMessageTooBig = 5,     // Size of the length delimited message was too big.
-    kInvalidVarInt = 6,     // Varint larger than 64 bits.
-  };
-
-  State state_ = kFieldPreamble;
-  uint32_t field_id_ = 0;
-  uint64_t varint_ = 0;
-  uint32_t varint_shift_ = 0;
-  uint32_t fixed_int_shift_ = 0;
-  uint32_t fixed_int_bits_ = 0;
-  uint64_t fixed_int_value_ = 0;
-};
-
-}  // namespace protozero
-
-#endif  // SRC_PROTOZERO_FILTERING_MESSAGE_TOKENIZER_H_
diff --git a/src/protozero/filtering/message_tokenizer_unittest.cc b/src/protozero/filtering/message_tokenizer_unittest.cc
deleted file mode 100644
index 666c4cf..0000000
--- a/src/protozero/filtering/message_tokenizer_unittest.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/gtest_and_gmock.h"
-
-#include "perfetto/protozero/message.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/protozero/filtering/message_tokenizer.h"
-
-namespace protozero {
-
-using proto_utils::ProtoWireType;
-using ::testing::ElementsAre;
-using Token = MessageTokenizer::Token;
-
-// For ASSERT_THAT(ElementsAre(...))
-inline std::ostream& operator<<(std::ostream& stream, const Token& t) {
-  stream << "{" << t.field_id << ", ";
-  switch (t.type) {
-    case ProtoWireType::kVarInt:
-      stream << "varint, ";
-      break;
-    case ProtoWireType::kFixed32:
-      stream << "fixed32, ";
-      break;
-    case ProtoWireType::kFixed64:
-      stream << "fixed64, ";
-      break;
-    case ProtoWireType::kLengthDelimited:
-      stream << "lendelim, ";
-      break;
-    default:
-      stream << "???, ";
-      break;
-  }
-  stream << t.value << "}";
-  return stream;
-}
-
-namespace {
-
-TEST(MessageTokenizerTest, FlatMessage) {
-  HeapBuffered<Message> msg;
-  msg->AppendVarInt(/*field_id*/ 1, 42u);
-  msg->AppendVarInt(/*field_id*/ 1, 1000u);
-  msg->AppendVarInt(/*field_id*/ 2, 1000000000ull);
-  msg->AppendVarInt(/*field_id*/ 3, 0xFF001234DEADBEEFull);
-  msg->AppendString(/*field_id*/ 4, "foo");
-  msg->AppendFixed(/*field_id*/ 5, 0xFFAAFFFFu);
-  msg->AppendString(/*field_id*/ 4, "foobar");
-  msg->AppendFixed(/*field_id*/ 6, uint64_t(1ull << 63));
-  msg->AppendVarInt(/*field_id*/ 1000, 1001ull);
-  msg->AppendVarInt(/*field_id*/ 1000000, 1000001ull);
-  msg->AppendVarInt(/*field_id*/ 1 << 28, uint64_t(1ull << 63));
-
-  // Treat all len-delimited fields as strings/bytes and just eat their payload.
-  MessageTokenizer tokenizer;
-  std::vector<Token> tokens;
-  size_t eat_bytes = 0;
-  for (uint8_t octet : msg.SerializeAsArray()) {
-    if (eat_bytes > 0) {
-      --eat_bytes;
-      continue;
-    }
-    auto token = tokenizer.Push(octet);
-    if (token.valid())
-      tokens.emplace_back(token);
-    if (token.type == ProtoWireType::kLengthDelimited) {
-      ASSERT_EQ(eat_bytes, 0u);
-      eat_bytes = static_cast<size_t>(token.value);
-    }
-  }
-  EXPECT_TRUE(tokenizer.idle());
-  EXPECT_THAT(
-      tokens,
-      ElementsAre(
-          Token{1, ProtoWireType::kVarInt, 42u},
-          Token{1, ProtoWireType::kVarInt, 1000u},
-          Token{2, ProtoWireType::kVarInt, 1000000000ull},
-          Token{3, ProtoWireType::kVarInt, 0xFF001234DEADBEEFull},
-          Token{4, ProtoWireType::kLengthDelimited, 3},
-          Token{5, ProtoWireType::kFixed32, 0xFFAAFFFFu},
-          Token{4, ProtoWireType::kLengthDelimited, 6},
-          Token{6, ProtoWireType::kFixed64, uint64_t(1ull << 63)},
-          Token{1000, ProtoWireType::kVarInt, 1001ull},
-          Token{1000000, ProtoWireType::kVarInt, 1000001ull},
-          Token{1 << 28, ProtoWireType::kVarInt, uint64_t(1ull << 63)}));
-}
-
-TEST(MessageTokenizerTest, NestedMessage) {
-  HeapBuffered<Message> msg;
-  msg->AppendVarInt(/*field_id*/ 1, 101u);
-  {
-    auto* nested = msg->BeginNestedMessage<Message>(2);
-    nested->AppendVarInt(/*field_id*/ 3, 103u);
-    nested->AppendFixed(/*field_id*/ 4, 104u);
-    {
-      auto* nested2 = nested->BeginNestedMessage<Message>(5);
-      nested2->AppendVarInt(/*field_id*/ 6, 106u);
-      nested2->AppendFixed(/*field_id*/ 7, 107u);
-      nested2->Finalize();
-    }
-    nested->AppendFixed(/*field_id*/ 8, 0x42420000u);
-    nested->Finalize();
-  }
-  msg->AppendFixed(/*field_id*/ 9, uint64_t(1ull << 63));
-
-  // Tokenize the message. This treat all len delimited fields as submessage
-  // and test the recursion logic.
-  MessageTokenizer tokenizer;
-  std::vector<Token> tokens;
-  for (uint8_t octet : msg.SerializeAsArray()) {
-    auto token = tokenizer.Push(octet);
-    if (token.valid())
-      tokens.emplace_back(token);
-  }
-  EXPECT_TRUE(tokenizer.idle());
-  EXPECT_THAT(
-      tokens,
-      ElementsAre(Token{1, ProtoWireType::kVarInt, 101u},
-                  Token{2, ProtoWireType::kLengthDelimited, 24u},
-                  Token{3, ProtoWireType::kVarInt, 103u},
-                  Token{4, ProtoWireType::kFixed32, 104u},
-                  Token{5, ProtoWireType::kLengthDelimited, 7},
-                  Token{6, ProtoWireType::kVarInt, 106u},
-                  Token{7, ProtoWireType::kFixed32, 107u},
-                  Token{8, ProtoWireType::kFixed32, 0x42420000u},
-                  Token{9, ProtoWireType::kFixed64, uint64_t(1ull << 63)}));
-}
-
-TEST(MessageTokenizerTest, InvlidCases) {
-  {
-    // A very large varint.
-    MessageTokenizer tokenizer;
-    EXPECT_FALSE(tokenizer.Push(0x08).valid());
-    for (int i = 0; i < 14; ++i)
-      EXPECT_FALSE(tokenizer.Push(0xff).valid());
-    EXPECT_FALSE(tokenizer.Push(0x0).valid());
-    EXPECT_FALSE(tokenizer.idle());
-    EXPECT_EQ(tokenizer.state(), 6u);
-  }
-  {
-    // A very large string.
-    MessageTokenizer tokenizer;
-    EXPECT_FALSE(tokenizer.Push(0x0A).valid());
-    EXPECT_FALSE(tokenizer.Push(0xFF).valid());
-    EXPECT_FALSE(tokenizer.Push(0xFF).valid());
-    EXPECT_FALSE(tokenizer.Push(0xFF).valid());
-    EXPECT_FALSE(tokenizer.Push(0xFF).valid());
-    EXPECT_FALSE(tokenizer.Push(0x20).valid());
-    EXPECT_FALSE(tokenizer.idle());
-    EXPECT_EQ(tokenizer.state(), 5u);
-  }
-  {
-    // A field of unknown type (wire type = 0x3).
-    MessageTokenizer tokenizer;
-    EXPECT_FALSE(tokenizer.Push(0x0B).valid());
-    EXPECT_FALSE(tokenizer.Push(0).valid());
-    EXPECT_FALSE(tokenizer.Push(0).valid());
-    EXPECT_FALSE(tokenizer.idle());
-    EXPECT_EQ(tokenizer.state(), 4u);
-  }
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/message.cc b/src/protozero/message.cc
index e33601c..419f7f1 100644
--- a/src/protozero/message.cc
+++ b/src/protozero/message.cc
@@ -19,12 +19,10 @@
 #include <atomic>
 #include <type_traits>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/protozero/message_arena.h"
 #include "perfetto/protozero/message_handle.h"
 
-#if !PERFETTO_IS_LITTLE_ENDIAN()
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
 // The memcpy() for float and double below needs to be adjusted if we want to
 // support big endian CPUs. There doesn't seem to be a compelling need today.
 #error Unimplemented for big endian archs.
@@ -40,11 +38,14 @@
 
 }  // namespace
 
+// static
+constexpr uint32_t Message::kMaxNestingDepth;
+
 // Do NOT put any code in the constructor or use default initialization.
-// Use the Reset() method below instead.
+// Use the Reset() method below instead. See the header for the reason why.
 
 // This method is called to initialize both root and nested messages.
-void Message::Reset(ScatteredStreamWriter* stream_writer, MessageArena* arena) {
+void Message::Reset(ScatteredStreamWriter* stream_writer) {
 // Older versions of libstdcxx don't have is_trivially_constructible.
 #if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20170516
   static_assert(std::is_trivially_constructible<Message>::value,
@@ -53,12 +54,19 @@
 
   static_assert(std::is_trivially_destructible<Message>::value,
                 "Message must be trivially destructible");
+
+  static_assert(
+      sizeof(Message::nested_messages_arena_) >=
+          kMaxNestingDepth *
+              (sizeof(Message) - sizeof(Message::nested_messages_arena_)),
+      "Message::nested_messages_arena_ is too small");
+
   stream_writer_ = stream_writer;
-  arena_ = arena;
   size_ = 0;
   size_field_ = nullptr;
   size_already_written_ = 0;
   nested_message_ = nullptr;
+  nesting_depth_ = 0;
   finalized_ = false;
 #if PERFETTO_DCHECK_IS_ON()
   handle_ = nullptr;
@@ -139,7 +147,7 @@
   return size_;
 }
 
-Message* Message::BeginNestedMessageInternal(uint32_t field_id) {
+void Message::BeginNestedMessageInternal(uint32_t field_id, Message* message) {
   if (nested_message_)
     EndNestedMessage();
 
@@ -149,22 +157,20 @@
       proto_utils::MakeTagLengthDelimited(field_id), data);
   WriteToStream(data, data_end);
 
-  Message* message = arena_->NewMessage();
-  message->Reset(stream_writer_, arena_);
+  message->Reset(stream_writer_);
+  PERFETTO_CHECK(nesting_depth_ < kMaxNestingDepth);
+  message->nesting_depth_ = nesting_depth_ + 1;
 
   // The length of the nested message cannot be known upfront. So right now
   // just reserve the bytes to encode the size after the nested message is done.
   message->set_size_field(
       stream_writer_->ReserveBytes(proto_utils::kMessageLengthFieldSize));
   size_ += proto_utils::kMessageLengthFieldSize;
-
   nested_message_ = message;
-  return message;
 }
 
 void Message::EndNestedMessage() {
   size_ += nested_message_->Finalize();
-  arena_->DeleteLastMessage(nested_message_);
   nested_message_ = nullptr;
 }
 
diff --git a/src/protozero/message_arena.cc b/src/protozero/message_arena.cc
deleted file mode 100644
index 6e92cd0..0000000
--- a/src/protozero/message_arena.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/protozero/message_arena.h"
-
-#include <atomic>
-#include <type_traits>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/message_handle.h"
-
-namespace protozero {
-
-MessageArena::MessageArena() {
-  // The code below assumes that there is always at least one block.
-  blocks_.emplace_front();
-  static_assert(std::alignment_of<decltype(blocks_.back().storage[0])>::value >=
-                    alignof(Message),
-                "MessageArea's storage is not properly aligned");
-}
-
-MessageArena::~MessageArena() = default;
-
-Message* MessageArena::NewMessage() {
-  PERFETTO_DCHECK(!blocks_.empty());  // Should never become empty.
-
-  Block* block = &blocks_.back();
-  if (PERFETTO_UNLIKELY(block->entries >= Block::kCapacity)) {
-    blocks_.emplace_back();
-    block = &blocks_.back();
-  }
-  const auto idx = block->entries++;
-  void* storage = &block->storage[idx];
-  PERFETTO_ASAN_UNPOISON(storage, sizeof(Message));
-  return new (storage) Message();
-}
-
-void MessageArena::DeleteLastMessageInternal() {
-  PERFETTO_DCHECK(!blocks_.empty());  // Should never be empty, see below.
-  Block* block = &blocks_.back();
-  PERFETTO_DCHECK(block->entries > 0);
-
-  // This is the reason why there is no ~Message() call here.
-  // MessageArea::Reset() (see header) also relies on dtor being trivial.
-  static_assert(std::is_trivially_destructible<Message>::value,
-                "Message must be trivially destructible");
-
-  --block->entries;
-  PERFETTO_ASAN_POISON(&block->storage[block->entries], sizeof(Message));
-
-  // Don't remove the first block to avoid malloc/free calls when the root
-  // message is reset. Hitting the allocator all the times is a waste of time.
-  if (block->entries == 0 && blocks_.size() > 1) {
-    blocks_.pop_back();
-  }
-}
-
-}  // namespace protozero
diff --git a/src/protozero/message_handle_unittest.cc b/src/protozero/message_handle_unittest.cc
index 96c8600..7f0ee08 100644
--- a/src/protozero/message_handle_unittest.cc
+++ b/src/protozero/message_handle_unittest.cc
@@ -16,7 +16,7 @@
 
 #include "perfetto/protozero/message_handle.h"
 
-#include "perfetto/protozero/root_message.h"
+#include "perfetto/protozero/message.h"
 #include "test/gtest_and_gmock.h"
 
 namespace protozero {
@@ -24,7 +24,8 @@
 namespace {
 
 TEST(MessageHandleTest, MoveHandleSharedMessageDoesntFinalize) {
-  RootMessage<Message> message;
+  Message message;
+  message.Reset(nullptr);
 
   MessageHandle<Message> handle_1(&message);
   handle_1 = MessageHandle<Message>(&message);
diff --git a/src/protozero/message_unittest.cc b/src/protozero/message_unittest.cc
index a061ad9..d75dcd0 100644
--- a/src/protozero/message_unittest.cc
+++ b/src/protozero/message_unittest.cc
@@ -15,6 +15,7 @@
  */
 
 #include "perfetto/protozero/message.h"
+#include "perfetto/protozero/message_handle.h"
 
 #include <limits>
 #include <memory>
@@ -22,8 +23,6 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/root_message.h"
 #include "src/base/test/utils.h"
 #include "src/protozero/test/fake_scattered_buffer.h"
 #include "test/gtest_and_gmock.h"
@@ -39,7 +38,7 @@
 constexpr const char kEndWatermark[] = {'9', '8', '7', '6',
                                         'z', 'w', 'y', '\0'};
 
-class FakeRootMessage : public RootMessage<Message> {};
+class FakeRootMessage : public Message {};
 class FakeChildMessage : public Message {};
 
 uint32_t SimpleHash(const std::string& str) {
@@ -64,10 +63,7 @@
       EXPECT_STREQ(kStartWatermark, reinterpret_cast<char*>(mem.get()));
       EXPECT_STREQ(kEndWatermark,
                    reinterpret_cast<char*>(mem.get() + sizeof(kStartWatermark) +
-                                           sizeof(FakeRootMessage)));
-      FakeRootMessage* msg = reinterpret_cast<FakeRootMessage*>(
-          mem.get() + sizeof(kStartWatermark));
-      msg->~FakeRootMessage();
+                                           sizeof(Message)));
       mem.reset();
     }
     messages_.clear();
@@ -87,7 +83,7 @@
     memcpy(msg_start + sizeof(FakeRootMessage), kEndWatermark,
            sizeof(kEndWatermark));
     messages_.push_back(std::move(mem));
-    FakeRootMessage* msg = new (msg_start) FakeRootMessage();
+    FakeRootMessage* msg = reinterpret_cast<FakeRootMessage*>(msg_start);
     msg->Reset(stream_writer_.get());
     return msg;
   }
@@ -105,16 +101,14 @@
     return buffer_->GetBytesAsString(old_readback_pos, num_bytes);
   }
 
-  static void BuildNestedMessages(Message* msg,
-                                  uint32_t max_depth,
-                                  uint32_t depth = 0) {
+  static void BuildNestedMessages(Message* msg, uint32_t depth = 0) {
     for (uint32_t i = 1; i <= 128; ++i)
       msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes));
 
-    if (depth < max_depth) {
+    if (depth < Message::kMaxNestingDepth) {
       auto* nested_msg =
           msg->BeginNestedMessage<FakeChildMessage>(1 + depth * 10);
-      BuildNestedMessages(nested_msg, max_depth, depth + 1);
+      BuildNestedMessages(nested_msg, depth + 1);
     }
 
     for (uint32_t i = 129; i <= 256; ++i)
@@ -285,7 +279,7 @@
   std::vector<Message*> nested_msgs;
 
   Message* root_msg = NewMessage();
-  BuildNestedMessages(root_msg, /*max_depth=*/10);
+  BuildNestedMessages(root_msg);
   root_msg->Finalize();
 
   // The main point of this test is to stress the code paths and test for
@@ -297,24 +291,13 @@
   EXPECT_EQ(0xf9e32b65, buf_hash);
 }
 
-TEST_F(MessageTest, DeeplyNested) {
-  std::vector<Message*> nested_msgs;
-
-  Message* root_msg = NewMessage();
-  BuildNestedMessages(root_msg, /*max_depth=*/1000);
-  root_msg->Finalize();
-
-  std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
-  size_t buf_hash = SimpleHash(full_buf);
-  EXPECT_EQ(0xc0fde419, buf_hash);
-}
-
 TEST_F(MessageTest, DestructInvalidMessageHandle) {
   FakeRootMessage* msg = NewMessage();
-  EXPECT_DCHECK_DEATH({
-    MessageHandle<FakeRootMessage> handle(msg);
-    ResetMessage(msg);
-  });
+  EXPECT_DCHECK_DEATH(
+      {
+        MessageHandle<FakeRootMessage> handle(msg);
+        ResetMessage(msg);
+      });
 }
 
 TEST_F(MessageTest, MessageHandle) {
diff --git a/src/protozero/proto_decoder.cc b/src/protozero/proto_decoder.cc
index f83c91f..b606818 100644
--- a/src/protozero/proto_decoder.cc
+++ b/src/protozero/proto_decoder.cc
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <limits>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/proto_utils.h"
@@ -28,7 +27,7 @@
 
 using namespace proto_utils;
 
-#if !PERFETTO_IS_LITTLE_ENDIAN()
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
 #error Unimplemented for big endian archs.
 #endif
 
diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc
index 5f40a89..580e959 100644
--- a/src/protozero/proto_decoder_unittest.cc
+++ b/src/protozero/proto_decoder_unittest.cc
@@ -61,25 +61,29 @@
   const uint64_t data_size = 4096 + kPayloadSize;
   std::unique_ptr<uint8_t, perfetto::base::FreeDeleter> data(
       static_cast<uint8_t*>(malloc(data_size)));
-  StaticBuffered<Message> message(data.get(), data_size);
+
+  StaticBufferDelegate delegate(data.get(), data_size);
+  ScatteredStreamWriter writer(&delegate);
+  Message message;
+  message.Reset(&writer);
 
   // Append a valid field.
-  message->AppendVarInt(/*field_id=*/1, 11);
+  message.AppendVarInt(/*field_id=*/1, 11);
 
   // Append a very large field that will be skipped.
   uint8_t raw[10];
   uint8_t* wptr = raw;
   wptr = WriteVarInt(MakeTagLengthDelimited(2), wptr);
   wptr = WriteVarInt(kPayloadSize, wptr);
-  message->AppendRawProtoBytes(raw, static_cast<size_t>(wptr - raw));
+  message.AppendRawProtoBytes(raw, static_cast<size_t>(wptr - raw));
   const uint8_t padding[1024 * 128]{};
   for (size_t i = 0; i < kPayloadSize / sizeof(padding); i++)
-    message->AppendRawProtoBytes(padding, sizeof(padding));
+    message.AppendRawProtoBytes(padding, sizeof(padding));
 
   // Append another valid field.
-  message->AppendVarInt(/*field_id=*/3, 13);
+  message.AppendVarInt(/*field_id=*/3, 13);
 
-  ProtoDecoder decoder(data.get(), message.Finalize());
+  ProtoDecoder decoder(data.get(), static_cast<size_t>(writer.written()));
   Field field = decoder.ReadField();
   ASSERT_EQ(1u, field.id());
   ASSERT_EQ(11, field.as_int32());
@@ -93,10 +97,16 @@
 }
 
 TEST(ProtoDecoderTest, SingleRepeatedField) {
-  HeapBuffered<Message> message;
-  message->AppendVarInt(/*field_id=*/2, 10);
-  auto data = message.SerializeAsArray();
-  TypedProtoDecoder<2, true> tpd(data.data(), data.size());
+  Message message;
+  ScatteredHeapBuffer delegate(512, 512);
+  ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+  message.Reset(&writer);
+  message.AppendVarInt(/*field_id=*/2, 10);
+  delegate.AdjustUsedSizeOfCurrentSlice();
+  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);
   EXPECT_TRUE(it);
   EXPECT_EQ(it.field().as_int32(), 10);
@@ -127,11 +137,16 @@
 }
 
 TEST(ProtoDecoderTest, SingleRepeatedFieldWithExpansion) {
-  HeapBuffered<Message> message;
+  Message message;
+  ScatteredHeapBuffer delegate(512, 512);
+  ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+  message.Reset(&writer);
   for (int i = 0; i < 2000; i++) {
-    message->AppendVarInt(/*field_id=*/2, i);
+    message.AppendVarInt(/*field_id=*/2, i);
   }
-  auto data = message.SerializeAsArray();
+  std::vector<uint8_t> data = delegate.StitchSlices();
+
   TypedProtoDecoder<2, true> tpd(data.data(), data.size());
   auto it = tpd.GetRepeated<int32_t>(/*field_id=*/2);
   for (int i = 0; i < 2000; i++) {
@@ -151,20 +166,26 @@
 }
 
 TEST(ProtoDecoderTest, RepeatedFields) {
-  HeapBuffered<Message> message;
+  Message message;
+  ScatteredHeapBuffer delegate(512, 512);
+  ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+  message.Reset(&writer);
 
-  message->AppendVarInt(1, 10);
-  message->AppendVarInt(2, 20);
-  message->AppendVarInt(3, 30);
+  message.AppendVarInt(1, 10);
+  message.AppendVarInt(2, 20);
+  message.AppendVarInt(3, 30);
 
-  message->AppendVarInt(1, 11);
-  message->AppendVarInt(2, 21);
-  message->AppendVarInt(2, 22);
+  message.AppendVarInt(1, 11);
+  message.AppendVarInt(2, 21);
+  message.AppendVarInt(2, 22);
+
+  delegate.AdjustUsedSizeOfCurrentSlice();
+  auto used_range = delegate.slices()[0].GetUsedRange();
 
   // When iterating with the simple decoder we should just see fields in parsing
   // order.
-  auto data = message.SerializeAsArray();
-  ProtoDecoder decoder(data.data(), data.size());
+  ProtoDecoder decoder(used_range.begin, used_range.size());
   std::string fields_seen;
   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
     fields_seen +=
@@ -172,7 +193,7 @@
   }
   EXPECT_EQ(fields_seen, "1:10;2:20;3:30;1:11;2:21;2:22;");
 
-  TypedProtoDecoder<4, true> tpd(data.data(), data.size());
+  TypedProtoDecoder<4, true> tpd(used_range.begin, used_range.size());
 
   // When parsing with the one-shot decoder and querying the single field id, we
   // should see the last value for each of them, not the first one. This is the
@@ -536,14 +557,18 @@
 // This is a regression test for b/145339282 (DataSourceConfig.for_testing
 // having a very large ID == 268435455 until Android R).
 TEST(ProtoDecoderTest, SkipBigFieldIds) {
-  HeapBuffered<Message> message;
-  message->AppendVarInt(/*field_id=*/1, 11);
-  message->AppendVarInt(/*field_id=*/1000000, 0);  // Will be skipped
-  message->AppendVarInt(/*field_id=*/65535, 99);
-  message->AppendVarInt(/*field_id=*/268435455, 0);  // Will be skipped
-  message->AppendVarInt(/*field_id=*/2, 12);
-  message->AppendVarInt(/*field_id=*/2000000, 0);  // Will be skipped
-  auto data = message.SerializeAsArray();
+  Message message;
+  ScatteredHeapBuffer delegate(512, 512);
+  ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+  message.Reset(&writer);
+  message.AppendVarInt(/*field_id=*/1, 11);
+  message.AppendVarInt(/*field_id=*/1000000, 0);  // Will be skipped
+  message.AppendVarInt(/*field_id=*/65535, 99);
+  message.AppendVarInt(/*field_id=*/268435455, 0);  // Will be skipped
+  message.AppendVarInt(/*field_id=*/2, 12);
+  message.AppendVarInt(/*field_id=*/2000000, 0);  // Will be skipped
+  std::vector<uint8_t> data = delegate.StitchSlices();
 
   // Check the iterator-based ProtoDecoder.
   {
@@ -581,9 +606,13 @@
 // very big id. Test that we skip it and return an invalid field, instead of
 // geetting stuck in some loop.
 TEST(ProtoDecoderTest, OneBigFieldIdOnly) {
-  HeapBuffered<Message> message;
-  message->AppendVarInt(/*field_id=*/268435455, 0);
-  auto data = message.SerializeAsArray();
+  Message message;
+  ScatteredHeapBuffer delegate(512, 512);
+  ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+  message.Reset(&writer);
+  message.AppendVarInt(/*field_id=*/268435455, 0);
+  std::vector<uint8_t> data = delegate.StitchSlices();
 
   // Check the iterator-based ProtoDecoder.
   ProtoDecoder decoder(data.data(), data.size());
diff --git a/src/protozero/proto_utils_unittest.cc b/src/protozero/proto_utils_unittest.cc
index 1cd8082..9124490 100644
--- a/src/protozero/proto_utils_unittest.cc
+++ b/src/protozero/proto_utils_unittest.cc
@@ -217,7 +217,7 @@
   uint64_t value = static_cast<uint64_t>(-1);
   const uint8_t* res = ParseVarInt(&good[0], &good[sizeof(good)], &value);
   EXPECT_EQ(&good[sizeof(good)], res);
-  EXPECT_EQ(value, static_cast<uint64_t>(-1));
+  EXPECT_EQ(value, static_cast<uint64_t>(-1ULL));
 
   uint8_t bad[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    0xff, 0xff, 0xff, 0xff, 0x01};
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
index 164fb63..514393b 100644
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ b/src/protozero/protoc_plugin/cppgen_plugin.cc
@@ -153,10 +153,8 @@
   cc_printer.Print("#include \"perfetto/protozero/proto_decoder.h\"\n");
   cc_printer.Print("#include \"perfetto/protozero/scattered_heap_buffer.h\"\n");
   cc_printer.Print(kHeader);
-  cc_printer.Print("#if defined(__GNUC__) || defined(__clang__)\n");
   cc_printer.Print("#pragma GCC diagnostic push\n");
   cc_printer.Print("#pragma GCC diagnostic ignored \"-Wfloat-equal\"\n");
-  cc_printer.Print("#endif\n");
 
   // Generate includes for translated types of dependencies.
 
@@ -337,10 +335,8 @@
     h_printer.Print("}  // namespace $n$\n", "n", ns);
     cc_printer.Print("}  // namespace $n$\n", "n", ns);
   }
-  cc_printer.Print("#if defined(__GNUC__) || defined(__clang__)\n");
-  cc_printer.Print("#pragma GCC diagnostic pop\n");
-  cc_printer.Print("#endif\n");
 
+  cc_printer.Print("#pragma GCC diagnostic pop\n");
   h_printer.Print("\n#endif  // $g$\n", "g", include_guard);
 
   return true;
@@ -614,35 +610,24 @@
         }
       }
     } 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());
-
-      // Generate accessors for repeated message types in the .cc file so that
-      // the header doesn't depend on the full definition of all nested types.
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("int $n$_size() const;\n", "t", GetCppType(field, false), "n",
-                 field->lowercase_name());
-        p->Print("void clear_$n$();\n", "n", field->lowercase_name());
-        p->Print("$t$* add_$n$();\n", "t", GetCppType(field, false), "n",
-                 field->lowercase_name());
-      } else {  // Primitive type.
-        p->Print(
-            "int $n$_size() const { return static_cast<int>($n$_.size()); }\n",
-            "t", GetCppType(field, false), "n", field->lowercase_name());
-        p->Print("void clear_$n$() { $n$_.clear(); }\n", "n",
-                 field->lowercase_name());
+      p->Print("void clear_$n$() { $n$_.clear(); }\n", "n",
+               field->lowercase_name());
+      if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
         p->Print("void add_$n$($t$ value) { $n$_.emplace_back(value); }\n", "t",
                  GetCppType(field, false), "n", field->lowercase_name());
-        // TODO(primiano): this should be done only for TYPE_MESSAGE.
-        // Unfortuntely we didn't realize before and now we have a bunch of code
-        // that does: *msg->add_int_value() = 42 instead of
-        // msg->add_int_value(42).
-        p->Print(
-            "$t$* add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
-            "t", GetCppType(field, false), "n", field->lowercase_name());
       }
+      // TODO(primiano): this should be done only for TYPE_MESSAGE. Unfortuntely
+      // we didn't realize before and now we have a bunch of code that does:
+      // *msg->add_int_value() = 42 instead of msg->add_int_value(42).
+      p->Print("$t$* add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
+               "t", GetCppType(field, false), "n", field->lowercase_name());
     }
   }
   p->Outdent();
@@ -706,25 +691,6 @@
   p->Outdent();
   p->Print("\n}\n\n");
 
-  // Accessors for repeated message fields.
-  for (int i = 0; i < msg->field_count(); i++) {
-    const FieldDescriptor* field = msg->field(i);
-    if (field->options().lazy() || !field->is_repeated() ||
-        field->type() != TYPE_MESSAGE) {
-      continue;
-    }
-    p->Print(
-        "int $c$::$n$_size() const { return static_cast<int>($n$_.size()); }\n",
-        "c", full_name, "t", GetCppType(field, false), "n",
-        field->lowercase_name());
-    p->Print("void $c$::clear_$n$() { $n$_.clear(); }\n", "c", full_name, "n",
-             field->lowercase_name());
-    p->Print(
-        "$t$* $c$::add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
-        "c", full_name, "t", GetCppType(field, false), "n",
-        field->lowercase_name());
-  }
-
   std::string proto_type = GetFullName(msg, true);
 
   // Generate the ParseFromArray() method definition.
@@ -758,7 +724,7 @@
     } else {
       std::string statement;
       if (field->type() == TYPE_MESSAGE) {
-        statement = "$rval$.ParseFromArray(field.data(), field.size());\n";
+        statement = "$rval$.ParseFromString(field.as_std_string());\n";
       } else {
         if (field->type() == TYPE_SINT32 || field->type() == TYPE_SINT64) {
           // sint32/64 fields are special and need to be zig-zag-decoded.
diff --git a/src/protozero/protoc_plugin/protozero_plugin.cc b/src/protozero/protoc_plugin/protozero_plugin.cc
index 311672a..dd49d45 100644
--- a/src/protozero/protoc_plugin/protozero_plugin.cc
+++ b/src/protozero/protoc_plugin/protozero_plugin.cc
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-
 #include <limits>
 #include <map>
 #include <memory>
@@ -56,7 +54,7 @@
 
 void Assert(bool condition) {
   if (!condition)
-    abort();
+    __builtin_trap();
 }
 
 struct FileDescriptorComp {
@@ -99,8 +97,6 @@
       GenerateEnumDescriptor(enumeration);
     for (const Descriptor* message : messages_)
       GenerateMessageDescriptor(message);
-    for (const auto& key_value : extensions_)
-      GenerateExtension(key_value.first, key_value.second);
     GenerateEpilogue();
     return error_.empty();
   }
@@ -157,6 +153,20 @@
     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) {
@@ -229,138 +239,18 @@
     return "";
   }
 
-  const char* FieldToProtoSchemaType(const FieldDescriptor* field) {
-    switch (field->type()) {
-      case FieldDescriptor::TYPE_BOOL:
-        return "kBool";
-      case FieldDescriptor::TYPE_INT32:
-        return "kInt32";
-      case FieldDescriptor::TYPE_INT64:
-        return "kInt64";
-      case FieldDescriptor::TYPE_UINT32:
-        return "kUint32";
-      case FieldDescriptor::TYPE_UINT64:
-        return "kUint64";
-      case FieldDescriptor::TYPE_SINT32:
-        return "kSint32";
-      case FieldDescriptor::TYPE_SINT64:
-        return "kSint64";
-      case FieldDescriptor::TYPE_FIXED32:
-        return "kFixed32";
-      case FieldDescriptor::TYPE_FIXED64:
-        return "kFixed64";
-      case FieldDescriptor::TYPE_SFIXED32:
-        return "kSfixed32";
-      case FieldDescriptor::TYPE_SFIXED64:
-        return "kSfixed64";
-      case FieldDescriptor::TYPE_FLOAT:
-        return "kFloat";
-      case FieldDescriptor::TYPE_DOUBLE:
-        return "kDouble";
-      case FieldDescriptor::TYPE_ENUM:
-        return "kEnum";
-      case FieldDescriptor::TYPE_STRING:
-        return "kString";
-      case FieldDescriptor::TYPE_MESSAGE:
-        return "kMessage";
-      case FieldDescriptor::TYPE_BYTES:
-        return "kBytes";
-
-      case FieldDescriptor::TYPE_GROUP:
-        Abort("Groups not supported.");
-        return "";
-    }
-    Abort("Unrecognized FieldDescriptor::Type.");
-    return "";
-  }
-
-  std::string FieldToCppTypeName(const FieldDescriptor* field) {
-    switch (field->type()) {
-      case FieldDescriptor::TYPE_BOOL:
-        return "bool";
-      case FieldDescriptor::TYPE_INT32:
-        return "int32_t";
-      case FieldDescriptor::TYPE_INT64:
-        return "int64_t";
-      case FieldDescriptor::TYPE_UINT32:
-        return "uint32_t";
-      case FieldDescriptor::TYPE_UINT64:
-        return "uint64_t";
-      case FieldDescriptor::TYPE_SINT32:
-        return "int32_t";
-      case FieldDescriptor::TYPE_SINT64:
-        return "int64_t";
-      case FieldDescriptor::TYPE_FIXED32:
-        return "uint32_t";
-      case FieldDescriptor::TYPE_FIXED64:
-        return "uint64_t";
-      case FieldDescriptor::TYPE_SFIXED32:
-        return "int32_t";
-      case FieldDescriptor::TYPE_SFIXED64:
-        return "int64_t";
-      case FieldDescriptor::TYPE_FLOAT:
-        return "float";
-      case FieldDescriptor::TYPE_DOUBLE:
-        return "double";
-      case FieldDescriptor::TYPE_ENUM:
-        return GetCppClassName(field->enum_type(), true);
-      case FieldDescriptor::TYPE_STRING:
-      case FieldDescriptor::TYPE_BYTES:
-        return "std::string";
-      case FieldDescriptor::TYPE_MESSAGE:
-        return GetCppClassName(field->message_type());
-      case FieldDescriptor::TYPE_GROUP:
-        Abort("Groups not supported.");
-        return "";
-    }
-    Abort("Unrecognized FieldDescriptor::Type.");
-    return "";
-  }
-
-  const char* FieldToRepetitionType(const FieldDescriptor* field) {
-    if (!field->is_repeated())
-      return "kNotRepeated";
-    if (field->is_packed())
-      return "kRepeatedPacked";
-    return "kRepeatedNotPacked";
-  }
-
   void CollectDescriptors() {
     // Collect message descriptors in DFS order.
     std::vector<const Descriptor*> stack;
-    stack.reserve(static_cast<size_t>(source_->message_type_count()));
     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();
-
-      if (message->extension_count() > 0) {
-        if (message->field_count() > 0 || message->nested_type_count() > 0 ||
-            message->enum_type_count() > 0) {
-          Abort("message with extend blocks shouldn't contain anything else");
-        }
-
-        // Iterate over all fields in "extend" blocks.
-        for (int i = 0; i < message->extension_count(); ++i) {
-          const FieldDescriptor* extension = message->extension(i);
-
-          // Protoc plugin API does not group fields in "extend" blocks.
-          // As the support for extensions in protozero is limited, the code
-          // assumes that extend blocks are located inside a wrapper message and
-          // name of this message is used to group them.
-          std::string extension_name = extension->extension_scope()->name();
-          extensions_[extension_name].push_back(extension);
-        }
-      } else {
-        messages_.push_back(message);
-        for (int i = 0; i < message->nested_type_count(); ++i) {
-          stack.push_back(message->nested_type(i));
-          // Emit a forward declaration of nested message types, as the outer
-          // class will refer to them when creating type aliases.
-          referenced_messages_.insert(message->nested_type(i));
-        }
+      messages_.push_back(message);
+      for (int i = 0; i < message->nested_type_count(); ++i) {
+        stack.push_back(message->nested_type(i));
       }
     }
 
@@ -368,9 +258,6 @@
     for (int i = 0; i < source_->enum_type_count(); ++i)
       enums_.push_back(source_->enum_type(i));
 
-    if (source_->extension_count() > 0)
-      Abort("top-level extension blocks are not supported");
-
     for (const Descriptor* message : messages_) {
       for (int i = 0; i < message->enum_type_count(); ++i) {
         enums_.push_back(message->enum_type(i));
@@ -387,7 +274,7 @@
     if (source_->weak_dependency_count() > 0)
       Abort("Weak imports are not supported.");
 
-    // Validations. Collect public imports (of collected imports) in DFS order.
+    // 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).
@@ -414,8 +301,8 @@
     }
 
     // Collect descriptors of messages and enums used in current proto.
-    // It will be used to generate necessary forward declarations and
-    // check that everything lays in the same namespace.
+    // 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);
@@ -464,7 +351,6 @@
         "#define $guard$\n\n"
         "#include <stddef.h>\n"
         "#include <stdint.h>\n\n"
-        "#include \"perfetto/protozero/field_writer.h\"\n"
         "#include \"perfetto/protozero/message.h\"\n"
         "#include \"perfetto/protozero/packed_repeated_fields.h\"\n"
         "#include \"perfetto/protozero/proto_decoder.h\"\n"
@@ -543,15 +429,14 @@
   // 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->lowercase_name();
-    setter["field_metadata"] = GetFieldMetadataTypeName(field);
     setter["action"] = "set";
     setter["buffer_type"] = FieldTypeToPackedBufferType(field->type());
     stub_h_->Print(
         setter,
         "void $action$_$name$(const $buffer_type$& packed_buffer) {\n"
-        "  AppendBytes($field_metadata$::kFieldId, packed_buffer.data(),\n"
-        "              packed_buffer.size());\n"
+        "  AppendBytes($id$, packed_buffer.data(), packed_buffer.size());\n"
         "}\n");
   }
 
@@ -559,41 +444,110 @@
     std::map<std::string, std::string> setter;
     setter["id"] = std::to_string(field->number());
     setter["name"] = field->lowercase_name();
-    setter["field_metadata"] = GetFieldMetadataTypeName(field);
     setter["action"] = field->is_repeated() ? "add" : "set";
-    setter["cpp_type"] = FieldToCppTypeName(field);
-    setter["proto_field_type"] = FieldToProtoSchemaType(field);
 
+    std::string appender;
+    std::string cpp_type;
     const char* code_stub =
         "void $action$_$name$($cpp_type$ value) {\n"
-        "  static constexpr uint32_t field_id = $field_metadata$::kFieldId;\n"
-        "  // Call the appropriate protozero::Message::Append(field_id, ...)\n"
-        "  // method based on the type of the field.\n"
-        "  ::protozero::internal::FieldWriter<\n"
-        "    ::protozero::proto_utils::ProtoSchemaType::$proto_field_type$>\n"
-        "      ::Append(*this, field_id, value);\n"
+        "  $appender$($id$, value);\n"
         "}\n";
 
-    if (field->type() == FieldDescriptor::TYPE_STRING) {
-      // Strings and bytes should have an additional accessor which specifies
-      // the length explicitly.
-      const char* additional_method =
-          "void $action$_$name$(const char* data, size_t size) {\n"
-          "  AppendBytes($field_metadata$::kFieldId, data, size);\n"
-          "}\n";
-      stub_h_->Print(setter, additional_method);
-    } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
-      const char* additional_method =
-          "void $action$_$name$(const uint8_t* data, size_t size) {\n"
-          "  AppendBytes($field_metadata$::kFieldId, data, size);\n"
-          "}\n";
-      stub_h_->Print(setter, additional_method);
-    } else if (field->type() == FieldDescriptor::TYPE_GROUP ||
-               field->type() == FieldDescriptor::TYPE_MESSAGE) {
-      Abort("Unsupported field type.");
-      return;
+    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:
+      case FieldDescriptor::TYPE_BYTES: {
+        if (field->type() == FieldDescriptor::TYPE_STRING) {
+          cpp_type = "const char*";
+        } else {
+          cpp_type = "const uint8_t*";
+        }
+        code_stub =
+            "void $action$_$name$(const std::string& value) {\n"
+            "  AppendBytes($id$, value.data(), value.size());\n"
+            "}\n"
+            "void $action$_$name$($cpp_type$ data, size_t size) {\n"
+            "  AppendBytes($id$, data, size);\n"
+            "}\n";
+        break;
+      }
+      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, code_stub);
   }
 
@@ -810,115 +764,20 @@
 
     // Field descriptors.
     for (int i = 0; i < message->field_count(); ++i) {
-      GenerateFieldDescriptor(GetCppClassName(message), message->field(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");
   }
 
-  std::string GetFieldMetadataTypeName(const FieldDescriptor* field) {
-    std::string name = field->camelcase_name();
-    if (isalpha(name[0]))
-      name[0] = static_cast<char>(toupper(name[0]));
-    return "FieldMetadata_" + name;
-  }
-
-  std::string GetFieldMetadataVariableName(const FieldDescriptor* field) {
-    std::string name = field->camelcase_name();
-    if (isalpha(name[0]))
-      name[0] = static_cast<char>(toupper(name[0]));
-    return "k" + name;
-  }
-
-  void GenerateFieldMetadata(const std::string& message_cpp_type,
-                             const FieldDescriptor* field) {
-    const char* code_stub = R"(
-using $field_metadata_type$ =
-  ::protozero::proto_utils::FieldMetadata<
-    $field_id$,
-    ::protozero::proto_utils::RepetitionType::$repetition_type$,
-    ::protozero::proto_utils::ProtoSchemaType::$proto_field_type$,
-    $cpp_type$,
-    $message_cpp_type$>;
-
-// Ceci n'est pas une pipe.
-// This is actually a variable of FieldMetadataHelper<FieldMetadata<...>>
-// type (and users are expected to use it as such, hence kCamelCase name).
-// It is declared as a function to keep protozero bindings header-only as
-// inline constexpr variables are not available until C++17 (while inline
-// functions are).
-// TODO(altimin): Use inline variable instead after adopting C++17.  
-static constexpr $field_metadata_type$ $field_metadata_var$() { return {}; }
-)";
-
-    stub_h_->Print(code_stub, "field_id", std::to_string(field->number()),
-                   "repetition_type", FieldToRepetitionType(field),
-                   "proto_field_type", FieldToProtoSchemaType(field),
-                   "cpp_type", FieldToCppTypeName(field), "message_cpp_type",
-                   message_cpp_type, "field_metadata_type",
-                   GetFieldMetadataTypeName(field), "field_metadata_var",
-                   GetFieldMetadataVariableName(field));
-  }
-
-  void GenerateFieldDescriptor(const std::string& message_cpp_type,
-                               const FieldDescriptor* field) {
-    GenerateFieldMetadata(message_cpp_type, field);
-    if (field->is_packed()) {
-      GeneratePackedRepeatedFieldDescriptor(field);
-    } else if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
-      GenerateSimpleFieldDescriptor(field);
-    } else {
-      GenerateNestedMessageFieldDescriptor(field);
-    }
-  }
-
-  // Generate extension class for a group of FieldDescriptor instances
-  // representing one "extend" block in proto definition. For example:
-  //
-  //   message SpecificExtension {
-  //     extend GeneralThing {
-  //       optional Fizz fizz = 101;
-  //       optional Buzz buzz = 102;
-  //     }
-  //   }
-  //
-  // This is going to be passed as a vector of two elements, "fizz" and
-  // "buzz". Wrapping message is used to provide a name for generated
-  // extension class.
-  //
-  // In the example above, generated code is going to look like:
-  //
-  //   class SpecificExtension : public GeneralThing {
-  //     Fizz* set_fizz();
-  //     Buzz* set_buzz();
-  //   }
-  void GenerateExtension(
-      const std::string& extension_name,
-      const std::vector<const FieldDescriptor*>& descriptors) {
-    // Use an arbitrary descriptor in order to get generic information not
-    // specific to any of them.
-    const FieldDescriptor* descriptor = descriptors[0];
-    const Descriptor* base_message = descriptor->containing_type();
-
-    // TODO(ddrone): ensure that this code works when containing_type located in
-    // other file or namespace.
-    stub_h_->Print("class $name$ : public $extendee$ {\n", "name",
-                   extension_name, "extendee",
-                   GetCppClassName(base_message, /*full=*/true));
-    stub_h_->Print(" public:\n");
-    stub_h_->Indent();
-    for (const FieldDescriptor* field : descriptors) {
-      if (field->containing_type() != base_message) {
-        Abort("one wrapper should extend only one message");
-        return;
-      }
-      GenerateFieldDescriptor(extension_name, field);
-    }
-    stub_h_->Outdent();
-    stub_h_->Print("};\n");
-  }
-
   void GenerateEpilogue() {
     for (unsigned i = 0; i < namespaces_.size(); ++i) {
       stub_h_->Print("} // Namespace.\n");
@@ -936,7 +795,6 @@
   std::string full_namespace_prefix_;
   std::vector<const Descriptor*> messages_;
   std::vector<const EnumDescriptor*> enums_;
-  std::map<std::string, std::vector<const FieldDescriptor*>> extensions_;
 
   // The custom *Comp comparators are to ensure determinism of the generator.
   std::set<const FileDescriptor*, FileDescriptorComp> public_imports_;
diff --git a/src/protozero/scattered_heap_buffer.cc b/src/protozero/scattered_heap_buffer.cc
index e2fc9af..389c36e 100644
--- a/src/protozero/scattered_heap_buffer.cc
+++ b/src/protozero/scattered_heap_buffer.cc
@@ -69,21 +69,10 @@
   return slices_.back().GetTotalRange();
 }
 
-const std::vector<ScatteredHeapBuffer::Slice>&
-ScatteredHeapBuffer::GetSlices() {
-  AdjustUsedSizeOfCurrentSlice();
-  return slices_;
-}
-
 std::vector<uint8_t> ScatteredHeapBuffer::StitchSlices() {
-  size_t stitched_size = 0u;
-  const auto& slices = GetSlices();
-  for (const auto& slice : slices)
-    stitched_size += slice.size() - slice.unused_bytes();
-
+  AdjustUsedSizeOfCurrentSlice();
   std::vector<uint8_t> buffer;
-  buffer.reserve(stitched_size);
-  for (const auto& slice : slices) {
+  for (const auto& slice : slices_) {
     auto used_range = slice.GetUsedRange();
     buffer.insert(buffer.end(), used_range.begin, used_range.end);
   }
@@ -91,8 +80,9 @@
 }
 
 std::vector<protozero::ContiguousMemoryRange> ScatteredHeapBuffer::GetRanges() {
+  AdjustUsedSizeOfCurrentSlice();
   std::vector<protozero::ContiguousMemoryRange> ranges;
-  for (const auto& slice : GetSlices())
+  for (const auto& slice : slices_)
     ranges.push_back(slice.GetUsedRange());
   return ranges;
 }
diff --git a/src/protozero/test/example_proto/extensions.proto b/src/protozero/test/example_proto/extensions.proto
deleted file mode 100644
index bbc344d..0000000
--- a/src/protozero/test/example_proto/extensions.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package protozero.test.protos;
-
-message RealFakeEvent {
-  optional uint32 base_int = 1;
-  optional string base_string = 2;
-
-  extensions 10 to 99;
-}
-
-message SystemA {
-  optional uint32 int_a = 1;
-  optional string string_a = 2;
-}
-
-message SystemB {
-  optional uint32 int_b = 1;
-  optional string string_b = 2;
-}
-
-// Dummy message used for naming purposes.
-message BrowserExtension {
-  extend RealFakeEvent {
-    optional SystemA extension_a = 10;
-    optional SystemB extension_b = 11;
-  }
-}
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
new file mode 100644
index 0000000..4c69fcb
--- /dev/null
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_EXAMPLE_PROTO_TEST_MESSAGES_DESCRIPTOR_H_
+#define SRC_PROTOZERO_TEST_EXAMPLE_PROTO_TEST_MESSAGES_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)
+// 3df80477da2ea38cc659967487b37051a154bb69
+// SHA1(src/protozero/test/example_proto/test_messages.proto)
+// 6db2d291c87441f363d941410a1c326078566aa0
+
+// This is the proto TestMessages encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 4235> kTestMessagesDescriptor{
+    {0x0a, 0x62, 0x0a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65,
+     0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x2f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72,
+     0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x54, 0x72,
+     0x69, 0x63, 0x6b, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6d,
+     0x70, 0x6f, 0x72, 0x74, 0x0a, 0xc8, 0x01, 0x0a, 0x41, 0x73, 0x72, 0x63,
+     0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74,
+     0x65, 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
+     0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x2f,
+     0x67, 0x61, 0x6c, 0x61, 0x78, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72,
+     0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x1a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78,
+     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
+     0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x35, 0x0a, 0x06, 0x47, 0x61,
+     0x6c, 0x61, 0x78, 0x79, 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x49, 0x4c, 0x4b,
+     0x59, 0x5f, 0x57, 0x41, 0x59, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x41,
+     0x4e, 0x44, 0x52, 0x4f, 0x4d, 0x45, 0x44, 0x41, 0x10, 0x02, 0x12, 0x0d,
+     0x0a, 0x09, 0x53, 0x55, 0x4e, 0x46, 0x4c, 0x4f, 0x57, 0x45, 0x52, 0x10,
+     0x03, 0x50, 0x00, 0x0a, 0xb0, 0x03, 0x0a, 0x2e, 0x73, 0x72, 0x63, 0x2f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65,
+     0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x41, 0x73, 0x72, 0x63, 0x2f, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73,
+     0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x67, 0x61,
+     0x6c, 0x61, 0x78, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x22, 0xa1, 0x02, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x67, 0x61,
+     0x6c, 0x61, 0x63, 0x74, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x12, 0x42, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f,
+     0x67, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x52, 0x0c, 0x6f, 0x72, 0x69,
+     0x67, 0x69, 0x6e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x12, 0x23, 0x0a,
+     0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e,
+     0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x72,
+     0x69, 0x67, 0x69, 0x6e, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x12, 0x4c,
+     0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x5f, 0x67, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
+     0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x52, 0x11, 0x64,
+     0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x61,
+     0x6c, 0x61, 0x78, 0x79, 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74,
+     0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e,
+     0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65,
+     0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61,
+     0x6e, 0x65, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x4d, 0x65, 0x73,
+     0x73, 0x61, 0x67, 0x65, 0x50, 0x00, 0x0a, 0xa6, 0x1b, 0x0a, 0x34, 0x73,
+     0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+     0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74,
+     0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
+     0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x1a, 0x2e, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65,
+     0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x22, 0x81, 0x01, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73,
+     0x67, 0x61, 0x6c, 0x61, 0x63, 0x74, 0x69, 0x63, 0x50, 0x61, 0x72, 0x63,
+     0x65, 0x6c, 0x12, 0x45, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e,
+     0x73, 0x67, 0x61, 0x6c, 0x61, 0x63, 0x74, 0x69, 0x63, 0x4d, 0x65, 0x73,
+     0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x69, 0x6e,
+     0x67, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f,
+     0x64, 0x65, 0x22, 0xbb, 0x07, 0x0a, 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x74,
+     0x33, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f,
+     0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12,
+     0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e,
+     0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21,
+     0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, 0x74,
+     0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x21, 0x0a,
+     0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33,
+     0x32, 0x18, 0x05, 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, 0x69, 0x6e, 0x74, 0x36, 0x34,
+     0x18, 0x06, 0x20, 0x01, 0x28, 0x12, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x53, 0x69, 0x6e, 0x74, 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, 0x23, 0x0a, 0x0d,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36,
+     0x34, 0x18, 0x08, 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, 0x33, 0x32, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0d, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32,
+     0x12, 0x25, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66,
+     0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x10,
+     0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65,
+     0x64, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x0b, 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, 0x64, 0x6f,
+     0x75, 0x62, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12,
+     0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x6f, 0x6f,
+     0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x44, 0x0a, 0x0c, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x0e,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x72, 0x79, 0x46, 0x69,
+     0x65, 0x6c, 0x64, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x65,
+     0x73, 0x74, 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x0a, 0x73, 0x6d, 0x61, 0x6c,
+     0x6c, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09,
+     0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x42, 0x0a,
+     0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
+     0x18, 0x34, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65,
+     0x64, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x65,
+     0x64, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x69, 0x67,
+     0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0e, 0x32,
+     0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e,
+     0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x42, 0x69, 0x67, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x07, 0x62, 0x69, 0x67,
+     0x45, 0x6e, 0x75, 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0xf4, 0x03, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74,
+     0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0xf9, 0x03, 0x20, 0x01,
+     0x28, 0x0c, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x79, 0x74,
+     0x65, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64,
+     0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0xd8, 0x04, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x45, 0x76, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e,
+     0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0a,
+     0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x26,
+     0x0a, 0x0e, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69,
+     0x6e, 0x74, 0x33, 0x32, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x05, 0x52,
+     0x0d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x74,
+     0x33, 0x32, 0x22, 0x20, 0x0a, 0x0a, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64,
+     0x45, 0x6e, 0x75, 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x49, 0x4e, 0x47,
+     0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x4e, 0x47, 0x10, 0x02,
+     0x22, 0x9b, 0x02, 0x0a, 0x07, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41,
+     0x12, 0x45, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
+     0x5f, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73,
+     0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4e, 0x65, 0x73,
+     0x74, 0x65, 0x64, 0x41, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x42,
+     0x52, 0x09, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x12,
+     0x51, 0x0a, 0x0c, 0x73, 0x75, 0x70, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x73,
+     0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65,
+     0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4e, 0x65,
+     0x73, 0x74, 0x65, 0x64, 0x41, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64,
+     0x42, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x52, 0x0b, 0x73,
+     0x75, 0x70, 0x65, 0x72, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x1a, 0x76,
+     0x0a, 0x07, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x12, 0x47, 0x0a,
+     0x07, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x62, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
+     0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x2e, 0x4e,
+     0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65,
+     0x64, 0x43, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x1a, 0x22,
+     0x0a, 0x07, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x12, 0x17, 0x0a,
+     0x07, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x22, 0x80,
+     0x02, 0x0a, 0x0f, 0x43, 0x61, 0x6d, 0x65, 0x6c, 0x43, 0x61, 0x73, 0x65,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x66, 0x6f,
+     0x6f, 0x5f, 0x62, 0x61, 0x72, 0x5f, 0x62, 0x61, 0x7a, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x6f, 0x6f, 0x42, 0x61, 0x72, 0x42,
+     0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x42, 0x61, 0x7a,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61, 0x72, 0x42,
+     0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x6f, 0x6f, 0x4d, 0x6f, 0x6f,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4d, 0x6f, 0x6f, 0x4d,
+     0x6f, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x45, 0x6e, 0x63,
+     0x6f, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
+     0x55, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x12, 0x12,
+     0x0a, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d, 0x55, 0x72,
+     0x4c, 0x45, 0x5f, 0x6e, 0x63, 0x6f, 0x5f, 0x5f, 0x64, 0x65, 0x72, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x55, 0x72, 0x4c, 0x45, 0x4e,
+     0x63, 0x6f, 0x44, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x09, 0x5f, 0x5f, 0x62,
+     0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x07, 0x42, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12, 0x0e, 0x0a,
+     0x02, 0x55, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x55,
+     0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42, 0x69, 0x67,
+     0x5f, 0x5f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x62, 0x61,
+     0x6e, 0x67, 0x42, 0x69, 0x67, 0x22, 0x8f, 0x01, 0x0a, 0x14, 0x50, 0x61,
+     0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0b, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20,
+     0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x27, 0x0a, 0x0d, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32,
+     0x18, 0x02, 0x20, 0x03, 0x28, 0x07, 0x42, 0x02, 0x10, 0x01, 0x52, 0x0c,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32,
+     0x12, 0x29, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66,
+     0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x03, 0x20, 0x03, 0x28, 0x10,
+     0x42, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53,
+     0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x22, 0x82, 0x04, 0x0a, 0x11,
+     0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69,
+     0x6e, 0x67, 0x5f, 0x56, 0x31, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x6f,
+     0x74, 0x5f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x07, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x05,
+     0x65, 0x6e, 0x75, 0x6d, 0x7a, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32,
+     0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e,
+     0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69,
+     0x6e, 0x67, 0x5f, 0x56, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x7a, 0x5f,
+     0x56, 0x31, 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x7a, 0x12, 0x1f, 0x0a,
+     0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74,
+     0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65,
+     0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x03,
+     0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x70, 0x53, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x12, 0x44, 0x0a, 0x04, 0x73, 0x75, 0x62, 0x31, 0x18, 0x05, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a,
+     0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73,
+     0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x31, 0x2e, 0x53, 0x75,
+     0x62, 0x31, 0x5f, 0x56, 0x31, 0x52, 0x04, 0x73, 0x75, 0x62, 0x31, 0x12,
+     0x4b, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x72, 0x65, 0x70, 0x18,
+     0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65,
+     0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x31, 0x2e,
+     0x53, 0x75, 0x62, 0x31, 0x5f, 0x56, 0x31, 0x52, 0x07, 0x73, 0x75, 0x62,
+     0x31, 0x52, 0x65, 0x70, 0x12, 0x51, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x31,
+     0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e,
+     0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69,
+     0x6e, 0x67, 0x5f, 0x56, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x31, 0x5f, 0x56,
+     0x31, 0x42, 0x02, 0x28, 0x01, 0x52, 0x08, 0x73, 0x75, 0x62, 0x31, 0x4c,
+     0x61, 0x7a, 0x79, 0x1a, 0x45, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x31, 0x5f,
+     0x56, 0x31, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x69,
+     0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x75,
+     0x62, 0x31, 0x49, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62,
+     0x31, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x31, 0x53, 0x74, 0x72, 0x69,
+     0x6e, 0x67, 0x22, 0x1c, 0x0a, 0x08, 0x45, 0x6e, 0x75, 0x6d, 0x7a, 0x5f,
+     0x56, 0x31, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12,
+     0x07, 0x0a, 0x03, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x22, 0xa4, 0x07, 0x0a,
+     0x11, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+     0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f,
+     0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+     0x52, 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x12, 0x47, 0x0a,
+     0x05, 0x65, 0x6e, 0x75, 0x6d, 0x7a, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e,
+     0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+     0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x7a,
+     0x5f, 0x56, 0x32, 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x7a, 0x12, 0x1f,
+     0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f,
+     0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x72,
+     0x65, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x70, 0x53, 0x74, 0x72, 0x69,
+     0x6e, 0x67, 0x12, 0x44, 0x0a, 0x04, 0x73, 0x75, 0x62, 0x31, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72,
+     0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x2e, 0x53,
+     0x75, 0x62, 0x31, 0x5f, 0x56, 0x32, 0x52, 0x04, 0x73, 0x75, 0x62, 0x31,
+     0x12, 0x4b, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x72, 0x65, 0x70,
+     0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56,
+     0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32,
+     0x2e, 0x53, 0x75, 0x62, 0x31, 0x5f, 0x56, 0x32, 0x52, 0x07, 0x73, 0x75,
+     0x62, 0x31, 0x52, 0x65, 0x70, 0x12, 0x51, 0x0a, 0x09, 0x73, 0x75, 0x62,
+     0x31, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+     0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+     0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x31, 0x5f,
+     0x56, 0x32, 0x42, 0x02, 0x28, 0x01, 0x52, 0x08, 0x73, 0x75, 0x62, 0x31,
+     0x4c, 0x61, 0x7a, 0x79, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74,
+     0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x32, 0x18, 0x0a, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x56, 0x32,
+     0x12, 0x44, 0x0a, 0x04, 0x73, 0x75, 0x62, 0x32, 0x18, 0x0b, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
+     0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69,
+     0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x2e, 0x53, 0x75, 0x62,
+     0x32, 0x5f, 0x56, 0x32, 0x52, 0x04, 0x73, 0x75, 0x62, 0x32, 0x12, 0x4b,
+     0x0a, 0x08, 0x73, 0x75, 0x62, 0x32, 0x5f, 0x72, 0x65, 0x70, 0x18, 0x0c,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72,
+     0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x56, 0x32, 0x2e, 0x53,
+     0x75, 0x62, 0x32, 0x5f, 0x56, 0x32, 0x52, 0x07, 0x73, 0x75, 0x62, 0x32,
+     0x52, 0x65, 0x70, 0x12, 0x51, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x32, 0x5f,
+     0x6c, 0x61, 0x7a, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74,
+     0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
+     0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e,
+     0x67, 0x5f, 0x56, 0x32, 0x2e, 0x53, 0x75, 0x62, 0x32, 0x5f, 0x56, 0x32,
+     0x42, 0x02, 0x28, 0x01, 0x52, 0x08, 0x73, 0x75, 0x62, 0x32, 0x4c, 0x61,
+     0x7a, 0x79, 0x1a, 0x8b, 0x01, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x31, 0x5f,
+     0x56, 0x32, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x69,
+     0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x75,
+     0x62, 0x31, 0x49, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62,
+     0x31, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x31, 0x53, 0x74, 0x72, 0x69,
+     0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x69,
+     0x6e, 0x74, 0x5f, 0x76, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x09, 0x73, 0x75, 0x62, 0x31, 0x49, 0x6e, 0x74, 0x56, 0x32, 0x12, 0x24,
+     0x0a, 0x0e, 0x73, 0x75, 0x62, 0x31, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x76, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+     0x73, 0x75, 0x62, 0x31, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x32,
+     0x1a, 0x45, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x32, 0x5f, 0x56, 0x32, 0x12,
+     0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x32, 0x5f, 0x69, 0x6e, 0x74, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x75, 0x62, 0x32, 0x49,
+     0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x32, 0x5f, 0x73,
+     0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x0a, 0x73, 0x75, 0x62, 0x32, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22,
+     0x2a, 0x0a, 0x08, 0x45, 0x6e, 0x75, 0x6d, 0x7a, 0x5f, 0x56, 0x32, 0x12,
+     0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03,
+     0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x48, 0x52,
+     0x45, 0x45, 0x5f, 0x56, 0x32, 0x10, 0x03, 0x2a, 0x25, 0x0a, 0x09, 0x53,
+     0x6d, 0x61, 0x6c, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x09, 0x0a, 0x05,
+     0x54, 0x4f, 0x5f, 0x42, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4e,
+     0x4f, 0x54, 0x5f, 0x54, 0x4f, 0x5f, 0x42, 0x45, 0x10, 0x00, 0x2a, 0x3e,
+     0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d,
+     0x12, 0x0c, 0x0a, 0x08, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x56, 0x45,
+     0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x45, 0x55, 0x54, 0x52, 0x41,
+     0x4c, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x08, 0x4e, 0x45, 0x47, 0x41, 0x54,
+     0x49, 0x56, 0x45, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0x01, 0x2a, 0x1f, 0x0a, 0x07, 0x42, 0x69, 0x67, 0x45, 0x6e, 0x75,
+     0x6d, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x10, 0x0a,
+     0x12, 0x09, 0x0a, 0x03, 0x45, 0x4e, 0x44, 0x10, 0x94, 0x91, 0x06}};
+
+}  // namespace perfetto
+
+#endif  // SRC_PROTOZERO_TEST_EXAMPLE_PROTO_TEST_MESSAGES_DESCRIPTOR_H_
diff --git a/src/protozero/test/protozero_benchmark.cc b/src/protozero/test/protozero_benchmark.cc
index 52f2a6c..4f9fe56 100644
--- a/src/protozero/test/protozero_benchmark.cc
+++ b/src/protozero/test/protozero_benchmark.cc
@@ -68,10 +68,8 @@
   template <typename T>
   void Append(T x) {
     // The reinterpret_cast is to give favorable alignment guarantees.
-    // The memcpy will be elided by the compiler, which will emit just a
-    // 64-bit aligned mov instruction.
-    memcpy(reinterpret_cast<void*>(ptr_), &x, sizeof(x));
-    ptr_ += sizeof(uint64_t);
+    memcpy(reinterpret_cast<T*>(ptr_), &x, sizeof(x));
+    ptr_ += sizeof(x);
   }
 
   void set_field_int32(int32_t x) { Append(x); }
@@ -82,7 +80,7 @@
 
   SOLMsg* add_field_nested() { return new (this + 1) SOLMsg(); }
 
-  alignas(uint64_t) char storage_[sizeof(g_fake_input_simple) + 8];
+  char storage_[sizeof(g_fake_input_simple)];
   char* ptr_ = &storage_[0];
 };
 
diff --git a/src/protozero/test/protozero_conformance_unittest.cc b/src/protozero/test/protozero_conformance_unittest.cc
index 05efa8f..85eaf43 100644
--- a/src/protozero/test/protozero_conformance_unittest.cc
+++ b/src/protozero/test/protozero_conformance_unittest.cc
@@ -24,8 +24,6 @@
 #include "test/gtest_and_gmock.h"
 
 // Autogenerated headers in out/*/gen/
-#include "src/protozero/test/example_proto/extensions.pb.h"
-#include "src/protozero/test/example_proto/extensions.pbzero.h"
 #include "src/protozero/test/example_proto/library.pbzero.h"
 #include "src/protozero/test/example_proto/test_messages.pb.h"
 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
@@ -118,39 +116,6 @@
   EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
 }
 
-TEST(ProtoZeroConformanceTest, Extensions) {
-  HeapBuffered<pbtest::BrowserExtension> msg_a{kChunkSize, kChunkSize};
-
-  msg_a->set_base_int(4);
-
-  pbtest::SystemA* msg_b = msg_a->set_extension_a();
-  msg_b->set_int_a(3);
-  msg_b->set_string_a("string a");
-
-  pbtest::SystemB* msg_c = msg_a->set_extension_b();
-  msg_c->set_int_b(10);
-  msg_c->set_string_b("string b");
-
-  msg_a->set_base_string("base string");
-
-  std::string serialized = msg_a.SerializeAsString();
-  pbgold::RealFakeEvent gold_msg_a;
-  gold_msg_a.ParseFromString(serialized);
-
-  EXPECT_EQ(gold_msg_a.base_int(), 4u);
-  EXPECT_EQ(gold_msg_a.base_string(), "base string");
-
-  pbgold::SystemA gold_msg_b =
-      gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_a);
-  EXPECT_EQ(gold_msg_b.int_a(), 3u);
-  EXPECT_EQ(gold_msg_b.string_a(), "string a");
-
-  pbgold::SystemB gold_msg_c =
-      gold_msg_a.GetExtension(pbgold::BrowserExtension::extension_b);
-  EXPECT_EQ(gold_msg_c.int_b(), 10u);
-  EXPECT_EQ(gold_msg_c.string_b(), "string b");
-}
-
 TEST(ProtoZeroConformanceTest, Import) {
   // Test the includes for indirect public import: library.pbzero.h ->
   // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h .
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 8384f51..2b26b7e 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -14,7 +14,6 @@
 
 import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_cc_proto_descriptor.gni")
 import("../../gn/perfetto_host_executable.gni")
 import("../../gn/test.gni")
 import("../../gn/wasm.gni")
@@ -27,7 +26,7 @@
 if (enable_perfetto_trace_processor_sqlite) {
   static_library("trace_processor") {
     complete_static_lib = true
-    public_deps = [ ":lib" ]
+    deps = [ ":lib" ]
   }
 }
 
@@ -54,6 +53,10 @@
   ]
 }
 
+source_set("track_event_descriptor") {
+  sources = [ "importers/proto/track_event.descriptor.h" ]
+}
+
 source_set("ftrace_descriptors") {
   sources = [
     "importers/ftrace/ftrace_descriptors.cc",
@@ -68,6 +71,7 @@
 
 source_set("storage_minimal") {
   sources = [
+    "chunked_trace_reader.h",
     "forwarding_trace_parser.cc",
     "forwarding_trace_parser.h",
     "importers/default_modules.cc",
@@ -82,22 +86,10 @@
     "importers/json/json_utils.h",
     "importers/ninja/ninja_log_parser.cc",
     "importers/ninja/ninja_log_parser.h",
-    "importers/proto/async_track_set_tracker.cc",
-    "importers/proto/async_track_set_tracker.h",
-    "importers/proto/chrome_string_lookup.cc",
-    "importers/proto/chrome_string_lookup.h",
-    "importers/proto/chrome_system_probes_module.cc",
-    "importers/proto/chrome_system_probes_module.h",
-    "importers/proto/chrome_system_probes_parser.cc",
-    "importers/proto/chrome_system_probes_parser.h",
+    "importers/proto/args_table_utils.cc",
+    "importers/proto/args_table_utils.h",
     "importers/proto/heap_profile_tracker.cc",
     "importers/proto/heap_profile_tracker.h",
-    "importers/proto/memory_tracker_snapshot_module.cc",
-    "importers/proto/memory_tracker_snapshot_module.h",
-    "importers/proto/memory_tracker_snapshot_parser.cc",
-    "importers/proto/memory_tracker_snapshot_parser.h",
-    "importers/proto/metadata_module.cc",
-    "importers/proto/metadata_module.h",
     "importers/proto/metadata_tracker.cc",
     "importers/proto/metadata_tracker.h",
     "importers/proto/packet_sequence_state.cc",
@@ -108,15 +100,11 @@
     "importers/proto/profile_module.h",
     "importers/proto/profile_packet_utils.cc",
     "importers/proto/profile_packet_utils.h",
-    "importers/proto/profiler_util.cc",
-    "importers/proto/profiler_util.h",
     "importers/proto/proto_importer_module.cc",
     "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_reader.cc",
-    "importers/proto/proto_trace_reader.h",
     "importers/proto/proto_trace_tokenizer.cc",
     "importers/proto/proto_trace_tokenizer.h",
     "importers/proto/stack_profile_tracker.cc",
@@ -127,11 +115,11 @@
     "importers/proto/track_event_parser.h",
     "importers/proto/track_event_tokenizer.cc",
     "importers/proto/track_event_tokenizer.h",
-    "importers/proto/track_event_tracker.cc",
-    "importers/proto/track_event_tracker.h",
     "importers/syscalls/syscall_tracker.h",
     "importers/systrace/systrace_line.h",
     "timestamped_trace_piece.h",
+    "trace_blob_view.h",
+    "trace_parser.h",
     "trace_processor_context.cc",
     "trace_processor_storage.cc",
     "trace_processor_storage_impl.cc",
@@ -141,20 +129,17 @@
     "virtual_destructors.cc",
   ]
   deps = [
+    ":track_event_descriptor",
     "../../gn:default_deps",
     "../base",
     "../protozero",
     "containers",
-    "importers:gen_cc_chrome_track_event_descriptor",
-    "importers:gen_cc_track_event_descriptor",
-    "importers/common",
-    "importers/memory_tracker:graph_processor",
+    "importers:common",
     "storage",
     "tables",
     "types",
     "util",
     "util:descriptors",
-    "util:proto_to_args_parser",
   ]
   public_deps = [
     "../../include/perfetto/trace_processor:storage",
@@ -221,12 +206,10 @@
     "importers/proto/android_probes_parser.h",
     "importers/proto/android_probes_tracker.cc",
     "importers/proto/android_probes_tracker.h",
-    "importers/proto/frame_timeline_event_parser.cc",
-    "importers/proto/frame_timeline_event_parser.h",
-    "importers/proto/gpu_event_parser.cc",
-    "importers/proto/gpu_event_parser.h",
     "importers/proto/graphics_event_module.cc",
     "importers/proto/graphics_event_module.h",
+    "importers/proto/gpu_event_parser.cc",
+    "importers/proto/gpu_event_parser.h",
     "importers/proto/graphics_frame_event_parser.cc",
     "importers/proto/graphics_frame_event_parser.h",
     "importers/proto/heap_graph_module.cc",
@@ -265,11 +248,9 @@
     "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
     "../protozero",
-    "importers/common",
+    "importers:common",
     "storage",
-    "tables",
     "types",
-    "util",
   ]
   if (enable_perfetto_trace_processor_json) {
     deps += [ "../../gn:jsoncpp" ]
@@ -297,28 +278,14 @@
 if (enable_perfetto_trace_processor_sqlite) {
   source_set("lib") {
     sources = [
-      "dynamic/ancestor_generator.cc",
-      "dynamic/ancestor_generator.h",
-      "dynamic/connected_flow_generator.cc",
-      "dynamic/connected_flow_generator.h",
-      "dynamic/descendant_slice_generator.cc",
-      "dynamic/descendant_slice_generator.h",
       "dynamic/describe_slice_generator.cc",
       "dynamic/describe_slice_generator.h",
-      "dynamic/experimental_annotated_stack_generator.cc",
-      "dynamic/experimental_annotated_stack_generator.h",
       "dynamic/experimental_counter_dur_generator.cc",
       "dynamic/experimental_counter_dur_generator.h",
       "dynamic/experimental_flamegraph_generator.cc",
       "dynamic/experimental_flamegraph_generator.h",
-      "dynamic/experimental_sched_upid_generator.cc",
-      "dynamic/experimental_sched_upid_generator.h",
       "dynamic/experimental_slice_layout_generator.cc",
       "dynamic/experimental_slice_layout_generator.h",
-      "dynamic/thread_state_generator.cc",
-      "dynamic/thread_state_generator.h",
-      "iterator_impl.cc",
-      "iterator_impl.h",
       "read_trace.cc",
       "trace_processor.cc",
       "trace_processor_impl.cc",
@@ -330,41 +297,40 @@
       ":metatrace",
       ":storage_full",
       "../../gn:default_deps",
+      "../../gn:sqlite",
+      "../../protos/perfetto/metrics:zero",
+      "../../protos/perfetto/metrics/android:zero",
       "../../protos/perfetto/trace/ftrace:zero",
       "../base",
-      "../protozero",
       "analysis",
-      "db",
-      "importers/common",
+      "db:lib",
+      "importers:common",
       "metrics:lib",
       "sqlite",
       "storage",
       "tables",
       "types",
-      "util",
-      "util:protozero_to_text",
     ]
-    public_deps = [
-      "../../gn:sqlite",  # iterator_impl.h includes sqlite3.h.
-      "../../include/perfetto/trace_processor",
-    ]
+    public_deps = [ "../../include/perfetto/trace_processor" ]
     if (enable_perfetto_trace_processor_json) {
       deps += [ "../../gn:jsoncpp" ]
     }
   }
 
-  executable("trace_processor_shell") {
+  perfetto_host_executable("trace_processor_shell") {
     deps = [
       ":lib",
       "../../gn:default_deps",
-      "../../gn:protobuf_full",
-      "../../src/profiling:deobfuscator",
+      "../../gn:protoc_lib",
       "../../src/profiling/symbolizer",
       "../../src/profiling/symbolizer:symbolize_database",
       "../base",
       "metrics:lib",
       "util",
     ]
+    if (enable_perfetto_version_gen) {
+      deps += [ "../../gn/standalone:gen_git_revision" ]
+    }
     if (enable_perfetto_trace_processor_linenoise) {
       deps += [ "../../gn:linenoise" ]
     }
@@ -376,14 +342,6 @@
       "util/proto_to_json.cc",
       "util/proto_to_json.h",
     ]
-    if (perfetto_build_standalone && !is_perfetto_build_generator) {
-      data_deps = [
-        # The diff testing framework depends on these descriptors.
-        "../../protos/perfetto/metrics:descriptor",
-        "../../protos/perfetto/trace:descriptor",
-        "../../protos/perfetto/trace:test_extensions_descriptor",
-      ]
-    }
   }
 }  # if (enable_perfetto_trace_processor_sqlite)
 
@@ -393,26 +351,19 @@
     "forwarding_trace_parser_unittest.cc",
     "importers/ftrace/sched_event_tracker_unittest.cc",
     "importers/fuchsia/fuchsia_trace_utils_unittest.cc",
-    "importers/memory_tracker/graph_processor_unittest.cc",
-    "importers/memory_tracker/graph_unittest.cc",
-    "importers/memory_tracker/raw_process_memory_node_unittest.cc",
-    "importers/proto/async_track_set_tracker_unittest.cc",
+    "importers/proto/args_table_utils_unittest.cc",
     "importers/proto/heap_graph_tracker_unittest.cc",
     "importers/proto/heap_profile_tracker_unittest.cc",
-    "importers/proto/perf_sample_tracker_unittest.cc",
     "importers/proto/proto_trace_parser_unittest.cc",
     "importers/syscalls/syscall_tracker_unittest.cc",
     "importers/systrace/systrace_parser_unittest.cc",
     "trace_sorter_unittest.cc",
   ]
   deps = [
-    ":gen_cc_test_messages_descriptor",
     ":storage_full",
     "../../gn:default_deps",
     "../../gn:gtest_and_gmock",
-    "../../protos/perfetto/common:cpp",
     "../../protos/perfetto/common:zero",
-    "../../protos/perfetto/trace:cpp",
     "../../protos/perfetto/trace:minimal_zero",
     "../../protos/perfetto/trace:zero",
     "../../protos/perfetto/trace/android:zero",
@@ -420,7 +371,6 @@
     "../../protos/perfetto/trace/ftrace:zero",
     "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
-    "../../protos/perfetto/trace/profiling:cpp",
     "../../protos/perfetto/trace/ps:zero",
     "../../protos/perfetto/trace/sys_stats:zero",
     "../../protos/perfetto/trace/track_event:zero",
@@ -429,15 +379,12 @@
     "../protozero:testing_messages_zero",
     "containers:unittests",
     "db:unittests",
-    "importers/common",
-    "importers/common:unittests",
-    "importers/memory_tracker:graph_processor",
-    "rpc:unittests",
+    "importers:common",
+    "importers:unittests",
     "storage",
     "tables:unittests",
     "types",
     "types:unittests",
-    "util:descriptors",
     "util:unittests",
   ]
 
@@ -445,7 +392,6 @@
     sources += [
       "dynamic/experimental_counter_dur_generator_unittest.cc",
       "dynamic/experimental_slice_layout_generator_unittest.cc",
-      "dynamic/thread_state_generator_unittest.cc",
     ]
     deps += [
       ":lib",
@@ -474,11 +420,6 @@
   }
 }
 
-perfetto_cc_proto_descriptor("gen_cc_test_messages_descriptor") {
-  descriptor_name = "test_messages.descriptor"
-  descriptor_target = "../protozero:test_messages_descriptor"
-}
-
 source_set("integrationtests") {
   testonly = true
   sources = []
@@ -492,9 +433,7 @@
       ":lib",
       "../../gn:default_deps",
       "../../gn:gtest_and_gmock",
-      "../../protos/perfetto/common:zero",
       "../../protos/perfetto/trace:zero",
-      "../../protos/perfetto/trace_processor:zero",
       "../base",
       "../base:test_support",
       "sqlite",
diff --git a/src/trace_processor/chunked_trace_reader.h b/src/trace_processor/chunked_trace_reader.h
new file mode 100644
index 0000000..0d487dc
--- /dev/null
+++ b/src/trace_processor/chunked_trace_reader.h
@@ -0,0 +1,50 @@
+/*
+ * 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_CHUNKED_TRACE_READER_H_
+#define SRC_TRACE_PROCESSOR_CHUNKED_TRACE_READER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "perfetto/trace_processor/basic_types.h"
+#include "perfetto/trace_processor/status.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Base interface for first stage of parsing pipeline
+// (JsonTraceParser, ProtoTraceTokenizer).
+class ChunkedTraceReader {
+ public:
+  virtual ~ChunkedTraceReader();
+
+  // Pushes more data into the trace parser. There is no requirement for the
+  // 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;
+
+  // Called after the last Parse() call.
+  virtual void NotifyEndOfFile() = 0;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_CHUNKED_TRACE_READER_H_
diff --git a/src/trace_processor/containers/BUILD.gn b/src/trace_processor/containers/BUILD.gn
index 1f843e1..836ab22 100644
--- a/src/trace_processor/containers/BUILD.gn
+++ b/src/trace_processor/containers/BUILD.gn
@@ -12,33 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/perfetto_component.gni")
 import("../../../gn/test.gni")
 
-# Used by two static libs - trace_processor and libpprofbuilder, hence using
-# perfetto_component to turn this into a cc_library in bazel builds.
-# The 'public' section gets converted to 'hdrs', and is necessary for the bazel
-# build to pass strict header checks.
-perfetto_component("containers") {
-  public = [
-    "bit_vector.h",
-    "bit_vector_iterators.h",
-    "null_term_string_view.h",
-    "nullable_vector.h",
-    "row_map.h",
-    "string_pool.h",
-  ]
+source_set("containers") {
   sources = [
     "bit_vector.cc",
+    "bit_vector.h",
     "bit_vector_iterators.cc",
+    "bit_vector_iterators.h",
+    "null_term_string_view.h",
     "nullable_vector.cc",
+    "nullable_vector.h",
     "row_map.cc",
+    "row_map.h",
     "string_pool.cc",
+    "string_pool.h",
   ]
   deps = [
     "../../../gn:default_deps",
+    "../../../include/perfetto/base",
+    "../../../include/perfetto/ext/base",
     "../../../include/perfetto/protozero",
-    "../../base",
   ]
 }
 
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index 20773dd..bfd8b4f 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -432,13 +432,18 @@
 
     // Returns the number of set bits.
     uint32_t GetNumBitsSet() const {
-      return static_cast<uint32_t>(PERFETTO_POPCOUNT(word_));
+      // 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);
-      return static_cast<uint32_t>(PERFETTO_POPCOUNT(WordUntil(idx)));
+
+      // 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
diff --git a/src/trace_processor/containers/row_map.cc b/src/trace_processor/containers/row_map.cc
index 297a0ef..88a3717 100644
--- a/src/trace_processor/containers/row_map.cc
+++ b/src/trace_processor/containers/row_map.cc
@@ -117,11 +117,7 @@
 
 RowMap SelectIvWithBv(const std::vector<uint32_t>& iv,
                       const BitVector& selector) {
-  PERFETTO_DCHECK(selector.size() <= iv.size());
-
   std::vector<uint32_t> copy = iv;
-  copy.resize(selector.size());
-
   uint32_t idx = 0;
   auto it = std::remove_if(
       copy.begin(), copy.end(),
diff --git a/src/trace_processor/containers/row_map_unittest.cc b/src/trace_processor/containers/row_map_unittest.cc
index ac54cb1..fde10d5 100644
--- a/src/trace_processor/containers/row_map_unittest.cc
+++ b/src/trace_processor/containers/row_map_unittest.cc
@@ -195,7 +195,7 @@
   ASSERT_EQ(res.Get(1u), 30u);
 }
 
-TEST(RowMapUnittest, SelectRangeWithSingleBitVector) {
+TEST(RowMapUnittest, SelectRangeWithSmallBitVector) {
   RowMap rm(27, 31);
   RowMap picker(BitVector{false, true});
   auto res = rm.SelectRows(picker);
@@ -204,16 +204,6 @@
   ASSERT_EQ(res.Get(0u), 28u);
 }
 
-TEST(RowMapUnittest, SelectRangeWithSmallBitVector) {
-  RowMap rm(27, 31);
-  RowMap picker(BitVector{false, true, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 28u);
-  ASSERT_EQ(res.Get(1u), 29u);
-}
-
 TEST(RowMapUnittest, SelectBitVectorWithBitVector) {
   RowMap rm(BitVector{true, false, true, true, false, true});
   RowMap picker(BitVector{true, false, false, true});
@@ -224,7 +214,7 @@
   ASSERT_EQ(res.Get(1u), 5u);
 }
 
-TEST(RowMapUnittest, SelectBitVectorWithSingleBitVector) {
+TEST(RowMapUnittest, SelectBitVectorWithSmallBitVector) {
   RowMap rm(BitVector{true, false, true, true, false, true});
   RowMap picker(BitVector{false, true});
   auto res = rm.SelectRows(picker);
@@ -233,16 +223,6 @@
   ASSERT_EQ(res.Get(0u), 2u);
 }
 
-TEST(RowMapUnittest, SelectBitVectorWithSmallBitVector) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  RowMap picker(BitVector{false, true, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 2u);
-  ASSERT_EQ(res.Get(1u), 3u);
-}
-
 TEST(RowMapUnittest, SelectIndexVectorWithBitVector) {
   RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
   RowMap picker(BitVector{true, false, false, true});
@@ -253,16 +233,6 @@
   ASSERT_EQ(res.Get(1u), 5u);
 }
 
-TEST(RowMapUnittest, SelectIndexVectorWithSmallBitVector) {
-  RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
-  RowMap picker(BitVector{false, true, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 2u);
-  ASSERT_EQ(res.Get(1u), 3u);
-}
-
 TEST(RowMapUnittest, SelectRangeWithIndexVector) {
   RowMap rm(27, 31);
   RowMap picker(std::vector<uint32_t>{3u, 2u, 0u, 1u, 1u, 3u});
diff --git a/src/trace_processor/containers/string_pool.h b/src/trace_processor/containers/string_pool.h
index 241240c..11ae91c 100644
--- a/src/trace_processor/containers/string_pool.h
+++ b/src/trace_processor/containers/string_pool.h
@@ -20,7 +20,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include <limits>
 #include <unordered_map>
 #include <vector>
 
@@ -294,8 +293,10 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
+namespace std {
+
 template <>
-struct std::hash<::perfetto::trace_processor::StringPool::Id> {
+struct hash< ::perfetto::trace_processor::StringPool::Id> {
   using argument_type = ::perfetto::trace_processor::StringPool::Id;
   using result_type = size_t;
 
@@ -304,4 +305,6 @@
   }
 };
 
+}  // namespace std
+
 #endif  // SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index ebbd478..f1a959f 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -14,7 +14,7 @@
 
 import("../../../gn/test.gni")
 
-source_set("db") {
+source_set("lib") {
   sources = [
     "column.cc",
     "column.h",
@@ -40,7 +40,7 @@
     "table_unittest.cc",
   ]
   deps = [
-    ":db",
+    ":lib",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
     "../../base:base",
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index 00496b3..c2452bd 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -186,7 +186,7 @@
         // for this function even though the LHS of the comparator should
         // actually be |v|. This saves us having a duplicate implementation of
         // the comparision function.
-        return -compare::LongToDouble(long_value, static_cast<double>(v));
+        return -compare::LongToDouble(long_value, v);
       };
       FilterIntoNumericWithComparatorSlow<T, is_nullable>(op, rm, fn);
     } else {
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index 9df9f70..a256cc1 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -38,7 +38,6 @@
   explicit constexpr BaseId(uint32_t v) : value(v) {}
 
   bool operator==(const BaseId& o) const { return o.value == value; }
-  bool operator!=(const BaseId& o) const { return !(*this == o); }
   bool operator<(const BaseId& o) const { return value < o.value; }
 
   uint32_t value;
@@ -112,53 +111,6 @@
     kDense = 1 << 3,
   };
 
-  // Iterator over a column which conforms to std iterator interface
-  // to allow using std algorithms (e.g. upper_bound, lower_bound etc.).
-  class Iterator {
-   public:
-    using iterator_category = std::random_access_iterator_tag;
-    using value_type = SqlValue;
-    using difference_type = uint32_t;
-    using pointer = uint32_t*;
-    using reference = uint32_t&;
-
-    Iterator(const Column* col, uint32_t row) : col_(col), row_(row) {}
-
-    Iterator(const Iterator&) = default;
-    Iterator& operator=(const Iterator&) = default;
-
-    bool operator==(const Iterator& other) const { return other.row_ == row_; }
-    bool operator!=(const Iterator& other) const { return !(*this == other); }
-    bool operator<(const Iterator& other) const { return row_ < other.row_; }
-    bool operator>(const Iterator& other) const { return other < *this; }
-    bool operator<=(const Iterator& other) const { return !(other < *this); }
-    bool operator>=(const Iterator& other) const { return !(*this < other); }
-
-    SqlValue operator*() const { return col_->Get(row_); }
-    Iterator& operator++() {
-      row_++;
-      return *this;
-    }
-    Iterator& operator--() {
-      row_--;
-      return *this;
-    }
-
-    Iterator& operator+=(uint32_t diff) {
-      row_ += diff;
-      return *this;
-    }
-    uint32_t operator-(const Iterator& other) const {
-      return row_ - other.row_;
-    }
-
-    uint32_t row() const { return row_; }
-
-   private:
-    const Column* col_ = nullptr;
-    uint32_t row_ = 0;
-  };
-
   // Flags specified for an id column.
   static constexpr uint32_t kIdFlags = Flag::kSorted | Flag::kNonNull;
 
@@ -392,12 +344,6 @@
   // Returns the JoinKey for this Column.
   JoinKey join_key() const { return JoinKey{col_idx_in_table_}; }
 
-  // Returns an iterator to the first entry in this column.
-  Iterator begin() const { return Iterator(this, 0); }
-
-  // Returns an iterator pointing beyond the last entry in this column.
-  Iterator end() const { return Iterator(this, row_map().size()); }
-
  protected:
   // Returns the backing sparse vector cast to contain data of type T.
   // Should only be called when |type_| == ToColumnType<T>().
@@ -436,6 +382,49 @@
     kId,
   };
 
+  // Iterator over a column which conforms to std iterator interface
+  // to allow using std algorithms (e.g. upper_bound, lower_bound etc.).
+  class Iterator {
+   public:
+    using iterator_category = std::random_access_iterator_tag;
+    using value_type = SqlValue;
+    using difference_type = uint32_t;
+    using pointer = uint32_t*;
+    using reference = uint32_t&;
+
+    Iterator(const Column* col, uint32_t row) : col_(col), row_(row) {}
+
+    Iterator(const Iterator&) = default;
+    Iterator& operator=(const Iterator&) = default;
+
+    bool operator==(const Iterator& other) const { return other.row_ == row_; }
+    bool operator!=(const Iterator& other) const { return !(*this == other); }
+    bool operator<(const Iterator& other) const { return other.row_ < row_; }
+    bool operator>(const Iterator& other) const { return other < *this; }
+    bool operator<=(const Iterator& other) const { return !(other < *this); }
+    bool operator>=(const Iterator& other) const { return !(*this < other); }
+
+    SqlValue operator*() const { return col_->Get(row_); }
+    Iterator& operator++() {
+      row_++;
+      return *this;
+    }
+    Iterator& operator--() {
+      row_--;
+      return *this;
+    }
+
+    Iterator& operator+=(uint32_t diff) {
+      row_ += diff;
+      return *this;
+    }
+    uint32_t operator-(const Iterator& other) { return row_ - other.row_; }
+
+   private:
+    const Column* col_ = nullptr;
+    uint32_t row_ = 0;
+  };
+
   friend class Table;
 
   // Base constructor for this class which all other constructors call into.
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 940d8b1..ebcdf9e 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -68,57 +68,41 @@
   if (od.empty())
     return Copy();
 
-  // Return a copy if there is a single constraint to sort the table
-  // by a column which is already sorted.
-  const auto& first_col = GetColumn(od.front().col_idx);
-  if (od.size() == 1 && first_col.IsSorted() && !od.front().desc)
-    return Copy();
-
   // Build an index vector with all the indices for the first |size_| rows.
   std::vector<uint32_t> idx(row_count_);
+  std::iota(idx.begin(), idx.end(), 0);
 
-  if (od.size() == 1 && first_col.IsSorted()) {
-    // We special case a single constraint in descending order as this
-    // happens any time the |max| function is used in SQLite. We can be
-    // more efficient as this column is already sorted so we simply need
-    // to reverse the order of this column.
-    PERFETTO_DCHECK(od.front().desc);
-    std::iota(idx.rbegin(), idx.rend(), 0);
-  } else {
-    // As our data is columnar, it's always more efficient to sort one column
-    // at a time rather than try and sort lexiographically all at once.
-    // To preserve correctness, we need to stably sort the index vector once
-    // for each order by in *reverse* order. Reverse order is important as it
-    // preserves the lexiographical property.
-    //
-    // For example, suppose we have the following:
-    // Table {
-    //   Column x;
-    //   Column y
-    //   Column z;
-    // }
-    //
-    // Then, to sort "y asc, x desc", we could do one of two things:
-    //  1) sort the index vector all at once and on each index, we compare
-    //     y then z. This is slow as the data is columnar and we need to
-    //     repeatedly branch inside each column.
-    //  2) we can stably sort first on x desc and then sort on y asc. This will
-    //     first put all the x in the correct order such that when we sort on
-    //     y asc, we will have the correct order of x where y is the same (since
-    //     the sort is stable).
-    //
-    // TODO(lalitm): it is possible that we could sort the last constraint (i.e.
-    // the first constraint in the below loop) in a non-stable way. However,
-    // this is more subtle than it appears as we would then need special
-    // handling where there are order bys on a column which is already sorted
-    // (e.g. ts, id). Investigate whether the performance gains from this are
-    // worthwhile. This also needs changes to the constraint modification logic
-    // in DbSqliteTable which currently eliminates constraints on sorted
-    // columns.
-    std::iota(idx.begin(), idx.end(), 0);
-    for (auto it = od.rbegin(); it != od.rend(); ++it) {
-      columns_[it->col_idx].StableSort(it->desc, &idx);
-    }
+  // As our data is columnar, it's always more efficient to sort one column
+  // at a time rather than try and sort lexiographically all at once.
+  // To preserve correctness, we need to stably sort the index vector once
+  // for each order by in *reverse* order. Reverse order is important as it
+  // preserves the lexiographical property.
+  //
+  // For example, suppose we have the following:
+  // Table {
+  //   Column x;
+  //   Column y
+  //   Column z;
+  // }
+  //
+  // Then, to sort "y asc, x desc", we could do one of two things:
+  //  1) sort the index vector all at once and on each index, we compare
+  //     y then z. This is slow as the data is columnar and we need to
+  //     repeatedly branch inside each column.
+  //  2) we can stably sort first on x desc and then sort on y asc. This will
+  //     first put all the x in the correct order such that when we sort on
+  //     y asc, we will have the correct order of x where y is the same (since
+  //     the sort is stable).
+  //
+  // TODO(lalitm): it is possible that we could sort the last constraint (i.e.
+  // the first constraint in the below loop) in a non-stable way. However, this
+  // is more subtle than it appears as we would then need special handling where
+  // there are order bys on a column which is already sorted (e.g. ts, id).
+  // Investigate whether the performance gains from this are worthwhile. This
+  // also needs changes to the constraint modification logic in DbSqliteTable
+  // which currently eliminates constraints on sorted columns.
+  for (auto it = od.rbegin(); it != od.rend(); ++it) {
+    columns_[it->col_idx].StableSort(it->desc, &idx);
   }
 
   // Return a copy of this table with the RowMaps using the computed ordered
@@ -135,11 +119,8 @@
     col.flags_ &= ~Column::Flag::kSorted;
   }
 
-  // For the first order by, make the column flag itself as sorted but
-  // only if the sort was in ascending order.
-  if (!od.front().desc) {
-    table.columns_[od.front().col_idx].flags_ |= Column::Flag::kSorted;
-  }
+  // For the first order by, make the column flag itself as sorted.
+  table.columns_[od.front().col_idx].flags_ |= Column::Flag::kSorted;
 
   return table;
 }
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index fb8b73b..bc515cd 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -150,12 +150,11 @@
   //  * |left|'s values must exist in |right|
   Table LookupJoin(JoinKey left, const Table& other, JoinKey right);
 
-  // Extends the table with a new column called |name| with data |sv|.
   template <typename T>
   Table ExtendWithColumn(const char* name,
                          std::unique_ptr<NullableVector<T>> sv,
                          uint32_t flags) const {
-    PERFETTO_CHECK(sv->size() == row_count_);
+    PERFETTO_DCHECK(sv->size() == row_count_);
     uint32_t size = sv->size();
     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
     Table ret = Copy();
@@ -165,21 +164,6 @@
     return ret;
   }
 
-  // Extends the table with a new column called |name| with data |sv|.
-  template <typename T>
-  Table ExtendWithColumn(const char* name,
-                         NullableVector<T>* sv,
-                         uint32_t flags) const {
-    PERFETTO_CHECK(sv->size() == row_count_);
-    uint32_t size = sv->size();
-    uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
-    Table ret = Copy();
-    ret.columns_.push_back(
-        Column(name, sv, flags, &ret, GetColumnCount(), row_map_count));
-    ret.row_maps_.emplace_back(RowMap(0, size));
-    return ret;
-  }
-
   // Returns the column at index |idx| in the Table.
   const Column& GetColumn(uint32_t idx) const { return columns_[idx]; }
 
@@ -194,13 +178,13 @@
   }
 
   template <typename T>
-  const TypedColumn<T>& GetTypedColumnByName(const char* name) const {
-    return *TypedColumn<T>::FromColumn(GetColumnByName(name));
+  const TypedColumn<T>* GetTypedColumnByName(const char* name) const {
+    return TypedColumn<T>::FromColumn(GetColumnByName(name));
   }
 
   template <typename T>
-  const IdColumn<T>& GetIdColumnByName(const char* name) const {
-    return *IdColumn<T>::FromColumn(GetColumnByName(name));
+  const IdColumn<T>* GetIdColumnByName(const char* name) const {
+    return IdColumn<T>::FromColumn(GetColumnByName(name));
   }
 
   // Returns the number of columns in the Table.
@@ -211,9 +195,6 @@
   // Returns an iterator into the Table.
   Iterator IterateRows() const { return Iterator(this); }
 
-  // Creates a copy of this table.
-  Table Copy() const;
-
   uint32_t row_count() const { return row_count_; }
   const std::vector<RowMap>& row_maps() const { return row_maps_; }
 
@@ -229,6 +210,7 @@
  private:
   friend class Column;
 
+  Table Copy() const;
   Table CopyExceptRowMaps() const;
 };
 
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
index a8fc424..2bef075 100644
--- a/src/trace_processor/db/typed_column.h
+++ b/src/trace_processor/db/typed_column.h
@@ -34,8 +34,8 @@
 //    overhead.
 // 2. Ergonomics: having to convert back and forth from/to SqlValue causes
 //    signifcant clutter in parts of the code which can already be quite hard
-//    to follow (e.g. trackers like SequenceStackProfileTracker which perform
-//    cross checking of various ids).
+//    to follow (e.g. trackers like StackProfileTracker which perform cross
+//    checking of various ids).
 //
 // Implementation:
 // TypedColumn is implemented as a memberless subclass of Column. This allows
diff --git a/src/trace_processor/db/typed_column_internal.h b/src/trace_processor/db/typed_column_internal.h
index 53898ad..128dd80 100644
--- a/src/trace_processor/db/typed_column_internal.h
+++ b/src/trace_processor/db/typed_column_internal.h
@@ -91,8 +91,7 @@
 struct TypeHandler {
   using non_optional_type = T;
   using get_type = T;
-  using sql_value_type =
-      typename Serializer<non_optional_type>::serialized_type;
+  using sql_value_type = T;
 
   static constexpr bool is_optional = false;
   static constexpr bool is_string = false;
@@ -116,8 +115,7 @@
 struct TypeHandler<base::Optional<T>> {
   using non_optional_type = T;
   using get_type = base::Optional<T>;
-  using sql_value_type =
-      typename Serializer<non_optional_type>::serialized_type;
+  using sql_value_type = T;
 
   static constexpr bool is_optional = true;
   static constexpr bool is_string = false;
diff --git a/src/trace_processor/dynamic/ancestor_generator.cc b/src/trace_processor/dynamic/ancestor_generator.cc
deleted file mode 100644
index 3db6d3d..0000000
--- a/src/trace_processor/dynamic/ancestor_generator.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/ancestor_generator.h"
-
-#include <memory>
-#include <set>
-
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-uint32_t GetConstraintColumnIndex(AncestorGenerator::Ancestor type,
-                                  TraceProcessorContext* context) {
-  switch (type) {
-    case AncestorGenerator::Ancestor::kSlice:
-      return context->storage->slice_table().GetColumnCount();
-    case AncestorGenerator::Ancestor::kStackProfileCallsite:
-      return context->storage->stack_profile_callsite_table().GetColumnCount();
-  }
-  return 0;
-}
-
-template <typename T>
-base::Optional<RowMap> BuildAncestorsRowMap(const T& table,
-                                            typename T::Id starting_id) {
-  auto start_row = table.id().IndexOf(starting_id);
-
-  if (!start_row) {
-    // TODO(lalitm): Ideally this should result in an error, or be filtered out
-    // during ValidateConstraints so we can just dereference |start_row|
-    // directly. However ValidateConstraints doesn't know the value we're
-    // filtering for so can't ensure it exists. For now we return a nullptr
-    // which will cause the query to surface an error with the message "SQL
-    // error: constraint failed".
-    return base::nullopt;
-  }
-
-  std::vector<uint32_t> parent_rows;
-  auto maybe_parent_id = table.parent_id()[*start_row];
-  while (maybe_parent_id) {
-    uint32_t parent_row = table.id().IndexOf(*maybe_parent_id).value();
-    parent_rows.push_back(parent_row);
-    // Update the loop variable by looking up the next parent_id.
-    maybe_parent_id = table.parent_id()[parent_row];
-  }
-  return RowMap(std::move(parent_rows));
-}
-
-template <typename T>
-std::unique_ptr<Table> BuildAncestorsTable(const T& table,
-                                           typename T::Id starting_id) {
-  // Build up all the parents row ids.
-  auto ancestors = BuildAncestorsRowMap(table, starting_id);
-  if (!ancestors) {
-    return nullptr;
-  }
-  // Add a new column that includes the constraint.
-  std::unique_ptr<NullableVector<uint32_t>> child_ids(
-      new NullableVector<uint32_t>());
-  for (uint32_t i = 0; i < ancestors->size(); ++i)
-    child_ids->Append(starting_id.value);
-  return std::unique_ptr<Table>(
-      new Table(table.Apply(std::move(*ancestors))
-                    .ExtendWithColumn("start_id", std::move(child_ids),
-                                      TypedColumn<uint32_t>::default_flags() |
-                                          TypedColumn<uint32_t>::kHidden)));
-}
-}  // namespace
-
-AncestorGenerator::AncestorGenerator(Ancestor type,
-                                     TraceProcessorContext* context)
-    : type_(type), context_(context) {}
-
-util::Status AncestorGenerator::ValidateConstraints(
-    const QueryConstraints& qc) {
-  const auto& cs = qc.constraints();
-
-  int column = static_cast<int>(GetConstraintColumnIndex(type_, context_));
-  auto id_fn = [column](const QueryConstraints::Constraint& c) {
-    return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
-  };
-  bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
-  return has_id_cs ? util::OkStatus()
-                   : util::ErrStatus("Failed to find required constraints");
-}
-
-std::unique_ptr<Table> AncestorGenerator::ComputeTable(
-    const std::vector<Constraint>& cs,
-    const std::vector<Order>&) {
-  uint32_t column = GetConstraintColumnIndex(type_, context_);
-  auto it = std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
-    return c.col_idx == column && c.op == FilterOp::kEq;
-  });
-  PERFETTO_DCHECK(it != cs.end());
-
-  auto start_id = static_cast<uint32_t>(it->value.AsLong());
-  switch (type_) {
-    case Ancestor::kSlice:
-      return BuildAncestorsTable(context_->storage->slice_table(),
-                                 SliceId(start_id));
-    case Ancestor::kStackProfileCallsite:
-      return BuildAncestorsTable(
-          context_->storage->stack_profile_callsite_table(),
-          CallsiteId(start_id));
-  }
-  return nullptr;
-}
-
-Table::Schema AncestorGenerator::CreateSchema() {
-  Table::Schema final_schema;
-  switch (type_) {
-    case Ancestor::kSlice:
-      final_schema = tables::SliceTable::Schema();
-      break;
-    case Ancestor::kStackProfileCallsite:
-      final_schema = tables::StackProfileCallsiteTable::Schema();
-      break;
-  }
-  final_schema.columns.push_back(Table::Schema::Column{
-      "start_id", SqlValue::Type::kLong, /* is_id = */ false,
-      /* is_sorted = */ false, /* is_hidden = */ true});
-  return final_schema;
-}
-
-std::string AncestorGenerator::TableName() {
-  switch (type_) {
-    case Ancestor::kSlice:
-      return "ancestor_slice";
-    case Ancestor::kStackProfileCallsite:
-      return "experimental_ancestor_stack_profile_callsite";
-  }
-  return "ancestor_unknown";
-}
-
-uint32_t AncestorGenerator::EstimateRowCount() {
-  return 1;
-}
-
-// static
-base::Optional<RowMap> AncestorGenerator::GetAncestorSlices(
-    const tables::SliceTable& slices,
-    SliceId slice_id) {
-  return BuildAncestorsRowMap(slices, slice_id);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/ancestor_generator.h b/src/trace_processor/dynamic/ancestor_generator.h
deleted file mode 100644
index bf6324e..0000000
--- a/src/trace_processor/dynamic/ancestor_generator.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_ANCESTOR_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_ANCESTOR_GENERATOR_H_
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Implements the following dynamic tables:
-// * ancestor_slice
-// * experimental_ancestor_stack_profile_callsite
-//
-// See docs/analysis/trace-processor for usage.
-class AncestorGenerator : public DbSqliteTable::DynamicTableGenerator {
- public:
-  enum class Ancestor { kSlice = 1, kStackProfileCallsite = 2 };
-
-  AncestorGenerator(Ancestor type, TraceProcessorContext* context);
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
-                                      const std::vector<Order>& ob) override;
-
-  // Returns a RowMap of slice IDs which are ancestors of |slice_id|. Returns
-  // NULL if an invalid |slice_id| is given. This is used by
-  // ConnectedFlowGenerator to traverse flow indirectly connected flow events.
-  static base::Optional<RowMap> GetAncestorSlices(
-      const tables::SliceTable& slices,
-      SliceId slice_id);
-
- private:
-  Ancestor type_;
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_ANCESTOR_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/connected_flow_generator.cc b/src/trace_processor/dynamic/connected_flow_generator.cc
deleted file mode 100644
index c8fb57d..0000000
--- a/src/trace_processor/dynamic/connected_flow_generator.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/connected_flow_generator.h"
-
-#include <memory>
-#include <queue>
-#include <set>
-
-#include "src/trace_processor/dynamic/ancestor_generator.h"
-#include "src/trace_processor/dynamic/descendant_slice_generator.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-ConnectedFlowGenerator::ConnectedFlowGenerator(Mode mode,
-                                               TraceProcessorContext* context)
-    : mode_(mode), context_(context) {}
-
-ConnectedFlowGenerator::~ConnectedFlowGenerator() = default;
-
-util::Status ConnectedFlowGenerator::ValidateConstraints(
-    const QueryConstraints& qc) {
-  const auto& cs = qc.constraints();
-
-  auto flow_id_fn = [this](const QueryConstraints::Constraint& c) {
-    return c.column == static_cast<int>(
-                           context_->storage->flow_table().GetColumnCount()) &&
-           c.op == SQLITE_INDEX_CONSTRAINT_EQ;
-  };
-  bool has_flow_id_cs =
-      std::find_if(cs.begin(), cs.end(), flow_id_fn) != cs.end();
-
-  return has_flow_id_cs
-             ? util::OkStatus()
-             : util::ErrStatus("Failed to find required constraints");
-}
-
-namespace {
-
-enum FlowVisitMode : uint8_t {
-  VISIT_INCOMING = 1 << 0,
-  VISIT_OUTGOING = 1 << 1,
-  VISIT_INCOMING_AND_OUTGOING = VISIT_INCOMING | VISIT_OUTGOING,
-};
-
-enum RelativesVisitMode : uint8_t {
-  VISIT_NO_RELATIVES = 0,
-  VISIT_ANCESTORS = 1 << 0,
-  VISIT_DESCENDANTS = 1 << 1,
-  VISIT_ALL_RELATIVES = VISIT_ANCESTORS | VISIT_DESCENDANTS,
-};
-
-// Searches through the slice table recursively to find connected flows.
-// Usage:
-//  BFS bfs = BFS(context);
-//  bfs
-//    // Add list of slices to start with.
-//    .Start(start_id).Start(start_id2)
-//    // Additionally include relatives of |another_id| in search space.
-//    .GoToRelatives(another_id, VISIT_ANCESTORS)
-//    // Visit all connected slices to the above slices.
-//    .VisitAll(VISIT_INCOMING, VISIT_NO_RELATIVES);
-//
-//  bfs.TakeResultingFlows();
-class BFS {
- public:
-  BFS(TraceProcessorContext* context) : context_(context) {}
-
-  RowMap TakeResultingFlows() && { return RowMap(std::move(flow_rows_)); }
-
-  // Includes a starting slice ID to search.
-  BFS& Start(SliceId start_id) {
-    slices_to_visit_.push({start_id, VisitType::START});
-    known_slices_.insert(start_id);
-    return *this;
-  }
-
-  // Visits all slices that can be reached from the given starting slices.
-  void VisitAll(FlowVisitMode visit_flow, RelativesVisitMode visit_relatives) {
-    while (!slices_to_visit_.empty()) {
-      SliceId slice_id = slices_to_visit_.front().first;
-      VisitType visit_type = slices_to_visit_.front().second;
-      slices_to_visit_.pop();
-
-      // If the given slice is being visited due to being ancestor or descendant
-      // of a previous one, do not compute ancestors or descendants again as the
-      // result is going to be the same.
-      if (visit_type != VisitType::VIA_RELATIVE) {
-        GoToRelatives(slice_id, visit_relatives);
-      }
-
-      // If the slice was visited by a flow, do not try to go back.
-      if ((visit_flow & VISIT_INCOMING) &&
-          visit_type != VisitType::VIA_OUTGOING_FLOW) {
-        GoByFlow(slice_id, FlowDirection::INCOMING);
-      }
-      if ((visit_flow & VISIT_OUTGOING) &&
-          visit_type != VisitType::VIA_INCOMING_FLOW) {
-        GoByFlow(slice_id, FlowDirection::OUTGOING);
-      }
-    }
-  }
-
-  // Includes the relatives of |slice_id| to the list of slices to visit.
-  BFS& GoToRelatives(SliceId slice_id, RelativesVisitMode visit_relatives) {
-    if (visit_relatives & VISIT_ANCESTORS) {
-      base::Optional<RowMap> ancestors = AncestorGenerator::GetAncestorSlices(
-          context_->storage->slice_table(), slice_id);
-      if (ancestors)
-        GoToRelativesImpl(ancestors->IterateRows());
-    }
-    if (visit_relatives & VISIT_DESCENDANTS) {
-      base::Optional<RowMap> descendants =
-          DescendantSliceGenerator::GetDescendantSlices(
-              context_->storage->slice_table(), slice_id);
-      GoToRelativesImpl(descendants->IterateRows());
-    }
-    return *this;
-  }
-
- private:
-  enum class FlowDirection {
-    INCOMING,
-    OUTGOING,
-  };
-
-  enum class VisitType {
-    START,
-    VIA_INCOMING_FLOW,
-    VIA_OUTGOING_FLOW,
-    VIA_RELATIVE,
-  };
-
-  void GoByFlow(SliceId slice_id, FlowDirection flow_direction) {
-    PERFETTO_DCHECK(known_slices_.count(slice_id) != 0);
-
-    const auto& flow = context_->storage->flow_table();
-
-    const TypedColumn<SliceId>& start_col =
-        (flow_direction == FlowDirection::OUTGOING ? flow.slice_out()
-                                                   : flow.slice_in());
-    const TypedColumn<SliceId>& end_col =
-        (flow_direction == FlowDirection::OUTGOING ? flow.slice_in()
-                                                   : flow.slice_out());
-
-    auto rows = flow.FilterToRowMap({start_col.eq(slice_id.value)});
-
-    for (auto row_it = rows.IterateRows(); row_it; row_it.Next()) {
-      flow_rows_.push_back(row_it.row());
-      SliceId next_slice_id = end_col[row_it.row()];
-      if (known_slices_.count(next_slice_id) != 0) {
-        continue;
-      }
-
-      known_slices_.insert(next_slice_id);
-      slices_to_visit_.push(
-          {next_slice_id, flow_direction == FlowDirection::INCOMING
-                              ? VisitType::VIA_INCOMING_FLOW
-                              : VisitType::VIA_OUTGOING_FLOW});
-    }
-  }
-
-  void GoToRelativesImpl(RowMap::Iterator it) {
-    const auto& slice = context_->storage->slice_table();
-    for (; it; it.Next()) {
-      auto relative_slice_id = slice.id()[it.row()];
-      if (known_slices_.count(relative_slice_id))
-        continue;
-      known_slices_.insert(relative_slice_id);
-      slices_to_visit_.push({relative_slice_id, VisitType::VIA_RELATIVE});
-    }
-  }
-
-  std::queue<std::pair<SliceId, VisitType>> slices_to_visit_;
-  std::set<SliceId> known_slices_;
-  std::vector<uint32_t> flow_rows_;
-
-  TraceProcessorContext* context_;
-};
-
-}  // namespace
-
-std::unique_ptr<Table> ConnectedFlowGenerator::ComputeTable(
-    const std::vector<Constraint>& cs,
-    const std::vector<Order>&) {
-  const auto& flow = context_->storage->flow_table();
-  const auto& slice = context_->storage->slice_table();
-
-  auto it = std::find_if(cs.begin(), cs.end(), [&flow](const Constraint& c) {
-    return c.col_idx == flow.GetColumnCount() && c.op == FilterOp::kEq;
-  });
-
-  PERFETTO_DCHECK(it != cs.end());
-
-  SliceId start_id{static_cast<uint32_t>(it->value.AsLong())};
-
-  if (!slice.id().IndexOf(start_id)) {
-    PERFETTO_ELOG("Given slice id is invalid (ConnectedFlowGenerator)");
-    return nullptr;
-  }
-
-  BFS bfs(context_);
-
-  switch (mode_) {
-    case Mode::kDirectlyConnectedFlow:
-      bfs.Start(start_id).VisitAll(VISIT_INCOMING_AND_OUTGOING,
-                                   VISIT_NO_RELATIVES);
-      break;
-    case Mode::kFollowingFlow:
-      bfs.Start(start_id).VisitAll(VISIT_OUTGOING, VISIT_DESCENDANTS);
-      break;
-    case Mode::kPrecedingFlow:
-      bfs.Start(start_id).VisitAll(VISIT_INCOMING, VISIT_ANCESTORS);
-      break;
-  }
-
-  RowMap result_rows = std::move(bfs).TakeResultingFlows();
-
-  // Aditional column for start_id
-  std::unique_ptr<NullableVector<uint32_t>> start_ids(
-      new NullableVector<uint32_t>());
-
-  for (size_t i = 0; i < result_rows.size(); i++) {
-    start_ids->Append(start_id.value);
-  }
-
-  return std::unique_ptr<Table>(
-      new Table(flow.Apply(RowMap(std::move(result_rows)))
-                    .ExtendWithColumn("start_id", std::move(start_ids),
-                                      TypedColumn<uint32_t>::default_flags() |
-                                          TypedColumn<uint32_t>::kHidden)));
-}
-
-Table::Schema ConnectedFlowGenerator::CreateSchema() {
-  auto schema = tables::FlowTable::Schema();
-  schema.columns.push_back(Table::Schema::Column{
-      "start_id", SqlValue::Type::kLong, /* is_id = */ false,
-      /* is_sorted = */ false, /* is_hidden = */ true});
-  return schema;
-}
-
-std::string ConnectedFlowGenerator::TableName() {
-  switch (mode_) {
-    case Mode::kDirectlyConnectedFlow:
-      return "directly_connected_flow";
-    case Mode::kFollowingFlow:
-      return "following_flow";
-    case Mode::kPrecedingFlow:
-      return "preceding_flow";
-  }
-  PERFETTO_FATAL("Unexpected ConnectedFlowType");
-}
-
-uint32_t ConnectedFlowGenerator::EstimateRowCount() {
-  return 1;
-}
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/connected_flow_generator.h b/src/trace_processor/dynamic/connected_flow_generator.h
deleted file mode 100644
index e6d01b3..0000000
--- a/src/trace_processor/dynamic/connected_flow_generator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_CONNECTED_FLOW_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_CONNECTED_FLOW_GENERATOR_H_
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-
-#include "src/trace_processor/storage/trace_storage.h"
-
-#include <queue>
-#include <set>
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Implementation of tables:
-// - DIRECTLY_CONNECTED_FLOW
-// - PRECEDING_FLOW
-// - FOLLOWING_FLOW
-class ConnectedFlowGenerator : public DbSqliteTable::DynamicTableGenerator {
- public:
-  enum class Mode {
-    // Directly connected slices through the same flow ID given by the trace
-    // writer.
-    kDirectlyConnectedFlow,
-    // Flow events which can be reached from the given slice by going over
-    // incoming flow events or to parent slices.
-    kPrecedingFlow,
-    // Flow events which can be reached from the given slice by going over
-    // outgoing flow events or to child slices.
-    kFollowingFlow,
-  };
-
-  ConnectedFlowGenerator(Mode mode, TraceProcessorContext* context);
-  ~ConnectedFlowGenerator() override;
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
-                                      const std::vector<Order>& ob) override;
-
- private:
-  Mode mode_;
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_CONNECTED_FLOW_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/descendant_slice_generator.cc b/src/trace_processor/dynamic/descendant_slice_generator.cc
deleted file mode 100644
index d42a6a9..0000000
--- a/src/trace_processor/dynamic/descendant_slice_generator.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/descendant_slice_generator.h"
-
-#include <memory>
-#include <set>
-
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-DescendantSliceGenerator::DescendantSliceGenerator(
-    TraceProcessorContext* context)
-    : context_(context) {}
-
-DescendantSliceGenerator::~DescendantSliceGenerator() = default;
-
-util::Status DescendantSliceGenerator::ValidateConstraints(
-    const QueryConstraints& qc) {
-  const auto& cs = qc.constraints();
-
-  auto slice_id_fn = [this](const QueryConstraints::Constraint& c) {
-    return c.column == static_cast<int>(
-                           context_->storage->slice_table().GetColumnCount()) &&
-           c.op == SQLITE_INDEX_CONSTRAINT_EQ;
-  };
-  bool has_slice_id_cs =
-      std::find_if(cs.begin(), cs.end(), slice_id_fn) != cs.end();
-
-  return has_slice_id_cs
-             ? util::OkStatus()
-             : util::ErrStatus("Failed to find required constraints");
-}
-
-std::unique_ptr<Table> DescendantSliceGenerator::ComputeTable(
-    const std::vector<Constraint>& cs,
-    const std::vector<Order>&) {
-  const auto& slice = context_->storage->slice_table();
-
-  auto it = std::find_if(cs.begin(), cs.end(), [&slice](const Constraint& c) {
-    return c.col_idx == slice.GetColumnCount() && c.op == FilterOp::kEq;
-  });
-  PERFETTO_DCHECK(it != cs.end());
-
-  uint32_t start_id = static_cast<uint32_t>(it->value.AsLong());
-  auto descendants = GetDescendantSlices(slice, SliceId(start_id));
-  if (!descendants)
-    return nullptr;
-  Table reduced_slice = slice.Apply(std::move(*descendants));
-
-  // For every row extend it to match the schema, and return it.
-  std::unique_ptr<NullableVector<uint32_t>> start_ids(
-      new NullableVector<uint32_t>());
-  for (size_t i = 0; i < reduced_slice.row_count(); ++i) {
-    start_ids->Append(start_id);
-  }
-  return std::unique_ptr<Table>(
-      new Table(std::move(reduced_slice)
-                    .ExtendWithColumn("start_id", std::move(start_ids),
-                                      TypedColumn<uint32_t>::default_flags() |
-                                          TypedColumn<uint32_t>::kHidden)));
-}
-
-Table::Schema DescendantSliceGenerator::CreateSchema() {
-  auto schema = tables::SliceTable::Schema();
-  schema.columns.push_back(Table::Schema::Column{
-      "start_id", SqlValue::Type::kLong, /* is_id = */ false,
-      /* is_sorted = */ false, /* is_hidden = */ true});
-  return schema;
-}
-
-std::string DescendantSliceGenerator::TableName() {
-  return "descendant_slice";
-}
-
-uint32_t DescendantSliceGenerator::EstimateRowCount() {
-  return 1;
-}
-
-// static
-base::Optional<RowMap> DescendantSliceGenerator::GetDescendantSlices(
-    const tables::SliceTable& slice,
-    SliceId start_id) {
-  auto start_row = slice.id().IndexOf(start_id);
-  // The query gave an invalid ID that doesn't exist in the slice table.
-  if (!start_row) {
-    // TODO(lalitm): Ideally this should result in an error, or be filtered out
-    // during ValidateConstraints so we can just dereference |start_row|
-    // directly. However ValidateConstraints doesn't know the value we're
-    // filtering for so can't ensure it exists. For now we return a nullptr
-    // which will cause the query to surface an error with the message "SQL
-    // error: constraint failed".
-    return base::nullopt;
-  }
-
-  // All nested descendents must be on the same track, with a ts between
-  // |start_id.ts| and |start_id.ts| + |start_id.dur|, and who's depth is larger
-  // then |start_row|'s. So we just use Filter to select all relevant slices.
-  return slice.FilterToRowMap(
-      {slice.ts().ge(slice.ts()[*start_row]),
-       slice.ts().le(slice.ts()[*start_row] + slice.dur()[*start_row]),
-       slice.track_id().eq(slice.track_id()[*start_row].value),
-       slice.depth().gt(slice.depth()[*start_row])});
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/descendant_slice_generator.h b/src/trace_processor/dynamic/descendant_slice_generator.h
deleted file mode 100644
index c152f7a..0000000
--- a/src/trace_processor/dynamic/descendant_slice_generator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Dynamic table for implementing the  table.
-// See /docs/analysis.md for details about the functionality and usage of this
-// table.
-class DescendantSliceGenerator : public DbSqliteTable::DynamicTableGenerator {
- public:
-  explicit DescendantSliceGenerator(TraceProcessorContext* context);
-  ~DescendantSliceGenerator() override;
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
-                                      const std::vector<Order>& ob) override;
-
-  // Returns a RowMap of slice IDs which are descendants of |slice_id|. Returns
-  // NULL if an invalid |slice_id| is given. This is used by
-  // ConnectedFlowGenerator to traverse flow indirectly connected flow events.
-  static base::Optional<RowMap> GetDescendantSlices(
-      const tables::SliceTable& slices,
-      SliceId start_id);
-
- private:
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_DESCENDANT_SLICE_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
deleted file mode 100644
index 1af5ad1..0000000
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/dynamic/experimental_annotated_stack_generator.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/profiler_tables.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-#include "perfetto/ext/base/string_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-enum class MapType {
-  kArtInterp,
-  kArtJit,
-  kArtAot,
-  kNativeLibart,
-  kNativeOther,
-  kOther
-};
-
-// Mapping examples:
-//   /system/lib64/libc.so
-//   /system/framework/framework.jar
-//   /memfd:jit-cache (deleted)
-//   [vdso]
-// TODO(rsavitski): consider moving this to a hidden column on
-// stack_profile_mapping, once this logic is sufficiently stable.
-MapType ClassifyMap(NullTermStringView map) {
-  if (map.empty())
-    return MapType::kOther;
-
-  // Primary mapping where modern ART puts jitted code.
-  // TODO(rsavitski): look into /memfd:jit-zygote-cache.
-  if (!strncmp(map.c_str(), "/memfd:jit-cache", 16))
-    return MapType::kArtJit;
-
-  size_t last_slash_pos = map.rfind('/');
-  if (last_slash_pos != NullTermStringView::npos) {
-    if (!strncmp(map.c_str() + last_slash_pos, "/libart.so", 10))
-      return MapType::kNativeLibart;
-    if (!strncmp(map.c_str() + last_slash_pos, "/libartd.so", 11))
-      return MapType::kNativeLibart;
-  }
-
-  size_t extension_pos = map.rfind('.');
-  if (extension_pos != NullTermStringView::npos) {
-    if (!strncmp(map.c_str() + extension_pos, ".so", 3))
-      return MapType::kNativeOther;
-    // dex with verification speedup info, produced by dex2oat
-    if (!strncmp(map.c_str() + extension_pos, ".vdex", 5))
-      return MapType::kArtInterp;
-    // possibly uncompressed dex in a jar archive
-    if (!strncmp(map.c_str() + extension_pos, ".jar", 4))
-      return MapType::kArtInterp;
-    // ahead of time compiled ELFs
-    if (!strncmp(map.c_str() + extension_pos, ".oat", 4))
-      return MapType::kArtAot;
-    // older/alternative name for .oat
-    if (!strncmp(map.c_str() + extension_pos, ".odex", 5))
-      return MapType::kArtAot;
-  }
-  return MapType::kOther;
-}
-
-uint32_t GetConstraintColumnIndex(TraceProcessorContext* context) {
-  // The dynamic table adds two columns on top of the callsite table. Last
-  // column is the hidden constrain (i.e. input arg) column.
-  return context->storage->stack_profile_callsite_table().GetColumnCount() + 1;
-}
-
-}  // namespace
-
-std::string ExperimentalAnnotatedStackGenerator::TableName() {
-  return "experimental_annotated_callstack";
-}
-
-Table::Schema ExperimentalAnnotatedStackGenerator::CreateSchema() {
-  auto schema = tables::StackProfileCallsiteTable::Schema();
-  schema.columns.push_back(Table::Schema::Column{
-      "annotation", SqlValue::Type::kString, /* is_id = */ false,
-      /* is_sorted = */ false, /* is_hidden = */ false});
-  schema.columns.push_back(Table::Schema::Column{
-      "start_id", SqlValue::Type::kLong, /* is_id = */ false,
-      /* is_sorted = */ false, /* is_hidden = */ true});
-  return schema;
-}
-
-util::Status ExperimentalAnnotatedStackGenerator::ValidateConstraints(
-    const QueryConstraints& qc) {
-  const auto& cs = qc.constraints();
-  int column = static_cast<int>(GetConstraintColumnIndex(context_));
-
-  auto id_fn = [column](const QueryConstraints::Constraint& c) {
-    return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
-  };
-  bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
-  return has_id_cs ? util::OkStatus()
-                   : util::ErrStatus("Failed to find required constraints");
-}
-
-std::unique_ptr<Table> ExperimentalAnnotatedStackGenerator::ComputeTable(
-    const std::vector<Constraint>& cs,
-    const std::vector<Order>&) {
-  const auto& cs_table = context_->storage->stack_profile_callsite_table();
-  const auto& f_table = context_->storage->stack_profile_frame_table();
-  const auto& m_table = context_->storage->stack_profile_mapping_table();
-
-  // Input (id of the callsite leaf) is the constraint on the hidden |start_id|
-  // column.
-  uint32_t constraint_col = GetConstraintColumnIndex(context_);
-  auto constraint_it =
-      std::find_if(cs.begin(), cs.end(), [constraint_col](const Constraint& c) {
-        return c.col_idx == constraint_col && c.op == FilterOp::kEq;
-      });
-  PERFETTO_DCHECK(constraint_it != cs.end());
-
-  auto start_id = static_cast<uint32_t>(constraint_it->value.AsLong());
-  base::Optional<uint32_t> start_row =
-      cs_table.id().IndexOf(CallsiteId(start_id));
-  if (!start_row)
-    return nullptr;
-
-  // Iteratively walk the parent_id chain to construct the list of callstack
-  // entries, each pointing at a frame.
-  std::vector<uint32_t> cs_rows;
-  cs_rows.push_back(*start_row);
-  base::Optional<CallsiteId> maybe_parent_id = cs_table.parent_id()[*start_row];
-  while (maybe_parent_id) {
-    uint32_t parent_row = cs_table.id().IndexOf(*maybe_parent_id).value();
-    cs_rows.push_back(parent_row);
-    maybe_parent_id = cs_table.parent_id()[parent_row];
-  }
-
-  // Walk the callsites root-to-leaf, annotating:
-  // * managed frames with their execution state (interpreted/jit/aot)
-  // * common ART frames, which are usually not relevant
-  //
-  // This is not a per-frame decision, because we do not want to filter out ART
-  // frames immediately after a JNI transition (such frames are often relevant).
-  //
-  // As a consequence of the logic being based on a root-to-leaf walk, a given
-  // callsite will always have the same annotation, as the parent path is always
-  // the same, and children callsites do not affect their parents' annotations.
-  //
-  // This could also be implemented as a hidden column on the callsite table
-  // (populated at import time), but we want to be more flexible for now.
-  StringId art_jni_trampoline =
-      context_->storage->InternString("art_jni_trampoline");
-
-  StringId common_frame = context_->storage->InternString("common-frame");
-  StringId art_interp = context_->storage->InternString("interp");
-  StringId art_jit = context_->storage->InternString("jit");
-  StringId art_aot = context_->storage->InternString("aot");
-
-  // Annotation FSM states:
-  // * kInitial: default, native-only callstacks never leave this state.
-  // * kEraseLibart: we've seen a managed frame, and will now "erase" (i.e. tag
-  //                 as a common-frame) frames belonging to the ART runtime.
-  // * kKeepNext: we've seen a special JNI trampoline for managed->native
-  //              transition, keep the immediate child (even if it is in ART),
-  //              and then go back to kEraseLibart.
-  // Regardless of the state, managed frames get annotated with their execution
-  // mode, based on the mapping.
-  enum class State { kInitial, kEraseLibart, kKeepNext };
-  State annotation_state = State::kInitial;
-
-  std::vector<StringPool::Id> annotations_reversed;
-  for (auto it = cs_rows.rbegin(); it != cs_rows.rend(); ++it) {
-    FrameId frame_id = cs_table.frame_id()[*it];
-    uint32_t frame_row = f_table.id().IndexOf(frame_id).value();
-
-    MappingId map_id = f_table.mapping()[frame_row];
-    uint32_t map_row = m_table.id().IndexOf(map_id).value();
-
-    // Keep immediate callee of a JNI trampoline, but keep tagging all
-    // successive libart frames as common.
-    if (annotation_state == State::kKeepNext) {
-      annotations_reversed.push_back(kNullStringId);
-      annotation_state = State::kEraseLibart;
-      continue;
-    }
-
-    // Special-case "art_jni_trampoline" frames, keeping their immediate callee
-    // even if it is in libart, as it could be a native implementation of a
-    // managed method. Example for "java.lang.reflect.Method.Invoke":
-    //   art_jni_trampoline
-    //   art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)
-    //
-    // Simpleperf also relies on this frame name, so it should be fairly stable.
-    // TODO(rsavitski): consider detecting standard JNI upcall entrypoints -
-    // _JNIEnv::Call*. These are sometimes inlined into other DSOs, so erasing
-    // only the libart frames does not clean up all of the JNI-related frames.
-    StringId fname_id = f_table.name()[frame_row];
-    if (fname_id == art_jni_trampoline) {
-      annotations_reversed.push_back(common_frame);
-      annotation_state = State::kKeepNext;
-      continue;
-    }
-
-    NullTermStringView map_view =
-        context_->storage->GetString(m_table.name()[map_row]);
-    MapType map_type = ClassifyMap(map_view);
-
-    // Annotate managed frames.
-    if (map_type == MapType::kArtInterp ||  //
-        map_type == MapType::kArtJit ||     //
-        map_type == MapType::kArtAot) {
-      if (map_type == MapType::kArtInterp)
-        annotations_reversed.push_back(art_interp);
-      else if (map_type == MapType::kArtJit)
-        annotations_reversed.push_back(art_jit);
-      else if (map_type == MapType::kArtAot)
-        annotations_reversed.push_back(art_aot);
-
-      // Now know to be in a managed callstack - erase subsequent ART frames.
-      if (annotation_state == State::kInitial)
-        annotation_state = State::kEraseLibart;
-      continue;
-    }
-
-    if (annotation_state == State::kEraseLibart &&
-        map_type == MapType::kNativeLibart) {
-      annotations_reversed.push_back(common_frame);
-      continue;
-    }
-
-    annotations_reversed.push_back(kNullStringId);
-  }
-
-  // Build the dynamic table.
-  auto base_rowmap = RowMap(std::move(cs_rows));
-
-  PERFETTO_DCHECK(base_rowmap.size() == annotations_reversed.size());
-  std::unique_ptr<NullableVector<StringPool::Id>> annotation_vals(
-      new NullableVector<StringPool::Id>());
-  for (auto it = annotations_reversed.rbegin();
-       it != annotations_reversed.rend(); ++it) {
-    annotation_vals->Append(*it);
-  }
-
-  // Hidden column - always the input, i.e. the callsite leaf.
-  std::unique_ptr<NullableVector<uint32_t>> start_id_vals(
-      new NullableVector<uint32_t>());
-  for (uint32_t i = 0; i < base_rowmap.size(); i++)
-    start_id_vals->Append(start_id);
-
-  return std::unique_ptr<Table>(new Table(
-      cs_table.Apply(std::move(base_rowmap))
-          .ExtendWithColumn("annotation", std::move(annotation_vals),
-                            TypedColumn<StringPool::Id>::default_flags())
-          .ExtendWithColumn("start_id", std::move(start_id_vals),
-                            TypedColumn<uint32_t>::default_flags() |
-                                TypedColumn<uint32_t>::kHidden)));
-}
-
-uint32_t ExperimentalAnnotatedStackGenerator::EstimateRowCount() {
-  return 1;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
deleted file mode 100644
index 7e6a62d..0000000
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// The "experimental_annotated_callstack" dynamic table.
-//
-// Given a leaf callsite id, returns the full callstack (including the leaf),
-// with optional (currently Android-specific) annotations. A given callsite will
-// always have the same annotation.
-class ExperimentalAnnotatedStackGenerator
-    : public DbSqliteTable::DynamicTableGenerator {
- public:
-  ExperimentalAnnotatedStackGenerator(TraceProcessorContext* context)
-      : context_(context) {}
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
-                                      const std::vector<Order>& ob) override;
-
- private:
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
index 88d167f..5f1e47c 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
@@ -29,9 +29,6 @@
   schema.columns.emplace_back(
       Table::Schema::Column{"dur", SqlValue::Type::kLong, false /* is_id */,
                             false /* is_sorted */, false /* is_hidden */});
-  schema.columns.emplace_back(
-      Table::Schema::Column{"delta", SqlValue::Type::kLong, false /* is_id */,
-                            false /* is_sorted */, false /* is_hidden */});
   return schema;
 }
 
@@ -49,22 +46,21 @@
 }
 
 std::unique_ptr<Table> ExperimentalCounterDurGenerator::ComputeTable(
-    const std::vector<Constraint>&,
+    const std::vector<Constraint>& cs,
     const std::vector<Order>&) {
-  if (!dur_column_) {
-    dur_column_.reset(
-        new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
-    delta_column_.reset(
-        new NullableVector<double>(ComputeDeltaColumn(*counter_table_)));
+  std::vector<Constraint> constraints;
+  for (const auto& c : cs) {
+    if (c.col_idx ==
+        static_cast<uint32_t>(tables::CounterTable::ColumnIndex::track_id)) {
+      constraints.push_back(c);
+    }
   }
+  Table table = counter_table_->Filter(constraints);
 
-  Table t = counter_table_
-                ->ExtendWithColumn("dur", std::move(dur_column_.get()),
-                                   TypedColumn<int64_t>::default_flags())
-                .ExtendWithColumn("delta", std::move(delta_column_.get()),
-                                  TypedColumn<int64_t>::default_flags());
-
-  return std::unique_ptr<Table>(new Table(t.Copy()));
+  std::unique_ptr<NullableVector<int64_t>> dur_column(
+      new NullableVector<int64_t>(ComputeDurColumn(table)));
+  return std::unique_ptr<Table>(new Table(table.ExtendWithColumn(
+      "dur", std::move(dur_column), TypedColumn<int64_t>::default_flags())));
 }
 
 // static
@@ -102,38 +98,5 @@
   return dur;
 }
 
-// static
-NullableVector<double> ExperimentalCounterDurGenerator::ComputeDeltaColumn(
-    const Table& table) {
-  // Keep track of the last seen row for each track id.
-  std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
-  NullableVector<double> delta;
-
-  const auto* value_col =
-      TypedColumn<double>::FromColumn(table.GetColumnByName("value"));
-  const auto* track_id_col =
-      TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
-          table.GetColumnByName("track_id"));
-
-  for (uint32_t i = 0; i < table.row_count(); ++i) {
-    // Check if we already have a previous row for the current track id.
-    TrackId track_id = (*track_id_col)[i];
-    auto it = last_row_for_track_id.find(track_id);
-    if (it == last_row_for_track_id.end()) {
-      // This means we don't have any row - start tracking this row for the
-      // future.
-      last_row_for_track_id.emplace(track_id, i);
-    } else {
-      // This means we have an previous row for the current track id. Update
-      // the duration of the previous row to be up to the current ts.
-      uint32_t old_row = it->second;
-      it->second = i;
-      delta.Set(old_row, (*value_col)[i] - (*value_col)[old_row]);
-    }
-    delta.Append(0);
-  }
-  return delta;
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.h b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
index 38f9773..b20ca22 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.h
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
@@ -39,12 +39,9 @@
 
   // public + static for testing
   static NullableVector<int64_t> ComputeDurColumn(const Table& table);
-  static NullableVector<double> ComputeDeltaColumn(const Table& table);
 
  private:
   const tables::CounterTable* counter_table_ = nullptr;
-  std::unique_ptr<NullableVector<int64_t>> dur_column_;
-  std::unique_ptr<NullableVector<double>> delta_column_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
index 90f52e9..0d4e81e 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
@@ -145,7 +145,7 @@
     return in;
   }
   std::vector<FocusedState> focused_state =
-      ComputeFocusedState(*in, Matcher(focus_str));
+      ComputeFocusedState(*in.get(), Matcher(focus_str));
   std::unique_ptr<ExperimentalFlamegraphNodesTable> tbl(
       new tables::ExperimentalFlamegraphNodesTable(
           storage->mutable_string_pool(), nullptr));
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
deleted file mode 100644
index 1906918..0000000
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-ExperimentalSchedUpidGenerator::ExperimentalSchedUpidGenerator(
-    const tables::SchedSliceTable& sched,
-    const tables::ThreadTable& thread)
-    : sched_slice_table_(&sched), thread_table_(&thread) {}
-ExperimentalSchedUpidGenerator::~ExperimentalSchedUpidGenerator() = default;
-
-Table::Schema ExperimentalSchedUpidGenerator::CreateSchema() {
-  Table::Schema schema = tables::SchedSliceTable::Schema();
-  schema.columns.emplace_back(
-      Table::Schema::Column{"upid", SqlValue::Type::kLong, false /* is_id */,
-                            false /* is_sorted */, false /* is_hidden */});
-  return schema;
-}
-
-std::string ExperimentalSchedUpidGenerator::TableName() {
-  return "experimental_sched_upid";
-}
-
-uint32_t ExperimentalSchedUpidGenerator::EstimateRowCount() {
-  return sched_slice_table_->row_count();
-}
-
-util::Status ExperimentalSchedUpidGenerator::ValidateConstraints(
-    const QueryConstraints&) {
-  return util::OkStatus();
-}
-
-std::unique_ptr<Table> ExperimentalSchedUpidGenerator::ComputeTable(
-    const std::vector<Constraint>&,
-    const std::vector<Order>&) {
-  if (!upid_column_) {
-    upid_column_.reset(new NullableVector<uint32_t>(ComputeUpidColumn()));
-  }
-  return std::unique_ptr<Table>(new Table(sched_slice_table_->ExtendWithColumn(
-      "upid", upid_column_.get(),
-      TypedColumn<base::Optional<uint32_t>>::default_flags())));
-}
-
-NullableVector<uint32_t> ExperimentalSchedUpidGenerator::ComputeUpidColumn() {
-  NullableVector<uint32_t> upid;
-  for (uint32_t i = 0; i < sched_slice_table_->row_count(); ++i) {
-    upid.Append(thread_table_->upid()[sched_slice_table_->utid()[i]]);
-  }
-  return upid;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.h b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
deleted file mode 100644
index 09e0dfa..0000000
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
-
-#include <set>
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class ExperimentalSchedUpidGenerator
-    : public DbSqliteTable::DynamicTableGenerator {
- public:
-  ExperimentalSchedUpidGenerator(const tables::SchedSliceTable&,
-                                 const tables::ThreadTable&);
-  virtual ~ExperimentalSchedUpidGenerator() override;
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
-                                      const std::vector<Order>&) override;
-
- private:
-  NullableVector<uint32_t> ComputeUpidColumn();
-
-  const tables::SchedSliceTable* sched_slice_table_;
-  const tables::ThreadTable* thread_table_;
-  std::unique_ptr<NullableVector<uint32_t>> upid_column_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
index 0c864a1..132d7dc 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
@@ -95,36 +95,7 @@
 
   StringPool::Id filter_id =
       string_pool_->InternString(base::StringView(filter_string));
-
-  // Try and find the table in the cache.
-  auto it = layout_table_cache_.find(filter_id);
-  if (it != layout_table_cache_.end()) {
-    return std::unique_ptr<Table>(new Table(it->second.Copy()));
-  }
-
-  // Find all the slices for the tracks we want to filter and create a RowMap
-  // out of them.
-  // TODO(lalitm): Update this to use iterator (as this code will be slow after
-  // the event table is implemented).
-  // TODO(lalitm): consider generalising this by adding OR constraint support to
-  // Constraint and Table::Filter. We definitely want to wait until we have more
-  // usecases before implementing that though because it will be a significant
-  // amount of work.
-  RowMap rm;
-  for (uint32_t i = 0; i < slice_table_->row_count(); ++i) {
-    if (selected_tracks.count(slice_table_->track_id()[i]) > 0) {
-      rm.Insert(i);
-    }
-  }
-
-  // Apply the row map to the table to cut down on the number of rows we have to
-  // go through.
-  Table filtered_table = slice_table_->Apply(std::move(rm));
-
-  // Compute the table and add it to the cache for future use.
-  Table layout_table = ComputeLayoutTable(filtered_table, filter_id);
-  auto res = layout_table_cache_.emplace(filter_id, std::move(layout_table));
-  return std::unique_ptr<Table>(new Table(res.first->second.Copy()));
+  return AddLayoutColumn(*slice_table_, selected_tracks, filter_id);
 }
 
 // Build up a table of slice id -> root slice id by observing each
@@ -172,32 +143,39 @@
 // 3. Go though each slice and give it a layout_depth by summing it's
 //    current depth and the root layout_depth of the stalactite it belongs to.
 //
-Table ExperimentalSliceLayoutGenerator::ComputeLayoutTable(
+std::unique_ptr<Table> ExperimentalSliceLayoutGenerator::AddLayoutColumn(
     const Table& table,
+    const std::set<TrackId>& selected,
     StringPool::Id filter_id) {
+  const auto& track_id_col =
+      *table.GetTypedColumnByName<tables::TrackTable::Id>("track_id");
+  const auto& id_col = *table.GetIdColumnByName<tables::SliceTable::Id>("id");
+  const auto& parent_id_col =
+      *table.GetTypedColumnByName<base::Optional<tables::SliceTable::Id>>(
+          "parent_id");
+  const auto& depth_col = *table.GetTypedColumnByName<uint32_t>("depth");
+  const auto& ts_col = *table.GetTypedColumnByName<int64_t>("ts");
+  const auto& dur_col = *table.GetTypedColumnByName<int64_t>("dur");
+
   std::map<tables::SliceTable::Id, GroupInfo> groups;
   // Map of id -> root_id
   std::map<tables::SliceTable::Id, tables::SliceTable::Id> id_map;
 
-  const auto& id_col = table.GetIdColumnByName<tables::SliceTable::Id>("id");
-  const auto& parent_id_col =
-      table.GetTypedColumnByName<base::Optional<tables::SliceTable::Id>>(
-          "parent_id");
-  const auto& depth_col = table.GetTypedColumnByName<uint32_t>("depth");
-  const auto& ts_col = table.GetTypedColumnByName<int64_t>("ts");
-  const auto& dur_col = table.GetTypedColumnByName<int64_t>("dur");
-
   // Step 1:
   // Find the bounding box (start ts, end ts, and max depth) for each group
-  // TODO(lalitm): Update this to use iterator (as this code will be slow after
-  // the event table is implemented)
+  // TODO(lalitm): Update this to use iterator (will be slow after event table)
   for (uint32_t i = 0; i < table.row_count(); ++i) {
+    TrackId track_id = track_id_col[i];
+    if (selected.count(track_id) == 0) {
+      continue;
+    }
+
     tables::SliceTable::Id id = id_col[i];
     base::Optional<tables::SliceTable::Id> parent_id = parent_id_col[i];
     uint32_t depth = depth_col[i];
     int64_t start = ts_col[i];
     int64_t dur = dur_col[i];
-    int64_t end = dur == -1 ? std::numeric_limits<int64_t>::max() : start + dur;
+    int64_t end = start + dur;
     InsertSlice(id_map, id, parent_id);
     std::map<tables::SliceTable::Id, GroupInfo>::iterator it;
     bool inserted;
@@ -281,20 +259,31 @@
       new NullableVector<StringPool::Id>());
 
   for (uint32_t i = 0; i < table.row_count(); ++i) {
+    TrackId track_id = track_id_col[i];
     tables::SliceTable::Id id = id_col[i];
     uint32_t depth = depth_col[i];
-    // Each slice depth is it's current slice depth + root slice depth of the
-    // group:
-    layout_depth_column->Append(depth + groups.at(id_map[id]).layout_depth);
-    // We must set this to the value we got in the constraint to ensure our
-    // rows are not filtered out:
-    filter_column->Append(filter_id);
+    if (selected.count(track_id) == 0) {
+      // Don't care about depth for slices from non-selected tracks:
+      layout_depth_column->Append(0);
+      // We (ab)use this column to also filter out all the slices we don't care
+      // about by giving it a different value.
+      filter_column->Append(empty_string_id_);
+    } else {
+      // Each slice depth is it's current slice depth + root slice depth of the
+      // group:
+      layout_depth_column->Append(depth + groups.at(id_map[id]).layout_depth);
+      // We must set this to the value we got in the constraint to ensure our
+      // rows are not filtered out:
+      filter_column->Append(filter_id);
+    }
   }
-  return table
-      .ExtendWithColumn("layout_depth", std::move(layout_depth_column),
-                        TypedColumn<int64_t>::default_flags())
-      .ExtendWithColumn("filter_track_ids", std::move(filter_column),
-                        TypedColumn<StringPool::Id>::default_flags());
+
+  return std::unique_ptr<Table>(new Table(
+      table
+          .ExtendWithColumn("layout_depth", std::move(layout_depth_column),
+                            TypedColumn<int64_t>::default_flags())
+          .ExtendWithColumn("filter_track_ids", std::move(filter_column),
+                            TypedColumn<StringPool::Id>::default_flags())));
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.h b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
index 4b033f7..3f5e6ff 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.h
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
@@ -43,16 +43,14 @@
                                       const std::vector<Order>&) override;
 
  private:
-  Table ComputeLayoutTable(const Table& table, StringPool::Id filter_id);
+  std::unique_ptr<Table> AddLayoutColumn(const Table& table,
+                                         const std::set<TrackId>& selected,
+                                         StringPool::Id filter_id);
   tables::SliceTable::Id InsertSlice(
       std::map<tables::SliceTable::Id, tables::SliceTable::Id>& id_map,
       tables::SliceTable::Id id,
       base::Optional<tables::SliceTable::Id> parent_id);
 
-  // TODO(lalitm): remove this cache and move to having explicitly scoped
-  // lifetimes of dynamic tables.
-  std::unordered_map<StringId, Table> layout_table_cache_;
-
   StringPool* string_pool_;
   const tables::SliceTable* slice_table_;
   const StringPool::Id empty_string_id_;
diff --git a/src/trace_processor/dynamic/thread_state_generator.cc b/src/trace_processor/dynamic/thread_state_generator.cc
deleted file mode 100644
index e2e7f89..0000000
--- a/src/trace_processor/dynamic/thread_state_generator.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/thread_state_generator.h"
-
-#include <memory>
-#include <set>
-
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-ThreadStateGenerator::ThreadStateGenerator(TraceProcessorContext* context)
-    : running_string_id_(context->storage->InternString("Running")),
-      runnable_string_id_(context->storage->InternString("R")),
-      context_(context) {}
-
-ThreadStateGenerator::~ThreadStateGenerator() = default;
-
-util::Status ThreadStateGenerator::ValidateConstraints(
-    const QueryConstraints&) {
-  return util::OkStatus();
-}
-
-std::unique_ptr<Table> ThreadStateGenerator::ComputeTable(
-    const std::vector<Constraint>&,
-    const std::vector<Order>&) {
-  if (!unsorted_thread_state_table_) {
-    int64_t trace_end_ts =
-        context_->storage->GetTraceTimestampBoundsNs().second;
-
-    unsorted_thread_state_table_ = ComputeThreadStateTable(trace_end_ts);
-
-    // We explicitly sort by ts here as ComputeThreadStateTable does not insert
-    // rows in sorted order but we expect our clients to always want to sort
-    // on ts. Writing ComputeThreadStateTable to insert in sorted order is
-    // more trouble than its worth.
-    sorted_thread_state_table_ = unsorted_thread_state_table_->Sort(
-        {unsorted_thread_state_table_->ts().ascending()});
-  }
-  PERFETTO_CHECK(sorted_thread_state_table_);
-  return std::unique_ptr<Table>(new Table(sorted_thread_state_table_->Copy()));
-}
-
-std::unique_ptr<tables::ThreadStateTable>
-ThreadStateGenerator::ComputeThreadStateTable(int64_t trace_end_ts) {
-  std::unique_ptr<tables::ThreadStateTable> table(new tables::ThreadStateTable(
-      context_->storage->mutable_string_pool(), nullptr));
-
-  const auto& raw_sched = context_->storage->sched_slice_table();
-  const auto& instants = context_->storage->instant_table();
-
-  // In both tables, exclude utid == 0 which represents the idle thread.
-  Table sched = raw_sched.Filter({raw_sched.utid().ne(0)});
-  Table waking = instants.Filter(
-      {instants.name().eq("sched_waking"), instants.ref().ne(0)});
-
-  // We prefer to use waking if at all possible and fall back to wakeup if not
-  // available.
-  if (waking.row_count() == 0) {
-    waking = instants.Filter(
-        {instants.name().eq("sched_wakeup"), instants.ref().ne(0)});
-  }
-
-  Table sched_blocked_reason = instants.Filter(
-      {instants.name().eq("sched_blocked_reason"), instants.ref().ne(0)});
-
-  const auto& sched_ts_col = sched.GetTypedColumnByName<int64_t>("ts");
-  const auto& waking_ts_col = waking.GetTypedColumnByName<int64_t>("ts");
-  const auto& blocked_ts_col =
-      sched_blocked_reason.GetTypedColumnByName<int64_t>("ts");
-
-  uint32_t sched_idx = 0;
-  uint32_t waking_idx = 0;
-  uint32_t blocked_idx = 0;
-  std::unordered_map<UniqueTid, ThreadSchedInfo> state_map;
-  while (sched_idx < sched.row_count() || waking_idx < waking.row_count() ||
-         blocked_idx < sched_blocked_reason.row_count()) {
-    int64_t sched_ts = sched_idx < sched.row_count()
-                           ? sched_ts_col[sched_idx]
-                           : std::numeric_limits<int64_t>::max();
-    int64_t waking_ts = waking_idx < waking.row_count()
-                            ? waking_ts_col[waking_idx]
-                            : std::numeric_limits<int64_t>::max();
-    int64_t blocked_ts = blocked_idx < sched_blocked_reason.row_count()
-                             ? blocked_ts_col[blocked_idx]
-                             : std::numeric_limits<int64_t>::max();
-
-    // We go through all tables, picking the earliest timestamp from any
-    // to process that event.
-    int64_t min_ts = std::min({sched_ts, waking_ts, blocked_ts});
-    if (min_ts == sched_ts) {
-      AddSchedEvent(sched, sched_idx++, state_map, trace_end_ts, table.get());
-    } else if (min_ts == waking_ts) {
-      AddWakingEvent(waking, waking_idx++, state_map);
-    } else /* (min_ts == blocked_ts) */ {
-      AddBlockedReasonEvent(sched_blocked_reason, blocked_idx++, state_map);
-    }
-  }
-
-  // At the end, go through and flush any remaining pending events.
-  for (const auto& utid_to_pending_info : state_map) {
-    UniqueTid utid = utid_to_pending_info.first;
-    const ThreadSchedInfo& pending_info = utid_to_pending_info.second;
-    FlushPendingEventsForThread(utid, pending_info, table.get(), base::nullopt);
-  }
-
-  return table;
-}
-
-void ThreadStateGenerator::AddSchedEvent(
-    const Table& sched,
-    uint32_t sched_idx,
-    std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map,
-    int64_t trace_end_ts,
-    tables::ThreadStateTable* table) {
-  int64_t ts = sched.GetTypedColumnByName<int64_t>("ts")[sched_idx];
-  UniqueTid utid = sched.GetTypedColumnByName<uint32_t>("utid")[sched_idx];
-  ThreadSchedInfo* info = &state_map[utid];
-
-  // Due to races in the kernel, it is possible for the same thread to be
-  // scheduled on different CPUs at the same time. This will manifest itself
-  // here by having |info->desched_ts| in the future of this scheduling slice
-  // (i.e. there was a scheduling slice in the past which ended after the start
-  // of the current scheduling slice).
-  //
-  // We work around this problem by truncating the previous slice to the start
-  // of this slice and not adding the descheduled slice (i.e. we don't call
-  // |FlushPendingEventsForThread| which adds this slice).
-  //
-  // See b/186509316 for details and an example on when this happens.
-  if (info->desched_ts && info->desched_ts.value() > ts) {
-    uint32_t prev_sched_row = info->scheduled_row.value();
-    int64_t prev_sched_start = table->ts()[prev_sched_row];
-
-    // Just a double check that descheduling slice would have started at the
-    // same time the scheduling slice would have ended.
-    PERFETTO_DCHECK(prev_sched_start + table->dur()[prev_sched_row] ==
-                    info->desched_ts.value());
-
-    // Truncate the duration of the old slice to end at the start of this
-    // scheduling slice.
-    table->mutable_dur()->Set(prev_sched_row, ts - prev_sched_start);
-  } else {
-    FlushPendingEventsForThread(utid, *info, table, ts);
-  }
-
-  // Reset so we don't have any leftover data on the next round.
-  *info = {};
-
-  // Undo the expansion of the final sched slice for each CPU to the end of the
-  // trace by setting the duration back to -1. This counteracts the code in
-  // SchedEventTracker::FlushPendingEvents
-  // TODO(lalitm): remove this hack when we stop expanding the last slice to the
-  // end of the trace.
-  int64_t dur = sched.GetTypedColumnByName<int64_t>("dur")[sched_idx];
-  if (ts + dur == trace_end_ts) {
-    dur = -1;
-  }
-
-  // Now add the sched slice itself as "Running" with the other fields
-  // unchanged.
-  tables::ThreadStateTable::Row sched_row;
-  sched_row.ts = ts;
-  sched_row.dur = dur;
-  sched_row.cpu = sched.GetTypedColumnByName<uint32_t>("cpu")[sched_idx];
-  sched_row.state = running_string_id_;
-  sched_row.utid = utid;
-
-  auto id_and_row = table->Insert(sched_row);
-
-  // If the sched row had a negative duration, don't add any descheduled slice
-  // because it would be meaningless.
-  if (sched_row.dur == -1) {
-    return;
-  }
-
-  // This will be flushed to the table on the next sched slice (or the very end
-  // of the big loop).
-  info->desched_ts = ts + dur;
-  info->desched_end_state =
-      sched.GetTypedColumnByName<StringId>("end_state")[sched_idx];
-  info->scheduled_row = id_and_row.row;
-}
-
-void ThreadStateGenerator::AddWakingEvent(
-    const Table& waking,
-    uint32_t waking_idx,
-    std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map) {
-  int64_t ts = waking.GetTypedColumnByName<int64_t>("ts")[waking_idx];
-  UniqueTid utid = static_cast<UniqueTid>(
-      waking.GetTypedColumnByName<int64_t>("ref")[waking_idx]);
-  ThreadSchedInfo* info = &state_map[utid];
-
-  // Occasionally, it is possible to get a waking event for a thread
-  // which is already in a runnable state. When this happens, we just
-  // ignore the waking event.
-  // See b/186509316 for details and an example on when this happens.
-  if (info->desched_end_state &&
-      *info->desched_end_state == runnable_string_id_) {
-    return;
-  }
-
-  // As counter-intuitive as it seems, occasionally we can get a waking
-  // event for a thread which is currently running.
-  //
-  // There are two cases when this can happen:
-  // 1. The kernel legitimately send a waking event for a "running" thread
-  //    because the thread was woken up before the kernel switched away
-  //    from it. In this case, the waking timestamp will be in the past
-  //    because we added the descheduled slice when we processed the sched
-  //    event.
-  // 2. We're close to the end of the trace or had data-loss and we missed
-  //    the switch out event for a thread but we see a waking after.
-
-  // Case 1 described above. In this situation, we should drop the waking
-  // entirely.
-  if (info->desched_ts && *info->desched_ts > ts) {
-    return;
-  }
-
-  // For case 2 and otherwise, we should just note the fact that the thread
-  // became runnable at this time. Note that we cannot check if runnable is
-  // already not set because we could have data-loss which leads to us getting
-  // back to back waking for a single thread.
-  info->runnable_ts = ts;
-}
-
-Table::Schema ThreadStateGenerator::CreateSchema() {
-  auto schema = tables::ThreadStateTable::Schema();
-
-  // Because we expect our users to generally want ordered by ts, we set the
-  // ordering for the schema to match our forced sort pass in ComputeTable.
-  auto ts_it = std::find_if(
-      schema.columns.begin(), schema.columns.end(),
-      [](const Table::Schema::Column& col) { return col.name == "ts"; });
-  ts_it->is_sorted = true;
-  auto id_it = std::find_if(
-      schema.columns.begin(), schema.columns.end(),
-      [](const Table::Schema::Column& col) { return col.name == "id"; });
-  id_it->is_sorted = false;
-
-  return schema;
-}
-
-void ThreadStateGenerator::FlushPendingEventsForThread(
-    UniqueTid utid,
-    const ThreadSchedInfo& info,
-    tables::ThreadStateTable* table,
-    base::Optional<int64_t> end_ts) {
-  // First, let's flush the descheduled period (if any) to the table.
-  if (info.desched_ts) {
-    PERFETTO_DCHECK(info.desched_end_state);
-
-    int64_t dur;
-    if (end_ts) {
-      int64_t desched_end_ts = info.runnable_ts ? *info.runnable_ts : *end_ts;
-      dur = desched_end_ts - *info.desched_ts;
-    } else {
-      dur = -1;
-    }
-
-    tables::ThreadStateTable::Row row;
-    row.ts = *info.desched_ts;
-    row.dur = dur;
-    row.state = *info.desched_end_state;
-    row.utid = utid;
-    row.io_wait = info.io_wait;
-    row.blocked_function = info.blocked_function;
-    table->Insert(row);
-  }
-
-  // Next, flush the runnable period (if any) to the table.
-  if (info.runnable_ts) {
-    tables::ThreadStateTable::Row row;
-    row.ts = *info.runnable_ts;
-    row.dur = end_ts ? *end_ts - row.ts : -1;
-    row.state = runnable_string_id_;
-    row.utid = utid;
-    table->Insert(row);
-  }
-}
-
-void ThreadStateGenerator::AddBlockedReasonEvent(
-    const Table& blocked_reason,
-    uint32_t blocked_idx,
-    std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map) {
-  const auto& utid_col = blocked_reason.GetTypedColumnByName<int64_t>("ref");
-  const auto& arg_set_id_col =
-      blocked_reason.GetTypedColumnByName<uint32_t>("arg_set_id");
-
-  UniqueTid utid = static_cast<UniqueTid>(utid_col[blocked_idx]);
-  uint32_t arg_set_id = arg_set_id_col[blocked_idx];
-  ThreadSchedInfo& info = state_map[utid];
-
-  base::Optional<Variadic> opt_value;
-  util::Status status =
-      context_->storage->ExtractArg(arg_set_id, "io_wait", &opt_value);
-
-  // We can't do anything better than ignoring any errors here.
-  // TODO(lalitm): see if there's a better way to handle this.
-  if (status.ok() && opt_value) {
-    PERFETTO_CHECK(opt_value->type == Variadic::Type::kBool);
-    info.io_wait = opt_value->bool_value;
-  }
-
-  status = context_->storage->ExtractArg(arg_set_id, "function", &opt_value);
-  if (status.ok() && opt_value) {
-    PERFETTO_CHECK(opt_value->type == Variadic::Type::kString);
-    info.blocked_function = opt_value->string_value;
-  }
-}
-
-std::string ThreadStateGenerator::TableName() {
-  return "thread_state";
-}
-
-uint32_t ThreadStateGenerator::EstimateRowCount() {
-  return context_->storage->sched_slice_table().row_count();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/thread_state_generator.h b/src/trace_processor/dynamic/thread_state_generator.h
deleted file mode 100644
index 75895ba..0000000
--- a/src/trace_processor/dynamic/thread_state_generator.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_THREAD_STATE_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_THREAD_STATE_GENERATOR_H_
-
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Dynamic table implementing the thread state table.
-// This table is a basically the same as sched with extra information added
-// about wakeups (obtained from sched_waking/sched_wakeup).
-class ThreadStateGenerator : public DbSqliteTable::DynamicTableGenerator {
- public:
-  explicit ThreadStateGenerator(TraceProcessorContext* context);
-  ~ThreadStateGenerator() override;
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  util::Status ValidateConstraints(const QueryConstraints&) override;
-  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
-                                      const std::vector<Order>& ob) override;
-
-  // Visible for testing.
-  std::unique_ptr<tables::ThreadStateTable> ComputeThreadStateTable(
-      int64_t trace_end_ts);
-
- private:
-  struct ThreadSchedInfo {
-    base::Optional<int64_t> desched_ts;
-    base::Optional<StringId> desched_end_state;
-    base::Optional<uint32_t> scheduled_row;
-    base::Optional<bool> io_wait;
-    base::Optional<int64_t> runnable_ts;
-    base::Optional<StringId> blocked_function;
-  };
-
-  void AddSchedEvent(const Table& sched,
-                     uint32_t sched_idx,
-                     std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map,
-                     int64_t trace_end_ts,
-                     tables::ThreadStateTable* table);
-
-  void AddWakingEvent(
-      const Table& wakeup,
-      uint32_t wakeup_idx,
-      std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map);
-
-  void AddBlockedReasonEvent(
-      const Table& blocked_reason,
-      uint32_t blocked_idx,
-      std::unordered_map<UniqueTid, ThreadSchedInfo>& state_map);
-
-  void FlushPendingEventsForThread(UniqueTid utid,
-                                   const ThreadSchedInfo&,
-                                   tables::ThreadStateTable* table,
-                                   base::Optional<int64_t> end_ts);
-
-  std::unique_ptr<tables::ThreadStateTable> unsorted_thread_state_table_;
-  base::Optional<Table> sorted_thread_state_table_;
-
-  const StringId running_string_id_;
-  const StringId runnable_string_id_;
-
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_THREAD_STATE_GENERATOR_H_
diff --git a/src/trace_processor/dynamic/thread_state_generator_unittest.cc b/src/trace_processor/dynamic/thread_state_generator_unittest.cc
deleted file mode 100644
index e9cf5d6..0000000
--- a/src/trace_processor/dynamic/thread_state_generator_unittest.cc
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/thread_state_generator.h"
-
-#include <algorithm>
-
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/global_args_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class ThreadStateGeneratorUnittest : public testing::Test {
- public:
-  struct Ts {
-    int64_t ts;
-  };
-
-  ThreadStateGeneratorUnittest() : idle_thread_(0), thread_a_(1), thread_b_(2) {
-    context_.storage.reset(new TraceStorage());
-    context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
-    context_.args_tracker.reset(new ArgsTracker(&context_));
-    thread_state_generator_.reset(new ThreadStateGenerator(&context_));
-  }
-
-  void ForwardSchedTo(Ts ts) { sched_insert_ts_ = ts.ts; }
-
-  void AddWaking(Ts ts, UniqueTid utid) {
-    tables::InstantTable::Row row;
-    row.ts = ts.ts;
-    row.ref = utid;
-    row.name = context_.storage->InternString("sched_waking");
-    context_.storage->mutable_instant_table()->Insert(row);
-  }
-
-  void AddWakup(Ts ts, UniqueTid utid) {
-    tables::InstantTable::Row row;
-    row.ts = ts.ts;
-    row.ref = utid;
-    row.name = context_.storage->InternString("sched_wakeup");
-    context_.storage->mutable_instant_table()->Insert(row);
-  }
-
-  void AddSched(base::Optional<Ts> end, UniqueTid utid, const char* end_state) {
-    StringId end_state_id = context_.storage->InternString(end_state);
-
-    tables::SchedSliceTable::Row row;
-
-    // cpu is hardcoded because it doesn't matter for the algorithm and is
-    // just passed through unchanged.
-    row.cpu = 0;
-
-    row.ts = sched_insert_ts_;
-    row.dur = end ? end->ts - row.ts : -1;
-    row.utid = utid;
-    row.end_state = end_state_id;
-    context_.storage->mutable_sched_slice_table()->Insert(row);
-
-    sched_insert_ts_ = end ? end->ts : -1;
-  }
-
-  void AddBlockedReason(Ts ts, UniqueTid utid, bool io_wait) {
-    tables::InstantTable::Row row;
-    row.ts = ts.ts;
-    row.ref = utid;
-    row.name = context_.storage->InternString("sched_blocked_reason");
-
-    auto id = context_.storage->mutable_instant_table()->Insert(row).id;
-    auto inserter = context_.args_tracker->AddArgsTo(id);
-    inserter.AddArg(context_.storage->InternString("io_wait"),
-                    Variadic::Boolean(io_wait));
-    context_.args_tracker->Flush();
-  }
-
-  void RunThreadStateComputation(Ts trace_end_ts = Ts{
-                                     std::numeric_limits<int64_t>::max()}) {
-    unsorted_table_ =
-        thread_state_generator_->ComputeThreadStateTable(trace_end_ts.ts);
-    table_.reset(
-        new Table(unsorted_table_->Sort({unsorted_table_->ts().ascending()})));
-  }
-
-  void VerifyThreadState(Ts from,
-                         base::Optional<Ts> to,
-                         UniqueTid utid,
-                         const char* state,
-                         base::Optional<bool> io_wait = base::nullopt) {
-    uint32_t row = thread_state_verify_row_++;
-
-    const auto& ts_col = table_->GetTypedColumnByName<int64_t>("ts");
-    const auto& dur_col = table_->GetTypedColumnByName<int64_t>("dur");
-    const auto& utid_col = table_->GetTypedColumnByName<UniqueTid>("utid");
-    const auto& cpu_col =
-        table_->GetTypedColumnByName<base::Optional<uint32_t>>("cpu");
-    const auto& end_state_col = table_->GetTypedColumnByName<StringId>("state");
-    const auto& io_wait_col =
-        table_->GetTypedColumnByName<base::Optional<uint32_t>>("io_wait");
-
-    ASSERT_LT(row, table_->row_count());
-    ASSERT_EQ(ts_col[row], from.ts);
-    ASSERT_EQ(dur_col[row], to ? to->ts - from.ts : -1);
-    ASSERT_EQ(utid_col[row], utid);
-    if (state == kRunning) {
-      ASSERT_EQ(cpu_col[row], 0u);
-    } else {
-      ASSERT_EQ(cpu_col[row], base::nullopt);
-    }
-    ASSERT_EQ(end_state_col.GetString(row), base::StringView(state));
-
-    base::Optional<uint32_t> mapped_io_wait =
-        io_wait ? base::make_optional(static_cast<uint32_t>(*io_wait))
-                : base::nullopt;
-    ASSERT_EQ(io_wait_col[row], mapped_io_wait);
-  }
-
-  void VerifyEndOfThreadState() {
-    ASSERT_EQ(thread_state_verify_row_, table_->row_count());
-  }
-
- protected:
-  static constexpr char kRunning[] = "Running";
-
-  const UniqueTid idle_thread_;
-  const UniqueTid thread_a_;
-  const UniqueTid thread_b_;
-
- private:
-  TraceProcessorContext context_;
-
-  int64_t sched_insert_ts_ = 0;
-
-  uint32_t thread_state_verify_row_ = 0;
-
-  std::unique_ptr<ThreadStateGenerator> thread_state_generator_;
-  std::unique_ptr<tables::ThreadStateTable> unsorted_table_;
-  std::unique_ptr<Table> table_;
-};
-
-constexpr char ThreadStateGeneratorUnittest::kRunning[];
-
-TEST_F(ThreadStateGeneratorUnittest, MultipleThreadWithOnlySched) {
-  ForwardSchedTo(Ts{0});
-  AddSched(Ts{10}, thread_a_, "S");
-  AddSched(Ts{15}, thread_b_, "D");
-  AddSched(Ts{20}, thread_a_, "R");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{0}, Ts{10}, thread_a_, kRunning);
-  VerifyThreadState(Ts{10}, Ts{15}, thread_b_, kRunning);
-  VerifyThreadState(Ts{10}, Ts{15}, thread_a_, "S");
-  VerifyThreadState(Ts{15}, Ts{20}, thread_a_, kRunning);
-  VerifyThreadState(Ts{15}, base::nullopt, thread_b_, "D");
-  VerifyThreadState(Ts{20}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, WakingFirst) {
-  AddWaking(Ts{10}, thread_a_);
-
-  ForwardSchedTo(Ts{20});
-  AddSched(Ts{30}, thread_a_, "S");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{10}, Ts{20}, thread_a_, "R");
-  VerifyThreadState(Ts{20}, Ts{30}, thread_a_, kRunning);
-  VerifyThreadState(Ts{30}, base::nullopt, thread_a_, "S");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, SchedWithWaking) {
-  ForwardSchedTo(Ts{0});
-  AddSched(Ts{10}, thread_a_, "S");
-
-  AddWaking(Ts{15}, thread_a_);
-
-  ForwardSchedTo(Ts{20});
-  AddSched(Ts{25}, thread_a_, "R");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{0}, Ts{10}, thread_a_, kRunning);
-  VerifyThreadState(Ts{10}, Ts{15}, thread_a_, "S");
-  VerifyThreadState(Ts{15}, Ts{20}, thread_a_, "R");
-  VerifyThreadState(Ts{20}, Ts{25}, thread_a_, kRunning);
-  VerifyThreadState(Ts{25}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, SchedWithWakeup) {
-  ForwardSchedTo(Ts{0});
-  AddSched(Ts{10}, thread_a_, "S");
-
-  AddWakup(Ts{15}, thread_a_);
-
-  ForwardSchedTo(Ts{20});
-  AddSched(Ts{25}, thread_a_, "R");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{0}, Ts{10}, thread_a_, kRunning);
-  VerifyThreadState(Ts{10}, Ts{15}, thread_a_, "S");
-  VerifyThreadState(Ts{15}, Ts{20}, thread_a_, "R");
-  VerifyThreadState(Ts{20}, Ts{25}, thread_a_, kRunning);
-  VerifyThreadState(Ts{25}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, SchedIdleIgnored) {
-  ForwardSchedTo(Ts{0});
-  AddSched(Ts{10}, idle_thread_, "R");
-  AddSched(Ts{15}, thread_a_, "R");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{10}, Ts{15}, thread_a_, kRunning);
-  VerifyThreadState(Ts{15}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, NegativeSchedDuration) {
-  ForwardSchedTo(Ts{0});
-
-  AddSched(Ts{10}, thread_a_, "S");
-
-  AddWaking(Ts{15}, thread_a_);
-
-  ForwardSchedTo(Ts{20});
-  AddSched(base::nullopt, thread_a_, "");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{0}, Ts{10}, thread_a_, kRunning);
-  VerifyThreadState(Ts{10}, Ts{15}, thread_a_, "S");
-  VerifyThreadState(Ts{15}, Ts{20}, thread_a_, "R");
-  VerifyThreadState(Ts{20}, base::nullopt, thread_a_, kRunning);
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, WakingOnRunningThreadAtEnd) {
-  AddWaking(Ts{5}, thread_a_);
-
-  ForwardSchedTo(Ts{10});
-  AddSched(base::nullopt, thread_a_, "");
-
-  AddWaking(Ts{15}, thread_a_);
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{5}, Ts{10}, thread_a_, "R");
-  VerifyThreadState(Ts{10}, base::nullopt, thread_a_, kRunning);
-  VerifyThreadState(Ts{15}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, SchedDataLoss) {
-  ForwardSchedTo(Ts{10});
-  AddSched(base::nullopt, thread_a_, "");
-  ForwardSchedTo(Ts{30});
-  AddSched(Ts{40}, thread_a_, "D");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{10}, base::nullopt, thread_a_, kRunning);
-  VerifyThreadState(Ts{30}, Ts{40}, thread_a_, kRunning);
-  VerifyThreadState(Ts{40}, base::nullopt, thread_a_, "D");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, StrechedSchedIgnored) {
-  ForwardSchedTo(Ts{10});
-  AddSched(Ts{100}, thread_a_, "");
-
-  RunThreadStateComputation(Ts{100});
-
-  VerifyThreadState(Ts{10}, base::nullopt, thread_a_, kRunning);
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, WakingAfterStrechedSched) {
-  ForwardSchedTo(Ts{10});
-  AddSched(Ts{100}, thread_a_, "");
-
-  AddWaking(Ts{15}, thread_a_);
-
-  RunThreadStateComputation(Ts{100});
-
-  VerifyThreadState(Ts{10}, base::nullopt, thread_a_, kRunning);
-  VerifyThreadState(Ts{15}, base::nullopt, thread_a_, "R");
-
-  VerifyEndOfThreadState();
-}
-
-TEST_F(ThreadStateGeneratorUnittest, BlockedReason) {
-  ForwardSchedTo(Ts{10});
-  AddSched(Ts{12}, thread_a_, "D");
-  AddWaking(Ts{15}, thread_a_);
-  AddBlockedReason(Ts{16}, thread_a_, true);
-
-  ForwardSchedTo(Ts{18});
-  AddSched(Ts{20}, thread_a_, "S");
-  AddWaking(Ts{24}, thread_a_);
-  AddBlockedReason(Ts{26}, thread_a_, false);
-
-  ForwardSchedTo(Ts{29});
-  AddSched(Ts{30}, thread_a_, "R");
-
-  ForwardSchedTo(Ts{39});
-  AddSched(Ts{40}, thread_a_, "D");
-  AddBlockedReason(Ts{44}, thread_a_, false);
-
-  ForwardSchedTo(Ts{49});
-  AddSched(Ts{50}, thread_a_, "D");
-
-  RunThreadStateComputation();
-
-  VerifyThreadState(Ts{10}, Ts{12}, thread_a_, kRunning);
-  VerifyThreadState(Ts{12}, Ts{15}, thread_a_, "D", true);
-  VerifyThreadState(Ts{15}, Ts{18}, thread_a_, "R");
-
-  VerifyThreadState(Ts{18}, Ts{20}, thread_a_, kRunning);
-  VerifyThreadState(Ts{20}, Ts{24}, thread_a_, "S", false);
-  VerifyThreadState(Ts{24}, Ts{29}, thread_a_, "R");
-
-  VerifyThreadState(Ts{29}, Ts{30}, thread_a_, kRunning);
-  VerifyThreadState(Ts{30}, Ts{39}, thread_a_, "R", base::nullopt);
-
-  VerifyThreadState(Ts{39}, Ts{40}, thread_a_, kRunning);
-  VerifyThreadState(Ts{40}, Ts{49}, thread_a_, "D", false);
-
-  VerifyThreadState(Ts{49}, Ts{50}, thread_a_, kRunning);
-  VerifyThreadState(Ts{50}, base::nullopt, thread_a_, "D");
-
-  VerifyEndOfThreadState();
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index fe73813..c9dc1b3 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -19,14 +19,12 @@
 
 #include <inttypes.h>
 #include <stdio.h>
-#include <sstream>
 
 #include <algorithm>
 #include <cmath>
 #include <cstring>
 #include <deque>
 #include <limits>
-#include <memory>
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/string_splitter.h"
@@ -83,12 +81,48 @@
 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();
 }
 
+std::string PrintUint64(uint64_t x) {
+  char hex_str[19];
+  sprintf(hex_str, "0x%" PRIx64, x);
+  return hex_str;
+}
+
+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;
+    }
+  }
+}
+
 class JsonExporter {
  public:
   JsonExporter(const TraceStorage* storage,
@@ -113,18 +147,10 @@
     if (!status.ok())
       return status;
 
-    status = ExportProcessUptimes();
-    if (!status.ok())
-      return status;
-
     status = ExportSlices();
     if (!status.ok())
       return status;
 
-    status = ExportFlows();
-    if (!status.ok())
-      return status;
-
     status = ExportRawEvents();
     if (!status.ok())
       return status;
@@ -141,10 +167,6 @@
     if (!status.ok())
       return status;
 
-    status = ExportMemorySnapshots();
-    if (!status.ok())
-      return status;
-
     return util::OkStatus();
   }
 
@@ -160,9 +182,6 @@
           metadata_filter_(metadata_filter),
           label_filter_(label_filter),
           first_event_(true) {
-      Json::StreamWriterBuilder b;
-      b.settings_["indentation"] = "";
-      writer_.reset(b.newStreamWriter());
       WriteHeader();
     }
 
@@ -315,17 +334,17 @@
     }
 
     void WriteMetadataEvent(const char* metadata_type,
-                            const char* metadata_arg_name,
-                            const char* metadata_arg_value,
+                            const char* metadata_value,
                             uint32_t pid,
                             uint32_t tid) {
       if (label_filter_ && !label_filter_("traceEvents"))
         return;
 
-      std::ostringstream ss;
       if (!first_event_)
-        ss << ",\n";
+        output_->AppendString(",\n");
 
+      Json::FastWriter writer;
+      writer.omitEndingLineFeed();
       Json::Value value;
       value["ph"] = "M";
       value["cat"] = "__metadata";
@@ -335,11 +354,10 @@
       value["tid"] = Json::Int(tid);
 
       Json::Value args;
-      args[metadata_arg_name] = metadata_arg_value;
+      args["name"] = metadata_value;
       value["args"] = args;
 
-      writer_->write(value, &ss);
-      output_->AppendString(ss.str());
+      output_->AppendString(writer.write(value));
       first_event_ = false;
     }
 
@@ -362,7 +380,7 @@
     }
 
     void SetTelemetryMetadataTimestamp(const char* key, int64_t value) {
-      metadata_["telemetry"][key] = static_cast<double>(value) / 1000.0;
+      metadata_["telemetry"][key] = value / 1000.0;
     }
 
     void SetStats(const char* key, int64_t value) {
@@ -416,17 +434,14 @@
         }
       }
 
+      Json::FastWriter writer;
+      writer.omitEndingLineFeed();
       if ((!label_filter_ || label_filter_("traceEvents")) &&
           !user_trace_data_.empty()) {
         user_trace_data_ += "]";
-
-        Json::CharReaderBuilder builder;
-        auto reader =
-            std::unique_ptr<Json::CharReader>(builder.newCharReader());
+        Json::Reader reader;
         Json::Value result;
-        if (reader->parse(user_trace_data_.data(),
-                          user_trace_data_.data() + user_trace_data_.length(),
-                          &result, nullptr)) {
+        if (reader.parse(user_trace_data_, result)) {
           for (const auto& event : result) {
             WriteCommonEvent(event);
           }
@@ -436,32 +451,27 @@
               user_trace_data_.c_str());
         }
       }
-
-      std::ostringstream ss;
       if (!label_filter_)
-        ss << "]";
-
+        output_->AppendString("]");
       if ((!label_filter_ || label_filter_("systemTraceEvents")) &&
           !system_trace_data_.empty()) {
-        ss << ",\"systemTraceEvents\":\n";
-        writer_->write(Json::Value(system_trace_data_), &ss);
+        output_->AppendString(",\"systemTraceEvents\":\n");
+        output_->AppendString(writer.write(Json::Value(system_trace_data_)));
       }
-
       if ((!label_filter_ || label_filter_("metadata")) && !metadata_.empty()) {
-        ss << ",\"metadata\":\n";
-        writer_->write(metadata_, &ss);
+        output_->AppendString(",\"metadata\":\n");
+        output_->AppendString(writer.write(metadata_));
       }
-
       if (!label_filter_)
-        ss << "}";
-
-      output_->AppendString(ss.str());
+        output_->AppendString("}");
     }
 
     void DoWriteEvent(const Json::Value& event) {
-      std::ostringstream ss;
       if (!first_event_)
-        ss << ",\n";
+        output_->AppendString(",\n");
+
+      Json::FastWriter writer;
+      writer.omitEndingLineFeed();
 
       ArgumentNameFilterPredicate argument_name_filter;
       bool strip_args =
@@ -479,13 +489,11 @@
               args[member] = kStrippedArgument;
           }
         }
-        writer_->write(event_copy, &ss);
+        output_->AppendString(writer.write(event_copy));
       } else {
-        writer_->write(event, &ss);
+        output_->AppendString(writer.write(event));
       }
       first_event_ = false;
-
-      output_->AppendString(ss.str());
     }
 
     OutputWriter* output_;
@@ -493,7 +501,6 @@
     MetadataFilterPredicate metadata_filter_;
     LabelFilterPredicate label_filter_;
 
-    std::unique_ptr<Json::StreamWriter> writer_;
     bool first_event_;
     Json::Value metadata_;
     std::string system_trace_data_;
@@ -558,16 +565,13 @@
             return variadic.real_value;
           }
         case Variadic::kPointer:
-          return base::Uint64ToHexString(variadic.pointer_value);
+          return PrintUint64(variadic.pointer_value);
         case Variadic::kBool:
           return variadic.bool_value;
         case Variadic::kJson:
-          Json::CharReaderBuilder b;
-          auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
-
+          Json::Reader reader;
           Json::Value result;
-          std::string v = GetNonNullString(storage_, variadic.json_value);
-          reader->parse(v.data(), v.data() + v.length(), &result, nullptr);
+          reader.parse(GetNonNullString(storage_, variadic.json_value), result);
           return result;
       }
       PERFETTO_FATAL("Not reached");  // For gcc.
@@ -643,14 +647,6 @@
           if (args["task"].empty())
             args.removeMember("task");
         }
-        if (args.isMember("source")) {
-          Json::Value source = args["source"];
-          if (source.isObject() && source.isMember("function_name")) {
-            args["function_name"] = source["function_name"];
-            args["file_name"] = source["file_name"];
-            args.removeMember("source");
-          }
-        }
       }
     }
 
@@ -707,7 +703,7 @@
       if (!opt_name.is_null()) {
         const char* thread_name = GetNonNullString(storage_, opt_name);
         auto pid_and_tid = UtidToPidAndTid(utid);
-        writer_.WriteMetadataEvent("thread_name", "name", thread_name,
+        writer_.WriteMetadataEvent("thread_name", thread_name,
                                    pid_and_tid.first, pid_and_tid.second);
       }
     }
@@ -720,56 +716,13 @@
       auto opt_name = process_table.name()[upid];
       if (!opt_name.is_null()) {
         const char* process_name = GetNonNullString(storage_, opt_name);
-        writer_.WriteMetadataEvent("process_name", "name", process_name,
+        writer_.WriteMetadataEvent("process_name", process_name,
                                    UpidToPid(upid), /*tid=*/0);
       }
     }
     return util::OkStatus();
   }
 
-  // For each process it writes an approximate uptime, based on the process'
-  // start time and the last slice in the entire trace. This same last slice is
-  // used with all processes, so the process could have ended earlier.
-  util::Status ExportProcessUptimes() {
-    int64_t last_timestamp_ns = FindLastSliceTimestamp();
-    if (last_timestamp_ns <= 0)
-      return util::OkStatus();
-
-    const auto& process_table = storage_->process_table();
-    for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
-      base::Optional<int64_t> start_timestamp_ns =
-          process_table.start_ts()[upid];
-      if (!start_timestamp_ns.has_value())
-        continue;
-
-      int64_t process_uptime_seconds =
-          (last_timestamp_ns - start_timestamp_ns.value()) /
-          (1000 * 1000 * 1000);
-
-      writer_.WriteMetadataEvent("process_uptime_seconds", "uptime",
-                                 std::to_string(process_uptime_seconds).c_str(),
-                                 UpidToPid(upid), /*tid=*/0);
-    }
-
-    return util::OkStatus();
-  }
-
-  // Returns the last slice's end timestamp for the entire trace. If no slices
-  // are found 0 is returned.
-  int64_t FindLastSliceTimestamp() {
-    int64_t last_ts = 0;
-    const auto& slices = storage_->slice_table();
-    for (uint32_t i = 0; i < slices.row_count(); ++i) {
-      int64_t duration_ns = slices.dur()[i];
-      int64_t timestamp_ns = slices.ts()[i];
-
-      if (duration_ns + timestamp_ns > last_ts) {
-        last_ts = duration_ns + timestamp_ns;
-      }
-    }
-    return last_ts;
-  }
-
   util::Status ExportSlices() {
     const auto& slices = storage_->slice_table();
     for (uint32_t i = 0; i < slices.row_count(); ++i) {
@@ -789,18 +742,17 @@
       event["tid"] = 0;
 
       base::Optional<UniqueTid> legacy_utid;
-      std::string legacy_phase;
 
       event["args"] =
           args_builder_.GetArgs(slices.arg_set_id()[i]);  // Makes a copy.
       if (event["args"].isMember(kLegacyEventArgsKey)) {
-        const auto& legacy_args = event["args"][kLegacyEventArgsKey];
+        ConvertLegacyFlowEventArgs(event["args"][kLegacyEventArgsKey], &event);
 
-        if (legacy_args.isMember(kLegacyEventPassthroughUtidKey)) {
-          legacy_utid = legacy_args[kLegacyEventPassthroughUtidKey].asUInt();
-        }
-        if (legacy_args.isMember(kLegacyEventPhaseKey)) {
-          legacy_phase = legacy_args[kLegacyEventPhaseKey].asString();
+        if (event["args"][kLegacyEventArgsKey].isMember(
+                kLegacyEventPassthroughUtidKey)) {
+          legacy_utid =
+              event["args"][kLegacyEventArgsKey][kLegacyEventPassthroughUtidKey]
+                  .asUInt();
         }
 
         event["args"].removeMember(kLegacyEventArgsKey);
@@ -822,34 +774,33 @@
       if (track_args_id) {
         track_args = &args_builder_.GetArgs(*track_args_id);
         legacy_chrome_track = (*track_args)["source"].asString() == "chrome";
-        is_child_track = track_args->isMember("is_root_in_scope") &&
-                         !(*track_args)["is_root_in_scope"].asBool();
+        is_child_track = track_args->isMember("parent_track_id");
       }
 
       const auto& thread_track = storage_->thread_track_table();
       const auto& process_track = storage_->process_track_table();
-      const auto& thread_slices = storage_->thread_slice_table();
+      const auto& thread_slices = storage_->thread_slices();
       const auto& virtual_track_slices = storage_->virtual_track_slices();
 
       int64_t duration_ns = slices.dur()[i];
-      base::Optional<int64_t> thread_ts_ns;
-      base::Optional<int64_t> thread_duration_ns;
-      base::Optional<int64_t> thread_instruction_count;
-      base::Optional<int64_t> thread_instruction_delta;
+      int64_t thread_ts_ns = 0;
+      int64_t thread_duration_ns = 0;
+      int64_t thread_instruction_count = 0;
+      int64_t thread_instruction_delta = 0;
 
-      SliceId id = slices.id()[i];
       base::Optional<uint32_t> thread_slice_row =
-          thread_slices.id().IndexOf(id);
+          thread_slices.FindRowForSliceId(i);
       if (thread_slice_row) {
-        thread_ts_ns = thread_slices.thread_ts()[*thread_slice_row];
-        thread_duration_ns = thread_slices.thread_dur()[*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_count()[*thread_slice_row];
+            thread_slices.thread_instruction_counts()[*thread_slice_row];
         thread_instruction_delta =
-            thread_slices.thread_instruction_delta()[*thread_slice_row];
+            thread_slices.thread_instruction_deltas()[*thread_slice_row];
       } else {
         base::Optional<uint32_t> vtrack_slice_row =
-            virtual_track_slices.FindRowForSliceId(id);
+            virtual_track_slices.FindRowForSliceId(i);
         if (vtrack_slice_row) {
           thread_ts_ns =
               virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
@@ -874,18 +825,14 @@
         event["tid"] = Json::Int(pid_and_tid.second);
 
         if (duration_ns == 0) {
-          if (legacy_phase.empty()) {
-            // Use "I" instead of "i" phase for backwards-compat with old
-            // consumers.
-            event["ph"] = "I";
-          } else {
-            event["ph"] = legacy_phase;
+          // 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_ts_ns && thread_ts_ns > 0) {
-            event["tts"] = Json::Int64(*thread_ts_ns / 1000);
-          }
-          if (thread_instruction_count && *thread_instruction_count > 0) {
-            event["ticount"] = Json::Int64(*thread_instruction_count);
+          if (thread_instruction_count > 0) {
+            event["ticount"] = Json::Int64(thread_instruction_count);
           }
           event["s"] = "t";
         } else {
@@ -897,17 +844,17 @@
             // write a begin event without end event in this case.
             event["ph"] = "B";
           }
-          if (thread_ts_ns && *thread_ts_ns > 0) {
-            event["tts"] = Json::Int64(*thread_ts_ns / 1000);
+          if (thread_ts_ns > 0) {
+            event["tts"] = Json::Int64(thread_ts_ns / 1000);
             // Only write thread duration for completed events.
-            if (duration_ns > 0 && thread_duration_ns)
-              event["tdur"] = Json::Int64(*thread_duration_ns / 1000);
+            if (duration_ns > 0)
+              event["tdur"] = Json::Int64(thread_duration_ns / 1000);
           }
-          if (thread_instruction_count && *thread_instruction_count > 0) {
-            event["ticount"] = Json::Int64(*thread_instruction_count);
+          if (thread_instruction_count > 0) {
+            event["ticount"] = Json::Int64(thread_instruction_count);
             // Only write thread instruction delta for completed events.
-            if (duration_ns > 0 && thread_instruction_delta)
-              event["tidelta"] = Json::Int64(*thread_instruction_delta);
+            if (duration_ns > 0)
+              event["tidelta"] = Json::Int64(thread_instruction_delta);
           }
         }
         writer_.WriteCommonEvent(event);
@@ -939,13 +886,13 @@
           bool source_id_is_process_scoped =
               (*track_args)["source_id_is_process_scoped"].asBool();
           if (source_id_is_process_scoped) {
-            event["id2"]["local"] = base::Uint64ToHexString(source_id);
+            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"] = base::Uint64ToHexString(source_id);
+            event["id"] = PrintUint64(source_id);
           }
         } else {
           if (opt_thread_track_row) {
@@ -953,7 +900,7 @@
             auto pid_and_tid = UtidToPidAndTid(utid);
             event["pid"] = Json::Int(pid_and_tid.first);
             event["tid"] = Json::Int(pid_and_tid.second);
-            event["id2"]["local"] = base::Uint64ToHexString(track_id.value);
+            event["id2"]["local"] = PrintUint64(track_id.value);
           } else if (opt_process_row) {
             uint32_t upid = process_track.upid()[*opt_process_row];
             uint32_t exported_pid = UpidToPid(upid);
@@ -961,7 +908,7 @@
             event["tid"] =
                 Json::Int(legacy_utid ? UtidToPidAndTid(*legacy_utid).second
                                       : exported_pid);
-            event["id2"]["local"] = base::Uint64ToHexString(track_id.value);
+            event["id2"]["local"] = PrintUint64(track_id.value);
           } else {
             if (legacy_utid) {
               auto pid_and_tid = UtidToPidAndTid(*legacy_utid);
@@ -973,45 +920,37 @@
             // 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"] = base::Uint64ToHexString(track_id.value);
+            event["id"] = PrintUint64(track_id.value);
           }
         }
 
-        if (thread_ts_ns && *thread_ts_ns > 0) {
-          event["tts"] = Json::Int64(*thread_ts_ns / 1000);
+        if (thread_ts_ns > 0) {
+          event["tts"] = Json::Int64(thread_ts_ns / 1000);
           event["use_async_tts"] = Json::Int(1);
         }
-        if (thread_instruction_count && *thread_instruction_count > 0) {
-          event["ticount"] = Json::Int64(*thread_instruction_count);
+        if (thread_instruction_count > 0) {
+          event["ticount"] = Json::Int64(thread_instruction_count);
           event["use_async_tts"] = Json::Int(1);
         }
 
-        if (duration_ns == 0) {
-          if (legacy_phase.empty()) {
-            // Instant async event.
-            event["ph"] = "n";
-            writer_.AddAsyncInstantEvent(event);
-          } else {
-            // Async step events.
-            event["ph"] = legacy_phase;
-            writer_.AddAsyncBeginEvent(event);
-          }
+        if (duration_ns == 0) {  // Instant async event.
+          event["ph"] = "n";
+          writer_.AddAsyncInstantEvent(event);
         } else {  // Async start and end.
-          event["ph"] = legacy_phase.empty() ? "b" : legacy_phase;
+          event["ph"] = "b";
           writer_.AddAsyncBeginEvent(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"] = legacy_phase.empty() ? "e" : "F";
+            event["ph"] = "e";
             event["ts"] = Json::Int64((slices.ts()[i] + duration_ns) / 1000);
-            if (thread_ts_ns && thread_duration_ns && *thread_ts_ns > 0) {
+            if (thread_ts_ns > 0) {
               event["tts"] =
-                  Json::Int64((*thread_ts_ns + *thread_duration_ns) / 1000);
+                  Json::Int64((thread_ts_ns + thread_duration_ns) / 1000);
             }
-            if (thread_instruction_count && thread_instruction_delta &&
-                *thread_instruction_count > 0) {
+            if (thread_instruction_count > 0) {
               event["ticount"] = Json::Int64(
-                  (*thread_instruction_count + *thread_instruction_delta));
+                  (thread_instruction_count + thread_instruction_delta));
             }
             event["args"].clear();
             writer_.AddAsyncEndEvent(event);
@@ -1026,13 +965,9 @@
           PERFETTO_DLOG(
               "skipping non-instant slice on global or process track");
         } else {
-          if (legacy_phase.empty()) {
-            // Use "I" instead of "i" phase for backwards-compat with old
-            // consumers.
-            event["ph"] = "I";
-          } else {
-            event["ph"] = legacy_phase;
-          }
+          // Use "I" instead of "i" phase for backwards-compat with old
+          // consumers.
+          event["ph"] = "I";
 
           auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
           if (opt_process_row.has_value()) {
@@ -1053,83 +988,6 @@
     return util::OkStatus();
   }
 
-  base::Optional<Json::Value> CreateFlowEventV1(uint32_t flow_id,
-                                                SliceId slice_id,
-                                                std::string name,
-                                                std::string cat,
-                                                Json::Value args,
-                                                bool flow_begin) {
-    const auto& slices = storage_->slice_table();
-    const auto& thread_tracks = storage_->thread_track_table();
-
-    auto opt_slice_idx = slices.id().IndexOf(slice_id);
-    if (!opt_slice_idx)
-      return base::nullopt;
-    uint32_t slice_idx = opt_slice_idx.value();
-
-    TrackId track_id = storage_->slice_table().track_id()[slice_idx];
-    auto opt_thread_track_idx = thread_tracks.id().IndexOf(track_id);
-    // catapult only supports flow events attached to thread-track slices
-    if (!opt_thread_track_idx)
-      return base::nullopt;
-
-    UniqueTid utid = thread_tracks.utid()[opt_thread_track_idx.value()];
-    auto pid_and_tid = UtidToPidAndTid(utid);
-    Json::Value event;
-    event["id"] = flow_id;
-    event["pid"] = Json::Int(pid_and_tid.first);
-    event["tid"] = Json::Int(pid_and_tid.second);
-    event["cat"] = cat;
-    event["name"] = name;
-    event["ph"] = (flow_begin ? "s" : "f");
-    event["ts"] = Json::Int64(slices.ts()[slice_idx] / 1000);
-    if (!flow_begin) {
-      event["bp"] = "e";
-    }
-    event["args"] = std::move(args);
-    return std::move(event);
-  }
-
-  util::Status ExportFlows() {
-    const auto& flow_table = storage_->flow_table();
-    const auto& slice_table = storage_->slice_table();
-    for (uint32_t i = 0; i < flow_table.row_count(); i++) {
-      SliceId slice_out = flow_table.slice_out()[i];
-      SliceId slice_in = flow_table.slice_in()[i];
-      uint32_t arg_set_id = flow_table.arg_set_id()[i];
-
-      std::string cat;
-      std::string name;
-      auto args = args_builder_.GetArgs(arg_set_id);
-      if (arg_set_id != kInvalidArgSetId) {
-        cat = args["cat"].asString();
-        name = args["name"].asString();
-        // Don't export these args since they are only used for this export and
-        // weren't part of the original event.
-        args.removeMember("name");
-        args.removeMember("cat");
-      } else {
-        auto opt_slice_out_idx = slice_table.id().IndexOf(slice_out);
-        PERFETTO_DCHECK(opt_slice_out_idx.has_value());
-        StringId cat_id = slice_table.category()[opt_slice_out_idx.value()];
-        StringId name_id = slice_table.name()[opt_slice_out_idx.value()];
-        cat = GetNonNullString(storage_, cat_id);
-        name = GetNonNullString(storage_, name_id);
-      }
-
-      auto out_event = CreateFlowEventV1(i, slice_out, name, cat, args,
-                                         /* flow_begin = */ true);
-      auto in_event = CreateFlowEventV1(i, slice_in, name, cat, std::move(args),
-                                        /* flow_begin = */ false);
-
-      if (out_event && in_event) {
-        writer_.WriteCommonEvent(out_event.value());
-        writer_.WriteCommonEvent(in_event.value());
-      }
-    }
-    return util::OkStatus();
-  }
-
   Json::Value ConvertLegacyRawEventToJson(uint32_t index) {
     const auto& events = storage_->raw_table();
 
@@ -1185,23 +1043,25 @@
       event["use_async_tts"] = legacy_args[kLegacyEventUseAsyncTtsKey];
 
     if (legacy_args.isMember(kLegacyEventUnscopedIdKey)) {
-      event["id"] = base::Uint64ToHexString(
-          legacy_args[kLegacyEventUnscopedIdKey].asUInt64());
+      event["id"] =
+          PrintUint64(legacy_args[kLegacyEventUnscopedIdKey].asUInt64());
     }
 
     if (legacy_args.isMember(kLegacyEventGlobalIdKey)) {
-      event["id2"]["global"] = base::Uint64ToHexString(
-          legacy_args[kLegacyEventGlobalIdKey].asUInt64());
+      event["id2"]["global"] =
+          PrintUint64(legacy_args[kLegacyEventGlobalIdKey].asUInt64());
     }
 
     if (legacy_args.isMember(kLegacyEventLocalIdKey)) {
-      event["id2"]["local"] = base::Uint64ToHexString(
-          legacy_args[kLegacyEventLocalIdKey].asUInt64());
+      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;
@@ -1242,128 +1102,7 @@
     return util::OkStatus();
   }
 
-  class MergedProfileSamplesEmitter {
-   public:
-    // The TraceFormatWriter must outlive this instance.
-    MergedProfileSamplesEmitter(TraceFormatWriter& writer) : writer_(writer) {}
-
-    uint64_t AddEventForUtid(UniqueTid utid,
-                             int64_t ts,
-                             CallsiteId callsite_id,
-                             const Json::Value& event) {
-      auto current_sample = current_events_.find(utid);
-
-      // If there's a current entry for our thread and it matches the callsite
-      // of the new sample, update the entry with the new timestamp. Otherwise
-      // create a new entry.
-      if (current_sample != current_events_.end() &&
-          current_sample->second.callsite_id() == callsite_id) {
-        current_sample->second.UpdateWithNewSample(ts);
-        return current_sample->second.event_id();
-      } else {
-        if (current_sample != current_events_.end())
-          current_events_.erase(current_sample);
-
-        auto new_entry = current_events_.emplace(
-            std::piecewise_construct, std::forward_as_tuple(utid),
-            std::forward_as_tuple(writer_, callsite_id, ts, event));
-        return new_entry.first->second.event_id();
-      }
-    }
-
-    static uint64_t GenerateNewEventId() {
-      // "n"-phase events are nestable async events which get tied together
-      // with their id, so we need to give each one a unique ID as we only
-      // want the samples to show up on their own track in the trace-viewer
-      // but not nested together (unless they're nested under a merged event).
-      static size_t g_id_counter = 0;
-      return ++g_id_counter;
-    }
-
-   private:
-    class Sample {
-     public:
-      Sample(TraceFormatWriter& writer,
-             CallsiteId callsite_id,
-             int64_t ts,
-             const Json::Value& event)
-          : writer_(writer),
-            callsite_id_(callsite_id),
-            begin_ts_(ts),
-            end_ts_(ts),
-            event_(event),
-            event_id_(MergedProfileSamplesEmitter::GenerateNewEventId()),
-            sample_count_(1) {}
-
-      ~Sample() {
-        // No point writing a merged event if we only got a single sample
-        // as ExportCpuProfileSamples will already be writing the instant event.
-        if (sample_count_ == 1)
-          return;
-
-        event_["id"] = base::Uint64ToHexString(event_id_);
-
-        // Write the BEGIN event.
-        event_["ph"] = "b";
-        // We subtract 1us as a workaround for the first async event not
-        // nesting underneath the parent event if the timestamp is identical.
-        int64_t begin_in_us_ = begin_ts_ / 1000;
-        event_["ts"] = Json::Int64(std::min(begin_in_us_ - 1, begin_in_us_));
-        writer_.WriteCommonEvent(event_);
-
-        // Write the END event.
-        event_["ph"] = "e";
-        event_["ts"] = Json::Int64(end_ts_ / 1000);
-        // No need for args for the end event; remove them to save some space.
-        event_["args"].clear();
-        writer_.WriteCommonEvent(event_);
-      }
-
-      void UpdateWithNewSample(int64_t ts) {
-        // We assume samples for a given thread will appear in timestamp
-        // order; if this assumption stops holding true, we'll have to sort the
-        // samples first.
-        if (ts < end_ts_ || begin_ts_ > ts) {
-          PERFETTO_ELOG(
-              "Got an timestamp out of sequence while merging stack samples "
-              "during JSON export!\n");
-          PERFETTO_DCHECK(false);
-        }
-
-        end_ts_ = ts;
-        sample_count_++;
-      }
-
-      uint64_t event_id() const { return event_id_; }
-      CallsiteId callsite_id() const { return callsite_id_; }
-
-     public:
-      Sample(const Sample&) = delete;
-      Sample& operator=(const Sample&) = delete;
-      Sample& operator=(Sample&& value) = delete;
-
-      TraceFormatWriter& writer_;
-      CallsiteId callsite_id_;
-      int64_t begin_ts_;
-      int64_t end_ts_;
-      Json::Value event_;
-      uint64_t event_id_;
-      size_t sample_count_;
-    };
-
-    MergedProfileSamplesEmitter(const MergedProfileSamplesEmitter&) = delete;
-    MergedProfileSamplesEmitter& operator=(const MergedProfileSamplesEmitter&) =
-        delete;
-    MergedProfileSamplesEmitter& operator=(
-        MergedProfileSamplesEmitter&& value) = delete;
-
-    std::unordered_map<UniqueTid, Sample> current_events_;
-    TraceFormatWriter& writer_;
-  };
-
   util::Status ExportCpuProfileSamples() {
-    MergedProfileSamplesEmitter merged_sample_emitter(writer_);
-
     const tables::CpuProfileStackSampleTable& samples =
         storage_->cpu_profile_stack_sample_table();
     for (uint32_t i = 0; i < samples.row_count(); ++i) {
@@ -1385,6 +1124,13 @@
       // samples.
       event["tts"] = Json::Int64(1);
 
+      // "n"-phase events are nestable async events which get tied together with
+      // their id, so we need to give each one a unique ID as we only
+      // want the samples to show up on their own track in the trace-viewer but
+      // not nested together.
+      static size_t g_id_counter = 0;
+      event["id"] = PrintUint64(++g_id_counter);
+
       const auto& callsites = storage_->stack_profile_callsite_table();
       const auto& frames = storage_->stack_profile_frame_table();
       const auto& mappings = storage_->stack_profile_mapping_table();
@@ -1412,7 +1158,7 @@
         char frame_entry[1024];
         snprintf(frame_entry, sizeof(frame_entry), "%s - %s [%s]\n",
                  (symbol_name.empty()
-                      ? base::Uint64ToHexString(
+                      ? PrintUint64(
                             static_cast<uint64_t>(frames.rel_pc()[frame_row]))
                             .c_str()
                       : symbol_name.c_str()),
@@ -1438,22 +1184,6 @@
       // tid.
       event["args"]["thread_id"] = Json::Int(pid_and_tid.second);
 
-      // Emit duration events for adjacent samples with the same callsite.
-      // For now, only do this when the trace has already been symbolized i.e.
-      // are not directly output by Chrome, to avoid interfering with other
-      // processing pipelines.
-      base::Optional<CallsiteId> opt_current_callsite_id =
-          samples.callsite_id()[i];
-
-      if (opt_current_callsite_id && storage_->symbol_table().row_count() > 0) {
-        uint64_t parent_event_id = merged_sample_emitter.AddEventForUtid(
-            utid, samples.ts()[i], *opt_current_callsite_id, event);
-        event["id"] = base::Uint64ToHexString(parent_event_id);
-      } else {
-        event["id"] = base::Uint64ToHexString(
-            MergedProfileSamplesEmitter::GenerateNewEventId());
-      }
-
       writer_.WriteCommonEvent(event);
     }
 
@@ -1467,23 +1197,16 @@
     const auto& str_values = trace_metadata.str_value();
 
     // Create a mapping from key string ids to keys.
-    std::unordered_map<StringId, metadata::KeyId> key_map;
+    std::unordered_map<StringId, metadata::KeyIDs> key_map;
     for (uint32_t i = 0; i < metadata::kNumKeys; ++i) {
       auto id = *storage_->string_pool().GetId(metadata::kNames[i]);
-      key_map[id] = static_cast<metadata::KeyId>(i);
+      key_map[id] = static_cast<metadata::KeyIDs>(i);
     }
 
     for (uint32_t pos = 0; pos < trace_metadata.row_count(); pos++) {
-      auto key_it = key_map.find(keys[pos]);
-      // Skip exporting dynamic entries; the cr-xxx entries that come from
-      // the ChromeMetadata proto message are already exported from the raw
-      // table.
-      if (key_it == key_map.end())
-        continue;
-
       // Cast away from enum type, as otherwise -Wswitch-enum will demand an
       // exhaustive list of cases, even if there's a default case.
-      metadata::KeyId key = key_it->second;
+      metadata::KeyIDs key = key_map[keys[pos]];
       switch (static_cast<size_t>(key)) {
         case metadata::benchmark_description:
           writer_.AppendTelemetryMetadataString(
@@ -1551,227 +1274,6 @@
     return util::OkStatus();
   }
 
-  util::Status ExportMemorySnapshots() {
-    const auto& memory_snapshots = storage_->memory_snapshot_table();
-    base::Optional<StringId> private_footprint_id =
-        storage_->string_pool().GetId("chrome.private_footprint_kb");
-    base::Optional<StringId> peak_resident_set_id =
-        storage_->string_pool().GetId("chrome.peak_resident_set_kb");
-
-    for (uint32_t memory_index = 0; memory_index < memory_snapshots.row_count();
-         ++memory_index) {
-      Json::Value event_base;
-
-      event_base["ph"] = "v";
-      event_base["cat"] = "disabled-by-default-memory-infra";
-      auto snapshot_id = memory_snapshots.id()[memory_index].value;
-      event_base["id"] = base::Uint64ToHexString(snapshot_id);
-      int64_t snapshot_ts = memory_snapshots.timestamp()[memory_index];
-      event_base["ts"] = Json::Int64(snapshot_ts / 1000);
-      // TODO(crbug:1116359): Add dump type to the snapshot proto
-      // to properly fill event_base["name"]
-      event_base["name"] = "periodic_interval";
-      event_base["args"]["dumps"]["level_of_detail"] = GetNonNullString(
-          storage_, memory_snapshots.detail_level()[memory_index]);
-
-      // Export OS dump events for processes with relevant data.
-      const auto& process_table = storage_->process_table();
-      for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
-        Json::Value event =
-            FillInProcessEventDetails(event_base, process_table.pid()[upid]);
-        Json::Value& totals = event["args"]["dumps"]["process_totals"];
-
-        const auto& process_counters = storage_->process_counter_track_table();
-
-        for (uint32_t counter_index = 0;
-             counter_index < process_counters.row_count(); ++counter_index) {
-          if (process_counters.upid()[counter_index] != upid)
-            continue;
-          TrackId track_id = process_counters.id()[counter_index];
-          if (private_footprint_id && (process_counters.name()[counter_index] ==
-                                       private_footprint_id)) {
-            totals["private_footprint_bytes"] = base::Uint64ToHexStringNoPrefix(
-                GetCounterValue(track_id, snapshot_ts));
-          } else if (peak_resident_set_id &&
-                     (process_counters.name()[counter_index] ==
-                      peak_resident_set_id)) {
-            totals["peak_resident_set_size"] = base::Uint64ToHexStringNoPrefix(
-                GetCounterValue(track_id, snapshot_ts));
-          }
-        }
-
-        auto process_args_id = process_table.arg_set_id()[upid];
-        if (process_args_id) {
-          const Json::Value* process_args =
-              &args_builder_.GetArgs(process_args_id);
-          if (process_args->isMember("is_peak_rss_resettable")) {
-            totals["is_peak_rss_resettable"] =
-                (*process_args)["is_peak_rss_resettable"];
-          }
-        }
-
-        const auto& smaps_table = storage_->profiler_smaps_table();
-        // Do not create vm_regions without memory maps, since catapult expects
-        // to have rows.
-        Json::Value* smaps =
-            smaps_table.row_count() > 0
-                ? &event["args"]["dumps"]["process_mmaps"]["vm_regions"]
-                : nullptr;
-        for (uint32_t smaps_index = 0; smaps_index < smaps_table.row_count();
-             ++smaps_index) {
-          if (smaps_table.upid()[smaps_index] != upid)
-            continue;
-          if (smaps_table.ts()[smaps_index] != snapshot_ts)
-            continue;
-          Json::Value region;
-          region["mf"] =
-              GetNonNullString(storage_, smaps_table.file_name()[smaps_index]);
-          region["pf"] =
-              Json::Int64(smaps_table.protection_flags()[smaps_index]);
-          region["sa"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(smaps_table.start_address()[smaps_index]));
-          region["sz"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(smaps_table.size_kb()[smaps_index]) * 1024);
-          region["ts"] =
-              Json::Int64(smaps_table.module_timestamp()[smaps_index]);
-          region["id"] = GetNonNullString(
-              storage_, smaps_table.module_debugid()[smaps_index]);
-          region["df"] = GetNonNullString(
-              storage_, smaps_table.module_debug_path()[smaps_index]);
-          region["bs"]["pc"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(
-                  smaps_table.private_clean_resident_kb()[smaps_index]) *
-              1024);
-          region["bs"]["pd"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(
-                  smaps_table.private_dirty_kb()[smaps_index]) *
-              1024);
-          region["bs"]["pss"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(
-                  smaps_table.proportional_resident_kb()[smaps_index]) *
-              1024);
-          region["bs"]["sc"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(
-                  smaps_table.shared_clean_resident_kb()[smaps_index]) *
-              1024);
-          region["bs"]["sd"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(
-                  smaps_table.shared_dirty_resident_kb()[smaps_index]) *
-              1024);
-          region["bs"]["sw"] = base::Uint64ToHexStringNoPrefix(
-              static_cast<uint64_t>(smaps_table.swap_kb()[smaps_index]) * 1024);
-          smaps->append(region);
-        }
-
-        if (!totals.empty() || (smaps && !smaps->empty()))
-          writer_.WriteCommonEvent(event);
-      }
-
-      // Export chrome dump events for process snapshots in current memory
-      // snapshot.
-      const auto& process_snapshots = storage_->process_memory_snapshot_table();
-
-      for (uint32_t process_index = 0;
-           process_index < process_snapshots.row_count(); ++process_index) {
-        if (process_snapshots.snapshot_id()[process_index].value != snapshot_id)
-          continue;
-
-        auto process_snapshot_id = process_snapshots.id()[process_index].value;
-        uint32_t pid = UpidToPid(process_snapshots.upid()[process_index]);
-
-        // Shared memory nodes are imported into a fake process with pid 0.
-        // Catapult expects them to be associated with one of the real processes
-        // of the snapshot, so we choose the first one we can find and replace
-        // the pid.
-        if (pid == 0) {
-          for (uint32_t i = 0; i < process_snapshots.row_count(); ++i) {
-            if (process_snapshots.snapshot_id()[i].value != snapshot_id)
-              continue;
-            uint32_t new_pid = UpidToPid(process_snapshots.upid()[i]);
-            if (new_pid != 0) {
-              pid = new_pid;
-              break;
-            }
-          }
-        }
-
-        Json::Value event = FillInProcessEventDetails(event_base, pid);
-
-        const auto& snapshot_nodes = storage_->memory_snapshot_node_table();
-
-        for (uint32_t node_index = 0; node_index < snapshot_nodes.row_count();
-             ++node_index) {
-          if (snapshot_nodes.process_snapshot_id()[node_index].value !=
-              process_snapshot_id) {
-            continue;
-          }
-          const char* path =
-              GetNonNullString(storage_, snapshot_nodes.path()[node_index]);
-          event["args"]["dumps"]["allocators"][path]["guid"] =
-              base::Uint64ToHexStringNoPrefix(
-                  static_cast<uint64_t>(snapshot_nodes.id()[node_index].value));
-          if (snapshot_nodes.size()[node_index]) {
-            AddAttributeToMemoryNode(&event, path, "size",
-                                     snapshot_nodes.size()[node_index],
-                                     "bytes");
-          }
-          if (snapshot_nodes.effective_size()[node_index]) {
-            AddAttributeToMemoryNode(
-                &event, path, "effective_size",
-                snapshot_nodes.effective_size()[node_index], "bytes");
-          }
-
-          auto node_args_id = snapshot_nodes.arg_set_id()[node_index];
-          if (!node_args_id)
-            continue;
-          const Json::Value* node_args =
-              &args_builder_.GetArgs(node_args_id.value());
-          for (const auto& arg_name : node_args->getMemberNames()) {
-            const Json::Value& arg_value = (*node_args)[arg_name]["value"];
-            if (arg_value.empty())
-              continue;
-            if (arg_value.isString()) {
-              AddAttributeToMemoryNode(&event, path, arg_name,
-                                       arg_value.asString());
-            } else if (arg_value.isInt64()) {
-              Json::Value unit = (*node_args)[arg_name]["unit"];
-              if (unit.empty())
-                unit = "unknown";
-              AddAttributeToMemoryNode(&event, path, arg_name,
-                                       arg_value.asInt64(), unit.asString());
-            }
-          }
-        }
-
-        const auto& snapshot_edges = storage_->memory_snapshot_edge_table();
-
-        for (uint32_t edge_index = 0; edge_index < snapshot_edges.row_count();
-             ++edge_index) {
-          SnapshotNodeId source_node_id =
-              snapshot_edges.source_node_id()[edge_index];
-          uint32_t source_node_row =
-              *snapshot_nodes.id().IndexOf(source_node_id);
-
-          if (snapshot_nodes.process_snapshot_id()[source_node_row].value !=
-              process_snapshot_id) {
-            continue;
-          }
-          Json::Value edge;
-          edge["source"] = base::Uint64ToHexStringNoPrefix(
-              snapshot_edges.source_node_id()[edge_index].value);
-          edge["target"] = base::Uint64ToHexStringNoPrefix(
-              snapshot_edges.target_node_id()[edge_index].value);
-          edge["importance"] =
-              Json::Int(snapshot_edges.importance()[edge_index]);
-          edge["type"] = "ownership";
-          event["args"]["dumps"]["allocators_graph"].append(edge);
-        }
-        writer_.WriteCommonEvent(event);
-      }
-    }
-    return util::OkStatus();
-  }
-
   uint32_t UpidToPid(UniquePid upid) {
     auto pid_it = upids_to_exported_pids_.find(upid);
     PERFETTO_DCHECK(pid_it != upids_to_exported_pids_.end());
@@ -1808,62 +1310,6 @@
     return false;
   }
 
-  Json::Value FillInProcessEventDetails(const Json::Value& event,
-                                        uint32_t pid) {
-    Json::Value output = event;
-    output["pid"] = Json::Int(pid);
-    output["tid"] = Json::Int(-1);
-    return output;
-  }
-
-  void AddAttributeToMemoryNode(Json::Value* event,
-                                const std::string& path,
-                                const std::string& key,
-                                int64_t value,
-                                const std::string& units) {
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["value"] =
-        base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(value));
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["type"] =
-        "scalar";
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["units"] =
-        units;
-  }
-
-  void AddAttributeToMemoryNode(Json::Value* event,
-                                const std::string& path,
-                                const std::string& key,
-                                const std::string& value,
-                                const std::string& units = "") {
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["value"] =
-        value;
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["type"] =
-        "string";
-    (*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["units"] =
-        units;
-  }
-
-  uint64_t GetCounterValue(TrackId track_id, int64_t ts) {
-    const auto& counter_table = storage_->counter_table();
-    auto begin = counter_table.ts().begin();
-    auto end = counter_table.ts().end();
-    PERFETTO_DCHECK(counter_table.ts().IsSorted() &&
-                    counter_table.ts().IsColumnType<int64_t>());
-    // The timestamp column is sorted, so we can binary search for a matching
-    // timestamp. Note that we don't use RowMap operations like FilterInto()
-    // here because they bloat trace processor's binary size in Chrome too much.
-    auto it = std::lower_bound(begin, end, ts,
-                               [](const SqlValue& value, int64_t expected_ts) {
-                                 return value.AsLong() < expected_ts;
-                               });
-    for (; it < end; ++it) {
-      if ((*it).AsLong() != ts)
-        break;
-      if (counter_table.track_id()[it.row()].value == track_id.value)
-        return static_cast<uint64_t>(counter_table.value()[it.row()]);
-    }
-    return 0;
-  }
-
   const TraceStorage* storage_;
   ArgsBuilder args_builder_;
   TraceFormatWriter writer_;
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 9dadb44..ef15834 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -24,14 +24,11 @@
 #include <json/reader.h>
 #include <json/value.h>
 
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/event_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/proto/metadata_tracker.h"
-#include "src/trace_processor/importers/proto/track_event_tracker.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 #include "test/gtest_and_gmock.h"
@@ -71,7 +68,6 @@
   ExportJsonTest() {
     context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
     context_.args_tracker.reset(new ArgsTracker(&context_));
-    context_.event_tracker.reset(new EventTracker(&context_));
     context_.storage.reset(new TraceStorage());
     context_.track_tracker.reset(new TrackTracker(&context_));
     context_.metadata_tracker.reset(new MetadataTracker(&context_));
@@ -90,12 +86,9 @@
   }
 
   Json::Value ToJsonValue(const std::string& json) {
-    Json::CharReaderBuilder b;
-    auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
+    Json::Reader reader;
     Json::Value result;
-    EXPECT_TRUE(reader->parse(json.data(), json.data() + json.length(), &result,
-                              nullptr))
-        << json;
+    EXPECT_TRUE(reader.parse(json, result)) << json;
     return result;
   }
 
@@ -130,11 +123,11 @@
   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));
-  // The thread_slice table is a sub table of slice.
-  context_.storage->mutable_thread_slice_table()->Insert(
-      {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0, SliceId(0u), 0,
-       kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
-       kThreadInstructionDelta});
+  context_.storage->mutable_slice_table()->Insert(
+      {kTimestamp, kDuration, track, 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+");
@@ -176,10 +169,11 @@
   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_thread_slice_table()->Insert(
-      {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0, SliceId(0u), 0,
-       kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
-       kThreadInstructionDelta});
+  context_.storage->mutable_slice_table()->Insert(
+      {kTimestamp, kDuration, track, 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+");
@@ -230,8 +224,9 @@
 }
 
 TEST_F(ExportJsonTest, SystemEventsIgnored) {
-  TrackId track = context_.track_tracker->CreateAndroidAsyncTrack(
-      /*name=*/kNullStringId, /*upid=*/0);
+  constexpr int64_t kCookie = 22;
+  TrackId track = context_.track_tracker->InternAndroidAsyncTrack(
+      /*name=*/kNullStringId, /*upid=*/0, kCookie);
   context_.args_tracker->Flush();  // Flush track args.
 
   // System events have no category.
@@ -256,7 +251,6 @@
   const char* kStoryName = "story name";
   const char* kStoryTag1 = "tag1";
   const char* kStoryTag2 = "tag2";
-  const char* kDynamicKey = "dyn_key1";
   const int64_t kBenchmarkStart = 1000000;
   const int64_t kStoryStart = 2000000;
   const bool kHadFailures = true;
@@ -302,13 +296,6 @@
   context_.metadata_tracker->SetMetadata(metadata::benchmark_had_failures,
                                          had_failures);
 
-  // Metadata entries with dynamic keys are not currently exported from the
-  // metadata table (the Chrome metadata is exported directly from the raw
-  // table).
-  StringId dynamic_key_id =
-      context_.storage->InternString(base::StringView(kDynamicKey));
-  context_.metadata_tracker->SetDynamicMetadata(dynamic_key_id, 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);
@@ -343,8 +330,6 @@
 
   EXPECT_EQ(telemetry_metadata["hadFailures"].size(), 1u);
   EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures);
-
-  EXPECT_FALSE(result["metadata"].isMember(kDynamicKey));
 }
 
 TEST_F(ExportJsonTest, StorageWithStats) {
@@ -458,6 +443,10 @@
 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();
 
@@ -466,14 +455,23 @@
   context_.args_tracker->Flush();  // Flush track args.
   StringId cat_id = storage->InternString(base::StringView(kCategory));
   StringId name_id = storage->InternString(base::StringView(kName));
-  SliceId id1 = storage->mutable_slice_table()
-                    ->Insert({0, 0, track, cat_id, name_id, 0, 0, 0})
-                    .id;
-  SliceId id2 = storage->mutable_slice_table()
-                    ->Insert({100, 0, track, cat_id, name_id, 0, 0, 0})
-                    .id;
+  SliceId id = storage->mutable_slice_table()
+                   ->Insert({0, 0, track, cat_id, name_id, 0, 0, 0})
+                   .id;
+  auto inserter = context_.args_tracker->AddArgsTo(id);
 
-  storage->mutable_flow_table()->Insert({id1, id2, 0});
+  auto add_arg = [&](const char* key, Variadic value) {
+    inserter.AddArg(storage->InternString(key), 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+");
@@ -482,30 +480,17 @@
   EXPECT_TRUE(status.ok());
 
   Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 4u);
+  EXPECT_EQ(result["traceEvents"].size(), 1u);
 
-  Json::Value slice_out = result["traceEvents"][0];
-  Json::Value slice_in = result["traceEvents"][1];
-  Json::Value flow_out = result["traceEvents"][2];
-  Json::Value flow_in = result["traceEvents"][3];
-
-  EXPECT_EQ(flow_out["cat"].asString(), kCategory);
-  EXPECT_EQ(flow_out["name"].asString(), kName);
-  EXPECT_EQ(flow_out["ph"].asString(), "s");
-  EXPECT_EQ(flow_out["tid"].asString(), slice_out["tid"].asString());
-  EXPECT_EQ(flow_out["pid"].asString(), slice_out["pid"].asString());
-
-  EXPECT_EQ(flow_in["cat"].asString(), kCategory);
-  EXPECT_EQ(flow_in["name"].asString(), kName);
-  EXPECT_EQ(flow_in["ph"].asString(), "f");
-  EXPECT_EQ(flow_in["bp"].asString(), "e");
-  EXPECT_EQ(flow_in["tid"].asString(), slice_in["tid"].asString());
-  EXPECT_EQ(flow_in["pid"].asString(), slice_in["pid"].asString());
-
-  EXPECT_LE(slice_out["ts"].asInt64(), flow_out["ts"].asInt64());
-  EXPECT_GE(slice_in["ts"].asInt64(), flow_in["ts"].asInt64());
-
-  EXPECT_EQ(flow_out["id"].asString(), flow_in["id"].asString());
+  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) {
@@ -749,15 +734,14 @@
       {kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
 
   // Global track.
-  TrackEventTracker track_event_tracker(&context_);
-  TrackId track2 = track_event_tracker.GetOrCreateDefaultDescriptorTrack();
+  TrackId track2 = context_.track_tracker->GetOrCreateDefaultDescriptorTrack();
   context_.args_tracker->Flush();  // Flush track args.
   context_.storage->mutable_slice_table()->Insert(
       {kTimestamp2, 0, track2, cat_id, name_id, 0, 0, 0});
 
   // Async event track.
-  track_event_tracker.ReserveDescriptorChildTrack(1234, 0, kNullStringId);
-  TrackId track3 = *track_event_tracker.GetDescriptorTrack(1234);
+  context_.track_tracker->ReserveDescriptorChildTrack(1234, 0, kNullStringId);
+  TrackId track3 = *context_.track_tracker->GetDescriptorTrack(1234);
   context_.args_tracker->Flush();  // Flush track args.
   context_.storage->mutable_slice_table()->Insert(
       {kTimestamp3, 0, track3, cat_id, name_id, 0, 0, 0});
@@ -830,7 +814,8 @@
       base::nullopt, base::nullopt, 1, kNullStringId);
   UniqueTid utid1a = context_.process_tracker->UpdateThread(1, 1);
   UniqueTid utid1b = context_.process_tracker->UpdateThread(2, 1);
-  UniqueTid utid1c = context_.process_tracker->StartNewThread(base::nullopt, 2);
+  UniqueTid utid1c =
+      context_.process_tracker->StartNewThread(base::nullopt, 2, kNullStringId);
   // Associate the new thread with its process.
   ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1));
 
@@ -1063,151 +1048,6 @@
   EXPECT_FALSE(end_event3.isMember("use_async_tts"));
 }
 
-TEST_F(ExportJsonTest, LegacyAsyncEvents) {
-  using Arg = GlobalArgsTracker::Arg;
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = 100000;
-  const int64_t kTimestamp2 = 10001000;
-  const int64_t kDuration2 = 0;
-  const int64_t kTimestamp3 = 10005000;
-  const int64_t kDuration3 = 100000;
-  const uint32_t kProcessID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const char* kName2 = "name2";
-  const char* kName3 = "name3";
-
-  UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  StringId name2_id = context_.storage->InternString(base::StringView(kName2));
-  StringId name3_id = context_.storage->InternString(base::StringView(kName3));
-
-  auto arg_inserter = [this](base::StringView arg_name,
-                             base::StringView arg_value,
-                             std::vector<Arg>& args) {
-    Arg arg;
-    StringId arg_key_id =
-        context_.storage->InternString(base::StringView(arg_name));
-    arg.flat_key = arg_key_id;
-    arg.key = arg_key_id;
-    StringId value_id = context_.storage->InternString(arg_value);
-    arg.value = Variadic::String(value_id);
-    args.push_back(arg);
-  };
-
-  constexpr int64_t kSourceId = 235;
-  TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/kNullStringId);
-  constexpr int64_t kSourceId2 = 236;
-  TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/kNullStringId);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  context_.storage->mutable_slice_table()->Insert(
-      {kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
-  std::vector<Arg> args1;
-  arg_inserter("arg1", "value1", args1);
-  arg_inserter("legacy_event.phase", "S", args1);
-  ArgSetId arg_id1 = context_.global_args_tracker->AddArgSet(args1, 0, 2);
-  context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0,
-                                                                     arg_id1);
-
-  // Step event with first event as parent.
-  context_.storage->mutable_slice_table()->Insert(
-      {kTimestamp2, kDuration2, track, cat_id, name2_id, 0, 0, 0});
-  std::vector<Arg> step_args;
-  arg_inserter("arg2", "value2", step_args);
-  arg_inserter("legacy_event.phase", "T", step_args);
-  arg_inserter("debug.step", "Step1", step_args);
-  ArgSetId arg_id2 = context_.global_args_tracker->AddArgSet(step_args, 0, 3);
-  context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(1,
-                                                                     arg_id2);
-
-  // Another overlapping async event on a different track.
-  context_.storage->mutable_slice_table()->Insert(
-      {kTimestamp3, kDuration3, track2, cat_id, name3_id, 0, 0, 0});
-  std::vector<Arg> args3;
-  arg_inserter("legacy_event.phase", "S", args3);
-  ArgSetId arg_id3 = context_.global_args_tracker->AddArgSet(args3, 0, 1);
-  context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(2,
-                                                                     arg_id3);
-
-  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(), 5u);
-
-  // Events should be sorted by timestamp, with child slice's end before its
-  // parent.
-
-  Json::Value begin_event1 = result["traceEvents"][0];
-  EXPECT_EQ(begin_event1["ph"].asString(), "S");
-  EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(begin_event1["pid"].asInt(), static_cast<int>(kProcessID));
-  EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(begin_event1["cat"].asString(), kCategory);
-  EXPECT_EQ(begin_event1["name"].asString(), kName);
-  EXPECT_FALSE(begin_event1.isMember("tts"));
-  EXPECT_FALSE(begin_event1.isMember("use_async_tts"));
-  EXPECT_EQ(begin_event1["args"].size(), 1u);
-  EXPECT_EQ(begin_event1["args"]["arg1"].asString(), "value1");
-
-  Json::Value step_event = result["traceEvents"][1];
-  EXPECT_EQ(step_event["ph"].asString(), "T");
-  EXPECT_EQ(step_event["ts"].asInt64(), kTimestamp2 / 1000);
-  EXPECT_EQ(step_event["pid"].asInt(), static_cast<int>(kProcessID));
-  EXPECT_EQ(step_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(step_event["cat"].asString(), kCategory);
-  EXPECT_EQ(step_event["name"].asString(), kName2);
-  EXPECT_TRUE(step_event["args"].isObject());
-  EXPECT_EQ(step_event["args"].size(), 2u);
-  EXPECT_EQ(step_event["args"]["arg2"].asString(), "value2");
-  EXPECT_EQ(step_event["args"]["step"].asString(), "Step1");
-
-  Json::Value begin_event2 = result["traceEvents"][2];
-  EXPECT_EQ(begin_event2["ph"].asString(), "S");
-  EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp3 / 1000);
-  EXPECT_EQ(begin_event2["pid"].asInt(), static_cast<int>(kProcessID));
-  EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xec");
-  EXPECT_EQ(begin_event2["cat"].asString(), kCategory);
-  EXPECT_EQ(begin_event2["name"].asString(), kName3);
-  EXPECT_TRUE(begin_event2["args"].isObject());
-  EXPECT_EQ(begin_event2["args"].size(), 0u);
-  EXPECT_FALSE(begin_event2.isMember("tts"));
-  EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
-
-  Json::Value end_event1 = result["traceEvents"][3];
-  EXPECT_EQ(end_event1["ph"].asString(), "F");
-  EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
-  EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID));
-  EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(end_event1["cat"].asString(), kCategory);
-  EXPECT_EQ(end_event1["name"].asString(), kName);
-  EXPECT_TRUE(end_event1["args"].isObject());
-  EXPECT_EQ(end_event1["args"].size(), 0u);
-  EXPECT_FALSE(end_event1.isMember("tts"));
-  EXPECT_FALSE(end_event1.isMember("use_async_tts"));
-
-  Json::Value end_event3 = result["traceEvents"][4];
-  EXPECT_EQ(end_event3["ph"].asString(), "F");
-  EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000);
-  EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID));
-  EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec");
-  EXPECT_EQ(end_event3["cat"].asString(), kCategory);
-  EXPECT_EQ(end_event3["name"].asString(), kName3);
-  EXPECT_TRUE(end_event3["args"].isObject());
-  EXPECT_EQ(end_event3["args"].size(), 0u);
-  EXPECT_FALSE(end_event3.isMember("tts"));
-  EXPECT_FALSE(end_event3.isMember("use_async_tts"));
-}
-
 TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
   const int64_t kTimestamp = 10000000;
   const int64_t kDuration = 100000;
@@ -1231,7 +1071,7 @@
   auto id_and_row =
       slices->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0});
   context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
-      id_and_row.id, kThreadTimestamp, kThreadDuration, 0, 0);
+      id_and_row.id.value, kThreadTimestamp, kThreadDuration, 0, 0);
 
   base::TempFile temp_file = base::TempFile::Create();
   FILE* output = fopen(temp_file.path().c_str(), "w+");
@@ -1288,7 +1128,7 @@
           ->Insert({kTimestamp, kDuration, track, cat_id, name_id, 0, 0, 0})
           .id;
   context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
-      slice_id, kThreadTimestamp, kThreadDuration, 0, 0);
+      slice_id.value, kThreadTimestamp, kThreadDuration, 0, 0);
 
   base::TempFile temp_file = base::TempFile::Create();
   FILE* output = fopen(temp_file.path().c_str(), "w+");
@@ -1445,6 +1285,10 @@
   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);
 }
 
@@ -1545,12 +1389,6 @@
   storage->mutable_cpu_profile_stack_sample_table()->Insert(
       {kTimestamp, frame_callsite_2.id, utid, kProcessPriority});
 
-  storage->mutable_cpu_profile_stack_sample_table()->Insert(
-      {kTimestamp + 10000, frame_callsite_1.id, utid, kProcessPriority});
-
-  storage->mutable_cpu_profile_stack_sample_table()->Insert(
-      {kTimestamp + 20000, frame_callsite_1.id, utid, kProcessPriority});
-
   base::TempFile temp_file = base::TempFile::Create();
   FILE* output = fopen(temp_file.path().c_str(), "w+");
   util::Status status = ExportJson(storage, output);
@@ -1559,10 +1397,7 @@
 
   Json::Value result = ToJsonValue(ReadFile(output));
 
-  // The first sample should generate only a single instant event;
-  // the two following samples should also generate an additional [b, e] pair
-  // (the async duration event).
-  EXPECT_EQ(result["traceEvents"].size(), 5u);
+  EXPECT_EQ(result["traceEvents"].size(), 1u);
   Json::Value event = result["traceEvents"][0];
   EXPECT_EQ(event["ph"].asString(), "n");
   EXPECT_EQ(event["id"].asString(), "0x1");
@@ -1575,29 +1410,6 @@
             "foo_func - foo_module_name [foo_module_id]\nbar_func - "
             "bar_module_name [bar_module_id]\n");
   EXPECT_EQ(event["args"]["process_priority"].asInt(), kProcessPriority);
-
-  event = result["traceEvents"][1];
-  EXPECT_EQ(event["ph"].asString(), "n");
-  EXPECT_EQ(event["id"].asString(), "0x2");
-  EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 10000) / 1000);
-
-  event = result["traceEvents"][2];
-  EXPECT_EQ(event["ph"].asString(), "n");
-  EXPECT_EQ(event["id"].asString(), "0x2");
-  EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 20000) / 1000);
-  Json::String second_callstack_ = event["args"]["frames"].asString();
-  EXPECT_EQ(second_callstack_, "foo_func - foo_module_name [foo_module_id]\n");
-
-  event = result["traceEvents"][3];
-  EXPECT_EQ(event["ph"].asString(), "b");
-  EXPECT_EQ(event["id"].asString(), "0x2");
-  EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 10000) / 1000 - 1);
-  EXPECT_EQ(event["args"]["frames"].asString(), second_callstack_);
-
-  event = result["traceEvents"][4];
-  EXPECT_EQ(event["ph"].asString(), "e");
-  EXPECT_EQ(event["id"].asString(), "0x2");
-  EXPECT_EQ(event["ts"].asInt64(), (kTimestamp + 20000) / 1000);
 }
 
 TEST_F(ExportJsonTest, ArgumentFilter) {
@@ -1747,260 +1559,6 @@
   EXPECT_EQ(result[1]["name"].asString(), kName);
 }
 
-TEST_F(ExportJsonTest, MemorySnapshotOsDumpEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kPeakResidentSetSize = 100000;
-  const int64_t kPrivateFootprintBytes = 200000;
-  const int64_t kProtectionFlags = 1;
-  const int64_t kStartAddress = 1000000000;
-  const int64_t kSizeKb = 1000;
-  const int64_t kPrivateCleanResidentKb = 2000;
-  const int64_t kPrivateDirtyKb = 3000;
-  const int64_t kProportionalResidentKb = 4000;
-  const int64_t kSharedCleanResidentKb = 5000;
-  const int64_t kSharedDirtyResidentKb = 6000;
-  const int64_t kSwapKb = 7000;
-  const int64_t kModuleTimestamp = 20000000;
-  const uint32_t kProcessID = 100;
-  const bool kIsPeakRssResettable = true;
-  const char* kLevelOfDetail = "detailed";
-  const char* kFileName = "filename";
-  const char* kModuleDebugid = "debugid";
-  const char* kModuleDebugPath = "debugpath";
-
-  UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
-  TrackId track = context_.track_tracker->InternProcessTrack(upid);
-  StringId level_of_detail_id =
-      context_.storage->InternString(base::StringView(kLevelOfDetail));
-  auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
-                         ->Insert({kTimestamp, track, level_of_detail_id})
-                         .id;
-
-  StringId peak_resident_set_size_id =
-      context_.storage->InternString("chrome.peak_resident_set_kb");
-  TrackId peak_resident_set_size_counter =
-      context_.track_tracker->InternProcessCounterTrack(
-          peak_resident_set_size_id, upid);
-  context_.event_tracker->PushCounter(kTimestamp, kPeakResidentSetSize,
-                                      peak_resident_set_size_counter);
-
-  StringId private_footprint_bytes_id =
-      context_.storage->InternString("chrome.private_footprint_kb");
-  TrackId private_footprint_bytes_counter =
-      context_.track_tracker->InternProcessCounterTrack(
-          private_footprint_bytes_id, upid);
-  context_.event_tracker->PushCounter(kTimestamp, kPrivateFootprintBytes,
-                                      private_footprint_bytes_counter);
-
-  StringId is_peak_rss_resettable_id =
-      context_.storage->InternString("is_peak_rss_resettable");
-  context_.args_tracker->AddArgsTo(upid).AddArg(
-      is_peak_rss_resettable_id, Variadic::Boolean(kIsPeakRssResettable));
-  context_.args_tracker->Flush();
-
-  context_.storage->mutable_profiler_smaps_table()->Insert(
-      {upid, kTimestamp, kNullStringId, kSizeKb, kPrivateDirtyKb, kSwapKb,
-       context_.storage->InternString(kFileName), kStartAddress,
-       kModuleTimestamp, context_.storage->InternString(kModuleDebugid),
-       context_.storage->InternString(kModuleDebugPath), kProtectionFlags,
-       kPrivateCleanResidentKb, kSharedDirtyResidentKb, kSharedCleanResidentKb,
-       0, kProportionalResidentKb});
-
-  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(), "v");
-  EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
-  EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["name"].asString(), "periodic_interval");
-  EXPECT_EQ(event["pid"].asUInt(), kProcessID);
-  EXPECT_EQ(event["tid"].asInt(), -1);
-
-  EXPECT_TRUE(event["args"].isObject());
-  EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
-            kLevelOfDetail);
-
-  EXPECT_EQ(event["args"]["dumps"]["process_totals"]["peak_resident_set_size"]
-                .asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kPeakResidentSetSize)));
-  EXPECT_EQ(event["args"]["dumps"]["process_totals"]["private_footprint_bytes"]
-                .asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kPrivateFootprintBytes)));
-  EXPECT_EQ(event["args"]["dumps"]["process_totals"]["is_peak_rss_resettable"]
-                .asBool(),
-            kIsPeakRssResettable);
-
-  EXPECT_TRUE(event["args"]["dumps"]["process_mmaps"]["vm_regions"].isArray());
-  EXPECT_EQ(event["args"]["dumps"]["process_mmaps"]["vm_regions"].size(), 1u);
-  Json::Value region = event["args"]["dumps"]["process_mmaps"]["vm_regions"][0];
-  EXPECT_EQ(region["mf"].asString(), kFileName);
-  EXPECT_EQ(region["pf"].asInt64(), kProtectionFlags);
-  EXPECT_EQ(region["sa"].asString(), base::Uint64ToHexStringNoPrefix(
-                                         static_cast<uint64_t>(kStartAddress)));
-  EXPECT_EQ(
-      region["sz"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSizeKb * 1024)));
-  EXPECT_EQ(region["id"].asString(), kModuleDebugid);
-  EXPECT_EQ(region["df"].asString(), kModuleDebugPath);
-  EXPECT_EQ(region["bs"]["pc"].asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kPrivateCleanResidentKb * 1024)));
-  EXPECT_EQ(region["bs"]["pd"].asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kPrivateDirtyKb * 1024)));
-  EXPECT_EQ(region["bs"]["pss"].asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kProportionalResidentKb * 1024)));
-  EXPECT_EQ(region["bs"]["sc"].asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kSharedCleanResidentKb * 1024)));
-  EXPECT_EQ(region["bs"]["sd"].asString(),
-            base::Uint64ToHexStringNoPrefix(
-                static_cast<uint64_t>(kSharedDirtyResidentKb * 1024)));
-  EXPECT_EQ(
-      region["bs"]["sw"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSwapKb * 1024)));
-}
-
-TEST_F(ExportJsonTest, MemorySnapshotChromeDumpEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kSize = 1000;
-  const int64_t kEffectiveSize = 2000;
-  const int64_t kScalarAttrValue = 3000;
-  const uint32_t kOsProcessID = 100;
-  const uint32_t kChromeProcessID = 200;
-  const uint32_t kImportance = 1;
-  const char* kLevelOfDetail = "detailed";
-  const char* kPath1 = "path/to_file1";
-  const char* kPath2 = "path/to_file2";
-  const char* kScalarAttrUnits = "scalar_units";
-  const char* kStringAttrValue = "string_value";
-  const std::string kScalarAttrName = "scalar_name";
-  const std::string kStringAttrName = "string_name";
-
-  UniquePid os_upid =
-      context_.process_tracker->GetOrCreateProcess(kOsProcessID);
-  TrackId track = context_.track_tracker->InternProcessTrack(os_upid);
-  StringId level_of_detail_id =
-      context_.storage->InternString(base::StringView(kLevelOfDetail));
-  auto snapshot_id = context_.storage->mutable_memory_snapshot_table()
-                         ->Insert({kTimestamp, track, level_of_detail_id})
-                         .id;
-
-  UniquePid chrome_upid =
-      context_.process_tracker->GetOrCreateProcess(kChromeProcessID);
-  auto process_id = context_.storage->mutable_process_memory_snapshot_table()
-                        ->Insert({snapshot_id, chrome_upid})
-                        .id;
-
-  StringId path1_id = context_.storage->InternString(base::StringView(kPath1));
-  StringId path2_id = context_.storage->InternString(base::StringView(kPath2));
-  SnapshotNodeId node1_id =
-      context_.storage->mutable_memory_snapshot_node_table()
-          ->Insert(
-              {process_id, SnapshotNodeId(0), path1_id, kSize, kEffectiveSize})
-          .id;
-  SnapshotNodeId node2_id =
-      context_.storage->mutable_memory_snapshot_node_table()
-          ->Insert({process_id, SnapshotNodeId(0), path2_id, 0, 0})
-          .id;
-
-  context_.args_tracker->AddArgsTo(node1_id).AddArg(
-      context_.storage->InternString(
-          base::StringView(kScalarAttrName + ".value")),
-      Variadic::Integer(kScalarAttrValue));
-  context_.args_tracker->AddArgsTo(node1_id).AddArg(
-      context_.storage->InternString(
-          base::StringView(kScalarAttrName + ".unit")),
-      Variadic::String(context_.storage->InternString(kScalarAttrUnits)));
-  context_.args_tracker->AddArgsTo(node1_id).AddArg(
-      context_.storage->InternString(
-          base::StringView(kStringAttrName + ".value")),
-      Variadic::String(context_.storage->InternString(kStringAttrValue)));
-  context_.args_tracker->Flush();
-
-  context_.storage->mutable_memory_snapshot_edge_table()->Insert(
-      {node1_id, node2_id, kImportance});
-
-  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(), "v");
-  EXPECT_EQ(event["cat"].asString(), "disabled-by-default-memory-infra");
-  EXPECT_EQ(event["id"].asString(), base::Uint64ToHexString(snapshot_id.value));
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["name"].asString(), "periodic_interval");
-  EXPECT_EQ(event["pid"].asUInt(), kChromeProcessID);
-  EXPECT_EQ(event["tid"].asInt(), -1);
-
-  EXPECT_TRUE(event["args"].isObject());
-  EXPECT_EQ(event["args"]["dumps"]["level_of_detail"].asString(),
-            kLevelOfDetail);
-
-  EXPECT_EQ(event["args"]["dumps"]["allocators"].size(), 2u);
-  Json::Value node1 = event["args"]["dumps"]["allocators"][kPath1];
-  EXPECT_TRUE(node1.isObject());
-  EXPECT_EQ(
-      node1["guid"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
-  EXPECT_TRUE(node1["attrs"]["size"].isObject());
-  EXPECT_EQ(node1["attrs"]["size"]["value"].asString(),
-            base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kSize)));
-  EXPECT_EQ(node1["attrs"]["size"]["type"].asString(), "scalar");
-  EXPECT_EQ(node1["attrs"]["size"]["units"].asString(), "bytes");
-  EXPECT_EQ(
-      node1["attrs"]["effective_size"]["value"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kEffectiveSize)));
-  EXPECT_TRUE(node1["attrs"][kScalarAttrName].isObject());
-  EXPECT_EQ(
-      node1["attrs"][kScalarAttrName]["value"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(kScalarAttrValue)));
-  EXPECT_EQ(node1["attrs"][kScalarAttrName]["type"].asString(), "scalar");
-  EXPECT_EQ(node1["attrs"][kScalarAttrName]["units"].asString(),
-            kScalarAttrUnits);
-  EXPECT_TRUE(node1["attrs"][kStringAttrName].isObject());
-  EXPECT_EQ(node1["attrs"][kStringAttrName]["value"].asString(),
-            kStringAttrValue);
-  EXPECT_EQ(node1["attrs"][kStringAttrName]["type"].asString(), "string");
-  EXPECT_EQ(node1["attrs"][kStringAttrName]["units"].asString(), "");
-
-  Json::Value node2 = event["args"]["dumps"]["allocators"][kPath2];
-  EXPECT_TRUE(node2.isObject());
-  EXPECT_EQ(
-      node2["guid"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
-  EXPECT_TRUE(node2["attrs"].empty());
-
-  Json::Value graph = event["args"]["dumps"]["allocators_graph"];
-  EXPECT_TRUE(graph.isArray());
-  EXPECT_EQ(graph.size(), 1u);
-  EXPECT_EQ(
-      graph[0]["source"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node1_id.value)));
-  EXPECT_EQ(
-      graph[0]["target"].asString(),
-      base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(node2_id.value)));
-  EXPECT_EQ(graph[0]["importance"].asUInt(), kImportance);
-  EXPECT_EQ(graph[0]["type"].asString(), "ownership");
-}
-
 }  // namespace
 }  // namespace json
 }  // namespace trace_processor
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
index 4ba663e..27cf542 100644
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -21,7 +21,7 @@
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/ninja/ninja_log_parser.h"
 #include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/proto_trace_reader.h"
+#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/trace_sorter.h"
 
 namespace perfetto {
@@ -81,7 +81,7 @@
         PERFETTO_DLOG("Proto trace detected");
         // This will be reduced once we read the trace config and we see flush
         // period being set.
-        reader_.reset(new ProtoTraceReader(context_));
+        reader_.reset(new ProtoTraceTokenizer(context_));
         context_->sorter.reset(new TraceSorter(
             std::unique_ptr<TraceParser>(new ProtoTraceParser(context_)),
             kMaxWindowSize));
@@ -130,9 +130,7 @@
           return util::ErrStatus(kNoZlibErr);
         }
       case kUnknownTraceType:
-        // If renaming this error message don't remove the "(ERR:fmt)" part.
-        // The UI's error_dialog.ts uses it to make the dialog more graceful.
-        return util::ErrStatus("Unknown trace type provided (ERR:fmt)");
+        return util::ErrStatus("Unknown trace type provided");
     }
   }
 
@@ -161,7 +159,7 @@
     return kJsonTraceType;
 
   // Systrace with header but no leading HTML.
-  if (base::Contains(start, "# tracer"))
+  if (base::StartsWith(start, "# tracer"))
     return kSystraceTraceType;
 
   // Systrace with leading HTML.
@@ -170,7 +168,7 @@
     return kSystraceTraceType;
 
   // Ctrace is deflate'ed systrace.
-  if (base::Contains(start, "TRACE:"))
+  if (start.find("TRACE:") != std::string::npos)
     return kCtraceTraceType;
 
   // Ninja's buils log (.ninja_log).
@@ -185,10 +183,7 @@
   if (base::StartsWith(start, "\x1f\x8b"))
     return kGzipTraceType;
 
-  if (base::StartsWith(start, "\x0a"))
-    return kProtoTraceType;
-
-  return kUnknownTraceType;
+  return kProtoTraceType;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/forwarding_trace_parser.h b/src/trace_processor/forwarding_trace_parser.h
index 0da568a..8b8a8bb 100644
--- a/src/trace_processor/forwarding_trace_parser.h
+++ b/src/trace_processor/forwarding_trace_parser.h
@@ -17,7 +17,7 @@
 #ifndef SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
 #define SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 
 #include "src/trace_processor/types/trace_processor_context.h"
 
diff --git a/src/trace_processor/forwarding_trace_parser_unittest.cc b/src/trace_processor/forwarding_trace_parser_unittest.cc
index 048ab14..78eb404 100644
--- a/src/trace_processor/forwarding_trace_parser_unittest.cc
+++ b/src/trace_processor/forwarding_trace_parser_unittest.cc
@@ -58,13 +58,6 @@
   EXPECT_EQ(kFuchsiaTraceType, GuessTraceType(prefix, sizeof(prefix)));
 }
 
-TEST(TraceProcessorImplTest, GuessTraceType_Bmp) {
-  const uint8_t prefix[] = {0x42, 0x4d, 0x1e, 0x00, 0x00, 0x00, 0x00,
-                            0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
-                            0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
-  EXPECT_EQ(kUnknownTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/BUILD.gn b/src/trace_processor/importers/BUILD.gn
index fceb53f..082f7bb 100644
--- a/src/trace_processor/importers/BUILD.gn
+++ b/src/trace_processor/importers/BUILD.gn
@@ -12,21 +12,54 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/perfetto_cc_proto_descriptor.gni")
+import("../../../gn/perfetto.gni")
 
-perfetto_cc_proto_descriptor("gen_cc_config_descriptor") {
-  descriptor_name = "config.descriptor"
-  descriptor_target = "../../../protos/perfetto/config:descriptor"
+source_set("common") {
+  sources = [
+    "common/args_tracker.cc",
+    "common/args_tracker.h",
+    "common/clock_tracker.cc",
+    "common/clock_tracker.h",
+    "common/event_tracker.cc",
+    "common/event_tracker.h",
+    "common/global_args_tracker.cc",
+    "common/global_args_tracker.h",
+    "common/process_tracker.cc",
+    "common/process_tracker.h",
+    "common/slice_tracker.cc",
+    "common/slice_tracker.h",
+    "common/system_info_tracker.cc",
+    "common/system_info_tracker.h",
+    "common/track_tracker.cc",
+    "common/track_tracker.h",
+  ]
+  deps = [
+    "../../../gn:default_deps",
+    "../../../protos/perfetto/common:zero",
+    "../../../protos/perfetto/trace:zero",
+    "../../../protos/perfetto/trace/profiling:zero",
+    "../../base",
+    "../storage",
+    "../types",
+  ]
 }
 
-perfetto_cc_proto_descriptor("gen_cc_chrome_track_event_descriptor") {
-  descriptor_name = "chrome_track_event.descriptor"
-  descriptor_target =
-      "../../../protos/third_party/chromium:chrome_track_event_descriptor"
-}
-
-perfetto_cc_proto_descriptor("gen_cc_track_event_descriptor") {
-  descriptor_name = "track_event.descriptor"
-  descriptor_target =
-      "../../../protos/perfetto/trace/track_event:track_event_descriptor"
+source_set("unittests") {
+  sources = [
+    "common/clock_tracker_unittest.cc",
+    "common/event_tracker_unittest.cc",
+    "common/process_tracker_unittest.cc",
+    "common/slice_tracker_unittest.cc",
+  ]
+  testonly = true
+  deps = [
+    ":common",
+    "../../../gn:default_deps",
+    "../../../gn:gtest_and_gmock",
+    "../../../protos/perfetto/common:zero",
+    "../../../protos/perfetto/trace:zero",
+    "../../base",
+    "../storage",
+    "../types",
+  ]
 }
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
deleted file mode 100644
index e187260..0000000
--- a/src/trace_processor/importers/common/BUILD.gn
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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("common") {
-  sources = [
-    "args_tracker.cc",
-    "args_tracker.h",
-    "chunked_trace_reader.h",
-    "clock_tracker.cc",
-    "clock_tracker.h",
-    "event_tracker.cc",
-    "event_tracker.h",
-    "flow_tracker.cc",
-    "flow_tracker.h",
-    "global_args_tracker.cc",
-    "global_args_tracker.h",
-    "process_tracker.cc",
-    "process_tracker.h",
-    "slice_tracker.cc",
-    "slice_tracker.h",
-    "system_info_tracker.cc",
-    "system_info_tracker.h",
-    "trace_blob_view.h",
-    "trace_parser.h",
-    "track_tracker.cc",
-    "track_tracker.h",
-  ]
-  public_deps = [
-    "../:gen_cc_config_descriptor",
-    "../../util:protozero_to_text",
-  ]
-  deps = [
-    "../../../../gn:default_deps",
-    "../../../../include/perfetto/trace_processor:basic_types",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/trace:zero",
-    "../../../../protos/perfetto/trace/profiling:zero",
-    "../../../base",
-    "../../storage",
-    "../../types",
-  ]
-}
-
-source_set("unittests") {
-  sources = [
-    "clock_tracker_unittest.cc",
-    "event_tracker_unittest.cc",
-    "flow_tracker_unittest.cc",
-    "process_tracker_unittest.cc",
-    "slice_tracker_unittest.cc",
-  ]
-  testonly = true
-  deps = [
-    ":common",
-    "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/trace:zero",
-    "../../../base",
-    "../../storage",
-    "../../types",
-  ]
-}
diff --git a/src/trace_processor/importers/common/args_tracker.h b/src/trace_processor/importers/common/args_tracker.h
index 4c2c943..ebcc8f9 100644
--- a/src/trace_processor/importers/common/args_tracker.h
+++ b/src/trace_processor/importers/common/args_tracker.h
@@ -90,7 +90,6 @@
   };
 
   explicit ArgsTracker(TraceProcessorContext*);
-  ArgsTracker(const ArgsTracker&) = default;
   virtual ~ArgsTracker();
 
   BoundInserter AddArgsTo(RawId id) {
@@ -109,15 +108,6 @@
     return AddArgsTo(context_->storage->mutable_slice_table(), id);
   }
 
-  BoundInserter AddArgsTo(tables::FlowTable::Id id) {
-    return AddArgsTo(context_->storage->mutable_flow_table(), id);
-  }
-
-  BoundInserter AddArgsTo(tables::MemorySnapshotNodeTable::Id id) {
-    return AddArgsTo(context_->storage->mutable_memory_snapshot_node_table(),
-                     id);
-  }
-
   BoundInserter AddArgsTo(MetadataId id) {
     auto* table = context_->storage->mutable_metadata_table();
     uint32_t row = *table->id().IndexOf(id);
@@ -135,12 +125,6 @@
         context_->storage->mutable_vulkan_memory_allocations_table(), id);
   }
 
-  BoundInserter AddArgsTo(UniquePid id) {
-    return BoundInserter(
-        this, context_->storage->mutable_process_table()->mutable_arg_set_id(),
-        id);
-  }
-
   // Commits the added args to storage.
   // Virtual for testing.
   virtual void Flush();
diff --git a/src/trace_processor/importers/common/chunked_trace_reader.h b/src/trace_processor/importers/common/chunked_trace_reader.h
deleted file mode 100644
index dc90344..0000000
--- a/src/trace_processor/importers/common/chunked_trace_reader.h
+++ /dev/null
@@ -1,50 +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_COMMON_CHUNKED_TRACE_READER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CHUNKED_TRACE_READER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Base interface for first stage of parsing pipeline
-// (JsonTraceParser, ProtoTraceReader).
-class ChunkedTraceReader {
- public:
-  virtual ~ChunkedTraceReader();
-
-  // Pushes more data into the trace parser. There is no requirement for the
-  // 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;
-
-  // Called after the last Parse() call.
-  virtual void NotifyEndOfFile() = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CHUNKED_TRACE_READER_H_
diff --git a/src/trace_processor/importers/common/clock_tracker.cc b/src/trace_processor/importers/common/clock_tracker.cc
index 75518a2..af809db 100644
--- a/src/trace_processor/importers/common/clock_tracker.cc
+++ b/src/trace_processor/importers/common/clock_tracker.cc
@@ -19,7 +19,6 @@
 #include <inttypes.h>
 
 #include <algorithm>
-#include <atomic>
 #include <queue>
 
 #include "perfetto/base/logging.h"
@@ -41,11 +40,12 @@
 
 ClockTracker::~ClockTracker() = default;
 
-uint32_t ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
+void ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
   const auto snapshot_id = cur_snapshot_id_++;
 
   // Clear the cache
-  cache_.fill({});
+  static_assert(std::is_trivial<decltype(cache_)>::value, "must be trivial");
+  memset(&cache_[0], 0, sizeof(cache_));
 
   // Compute the fingerprint of the snapshot by hashing all clock ids. This is
   // used by the clock pathfinding logic.
@@ -65,7 +65,7 @@
                       "supported for sequence-scoped clocks.",
                       clock_id);
         context_->storage->IncrementStats(stats::invalid_clock_snapshots);
-        return snapshot_id;
+        return;
       }
       domain.unit_multiplier_ns = clock.unit_multiplier_ns;
       domain.is_incremental = clock.is_incremental;
@@ -79,7 +79,7 @@
                     clock_id, clock.unit_multiplier_ns, clock.is_incremental,
                     domain.unit_multiplier_ns, domain.is_incremental);
       context_->storage->IncrementStats(stats::invalid_clock_snapshots);
-      return snapshot_id;
+      return;
     }
     const int64_t timestamp_ns =
         clock.absolute_timestamp * domain.unit_multiplier_ns;
@@ -92,7 +92,7 @@
                     " at snapshot %" PRIu32 ".",
                     clock_id, snapshot_id);
       context_->storage->IncrementStats(stats::invalid_clock_snapshots);
-      return snapshot_id;
+      return;
     }
 
     // Clock ids in the range [64, 128) are sequence-scoped and must be
@@ -116,7 +116,7 @@
                       clock_id, snapshot_id, timestamp_ns,
                       vect.timestamps_ns.back());
         context_->storage->IncrementStats(stats::invalid_clock_snapshots);
-        return snapshot_id;
+        return;
       }
 
       PERFETTO_DLOG("Detected non-monotonic clock with ID %" PRIu64, clock_id);
@@ -159,7 +159,6 @@
         graph_.emplace(it2->clock_id, it1->clock_id, snapshot_hash);
     }
   }
-  return snapshot_id;
 }
 
 // Finds the shortest clock resolution path in the graph that allows to
@@ -211,13 +210,9 @@
 
   ClockPath path = FindPath(src_clock_id, target_clock_id);
   if (!path.valid()) {
-    // Too many logs maybe emitted when path is invalid.
-    static std::atomic<uint32_t> dlog_count(0);
-    if (dlog_count++ < 10) {
-      PERFETTO_DLOG("No path from clock %" PRIu64 " to %" PRIu64
-                    " at timestamp %" PRId64,
-                    src_clock_id, target_clock_id, src_timestamp);
-    }
+    PERFETTO_DLOG("No path from clock %" PRIu64 " to %" PRIu64
+                  " at timestamp %" PRId64,
+                  src_clock_id, target_clock_id, src_timestamp);
     context_->storage->IncrementStats(stats::clock_sync_failure);
     return base::nullopt;
   }
@@ -257,18 +252,11 @@
     // 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.
-    // This can also happen if the checks in AddSnapshot fail and we skip part
-    // of the snapshot.
     const ClockSnapshots& next_snap = next_clock->GetSnapshot(hash);
-
-    // Using std::lower_bound because snapshot_ids is sorted, so we can do
-    // a binary search. std::find would do a linear scan.
     auto next_it = std::lower_bound(next_snap.snapshot_ids.begin(),
                                     next_snap.snapshot_ids.end(), snapshot_id);
-    if (next_it == next_snap.snapshot_ids.end() || *next_it != snapshot_id) {
-      PERFETTO_DFATAL("Snapshot does not exist in clock domain.");
-      continue;
-    }
+    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());
diff --git a/src/trace_processor/importers/common/clock_tracker.h b/src/trace_processor/importers/common/clock_tracker.h
index 16b9d79..469aca7 100644
--- a/src/trace_processor/importers/common/clock_tracker.h
+++ b/src/trace_processor/importers/common/clock_tracker.h
@@ -154,8 +154,7 @@
 
   // Appends a new snapshot for the given clock domains.
   // This is typically called by the code that reads the ClockSnapshot packet.
-  // Returns the internal snapshot id of this set of clocks.
-  uint32_t AddSnapshot(const std::vector<ClockValue>&);
+  void AddSnapshot(const std::vector<ClockValue>&);
 
   // Converts a timestamp between two clock domains. Tries to use the cache
   // first (only for single-path resolutions), then falls back on path finding
@@ -188,8 +187,7 @@
 
   void SetTraceTimeClock(ClockId clock_id) {
     PERFETTO_DCHECK(!IsReservedSeqScopedClockId(clock_id));
-    if (trace_time_clock_id_used_for_conversion_ &&
-        trace_time_clock_id_ != clock_id) {
+    if (trace_time_clock_id_used_for_conversion_) {
       PERFETTO_ELOG("Not updating trace time clock from %" PRIu64 " to %" PRIu64
                     " because the old clock was already used for timestamp "
                     "conversion - ClockSnapshot too late in trace?",
diff --git a/src/trace_processor/importers/common/event_tracker.cc b/src/trace_processor/importers/common/event_tracker.cc
index 1be476f..3130566 100644
--- a/src/trace_processor/importers/common/event_tracker.cc
+++ b/src/trace_processor/importers/common/event_tracker.cc
@@ -55,9 +55,9 @@
                                                     double value,
                                                     TrackId track_id) {
   if (timestamp < max_timestamp_) {
-    PERFETTO_DLOG(
-        "counter event (ts: %" PRId64 ") out of order by %.4f ms, skipping",
-        timestamp, static_cast<double>(max_timestamp_ - timestamp) / 1e6);
+    PERFETTO_DLOG("counter event (ts: %" PRId64
+                  ") out of order by %.4f ms, skipping",
+                  timestamp, (max_timestamp_ - timestamp) / 1e6);
     context_->storage->IncrementStats(stats::counter_events_out_of_order);
     return base::nullopt;
   }
@@ -67,19 +67,6 @@
   return counter_values->Insert({timestamp, track_id, value}).id;
 }
 
-base::Optional<CounterId> EventTracker::PushCounter(
-    int64_t timestamp,
-    double value,
-    TrackId track_id,
-    SetArgsCallback args_callback) {
-  auto maybe_counter_id = PushCounter(timestamp, value, track_id);
-  if (maybe_counter_id) {
-    auto inserter = context_->args_tracker->AddArgsTo(*maybe_counter_id);
-    args_callback(&inserter);
-  }
-  return maybe_counter_id;
-}
-
 InstantId EventTracker::PushInstant(int64_t timestamp,
                                     StringId name_id,
                                     int64_t ref,
diff --git a/src/trace_processor/importers/common/event_tracker.h b/src/trace_processor/importers/common/event_tracker.h
index 428e858..26c3785 100644
--- a/src/trace_processor/importers/common/event_tracker.h
+++ b/src/trace_processor/importers/common/event_tracker.h
@@ -22,7 +22,6 @@
 
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
 
 namespace perfetto {
@@ -33,8 +32,6 @@
 // Tracks sched events, instants, and counters.
 class EventTracker {
  public:
-  using SetArgsCallback = std::function<void(ArgsTracker::BoundInserter*)>;
-
   explicit EventTracker(TraceProcessorContext*);
   EventTracker(const EventTracker&) = delete;
   EventTracker& operator=(const EventTracker&) = delete;
@@ -46,13 +43,6 @@
                                                 double value,
                                                 TrackId track_id);
 
-  // Adds a counter event with args to the counters table returning the index of
-  // the newly added row.
-  base::Optional<CounterId> PushCounter(int64_t timestamp,
-                                        double value,
-                                        TrackId track_id,
-                                        SetArgsCallback args_callback);
-
   // 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).
diff --git a/src/trace_processor/importers/common/flow_tracker.cc b/src/trace_processor/importers/common/flow_tracker.cc
deleted file mode 100644
index 9e6e2d8..0000000
--- a/src/trace_processor/importers/common/flow_tracker.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <limits>
-
-#include <stdint.h>
-
-#include "src/trace_processor/importers/common/flow_tracker.h"
-#include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-FlowTracker::FlowTracker(TraceProcessorContext* context) : context_(context) {
-  name_key_id_ = context_->storage->InternString("name");
-  cat_key_id_ = context_->storage->InternString("cat");
-}
-
-FlowTracker::~FlowTracker() = default;
-
-/* TODO: if we report a flow event earlier that a corresponding slice then
-  flow event would not be added, and it will increase "flow_no_enclosing_slice"
-  In catapult, it was possible to report a flow after an enclosing slice if
-  timestamps were equal. But because of our seqential processing of a trace
-  it is a bit tricky to make it here.
-  We suspect that this case is too rare or impossible */
-void FlowTracker::Begin(TrackId track_id, FlowId flow_id) {
-  base::Optional<SliceId> open_slice_id =
-      context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
-  if (!open_slice_id) {
-    context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
-    return;
-  }
-  if (flow_to_slice_map_.count(flow_id) != 0) {
-    context_->storage->IncrementStats(stats::flow_duplicate_id);
-    return;
-  }
-  flow_to_slice_map_[flow_id] = open_slice_id.value();
-}
-
-void FlowTracker::Step(TrackId track_id, FlowId flow_id) {
-  base::Optional<SliceId> open_slice_id =
-      context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
-  if (!open_slice_id) {
-    context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
-    return;
-  }
-  if (flow_to_slice_map_.count(flow_id) == 0) {
-    context_->storage->IncrementStats(stats::flow_step_without_start);
-    return;
-  }
-  SliceId slice_out_id = flow_to_slice_map_[flow_id];
-  InsertFlow(flow_id, slice_out_id, open_slice_id.value());
-  flow_to_slice_map_[flow_id] = open_slice_id.value();
-}
-
-void FlowTracker::End(TrackId track_id,
-                      FlowId flow_id,
-                      bool bind_enclosing_slice,
-                      bool close_flow) {
-  if (!bind_enclosing_slice) {
-    pending_flow_ids_map_[track_id].push_back(flow_id);
-    return;
-  }
-  base::Optional<SliceId> open_slice_id =
-      context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
-  if (!open_slice_id) {
-    context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
-    return;
-  }
-  if (flow_to_slice_map_.count(flow_id) == 0) {
-    context_->storage->IncrementStats(stats::flow_end_without_start);
-    return;
-  }
-  SliceId slice_out_id = flow_to_slice_map_[flow_id];
-  if (close_flow) {
-    flow_to_slice_map_.erase(flow_to_slice_map_.find(flow_id));
-  }
-  InsertFlow(flow_id, slice_out_id, open_slice_id.value());
-}
-
-bool FlowTracker::IsActive(FlowId flow_id) const {
-  return flow_to_slice_map_.find(flow_id) != flow_to_slice_map_.end();
-}
-
-FlowId FlowTracker::GetFlowIdForV1Event(uint64_t source_id,
-                                        StringId cat,
-                                        StringId name) {
-  V1FlowId v1_flow_id = {source_id, cat, name};
-  auto iter = v1_flow_id_to_flow_id_map_.find(v1_flow_id);
-  if (iter != v1_flow_id_to_flow_id_map_.end()) {
-    return iter->second;
-  }
-  FlowId new_id = v1_id_counter_++;
-  flow_id_to_v1_flow_id_map_[new_id] = v1_flow_id;
-  v1_flow_id_to_flow_id_map_[v1_flow_id] = new_id;
-  return new_id;
-}
-
-void FlowTracker::ClosePendingEventsOnTrack(TrackId track_id,
-                                            SliceId slice_id) {
-  auto iter = pending_flow_ids_map_.find(track_id);
-  if (iter == pending_flow_ids_map_.end())
-    return;
-
-  for (FlowId flow_id : iter->second) {
-    SliceId slice_out_id = flow_to_slice_map_[flow_id];
-    InsertFlow(flow_id, slice_out_id, slice_id);
-  }
-
-  pending_flow_ids_map_.erase(iter);
-}
-
-void FlowTracker::InsertFlow(FlowId flow_id,
-                             SliceId slice_out_id,
-                             SliceId slice_in_id) {
-  tables::FlowTable::Row row(slice_out_id, slice_in_id, kInvalidArgSetId);
-  auto id = context_->storage->mutable_flow_table()->Insert(row).id;
-
-  auto it = flow_id_to_v1_flow_id_map_.find(flow_id);
-  if (it != flow_id_to_v1_flow_id_map_.end()) {
-    // TODO(b/168007725): Add any args from v1 flow events and also export them.
-    auto args_tracker = ArgsTracker(context_);
-    auto inserter = context_->args_tracker->AddArgsTo(id);
-    inserter.AddArg(name_key_id_, Variadic::String(it->second.name));
-    inserter.AddArg(cat_key_id_, Variadic::String(it->second.cat));
-    context_->args_tracker->Flush();
-  }
-}
-
-void FlowTracker::InsertFlow(SliceId slice_out_id, SliceId slice_in_id) {
-  tables::FlowTable::Row row(slice_out_id, slice_in_id, kInvalidArgSetId);
-  context_->storage->mutable_flow_table()->Insert(row);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/common/flow_tracker.h b/src/trace_processor/importers/common/flow_tracker.h
deleted file mode 100644
index f05d854..0000000
--- a/src/trace_processor/importers/common/flow_tracker.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_
-
-#include <stdint.h>
-
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using FlowId = uint64_t;
-
-class FlowTracker {
- public:
-  explicit FlowTracker(TraceProcessorContext*);
-  virtual ~FlowTracker();
-
-  void InsertFlow(SliceId slice_out_id, SliceId slice_in_id);
-
-  // These methods assume you have created a FlowId via GetFlowIdForV1Event.
-  // If you don't have a v1 event you should use the InsertFlow method above.
-  virtual void Begin(TrackId track_id, FlowId flow_id);
-  virtual void Step(TrackId track_id, FlowId flow_id);
-
-  // When |bind_enclosing_slice| is true we will connect the flow to the
-  // currently open slice on the track, when false we will connect the flow to
-  // the next slice to be opened on the track.
-  // When |close_flow| is true it will mark this as the singular end of the
-  // flow, however if there are multiple end points this should be set to
-  // false. Both parameters are only needed for v1 flow events support
-  virtual void End(TrackId track_id,
-                   FlowId flow_id,
-                   bool bind_enclosing_slice,
-                   bool close_flow);
-
-  bool IsActive(FlowId flow_id) const;
-
-  FlowId GetFlowIdForV1Event(uint64_t source_id, StringId cat, StringId name);
-
-  void ClosePendingEventsOnTrack(TrackId track_id, SliceId slice_id);
-
- private:
-  struct V1FlowId {
-    uint64_t source_id;
-    StringId cat;
-    StringId name;
-
-    bool operator==(const V1FlowId& o) const {
-      return o.source_id == source_id && o.cat == cat && o.name == name;
-    }
-  };
-
-  struct V1FlowIdHasher {
-    size_t operator()(const V1FlowId& c) const {
-      base::Hash hasher;
-      hasher.Update(c.source_id);
-      hasher.Update(c.cat.raw_id());
-      hasher.Update(c.name.raw_id());
-      return std::hash<uint64_t>{}(hasher.digest());
-    }
-  };
-
-  using FlowToSourceSliceMap = std::unordered_map<FlowId, SliceId>;
-  using PendingFlowsMap = std::unordered_map<TrackId, std::vector<FlowId>>;
-  using V1FlowIdToFlowIdMap =
-      std::unordered_map<V1FlowId, FlowId, V1FlowIdHasher>;
-  using FlowIdToV1FlowId = std::unordered_map<FlowId, V1FlowId>;
-
-  void InsertFlow(FlowId flow_id,
-                  SliceId outgoing_slice_id,
-                  SliceId incoming_slice_id);
-
-  // List of flow end calls waiting for the next slice
-  PendingFlowsMap pending_flow_ids_map_;
-
-  // Flows generated by Begin() or Step()
-  FlowToSourceSliceMap flow_to_slice_map_;
-
-  V1FlowIdToFlowIdMap v1_flow_id_to_flow_id_map_;
-  FlowIdToV1FlowId flow_id_to_v1_flow_id_map_;
-  uint32_t v1_id_counter_ = 0;
-
-  TraceProcessorContext* const context_;
-
-  StringId name_key_id_;
-  StringId cat_key_id_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_
diff --git a/src/trace_processor/importers/common/flow_tracker_unittest.cc b/src/trace_processor/importers/common/flow_tracker_unittest.cc
deleted file mode 100644
index d8af423..0000000
--- a/src/trace_processor/importers/common/flow_tracker_unittest.cc
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vector>
-
-#include "src/trace_processor/importers/common/flow_tracker.h"
-#include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-using ::testing::Eq;
-
-TEST(FlowTrackerTest, SingleFlowEventExplicitInSliceBinding) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow_id = 1;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow_id);
-  slice_tracker->End(120, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  slice_tracker->Begin(140, track_2, StringId::Raw(2), StringId::Raw(2));
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-  tracker.End(track_2, flow_id, /* bind_enclosing = */ true,
-              /* close_flow = */ false);
-  slice_tracker->End(160, track_2, StringId::Raw(2), StringId::Raw(2));
-
-  const auto& flows = context.storage->flow_table();
-  EXPECT_EQ(flows.row_count(), 1u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice_id);
-  EXPECT_EQ(flows.slice_in()[0], in_slice_id);
-}
-
-TEST(FlowTrackerTest, SingleFlowEventWaitForNextSlice) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow_id = 1;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow_id);
-  slice_tracker->End(120, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  tracker.End(track_2, flow_id, /* bind_enclosing = */ false,
-              /* close_flow = */ false);
-
-  const auto& flows = context.storage->flow_table();
-
-  EXPECT_EQ(flows.row_count(), 0u);
-
-  slice_tracker->Begin(140, track_2, StringId::Raw(2), StringId::Raw(2));
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-  slice_tracker->End(160, track_2, StringId::Raw(2), StringId::Raw(2));
-
-  EXPECT_EQ(flows.row_count(), 1u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice_id);
-  EXPECT_EQ(flows.slice_in()[0], in_slice_id);
-}
-
-TEST(FlowTrackerTest, SingleFlowEventWaitForNextSliceScoped) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow_id = 1;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow_id);
-  slice_tracker->End(120, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  tracker.End(track_2, flow_id, /* bind_enclosing = */ false,
-              /* close_flow = */ false);
-
-  const auto& flows = context.storage->flow_table();
-
-  EXPECT_EQ(flows.row_count(), 0u);
-
-  slice_tracker->Scoped(140, track_2, StringId::Raw(2), StringId::Raw(2), 100);
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-
-  EXPECT_EQ(flows.row_count(), 1u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice_id);
-  EXPECT_EQ(flows.slice_in()[0], in_slice_id);
-}
-
-TEST(FlowTrackerTest, TwoFlowEventsWaitForNextSlice) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow1_id = 1;
-  FlowId flow2_id = 2;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  // begin flow1 in enclosing slice1
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice1_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow1_id);
-  tracker.End(track_2, flow1_id, /* bind_enclosing = */ false,
-              /* close_flow = */ false);
-  slice_tracker->End(120, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  // begin flow2 in enclosing slice2
-  slice_tracker->Begin(130, track_1, StringId::Raw(2), StringId::Raw(2));
-  SliceId out_slice2_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow2_id);
-  tracker.End(track_2, flow2_id, /* bind_enclosing = */ false,
-              /* close_flow = */ false);
-  slice_tracker->End(140, track_1, StringId::Raw(2), StringId::Raw(2));
-
-  const auto& flows = context.storage->flow_table();
-
-  EXPECT_EQ(flows.row_count(), 0u);
-
-  // close all pending flows
-  slice_tracker->Begin(160, track_2, StringId::Raw(3), StringId::Raw(3));
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-  slice_tracker->End(170, track_2, StringId::Raw(3), StringId::Raw(3));
-
-  EXPECT_EQ(flows.row_count(), 2u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice1_id);
-  EXPECT_EQ(flows.slice_in()[0], in_slice_id);
-  EXPECT_EQ(flows.slice_out()[1], out_slice2_id);
-  EXPECT_EQ(flows.slice_in()[1], in_slice_id);
-}
-
-TEST(FlowTrackerTest, TwoFlowEventsSliceInSlice) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow1_id = 1;
-  FlowId flow2_id = 2;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  // start two nested slices
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice1_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  slice_tracker->Begin(120, track_1, StringId::Raw(2), StringId::Raw(2));
-  SliceId out_slice2_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-
-  tracker.Begin(track_1, flow1_id);
-
-  slice_tracker->End(140, track_1, StringId::Raw(2), StringId::Raw(2));
-
-  tracker.Begin(track_1, flow2_id);
-
-  slice_tracker->End(150, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  slice_tracker->Begin(160, track_2, StringId::Raw(3), StringId::Raw(3));
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-
-  tracker.End(track_2, flow1_id, /* bind_enclosing = */ true,
-              /* close_flow = */ false);
-  tracker.End(track_2, flow2_id, /* bind_enclosing = */ true,
-              /* close_flow = */ false);
-
-  slice_tracker->End(170, track_2, StringId::Raw(3), StringId::Raw(3));
-
-  const auto& flows = context.storage->flow_table();
-  EXPECT_EQ(flows.row_count(), 2u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice2_id);
-  EXPECT_EQ(flows.slice_in()[0], in_slice_id);
-  EXPECT_EQ(flows.slice_out()[1], out_slice1_id);
-  EXPECT_EQ(flows.slice_in()[1], in_slice_id);
-}
-
-TEST(FlowTrackerTest, FlowEventsWithStep) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.slice_tracker.reset(new SliceTracker(&context));
-  auto& slice_tracker = context.slice_tracker;
-  FlowTracker tracker(&context);
-  slice_tracker->SetOnSliceBeginCallback(
-      [&tracker](TrackId track_id, SliceId slice_id) {
-        tracker.ClosePendingEventsOnTrack(track_id, slice_id);
-      });
-
-  FlowId flow_id = 1;
-  TrackId track_1(1);
-  TrackId track_2(2);
-
-  // flow begin inside slice1 on track1
-  slice_tracker->Begin(100, track_1, StringId::Raw(1), StringId::Raw(1));
-  SliceId out_slice1_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.Begin(track_1, flow_id);
-  slice_tracker->End(140, track_1, StringId::Raw(1), StringId::Raw(1));
-
-  // flow step inside slice2 on track2
-  slice_tracker->Begin(160, track_2, StringId::Raw(2), StringId::Raw(2));
-  SliceId inout_slice2_id =
-      slice_tracker->GetTopmostSliceOnTrack(track_2).value();
-  tracker.Step(track_2, flow_id);
-  slice_tracker->End(170, track_2, StringId::Raw(2), StringId::Raw(2));
-
-  // flow end inside slice3 on track3
-  slice_tracker->Begin(180, track_1, StringId::Raw(3), StringId::Raw(3));
-  SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_1).value();
-  tracker.End(track_1, flow_id, /* bind_enclosing = */ true,
-              /* close_flow = */ false);
-  slice_tracker->End(190, track_1, StringId::Raw(3), StringId::Raw(3));
-
-  const auto& flows = context.storage->flow_table();
-  EXPECT_EQ(flows.row_count(), 2u);
-  EXPECT_EQ(flows.slice_out()[0], out_slice1_id);
-  EXPECT_EQ(flows.slice_in()[0], inout_slice2_id);
-  EXPECT_EQ(flows.slice_out()[1], inout_slice2_id);
-  EXPECT_EQ(flows.slice_in()[1], in_slice_id);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/common/global_args_tracker.h b/src/trace_processor/importers/common/global_args_tracker.h
index 94b960e..4a0417d 100644
--- a/src/trace_processor/importers/common/global_args_tracker.h
+++ b/src/trace_processor/importers/common/global_args_tracker.h
@@ -49,7 +49,7 @@
   struct ArgHasher {
     uint64_t operator()(const Arg& arg) const noexcept {
       base::Hash hash;
-      hash.Update(arg.key.raw_id());
+      hash.Update(arg.key);
       // We don't hash arg.flat_key because it's a subsequence of arg.key.
       switch (arg.value.type) {
         case Variadic::Type::kInt:
@@ -59,7 +59,7 @@
           hash.Update(arg.value.uint_value);
           break;
         case Variadic::Type::kString:
-          hash.Update(arg.value.string_value.raw_id());
+          hash.Update(arg.value.string_value);
           break;
         case Variadic::Type::kReal:
           hash.Update(arg.value.real_value);
@@ -71,7 +71,7 @@
           hash.Update(arg.value.bool_value);
           break;
         case Variadic::Type::kJson:
-          hash.Update(arg.value.json_value.raw_id());
+          hash.Update(arg.value.json_value);
           break;
       }
       return hash.digest();
diff --git a/src/trace_processor/importers/common/process_tracker.cc b/src/trace_processor/importers/common/process_tracker.cc
index 173d47d..f7ae380 100644
--- a/src/trace_processor/importers/common/process_tracker.cc
+++ b/src/trace_processor/importers/common/process_tracker.cc
@@ -25,36 +25,21 @@
 namespace trace_processor {
 
 ProcessTracker::ProcessTracker(TraceProcessorContext* context)
-    : context_(context), args_tracker_(context) {
-  // Reserve utid/upid 0. These are special as embedders (e.g. Perfetto UI)
-  // exclude them by filtering them out. If the parsed trace contains ftrace
-  // data, SetPidZeroIgnoredForIdleProcess will create a mapping
-  // to these rows for tid/pid 0.
-  tables::ThreadTable::Row thread_row;
-  thread_row.tid = 0;
-  context_->storage->mutable_thread_table()->Insert(thread_row);
-
-  tables::ProcessTable::Row process_row;
-  process_row.pid = 0;
-  context_->storage->mutable_process_table()->Insert(process_row);
-
-  // An element to match the reserved tid = 0.
-  thread_name_priorities_.push_back(ThreadNamePriority::kOther);
-}
+    : context_(context) {}
 
 ProcessTracker::~ProcessTracker() = default;
 
 UniqueTid ProcessTracker::StartNewThread(base::Optional<int64_t> timestamp,
-                                         uint32_t tid) {
+                                         uint32_t tid,
+                                         StringId thread_name_id) {
   tables::ThreadTable::Row row;
   row.tid = tid;
+  row.name = thread_name_id;
   row.start_ts = timestamp;
 
   auto* thread_table = context_->storage->mutable_thread_table();
   UniqueTid new_utid = thread_table->Insert(row).row;
   tids_[tid].emplace_back(new_utid);
-  PERFETTO_DCHECK(thread_name_priorities_.size() == new_utid);
-  thread_name_priorities_.push_back(ThreadNamePriority::kOther);
   return new_utid;
 }
 
@@ -100,28 +85,23 @@
 
 UniqueTid ProcessTracker::GetOrCreateThread(uint32_t tid) {
   auto utid = GetThreadOrNull(tid);
-  return utid ? *utid : StartNewThread(base::nullopt, tid);
+  return utid ? *utid : StartNewThread(base::nullopt, tid, kNullStringId);
 }
 
 UniqueTid ProcessTracker::UpdateThreadName(uint32_t tid,
-                                           StringId thread_name_id,
-                                           ThreadNamePriority priority) {
+                                           StringId thread_name_id) {
+  auto* thread_table = context_->storage->mutable_thread_table();
   auto utid = GetOrCreateThread(tid);
-  UpdateThreadNameByUtid(utid, thread_name_id, priority);
+  if (!thread_name_id.is_null())
+    thread_table->mutable_name()->Set(utid, thread_name_id);
   return utid;
 }
 
-void ProcessTracker::UpdateThreadNameByUtid(UniqueTid utid,
-                                            StringId thread_name_id,
-                                            ThreadNamePriority priority) {
-  if (thread_name_id.is_null())
-    return;
-
+void ProcessTracker::SetThreadNameIfUnset(UniqueTid utid,
+                                          StringId thread_name_id) {
   auto* thread_table = context_->storage->mutable_thread_table();
-  if (priority >= thread_name_priorities_[utid]) {
+  if (thread_table->name()[utid].is_null())
     thread_table->mutable_name()->Set(utid, thread_name_id);
-    thread_name_priorities_[utid] = priority;
-  }
 }
 
 bool ProcessTracker::IsThreadAlive(UniqueTid utid) {
@@ -195,7 +175,8 @@
   base::Optional<UniqueTid> opt_utid = GetThreadOrNull(tid, pid);
 
   // If no matching thread was found, create a new one.
-  UniqueTid utid = opt_utid ? *opt_utid : StartNewThread(base::nullopt, tid);
+  UniqueTid utid =
+      opt_utid ? *opt_utid : StartNewThread(base::nullopt, tid, kNullStringId);
   PERFETTO_DCHECK(thread_table->tid()[utid] == tid);
 
   // Find matching process or create new one.
@@ -220,7 +201,7 @@
 
   // 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);
+  StartNewThread(timestamp, /*tid=*/pid, kNullStringId);
 
   // Note that we erased the pid above so this should always return a new
   // process.
@@ -251,8 +232,7 @@
 
 UniquePid ProcessTracker::SetProcessMetadata(uint32_t pid,
                                              base::Optional<uint32_t> ppid,
-                                             base::StringView name,
-                                             base::StringView cmdline) {
+                                             base::StringView name) {
   auto proc_name_id = context_->storage->InternString(name);
 
   base::Optional<UniquePid> pupid;
@@ -264,8 +244,6 @@
 
   auto* process_table = context_->storage->mutable_process_table();
   process_table->mutable_name()->Set(upid, proc_name_id);
-  process_table->mutable_cmdline()->Set(
-      upid, context_->storage->InternString(cmdline));
 
   if (pupid)
     process_table->mutable_parent_upid()->Set(upid, *pupid);
@@ -289,13 +267,6 @@
     process_table->mutable_name()->Set(upid, process_name_id);
 }
 
-void ProcessTracker::SetStartTsIfUnset(UniquePid upid,
-                                       int64_t start_ts_nanoseconds) {
-  auto* process_table = context_->storage->mutable_process_table();
-  if (!process_table->start_ts()[upid].has_value())
-    process_table->mutable_start_ts()->Set(upid, start_ts_nanoseconds);
-}
-
 void ProcessTracker::UpdateProcessNameFromThreadName(uint32_t tid,
                                                      StringId thread_name) {
   auto* thread_table = context_->storage->mutable_thread_table();
@@ -398,8 +369,7 @@
       pending_parent_assocs_.pop_back();
     }
 
-    auto end = pending_assocs_.end();
-    for (auto it = pending_assocs_.begin(); it != end;) {
+    for (auto it = pending_assocs_.begin(); it != pending_assocs_.end();) {
       UniqueTid other_utid;
       if (it->first == utid) {
         other_utid = it->second;
@@ -417,20 +387,15 @@
                       tt->upid()[other_utid] == upid);
       AssociateThreadToProcess(other_utid, upid);
 
-      // Swap the current element to the end of the list and move the end
-      // iterator back. This works because |pending_assocs_| is not sorted. We
-      // do it this way rather than modifying |pending_assocs_| directly to
-      // prevent undefined behaviour caused by modifying a vector while
-      // iterating through it.
-      std::swap(*it, *(--end));
+      // Erase the pair. The |pending_assocs_| vector is not sorted and swapping
+      // a std::pair<uint32_t, uint32_t> is cheap.
+      std::swap(*it, pending_assocs_.back());
+      pending_assocs_.pop_back();
 
       // Recurse into the newly resolved thread. Some other threads might have
       // been bound to that.
       resolved_utids.emplace_back(other_utid);
     }
-
-    // Make sure to actually erase the utids which have been resolved.
-    pending_assocs_.erase(end, pending_assocs_.end());
   }  // while (!resolved_utids.empty())
 }
 
@@ -446,17 +411,6 @@
   // Create a mapping from (t|p)id 0 -> u(t|p)id 0 for the idle process.
   tids_.emplace(0, std::vector<UniqueTid>{0});
   pids_.emplace(0, 0);
-
-  auto swapper_id = context_->storage->InternString("swapper");
-  UpdateThreadName(0, swapper_id, ThreadNamePriority::kTraceProcessorConstant);
-}
-
-ArgsTracker::BoundInserter ProcessTracker::AddArgsTo(UniquePid upid) {
-  return args_tracker_.AddArgsTo(upid);
-}
-
-void ProcessTracker::NotifyEndOfFile() {
-  args_tracker_.Flush();
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/common/process_tracker.h b/src/trace_processor/importers/common/process_tracker.h
index 3c46c38..e993c6b 100644
--- a/src/trace_processor/importers/common/process_tracker.h
+++ b/src/trace_processor/importers/common/process_tracker.h
@@ -20,29 +20,12 @@
 #include <tuple>
 
 #include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-// Thread names can come from different sources, and we don't always want to
-// overwrite the previously set name. This enum determines the priority of
-// different sources.
-enum class ThreadNamePriority {
-  kOther = 0,
-  kFtrace = 1,
-  kProcessTree = 2,
-  kTrackDescriptorThreadType = 3,
-  kTrackDescriptor = 4,
-
-  // Priority when trace processor hardcodes a name for a process (e.g. calling
-  // the idle thread "swapper" when parsing ftrace).
-  // Keep this last.
-  kTraceProcessorConstant = 5,
-};
-
 class ProcessTracker {
  public:
   explicit ProcessTracker(TraceProcessorContext*);
@@ -65,7 +48,9 @@
 
   // Called when a task_newtask is observed. This force the tracker to start
   // a new UTID for the thread, which is needed for TID-recycling resolution.
-  UniqueTid StartNewThread(base::Optional<int64_t> timestamp, uint32_t tid);
+  UniqueTid StartNewThread(base::Optional<int64_t> timestamp,
+                           uint32_t tid,
+                           StringId thread_name_id);
 
   // Returns whether a thread is considered alive by the process tracker.
   bool IsThreadAlive(UniqueTid utid);
@@ -80,17 +65,14 @@
   // Returns the thread utid (or creates a new entry if not present)
   UniqueTid GetOrCreateThread(uint32_t tid);
 
-  // Assigns the given name to the thread if the new name has a higher priority
-  // than the existing one. Returns the utid of the thread.
-  virtual UniqueTid UpdateThreadName(uint32_t tid,
-                                     StringId thread_name_id,
-                                     ThreadNamePriority priority);
+  // 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 if the new name has a higher priority
-  // than the existing one. The thread is identified by utid.
-  virtual void UpdateThreadNameByUtid(UniqueTid utid,
-                                      StringId thread_name_id,
-                                      ThreadNamePriority priority);
+  // 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);
 
   // 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.
@@ -109,8 +91,7 @@
   // Virtual for testing.
   virtual UniquePid SetProcessMetadata(uint32_t pid,
                                        base::Optional<uint32_t> ppid,
-                                       base::StringView name,
-                                       base::StringView cmdline);
+                                       base::StringView name);
 
   // Sets the process user id.
   void SetProcessUid(UniquePid upid, uint32_t uid);
@@ -119,10 +100,6 @@
   // have a name yet.
   virtual void SetProcessNameIfUnset(UniquePid upid, StringId process_name_id);
 
-  // Sets the start timestamp to the process identified by |upid| if it doesn't
-  // have a timestamp yet.
-  void SetStartTsIfUnset(UniquePid upid, int64_t start_ts_nanoseconds);
-
   // 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);
@@ -156,14 +133,6 @@
   // traces, we always have the "swapper" (idle) process having tid/pid 0.
   void SetPidZeroIgnoredForIdleProcess();
 
-  // Returns a BoundInserter to add arguments to the arg set of a process.
-  // Arguments are flushed into trace storage only after the trace was loaded in
-  // its entirety.
-  ArgsTracker::BoundInserter AddArgsTo(UniquePid upid);
-
-  // Called when the trace was fully loaded.
-  void NotifyEndOfFile();
-
  private:
   // Returns the utid of a thread having |tid| and |pid| as the parent process.
   // pid == base::nullopt matches all processes.
@@ -182,8 +151,6 @@
 
   TraceProcessorContext* const context_;
 
-  ArgsTracker args_tracker_;
-
   // Each tid can have multiple UniqueTid entries, a new UniqueTid is assigned
   // each time a thread is seen in the trace.
   std::map<uint32_t /* tid */, std::vector<UniqueTid>> tids_;
@@ -202,9 +169,6 @@
   // 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_;
-
-  // A mapping from utid to the priority of a thread name source.
-  std::vector<ThreadNamePriority> thread_name_priorities_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/common/process_tracker_unittest.cc b/src/trace_processor/importers/common/process_tracker_unittest.cc
index 3b1f9dd..f9bad28 100644
--- a/src/trace_processor/importers/common/process_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/process_tracker_unittest.cc
@@ -17,7 +17,6 @@
 #include "src/trace_processor/importers/common/process_tracker.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
 #include "test/gtest_and_gmock.h"
@@ -45,18 +44,20 @@
 };
 
 TEST_F(ProcessTrackerTest, PushProcess) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
-                                              base::StringView());
+  TraceStorage storage;
+  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
   ASSERT_EQ(pair_it.first->second, 1u);
 }
 
 TEST_F(ProcessTrackerTest, GetOrCreateNewProcess) {
+  TraceStorage storage;
   auto upid = context.process_tracker->GetOrCreateProcess(123);
   ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
 }
 
 TEST_F(ProcessTrackerTest, StartNewProcess) {
+  TraceStorage storage;
   auto upid =
       context.process_tracker->StartNewProcess(1000, 0u, 123, kNullStringId);
   ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
@@ -64,20 +65,16 @@
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
-                                              base::StringView());
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
-                                              base::StringView());
+  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
+  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
   ASSERT_EQ(pair_it.first->second, 1u);
   ASSERT_EQ(++pair_it.first, pair_it.second);
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_DifferentPid) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
-                                              base::StringView());
-  context.process_tracker->SetProcessMetadata(3, base::nullopt, "test",
-                                              base::StringView());
+  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
+  context.process_tracker->SetProcessMetadata(3, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPidForTesting(1);
   ASSERT_EQ(pair_it.first->second, 1u);
   auto second_pair_it = context.process_tracker->UpidsForPidForTesting(3);
@@ -85,8 +82,7 @@
 }
 
 TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test",
-                                              base::StringView());
+  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
   auto name =
       context.storage->GetString(context.storage->process_table().name()[1]);
   ASSERT_EQ(name, "test");
@@ -124,46 +120,6 @@
   ASSERT_EQ(context.storage->thread_table().row_count(), 5u);
 }
 
-TEST_F(ProcessTrackerTest, Cmdline) {
-  UniquePid upid = context.process_tracker->SetProcessMetadata(
-      1, base::nullopt, "test", "cmdline blah");
-  ASSERT_EQ(context.storage->process_table().cmdline().GetString(upid),
-            "cmdline blah");
-}
-
-TEST_F(ProcessTrackerTest, UpdateThreadName) {
-  auto name1 = context.storage->InternString("name1");
-  auto name2 = context.storage->InternString("name2");
-  auto name3 = context.storage->InternString("name3");
-
-  context.process_tracker->UpdateThreadName(1, name1,
-                                            ThreadNamePriority::kFtrace);
-  ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
-  ASSERT_EQ(context.storage->thread_table().name()[1], name1);
-
-  context.process_tracker->UpdateThreadName(1, name2,
-                                            ThreadNamePriority::kProcessTree);
-  // The priority is higher: the name should change.
-  ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
-  ASSERT_EQ(context.storage->thread_table().name()[1], name2);
-
-  context.process_tracker->UpdateThreadName(1, name3,
-                                            ThreadNamePriority::kFtrace);
-  // The priority is lower: the name should stay the same.
-  ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
-  ASSERT_EQ(context.storage->thread_table().name()[1], name2);
-}
-
-TEST_F(ProcessTrackerTest, SetStartTsIfUnset) {
-  auto upid = context.process_tracker->StartNewProcess(
-      /*timestamp=*/base::nullopt, 0u, 123, kNullStringId);
-  context.process_tracker->SetStartTsIfUnset(upid, 1000);
-  ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
-
-  context.process_tracker->SetStartTsIfUnset(upid, 3000);
-  ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/common/slice_tracker.cc b/src/trace_processor/importers/common/slice_tracker.cc
index 728f9c2..3fca417 100644
--- a/src/trace_processor/importers/common/slice_tracker.cc
+++ b/src/trace_processor/importers/common/slice_tracker.cc
@@ -26,21 +26,22 @@
 
 namespace perfetto {
 namespace trace_processor {
+namespace {
+// Slices which have been opened but haven't been closed yet will be marked
+// with this duration placeholder.
+constexpr int64_t kPendingDuration = -1;
+}  // namespace
 
 SliceTracker::SliceTracker(TraceProcessorContext* context)
-    : legacy_unnestable_begin_count_string_id_(
-          context->storage->InternString("legacy_unnestable_begin_count")),
-      legacy_unnestable_last_begin_ts_string_id_(
-          context->storage->InternString("legacy_unnestable_last_begin_ts")),
-      context_(context) {}
+    : context_(context) {}
 
 SliceTracker::~SliceTracker() = default;
 
-base::Optional<SliceId> SliceTracker::Begin(int64_t timestamp,
-                                            TrackId track_id,
-                                            StringId category,
-                                            StringId name,
-                                            SetArgsCallback args_callback) {
+base::Optional<uint32_t> SliceTracker::Begin(int64_t timestamp,
+                                             TrackId track_id,
+                                             StringId category,
+                                             StringId name,
+                                             SetArgsCallback args_callback) {
   tables::SliceTable::Row row(timestamp, kPendingDuration, track_id, category,
                               name);
   return StartSlice(timestamp, track_id, args_callback, [this, &row]() {
@@ -48,33 +49,36 @@
   });
 }
 
-void SliceTracker::BeginLegacyUnnestable(tables::SliceTable::Row row,
-                                         SetArgsCallback args_callback) {
+void SliceTracker::BeginGpu(tables::GpuSliceTable::Row row,
+                            SetArgsCallback args_callback) {
   // Ensure that the duration is pending for this row.
   // TODO(lalitm): change this to eventually use null instead of -1.
   row.dur = kPendingDuration;
 
-  // Double check that if we've seen this track in the past, it was also
-  // marked as unnestable then.
-#if PERFETTO_DCHECK_IS_ON()
-  auto it = stacks_.find(row.track_id);
-  PERFETTO_DCHECK(it == stacks_.end() || it->second.is_legacy_unnestable);
-#endif
-
-  // Ensure that StartSlice knows that this track is unnestable.
-  stacks_[row.track_id].is_legacy_unnestable = true;
-
   StartSlice(row.ts, row.track_id, args_callback, [this, &row]() {
-    return context_->storage->mutable_slice_table()->Insert(row).id;
+    return context_->storage->mutable_gpu_slice_table()->Insert(row).id;
   });
 }
 
-base::Optional<SliceId> SliceTracker::Scoped(int64_t timestamp,
-                                             TrackId track_id,
-                                             StringId category,
-                                             StringId name,
-                                             int64_t duration,
-                                             SetArgsCallback args_callback) {
+void SliceTracker::BeginFrameEvent(tables::GraphicsFrameSliceTable::Row row,
+                                   SetArgsCallback args_callback) {
+  // Ensure that the duration is pending for this row.
+  // TODO(lalitm): change this to eventually use null instead of -1.
+  row.dur = kPendingDuration;
+
+  StartSlice(row.ts, row.track_id, args_callback, [this, &row]() {
+    return context_->storage->mutable_graphics_frame_slice_table()
+        ->Insert(row)
+        .id;
+  });
+}
+
+base::Optional<uint32_t> SliceTracker::Scoped(int64_t timestamp,
+                                              TrackId track_id,
+                                              StringId category,
+                                              StringId name,
+                                              int64_t duration,
+                                              SetArgsCallback args_callback) {
   PERFETTO_DCHECK(duration >= 0);
 
   tables::SliceTable::Row row(timestamp, duration, track_id, category, name);
@@ -83,26 +87,48 @@
   });
 }
 
-base::Optional<SliceId> SliceTracker::End(int64_t timestamp,
-                                          TrackId track_id,
-                                          StringId category,
-                                          StringId name,
-                                          SetArgsCallback args_callback) {
+void SliceTracker::ScopedGpu(const tables::GpuSliceTable::Row& row,
+                             SetArgsCallback args_callback) {
+  PERFETTO_DCHECK(row.dur >= 0);
+
+  StartSlice(row.ts, TrackId(row.track_id), args_callback, [this, &row]() {
+    return context_->storage->mutable_gpu_slice_table()->Insert(row).id;
+  });
+}
+
+SliceId SliceTracker::ScopedFrameEvent(
+    const tables::GraphicsFrameSliceTable::Row& row,
+    SetArgsCallback args_callback) {
+  PERFETTO_DCHECK(row.dur >= 0);
+
+  SliceId id;
+  StartSlice(row.ts, TrackId(row.track_id), args_callback, [this, &row, &id]() {
+    id =
+        context_->storage->mutable_graphics_frame_slice_table()->Insert(row).id;
+    return id;
+  });
+  return id;
+}
+
+base::Optional<uint32_t> SliceTracker::End(int64_t timestamp,
+                                           TrackId track_id,
+                                           StringId category,
+                                           StringId name,
+                                           SetArgsCallback args_callback) {
   auto finder = [this, category, name](const SlicesStack& stack) {
     return MatchingIncompleteSliceIndex(stack, name, category);
   };
-  return CompleteSlice(timestamp, track_id, args_callback, finder);
+  auto slice_id = CompleteSlice(timestamp, track_id, args_callback, finder);
+  if (!slice_id)
+    return base::nullopt;
+  return context_->storage->slice_table().id().IndexOf(*slice_id);
 }
 
 base::Optional<uint32_t> SliceTracker::AddArgs(TrackId track_id,
                                                StringId category,
                                                StringId name,
                                                SetArgsCallback args_callback) {
-  auto it = stacks_.find(track_id);
-  if (it == stacks_.end())
-    return base::nullopt;
-
-  auto& stack = it->second.slice_stack;
+  auto& stack = stacks_[track_id];
   if (stack.empty())
     return base::nullopt;
 
@@ -111,16 +137,33 @@
       MatchingIncompleteSliceIndex(stack, name, category);
   if (!stack_idx.has_value())
     return base::nullopt;
-  uint32_t slice_idx = stack[*stack_idx].row;
+  uint32_t slice_idx = stack[*stack_idx].first;
   PERFETTO_DCHECK(slices->dur()[slice_idx] == kPendingDuration);
   // Add args to current pending slice.
-  ArgsTracker* tracker = &stack[*stack_idx].args_tracker;
+  ArgsTracker* tracker = &stack[*stack_idx].second;
   auto bound_inserter = tracker->AddArgsTo(slices->id()[slice_idx]);
   args_callback(&bound_inserter);
   return slice_idx;
 }
 
-base::Optional<SliceId> SliceTracker::StartSlice(
+base::Optional<SliceId> SliceTracker::EndGpu(int64_t ts,
+                                             TrackId t_id,
+                                             SetArgsCallback args_callback) {
+  return CompleteSlice(ts, t_id, args_callback, [](const SlicesStack& stack) {
+    return static_cast<uint32_t>(stack.size() - 1);
+  });
+}
+
+base::Optional<SliceId> SliceTracker::EndFrameEvent(
+    int64_t ts,
+    TrackId t_id,
+    SetArgsCallback args_callback) {
+  return CompleteSlice(ts, t_id, args_callback, [](const SlicesStack& stack) {
+    return static_cast<uint32_t>(stack.size() - 1);
+  });
+}
+
+base::Optional<uint32_t> SliceTracker::StartSlice(
     int64_t timestamp,
     TrackId track_id,
     SetArgsCallback args_callback,
@@ -132,24 +175,9 @@
   }
   prev_timestamp_ = timestamp;
 
-  auto* track_info = &stacks_[track_id];
-  auto* stack = &track_info->slice_stack;
-
-  if (track_info->is_legacy_unnestable) {
-    PERFETTO_DCHECK(stack->size() <= 1);
-
-    track_info->legacy_unnestable_begin_count++;
-    track_info->legacy_unnestable_last_begin_ts = timestamp;
-
-    // If this is an unnestable track, don't start a new slice if one already
-    // exists.
-    if (!stack->empty()) {
-      return base::nullopt;
-    }
-  }
-
+  auto* stack = &stacks_[track_id];
   auto* slices = context_->storage->mutable_slice_table();
-  MaybeCloseStack(timestamp, stack, track_id);
+  MaybeCloseStack(timestamp, stack);
 
   const uint8_t depth = static_cast<uint8_t>(stack->size());
   if (depth >= std::numeric_limits<uint8_t>::max()) {
@@ -157,14 +185,14 @@
     return base::nullopt;
   }
   int64_t parent_stack_id =
-      depth == 0 ? 0 : slices->stack_id()[stack->back().row];
+      depth == 0 ? 0 : slices->stack_id()[stack->back().first];
   base::Optional<tables::SliceTable::Id> parent_id =
       depth == 0 ? base::nullopt
-                 : base::make_optional(slices->id()[stack->back().row]);
+                 : base::make_optional(slices->id()[stack->back().first]);
 
   SliceId id = inserter();
   uint32_t slice_idx = *slices->id().IndexOf(id);
-  StackPush(track_id, slice_idx);
+  stack->emplace_back(std::make_pair(slice_idx, ArgsTracker(context_)));
 
   // Post fill all the relevant columns. All the other columns should have
   // been filled by the inserter.
@@ -175,11 +203,11 @@
     slices->mutable_parent_id()->Set(slice_idx, *parent_id);
 
   if (args_callback) {
-    ArgsTracker* tracker = &stack->back().args_tracker;
+    ArgsTracker* tracker = &stack->back().second;
     auto bound_inserter = tracker->AddArgsTo(id);
     args_callback(&bound_inserter);
   }
-  return id;
+  return slice_idx;
 }
 
 base::Optional<SliceId> SliceTracker::CompleteSlice(
@@ -194,13 +222,8 @@
   }
   prev_timestamp_ = timestamp;
 
-  auto it = stacks_.find(track_id);
-  if (it == stacks_.end())
-    return base::nullopt;
-
-  TrackInfo& track_info = it->second;
-  SlicesStack& stack = track_info.slice_stack;
-  MaybeCloseStack(timestamp, &stack, track_id);
+  auto& stack = stacks_[track_id];
+  MaybeCloseStack(timestamp, &stack);
   if (stack.empty())
     return base::nullopt;
 
@@ -212,28 +235,16 @@
   if (!stack_idx)
     return base::nullopt;
 
-  const auto& slice_info = stack[stack_idx.value()];
-  uint32_t slice_idx = slice_info.row;
+  uint32_t slice_idx = stack[stack_idx.value()].first;
   PERFETTO_DCHECK(slices->dur()[slice_idx] == kPendingDuration);
   slices->mutable_dur()->Set(slice_idx, timestamp - slices->ts()[slice_idx]);
 
-  ArgsTracker* tracker = &stack[stack_idx.value()].args_tracker;
   if (args_callback) {
+    ArgsTracker* tracker = &stack[stack_idx.value()].second;
     auto bound_inserter = tracker->AddArgsTo(slices->id()[slice_idx]);
     args_callback(&bound_inserter);
   }
 
-  // Add the legacy unnestable args if they exist.
-  if (track_info.is_legacy_unnestable) {
-    auto bound_inserter = tracker->AddArgsTo(slices->id()[slice_idx]);
-    bound_inserter.AddArg(
-        legacy_unnestable_begin_count_string_id_,
-        Variadic::Integer(track_info.legacy_unnestable_begin_count));
-    bound_inserter.AddArg(
-        legacy_unnestable_last_begin_ts_string_id_,
-        Variadic::Integer(track_info.legacy_unnestable_last_begin_ts));
-  }
-
   // If this slice is the top slice on the stack, pop it off.
   if (*stack_idx == stack.size() - 1)
     stack.pop_back();
@@ -249,7 +260,7 @@
     StringId category) {
   auto* slices = context_->storage->mutable_slice_table();
   for (int i = static_cast<int>(stack.size()) - 1; i >= 0; i--) {
-    uint32_t slice_idx = stack[static_cast<size_t>(i)].row;
+    uint32_t slice_idx = stack[static_cast<size_t>(i)].first;
     if (slices->dur()[slice_idx] != kPendingDuration)
       continue;
     const StringId& other_category = slices->category()[slice_idx];
@@ -275,29 +286,11 @@
   stacks_.clear();
 }
 
-void SliceTracker::SetOnSliceBeginCallback(OnSliceBeginCallback callback) {
-  on_slice_begin_callback_ = callback;
-}
-
-base::Optional<SliceId> SliceTracker::GetTopmostSliceOnTrack(
-    TrackId track_id) const {
-  const auto iter = stacks_.find(track_id);
-  if (iter == stacks_.end())
-    return base::nullopt;
-  const auto& stack = iter->second.slice_stack;
-  if (stack.empty())
-    return base::nullopt;
-  uint32_t slice_idx = stack.back().row;
-  return context_->storage->slice_table().id()[slice_idx];
-}
-
-void SliceTracker::MaybeCloseStack(int64_t ts,
-                                   SlicesStack* stack,
-                                   TrackId track_id) {
+void SliceTracker::MaybeCloseStack(int64_t ts, SlicesStack* stack) {
   auto* slices = context_->storage->mutable_slice_table();
   bool incomplete_descendent = false;
   for (int i = static_cast<int>(stack->size()) - 1; i >= 0; i--) {
-    uint32_t slice_idx = (*stack)[static_cast<size_t>(i)].row;
+    uint32_t slice_idx = (*stack)[static_cast<size_t>(i)].first;
 
     int64_t start_ts = slices->ts()[slice_idx];
     int64_t dur = slices->dur()[slice_idx];
@@ -330,21 +323,21 @@
       // of them to have the end ts of the current slice and pop them
       // all off.
       for (int j = static_cast<int>(stack->size()) - 1; j > i; --j) {
-        uint32_t child_idx = (*stack)[static_cast<size_t>(j)].row;
+        uint32_t child_idx = (*stack)[static_cast<size_t>(j)].first;
         PERFETTO_DCHECK(slices->dur()[child_idx] == kPendingDuration);
         slices->mutable_dur()->Set(child_idx, end_ts - slices->ts()[child_idx]);
-        StackPop(track_id);
+        stack->pop_back();
       }
 
       // Also pop the current row itself and reset the incomplete flag.
-      StackPop(track_id);
+      stack->pop_back();
       incomplete_descendent = false;
 
       continue;
     }
 
     if (end_ts <= ts) {
-      StackPop(track_id);
+      stack->pop_back();
     }
   }
 }
@@ -356,9 +349,9 @@
 
   base::Hash hash;
   for (size_t i = 0; i < stack.size(); i++) {
-    uint32_t slice_idx = stack[i].row;
-    hash.Update(slices.category()[slice_idx].raw_id());
-    hash.Update(slices.name()[slice_idx].raw_id());
+    uint32_t slice_idx = stack[i].first;
+    hash.Update(slices.category()[slice_idx]);
+    hash.Update(slices.name()[slice_idx]);
   }
 
   // For clients which don't have an integer type (i.e. Javascript), returning
@@ -370,19 +363,5 @@
   return static_cast<int64_t>(hash.digest() & kSafeBitmask);
 }
 
-void SliceTracker::StackPop(TrackId track_id) {
-  stacks_[track_id].slice_stack.pop_back();
-}
-
-void SliceTracker::StackPush(TrackId track_id, uint32_t slice_idx) {
-  stacks_[track_id].slice_stack.push_back(
-      SliceInfo{slice_idx, ArgsTracker(context_)});
-
-  const auto& slices = context_->storage->slice_table();
-  if (on_slice_begin_callback_) {
-    on_slice_begin_callback_(track_id, slices.id()[slice_idx]);
-  }
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/common/slice_tracker.h b/src/trace_processor/importers/common/slice_tracker.h
index f574164..eac656e 100644
--- a/src/trace_processor/importers/common/slice_tracker.h
+++ b/src/trace_processor/importers/common/slice_tracker.h
@@ -31,41 +31,26 @@
 class SliceTracker {
  public:
   using SetArgsCallback = std::function<void(ArgsTracker::BoundInserter*)>;
-  using OnSliceBeginCallback = std::function<void(TrackId, SliceId)>;
 
   explicit SliceTracker(TraceProcessorContext*);
   virtual ~SliceTracker();
 
   // virtual for testing
-  virtual base::Optional<SliceId> Begin(
+  virtual base::Optional<uint32_t> Begin(
       int64_t timestamp,
       TrackId track_id,
       StringId category,
       StringId name,
       SetArgsCallback args_callback = SetArgsCallback());
 
-  // Unnestable slices are slices which do not have any concept of nesting so
-  // starting a new slice when a slice already exists leads to no new slice
-  // being added. The number of times a begin event is seen is tracked as well
-  // as the latest time we saw a begin event. For legacy Android use only. See
-  // the comment in SystraceParser::ParseSystracePoint for information on why
-  // this method exists.
-  void BeginLegacyUnnestable(tables::SliceTable::Row row,
-                             SetArgsCallback args_callback);
+  void BeginGpu(tables::GpuSliceTable::Row row,
+                SetArgsCallback args_callback = SetArgsCallback());
 
-  template <typename Table>
-  base::Optional<SliceId> BeginTyped(
-      Table* table,
-      typename Table::Row row,
-      SetArgsCallback args_callback = SetArgsCallback()) {
-    // Ensure that the duration is pending for this row.
-    row.dur = kPendingDuration;
-    return StartSlice(row.ts, row.track_id, args_callback,
-                      [table, &row]() { return table->Insert(row).id; });
-  }
+  void BeginFrameEvent(tables::GraphicsFrameSliceTable::Row row,
+                       SetArgsCallback args_callback = SetArgsCallback());
 
   // virtual for testing
-  virtual base::Optional<SliceId> Scoped(
+  virtual base::Optional<uint32_t> Scoped(
       int64_t timestamp,
       TrackId track_id,
       StringId category,
@@ -73,18 +58,14 @@
       int64_t duration,
       SetArgsCallback args_callback = SetArgsCallback());
 
-  template <typename Table>
-  base::Optional<SliceId> ScopedTyped(
-      Table* table,
-      const typename Table::Row& row,
-      SetArgsCallback args_callback = SetArgsCallback()) {
-    PERFETTO_DCHECK(row.dur >= 0);
-    return StartSlice(row.ts, row.track_id, args_callback,
-                      [table, &row]() { return table->Insert(row).id; });
-  }
+  void ScopedGpu(const tables::GpuSliceTable::Row& row,
+                 SetArgsCallback args_callback = SetArgsCallback());
+
+  SliceId ScopedFrameEvent(const tables::GraphicsFrameSliceTable::Row& row,
+                           SetArgsCallback args_callback = SetArgsCallback());
 
   // virtual for testing
-  virtual base::Optional<SliceId> End(
+  virtual base::Optional<uint32_t> End(
       int64_t timestamp,
       TrackId track_id,
       StringId opt_category = {},
@@ -99,38 +80,28 @@
                                    StringId name,
                                    SetArgsCallback args_callback);
 
+  // TODO(lalitm): eventually this method should become End and End should
+  // be renamed EndChrome.
+  base::Optional<SliceId> EndGpu(
+      int64_t ts,
+      TrackId track_id,
+      SetArgsCallback args_callback = SetArgsCallback());
+
+  base::Optional<SliceId> EndFrameEvent(
+      int64_t ts,
+      TrackId track_id,
+      SetArgsCallback args_callback = SetArgsCallback());
+
   void FlushPendingSlices();
 
-  void SetOnSliceBeginCallback(OnSliceBeginCallback callback);
-
-  base::Optional<SliceId> GetTopmostSliceOnTrack(TrackId track_id) const;
-
  private:
-  // Slices which have been opened but haven't been closed yet will be marked
-  // with this duration placeholder.
-  static constexpr int64_t kPendingDuration = -1;
+  using SlicesStack = std::vector<std::pair<uint32_t /* row */, ArgsTracker>>;
+  using StackMap = std::unordered_map<TrackId, SlicesStack>;
 
-  struct SliceInfo {
-    uint32_t row;
-    ArgsTracker args_tracker;
-  };
-  using SlicesStack = std::vector<SliceInfo>;
-
-  struct TrackInfo {
-    SlicesStack slice_stack;
-
-    // These field is only valid for legacy unnestable slices.
-    bool is_legacy_unnestable = false;
-    uint32_t legacy_unnestable_begin_count = 0;
-    int64_t legacy_unnestable_last_begin_ts = 0;
-  };
-  using StackMap = std::unordered_map<TrackId, TrackInfo>;
-
-  // virtual for testing.
-  virtual base::Optional<SliceId> StartSlice(int64_t timestamp,
-                                             TrackId track_id,
-                                             SetArgsCallback args_callback,
-                                             std::function<SliceId()> inserter);
+  base::Optional<uint32_t> StartSlice(int64_t timestamp,
+                                      TrackId track_id,
+                                      SetArgsCallback args_callback,
+                                      std::function<SliceId()> inserter);
 
   base::Optional<SliceId> CompleteSlice(
       int64_t timestamp,
@@ -138,27 +109,17 @@
       SetArgsCallback args_callback,
       std::function<base::Optional<uint32_t>(const SlicesStack&)> finder);
 
-  void MaybeCloseStack(int64_t end_ts, SlicesStack*, TrackId track_id);
+  void MaybeCloseStack(int64_t end_ts, SlicesStack*);
 
   base::Optional<uint32_t> MatchingIncompleteSliceIndex(
       const SlicesStack& stack,
       StringId name,
       StringId category);
-
   int64_t GetStackHash(const SlicesStack&);
 
-  void StackPop(TrackId track_id);
-  void StackPush(TrackId track_id, uint32_t slice_idx);
-  void FlowTrackerUpdate(TrackId track_id);
-
-  OnSliceBeginCallback on_slice_begin_callback_;
-
   // Timestamp of the previous event. Used to discard events arriving out
   // of order.
-  int64_t prev_timestamp_ = std::numeric_limits<int64_t>::min();
-
-  const StringId legacy_unnestable_begin_count_string_id_;
-  const StringId legacy_unnestable_last_begin_ts_string_id_;
+  int64_t prev_timestamp_ = 0;
 
   TraceProcessorContext* const context_;
   StackMap stacks_;
diff --git a/src/trace_processor/importers/common/slice_tracker_unittest.cc b/src/trace_processor/importers/common/slice_tracker_unittest.cc
index 23e2bcf..35b1f5b 100644
--- a/src/trace_processor/importers/common/slice_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/slice_tracker_unittest.cc
@@ -72,28 +72,6 @@
   EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
 }
 
-TEST(SliceTrackerTest, NegativeTimestamps) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  constexpr TrackId track{22u};
-  tracker.Begin(-1000 /*ts*/, track, kNullStringId /*cat*/,
-                StringId::Raw(1) /*name*/);
-  tracker.End(-501 /*ts*/, track, kNullStringId /*cat*/,
-              StringId::Raw(1) /*name*/);
-
-  const auto& slices = context.storage->slice_table();
-  EXPECT_EQ(slices.row_count(), 1u);
-  EXPECT_EQ(slices.ts()[0], -1000);
-  EXPECT_EQ(slices.dur()[0], 499);
-  EXPECT_EQ(slices.track_id()[0], track);
-  EXPECT_EQ(slices.category()[0].raw_id(), 0u);
-  EXPECT_EQ(slices.name()[0].raw_id(), 1u);
-  EXPECT_EQ(slices.depth()[0], 0u);
-  EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
-}
-
 TEST(SliceTrackerTest, OneSliceWithArgs) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
@@ -327,72 +305,6 @@
   EXPECT_EQ(context.storage->slice_table().depth()[3], 0u);
 }
 
-TEST(SliceTrackerTest, GetTopmostSliceOnTrack) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  TrackId track{1u};
-  TrackId track2{2u};
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track), base::nullopt);
-
-  tracker.Begin(100, track, StringId::Raw(11), StringId::Raw(11));
-  SliceId slice1 = context.storage->slice_table().id()[0];
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track).value(), slice1);
-
-  tracker.Begin(120, track, StringId::Raw(22), StringId::Raw(22));
-  SliceId slice2 = context.storage->slice_table().id()[1];
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track).value(), slice2);
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track2), base::nullopt);
-
-  tracker.End(140, track, StringId::Raw(22), StringId::Raw(22));
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track).value(), slice1);
-
-  tracker.End(330, track, StringId::Raw(11), StringId::Raw(11));
-
-  EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track), base::nullopt);
-}
-
-TEST(SliceTrackerTest, OnSliceBeginCallback) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  TrackId track1{1u};
-  TrackId track2{2u};
-
-  std::vector<TrackId> track_records;
-  std::vector<SliceId> slice_records;
-  tracker.SetOnSliceBeginCallback([&](TrackId track_id, SliceId slice_id) {
-    track_records.emplace_back(track_id);
-    slice_records.emplace_back(slice_id);
-  });
-
-  EXPECT_TRUE(track_records.empty());
-  EXPECT_TRUE(slice_records.empty());
-
-  tracker.Begin(100, track1, StringId::Raw(11), StringId::Raw(11));
-  SliceId slice1 = context.storage->slice_table().id()[0];
-  EXPECT_THAT(track_records, ElementsAre(TrackId{1u}));
-  EXPECT_THAT(slice_records, ElementsAre(slice1));
-
-  tracker.Begin(120, track2, StringId::Raw(22), StringId::Raw(22));
-  SliceId slice2 = context.storage->slice_table().id()[1];
-  EXPECT_THAT(track_records, ElementsAre(TrackId{1u}, TrackId{2u}));
-  EXPECT_THAT(slice_records, ElementsAre(slice1, slice2));
-
-  tracker.Begin(330, track1, StringId::Raw(33), StringId::Raw(33));
-  SliceId slice3 = context.storage->slice_table().id()[2];
-  EXPECT_THAT(track_records,
-              ElementsAre(TrackId{1u}, TrackId{2u}, TrackId{1u}));
-  EXPECT_THAT(slice_records, ElementsAre(slice1, slice2, slice3));
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/common/trace_blob_view.h b/src/trace_processor/importers/common/trace_blob_view.h
deleted file mode 100644
index a94a994..0000000
--- a/src/trace_processor/importers/common/trace_blob_view.h
+++ /dev/null
@@ -1,148 +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_COMMON_TRACE_BLOB_VIEW_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_BLOB_VIEW_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-#include <memory>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// This class is an equivalent of std::string_view for trace binary data.
-// The main difference is that this class has also shared ownership of a portion
-// of the raw trace.
-// The underlying buffer will be freed once all the TraceBlobViews that refer
-// to the same buffer have passed through the pipeline and been parsed.
-class TraceBlobView {
- public:
-  TraceBlobView(std::unique_ptr<uint8_t[]> buffer, size_t offset, size_t length)
-      : shbuf_(SharedBuf(std::move(buffer))),
-        offset_(static_cast<uint32_t>(offset)),
-        length_(static_cast<uint32_t>(length)) {
-    PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max());
-    PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max());
-  }
-
-  // Allow std::move().
-  TraceBlobView(TraceBlobView&&) noexcept = default;
-  TraceBlobView& operator=(TraceBlobView&&) = default;
-
-  // Disable implicit copy.
-  TraceBlobView(const TraceBlobView&) = delete;
-  TraceBlobView& operator=(const TraceBlobView&) = delete;
-
-  TraceBlobView slice(size_t offset, size_t length) const {
-    PERFETTO_DCHECK(offset + length <= offset_ + length_);
-    return TraceBlobView(shbuf_, offset, length);
-  }
-
-  bool operator==(const TraceBlobView& rhs) const {
-    return (shbuf_ == rhs.shbuf_) && (offset_ == rhs.offset_) &&
-           (length_ == rhs.length_);
-  }
-  bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); }
-
-  inline const uint8_t* data() const { return start() + offset_; }
-
-  size_t offset_of(const uint8_t* data) const {
-    // When a field is size 0, data can be equal to start() + offset_ + length_.
-    PERFETTO_DCHECK(data >= start() && data <= (start() + offset_ + length_));
-    return static_cast<size_t>(data - start());
-  }
-
-  size_t length() const { return length_; }
-  size_t offset() const { return offset_; }
-
- private:
-  // An equivalent to std::shared_ptr<uint8_t>, with the differnce that:
-  // - Supports array types, available for shared_ptr only in C++17.
-  // - Is not thread safe, which is not needed for our purposes.
-  class SharedBuf {
-   public:
-    explicit SharedBuf(std::unique_ptr<uint8_t[]> mem) {
-      rcbuf_ = new RefCountedBuf(std::move(mem));
-    }
-
-    SharedBuf(const SharedBuf& copy) : rcbuf_(copy.rcbuf_) {
-      PERFETTO_DCHECK(rcbuf_->refcount > 0);
-      rcbuf_->refcount++;
-    }
-
-    ~SharedBuf() {
-      if (!rcbuf_)
-        return;
-      PERFETTO_DCHECK(rcbuf_->refcount > 0);
-      if (--rcbuf_->refcount == 0) {
-        RefCountedBuf* rcbuf = rcbuf_;
-        rcbuf_ = nullptr;
-        delete rcbuf;
-      }
-    }
-
-    SharedBuf(SharedBuf&& other) noexcept {
-      rcbuf_ = other.rcbuf_;
-      other.rcbuf_ = nullptr;
-    }
-
-    SharedBuf& operator=(SharedBuf&& other) {
-      if (this != &other) {
-        // A bit of a ugly but pragmatic pattern to implement move assignment.
-        // First invoke the distructor and then invoke the move constructor
-        // inline via placement-new.
-        this->~SharedBuf();
-        new (this) SharedBuf(std::move(other));
-      }
-      return *this;
-    }
-
-    bool operator==(const SharedBuf& x) const { return x.rcbuf_ == rcbuf_; }
-    bool operator!=(const SharedBuf& x) const { return !(x == *this); }
-    const uint8_t* data() const { return rcbuf_->mem.get(); }
-
-   private:
-    struct RefCountedBuf {
-      explicit RefCountedBuf(std::unique_ptr<uint8_t[]> buf)
-          : refcount(1), mem(std::move(buf)) {}
-      int refcount;
-      std::unique_ptr<uint8_t[]> mem;
-    };
-
-    RefCountedBuf* rcbuf_ = nullptr;
-  };
-
-  inline const uint8_t* start() const { return shbuf_.data(); }
-
-  TraceBlobView(SharedBuf b, size_t o, size_t l)
-      : shbuf_(b),
-        offset_(static_cast<uint32_t>(o)),
-        length_(static_cast<uint32_t>(l)) {}
-
-  SharedBuf shbuf_;
-  uint32_t offset_;
-  uint32_t length_;  // Measured from |offset_|, not from |data()|.
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_BLOB_VIEW_H_
diff --git a/src/trace_processor/importers/common/trace_parser.h b/src/trace_processor/importers/common/trace_parser.h
deleted file mode 100644
index 278a9d7..0000000
--- a/src/trace_processor/importers/common/trace_parser.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_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_PARSER_H_
-
-#include <stdint.h>
-
-namespace perfetto {
-namespace trace_processor {
-
-struct TimestampedTracePiece;
-
-class TraceParser {
- public:
-  virtual ~TraceParser();
-
-  virtual void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) = 0;
-  virtual void ParseFtracePacket(uint32_t cpu,
-                                 int64_t timestamp,
-                                 TimestampedTracePiece) = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_PARSER_H_
diff --git a/src/trace_processor/importers/common/track_tracker.cc b/src/trace_processor/importers/common/track_tracker.cc
index 73aef4e..788296d 100644
--- a/src/trace_processor/importers/common/track_tracker.cc
+++ b/src/trace_processor/importers/common/track_tracker.cc
@@ -22,16 +22,23 @@
 namespace perfetto {
 namespace trace_processor {
 
+// static
+constexpr uint64_t 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")),
+      parent_track_id_key_(context->storage->InternString("parent_track_id")),
       category_key_(context->storage->InternString("category")),
       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) {
@@ -59,21 +66,18 @@
 }
 
 TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
-                                              uint32_t upid,
                                               int64_t correlation_id) {
-  return InternLegacyChromeAsyncTrack(name, upid, correlation_id, false,
-                                      StringId());
-}
-
-TrackId TrackTracker::InternCpuTrack(StringId name, uint32_t cpu) {
-  auto it = cpu_tracks_.find(std::make_pair(name, cpu));
-  if (it != cpu_tracks_.end()) {
+  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).id;
-  cpu_tracks_[std::make_pair(name, cpu)] = id;
+  fuchsia_async_tracks_[correlation_id] = id;
+
+  context_->args_tracker->AddArgsTo(id)
+      .AddArg(source_key_, Variadic::String(fuchsia_source_))
+      .AddArg(source_id_key_, Variadic::Integer(correlation_id));
 
   return id;
 }
@@ -103,17 +107,8 @@
   tuple.source_scope = source_scope;
 
   auto it = chrome_tracks_.find(tuple);
-  if (it != chrome_tracks_.end()) {
-    if (name != kNullStringId) {
-      // The track may have been created for an end event without name. In that
-      // case, update it with this event's name.
-      auto* tracks = context_->storage->mutable_track_table();
-      uint32_t track_row = *tracks->id().IndexOf(it->second);
-      if (tracks->name()[track_row] == kNullStringId)
-        tracks->mutable_name()->Set(track_row, name);
-    }
+  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.
@@ -133,26 +128,38 @@
   return id;
 }
 
-TrackId TrackTracker::CreateGlobalAsyncTrack(StringId name) {
-  tables::TrackTable::Row row(name);
-  auto id = context_->storage->mutable_track_table()->Insert(row).id;
-  return id;
-}
+TrackId TrackTracker::InternAndroidAsyncTrack(StringId name,
+                                              UniquePid upid,
+                                              int64_t cookie) {
+  AndroidAsyncTrackTuple tuple{upid, cookie, name};
 
-TrackId TrackTracker::CreateAndroidAsyncTrack(StringId name, UniquePid upid) {
+  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).id;
-  context_->args_tracker->AddArgsTo(id).AddArg(
-      source_key_, Variadic::String(android_source_));
+  android_async_tracks_[tuple] = id;
+
+  context_->args_tracker->AddArgsTo(id)
+      .AddArg(source_key_, Variadic::String(android_source_))
+      .AddArg(source_id_key_, Variadic::Integer(cookie));
+
   return id;
 }
 
-TrackId TrackTracker::CreateFrameTimelineAsyncTrack(StringId name,
-                                                    UniquePid upid) {
+TrackId TrackTracker::InternPerfStackTrack(UniquePid upid) {
+  auto it = perf_stack_tracks_.find(upid);
+  if (it != perf_stack_tracks_.end())
+    return it->second;
+
+  StringId name = context_->storage->InternString("Stack samples");
   tables::ProcessTrackTable::Row row(name);
   row.upid = upid;
-  return context_->storage->mutable_process_track_table()->Insert(row).id;
+  auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
+  perf_stack_tracks_[upid] = id;
+  return id;
 }
 
 TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
@@ -182,6 +189,359 @@
   return *chrome_global_instant_track_id_;
 }
 
+void TrackTracker::ReserveDescriptorProcessTrack(uint64_t uuid,
+                                                 StringId name,
+                                                 uint32_t pid,
+                                                 int64_t timestamp) {
+  DescriptorTrackReservation reservation;
+  reservation.min_timestamp = timestamp;
+  reservation.pid = pid;
+  reservation.name = name;
+
+  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+  bool inserted;
+  std::tie(it, inserted) =
+      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+  if (inserted)
+    return;
+
+  if (!it->second.IsForSameTrack(reservation)) {
+    // Process tracks should not be reassigned to a different pid later (neither
+    // should the type of the track change).
+    PERFETTO_DLOG("New track reservation for process track with uuid %" PRIu64
+                  " doesn't match earlier one",
+                  uuid);
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return;
+  }
+
+  it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
+}
+
+void TrackTracker::ReserveDescriptorThreadTrack(uint64_t uuid,
+                                                uint64_t parent_uuid,
+                                                StringId name,
+                                                uint32_t pid,
+                                                uint32_t tid,
+                                                int64_t timestamp) {
+  DescriptorTrackReservation reservation;
+  reservation.min_timestamp = timestamp;
+  reservation.parent_uuid = parent_uuid;
+  reservation.pid = pid;
+  reservation.tid = tid;
+  reservation.name = name;
+
+  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+  bool inserted;
+  std::tie(it, inserted) =
+      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+  if (inserted)
+    return;
+
+  if (!it->second.IsForSameTrack(reservation)) {
+    // Thread tracks should not be reassigned to a different pid/tid later
+    // (neither should the type of the track change).
+    PERFETTO_DLOG("New track reservation for thread track with uuid %" PRIu64
+                  " doesn't match earlier one",
+                  uuid);
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return;
+  }
+
+  it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
+}
+
+void TrackTracker::ReserveDescriptorCounterTrack(uint64_t uuid,
+                                                 uint64_t parent_uuid,
+                                                 StringId name,
+                                                 StringId category,
+                                                 int64_t unit_multiplier,
+                                                 bool is_incremental,
+                                                 uint32_t packet_sequence_id) {
+  DescriptorTrackReservation reservation;
+  reservation.parent_uuid = parent_uuid;
+  reservation.is_counter = true;
+  reservation.name = name;
+  reservation.category = category;
+  reservation.unit_multiplier = unit_multiplier;
+  reservation.is_incremental = is_incremental;
+  // Incrementally encoded counters are only valid on a single sequence.
+  if (is_incremental)
+    reservation.packet_sequence_id = packet_sequence_id;
+
+  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+  bool inserted;
+  std::tie(it, inserted) =
+      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+  if (inserted || it->second.IsForSameTrack(reservation))
+    return;
+
+  // Counter tracks should not be reassigned to a different parent track later
+  // (neither should the type of the track change).
+  PERFETTO_DLOG("New track reservation for counter track with uuid %" PRIu64
+                " doesn't match earlier one",
+                uuid);
+  context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+}
+
+void TrackTracker::ReserveDescriptorChildTrack(uint64_t uuid,
+                                               uint64_t parent_uuid,
+                                               StringId name) {
+  DescriptorTrackReservation reservation;
+  reservation.parent_uuid = parent_uuid;
+  reservation.name = name;
+
+  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+  bool inserted;
+  std::tie(it, inserted) =
+      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+  if (inserted || it->second.IsForSameTrack(reservation))
+    return;
+
+  // Child tracks should not be reassigned to a different parent track later
+  // (neither should the type of the track change).
+  PERFETTO_DLOG("New track reservation for child track with uuid %" PRIu64
+                " doesn't match earlier one",
+                uuid);
+  context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+}
+
+base::Optional<TrackId> TrackTracker::GetDescriptorTrack(uint64_t uuid) {
+  return GetDescriptorTrackImpl(uuid);
+}
+
+base::Optional<TrackId> TrackTracker::GetDescriptorTrackImpl(
+    uint64_t uuid,
+    std::vector<uint64_t>* descendent_uuids) {
+  auto it = resolved_descriptor_tracks_.find(uuid);
+  if (it == resolved_descriptor_tracks_.end()) {
+    auto reservation_it = reserved_descriptor_tracks_.find(uuid);
+    if (reservation_it == reserved_descriptor_tracks_.end())
+      return base::nullopt;
+    TrackId track_id =
+        ResolveDescriptorTrack(uuid, reservation_it->second, descendent_uuids);
+    resolved_descriptor_tracks_[uuid] = track_id;
+    return track_id;
+  }
+  return it->second;
+}
+
+TrackId TrackTracker::ResolveDescriptorTrack(
+    uint64_t uuid,
+    const DescriptorTrackReservation& reservation,
+    std::vector<uint64_t>* descendent_uuids) {
+  auto set_track_name_and_return = [this, &reservation](TrackId track_id) {
+    // Initialize the track name here, so that, if a name was given in the
+    // reservation, it is set immediately after resolution takes place.
+    if (reservation.name != kNullStringId) {
+      auto* tracks = context_->storage->mutable_track_table();
+      tracks->mutable_name()->Set(*tracks->id().IndexOf(track_id),
+                                  reservation.name);
+    }
+    return track_id;
+  };
+
+  static constexpr size_t kMaxAncestors = 10;
+
+  // Try to resolve any parent tracks recursively, too.
+  base::Optional<TrackId> parent_track_id;
+  if (reservation.parent_uuid) {
+    // Input data may contain loops or extremely long ancestor track chains. To
+    // avoid stack overflow in these situations, we keep track of the ancestors
+    // seen in the recursion.
+    std::unique_ptr<std::vector<uint64_t>> owned_descendent_uuids;
+    if (!descendent_uuids) {
+      owned_descendent_uuids.reset(new std::vector<uint64_t>());
+      descendent_uuids = owned_descendent_uuids.get();
+    }
+    descendent_uuids->push_back(uuid);
+
+    if (descendent_uuids->size() > kMaxAncestors) {
+      PERFETTO_ELOG(
+          "Too many ancestors in parent_track_uuid hierarchy at track %" PRIu64
+          " with parent %" PRIu64,
+          uuid, reservation.parent_uuid);
+    } else if (std::find(descendent_uuids->begin(), descendent_uuids->end(),
+                         reservation.parent_uuid) != descendent_uuids->end()) {
+      PERFETTO_ELOG(
+          "Loop detected in parent_track_uuid hierarchy at track %" PRIu64
+          " with parent %" PRIu64,
+          uuid, reservation.parent_uuid);
+    } else {
+      parent_track_id =
+          GetDescriptorTrackImpl(reservation.parent_uuid, descendent_uuids);
+      if (!parent_track_id) {
+        PERFETTO_ELOG("Unknown parent track %" PRIu64 " for track %" PRIu64,
+                      reservation.parent_uuid, uuid);
+      }
+    }
+
+    descendent_uuids->pop_back();
+    if (owned_descendent_uuids)
+      descendent_uuids = nullptr;
+  }
+
+  if (reservation.tid) {
+    UniqueTid utid = context_->process_tracker->UpdateThread(*reservation.tid,
+                                                             *reservation.pid);
+    auto it_and_inserted =
+        descriptor_uuids_by_utid_.insert(std::make_pair<>(utid, uuid));
+    if (!it_and_inserted.second) {
+      // We already saw a another track with a different uuid for this thread.
+      // Since there should only be one descriptor track for each thread, we
+      // assume that its tid was reused. So, start a new thread.
+      uint64_t old_uuid = it_and_inserted.first->second;
+      PERFETTO_DCHECK(old_uuid != uuid);  // Every track is only resolved once.
+
+      PERFETTO_DLOG("Detected tid reuse (pid: %" PRIu32 " tid: %" PRIu32
+                    ") from track descriptors (old uuid: %" PRIu64
+                    " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
+                    *reservation.pid, *reservation.tid, old_uuid, uuid,
+                    reservation.min_timestamp);
+
+      utid = context_->process_tracker->StartNewThread(
+          base::nullopt, *reservation.tid, kNullStringId);
+
+      // Associate the new thread with its process.
+      PERFETTO_CHECK(context_->process_tracker->UpdateThread(
+                         *reservation.tid, *reservation.pid) == utid);
+
+      descriptor_uuids_by_utid_[utid] = uuid;
+    }
+    return set_track_name_and_return(InternThreadTrack(utid));
+  }
+
+  if (reservation.pid) {
+    UniquePid upid =
+        context_->process_tracker->GetOrCreateProcess(*reservation.pid);
+    auto it_and_inserted =
+        descriptor_uuids_by_upid_.insert(std::make_pair<>(upid, uuid));
+    if (!it_and_inserted.second) {
+      // We already saw a another track with a different uuid for this process.
+      // Since there should only be one descriptor track for each process, we
+      // assume that its pid was reused. So, start a new process.
+      uint64_t old_uuid = it_and_inserted.first->second;
+      PERFETTO_DCHECK(old_uuid != uuid);  // Every track is only resolved once.
+
+      PERFETTO_DLOG("Detected pid reuse (pid: %" PRIu32
+                    ") from track descriptors (old uuid: %" PRIu64
+                    " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
+                    *reservation.pid, old_uuid, uuid,
+                    reservation.min_timestamp);
+
+      upid = context_->process_tracker->StartNewProcess(
+          base::nullopt, base::nullopt, *reservation.pid, kNullStringId);
+
+      descriptor_uuids_by_upid_[upid] = uuid;
+    }
+    return set_track_name_and_return(InternProcessTrack(upid));
+  }
+
+  base::Optional<TrackId> track_id;
+  if (parent_track_id) {
+    // If parent is a thread track, create another thread-associated track.
+    auto* thread_tracks = context_->storage->mutable_thread_track_table();
+    base::Optional<uint32_t> thread_track_index =
+        thread_tracks->id().IndexOf(*parent_track_id);
+    if (thread_track_index) {
+      if (reservation.is_counter) {
+        // Thread counter track.
+        auto* thread_counter_tracks =
+            context_->storage->mutable_thread_counter_track_table();
+        tables::ThreadCounterTrackTable::Row row;
+        row.utid = thread_tracks->utid()[*thread_track_index];
+        track_id = thread_counter_tracks->Insert(row).id;
+      } else {
+        // Thread slice track.
+        tables::ThreadTrackTable::Row row;
+        row.utid = thread_tracks->utid()[*thread_track_index];
+        track_id = thread_tracks->Insert(row).id;
+      }
+    } else {
+      // If parent is a process track, create another process-associated track.
+      auto* process_tracks = context_->storage->mutable_process_track_table();
+      base::Optional<uint32_t> process_track_index =
+          process_tracks->id().IndexOf(*parent_track_id);
+      if (process_track_index) {
+        if (reservation.is_counter) {
+          // Process counter track.
+          auto* thread_counter_tracks =
+              context_->storage->mutable_process_counter_track_table();
+          tables::ProcessCounterTrackTable::Row row;
+          row.upid = process_tracks->upid()[*process_track_index];
+          track_id = thread_counter_tracks->Insert(row).id;
+        } else {
+          // Process slice track.
+          tables::ProcessTrackTable::Row row;
+          row.upid = process_tracks->upid()[*process_track_index];
+          track_id = process_tracks->Insert(row).id;
+        }
+      }
+    }
+  }
+
+  // Otherwise create a global track.
+  if (!track_id) {
+    if (reservation.is_counter) {
+      // Global counter track.
+      tables::CounterTrackTable::Row row;
+      track_id =
+          context_->storage->mutable_counter_track_table()->Insert(row).id;
+    } else {
+      // Global slice track.
+      tables::TrackTable::Row row;
+      track_id = context_->storage->mutable_track_table()->Insert(row).id;
+    }
+    // The global track with no uuid is the default global track (e.g. for
+    // global instant events). Any other global tracks are considered children
+    // of the default track.
+    if (!parent_track_id && uuid) {
+      // Detect loops where the default track has a parent that itself is a
+      // global track (and thus should be parent of the default track).
+      if (descendent_uuids &&
+          std::find(descendent_uuids->begin(), descendent_uuids->end(),
+                    kDefaultDescriptorTrackUuid) != descendent_uuids->end()) {
+        PERFETTO_ELOG(
+            "Loop detected in parent_track_uuid hierarchy at track %" PRIu64
+            " with parent %" PRIu64,
+            uuid, kDefaultDescriptorTrackUuid);
+      } else {
+        parent_track_id = GetOrCreateDefaultDescriptorTrack();
+      }
+    }
+  }
+
+  auto args = context_->args_tracker->AddArgsTo(*track_id);
+  args.AddArg(source_key_, Variadic::String(descriptor_source_))
+      .AddArg(source_id_key_, Variadic::Integer(static_cast<int64_t>(uuid)));
+  if (parent_track_id) {
+    args.AddArg(parent_track_id_key_,
+                Variadic::Integer(parent_track_id->value));
+  }
+  if (reservation.category != kNullStringId) {
+    args.AddArg(category_key_, Variadic::String(reservation.category));
+  }
+  return set_track_name_and_return(*track_id);
+}
+
+TrackId TrackTracker::GetOrCreateDefaultDescriptorTrack() {
+  // If the default track was already reserved (e.g. because a producer emitted
+  // a descriptor for it) or created, resolve and return it.
+  base::Optional<TrackId> track_id =
+      GetDescriptorTrack(kDefaultDescriptorTrackUuid);
+  if (track_id)
+    return *track_id;
+
+  // Otherwise reserve a new track and resolve it.
+  ReserveDescriptorChildTrack(kDefaultDescriptorTrackUuid, /*parent_uuid=*/0,
+                              default_descriptor_track_name_);
+  return *GetDescriptorTrack(kDefaultDescriptorTrackUuid);
+}
+
 TrackId TrackTracker::GetOrCreateTriggerTrack() {
   if (trigger_track_id_) {
     return *trigger_track_id_;
@@ -192,17 +552,13 @@
   return *trigger_track_id_;
 }
 
-TrackId TrackTracker::InternGlobalCounterTrack(StringId name,
-                                               StringId unit,
-                                               StringId description) {
+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);
-  row.unit = unit;
-  row.description = description;
   TrackId track =
       context_->storage->mutable_counter_track_table()->Insert(row).id;
   global_counter_tracks_by_name_[name] = track;
@@ -239,10 +595,7 @@
   return track;
 }
 
-TrackId TrackTracker::InternProcessCounterTrack(StringId name,
-                                                UniquePid upid,
-                                                StringId unit,
-                                                StringId description) {
+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;
@@ -250,8 +603,6 @@
 
   tables::ProcessCounterTrackTable::Row row(name);
   row.upid = upid;
-  row.unit = unit;
-  row.description = description;
 
   TrackId track =
       context_->storage->mutable_process_counter_track_table()->Insert(row).id;
@@ -312,15 +663,60 @@
   return context_->storage->mutable_gpu_counter_track_table()->Insert(row).id;
 }
 
-TrackId TrackTracker::CreatePerfCounterTrack(StringId name,
-                                             uint32_t perf_session_id,
-                                             uint32_t cpu,
-                                             bool is_timebase) {
-  tables::PerfCounterTrackTable::Row row(name);
-  row.perf_session_id = perf_session_id;
-  row.cpu = cpu;
-  row.is_timebase = is_timebase;
-  return context_->storage->mutable_perf_counter_track_table()->Insert(row).id;
+base::Optional<int64_t> TrackTracker::ConvertToAbsoluteCounterValue(
+    uint64_t counter_track_uuid,
+    uint32_t packet_sequence_id,
+    int64_t value) {
+  auto reservation_it = reserved_descriptor_tracks_.find(counter_track_uuid);
+  if (reservation_it == reserved_descriptor_tracks_.end()) {
+    PERFETTO_DLOG("Unknown counter track with uuid %" PRIu64,
+                  counter_track_uuid);
+    return base::nullopt;
+  }
+
+  DescriptorTrackReservation& reservation = reservation_it->second;
+  if (!reservation.is_counter) {
+    PERFETTO_DLOG("Track with uuid %" PRIu64 " is not a counter track",
+                  counter_track_uuid);
+    return base::nullopt;
+  }
+
+  if (reservation.unit_multiplier > 0)
+    value *= reservation.unit_multiplier;
+
+  if (reservation.is_incremental) {
+    if (reservation.packet_sequence_id != packet_sequence_id) {
+      PERFETTO_DLOG(
+          "Incremental counter track with uuid %" PRIu64
+          " was updated from the wrong packet sequence (expected: %" PRIu32
+          " got:%" PRIu32 ")",
+          counter_track_uuid, reservation.packet_sequence_id,
+          packet_sequence_id);
+      return base::nullopt;
+    }
+
+    reservation.latest_value += value;
+    value = reservation.latest_value;
+  }
+
+  return value;
+}
+
+void TrackTracker::OnIncrementalStateCleared(uint32_t packet_sequence_id) {
+  // TODO(eseckler): Improve on the runtime complexity of this. At O(hundreds)
+  // of packet sequences, incremental state clearing at O(trace second), and
+  // total number of tracks in O(thousands), a linear scan through all tracks
+  // here might not be fast enough.
+  for (auto& entry : reserved_descriptor_tracks_) {
+    DescriptorTrackReservation& reservation = entry.second;
+    // Only consider incremental counter tracks for current sequence.
+    if (!reservation.is_counter || !reservation.is_incremental ||
+        reservation.packet_sequence_id != packet_sequence_id) {
+      continue;
+    }
+    // Reset their value to 0, see CounterDescriptor's |is_incremental|.
+    reservation.latest_value = 0;
+  }
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/common/track_tracker.h b/src/trace_processor/importers/common/track_tracker.h
index 6ed95b9..c4bd3c7 100644
--- a/src/trace_processor/importers/common/track_tracker.h
+++ b/src/trace_processor/importers/common/track_tracker.h
@@ -35,12 +35,7 @@
   TrackId InternProcessTrack(UniquePid upid);
 
   // Interns a Fuchsia async track into the storage.
-  TrackId InternFuchsiaAsyncTrack(StringId name,
-                                  uint32_t upid,
-                                  int64_t correlation_id);
-
-  // Interns a global track keyed by CPU + name into the storage.
-  TrackId InternCpuTrack(StringId name, uint32_t cpu);
+  TrackId InternFuchsiaAsyncTrack(StringId name, int64_t correlation_id);
 
   // Interns a given GPU track into the storage.
   TrackId InternGpuTrack(const tables::GpuTrackTable::Row& row);
@@ -52,14 +47,13 @@
                                        bool source_id_is_process_scoped,
                                        StringId source_scope);
 
-  // Creates and inserts a global async track into the storage.
-  TrackId CreateGlobalAsyncTrack(StringId name);
+  // Interns a Android async track into the storage.
+  TrackId InternAndroidAsyncTrack(StringId name,
+                                  UniquePid upid,
+                                  int64_t cookie);
 
-  // Creates and inserts a Android async track into the storage.
-  TrackId CreateAndroidAsyncTrack(StringId name, UniquePid upid);
-
-  // Creates and inserts a FrameTimeline async track into the storage.
-  TrackId CreateFrameTimelineAsyncTrack(StringId name, UniquePid upid);
+  // Interns a track for perf event stack samples, with process-wide grouping.
+  TrackId InternPerfStackTrack(UniquePid upid);
 
   // Interns a track for legacy Chrome process-scoped instant events into the
   // storage.
@@ -68,14 +62,88 @@
   // Lazily creates the track for legacy Chrome global instant events.
   TrackId GetOrCreateLegacyChromeGlobalInstantTrack();
 
+  // Associate a TrackDescriptor track identified by the given |uuid| with a
+  // process's |pid|. This is called during tokenization. If a reservation for
+  // the same |uuid| already exists, verifies that the present reservation
+  // matches the new one.
+  //
+  // The track will be resolved to the process track (see InternProcessTrack())
+  // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
+  // time, |pid| will also be resolved to a |upid|.
+  void ReserveDescriptorProcessTrack(uint64_t uuid,
+                                     StringId name,
+                                     uint32_t pid,
+                                     int64_t timestamp);
+
+  // Associate a TrackDescriptor track identified by the given |uuid| with a
+  // thread's |pid| and |tid|. This is called during tokenization. If a
+  // reservation for the same |uuid| already exists, verifies that the present
+  // reservation matches the new one.
+  //
+  // The track will be resolved to the thread track (see InternThreadTrack())
+  // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
+  // time, |pid| will also be resolved to a |upid|.
+  void ReserveDescriptorThreadTrack(uint64_t uuid,
+                                    uint64_t parent_uuid,
+                                    StringId name,
+                                    uint32_t pid,
+                                    uint32_t tid,
+                                    int64_t timestamp);
+
+  // Associate a TrackDescriptor track identified by the given |uuid| with a
+  // parent track (usually a process- or thread-associated track). This is
+  // called during tokenization. If a reservation for the same |uuid| already
+  // exists, will attempt to update it.
+  //
+  // The track will be created upon the first call to GetDescriptorTrack() with
+  // the same |uuid|. If |parent_uuid| is 0, the track will become a global
+  // track. Otherwise, it will become a new track of the same type as its parent
+  // track.
+  void ReserveDescriptorChildTrack(uint64_t uuid,
+                                   uint64_t parent_uuid,
+                                   StringId name);
+
+  // Associate a counter-type TrackDescriptor track identified by the given
+  // |uuid| with a parent track (usually a process or thread track). This is
+  // called during tokenization. If a reservation for the same |uuid| already
+  // exists, will attempt to update it. The provided |category| will be stored
+  // into the track's args.
+  //
+  // If |is_incremental| is true, the counter will only be valid on the packet
+  // sequence identified by |packet_sequence_id|. |unit_multiplier| is an
+  // optional multiplication factor applied to counter values. Values for the
+  // counter will be translated during tokenization via
+  // ConvertToAbsoluteCounterValue().
+  //
+  // The track will be created upon the first call to GetDescriptorTrack() with
+  // the same |uuid|. If |parent_uuid| is 0, the track will become a global
+  // track. Otherwise, it will become a new counter track for the same
+  // process/thread as its parent track.
+  void ReserveDescriptorCounterTrack(uint64_t uuid,
+                                     uint64_t parent_uuid,
+                                     StringId name,
+                                     StringId category,
+                                     int64_t unit_multiplier,
+                                     bool is_incremental,
+                                     uint32_t packet_sequence_id);
+
+  // Returns the ID of the track for the TrackDescriptor with the given |uuid|.
+  // This is called during parsing. The first call to GetDescriptorTrack() for
+  // each |uuid| resolves and inserts the track (and its parent tracks,
+  // following the parent_uuid chain recursively) based on reservations made for
+  // the |uuid|. Returns nullopt if no track for a descriptor with this |uuid|
+  // has been reserved.
+  base::Optional<TrackId> GetDescriptorTrack(uint64_t uuid);
+
+  // Returns the ID of the implicit trace-global default TrackDescriptor track.
+  TrackId GetOrCreateDefaultDescriptorTrack();
+
   // Returns the ID of the implicit trace-global default track for triggers
   // received by the service.
   TrackId GetOrCreateTriggerTrack();
 
   // Interns a global counter track into the storage.
-  TrackId InternGlobalCounterTrack(StringId name,
-                                   StringId unit = kNullStringId,
-                                   StringId description = kNullStringId);
+  TrackId InternGlobalCounterTrack(StringId name);
 
   // Interns a counter track associated with a cpu into the storage.
   TrackId InternCpuCounterTrack(StringId name, uint32_t cpu);
@@ -84,10 +152,7 @@
   TrackId InternThreadCounterTrack(StringId name, UniqueTid utid);
 
   // Interns a counter track associated with a process into the storage.
-  TrackId InternProcessCounterTrack(StringId name,
-                                    UniquePid upid,
-                                    StringId unit = kNullStringId,
-                                    StringId description = kNullStringId);
+  TrackId InternProcessCounterTrack(StringId name, UniquePid upid);
 
   // Interns a counter track associated with an irq into the storage.
   TrackId InternIrqCounterTrack(StringId name, int32_t irq);
@@ -104,12 +169,20 @@
                                 StringId description = StringId::Null(),
                                 StringId unit = StringId::Null());
 
-  // Creaates a counter track for values within perf samples.
-  // The tracks themselves are managed by PerfSampleTracker.
-  TrackId CreatePerfCounterTrack(StringId name,
-                                 uint32_t perf_session_id,
-                                 uint32_t cpu,
-                                 bool is_timebase);
+  // Converts the given counter value to an absolute value in the unit of the
+  // counter, applying incremental delta encoding or unit multipliers as
+  // necessary. If the counter uses incremental encoding, |packet_sequence_id|
+  // must match the one in its track reservation. Returns base::nullopt if the
+  // counter track is unknown or an invalid |packet_sequence_id| was passed.
+  base::Optional<int64_t> ConvertToAbsoluteCounterValue(
+      uint64_t counter_track_uuid,
+      uint32_t packet_sequence_id,
+      int64_t value);
+
+  // Called by ProtoTraceTokenizer whenever incremental state is cleared on a
+  // packet sequence. Resets counter values for any incremental counters of
+  // the sequence identified by |packet_sequence_id|.
+  void OnIncrementalStateCleared(uint32_t packet_sequence_id);
 
  private:
   struct GpuTrackTuple {
@@ -133,16 +206,65 @@
              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);
+    }
+  };
+  struct DescriptorTrackReservation {
+    uint64_t parent_uuid = 0;
+    base::Optional<uint32_t> pid;
+    base::Optional<uint32_t> tid;
+    int64_t min_timestamp = 0;  // only set if |pid| and/or |tid| is set.
+    StringId name = kNullStringId;
+
+    // For counter tracks.
+    bool is_counter = false;
+    StringId category = kNullStringId;
+    int64_t unit_multiplier = 1;
+    bool is_incremental = false;
+    uint32_t packet_sequence_id = 0;
+    int64_t latest_value = 0;
+
+    // Whether |other| is a valid descriptor for this track reservation. A track
+    // should always remain nested underneath its original parent.
+    bool IsForSameTrack(const DescriptorTrackReservation& other) {
+      // Note that |min_timestamp|, |latest_value|, and |name| are ignored for
+      // this comparison.
+      return std::tie(parent_uuid, pid, tid, is_counter, category,
+                      unit_multiplier, is_incremental, packet_sequence_id) ==
+             std::tie(other.parent_uuid, pid, tid, is_counter, category,
+                      unit_multiplier, is_incremental, packet_sequence_id);
+    }
+  };
+
+  base::Optional<TrackId> GetDescriptorTrackImpl(
+      uint64_t uuid,
+      std::vector<uint64_t>* descendent_uuids = nullptr);
+  TrackId ResolveDescriptorTrack(uint64_t uuid,
+                                 const DescriptorTrackReservation&,
+                                 std::vector<uint64_t>* descendent_uuids);
+
+  static constexpr uint64_t kDefaultDescriptorTrackUuid = 0u;
 
   std::map<UniqueTid, TrackId> thread_tracks_;
   std::map<UniquePid, TrackId> process_tracks_;
   std::map<int64_t /* correlation_id */, TrackId> fuchsia_async_tracks_;
-
-  std::map<std::pair<StringId, uint32_t /* cpu */>, TrackId> cpu_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 */, DescriptorTrackReservation>
+      reserved_descriptor_tracks_;
+  std::map<uint64_t /* uuid */, TrackId> resolved_descriptor_tracks_;
+  std::map<UniquePid, TrackId> perf_stack_tracks_;
 
   std::map<StringId, TrackId> global_counter_tracks_by_name_;
   std::map<std::pair<StringId, uint32_t>, TrackId> cpu_counter_tracks_;
@@ -152,18 +274,26 @@
   std::map<std::pair<StringId, int32_t>, TrackId> softirq_counter_tracks_;
   std::map<std::pair<StringId, uint32_t>, TrackId> gpu_counter_tracks_;
 
-  base::Optional<TrackId> chrome_global_instant_track_id_;
+  // Stores the descriptor uuid used for the primary process/thread track
+  // for the given upid / utid. Used for pid/tid reuse detection.
+  std::map<UniquePid, uint64_t /*uuid*/> descriptor_uuids_by_upid_;
+  std::map<UniqueTid, uint64_t /*uuid*/> descriptor_uuids_by_utid_;
+
   base::Optional<TrackId> trigger_track_id_;
 
   const StringId source_key_ = kNullStringId;
   const StringId source_id_key_ = kNullStringId;
   const StringId source_id_is_process_scoped_key_ = kNullStringId;
   const StringId source_scope_key_ = kNullStringId;
+  const StringId parent_track_id_key_ = kNullStringId;
   const StringId category_key_ = kNullStringId;
 
   const StringId fuchsia_source_ = kNullStringId;
   const StringId chrome_source_ = kNullStringId;
   const StringId android_source_ = kNullStringId;
+  const StringId descriptor_source_ = kNullStringId;
+
+  const StringId default_descriptor_track_name_ = kNullStringId;
 
   TraceProcessorContext* const context_;
 };
diff --git a/src/trace_processor/importers/default_modules.cc b/src/trace_processor/importers/default_modules.cc
index 19345cf..2704478 100644
--- a/src/trace_processor/importers/default_modules.cc
+++ b/src/trace_processor/importers/default_modules.cc
@@ -16,9 +16,6 @@
 
 #include "src/trace_processor/importers/default_modules.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/proto/chrome_system_probes_module.h"
-#include "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h"
-#include "src/trace_processor/importers/proto/metadata_module.h"
 #include "src/trace_processor/importers/proto/profile_module.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/track_event_module.h"
@@ -33,11 +30,8 @@
   context->ftrace_module =
       static_cast<FtraceModule*>(context->modules.back().get());
 
-  context->modules.emplace_back(new MemoryTrackerSnapshotModule(context));
-  context->modules.emplace_back(new ChromeSystemProbesModule(context));
   context->modules.emplace_back(new TrackEventModule(context));
   context->modules.emplace_back(new ProfileModule(context));
-  context->modules.emplace_back(new MetadataModule(context));
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/binder_tracker.cc b/src/trace_processor/importers/ftrace/binder_tracker.cc
index d866c0a..b6ef00e 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker.cc
@@ -106,7 +106,7 @@
                                  base::StringView(flag_str))));
     inserter->AddArg(code_, Variadic::String(code));
     inserter->AddArg(calling_tid_, Variadic::UnsignedInteger(tid));
-    // TODO(hjd): The legacy UI included the calling pid in the args,
+    // TODO(taylori): The legacy UI included the calling pid in the args,
     // is this necessary? It's complicated in our case because process
     // association might not happen until after the binder transaction slices
     // have been parsed. We would need to backfill the arg.
@@ -125,7 +125,7 @@
     };
     context_->slice_tracker->AddArgs(track_id, binder_category_id_, reply_id_,
                                      dest_args_inserter);
-    context_->slice_tracker->End(ts, track_id, kNullStringId, kNullStringId,
+    context_->slice_tracker->End(ts, track_id, binder_category_id_, reply_id_,
                                  args_inserter);
     awaiting_rcv_for_reply_.insert(transaction_id);
     return;
@@ -138,8 +138,11 @@
                                    transaction_slice_id_, args_inserter);
     transaction_await_rcv[transaction_id] = track_id;
   } else {
+    // TODO(taylori): Change these to instant events with 0 duration
+    // once instants are displayed properly.
     context_->slice_tracker->Scoped(ts, track_id, binder_category_id_,
-                                    transaction_async_id_, 0, args_inserter);
+                                    transaction_async_id_, 10000,
+                                    args_inserter);
     awaiting_async_rcv_[transaction_id] = args_inserter;
   }
 }
@@ -152,7 +155,8 @@
   StringId thread_name = thread_table.name()[utid];
   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
   if (awaiting_rcv_for_reply_.count(transaction_id) > 0) {
-    context_->slice_tracker->End(ts, track_id);
+    context_->slice_tracker->End(ts, track_id, binder_category_id_,
+                                 transaction_slice_id_);
     awaiting_rcv_for_reply_.erase(transaction_id);
     return;
   }
@@ -168,7 +172,7 @@
       inserter->AddArg(dest_name_, Variadic::String(thread_name));
       if (reply_slice_id.has_value())
         inserter->AddArg(dest_slice_id_,
-                         Variadic::UnsignedInteger(reply_slice_id->value));
+                         Variadic::UnsignedInteger(reply_slice_id.value()));
     };
     // Add the dest args to the current transaction slice and get the slice id.
     auto transaction_slice_id = context_->slice_tracker->AddArgs(
@@ -191,7 +195,7 @@
   if (awaiting_async_rcv_.count(transaction_id) > 0) {
     auto args = awaiting_async_rcv_[transaction_id];
     context_->slice_tracker->Scoped(ts, track_id, binder_category_id_,
-                                    async_rcv_id_, 0, args);
+                                    async_rcv_id_, 10000, args);
     awaiting_async_rcv_.erase(transaction_id);
     return;
   }
@@ -199,11 +203,6 @@
 
 void BinderTracker::Lock(int64_t ts, uint32_t pid) {
   attempt_lock_[pid] = ts;
-
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->Begin(ts, track_id, binder_category_id_,
-                                 lock_waiting_id_);
 }
 
 void BinderTracker::Locked(int64_t ts, uint32_t pid) {
@@ -213,9 +212,9 @@
     return;
 
   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->End(ts, track_id);
-  context_->slice_tracker->Begin(ts, track_id, binder_category_id_,
-                                 lock_held_id_);
+  context_->slice_tracker->Scoped(attempt_lock_[pid], track_id,
+                                  binder_category_id_, lock_waiting_id_,
+                                  ts - attempt_lock_[pid]);
 
   lock_acquired_[pid] = ts;
   attempt_lock_.erase(pid);
@@ -228,8 +227,9 @@
     return;
 
   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->End(ts, track_id, binder_category_id_,
-                               lock_held_id_);
+  context_->slice_tracker->Scoped(lock_acquired_[pid], track_id,
+                                  binder_category_id_, lock_held_id_,
+                                  ts - lock_acquired_[pid]);
   lock_acquired_.erase(pid);
 }
 
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index cb0d50e..477c086 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -24,7 +24,7 @@
 namespace trace_processor {
 namespace {
 
-std::array<MessageDescriptor, 359> descriptors{{
+std::array<MessageDescriptor, 338> descriptors{{
     {nullptr, 0, {}},
     {nullptr, 0, {}},
     {nullptr, 0, {}},
@@ -3603,244 +3603,6 @@
             {"len", ProtoSchemaType::kUint64},
         },
     },
-    {
-        "scm_call_start",
-        3,
-        {
-            {},
-            {"arginfo", ProtoSchemaType::kUint32},
-            {"x0", ProtoSchemaType::kUint64},
-            {"x5", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "scm_call_end",
-        0,
-        {
-            {},
-        },
-    },
-    {
-        "gpu_mem_total",
-        3,
-        {
-            {},
-            {"gpu_id", ProtoSchemaType::kUint32},
-            {"pid", ProtoSchemaType::kUint32},
-            {"size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "thermal_temperature",
-        4,
-        {
-            {},
-            {"id", ProtoSchemaType::kInt32},
-            {"temp", ProtoSchemaType::kInt32},
-            {"temp_prev", ProtoSchemaType::kInt32},
-            {"thermal_zone", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cdev_update",
-        2,
-        {
-            {},
-            {"target", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cpuhp_exit",
-        4,
-        {
-            {},
-            {"cpu", ProtoSchemaType::kUint32},
-            {"idx", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-            {"state", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "cpuhp_multi_enter",
-        4,
-        {
-            {},
-            {"cpu", ProtoSchemaType::kUint32},
-            {"fun", ProtoSchemaType::kUint64},
-            {"idx", ProtoSchemaType::kInt32},
-            {"target", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "cpuhp_enter",
-        4,
-        {
-            {},
-            {"cpu", ProtoSchemaType::kUint32},
-            {"fun", ProtoSchemaType::kUint64},
-            {"idx", ProtoSchemaType::kInt32},
-            {"target", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "cpuhp_latency",
-        4,
-        {
-            {},
-            {"cpu", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-            {"state", ProtoSchemaType::kUint32},
-            {"time", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "fastrpc_dma_stat",
-        3,
-        {
-            {},
-            {"cid", ProtoSchemaType::kInt32},
-            {"len", ProtoSchemaType::kInt64},
-            {"total_allocated", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "dpu_tracing_mark_write",
-        6,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"trace_name", ProtoSchemaType::kString},
-            {"trace_begin", ProtoSchemaType::kUint32},
-            {"name", ProtoSchemaType::kString},
-            {"type", ProtoSchemaType::kUint32},
-            {"value", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "g2d_tracing_mark_write",
-        6,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {},
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"type", ProtoSchemaType::kUint32},
-            {"value", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mali_tracing_mark_write",
-        4,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"type", ProtoSchemaType::kUint32},
-            {"value", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "dma_heap_stat",
-        3,
-        {
-            {},
-            {"inode", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kInt64},
-            {"total_allocated", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "cpuhp_pause",
-        4,
-        {
-            {},
-            {"active_cpus", ProtoSchemaType::kUint32},
-            {"cpus", ProtoSchemaType::kUint32},
-            {"pause", ProtoSchemaType::kUint32},
-            {"time", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sched_pi_setprio",
-        4,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"newprio", ProtoSchemaType::kInt32},
-            {"oldprio", ProtoSchemaType::kInt32},
-            {"pid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sde_sde_evtlog",
-        3,
-        {
-            {},
-            {"evtlog_tag", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"tag_id", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sde_sde_perf_calc_crtc",
-        8,
-        {
-            {},
-            {"bw_ctl_ebi", ProtoSchemaType::kUint64},
-            {"bw_ctl_llcc", ProtoSchemaType::kUint64},
-            {"bw_ctl_mnoc", ProtoSchemaType::kUint64},
-            {"core_clk_rate", ProtoSchemaType::kUint32},
-            {"crtc", ProtoSchemaType::kUint32},
-            {"ib_ebi", ProtoSchemaType::kUint64},
-            {"ib_llcc", ProtoSchemaType::kUint64},
-            {"ib_mnoc", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "sde_sde_perf_crtc_update",
-        12,
-        {
-            {},
-            {"bw_ctl_ebi", ProtoSchemaType::kUint64},
-            {"bw_ctl_llcc", ProtoSchemaType::kUint64},
-            {"bw_ctl_mnoc", ProtoSchemaType::kUint64},
-            {"core_clk_rate", ProtoSchemaType::kUint32},
-            {"crtc", ProtoSchemaType::kUint32},
-            {"params", ProtoSchemaType::kInt32},
-            {"per_pipe_ib_ebi", ProtoSchemaType::kUint64},
-            {"per_pipe_ib_llcc", ProtoSchemaType::kUint64},
-            {"per_pipe_ib_mnoc", ProtoSchemaType::kUint64},
-            {"stop_req", ProtoSchemaType::kUint32},
-            {"update_bus", ProtoSchemaType::kUint32},
-            {"update_clk", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sde_sde_perf_set_qos_luts",
-        6,
-        {
-            {},
-            {"fl", ProtoSchemaType::kUint32},
-            {"fmt", ProtoSchemaType::kUint32},
-            {"lut", ProtoSchemaType::kUint64},
-            {"lut_usage", ProtoSchemaType::kUint32},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"rt", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sde_sde_perf_update_bus",
-        4,
-        {
-            {},
-            {"ab_quota", ProtoSchemaType::kUint64},
-            {"bus_id", ProtoSchemaType::kUint32},
-            {"client", ProtoSchemaType::kInt32},
-            {"ib_quota", ProtoSchemaType::kUint64},
-        },
-    },
 }};
 
 }  // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_module_impl.cc b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
index f86bdc5..63f926b 100644
--- a/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
@@ -16,10 +16,10 @@
 
 #include "src/trace_processor/importers/ftrace/ftrace_module_impl.h"
 #include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/ftrace/ftrace_parser.h"
 #include "src/trace_processor/importers/ftrace/ftrace_tokenizer.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"
 
@@ -38,13 +38,12 @@
     const protos::pbzero::TracePacket::Decoder& decoder,
     TraceBlobView* packet,
     int64_t /*packet_timestamp*/,
-    PacketSequenceState* seq_state,
+    PacketSequenceState* /*state*/,
     uint32_t field_id) {
   if (field_id == TracePacket::kFtraceEventsFieldNumber) {
     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),
-                                    seq_state);
+    tokenizer_.TokenizeFtraceBundle(packet->slice(fld_off, ftrace_field.size));
     return ModuleResult::Handled();
   }
   return ModuleResult::Ignored();
diff --git a/src/trace_processor/importers/ftrace/ftrace_module_impl.h b/src/trace_processor/importers/ftrace/ftrace_module_impl.h
index 2ba4d6b..66f5fe4 100644
--- a/src/trace_processor/importers/ftrace/ftrace_module_impl.h
+++ b/src/trace_processor/importers/ftrace/ftrace_module_impl.h
@@ -18,12 +18,12 @@
 #define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_MODULE_IMPL_H_
 
 #include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.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"
 
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 654b332..4282716 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -21,43 +21,28 @@
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
 #include "src/trace_processor/importers/syscalls/syscall_tracker.h"
 #include "src/trace_processor/importers/systrace/systrace_parser.h"
 #include "src/trace_processor/storage/stats.h"
 #include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/softirq_action.h"
 
-#include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
-#include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
-#include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
-#include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
-#include "protos/perfetto/trace/ftrace/fastrpc.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/g2d.pbzero.h"
 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
-#include "protos/perfetto/trace/ftrace/gpu_mem.pbzero.h"
 #include "protos/perfetto/trace/ftrace/ion.pbzero.h"
-#include "protos/perfetto/trace/ftrace/irq.pbzero.h"
 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
-#include "protos/perfetto/trace/ftrace/mali.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/scm.pbzero.h"
 #include "protos/perfetto/trace/ftrace/sde.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"
-#include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
-#include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -72,29 +57,6 @@
 const uint32_t kKthreaddPid = 2;
 const char kKthreaddName[] = "kthreadd";
 
-struct FtraceEventAndFieldId {
-  uint32_t event_id;
-  uint32_t field_id;
-};
-
-// Contains a list of all the proto fields in ftrace events which represent
-// kernel functions. This list is used to convert the iids in these fields to
-// proper kernel symbols.
-// TODO(lalitm): going through this array is O(n) on a hot-path (see
-// ParseTypedFtraceToRaw). Consider changing this if we end up adding a lot of
-// events here.
-constexpr auto kKernelFunctionFields = std::array<FtraceEventAndFieldId, 3>{
-    {FtraceEventAndFieldId{
-         protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
-         protos::pbzero::SchedBlockedReasonFtraceEvent::kCallerFieldNumber},
-     FtraceEventAndFieldId{
-         protos::pbzero::FtraceEvent::kWorkqueueExecuteStartFieldNumber,
-         protos::pbzero::WorkqueueExecuteStartFtraceEvent::
-             kFunctionFieldNumber},
-     FtraceEventAndFieldId{
-         protos::pbzero::FtraceEvent::kWorkqueueQueueWorkFieldNumber,
-         protos::pbzero::WorkqueueQueueWorkFtraceEvent::kFunctionFieldNumber}}};
-
 }  // namespace
 
 FtraceParser::FtraceParser(TraceProcessorContext* context)
@@ -107,11 +69,6 @@
       cpu_idle_name_id_(context->storage->InternString("cpuidle")),
       ion_total_id_(context->storage->InternString("mem.ion")),
       ion_change_id_(context->storage->InternString("mem.ion_change")),
-      ion_buffer_id_(context->storage->InternString("mem.ion_buffer")),
-      dma_heap_total_id_(context->storage->InternString("mem.dma_heap")),
-      dma_heap_change_id_(
-          context->storage->InternString("mem.dma_heap_change")),
-      dma_buffer_id_(context->storage->InternString("mem.dma_buffer")),
       ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
       ion_change_unknown_id_(
           context->storage->InternString("mem.ion_change.unknown")),
@@ -121,22 +78,7 @@
       lmk_id_(context->storage->InternString("mem.lmk")),
       comm_name_id_(context->storage->InternString("comm")),
       signal_name_id_(context_->storage->InternString("signal.sig")),
-      oom_kill_id_(context_->storage->InternString("mem.oom_kill")),
-      workqueue_id_(context_->storage->InternString("workqueue")),
-      irq_id_(context_->storage->InternString("irq")),
-      ret_arg_id_(context_->storage->InternString("ret")),
-      vec_arg_id_(context->storage->InternString("vec")),
-      gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
-      gpu_mem_total_unit_id_(context->storage->InternString(
-          std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
-      gpu_mem_total_global_desc_id_(context->storage->InternString(
-          "Total GPU memory used by the entire system")),
-      gpu_mem_total_proc_desc_id_(context->storage->InternString(
-          "Total GPU memory used by this process")),
-      sched_blocked_reason_id_(
-          context->storage->InternString("sched_blocked_reason")),
-      io_wait_id_(context->storage->InternString("io_wait")),
-      function_id_(context->storage->InternString("function")) {
+      oom_kill_id_(context_->storage->InternString("mem.oom_kill")) {
   // 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++) {
@@ -160,25 +102,6 @@
     ftrace_message_strings_.emplace_back(ftrace_strings);
   }
 
-  // Array initialization causes a spurious warning due to llvm bug.
-  // See https://bugs.llvm.org/show_bug.cgi?id=21629
-  fast_rpc_delta_names_[0] =
-      context->storage->InternString("mem.fastrpc_change[ASDP]");
-  fast_rpc_delta_names_[1] =
-      context->storage->InternString("mem.fastrpc_change[MDSP]");
-  fast_rpc_delta_names_[2] =
-      context->storage->InternString("mem.fastrpc_change[SDSP]");
-  fast_rpc_delta_names_[3] =
-      context->storage->InternString("mem.fastrpc_change[CDSP]");
-  fast_rpc_total_names_[0] =
-      context->storage->InternString("mem.fastrpc[ASDP]");
-  fast_rpc_total_names_[1] =
-      context->storage->InternString("mem.fastrpc[MDSP]");
-  fast_rpc_total_names_[2] =
-      context->storage->InternString("mem.fastrpc[SDSP]");
-  fast_rpc_total_names_[3] =
-      context->storage->InternString("mem.fastrpc[CDSP]");
-
   mm_event_counter_names_ = {
       {MmEventCounterNames(
            context->storage->InternString("mem.mm.min_flt.count"),
@@ -241,14 +164,7 @@
     // of wrapping. Ensure that we are not overflowing to avoid ubsan
     // complaining.
     double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
-    // NB: This comparison is correct only because of the >=, it would be
-    // incorrect with >. std::numeric_limits<int64_t>::max() converted to
-    // a double is the next value representable as a double that is *larger*
-    // than std::numeric_limits<int64_t>::max(). All values that are
-    // representable as doubles and < than that value are thus representable as
-    // int64_t.
-    if (oldest_event_ts >=
-        static_cast<double>(std::numeric_limits<int64_t>::max())) {
+    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 {
@@ -269,43 +185,8 @@
 PERFETTO_ALWAYS_INLINE
 util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
                                             const TimestampedTracePiece& ttp) {
-  int64_t ts = ttp.timestamp;
-
-  // On the first ftrace packet, check the metadata table for the
-  // ts of the event which is specified in the config. If it exists we can use
-  // it to filter out ftrace packets which happen earlier than it.
-  if (PERFETTO_UNLIKELY(!has_seen_first_ftrace_packet_)) {
-    DropFtraceDataBefore drop_before = context_->config.drop_ftrace_data_before;
-    switch (drop_before) {
-      case DropFtraceDataBefore::kNoDrop: {
-        drop_ftrace_data_before_ts_ = 0;
-        break;
-      }
-      case DropFtraceDataBefore::kAllDataSourcesStarted:
-      case DropFtraceDataBefore::kTracingStarted: {
-        metadata::KeyId event_key =
-            drop_before == DropFtraceDataBefore::kAllDataSourcesStarted
-                ? metadata::all_data_source_started_ns
-                : metadata::tracing_started_ns;
-        const auto& metadata = context_->storage->metadata_table();
-        base::Optional<uint32_t> opt_row =
-            metadata.name().IndexOf(metadata::kNames[event_key]);
-        if (opt_row) {
-          drop_ftrace_data_before_ts_ = *metadata.int_value()[*opt_row];
-        }
-        break;
-      }
-    }
-    has_seen_first_ftrace_packet_ = true;
-  }
-
-  if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
-    context_->storage->IncrementStats(
-        stats::ftrace_packet_before_tracing_start);
-    return util::OkStatus();
-  }
-
   using protos::pbzero::FtraceEvent;
+  int64_t ts = ttp.timestamp;
   SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
 
   // Handle the (optional) alternative encoding format for sched_switch.
@@ -327,9 +208,7 @@
   }
 
   PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kFtraceEvent);
-  const TraceBlobView& event = ttp.ftrace_event.event;
-  PacketSequenceStateGeneration* seq_state =
-      ttp.ftrace_event.sequence_state.get();
+  const TraceBlobView& event = ttp.ftrace_event;
   ProtoDecoder decoder(event.data(), event.length());
   uint64_t raw_pid = 0;
   if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
@@ -350,7 +229,7 @@
       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, seq_state);
+      ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
     }
 
     switch (fld.id()) {
@@ -406,10 +285,6 @@
         ParseIonStat(ts, pid, data);
         break;
       }
-      case FtraceEvent::kDmaHeapStatFieldNumber: {
-        ParseDmaHeapStat(ts, pid, data);
-        break;
-      }
       case FtraceEvent::kSignalGenerateFieldNumber: {
         ParseSignalGenerate(ts, data);
         break;
@@ -478,86 +353,6 @@
         ParseSdeTracingMarkWrite(ts, pid, data);
         break;
       }
-      case FtraceEvent::kClockSetRateFieldNumber: {
-        ParseClockSetRate(ts, data);
-        break;
-      }
-      case FtraceEvent::kClockEnableFieldNumber: {
-        ParseClockEnable(ts, data);
-        break;
-      }
-      case FtraceEvent::kClockDisableFieldNumber: {
-        ParseClockDisable(ts, data);
-        break;
-      }
-      case FtraceEvent::kScmCallStartFieldNumber: {
-        ParseScmCallStart(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kScmCallEndFieldNumber: {
-        ParseScmCallEnd(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kWorkqueueExecuteStartFieldNumber: {
-        ParseWorkqueueExecuteStart(ts, pid, data, seq_state);
-        break;
-      }
-      case FtraceEvent::kWorkqueueExecuteEndFieldNumber: {
-        ParseWorkqueueExecuteEnd(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kIrqHandlerEntryFieldNumber: {
-        ParseIrqHandlerEntry(cpu, ts, data);
-        break;
-      }
-      case FtraceEvent::kIrqHandlerExitFieldNumber: {
-        ParseIrqHandlerExit(cpu, ts, data);
-        break;
-      }
-      case FtraceEvent::kSoftirqEntryFieldNumber: {
-        ParseSoftIrqEntry(cpu, ts, data);
-        break;
-      }
-      case FtraceEvent::kSoftirqExitFieldNumber: {
-        ParseSoftIrqExit(cpu, ts, data);
-        break;
-      }
-      case FtraceEvent::kGpuMemTotalFieldNumber: {
-        ParseGpuMemTotal(ts, data);
-        break;
-      }
-      case FtraceEvent::kThermalTemperatureFieldNumber: {
-        ParseThermalTemperature(ts, data);
-        break;
-      }
-      case FtraceEvent::kCdevUpdateFieldNumber: {
-        ParseCdevUpdate(ts, data);
-        break;
-      }
-      case FtraceEvent::kSchedBlockedReasonFieldNumber: {
-        ParseSchedBlockedReason(ts, data, seq_state);
-        break;
-      }
-      case FtraceEvent::kFastrpcDmaStatFieldNumber: {
-        ParseFastRpcDmaStat(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kG2dTracingMarkWriteFieldNumber: {
-        ParseG2dTracingMarkWrite(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kDpuTracingMarkWriteFieldNumber: {
-        ParseDpuTracingMarkWrite(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kMaliTracingMarkWriteFieldNumber: {
-        ParseMaliTracingMarkWrite(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kCpuhpPauseFieldNumber: {
-        ParseCpuhpPause(ts, pid, data);
-        break;
-      }
       default:
         break;
     }
@@ -595,13 +390,11 @@
   }
 }
 
-void FtraceParser::ParseTypedFtraceToRaw(
-    uint32_t ftrace_id,
-    int64_t timestamp,
-    uint32_t cpu,
-    uint32_t tid,
-    ConstBytes blob,
-    PacketSequenceStateGeneration* seq_state) {
+void FtraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
+                                         int64_t ts,
+                                         uint32_t cpu,
+                                         uint32_t tid,
+                                         ConstBytes blob) {
   if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
     return;
 
@@ -615,49 +408,20 @@
   MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
   const auto& message_strings = ftrace_message_strings_[ftrace_id];
   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
-  RawId id =
-      context_->storage->mutable_raw_table()
-          ->Insert({timestamp, message_strings.message_name_id, cpu, utid})
-          .id;
+  RawId id = context_->storage->mutable_raw_table()
+                 ->Insert({ts, message_strings.message_name_id, cpu, utid})
+                 .id;
   auto inserter = context_->args_tracker->AddArgsTo(id);
 
   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
-    uint16_t field_id = fld.id();
-    if (PERFETTO_UNLIKELY(field_id >= kMaxFtraceEventFields)) {
+    if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
       PERFETTO_DLOG(
           "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
-          field_id);
+          fld.id());
       continue;
     }
-
-    ProtoSchemaType type = m->fields[field_id].type;
-    StringId name_id = message_strings.field_name_ids[field_id];
-
-    // Check if this field represents a kernel function.
-    auto it = std::find_if(
-        kKernelFunctionFields.begin(), kKernelFunctionFields.end(),
-        [ftrace_id, field_id](const FtraceEventAndFieldId& ev) {
-          return ev.event_id == ftrace_id && ev.field_id == field_id;
-        });
-    if (it != kKernelFunctionFields.end()) {
-      PERFETTO_CHECK(type == ProtoSchemaType::kUint64);
-
-      auto* interned_string = seq_state->LookupInternedMessage<
-          protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
-          protos::pbzero::InternedString>(fld.as_uint64());
-
-      // If we don't have the string for this field (can happen if symbolization
-      // wasn't enabled, if reading the symbols errored out or on legacy traces)
-      // then just add the field as a normal arg.
-      if (interned_string) {
-        protozero::ConstBytes str = interned_string->str();
-        StringId str_id = context_->storage->InternString(base::StringView(
-            reinterpret_cast<const char*>(str.data), str.size));
-        inserter.AddArg(name_id, Variadic::String(str_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:
@@ -706,86 +470,79 @@
 }
 
 PERFETTO_ALWAYS_INLINE
-void FtraceParser::ParseSchedSwitch(uint32_t cpu,
-                                    int64_t timestamp,
-                                    ConstBytes blob) {
+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());
   SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
-      cpu, timestamp, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
+      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 timestamp, ConstBytes blob) {
+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, ThreadNamePriority::kFtrace);
-  context_->event_tracker->PushInstant(timestamp, sched_wakeup_name_id_, utid,
+  auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
+  context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_, utid,
                                        RefType::kRefUtid);
 }
 
-void FtraceParser::ParseSchedWaking(int64_t timestamp, ConstBytes blob) {
+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, ThreadNamePriority::kFtrace);
-  context_->event_tracker->PushInstant(timestamp, sched_waking_name_id_, utid,
+  auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
+  context_->event_tracker->PushInstant(ts, sched_waking_name_id_, utid,
                                        RefType::kRefUtid);
 }
 
-void FtraceParser::ParseSchedProcessFree(int64_t timestamp, ConstBytes blob) {
+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(timestamp, pid);
+  context_->process_tracker->EndThread(ts, pid);
 }
 
-void FtraceParser::ParseCpuFreq(int64_t timestamp, ConstBytes blob) {
+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(timestamp, new_freq, track);
+  context_->event_tracker->PushCounter(ts, new_freq, track);
 }
 
-void FtraceParser::ParseGpuFreq(int64_t timestamp, ConstBytes blob) {
+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(timestamp, new_freq, track);
+  context_->event_tracker->PushCounter(ts, new_freq, track);
 }
 
-void FtraceParser::ParseCpuIdle(int64_t timestamp, ConstBytes blob) {
+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(timestamp, new_state, track);
+  context_->event_tracker->PushCounter(ts, new_state, track);
 }
 
-void FtraceParser::ParsePrint(int64_t timestamp,
-                              uint32_t pid,
-                              ConstBytes blob) {
+void FtraceParser::ParsePrint(int64_t ts, uint32_t pid, ConstBytes blob) {
   protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
-  SystraceParser::GetOrCreate(context_)->ParsePrintEvent(timestamp, pid,
-                                                         evt.buf());
+  SystraceParser::GetOrCreate(context_)->ParsePrintEvent(ts, pid, evt.buf());
 }
 
-void FtraceParser::ParseZero(int64_t timestamp, uint32_t pid, ConstBytes blob) {
+void FtraceParser::ParseZero(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());
   SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
-      timestamp, pid, evt.flag(), evt.name(), tgid, evt.value());
+      ts, pid, evt.flag(), evt.name(), tgid, evt.value());
 }
 
-void FtraceParser::ParseSdeTracingMarkWrite(int64_t timestamp,
+void FtraceParser::ParseSdeTracingMarkWrite(int64_t ts,
                                             uint32_t pid,
                                             ConstBytes blob) {
   protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
@@ -796,61 +553,13 @@
   }
 
   uint32_t tgid = static_cast<uint32_t>(evt.pid());
-  SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
-      timestamp, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
+  SystraceParser::GetOrCreate(context_)->ParseSdeTracingMarkWrite(
+      ts, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
       evt.trace_name(), tgid, evt.value());
 }
 
-void FtraceParser::ParseDpuTracingMarkWrite(int64_t timestamp,
-                                            uint32_t pid,
-                                            ConstBytes blob) {
-  protos::pbzero::DpuTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
-                                                              blob.size);
-  if (!evt.type()) {
-    context_->storage->IncrementStats(stats::systrace_parse_failure);
-    return;
-  }
-
-  uint32_t tgid = static_cast<uint32_t>(evt.pid());
-  SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
-      timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
-      evt.name(), tgid, evt.value());
-}
-
-void FtraceParser::ParseG2dTracingMarkWrite(int64_t timestamp,
-                                            uint32_t pid,
-                                            ConstBytes blob) {
-  protos::pbzero::G2dTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
-                                                              blob.size);
-  if (!evt.type()) {
-    context_->storage->IncrementStats(stats::systrace_parse_failure);
-    return;
-  }
-
-  uint32_t tgid = static_cast<uint32_t>(evt.pid());
-  SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
-      timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
-      evt.name(), tgid, evt.value());
-}
-
-void FtraceParser::ParseMaliTracingMarkWrite(int64_t timestamp,
-                                             uint32_t pid,
-                                             ConstBytes blob) {
-  protos::pbzero::MaliTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
-                                                               blob.size);
-  if (!evt.type()) {
-    context_->storage->IncrementStats(stats::systrace_parse_failure);
-    return;
-  }
-
-  uint32_t tgid = static_cast<uint32_t>(evt.pid());
-  SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
-      timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
-      evt.name(), tgid, evt.value());
-}
-
 /** Parses ion heap events present in Pixel kernels. */
-void FtraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
+void FtraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
                                             uint32_t pid,
                                             ConstBytes blob,
                                             bool grow) {
@@ -876,16 +585,14 @@
   // Push the global counter.
   TrackId track =
       context_->track_tracker->InternGlobalCounterTrack(global_name_id);
-  context_->event_tracker->PushCounter(timestamp,
-                                       static_cast<double>(total_bytes), track);
+  context_->event_tracker->PushCounter(ts, total_bytes, track);
 
   // Push the change counter.
   // TODO(b/121331269): these should really be instant events.
   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
   track =
       context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(change_bytes), track);
+  context_->event_tracker->PushCounter(ts, change_bytes, 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
@@ -907,105 +614,51 @@
 }
 
 /** Parses ion heap events (introduced in 4.19 kernels). */
-void FtraceParser::ParseIonStat(int64_t timestamp,
+void FtraceParser::ParseIonStat(int64_t ts,
                                 uint32_t pid,
                                 protozero::ConstBytes data) {
   protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
   // Push the global counter.
   TrackId track =
       context_->track_tracker->InternGlobalCounterTrack(ion_total_id_);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(ion.total_allocated()), track);
+  context_->event_tracker->PushCounter(ts, ion.total_allocated(), track);
 
   // Push the change counter.
   // TODO(b/121331269): these should really be instant events.
   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
   track =
       context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
-  context_->event_tracker->PushCounter(timestamp,
-                                       static_cast<double>(ion.len()), track);
-
-  // Global track for individual buffer tracking
-  auto async_track =
-      context_->async_track_set_tracker->InternGlobalTrackSet(ion_buffer_id_);
-  if (ion.len() > 0) {
-    TrackId start_id =
-        context_->async_track_set_tracker->Begin(async_track, ion.buffer_id());
-    std::string buf = std::to_string(ion.len() / 1024) + " kB";
-    context_->slice_tracker->Begin(
-        timestamp, start_id, kNullStringId,
-        context_->storage->InternString(base::StringView(buf)));
-  } else {
-    TrackId end_id =
-        context_->async_track_set_tracker->End(async_track, ion.buffer_id());
-    context_->slice_tracker->End(timestamp, end_id);
-  }
-}
-
-void FtraceParser::ParseDmaHeapStat(int64_t timestamp,
-                                    uint32_t pid,
-                                    protozero::ConstBytes data) {
-  protos::pbzero::DmaHeapStatFtraceEvent::Decoder dma_heap(data.data,
-                                                           data.size);
-  // Push the global counter.
-  TrackId track =
-      context_->track_tracker->InternGlobalCounterTrack(dma_heap_total_id_);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(dma_heap.total_allocated()), track);
-
-  // Push the change counter.
-  // TODO(b/121331269): these should really be instant events.
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  track = context_->track_tracker->InternThreadCounterTrack(dma_heap_change_id_,
-                                                            utid);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(dma_heap.len()), track);
-
-  // Global track for individual buffer tracking
-  auto async_track =
-      context_->async_track_set_tracker->InternGlobalTrackSet(dma_buffer_id_);
-  if (dma_heap.len() > 0) {
-    TrackId start_id = context_->async_track_set_tracker->Begin(
-        async_track, static_cast<int64_t>(dma_heap.inode()));
-    std::string buf = std::to_string(dma_heap.len() / 1024) + " kB";
-    context_->slice_tracker->Begin(
-        timestamp, start_id, kNullStringId,
-        context_->storage->InternString(base::StringView(buf)));
-  } else {
-    TrackId end_id = context_->async_track_set_tracker->End(
-        async_track, static_cast<int64_t>(dma_heap.inode()));
-    context_->slice_tracker->End(timestamp, end_id);
-  }
+  context_->event_tracker->PushCounter(ts, ion.len(), track);
 }
 
 // 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 timestamp, ConstBytes blob) {
+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()));
-  InstantId id = context_->event_tracker->PushInstant(
-      timestamp, signal_generate_id_, utid, RefType::kRefUtid);
+  InstantId id = context_->event_tracker->PushInstant(ts, signal_generate_id_,
+                                                      utid, RefType::kRefUtid);
 
   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
                                                Variadic::Integer(sig.sig()));
 }
 
-void FtraceParser::ParseSignalDeliver(int64_t timestamp,
+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);
-  InstantId id = context_->event_tracker->PushInstant(
-      timestamp, signal_deliver_id_, utid, RefType::kRefUtid);
+  InstantId id = context_->event_tracker->PushInstant(ts, signal_deliver_id_,
+                                                      utid, RefType::kRefUtid);
 
   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
                                                Variadic::Integer(sig.sig()));
 }
 
-void FtraceParser::ParseLowmemoryKill(int64_t timestamp, ConstBytes blob) {
-  // TODO(hjd): Store the pagecache_size, pagecache_limit and free fields
+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);
 
@@ -1019,7 +672,7 @@
     return;
 
   InstantId id = context_->event_tracker->PushInstant(
-      timestamp, lmk_id_, opt_utid.value(), RefType::kRefUtid, true);
+      ts, lmk_id_, opt_utid.value(), RefType::kRefUtid, true);
 
   // Store the comm as an arg.
   auto comm_id = context_->storage->InternString(
@@ -1028,7 +681,7 @@
                                                Variadic::String(comm_id));
 }
 
-void FtraceParser::ParseOOMScoreAdjUpdate(int64_t timestamp, ConstBytes blob) {
+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
@@ -1036,19 +689,19 @@
   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(timestamp, oom_adj,
+  context_->event_tracker->PushProcessCounterForThread(ts, oom_adj,
                                                        oom_score_adj_id_, utid);
 }
 
-void FtraceParser::ParseOOMKill(int64_t timestamp, ConstBytes blob) {
+void FtraceParser::ParseOOMKill(int64_t ts, ConstBytes blob) {
   protos::pbzero::MarkVictimFtraceEvent::Decoder evt(blob.data, blob.size);
   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
       static_cast<uint32_t>(evt.pid()));
-  context_->event_tracker->PushInstant(timestamp, oom_kill_id_, utid,
+  context_->event_tracker->PushInstant(ts, oom_kill_id_, utid,
                                        RefType::kRefUtid, true);
 }
 
-void FtraceParser::ParseMmEventRecord(int64_t timestamp,
+void FtraceParser::ParseMmEventRecord(int64_t ts,
                                       uint32_t pid,
                                       ConstBytes blob) {
   protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
@@ -1062,14 +715,14 @@
 
   const auto& counter_names = mm_event_counter_names_[type];
   context_->event_tracker->PushProcessCounterForThread(
-      timestamp, evt.count(), counter_names.count, utid);
+      ts, evt.count(), counter_names.count, utid);
   context_->event_tracker->PushProcessCounterForThread(
-      timestamp, evt.max_lat(), counter_names.max_lat, utid);
+      ts, evt.max_lat(), counter_names.max_lat, utid);
   context_->event_tracker->PushProcessCounterForThread(
-      timestamp, evt.avg_lat(), counter_names.avg_lat, utid);
+      ts, evt.avg_lat(), counter_names.avg_lat, utid);
 }
 
-void FtraceParser::ParseSysEvent(int64_t timestamp,
+void FtraceParser::ParseSysEvent(int64_t ts,
                                  uint32_t pid,
                                  bool is_enter,
                                  ConstBytes blob) {
@@ -1079,9 +732,9 @@
 
   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
   if (is_enter) {
-    syscall_tracker->Enter(timestamp, utid, syscall_num);
+    syscall_tracker->Enter(ts, utid, syscall_num);
   } else {
-    syscall_tracker->Exit(timestamp, utid, syscall_num);
+    syscall_tracker->Exit(ts, utid, syscall_num);
   }
 
   // We are reusing the same function for sys_enter and sys_exit.
@@ -1093,7 +746,7 @@
       "field mismatch");
 }
 
-void FtraceParser::ParseTaskNewTask(int64_t timestamp,
+void FtraceParser::ParseTaskNewTask(int64_t ts,
                                     uint32_t source_tid,
                                     ConstBytes blob) {
   protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
@@ -1110,21 +763,19 @@
   // 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(timestamp, source_tid, new_tid, new_comm);
+    proc_tracker->StartNewProcess(ts, source_tid, new_tid, new_comm);
     return;
   }
 
   if (source_tid == kKthreaddPid) {
-    context_->process_tracker->SetProcessMetadata(
-        kKthreaddPid, base::nullopt, kKthreaddName, base::StringView());
+    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(timestamp, new_tid);
-  proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
-                                       ThreadNamePriority::kFtrace);
+  auto new_utid = proc_tracker->StartNewThread(ts, new_tid, new_comm);
   proc_tracker->AssociateThreads(source_utid, new_utid);
 }
 
@@ -1132,8 +783,7 @@
   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,
-                                              ThreadNamePriority::kFtrace);
+  context_->process_tracker->UpdateThreadName(tid, comm);
   context_->process_tracker->UpdateProcessNameFromThreadName(tid, comm);
 }
 
@@ -1198,285 +848,5 @@
   BinderTracker::GetOrCreate(context_)->Unlock(timestamp, pid);
 }
 
-void FtraceParser::ParseClockSetRate(int64_t timestamp, ConstBytes blob) {
-  protos::pbzero::ClockSetRateFtraceEvent::Decoder evt(blob.data, blob.size);
-  static const char kSubtitle[] = "Frequency";
-  ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
-}
-
-void FtraceParser::ParseClockEnable(int64_t timestamp, ConstBytes blob) {
-  protos::pbzero::ClockEnableFtraceEvent::Decoder evt(blob.data, blob.size);
-  static const char kSubtitle[] = "State";
-  ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
-}
-
-void FtraceParser::ParseClockDisable(int64_t timestamp, ConstBytes blob) {
-  protos::pbzero::ClockDisableFtraceEvent::Decoder evt(blob.data, blob.size);
-  static const char kSubtitle[] = "State";
-  ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
-}
-
-void FtraceParser::ClockRate(int64_t timestamp,
-                             base::StringView clock_name,
-                             base::StringView subtitle,
-                             uint64_t rate) {
-  char counter_name[255];
-  snprintf(counter_name, sizeof(counter_name), "%.*s %.*s",
-           int(clock_name.size()), clock_name.data(), int(subtitle.size()),
-           subtitle.data());
-  StringId name = context_->storage->InternString(counter_name);
-  TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
-  context_->event_tracker->PushCounter(timestamp, static_cast<double>(rate),
-                                       track);
-}
-
-void FtraceParser::ParseScmCallStart(int64_t timestamp,
-                                     uint32_t pid,
-                                     ConstBytes blob) {
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  protos::pbzero::ScmCallStartFtraceEvent::Decoder evt(blob.data, blob.size);
-
-  char str[64];
-  sprintf(str, "scm id=%#" PRIx64, evt.x0());
-  StringId name_id = context_->storage->InternString(str);
-  context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id);
-}
-
-void FtraceParser::ParseScmCallEnd(int64_t timestamp,
-                                   uint32_t pid,
-                                   ConstBytes blob) {
-  protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->End(timestamp, track_id);
-}
-
-void FtraceParser::ParseWorkqueueExecuteStart(
-    int64_t timestamp,
-    uint32_t pid,
-    ConstBytes blob,
-    PacketSequenceStateGeneration* seq_state) {
-  protos::pbzero::WorkqueueExecuteStartFtraceEvent::Decoder evt(blob.data,
-                                                                blob.size);
-
-  auto* interned_string = seq_state->LookupInternedMessage<
-      protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
-      protos::pbzero::InternedString>(static_cast<uint32_t>(evt.function()));
-  StringId name_id;
-  if (interned_string) {
-    protozero::ConstBytes str = interned_string->str();
-    name_id = context_->storage->InternString(
-        base::StringView(reinterpret_cast<const char*>(str.data), str.size));
-  } else {
-    char slice_name[255];
-    snprintf(slice_name, base::ArraySize(slice_name), "%#" PRIx64,
-             evt.function());
-    name_id = context_->storage->InternString(base::StringView(slice_name));
-  }
-
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId track = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->Begin(timestamp, track, workqueue_id_, name_id);
-}
-
-void FtraceParser::ParseWorkqueueExecuteEnd(int64_t timestamp,
-                                            uint32_t pid,
-                                            ConstBytes blob) {
-  protos::pbzero::WorkqueueExecuteEndFtraceEvent::Decoder evt(blob.data,
-                                                              blob.size);
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId track = context_->track_tracker->InternThreadTrack(utid);
-  context_->slice_tracker->End(timestamp, track, workqueue_id_);
-}
-
-void FtraceParser::ParseIrqHandlerEntry(uint32_t cpu,
-                                        int64_t timestamp,
-                                        protozero::ConstBytes blob) {
-  protos::pbzero::IrqHandlerEntryFtraceEvent::Decoder evt(blob.data, blob.size);
-  char track_name[255];
-  snprintf(track_name, sizeof(track_name), "Irq Cpu %d", cpu);
-  StringId track_name_id = context_->storage->InternString(track_name);
-  char slice_name[255];
-  base::StringView irq_name = evt.name();
-  snprintf(slice_name, sizeof(slice_name), "IRQ (%.*s)", int(irq_name.size()),
-           irq_name.data());
-  StringId slice_name_id = context_->storage->InternString(slice_name);
-  TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
-  context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
-}
-
-void FtraceParser::ParseIrqHandlerExit(uint32_t cpu,
-                                       int64_t timestamp,
-                                       protozero::ConstBytes blob) {
-  protos::pbzero::IrqHandlerExitFtraceEvent::Decoder evt(blob.data, blob.size);
-  char track_name[255];
-  snprintf(track_name, sizeof(track_name), "Irq Cpu %d", cpu);
-  StringId track_name_id = context_->storage->InternString(track_name);
-  TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
-  char status[255];
-  snprintf(status, sizeof(status), "%s",
-           evt.ret() == 1 ? "handled" : "unhandled");
-  StringId status_id = context_->storage->InternString(status);
-  auto args_inserter = [this,
-                        &status_id](ArgsTracker::BoundInserter* inserter) {
-    inserter->AddArg(ret_arg_id_, Variadic::String(status_id));
-  };
-  context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
-}
-
-void FtraceParser::ParseSoftIrqEntry(uint32_t cpu,
-                                     int64_t timestamp,
-                                     protozero::ConstBytes blob) {
-  protos::pbzero::SoftirqEntryFtraceEvent::Decoder evt(blob.data, blob.size);
-  char track_name[255];
-  snprintf(track_name, sizeof(track_name), "SoftIrq Cpu %d", cpu);
-  StringId track_name_id = context_->storage->InternString(track_name);
-  auto num_actions = sizeof(kActionNames) / sizeof(*kActionNames);
-  if (evt.vec() >= num_actions) {
-    PERFETTO_DFATAL("No action name at index %d for softirq event.", evt.vec());
-    return;
-  }
-  base::StringView slice_name = kActionNames[evt.vec()];
-  StringId slice_name_id = context_->storage->InternString(slice_name);
-  TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
-  context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
-}
-
-void FtraceParser::ParseSoftIrqExit(uint32_t cpu,
-                                    int64_t timestamp,
-                                    protozero::ConstBytes blob) {
-  protos::pbzero::SoftirqExitFtraceEvent::Decoder evt(blob.data, blob.size);
-  char track_name[255];
-  snprintf(track_name, sizeof(track_name), "SoftIrq Cpu %d", cpu);
-  StringId track_name_id = context_->storage->InternString(track_name);
-  TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
-  auto vec = evt.vec();
-  auto args_inserter = [this, vec](ArgsTracker::BoundInserter* inserter) {
-    inserter->AddArg(vec_arg_id_, Variadic::Integer(vec));
-  };
-  context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
-}
-
-void FtraceParser::ParseGpuMemTotal(int64_t timestamp,
-                                    protozero::ConstBytes data) {
-  protos::pbzero::GpuMemTotalFtraceEvent::Decoder gpu_mem_total(data.data,
-                                                                data.size);
-
-  TrackId track = kInvalidTrackId;
-  const uint32_t pid = gpu_mem_total.pid();
-  if (pid == 0) {
-    // Pid 0 is used to indicate the global total
-    track = context_->track_tracker->InternGlobalCounterTrack(
-        gpu_mem_total_name_id_, gpu_mem_total_unit_id_,
-        gpu_mem_total_global_desc_id_);
-  } else {
-    // Process emitting the packet can be different from the pid in the event.
-    UniqueTid utid = context_->process_tracker->UpdateThread(pid, pid);
-    UniquePid upid = context_->storage->thread_table().upid()[utid].value_or(0);
-    track = context_->track_tracker->InternProcessCounterTrack(
-        gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
-        gpu_mem_total_proc_desc_id_);
-  }
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(gpu_mem_total.size()), track);
-}
-
-void FtraceParser::ParseThermalTemperature(int64_t timestamp,
-                                           protozero::ConstBytes blob) {
-  protos::pbzero::ThermalTemperatureFtraceEvent::Decoder evt(blob.data,
-                                                             blob.size);
-  char counter_name[255];
-  base::StringView thermal_zone = evt.thermal_zone();
-  snprintf(counter_name, sizeof(counter_name), "%.*s Temperature",
-           int(thermal_zone.size()), thermal_zone.data());
-  StringId name = context_->storage->InternString(counter_name);
-  TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
-  context_->event_tracker->PushCounter(timestamp, evt.temp(), track);
-}
-
-void FtraceParser::ParseCdevUpdate(int64_t timestamp,
-                                   protozero::ConstBytes blob) {
-  protos::pbzero::CdevUpdateFtraceEvent::Decoder evt(blob.data, blob.size);
-  char counter_name[255];
-  base::StringView type = evt.type();
-  snprintf(counter_name, sizeof(counter_name), "%.*s Cooling Device",
-           int(type.size()), type.data());
-  StringId name = context_->storage->InternString(counter_name);
-  TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(evt.target()), track);
-}
-
-void FtraceParser::ParseSchedBlockedReason(
-    int64_t timestamp,
-    protozero::ConstBytes blob,
-    PacketSequenceStateGeneration* seq_state) {
-  protos::pbzero::SchedBlockedReasonFtraceEvent::Decoder evt(blob);
-  uint32_t pid = static_cast<uint32_t>(evt.pid());
-  auto utid = context_->process_tracker->GetOrCreateThread(pid);
-  InstantId id = context_->event_tracker->PushInstant(
-      timestamp, sched_blocked_reason_id_, utid, RefType::kRefUtid, false);
-
-  auto inserter = context_->args_tracker->AddArgsTo(id);
-  inserter.AddArg(io_wait_id_, Variadic::Boolean(evt.io_wait()));
-
-  uint32_t caller_iid = static_cast<uint32_t>(evt.caller());
-  auto* interned_string = seq_state->LookupInternedMessage<
-      protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
-      protos::pbzero::InternedString>(caller_iid);
-
-  if (interned_string) {
-    protozero::ConstBytes str = interned_string->str();
-    StringId str_id = context_->storage->InternString(
-        base::StringView(reinterpret_cast<const char*>(str.data), str.size));
-    inserter.AddArg(function_id_, Variadic::String(str_id));
-  }
-}
-
-void FtraceParser::ParseFastRpcDmaStat(int64_t timestamp,
-                                       uint32_t pid,
-                                       protozero::ConstBytes blob) {
-  protos::pbzero::FastrpcDmaStatFtraceEvent::Decoder evt(blob.data, blob.size);
-
-  StringId name;
-  if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
-    name = fast_rpc_delta_names_[static_cast<size_t>(evt.cid())];
-  } else {
-    char str[64];
-    snprintf(str, sizeof(str), "mem.fastrpc[%" PRId32 "]", evt.cid());
-    name = context_->storage->InternString(str);
-  }
-
-  StringId total_name;
-  if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
-    total_name = fast_rpc_total_names_[static_cast<size_t>(evt.cid())];
-  } else {
-    char str[64];
-    snprintf(str, sizeof(str), "mem.fastrpc[%" PRId32 "]", evt.cid());
-    total_name = context_->storage->InternString(str);
-  }
-
-  // Push the global counter.
-  TrackId track = context_->track_tracker->InternGlobalCounterTrack(total_name);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(evt.total_allocated()), track);
-
-  // Push the change counter.
-  // TODO(b/121331269): these should really be instant events.
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  TrackId delta_track =
-      context_->track_tracker->InternThreadCounterTrack(name, utid);
-  context_->event_tracker->PushCounter(
-      timestamp, static_cast<double>(evt.len()), delta_track);
-}
-
-void FtraceParser::ParseCpuhpPause(int64_t,
-                                   uint32_t,
-                                   protozero::ConstBytes blob) {
-  protos::pbzero::CpuhpPauseFtraceEvent::Decoder evt(blob.data, blob.size);
-  // TODO(b/183110813): Parse and visualize this event.
-}
-
 }  // 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
index f0ef2b9..5d7ae96 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -19,11 +19,12 @@
 
 #include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
+#include "src/trace_processor/importers/ftrace/binder_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
 #include "src/trace_processor/importers/ftrace/rss_stat_tracker.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/types/trace_processor_context.h"
 
 namespace perfetto {
@@ -46,8 +47,7 @@
                              int64_t timestamp,
                              uint32_t cpu,
                              uint32_t pid,
-                             protozero::ConstBytes,
-                             PacketSequenceStateGeneration*);
+                             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);
@@ -60,32 +60,18 @@
   void ParseSdeTracingMarkWrite(int64_t timestamp,
                                 uint32_t pid,
                                 protozero::ConstBytes);
-  void ParseDpuTracingMarkWrite(int64_t timestamp,
-                                uint32_t pid,
-                                protozero::ConstBytes);
-  void ParseG2dTracingMarkWrite(int64_t timestamp,
-                                uint32_t pid,
-                                protozero::ConstBytes);
-  void ParseMaliTracingMarkWrite(int64_t timestamp,
-                                 uint32_t pid,
-                                 protozero::ConstBytes);
-  void ParseIonHeapGrowOrShrink(int64_t timestamp,
+  void ParseIonHeapGrowOrShrink(int64_t ts,
                                 uint32_t pid,
                                 protozero::ConstBytes,
                                 bool grow);
-  void ParseIonStat(int64_t timestamp, uint32_t pid, protozero::ConstBytes);
-  void ParseDmaHeapStat(int64_t timestamp, uint32_t pid, protozero::ConstBytes);
-  void ParseSignalGenerate(int64_t timestamp, protozero::ConstBytes);
-  void ParseSignalDeliver(int64_t timestamp,
-                          uint32_t pid,
-                          protozero::ConstBytes);
-  void ParseLowmemoryKill(int64_t timestamp, protozero::ConstBytes);
-  void ParseOOMScoreAdjUpdate(int64_t timestamp, protozero::ConstBytes);
-  void ParseOOMKill(int64_t timestamp, protozero::ConstBytes);
-  void ParseMmEventRecord(int64_t timestamp,
-                          uint32_t pid,
-                          protozero::ConstBytes);
-  void ParseSysEvent(int64_t timestamp,
+  void ParseIonStat(int64_t ts, uint32_t pid, protozero::ConstBytes);
+  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 ParseOOMKill(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);
@@ -109,44 +95,6 @@
   void ParseBinderUnlock(int64_t timestamp,
                          uint32_t pid,
                          protozero::ConstBytes);
-  void ParseClockSetRate(int64_t timestamp, protozero::ConstBytes);
-  void ParseClockEnable(int64_t timestamp, protozero::ConstBytes);
-  void ParseClockDisable(int64_t timestamp, protozero::ConstBytes);
-  void ClockRate(int64_t timestamp,
-                 base::StringView clock_name,
-                 base::StringView subtitle,
-                 uint64_t rate);
-  void ParseScmCallStart(int64_t timestamp,
-                         uint32_t pid,
-                         protozero::ConstBytes);
-  void ParseScmCallEnd(int64_t timestamp, uint32_t pid, protozero::ConstBytes);
-  void ParseWorkqueueExecuteStart(int64_t timestamp,
-                                  uint32_t pid,
-                                  protozero::ConstBytes,
-                                  PacketSequenceStateGeneration* seq_state);
-  void ParseWorkqueueExecuteEnd(int64_t timestamp,
-                                uint32_t pid,
-                                protozero::ConstBytes);
-  void ParseIrqHandlerEntry(uint32_t cpu,
-                            int64_t timestamp,
-                            protozero::ConstBytes);
-  void ParseIrqHandlerExit(uint32_t cpu,
-                           int64_t timestamp,
-                           protozero::ConstBytes);
-  void ParseSoftIrqEntry(uint32_t cpu,
-                         int64_t timestamp,
-                         protozero::ConstBytes);
-  void ParseSoftIrqExit(uint32_t cpu, int64_t timestamp, protozero::ConstBytes);
-  void ParseGpuMemTotal(int64_t timestamp, protozero::ConstBytes);
-  void ParseThermalTemperature(int64_t timestamp, protozero::ConstBytes);
-  void ParseCdevUpdate(int64_t timestamp, protozero::ConstBytes);
-  void ParseSchedBlockedReason(int64_t timestamp,
-                               protozero::ConstBytes,
-                               PacketSequenceStateGeneration*);
-  void ParseFastRpcDmaStat(int64_t timestamp,
-                           uint32_t pid,
-                           protozero::ConstBytes);
-  void ParseCpuhpPause(int64_t, uint32_t, protozero::ConstBytes);
 
   TraceProcessorContext* context_;
   RssStatTracker rss_stat_tracker_;
@@ -158,10 +106,6 @@
   const StringId cpu_idle_name_id_;
   const StringId ion_total_id_;
   const StringId ion_change_id_;
-  const StringId ion_buffer_id_;
-  const StringId dma_heap_total_id_;
-  const StringId dma_heap_change_id_;
-  const StringId dma_buffer_id_;
   const StringId ion_total_unknown_id_;
   const StringId ion_change_unknown_id_;
   const StringId signal_generate_id_;
@@ -171,17 +115,6 @@
   const StringId comm_name_id_;
   const StringId signal_name_id_;
   const StringId oom_kill_id_;
-  const StringId workqueue_id_;
-  const StringId irq_id_;
-  const StringId ret_arg_id_;
-  const StringId vec_arg_id_;
-  const StringId gpu_mem_total_name_id_;
-  const StringId gpu_mem_total_unit_id_;
-  const StringId gpu_mem_total_global_desc_id_;
-  const StringId gpu_mem_total_proc_desc_id_;
-  const StringId sched_blocked_reason_id_;
-  const StringId io_wait_id_;
-  const StringId function_id_;
 
   struct FtraceMessageStrings {
     // The string id of name of the event field (e.g. sched_switch's id).
@@ -200,19 +133,9 @@
     StringId avg_lat = kNullStringId;
   };
 
-  static constexpr size_t kFastRpcCounterSize = 4;
-  std::array<StringId, kFastRpcCounterSize> fast_rpc_delta_names_;
-  std::array<StringId, kFastRpcCounterSize> fast_rpc_total_names_;
-
   // 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_;
-
-  bool has_seen_first_ftrace_packet_ = false;
-
-  // Stores information about the timestamp from the metadata table which is
-  // used to filter ftrace packets which happen before this point.
-  int64_t drop_ftrace_data_before_ts_ = 0;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
index e51545d..d196df2 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
@@ -30,12 +30,12 @@
 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,
-                                           PacketSequenceState* state) {
+void FtraceTokenizer::TokenizeFtraceBundle(TraceBlobView bundle) {
   protos::pbzero::FtraceEventBundle::Decoder decoder(bundle.data(),
                                                      bundle.length());
 
@@ -59,15 +59,13 @@
   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), state);
+    TokenizeFtraceEvent(cpu, bundle.slice(off, event.size));
   }
   context_->sorter->FinalizeFtraceEventBatch(cpu);
 }
 
 PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu,
-                                          TraceBlobView event,
-                                          PacketSequenceState* state) {
+void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event) {
   constexpr auto kTimestampFieldNumber =
       protos::pbzero::FtraceEvent::kTimestampFieldNumber;
   const uint8_t* data = event.data();
@@ -98,10 +96,11 @@
     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.
-  int64_t timestamp = static_cast<int64_t>(raw_timestamp);
-  context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event), state);
+  context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event));
 }
 
 PERFETTO_ALWAYS_INLINE
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
index f4f5416..e48cb74 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
@@ -18,26 +18,22 @@
 #define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
 
 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-class PacketSequenceState;
-
 class FtraceTokenizer {
  public:
   explicit FtraceTokenizer(TraceProcessorContext* context)
       : context_(context) {}
 
-  void TokenizeFtraceBundle(TraceBlobView bundle, PacketSequenceState*);
+  void TokenizeFtraceBundle(TraceBlobView bundle);
 
  private:
-  void TokenizeFtraceEvent(uint32_t cpu,
-                           TraceBlobView event,
-                           PacketSequenceState*);
+  void TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event);
   void TokenizeFtraceCompactSched(uint32_t cpu,
                                   const uint8_t* data,
                                   size_t size);
diff --git a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
index 214bd75..8c5e8f6 100644
--- a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
+++ b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
@@ -39,26 +39,9 @@
 
 void RssStatTracker::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
   protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);
-  uint32_t member = static_cast<uint32_t>(rss.member());
-  int64_t size = rss.size();
-  base::Optional<bool> curr;
-  base::Optional<int64_t> mm_id;
-  if (rss.has_curr()) {
-    curr = base::make_optional(static_cast<bool>(rss.curr()));
-  }
-  if (rss.has_mm_id()) {
-    mm_id = base::make_optional(rss.mm_id());
-  }
-  ParseRssStat(ts, pid, size, member, curr, mm_id);
-}
-
-void RssStatTracker::ParseRssStat(int64_t ts,
-                                  uint32_t pid,
-                                  int64_t size,
-                                  uint32_t member,
-                                  base::Optional<bool> curr,
-                                  base::Optional<int64_t> mm_id) {
   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;
@@ -70,15 +53,16 @@
   }
 
   base::Optional<UniqueTid> utid;
-  if (mm_id.has_value() && curr.has_value()) {
-    utid = FindUtidForMmId(*mm_id, *curr, pid);
+  if (rss.has_mm_id()) {
+    PERFETTO_DCHECK(rss.has_curr());
+    utid = FindUtidForMmId(rss.mm_id(), rss.curr(), pid);
   } else {
     utid = context_->process_tracker->GetOrCreateThread(pid);
   }
 
   if (utid) {
     context_->event_tracker->PushProcessCounterForThread(
-        ts, static_cast<double>(size), rss_members_[member], *utid);
+        ts, size, rss_members_[member], *utid);
   } else {
     context_->storage->IncrementStats(stats::rss_stat_unknown_thread_for_mm_id);
   }
diff --git a/src/trace_processor/importers/ftrace/rss_stat_tracker.h b/src/trace_processor/importers/ftrace/rss_stat_tracker.h
index fff203c..50ad001 100644
--- a/src/trace_processor/importers/ftrace/rss_stat_tracker.h
+++ b/src/trace_processor/importers/ftrace/rss_stat_tracker.h
@@ -34,12 +34,6 @@
   explicit RssStatTracker(TraceProcessorContext*);
 
   void ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob);
-  void ParseRssStat(int64_t ts,
-                    uint32_t pid,
-                    int64_t size,
-                    uint32_t member,
-                    base::Optional<bool> curr,
-                    base::Optional<int64_t> mm_id);
 
  private:
   base::Optional<UniqueTid> FindUtidForMmId(int64_t mm_id,
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
index 247c08e..5a43d54 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
@@ -73,10 +73,8 @@
                                         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",
-        static_cast<double>(context_->event_tracker->max_timestamp() - ts) /
-            1e6);
+    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;
   }
@@ -84,8 +82,8 @@
   PERFETTO_DCHECK(cpu < kMaxCpus);
 
   StringId next_comm_id = context_->storage->InternString(next_comm);
-  UniqueTid next_utid = context_->process_tracker->UpdateThreadName(
-      next_pid, next_comm_id, ThreadNamePriority::kFtrace);
+  UniqueTid 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;
@@ -105,8 +103,8 @@
   // 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, ThreadNamePriority::kFtrace);
+  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,
@@ -127,18 +125,16 @@
                                                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",
-        static_cast<double>(context_->event_tracker->max_timestamp() - ts) /
-            1e6);
+    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 < kMaxCpus);
 
-  UniqueTid next_utid = context_->process_tracker->UpdateThreadName(
-      next_pid, next_comm_id, ThreadNamePriority::kFtrace);
+  UniqueTid next_utid =
+      context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
 
   auto* pending_sched = &pending_sched_per_cpu_[cpu];
 
@@ -267,10 +263,8 @@
                                                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",
-        static_cast<double>(context_->event_tracker->max_timestamp() - ts) /
-            1e6);
+    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;
   }
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc b/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
index 15f6eca..82363f9 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc
@@ -125,8 +125,7 @@
                                  prio, prev_state,
                                  /*tid=*/1, kCommProc2, prio);
 
-  context.process_tracker->SetProcessMetadata(2, base::nullopt, "test",
-                                              base::StringView());
+  context.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
   context.process_tracker->UpdateThread(4, 2);
 
   ASSERT_EQ(context.storage->thread_table().tid()[1], 4u);
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_record.h b/src/trace_processor/importers/fuchsia/fuchsia_record.h
index 9518c35..211785d 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_record.h
+++ b/src/trace_processor/importers/fuchsia/fuchsia_record.h
@@ -17,9 +17,9 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_RECORD_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_RECORD_H_
 
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 
 #include <vector>
 
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
index 5e61475..c1c5361 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
@@ -18,7 +18,6 @@
 
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
@@ -39,9 +38,6 @@
 constexpr uint32_t kAsyncBegin = 5;
 constexpr uint32_t kAsyncInstant = 6;
 constexpr uint32_t kAsyncEnd = 7;
-constexpr uint32_t kFlowBegin = 8;
-constexpr uint32_t kFlowStep = 9;
-constexpr uint32_t kFlowEnd = 10;
 
 // Argument Types
 constexpr uint32_t kNull = 0;
@@ -249,13 +245,6 @@
         args.push_back(arg);
         cursor.SetWordIndex(arg_base + arg_size_words);
       }
-      auto insert_args = [this, args](ArgsTracker::BoundInserter* inserter) {
-        for (const Arg& arg : args) {
-          inserter->AddArg(
-              arg.name, arg.name,
-              arg.value.ToStorageVariadic(context_->storage.get()));
-        }
-      };
 
       switch (event_type) {
         case kInstant: {
@@ -333,7 +322,7 @@
               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, cat, name, insert_args);
+          slices->Begin(ts, track_id, cat, name);
           break;
         }
         case kDurationEnd: {
@@ -344,7 +333,7 @@
           // 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, {}, {}, insert_args);
+          slices->End(ts, track_id);
           break;
         }
         case kDurationComplete: {
@@ -362,7 +351,7 @@
               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, cat, name, duration, insert_args);
+          slices->Scoped(ts, track_id, cat, name, duration);
           break;
         }
         case kAsyncBegin: {
@@ -371,11 +360,9 @@
             context_->storage->IncrementStats(stats::fuchsia_invalid_event);
             return;
           }
-          UniquePid upid =
-              procs->GetOrCreateProcess(static_cast<uint32_t>(tinfo.pid));
           TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, upid, correlation_id);
-          slices->Begin(ts, track_id, cat, name, insert_args);
+              name, correlation_id);
+          slices->Begin(ts, track_id, cat, name);
           break;
         }
         case kAsyncInstant: {
@@ -387,10 +374,8 @@
             context_->storage->IncrementStats(stats::fuchsia_invalid_event);
             return;
           }
-          UniquePid upid =
-              procs->GetOrCreateProcess(static_cast<uint32_t>(tinfo.pid));
           TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, upid, correlation_id);
+              name, correlation_id);
           InstantId id = context_->event_tracker->PushInstant(
               ts, name, track_id.value, RefType::kRefTrack);
           auto inserter = context_->args_tracker->AddArgsTo(id);
@@ -408,50 +393,9 @@
             context_->storage->IncrementStats(stats::fuchsia_invalid_event);
             return;
           }
-          UniquePid upid =
-              procs->GetOrCreateProcess(static_cast<uint32_t>(tinfo.pid));
           TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, upid, correlation_id);
-          slices->End(ts, track_id, cat, name, insert_args);
-          break;
-        }
-        case kFlowBegin: {
-          uint64_t correlation_id;
-          if (!cursor.ReadUint64(&correlation_id)) {
-            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);
-          context_->flow_tracker->Begin(track_id, correlation_id);
-          break;
-        }
-        case kFlowStep: {
-          uint64_t correlation_id;
-          if (!cursor.ReadUint64(&correlation_id)) {
-            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);
-          context_->flow_tracker->Step(track_id, correlation_id);
-          break;
-        }
-        case kFlowEnd: {
-          uint64_t correlation_id;
-          if (!cursor.ReadUint64(&correlation_id)) {
-            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);
-          context_->flow_tracker->End(track_id, correlation_id, true, true);
+              name, correlation_id);
+          slices->End(ts, track_id, cat, name);
           break;
         }
       }
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h
index a0e39c2..581704d 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h
@@ -17,9 +17,9 @@
 #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/common/trace_parser.h"
 #include "src/trace_processor/importers/fuchsia/fuchsia_record.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_parser.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
index a78e896..ffc16eb 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
@@ -99,7 +99,7 @@
                            data.get() + size);
     return util::OkStatus();
   }
-  if (!leftover_bytes_.empty()) {
+  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.
@@ -392,9 +392,9 @@
           // 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)), base::StringView());
+          procs->SetProcessMetadata(static_cast<uint32_t>(obj_id),
+                                    base::Optional<uint32_t>(),
+                                    base::StringView(storage->GetString(name)));
           break;
         }
         case kZxObjTypeThread: {
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h
index 0881fd5..efec186 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h
@@ -17,10 +17,10 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_TOKENIZER_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_TOKENIZER_H_
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h
index f6f99d0..3af9649 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h
@@ -22,8 +22,8 @@
 #include <functional>
 
 #include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/importers/gzip/gzip_trace_parser.cc b/src/trace_processor/importers/gzip/gzip_trace_parser.cc
index bc42db3..89e8c1d 100644
--- a/src/trace_processor/importers/gzip/gzip_trace_parser.cc
+++ b/src/trace_processor/importers/gzip/gzip_trace_parser.cc
@@ -22,43 +22,26 @@
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/util/status_macros.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-namespace {
-
-using ResultCode = GzipDecompressor::ResultCode;
-
-}  // namespace
-
 GzipTraceParser::GzipTraceParser(TraceProcessorContext* context)
     : context_(context) {}
 
-GzipTraceParser::GzipTraceParser(std::unique_ptr<ChunkedTraceReader> reader)
-    : context_(nullptr), inner_(std::move(reader)) {}
-
 GzipTraceParser::~GzipTraceParser() = default;
 
 util::Status GzipTraceParser::Parse(std::unique_ptr<uint8_t[]> data,
                                     size_t size) {
-  return ParseUnowned(data.get(), size);
-}
-
-util::Status GzipTraceParser::ParseUnowned(const uint8_t* data, size_t size) {
-  const uint8_t* start = data;
+  uint8_t* start = data.get();
   size_t len = size;
 
   if (!inner_) {
-    PERFETTO_CHECK(context_);
     inner_.reset(new ForwardingTraceParser(context_));
-  }
 
-  if (!first_chunk_parsed_) {
     // .ctrace files begin with: "TRACE:\n" or "done. TRACE:\n" strip this if
     // present.
-    base::StringView beginning(reinterpret_cast<const char*>(start), size);
+    base::StringView beginning(reinterpret_cast<char*>(start), size);
 
     static const char* kSystraceFileHeader = "TRACE:\n";
     size_t offset = Find(kSystraceFileHeader, beginning);
@@ -66,49 +49,33 @@
       start += strlen(kSystraceFileHeader) + offset;
       len -= strlen(kSystraceFileHeader) + offset;
     }
-    first_chunk_parsed_ = true;
   }
+  decompressor_.SetInput(start, len);
 
   // Our default uncompressed buffer size is 32MB as it allows for good
   // throughput.
+  using ResultCode = GzipDecompressor::ResultCode;
   constexpr size_t kUncompressedBufferSize = 32 * 1024 * 1024;
 
-  needs_more_input_ = false;
-  decompressor_.SetInput(start, len);
-
   for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
-    if (!buffer_) {
-      buffer_.reset(new uint8_t[kUncompressedBufferSize]);
-      bytes_written_ = 0;
-    }
-
+    std::unique_ptr<uint8_t[]> buffer(new uint8_t[kUncompressedBufferSize]);
     auto result =
-        decompressor_.Decompress(buffer_.get() + bytes_written_,
-                                 kUncompressedBufferSize - bytes_written_);
+        decompressor_.Decompress(buffer.get(), kUncompressedBufferSize);
     ret = result.ret;
     if (ret == ResultCode::kError || ret == ResultCode::kNoProgress)
-      return util::ErrStatus("Failed to decompress trace chunk");
+      return util::ErrStatus("Unable to decompress gzip/ctrace trace");
+    if (ret == ResultCode::kNeedsMoreInput)
+      break;
 
-    if (ret == ResultCode::kNeedsMoreInput) {
-      PERFETTO_DCHECK(result.bytes_written == 0);
-      needs_more_input_ = true;
-      return util::OkStatus();
-    }
-    bytes_written_ += result.bytes_written;
-
-    if (bytes_written_ == kUncompressedBufferSize || ret == ResultCode::kEof)
-      RETURN_IF_ERROR(inner_->Parse(std::move(buffer_), bytes_written_));
+    util::Status status =
+        inner_->Parse(std::move(buffer), result.bytes_written);
+    if (!status.ok())
+      return status;
   }
   return util::OkStatus();
 }
 
-void GzipTraceParser::NotifyEndOfFile() {
-  // TODO(lalitm): this should really be an error returned to the caller but
-  // due to historical implementation, NotifyEndOfFile does not return a
-  // util::Status.
-  PERFETTO_DCHECK(!needs_more_input_);
-  PERFETTO_DCHECK(!buffer_);
-}
+void GzipTraceParser::NotifyEndOfFile() {}
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/gzip/gzip_trace_parser.h b/src/trace_processor/importers/gzip/gzip_trace_parser.h
index 82b4cd9..c83416e 100644
--- a/src/trace_processor/importers/gzip/gzip_trace_parser.h
+++ b/src/trace_processor/importers/gzip/gzip_trace_parser.h
@@ -17,7 +17,7 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_GZIP_GZIP_TRACE_PARSER_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_GZIP_GZIP_TRACE_PARSER_H_
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/importers/gzip/gzip_utils.h"
 
 namespace perfetto {
@@ -28,27 +28,16 @@
 class GzipTraceParser : public ChunkedTraceReader {
  public:
   explicit GzipTraceParser(TraceProcessorContext*);
-  explicit GzipTraceParser(std::unique_ptr<ChunkedTraceReader>);
   ~GzipTraceParser() override;
 
   // ChunkedTraceReader implementation
   util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
   void NotifyEndOfFile() override;
 
-  util::Status ParseUnowned(const uint8_t*, size_t);
-
-  bool needs_more_input() const { return needs_more_input_; }
-
  private:
   TraceProcessorContext* const context_;
   GzipDecompressor decompressor_;
   std::unique_ptr<ChunkedTraceReader> inner_;
-
-  std::unique_ptr<uint8_t[]> buffer_;
-  size_t bytes_written_ = 0;
-
-  bool first_chunk_parsed_ = false;
-  bool needs_more_input_ = false;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/gzip/gzip_utils.cc b/src/trace_processor/importers/gzip/gzip_utils.cc
index 8a30c7f..1edb9d0 100644
--- a/src/trace_processor/importers/gzip/gzip_utils.cc
+++ b/src/trace_processor/importers/gzip/gzip_utils.cc
@@ -18,7 +18,6 @@
 
 // For bazel build.
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
 #include <zlib.h>
@@ -71,9 +70,6 @@
   // compatible with other embedders.
   z_stream_->next_in = const_cast<uint8_t*>(data);
   z_stream_->avail_in = static_cast<uInt>(size);
-#else
-  base::ignore_result(data);
-  base::ignore_result(size);
 #endif
 }
 
@@ -102,8 +98,6 @@
       return Result{ResultCode::kOk, out_size - z_stream_->avail_out};
   }
 #else
-  base::ignore_result(out);
-  base::ignore_result(out_size);
   return Result{ResultCode::kError, 0};
 #endif
 }
diff --git a/src/trace_processor/importers/json/json_trace_parser.cc b/src/trace_processor/importers/json/json_trace_parser.cc
index eabd57d..37b6820 100644
--- a/src/trace_processor/importers/json/json_trace_parser.cc
+++ b/src/trace_processor/importers/json/json_trace_parser.cc
@@ -22,10 +22,8 @@
 #include <string>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
@@ -36,26 +34,6 @@
 namespace perfetto {
 namespace trace_processor {
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-namespace {
-
-base::Optional<uint64_t> MaybeExtractFlowIdentifier(const Json::Value& value,
-                                                    bool version2) {
-  std::string id_key = (version2 ? "bind_id" : "id");
-  if (!value.isMember(id_key))
-    return base::nullopt;
-  auto id = value[id_key];
-  if (id.isNumeric())
-    return id.asUInt64();
-  if (!id.isString())
-    return base::nullopt;
-  const char* c_string = id.asCString();
-  return base::CStringToUInt64(c_string, 16);
-}
-
-}  // namespace
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-
 JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
     : context_(context), systrace_line_parser_(context) {}
 
@@ -79,18 +57,12 @@
     return;
   }
 
-  auto opt_value = json::ParseJsonString(base::StringView(ttp.json_value));
-  if (!opt_value) {
-    context_->storage->IncrementStats(stats::json_parser_failure);
-    return;
-  }
+  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();
-  FlowTracker* flow_tracker = context_->flow_tracker.get();
 
-  const Json::Value& value = *opt_value;
   auto& ph = value["ph"];
   if (!ph.isString())
     return;
@@ -129,7 +101,6 @@
     case 'B': {  // TRACE_EVENT_BEGIN.
       TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
       slice_tracker->Begin(timestamp, track_id, cat_id, name_id, args_inserter);
-      MaybeAddFlow(track_id, value);
       break;
     }
     case 'E': {  // TRACE_EVENT_END.
@@ -145,49 +116,6 @@
       TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
       slice_tracker->Scoped(timestamp, track_id, cat_id, name_id,
                             opt_dur.value(), args_inserter);
-      MaybeAddFlow(track_id, value);
-      break;
-    }
-    case 's': {  // TRACE_EVENT_FLOW_START
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      auto opt_source_id =
-          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
-      if (opt_source_id) {
-        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
-            opt_source_id.value(), cat_id, name_id);
-        flow_tracker->Begin(track_id, flow_id);
-      } else {
-        context_->storage->IncrementStats(stats::flow_invalid_id);
-      }
-      break;
-    }
-    case 't': {  // TRACE_EVENT_FLOW_STEP
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      auto opt_source_id =
-          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
-      if (opt_source_id) {
-        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
-            opt_source_id.value(), cat_id, name_id);
-        flow_tracker->Step(track_id, flow_id);
-      } else {
-        context_->storage->IncrementStats(stats::flow_invalid_id);
-      }
-      break;
-    }
-    case 'f': {  // TRACE_EVENT_FLOW_END
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      auto opt_source_id =
-          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
-      if (opt_source_id) {
-        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
-            opt_source_id.value(), cat_id, name_id);
-        bool bind_enclosing_slice =
-            value.isMember("bp") && strcmp(value["bp"].asCString(), "e") == 0;
-        flow_tracker->End(track_id, flow_id, bind_enclosing_slice,
-                          /* close_flow = */ false);
-      } else {
-        context_->storage->IncrementStats(stats::flow_invalid_id);
-      }
       break;
     }
     case 'M': {  // Metadata events (process and thread names).
@@ -195,15 +123,13 @@
           !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,
-                                ThreadNamePriority::kOther);
+        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,
-                                  base::StringView());
+        procs->SetProcessMetadata(pid, base::nullopt, proc_name);
         break;
       }
     }
@@ -216,29 +142,6 @@
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
 }
 
-void JsonTraceParser::MaybeAddFlow(TrackId track_id, const Json::Value& event) {
-  PERFETTO_DCHECK(json::IsJsonSupported());
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-  auto opt_bind_id = MaybeExtractFlowIdentifier(event, /* version2 = */ true);
-  if (opt_bind_id) {
-    FlowTracker* flow_tracker = context_->flow_tracker.get();
-    bool flow_out = event.isMember("flow_out") && event["flow_out"].asBool();
-    bool flow_in = event.isMember("flow_in") && event["flow_in"].asBool();
-    if (flow_in && flow_out) {
-      flow_tracker->Step(track_id, opt_bind_id.value());
-    } else if (flow_out) {
-      flow_tracker->Begin(track_id, opt_bind_id.value());
-    } else if (flow_in) {
-      // bind_enclosing_slice is always true for v2 flow events
-      flow_tracker->End(track_id, opt_bind_id.value(), true,
-                        /* close_flow = */ false);
-    } else {
-      context_->storage->IncrementStats(stats::flow_without_direction);
-    }
-  }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
 
diff --git a/src/trace_processor/importers/json/json_trace_parser.h b/src/trace_processor/importers/json/json_trace_parser.h
index 2084c4b..b2f7cc4 100644
--- a/src/trace_processor/importers/json/json_trace_parser.h
+++ b/src/trace_processor/importers/json/json_trace_parser.h
@@ -23,10 +23,10 @@
 #include <tuple>
 #include <unordered_map>
 
-#include "src/trace_processor/importers/common/trace_parser.h"
 #include "src/trace_processor/importers/json/json_tracker.h"
 #include "src/trace_processor/importers/systrace/systrace_line_parser.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_parser.h"
 
 namespace Json {
 class Value;
@@ -51,8 +51,6 @@
  private:
   TraceProcessorContext* const context_;
   SystraceLineParser systrace_line_parser_;
-
-  void MaybeAddFlow(TrackId track_id, const Json::Value& event);
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer.cc b/src/trace_processor/importers/json/json_trace_tokenizer.cc
index cdf7020..329d05f 100644
--- a/src/trace_processor/importers/json/json_trace_tokenizer.cc
+++ b/src/trace_processor/importers/json/json_trace_tokenizer.cc
@@ -14,19 +14,17 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
 
-#include <memory>
+#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/string_utils.h"
 
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/json/json_tracker.h"
 #include "src/trace_processor/importers/json/json_utils.h"
 #include "src/trace_processor/storage/stats.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/util/status_macros.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -34,7 +32,6 @@
 namespace {
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-
 util::Status AppendUnescapedCharacter(char c,
                                       bool is_escaping,
                                       std::string* key) {
@@ -102,15 +99,14 @@
   }
   return ReadStringRes::kNeedsMoreData;
 }
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+#endif
 
 }  // namespace
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
 ReadDictRes ReadOneJsonDict(const char* start,
                             const char* end,
-                            base::StringView* value,
+                            Json::Value* value,
                             const char** next) {
   int braces = 0;
   int square_brackets = 0;
@@ -144,7 +140,12 @@
       if (--braces > 0)
         continue;
       size_t len = static_cast<size_t>((s + 1) - dict_begin);
-      *value = base::StringView(dict_begin, len);
+      auto opt_value = json::ParseJsonString(base::StringView(dict_begin, len));
+      if (!opt_value) {
+        PERFETTO_ELOG("Error while parsing JSON string during tokenization");
+        return ReadDictRes::kFatalError;
+      }
+      *value = std::move(*opt_value);
       *next = s + 1;
       return ReadDictRes::kFoundDict;
     }
@@ -177,6 +178,7 @@
   };
 
   NextToken next_token = NextToken::kStringOrEndOfDict;
+  bool seen_comma = false;
   for (const char* s = start; s < end; s++) {
     // Whitespace characters anywhere can be skipped.
     if (isspace(*s))
@@ -192,8 +194,13 @@
         }
 
         // If we see a comma separator, just ignore it.
-        if (*s == ',')
+        if (*s == ',') {
+          if (!seen_comma)
+            continue;
+
+          seen_comma = true;
           continue;
+        }
 
         // If we see anything else but a quote character here, this cannot be a
         // valid key.
@@ -218,123 +225,13 @@
         next_token = NextToken::kValue;
         break;
       case NextToken::kValue:
-        // Allowed value starting chars: [ { digit - "
-        // Also allowed: true, false, null. For simplicities sake, we only check
-        // against the first character as we're not trying to be super accurate.
-        if (*s == '[' || *s == '{' || isdigit(*s) || *s == '-' || *s == '"' ||
-            *s == 't' || *s == 'f' || *s == 'n') {
-          *next = s;
-          return ReadKeyRes::kFoundKey;
-        }
-        return ReadKeyRes::kFatalError;
+        *next = s;
+        return ReadKeyRes::kFoundKey;
     }
   }
   return ReadKeyRes::kNeedsMoreData;
 }
 
-util::Status ExtractValueForJsonKey(base::StringView dict,
-                                    const std::string& key,
-                                    base::Optional<std::string>* value) {
-  PERFETTO_DCHECK(dict.size() >= 2);
-
-  const char* start = dict.data();
-  const char* end = dict.data() + dict.size();
-
-  enum ExtractValueState {
-    kBeforeDict,
-    kInsideDict,
-    kAfterDict,
-  };
-
-  ExtractValueState state = kBeforeDict;
-  for (const char* s = start; s < end;) {
-    if (isspace(*s)) {
-      ++s;
-      continue;
-    }
-
-    if (state == kBeforeDict) {
-      if (*s == '{') {
-        ++s;
-        state = kInsideDict;
-        continue;
-      }
-      return util::ErrStatus("Unexpected character before JSON dict");
-    }
-
-    if (state == kAfterDict)
-      return util::ErrStatus("Unexpected character after JSON dict");
-
-    PERFETTO_DCHECK(state == kInsideDict);
-    PERFETTO_DCHECK(s < end);
-
-    if (*s == '}') {
-      ++s;
-      state = kAfterDict;
-      continue;
-    }
-
-    std::string current_key;
-    auto res = ReadOneJsonKey(s, end, &current_key, &s);
-    if (res == ReadKeyRes::kEndOfDictionary)
-      break;
-
-    if (res == ReadKeyRes::kFatalError)
-      return util::ErrStatus("Failure parsing JSON: encountered fatal error");
-
-    if (res == ReadKeyRes::kNeedsMoreData) {
-      return util::ErrStatus("Failure parsing JSON: partial JSON dictionary");
-    }
-
-    PERFETTO_DCHECK(res == ReadKeyRes::kFoundKey);
-
-    if (*s == '[') {
-      return util::ErrStatus(
-          "Failure parsing JSON: unsupported JSON dictionary with array");
-    }
-
-    std::string value_str;
-    if (*s == '{') {
-      base::StringView dict_str;
-      ReadDictRes dict_res = ReadOneJsonDict(s, end, &dict_str, &s);
-      if (dict_res == ReadDictRes::kNeedsMoreData ||
-          dict_res == ReadDictRes::kEndOfArray ||
-          dict_res == ReadDictRes::kEndOfTrace) {
-        return util::ErrStatus(
-            "Failure parsing JSON: unable to parse dictionary");
-      }
-      value_str = dict_str.ToStdString();
-    } else if (*s == '"') {
-      auto str_res = ReadOneJsonString(s + 1, end, &value_str, &s);
-      if (str_res == ReadStringRes::kNeedsMoreData ||
-          str_res == ReadStringRes::kFatalError) {
-        return util::ErrStatus("Failure parsing JSON: unable to parse string");
-      }
-    } else {
-      const char* value_start = s;
-      const char* value_end = end;
-      for (; s < end; ++s) {
-        if (*s == ',' || isspace(*s) || *s == '}') {
-          value_end = s;
-          break;
-        }
-      }
-      value_str = std::string(value_start, value_end);
-    }
-
-    if (key == current_key) {
-      *value = value_str;
-      return util::OkStatus();
-    }
-  }
-
-  if (state != kAfterDict)
-    return util::ErrStatus("Failure parsing JSON: malformed dictionary");
-
-  *value = base::nullopt;
-  return util::OkStatus();
-}
-
 ReadSystemLineRes ReadOneSystemTraceLine(const char* start,
                                          const char* end,
                                          std::string* line,
@@ -365,7 +262,7 @@
   }
   return ReadSystemLineRes::kNeedsMoreData;
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+#endif
 
 JsonTraceTokenizer::JsonTraceTokenizer(TraceProcessorContext* ctx)
     : context_(ctx) {}
@@ -403,7 +300,7 @@
     }
     if (next == end) {
       return util::ErrStatus(
-          "Failure parsing JSON: first chunk has only whitespace");
+          "Failed to parse: first chunk has only whitespace");
     }
 
     // Trace could begin in any of these ways:
@@ -412,7 +309,7 @@
     // [{
     if (*next != '{' && *next != '[') {
       return util::ErrStatus(
-          "Failure parsing JSON: first non-whitespace character is not [ or {");
+          "Failed to parse: first non-whitespace character is not [ or {");
     }
 
     // Figure out the format of the JSON file based on the first non-whitespace
@@ -444,7 +341,7 @@
   perfetto::base::ignore_result(position_);
   perfetto::base::ignore_result(offset_);
   return util::ErrStatus("Cannot parse JSON trace due to missing JSON support");
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+#endif
 }
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
@@ -460,13 +357,13 @@
     case TracePosition::kDictionaryKey: {
       if (format_ != TraceFormat::kOuterDictionary) {
         return util::ErrStatus(
-            "Failure parsing JSON: illegal format when parsing dictionary key");
+            "Failed to parse: illegal JSON format when parsing dictionary key");
       }
 
       std::string key;
       auto res = ReadOneJsonKey(start, end, &key, &next);
       if (res == ReadKeyRes::kFatalError)
-        return util::ErrStatus("Failure parsing JSON: encountered fatal error");
+        return util::ErrStatus("Encountered fatal error while parsing JSON");
 
       if (res == ReadKeyRes::kEndOfDictionary ||
           res == ReadKeyRes::kNeedsMoreData) {
@@ -482,16 +379,6 @@
       } else if (key == "metadata") {
         position_ = TracePosition::kWaitingForMetadataDictionary;
         return ParseInternal(next + 1, end, out);
-      } else if (key == "displayTimeUnit") {
-        std::string time_unit;
-        auto string_res = ReadOneJsonString(next + 1, end, &time_unit, &next);
-        if (string_res == ReadStringRes::kFatalError)
-          return util::ErrStatus("Could not parse displayTimeUnit");
-        if (string_res == ReadStringRes::kNeedsMoreData)
-          return util::ErrStatus("displayTimeUnit too large");
-        if (time_unit != "ms" && time_unit != "ns")
-          return util::ErrStatus("displayTimeUnit unknown");
-        return ParseInternal(next, end, out);
       } else {
         // If we don't recognize the key, just ignore the rest of the trace and
         // go to EOF.
@@ -503,15 +390,14 @@
     case TracePosition::kSystemTraceEventsString: {
       if (format_ != TraceFormat::kOuterDictionary) {
         return util::ErrStatus(
-            "Failure parsing JSON: illegal format when parsing system events");
+            "Failed to parse: illegal JSON format when parsing system events");
       }
 
       while (next < end) {
         std::string raw_line;
         auto res = ReadOneSystemTraceLine(next, end, &raw_line, &next);
         if (res == ReadSystemLineRes::kFatalError)
-          return util::ErrStatus(
-              "Failure parsing JSON: encountered fatal error");
+          return util::ErrStatus("Encountered fatal error while parsing JSON");
 
         if (res == ReadSystemLineRes::kNeedsMoreData)
           break;
@@ -536,13 +422,13 @@
     case TracePosition::kWaitingForMetadataDictionary: {
       if (format_ != TraceFormat::kOuterDictionary) {
         return util::ErrStatus(
-            "Failure parsing JSON: illegal format when parsing metadata");
+            "Failed to parse: illegal JSON format when parsing metadata");
       }
 
-      base::StringView unparsed;
-      const auto res = ReadOneJsonDict(next, end, &unparsed, &next);
-      if (res == ReadDictRes::kEndOfArray)
-        return util::ErrStatus("Failure parsing JSON: encountered fatal error");
+      std::unique_ptr<Json::Value> value(new Json::Value());
+      const auto res = ReadOneJsonDict(next, end, value.get(), &next);
+      if (res == ReadDictRes::kFatalError || res == ReadDictRes::kEndOfArray)
+        return util::ErrStatus("Encountered fatal error while parsing JSON");
       if (res == ReadDictRes::kEndOfTrace ||
           res == ReadDictRes::kNeedsMoreData) {
         break;
@@ -554,8 +440,10 @@
     }
     case TracePosition::kTraceEventsArray: {
       while (next < end) {
-        base::StringView unparsed;
-        const auto res = ReadOneJsonDict(next, end, &unparsed, &next);
+        std::unique_ptr<Json::Value> value(new Json::Value());
+        const auto res = ReadOneJsonDict(next, end, value.get(), &next);
+        if (res == ReadDictRes::kFatalError)
+          return util::ErrStatus("Encountered fatal error while parsing JSON");
         if (res == ReadDictRes::kEndOfTrace ||
             res == ReadDictRes::kNeedsMoreData) {
           break;
@@ -568,23 +456,20 @@
           break;
         }
 
-        base::Optional<std::string> opt_raw_ts;
-        RETURN_IF_ERROR(ExtractValueForJsonKey(unparsed, "ts", &opt_raw_ts));
         base::Optional<int64_t> opt_ts =
-            opt_raw_ts ? json_tracker->CoerceToTs(*opt_raw_ts) : base::nullopt;
+            json_tracker->CoerceToTs((*value)["ts"]);
         int64_t ts = 0;
         if (opt_ts.has_value()) {
           ts = opt_ts.value();
         } else {
           // Metadata events may omit ts. In all other cases error:
-          base::Optional<std::string> opt_raw_ph;
-          RETURN_IF_ERROR(ExtractValueForJsonKey(unparsed, "ph", &opt_raw_ph));
-          if (!opt_raw_ph || *opt_raw_ph != "M") {
+          auto& ph = (*value)["ph"];
+          if (!ph.isString() || *ph.asCString() != 'M') {
             context_->storage->IncrementStats(stats::json_tokenizer_failure);
             continue;
           }
         }
-        trace_sorter->PushJsonValue(ts, unparsed.ToStdString());
+        trace_sorter->PushJsonValue(ts, std::move(value));
       }
       break;
     }
@@ -595,9 +480,10 @@
   *out = next;
   return util::OkStatus();
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+#endif
 
 void JsonTraceTokenizer::NotifyEndOfFile() {}
 
 }  // namespace trace_processor
 }  // namespace perfetto
+
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer.h b/src/trace_processor/importers/json/json_trace_tokenizer.h
index 86f5731..d69189f 100644
--- a/src/trace_processor/importers/json/json_trace_tokenizer.h
+++ b/src/trace_processor/importers/json/json_trace_tokenizer.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/importers/systrace/systrace_line_tokenizer.h"
 #include "src/trace_processor/storage/trace_storage.h"
 
@@ -39,6 +39,7 @@
   kNeedsMoreData,
   kEndOfTrace,
   kEndOfArray,
+  kFatalError,
 };
 
 // Parses at most one JSON dictionary and returns a pointer to the end of it,
@@ -49,7 +50,7 @@
 // Visible for testing.
 ReadDictRes ReadOneJsonDict(const char* start,
                             const char* end,
-                            base::StringView* value,
+                            Json::Value* value,
                             const char** next);
 
 enum class ReadKeyRes {
@@ -72,16 +73,6 @@
                           std::string* key,
                           const char** next);
 
-// Takes as input a JSON dictionary and returns the value associated with
-// the provided key (if it exists).
-// Implementation note: this method does not currently support dictionaries
-// which have arrays as JSON values because current users of this method
-// do not require this.
-// Visible for testing.
-util::Status ExtractValueForJsonKey(base::StringView dict,
-                                    const std::string& key,
-                                    base::Optional<std::string>* value);
-
 enum class ReadSystemLineRes {
   kFoundLine,
   kNeedsMoreData,
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc b/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc
index 051f52a..4bae1a7 100644
--- a/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc
+++ b/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc
@@ -18,7 +18,6 @@
 
 #include <json/value.h>
 
-#include "src/trace_processor/importers/json/json_utils.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
@@ -29,28 +28,24 @@
   const char* start = R"({ "foo": "bar" })";
   const char* end = start + strlen(start);
   const char* next = nullptr;
-  base::StringView value;
+  Json::Value value;
   ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
 
   ASSERT_EQ(result, ReadDictRes::kFoundDict);
   ASSERT_EQ(next, end);
-
-  Json::Value parsed = *json::ParseJsonString(value);
-  ASSERT_EQ(parsed["foo"].asString(), "bar");
+  ASSERT_EQ(value["foo"].asString(), "bar");
 }
 
 TEST(JsonTraceTokenizerTest, ReadDictQuotedBraces) {
   const char* start = R"({ "foo": "}\"bar{\\" })";
   const char* end = start + strlen(start);
   const char* next = nullptr;
-  base::StringView value;
+  Json::Value value;
   ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
 
   ASSERT_EQ(result, ReadDictRes::kFoundDict);
   ASSERT_EQ(next, end);
-
-  Json::Value parsed = *json::ParseJsonString(value);
-  ASSERT_EQ(parsed["foo"].asString(), "}\"bar{\\");
+  ASSERT_EQ(value["foo"].asString(), "}\"bar{\\");
 }
 
 TEST(JsonTraceTokenizerTest, ReadDictTwoDicts) {
@@ -58,33 +53,40 @@
   const char* middle = start + strlen(R"({"foo": 1})");
   const char* end = start + strlen(start);
   const char* next = nullptr;
-  base::StringView value;
+  Json::Value value;
 
   ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next),
             ReadDictRes::kFoundDict);
   ASSERT_EQ(next, middle);
-
-  Json::Value parsed = *json::ParseJsonString(value);
-  ASSERT_EQ(parsed["foo"].asInt(), 1);
+  ASSERT_EQ(value["foo"].asInt(), 1);
 
   ASSERT_EQ(ReadOneJsonDict(next, end, &value, &next), ReadDictRes::kFoundDict);
   ASSERT_EQ(next, end);
-
-  parsed = *json::ParseJsonString(value);
-  ASSERT_EQ(parsed["bar"].asInt(), 2);
+  ASSERT_EQ(value["bar"].asInt(), 2);
 }
 
 TEST(JsonTraceTokenizerTest, ReadDictNeedMoreData) {
   const char* start = R"({"foo": 1)";
   const char* end = start + strlen(start);
   const char* next = nullptr;
-  base::StringView value;
+  Json::Value value;
 
   ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next),
             ReadDictRes::kNeedsMoreData);
   ASSERT_EQ(next, nullptr);
 }
 
+TEST(JsonTraceTokenizerTest, ReadDictFatalError) {
+  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),
+            ReadDictRes::kFatalError);
+  ASSERT_EQ(next, nullptr);
+}
+
 TEST(JsonTraceTokenizerTest, ReadKeyIntValue) {
   const char* start = R"("Test": 01234, )";
   const char* middle = start + strlen(R"("Test": )");
@@ -225,53 +227,6 @@
   ASSERT_EQ(next, end);
 }
 
-TEST(JsonTraceTokenizerTest, ExtractValueForJsonKey) {
-  base::Optional<std::string> line;
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"({"ts": 149029})", "ts", &line).ok());
-  ASSERT_EQ(*line, "149029");
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"(
-    {
-      "lots_of": "whitespace"
-    }
-  )",
-                                     "lots_of", &line)
-                  .ok());
-  ASSERT_EQ(*line, "whitespace");
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"(
-    {
-      "lots_of": "whitespace"   ,     
-      "other": "value"
-    }
-  )",
-                                     "other", &line)
-                  .ok());
-  ASSERT_EQ(*line, "value");
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"({
-    "ts": 149029, "foo": "bar"
-  })",
-                                     "ts", &line)
-                  .ok());
-  ASSERT_EQ(*line, "149029");
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"({
-    "ts": 149029, "foo": "bar"
-  })",
-                                     "foo", &line)
-                  .ok());
-  ASSERT_EQ(*line, "bar");
-
-  ASSERT_TRUE(ExtractValueForJsonKey(R"({
-    "nested": {"ts": 149029, "foo": "bar"}
-  })",
-                                     "nested", &line)
-                  .ok());
-  ASSERT_EQ(*line, R"({"ts": 149029, "foo": "bar"})");
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/json/json_tracker.h b/src/trace_processor/importers/json/json_tracker.h
index d786bf1..ac24083 100644
--- a/src/trace_processor/importers/json/json_tracker.h
+++ b/src/trace_processor/importers/json/json_tracker.h
@@ -33,7 +33,7 @@
   JsonTracker(const JsonTracker&) = delete;
   JsonTracker& operator=(const JsonTracker&) = delete;
   explicit JsonTracker(TraceProcessorContext*);
-  ~JsonTracker() override;
+  virtual ~JsonTracker();
 
   static JsonTracker* GetOrCreate(TraceProcessorContext* context) {
     if (!context->json_tracker) {
diff --git a/src/trace_processor/importers/json/json_utils.cc b/src/trace_processor/importers/json/json_utils.cc
index 5d0b2d1..b9b1e65 100644
--- a/src/trace_processor/importers/json/json_utils.cc
+++ b/src/trace_processor/importers/json/json_utils.cc
@@ -22,7 +22,6 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
 #include <json/reader.h>
-#include "perfetto/ext/base/string_utils.h"
 #endif
 
 namespace perfetto {
@@ -52,26 +51,17 @@
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
   switch (static_cast<size_t>(value.type())) {
     case Json::realValue:
-      return static_cast<int64_t>(value.asDouble() *
-                                  static_cast<double>(TimeUnitToNs(unit)));
+      return static_cast<int64_t>(value.asDouble() * TimeUnitToNs(unit));
     case Json::uintValue:
     case Json::intValue:
       return value.asInt64() * TimeUnitToNs(unit);
     case Json::stringValue: {
       std::string s = value.asString();
-      size_t lhs_end = std::min<size_t>(s.find('.'), s.size());
-      size_t rhs_start = std::min<size_t>(lhs_end + 1, s.size());
-      base::Optional<int64_t> lhs = base::StringToInt64(s.substr(0, lhs_end));
-      base::Optional<double> rhs =
-          base::StringToDouble("0." + s.substr(rhs_start, std::string::npos));
-      if ((!lhs.has_value() && lhs_end > 0) ||
-          (!rhs.has_value() && rhs_start < s.size())) {
+      char* end;
+      int64_t n = strtoll(s.c_str(), &end, 10);
+      if (end != s.data() + s.size())
         return base::nullopt;
-      }
-      int64_t factor = TimeUnitToNs(unit);
-      return lhs.value_or(0) * factor +
-             static_cast<int64_t>(rhs.value_or(0) *
-                                  static_cast<double>(factor));
+      return n * TimeUnitToNs(unit);
     }
     default:
       return base::nullopt;
@@ -131,12 +121,10 @@
   PERFETTO_DCHECK(IsJsonSupported());
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-  Json::CharReaderBuilder b;
-  auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
-
+  Json::Reader reader;
   Json::Value value;
   const char* begin = raw_string.data();
-  return reader->parse(begin, begin + raw_string.size(), &value, nullptr)
+  return reader.parse(begin, begin + raw_string.size(), value)
              ? base::make_optional(std::move(value))
              : base::nullopt;
 #else
@@ -157,7 +145,7 @@
     auto it = value.begin();
     bool inserted = false;
     for (; it != value.end(); ++it) {
-      std::string child_name = it.name();
+      std::string child_name = it.memberName();
       std::string child_flat_key = flat_key.ToStdString() + "." + child_name;
       std::string child_key = key.ToStdString() + "." + child_name;
       inserted |=
diff --git a/src/trace_processor/importers/json/json_utils_unittest.cc b/src/trace_processor/importers/json/json_utils_unittest.cc
index a3846ea..4134cc6 100644
--- a/src/trace_processor/importers/json/json_utils_unittest.cc
+++ b/src/trace_processor/importers/json/json_utils_unittest.cc
@@ -46,20 +46,9 @@
   ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value(42)).value_or(-1), 42000);
   ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("42")).value_or(-1), 42000);
   ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value(42.1)).value_or(-1), 42100);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("42.1")).value_or(-1), 42100);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value(".42")).value_or(-1), 420);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("42.")).value_or(-1), 42000);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("42.0")).value_or(-1), 42000);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("0.2")).value_or(-1), 200);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value("0.2e-1")).value_or(-1), 20);
   ASSERT_EQ(CoerceToTs(TimeUnit::kNs, Json::Value(42)).value_or(-1), 42);
   ASSERT_EQ(CoerceToTs(TimeUnit::kMs, Json::Value(42)).value_or(-1), 42000000);
-  ASSERT_EQ(CoerceToTs(TimeUnit::kUs, Json::Value(".")).value_or(-1), 0);
   ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value("foo")).has_value());
-  ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value(".foo")).has_value());
-  ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value("0.foo")).has_value());
-  ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value("foo0.23")).has_value());
-  ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value("23.12foo")).has_value());
   ASSERT_FALSE(CoerceToTs(TimeUnit::kNs, Json::Value("1234!")).has_value());
   ASSERT_FALSE(CoerceToTs(TimeUnit::kUs, Json::Value("1234!")).has_value());
   ASSERT_FALSE(CoerceToTs(TimeUnit::kMs, Json::Value("1234!")).has_value());
diff --git a/src/trace_processor/importers/memory_tracker/BUILD.gn b/src/trace_processor/importers/memory_tracker/BUILD.gn
deleted file mode 100644
index 4ac6669..0000000
--- a/src/trace_processor/importers/memory_tracker/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../../gn/perfetto.gni")
-
-source_set("graph_processor") {
-  deps = [ "../../../../gn:default_deps" ]
-  public_deps = [
-    "../../../../include/perfetto/base",
-    "../../../../include/perfetto/ext/base",
-    "../../../../include/perfetto/ext/trace_processor/importers/memory_tracker",
-  ]
-  sources = [
-    "graph.cc",
-    "graph_processor.cc",
-    "memory_allocator_node_id.cc",
-    "raw_memory_graph_node.cc",
-    "raw_process_memory_node.cc",
-  ]
-}
diff --git a/src/trace_processor/importers/memory_tracker/graph.cc b/src/trace_processor/importers/memory_tracker/graph.cc
deleted file mode 100644
index d156da6..0000000
--- a/src/trace_processor/importers/memory_tracker/graph.cc
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-using Edge = GlobalNodeGraph::Edge;
-using PostOrderIterator = GlobalNodeGraph::PostOrderIterator;
-using PreOrderIterator = GlobalNodeGraph::PreOrderIterator;
-using Process = GlobalNodeGraph::Process;
-using Node = GlobalNodeGraph::Node;
-using perfetto::base::SplitString;
-
-}  // namespace
-
-GlobalNodeGraph::GlobalNodeGraph()
-    : shared_memory_graph_(
-          std::unique_ptr<Process>(new Process(kNullProcessId, this))) {}
-GlobalNodeGraph::~GlobalNodeGraph() {}
-
-Process* GlobalNodeGraph::CreateGraphForProcess(
-    base::PlatformProcessId process_id) {
-  auto id_to_node_iterator = process_node_graphs_.emplace(
-      process_id, std::unique_ptr<Process>(new Process(process_id, this)));
-  return id_to_node_iterator.first->second.get();
-}
-
-void GlobalNodeGraph::AddNodeOwnershipEdge(Node* owner,
-                                           Node* owned,
-                                           int importance) {
-  all_edges_.emplace_front(owner, owned, importance);
-  Edge* edge = &*all_edges_.begin();
-  owner->SetOwnsEdge(edge);
-  owned->AddOwnedByEdge(edge);
-}
-
-Node* GlobalNodeGraph::CreateNode(Process* process_graph, Node* parent) {
-  all_nodes_.emplace_front(process_graph, parent);
-  return &*all_nodes_.begin();
-}
-
-PreOrderIterator GlobalNodeGraph::VisitInDepthFirstPreOrder() {
-  std::vector<Node*> roots;
-  for (auto it = process_node_graphs_.rbegin();
-       it != process_node_graphs_.rend(); it++) {
-    roots.push_back(it->second->root());
-  }
-  roots.push_back(shared_memory_graph_->root());
-  return PreOrderIterator{std::move(roots)};
-}
-
-PostOrderIterator GlobalNodeGraph::VisitInDepthFirstPostOrder() {
-  std::vector<Node*> roots;
-  for (auto it = process_node_graphs_.rbegin();
-       it != process_node_graphs_.rend(); it++) {
-    roots.push_back(it->second->root());
-  }
-  roots.push_back(shared_memory_graph_->root());
-  return PostOrderIterator(std::move(roots));
-}
-
-Process::Process(base::PlatformProcessId pid, GlobalNodeGraph* global_graph)
-    : pid_(pid),
-      global_graph_(global_graph),
-      root_(global_graph->CreateNode(this, nullptr)) {}
-Process::~Process() {}
-
-Node* Process::CreateNode(MemoryAllocatorNodeId id,
-                          const std::string& path,
-                          bool weak) {
-  auto tokens = base::SplitString(path, "/");
-
-  // Perform a tree traversal, creating the nodes if they do not
-  // already exist on the path to the child.
-  Node* current = root_;
-  for (const auto& key : tokens) {
-    Node* parent = current;
-    current = current->GetChild(key);
-    if (!current) {
-      current = global_graph_->CreateNode(this, parent);
-      parent->InsertChild(key, current);
-    }
-  }
-
-  // The final node should have the weakness specified by the
-  // argument and also be considered explicit.
-  current->set_weak(weak);
-  current->set_explicit(true);
-
-  // The final node should also have the associated |id|.
-  current->set_id(id);
-
-  // Add to the global id map as well if it exists.
-  if (!id.empty())
-    global_graph_->nodes_by_id_.emplace(id, current);
-
-  return current;
-}
-
-Node* Process::FindNode(const std::string& path) {
-  auto tokens = base::SplitString(path, "/");
-
-  Node* current = root_;
-  for (const auto& key : tokens) {
-    current = current->GetChild(key);
-    if (!current)
-      return nullptr;
-  }
-  return current;
-}
-
-Node::Node(Process* node_graph, Node* parent)
-    : node_graph_(node_graph), parent_(parent), owns_edge_(nullptr) {}
-Node::~Node() {}
-
-Node* Node::GetChild(const std::string& name) const {
-  auto child = children_.find(name);
-  return child == children_.end() ? nullptr : child->second;
-}
-
-void Node::InsertChild(const std::string& name, Node* node) {
-  PERFETTO_DCHECK(node);
-  children_.emplace(name, node);
-}
-
-Node* Node::CreateChild(const std::string& name) {
-  Node* new_child = node_graph_->global_graph()->CreateNode(node_graph_, this);
-  InsertChild(name, new_child);
-  return new_child;
-}
-
-bool Node::IsDescendentOf(const Node& possible_parent) const {
-  const Node* current = this;
-  while (current != nullptr) {
-    if (current == &possible_parent)
-      return true;
-    current = current->parent();
-  }
-  return false;
-}
-
-void Node::AddOwnedByEdge(Edge* edge) {
-  owned_by_edges_.push_back(edge);
-}
-
-void Node::SetOwnsEdge(Edge* owns_edge) {
-  owns_edge_ = owns_edge;
-}
-
-void Node::AddEntry(const std::string& name,
-                    Node::Entry::ScalarUnits units,
-                    uint64_t value) {
-  entries_.emplace(name, Node::Entry(units, value));
-}
-
-void Node::AddEntry(const std::string& name, const std::string& value) {
-  entries_.emplace(name, Node::Entry(value));
-}
-
-Node::Entry::Entry(Entry::ScalarUnits units2, uint64_t value)
-    : type(Node::Entry::Type::kUInt64), units(units2), value_uint64(value) {}
-
-Node::Entry::Entry(const std::string& value)
-    : type(Node::Entry::Type::kString),
-      units(Node::Entry::ScalarUnits::kObjects),
-      value_string(value),
-      value_uint64(0) {}
-
-Edge::Edge(Node* source, Node* target, int priority)
-    : source_(source), target_(target), priority_(priority) {}
-
-PreOrderIterator::PreOrderIterator(std::vector<Node*>&& roots)
-    : to_visit_(std::move(roots)) {}
-PreOrderIterator::PreOrderIterator(PreOrderIterator&& other) = default;
-PreOrderIterator::~PreOrderIterator() {}
-
-// Yields the next node in the DFS post-order traversal.
-Node* PreOrderIterator::next() {
-  while (!to_visit_.empty()) {
-    // Retain a pointer to the node at the top and remove it from stack.
-    Node* node = to_visit_.back();
-    to_visit_.pop_back();
-
-    // If the node has already been visited, don't visit it again.
-    if (visited_.count(node) != 0)
-      continue;
-
-    // If we haven't visited the node which this node owns then wait for that.
-    if (node->owns_edge() && visited_.count(node->owns_edge()->target()) == 0)
-      continue;
-
-    // If we haven't visited the node's parent then wait for that.
-    if (node->parent() && visited_.count(node->parent()) == 0)
-      continue;
-
-    // Visit all children of this node.
-    for (auto it = node->children()->rbegin(); it != node->children()->rend();
-         it++) {
-      to_visit_.push_back(it->second);
-    }
-
-    // Visit all owners of this node.
-    for (auto it = node->owned_by_edges()->rbegin();
-         it != node->owned_by_edges()->rend(); it++) {
-      to_visit_.push_back((*it)->source());
-    }
-
-    // Add this node to the visited set.
-    visited_.insert(node);
-    return node;
-  }
-  return nullptr;
-}
-
-PostOrderIterator::PostOrderIterator(std::vector<Node*>&& roots)
-    : to_visit_(std::move(roots)) {}
-PostOrderIterator::PostOrderIterator(PostOrderIterator&& other) = default;
-PostOrderIterator::~PostOrderIterator() = default;
-
-// Yields the next node in the DFS post-order traversal.
-Node* PostOrderIterator::next() {
-  while (!to_visit_.empty()) {
-    // Retain a pointer to the node at the top and remove it from stack.
-    Node* node = to_visit_.back();
-    to_visit_.pop_back();
-
-    // If the node has already been visited, don't visit it again.
-    if (visited_.count(node) != 0)
-      continue;
-
-    // If the node is at the top of the path, we have already looked
-    // at its children and owners.
-    if (!path_.empty() && path_.back() == node) {
-      // Mark the current node as visited so we don't visit again.
-      visited_.insert(node);
-
-      // The current node is no longer on the path.
-      path_.pop_back();
-
-      return node;
-    }
-
-    // If the node is not at the front, it should also certainly not be
-    // anywhere else in the path. If it is, there is a cycle in the graph.
-    path_.push_back(node);
-
-    // Add this node back to the queue of nodes to visit.
-    to_visit_.push_back(node);
-
-    // Visit all children of this node.
-    for (auto it = node->children()->rbegin(); it != node->children()->rend();
-         it++) {
-      to_visit_.push_back(it->second);
-    }
-
-    // Visit all owners of this node.
-    for (auto it = node->owned_by_edges()->rbegin();
-         it != node->owned_by_edges()->rend(); it++) {
-      to_visit_.push_back((*it)->source());
-    }
-  }
-  return nullptr;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/graph_processor.cc b/src/trace_processor/importers/memory_tracker/graph_processor.cc
deleted file mode 100644
index 85dc9ad..0000000
--- a/src/trace_processor/importers/memory_tracker/graph_processor.cc
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
-
-#include <list>
-
-namespace perfetto {
-namespace trace_processor {
-
-using Edge = GlobalNodeGraph::Edge;
-using Node = GlobalNodeGraph::Node;
-using Process = GlobalNodeGraph::Process;
-
-namespace {
-
-const char kSharedMemoryRootNode[] = "shared_memory";
-const char kSizeEntryName[] = "size";
-const char kEffectiveSizeEntryName[] = "effective_size";
-
-Node::Entry::ScalarUnits EntryUnitsFromString(const std::string& units) {
-  if (units == RawMemoryGraphNode::kUnitsBytes) {
-    return Node::Entry::ScalarUnits::kBytes;
-  } else if (units == RawMemoryGraphNode::kUnitsObjects) {
-    return Node::Entry::ScalarUnits::kObjects;
-  } else {
-    // Invalid units so we just return a value of the correct type.
-    return Node::Entry::ScalarUnits::kObjects;
-  }
-}
-
-base::Optional<uint64_t> GetSizeEntryOfNode(Node* node) {
-  auto size_it = node->entries()->find(kSizeEntryName);
-  if (size_it == node->entries()->end())
-    return base::nullopt;
-
-  PERFETTO_DCHECK(size_it->second.type == Node::Entry::Type::kUInt64);
-  PERFETTO_DCHECK(size_it->second.units == Node::Entry::ScalarUnits::kBytes);
-  return base::Optional<uint64_t>(size_it->second.value_uint64);
-}
-
-}  // namespace
-
-// static
-std::unique_ptr<GlobalNodeGraph> GraphProcessor::CreateMemoryGraph(
-    const GraphProcessor::RawMemoryNodeMap& process_nodes) {
-  auto global_graph = std::unique_ptr<GlobalNodeGraph>(new GlobalNodeGraph());
-
-  // First pass: collects allocator nodes into a graph and populate
-  // with entries.
-  for (const auto& pid_to_node : process_nodes) {
-    // There can be null entries in the map; simply filter these out.
-    if (!pid_to_node.second)
-      continue;
-
-    auto* graph = global_graph->CreateGraphForProcess(pid_to_node.first);
-    CollectAllocatorNodes(*pid_to_node.second, global_graph.get(), graph);
-  }
-
-  // Second pass: generate the graph of edges between the nodes.
-  for (const auto& pid_to_node : process_nodes) {
-    // There can be null entries in the map; simply filter these out.
-    if (!pid_to_node.second)
-      continue;
-
-    AddEdges(*pid_to_node.second, global_graph.get());
-  }
-
-  return global_graph;
-}
-
-// static
-void GraphProcessor::RemoveWeakNodesFromGraph(GlobalNodeGraph* global_graph) {
-  auto* global_root = global_graph->shared_memory_graph()->root();
-
-  // Third pass: mark recursively nodes as weak if they don't have an associated
-  // node and all their children are weak.
-  MarkImplicitWeakParentsRecursively(global_root);
-  for (const auto& pid_to_process : global_graph->process_node_graphs()) {
-    MarkImplicitWeakParentsRecursively(pid_to_process.second->root());
-  }
-
-  // Fourth pass: recursively mark nodes as weak if they own a node which is
-  // weak or if they have a parent who is weak.
-  {
-    std::set<const Node*> visited;
-    MarkWeakOwnersAndChildrenRecursively(global_root, &visited);
-    for (const auto& pid_to_process : global_graph->process_node_graphs()) {
-      MarkWeakOwnersAndChildrenRecursively(pid_to_process.second->root(),
-                                           &visited);
-    }
-  }
-
-  // Fifth pass: remove all nodes which are weak (including their descendants)
-  // and clean owned by edges to match.
-  RemoveWeakNodesRecursively(global_root);
-  for (const auto& pid_to_process : global_graph->process_node_graphs()) {
-    RemoveWeakNodesRecursively(pid_to_process.second->root());
-  }
-}
-
-// static
-void GraphProcessor::AddOverheadsAndPropagateEntries(
-    GlobalNodeGraph* global_graph) {
-  // Sixth pass: account for tracing overhead in system memory allocators.
-  for (auto& pid_to_process : global_graph->process_node_graphs()) {
-    Process* process = pid_to_process.second.get();
-    if (process->FindNode("winheap")) {
-      AssignTracingOverhead("winheap", global_graph,
-                            pid_to_process.second.get());
-    } else if (process->FindNode("malloc")) {
-      AssignTracingOverhead("malloc", global_graph,
-                            pid_to_process.second.get());
-    }
-  }
-
-  // Seventh pass: aggregate non-size integer entries into parents and propagate
-  // string and int entries for shared graph.
-  auto* global_root = global_graph->shared_memory_graph()->root();
-  AggregateNumericsRecursively(global_root);
-  PropagateNumericsAndDiagnosticsRecursively(global_root);
-  for (auto& pid_to_process : global_graph->process_node_graphs()) {
-    AggregateNumericsRecursively(pid_to_process.second->root());
-  }
-}
-
-// static
-void GraphProcessor::CalculateSizesForGraph(GlobalNodeGraph* global_graph) {
-  // Eighth pass: calculate the size field for nodes by considering the sizes
-  // of their children and owners.
-  {
-    auto it = global_graph->VisitInDepthFirstPostOrder();
-    while (Node* node = it.next()) {
-      CalculateSizeForNode(node);
-    }
-  }
-
-  // Ninth pass: Calculate not-owned and not-owning sub-sizes of all nodes.
-  {
-    auto it = global_graph->VisitInDepthFirstPostOrder();
-    while (Node* node = it.next()) {
-      CalculateNodeSubSizes(node);
-    }
-  }
-
-  // Tenth pass: Calculate owned and owning coefficients of owned and owner
-  // nodes.
-  {
-    auto it = global_graph->VisitInDepthFirstPostOrder();
-    while (Node* node = it.next()) {
-      CalculateNodeOwnershipCoefficient(node);
-    }
-  }
-
-  // Eleventh pass: Calculate cumulative owned and owning coefficients of all
-  // nodes.
-  {
-    auto it = global_graph->VisitInDepthFirstPreOrder();
-    while (Node* node = it.next()) {
-      CalculateNodeCumulativeOwnershipCoefficient(node);
-    }
-  }
-
-  // Twelfth pass: Calculate the effective sizes of all nodes.
-  {
-    auto it = global_graph->VisitInDepthFirstPostOrder();
-    while (Node* node = it.next()) {
-      CalculateNodeEffectiveSize(node);
-    }
-  }
-}
-
-// static
-std::map<base::PlatformProcessId, uint64_t>
-GraphProcessor::ComputeSharedFootprintFromGraph(
-    const GlobalNodeGraph& global_graph) {
-  // Go through all nodes associated with global nodes and find if they are
-  // owned by shared memory nodes.
-  Node* global_root =
-      global_graph.shared_memory_graph()->root()->GetChild("global");
-
-  // If there are no global nodes then just return an empty map with no data.
-  if (!global_root)
-    return std::map<base::PlatformProcessId, uint64_t>();
-
-  struct GlobalNodeOwners {
-    std::list<Edge*> edges;
-    int max_priority = 0;
-  };
-
-  std::map<Node*, GlobalNodeOwners> global_node_to_shared_owners;
-  for (const auto& path_to_child : *global_root->children()) {
-    // The path of this node is something like "global/foo".
-    Node* global_node = path_to_child.second;
-
-    // If there's no size to attribute, there's no point in propagating
-    // anything.
-    if (global_node->entries()->count(kSizeEntryName) == 0)
-      continue;
-
-    for (auto* edge : *global_node->owned_by_edges()) {
-      // Find if the source node's path starts with "shared_memory/" which
-      // indcates shared memory.
-      Node* source_root = edge->source()->node_graph()->root();
-      const Node* current = edge->source();
-      PERFETTO_DCHECK(current != source_root);
-
-      // Traverse up until we hit the point where |current| holds a node which
-      // is the child of |source_root|.
-      while (current->parent() != source_root)
-        current = current->parent();
-
-      // If the source is indeed a shared memory node, add the edge to the map.
-      if (source_root->GetChild(kSharedMemoryRootNode) == current) {
-        GlobalNodeOwners* owners = &global_node_to_shared_owners[global_node];
-        owners->edges.push_back(edge);
-        owners->max_priority = std::max(owners->max_priority, edge->priority());
-      }
-    }
-  }
-
-  // Go through the map and leave only the edges which have the maximum
-  // priority.
-  for (auto& global_to_shared_edges : global_node_to_shared_owners) {
-    int max_priority = global_to_shared_edges.second.max_priority;
-    global_to_shared_edges.second.edges.remove_if(
-        [max_priority](Edge* edge) { return edge->priority() < max_priority; });
-  }
-
-  // Compute the footprints by distributing the memory of the nodes
-  // among the processes which have edges left.
-  std::map<base::PlatformProcessId, uint64_t> pid_to_shared_footprint;
-  for (const auto& global_to_shared_edges : global_node_to_shared_owners) {
-    Node* node = global_to_shared_edges.first;
-    const auto& edges = global_to_shared_edges.second.edges;
-
-    const Node::Entry& size_entry =
-        node->entries()->find(kSizeEntryName)->second;
-    PERFETTO_DCHECK(size_entry.type == Node::Entry::kUInt64);
-
-    uint64_t size_per_process = size_entry.value_uint64 / edges.size();
-    for (auto* edge : edges) {
-      base::PlatformProcessId pid = edge->source()->node_graph()->pid();
-      pid_to_shared_footprint[pid] += size_per_process;
-    }
-  }
-
-  return pid_to_shared_footprint;
-}
-
-// static
-void GraphProcessor::CollectAllocatorNodes(const RawProcessMemoryNode& source,
-                                           GlobalNodeGraph* global_graph,
-                                           Process* process_graph) {
-  // Turn each node into a node in the graph of nodes in the appropriate
-  // process node or global node.
-  for (const auto& path_to_node : source.allocator_nodes()) {
-    const std::string& path = path_to_node.first;
-    const RawMemoryGraphNode& raw_node = *path_to_node.second;
-
-    // All global nodes (i.e. those starting with global/) should be redirected
-    // to the shared graph.
-    bool is_global = base::StartsWith(path, "global/");
-    Process* process =
-        is_global ? global_graph->shared_memory_graph() : process_graph;
-
-    Node* node;
-    auto node_iterator = global_graph->nodes_by_id().find(raw_node.id());
-    if (node_iterator == global_graph->nodes_by_id().end()) {
-      // Storing whether the process is weak here will allow for later
-      // computations on whether or not the node should be removed.
-      bool is_weak = raw_node.flags() & RawMemoryGraphNode::Flags::kWeak;
-      node = process->CreateNode(raw_node.id(), path, is_weak);
-    } else {
-      node = node_iterator->second;
-
-      PERFETTO_DCHECK(node == process->FindNode(path));
-
-      PERFETTO_DCHECK(is_global);
-    }
-
-    // Copy any entries not already present into the node.
-    for (auto& entry : raw_node.entries()) {
-      switch (entry.entry_type) {
-        case RawMemoryGraphNode::MemoryNodeEntry::EntryType::kUint64:
-          node->AddEntry(entry.name, EntryUnitsFromString(entry.units),
-                         entry.value_uint64);
-          break;
-        case RawMemoryGraphNode::MemoryNodeEntry::EntryType::kString:
-          node->AddEntry(entry.name, entry.value_string);
-          break;
-      }
-    }
-  }
-}
-
-// static
-void GraphProcessor::AddEdges(const RawProcessMemoryNode& source,
-                              GlobalNodeGraph* global_graph) {
-  const auto& nodes_by_id = global_graph->nodes_by_id();
-  for (const auto& id_to_edge : source.allocator_nodes_edges()) {
-    auto& edge = id_to_edge.second;
-
-    // Find the source and target nodes in the global map by id.
-    auto source_it = nodes_by_id.find(edge->source);
-    auto target_it = nodes_by_id.find(edge->target);
-
-    if (source_it == nodes_by_id.end()) {
-      // If the source is missing then simply pretend the edge never existed
-      // leading to the memory being allocated to the target (if it exists).
-      continue;
-    } else if (target_it == nodes_by_id.end()) {
-      // If the target is lost but the source is present, then also ignore
-      // this edge for now.
-      // TODO(lalitm): see crbug.com/770712 for the permanent fix for this
-      // issue.
-      continue;
-    } else {
-      // Add an edge indicating the source node owns the memory of the
-      // target node with the given importance of the edge.
-      global_graph->AddNodeOwnershipEdge(source_it->second, target_it->second,
-                                         edge->importance);
-    }
-  }
-}
-
-// static
-void GraphProcessor::MarkImplicitWeakParentsRecursively(Node* node) {
-  // Ensure that we aren't in a bad state where we have an implicit node
-  // which doesn't have any children (which is not the root node).
-  PERFETTO_DCHECK(node->is_explicit() || !node->children()->empty() ||
-                  !node->parent());
-
-  // Check that at this stage, any node which is weak is only so because
-  // it was explicitly created as such.
-  PERFETTO_DCHECK(!node->is_weak() || node->is_explicit());
-
-  // If a node is already weak then all children will be marked weak at a
-  // later stage.
-  if (node->is_weak())
-    return;
-
-  // Recurse into each child and find out if all the children of this node are
-  // weak.
-  bool all_children_weak = true;
-  for (const auto& path_to_child : *node->children()) {
-    MarkImplicitWeakParentsRecursively(path_to_child.second);
-    all_children_weak = all_children_weak && path_to_child.second->is_weak();
-  }
-
-  // If all the children are weak and the parent is only an implicit one then we
-  // consider the parent as weak as well and we will later remove it.
-  node->set_weak(!node->is_explicit() && all_children_weak);
-}
-
-// static
-void GraphProcessor::MarkWeakOwnersAndChildrenRecursively(
-    Node* node,
-    std::set<const Node*>* visited) {
-  // If we've already visited this node then nothing to do.
-  if (visited->count(node) != 0)
-    return;
-
-  // If we haven't visited the node which this node owns then wait for that.
-  if (node->owns_edge() && visited->count(node->owns_edge()->target()) == 0)
-    return;
-
-  // If we haven't visited the node's parent then wait for that.
-  if (node->parent() && visited->count(node->parent()) == 0)
-    return;
-
-  // If either the node we own or our parent is weak, then mark this node
-  // as weak.
-  if ((node->owns_edge() && node->owns_edge()->target()->is_weak()) ||
-      (node->parent() && node->parent()->is_weak())) {
-    node->set_weak(true);
-  }
-  visited->insert(node);
-
-  // Recurse into each owner node to mark any other nodes.
-  for (auto* owned_by_edge : *node->owned_by_edges()) {
-    MarkWeakOwnersAndChildrenRecursively(owned_by_edge->source(), visited);
-  }
-
-  // Recurse into each child and find out if all the children of this node are
-  // weak.
-  for (const auto& path_to_child : *node->children()) {
-    MarkWeakOwnersAndChildrenRecursively(path_to_child.second, visited);
-  }
-}
-
-// static
-void GraphProcessor::RemoveWeakNodesRecursively(Node* node) {
-  auto* children = node->children();
-  for (auto child_it = children->begin(); child_it != children->end();) {
-    Node* child = child_it->second;
-
-    // If the node is weak, remove it. This automatically makes all
-    // descendents unreachable from the parents. If this node owned
-    // by another, it will have been marked earlier in
-    // |MarkWeakOwnersAndChildrenRecursively| and so will be removed
-    // by this method at some point.
-    if (child->is_weak()) {
-      child_it = children->erase(child_it);
-      continue;
-    }
-
-    // We should never be in a situation where we're about to
-    // keep a node which owns a weak node (which will be/has been
-    // removed).
-    PERFETTO_DCHECK(!child->owns_edge() ||
-                    !child->owns_edge()->target()->is_weak());
-
-    // Descend and remove all weak child nodes.
-    RemoveWeakNodesRecursively(child);
-
-    // Remove all edges with owner nodes which are weak.
-    std::vector<Edge*>* owned_by_edges = child->owned_by_edges();
-    auto new_end =
-        std::remove_if(owned_by_edges->begin(), owned_by_edges->end(),
-                       [](Edge* edge) { return edge->source()->is_weak(); });
-    owned_by_edges->erase(new_end, owned_by_edges->end());
-
-    ++child_it;
-  }
-}
-
-// static
-void GraphProcessor::AssignTracingOverhead(const std::string& allocator,
-                                           GlobalNodeGraph* global_graph,
-                                           Process* process) {
-  // This method should only be called if the allocator node exists.
-  PERFETTO_DCHECK(process->FindNode(allocator));
-
-  // Check that the tracing node exists and isn't already owning another node.
-  Node* tracing_node = process->FindNode("tracing");
-  if (!tracing_node)
-    return;
-
-  // This should be first edge associated with the tracing node.
-  PERFETTO_DCHECK(!tracing_node->owns_edge());
-
-  // Create the node under the allocator to which tracing overhead can be
-  // assigned.
-  std::string child_name = allocator + "/allocated_objects/tracing_overhead";
-  Node* child_node = process->CreateNode(MemoryAllocatorNodeId(), child_name,
-                                         false /* weak */);
-
-  // Assign the overhead of tracing to the tracing node.
-  global_graph->AddNodeOwnershipEdge(tracing_node, child_node,
-                                     0 /* importance */);
-}
-
-// static
-Node::Entry GraphProcessor::AggregateNumericWithNameForNode(
-    Node* node,
-    const std::string& name) {
-  bool first = true;
-  Node::Entry::ScalarUnits units = Node::Entry::ScalarUnits::kObjects;
-  uint64_t aggregated = 0;
-  for (auto& path_to_child : *node->children()) {
-    auto* entries = path_to_child.second->entries();
-
-    // Retrieve the entry with the given column name.
-    auto name_to_entry_it = entries->find(name);
-    if (name_to_entry_it == entries->end())
-      continue;
-
-    // Extract the entry from the iterator.
-    const Node::Entry& entry = name_to_entry_it->second;
-
-    // Ensure that the entry is numeric.
-    PERFETTO_DCHECK(entry.type == Node::Entry::Type::kUInt64);
-
-    // Check that the units of every child's entry with the given name is the
-    // same (i.e. we don't get a number for one child and size for another
-    // child). We do this by having a DCHECK that the units match the first
-    // child's units.
-    PERFETTO_DCHECK(first || units == entry.units);
-    units = entry.units;
-    aggregated += entry.value_uint64;
-    first = false;
-  }
-  return Node::Entry(units, aggregated);
-}
-
-// static
-void GraphProcessor::AggregateNumericsRecursively(Node* node) {
-  std::set<std::string> numeric_names;
-
-  for (const auto& path_to_child : *node->children()) {
-    AggregateNumericsRecursively(path_to_child.second);
-    for (const auto& name_to_entry : *path_to_child.second->entries()) {
-      const std::string& name = name_to_entry.first;
-      if (name_to_entry.second.type == Node::Entry::Type::kUInt64 &&
-          name != kSizeEntryName && name != kEffectiveSizeEntryName) {
-        numeric_names.insert(name);
-      }
-    }
-  }
-
-  for (auto& name : numeric_names) {
-    node->entries()->emplace(name, AggregateNumericWithNameForNode(node, name));
-  }
-}
-
-// static
-void GraphProcessor::PropagateNumericsAndDiagnosticsRecursively(Node* node) {
-  for (const auto& name_to_entry : *node->entries()) {
-    for (auto* edge : *node->owned_by_edges()) {
-      edge->source()->entries()->insert(name_to_entry);
-    }
-  }
-  for (const auto& path_to_child : *node->children()) {
-    PropagateNumericsAndDiagnosticsRecursively(path_to_child.second);
-  }
-}
-
-// static
-base::Optional<uint64_t> GraphProcessor::AggregateSizeForDescendantNode(
-    Node* root,
-    Node* descendant) {
-  Edge* owns_edge = descendant->owns_edge();
-  if (owns_edge && owns_edge->target()->IsDescendentOf(*root))
-    return base::make_optional(0UL);
-
-  if (descendant->children()->empty())
-    return GetSizeEntryOfNode(descendant).value_or(0ul);
-
-  base::Optional<uint64_t> size;
-  for (const auto& path_to_child : *descendant->children()) {
-    auto c_size = AggregateSizeForDescendantNode(root, path_to_child.second);
-    if (size) {
-      *size += c_size.value_or(0);
-    } else {
-      size = std::move(c_size);
-    }
-  }
-  return size;
-}
-
-// Assumes that this function has been called on all children and owner nodes.
-// static
-void GraphProcessor::CalculateSizeForNode(Node* node) {
-  // Get the size at the root node if it exists.
-  base::Optional<uint64_t> node_size = GetSizeEntryOfNode(node);
-
-  // Aggregate the size of all the child nodes.
-  base::Optional<uint64_t> aggregated_size;
-  for (const auto& path_to_child : *node->children()) {
-    auto c_size = AggregateSizeForDescendantNode(node, path_to_child.second);
-    if (aggregated_size) {
-      *aggregated_size += c_size.value_or(0ul);
-    } else {
-      aggregated_size = std::move(c_size);
-    }
-  }
-
-  // Check that if both aggregated and node sizes exist that the node size
-  // is bigger than the aggregated.
-  // TODO(lalitm): the following condition is triggered very often even though
-  // it is a warning in JS code. Find a way to add the warning to display in UI
-  // or to fix all instances where this is violated and then enable this check.
-  // PERFETTO_DCHECK(!node_size || !aggregated_size || *node_size >=
-  // *aggregated_size);
-
-  // Calculate the maximal size of an owner node.
-  base::Optional<uint64_t> max_owner_size;
-  for (auto* edge : *node->owned_by_edges()) {
-    auto o_size = GetSizeEntryOfNode(edge->source());
-    if (max_owner_size) {
-      *max_owner_size = std::max(o_size.value_or(0ul), *max_owner_size);
-    } else {
-      max_owner_size = std::move(o_size);
-    }
-  }
-
-  // Check that if both owner and node sizes exist that the node size
-  // is bigger than the owner.
-  // TODO(lalitm): the following condition is triggered very often even though
-  // it is a warning in JS code. Find a way to add the warning to display in UI
-  // or to fix all instances where this is violated and then enable this check.
-  // PERFETTO_DCHECK(!node_size || !max_owner_size || *node_size >=
-  // *max_owner_size);
-
-  // Clear out any existing size entry which may exist.
-  node->entries()->erase(kSizeEntryName);
-
-  // If no inference about size can be made then simply return.
-  if (!node_size && !aggregated_size && !max_owner_size)
-    return;
-
-  // Update the node with the new size entry.
-  uint64_t aggregated_size_value = aggregated_size.value_or(0ul);
-  uint64_t process_size =
-      std::max({node_size.value_or(0ul), aggregated_size_value,
-                max_owner_size.value_or(0ul)});
-  node->AddEntry(kSizeEntryName, Node::Entry::ScalarUnits::kBytes,
-                 process_size);
-
-  // If this is an intermediate node then add a ghost node which stores
-  // all sizes not accounted for by the children.
-  uint64_t unaccounted = process_size - aggregated_size_value;
-  if (unaccounted > 0 && !node->children()->empty()) {
-    Node* unspecified = node->CreateChild("<unspecified>");
-    unspecified->AddEntry(kSizeEntryName, Node::Entry::ScalarUnits::kBytes,
-                          unaccounted);
-  }
-}
-
-// Assumes that this function has been called on all children and owner nodes.
-// static
-void GraphProcessor::CalculateNodeSubSizes(Node* node) {
-  // Completely skip nodes with undefined size.
-  base::Optional<uint64_t> size_opt = GetSizeEntryOfNode(node);
-  if (!size_opt)
-    return;
-
-  // If the node is a leaf node, then both sub-sizes are equal to the size.
-  if (node->children()->empty()) {
-    node->add_not_owning_sub_size(*size_opt);
-    node->add_not_owned_sub_size(*size_opt);
-    return;
-  }
-
-  // Calculate this node's not-owning sub-size by summing up the not-owning
-  // sub-sizes of children which do not own another node.
-  for (const auto& path_to_child : *node->children()) {
-    if (path_to_child.second->owns_edge())
-      continue;
-    node->add_not_owning_sub_size(path_to_child.second->not_owning_sub_size());
-  }
-
-  // Calculate this node's not-owned sub-size.
-  for (const auto& path_to_child : *node->children()) {
-    Node* child = path_to_child.second;
-
-    // If the child node is not owned, then add its not-owned sub-size.
-    if (child->owned_by_edges()->empty()) {
-      node->add_not_owned_sub_size(child->not_owned_sub_size());
-      continue;
-    }
-
-    // If the child node is owned, then add the difference between its size
-    // and the largest owner.
-    uint64_t largest_owner_size = 0;
-    for (Edge* edge : *child->owned_by_edges()) {
-      uint64_t source_size = GetSizeEntryOfNode(edge->source()).value_or(0);
-      largest_owner_size = std::max(largest_owner_size, source_size);
-    }
-    uint64_t child_size = GetSizeEntryOfNode(child).value_or(0);
-    node->add_not_owned_sub_size(child_size - largest_owner_size);
-  }
-}
-
-// static
-void GraphProcessor::CalculateNodeOwnershipCoefficient(Node* node) {
-  // Completely skip nodes with undefined size.
-  base::Optional<uint64_t> size_opt = GetSizeEntryOfNode(node);
-  if (!size_opt)
-    return;
-
-  // We only need to consider owned nodes.
-  if (node->owned_by_edges()->empty())
-    return;
-
-  // Sort the owners in decreasing order of ownership priority and
-  // increasing order of not-owning sub-size (in case of equal priority).
-  std::vector<Edge*> owners = *node->owned_by_edges();
-  std::sort(owners.begin(), owners.end(), [](Edge* a, Edge* b) {
-    if (a->priority() == b->priority()) {
-      return a->source()->not_owning_sub_size() <
-             b->source()->not_owning_sub_size();
-    }
-    return b->priority() < a->priority();
-  });
-
-  // Loop over the list of owners and distribute the owned node's not-owned
-  // sub-size among them according to their ownership priority and
-  // not-owning sub-size.
-  uint64_t already_attributed_sub_size = 0;
-  for (auto current_it = owners.begin(); current_it != owners.end();) {
-    // Find the position of the first owner with lower priority.
-    int current_priority = (*current_it)->priority();
-    auto next_it =
-        std::find_if(current_it, owners.end(), [current_priority](Edge* edge) {
-          return edge->priority() < current_priority;
-        });
-
-    // Compute the number of nodes which have the same priority as current.
-    size_t difference = static_cast<size_t>(std::distance(current_it, next_it));
-
-    // Visit the owners with the same priority in increasing order of
-    // not-owned sub-size, split the owned memory among them appropriately,
-    // and calculate their owning coefficients.
-    double attributed_not_owning_sub_size = 0;
-    for (; current_it != next_it; current_it++) {
-      uint64_t not_owning_sub_size =
-          (*current_it)->source()->not_owning_sub_size();
-      if (not_owning_sub_size > already_attributed_sub_size) {
-        attributed_not_owning_sub_size +=
-            static_cast<double>(not_owning_sub_size -
-                                already_attributed_sub_size) /
-            static_cast<double>(difference);
-        already_attributed_sub_size = not_owning_sub_size;
-      }
-
-      if (not_owning_sub_size != 0) {
-        double coeff = attributed_not_owning_sub_size /
-                       static_cast<double>(not_owning_sub_size);
-        (*current_it)->source()->set_owning_coefficient(coeff);
-      }
-      difference--;
-    }
-
-    // At the end of this loop, we should move to a node with a lower priority.
-    PERFETTO_DCHECK(current_it == next_it);
-  }
-
-  // Attribute the remainder of the owned node's not-owned sub-size to
-  // the node itself and calculate its owned coefficient.
-  uint64_t not_owned_sub_size = node->not_owned_sub_size();
-  if (not_owned_sub_size != 0) {
-    double remainder_sub_size =
-        static_cast<double>(not_owned_sub_size - already_attributed_sub_size);
-    node->set_owned_coefficient(remainder_sub_size /
-                                static_cast<double>(not_owned_sub_size));
-  }
-}
-
-// static
-void GraphProcessor::CalculateNodeCumulativeOwnershipCoefficient(Node* node) {
-  // Completely skip nodes with undefined size.
-  base::Optional<uint64_t> size_opt = GetSizeEntryOfNode(node);
-  if (!size_opt)
-    return;
-
-  double cumulative_owned_coefficient = node->owned_coefficient();
-  if (node->parent()) {
-    cumulative_owned_coefficient *=
-        node->parent()->cumulative_owned_coefficient();
-  }
-  node->set_cumulative_owned_coefficient(cumulative_owned_coefficient);
-
-  if (node->owns_edge()) {
-    node->set_cumulative_owning_coefficient(
-        node->owning_coefficient() *
-        node->owns_edge()->target()->cumulative_owning_coefficient());
-  } else if (node->parent()) {
-    node->set_cumulative_owning_coefficient(
-        node->parent()->cumulative_owning_coefficient());
-  } else {
-    node->set_cumulative_owning_coefficient(1);
-  }
-}
-
-// static
-void GraphProcessor::CalculateNodeEffectiveSize(Node* node) {
-  // Completely skip nodes with undefined size. As a result, each node will
-  // have defined effective size if and only if it has defined size.
-  base::Optional<uint64_t> size_opt = GetSizeEntryOfNode(node);
-  if (!size_opt) {
-    node->entries()->erase(kEffectiveSizeEntryName);
-    return;
-  }
-
-  uint64_t effective_size = 0;
-  if (node->children()->empty()) {
-    // Leaf node.
-    effective_size = static_cast<uint64_t>(
-        static_cast<double>(*size_opt) * node->cumulative_owning_coefficient() *
-        node->cumulative_owned_coefficient());
-  } else {
-    // Non-leaf node.
-    for (const auto& path_to_child : *node->children()) {
-      Node* child = path_to_child.second;
-      if (!GetSizeEntryOfNode(child))
-        continue;
-      effective_size +=
-          child->entries()->find(kEffectiveSizeEntryName)->second.value_uint64;
-    }
-  }
-  node->AddEntry(kEffectiveSizeEntryName, Node::Entry::ScalarUnits::kBytes,
-                 effective_size);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/graph_processor_unittest.cc b/src/trace_processor/importers/memory_tracker/graph_processor_unittest.cc
deleted file mode 100644
index 8d1cc31..0000000
--- a/src/trace_processor/importers/memory_tracker/graph_processor_unittest.cc
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
-
-#include <stddef.h>
-
-#include <unordered_map>
-
-#include "perfetto/base/build_config.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using Edge = GlobalNodeGraph::Edge;
-using Node = GlobalNodeGraph::Node;
-using Process = GlobalNodeGraph::Process;
-
-namespace {
-
-const MemoryAllocatorNodeId kEmptyId;
-
-}  // namespace
-
-class GraphProcessorTest : public testing::Test {
- public:
-  GraphProcessorTest() {}
-
-  void MarkImplicitWeakParentsRecursively(Node* node) {
-    GraphProcessor::MarkImplicitWeakParentsRecursively(node);
-  }
-
-  void MarkWeakOwnersAndChildrenRecursively(Node* node) {
-    std::set<const Node*> visited;
-    GraphProcessor::MarkWeakOwnersAndChildrenRecursively(node, &visited);
-  }
-
-  void RemoveWeakNodesRecursively(Node* node) {
-    GraphProcessor::RemoveWeakNodesRecursively(node);
-  }
-
-  void AssignTracingOverhead(const std::string& allocator,
-                             GlobalNodeGraph* global_graph,
-                             Process* process) {
-    GraphProcessor::AssignTracingOverhead(allocator, global_graph, process);
-  }
-
-  GlobalNodeGraph::Node::Entry AggregateNumericWithNameForNode(
-      Node* node,
-      const std::string& name) {
-    return GraphProcessor::AggregateNumericWithNameForNode(node, name);
-  }
-
-  void AggregateNumericsRecursively(Node* node) {
-    GraphProcessor::AggregateNumericsRecursively(node);
-  }
-
-  void PropagateNumericsAndDiagnosticsRecursively(Node* node) {
-    GraphProcessor::PropagateNumericsAndDiagnosticsRecursively(node);
-  }
-
-  base::Optional<uint64_t> AggregateSizeForDescendantNode(Node* root,
-                                                          Node* descendant) {
-    return GraphProcessor::AggregateSizeForDescendantNode(root, descendant);
-  }
-
-  void CalculateSizeForNode(Node* node) {
-    GraphProcessor::CalculateSizeForNode(node);
-  }
-
-  void CalculateNodeSubSizes(Node* node) {
-    GraphProcessor::CalculateNodeSubSizes(node);
-  }
-
-  void CalculateNodeOwnershipCoefficient(Node* node) {
-    GraphProcessor::CalculateNodeOwnershipCoefficient(node);
-  }
-
-  void CalculateNodeCumulativeOwnershipCoefficient(Node* node) {
-    GraphProcessor::CalculateNodeCumulativeOwnershipCoefficient(node);
-  }
-
-  void CalculateNodeEffectiveSize(Node* node) {
-    GraphProcessor::CalculateNodeEffectiveSize(node);
-  }
-
- protected:
-  GlobalNodeGraph graph;
-};
-
-TEST_F(GraphProcessorTest, SmokeComputeMemoryGraph) {
-  std::map<base::PlatformProcessId, std::unique_ptr<RawProcessMemoryNode>>
-      process_nodes;
-
-  std::unique_ptr<RawMemoryGraphNode> source(new RawMemoryGraphNode(
-      "test1/test2/test3", LevelOfDetail::kDetailed, MemoryAllocatorNodeId(42),
-      std::vector<RawMemoryGraphNode::MemoryNodeEntry>{
-          {RawMemoryGraphNode::kNameSize, RawMemoryGraphNode::kUnitsBytes,
-           10}}));
-
-  std::unique_ptr<RawMemoryGraphNode> target(new RawMemoryGraphNode(
-      "target", LevelOfDetail::kDetailed, MemoryAllocatorNodeId(4242)));
-
-  std::unique_ptr<MemoryGraphEdge> edge(
-      new MemoryGraphEdge(source->id(), target->id(), 10, false));
-  RawProcessMemoryNode::AllocatorNodeEdgesMap edgesMap;
-  edgesMap.emplace(edge->source, std::move(edge));
-
-  RawProcessMemoryNode::MemoryNodesMap nodesMap;
-  nodesMap.emplace(source->absolute_name(), std::move(source));
-  nodesMap.emplace(target->absolute_name(), std::move(target));
-
-  auto pmd = std::unique_ptr<RawProcessMemoryNode>(new RawProcessMemoryNode(
-      LevelOfDetail::kDetailed, std::move(edgesMap), std::move(nodesMap)));
-  process_nodes.emplace(1, std::move(pmd));
-
-  auto global_node = GraphProcessor::CreateMemoryGraph(process_nodes);
-
-  ASSERT_EQ(1u, global_node->process_node_graphs().size());
-
-  auto id_to_node_it = global_node->process_node_graphs().find(1);
-  auto* first_child = id_to_node_it->second->FindNode("test1");
-  ASSERT_NE(first_child, nullptr);
-  ASSERT_EQ(first_child->parent(), id_to_node_it->second->root());
-
-  auto* second_child = first_child->GetChild("test2");
-  ASSERT_NE(second_child, nullptr);
-  ASSERT_EQ(second_child->parent(), first_child);
-
-  auto* third_child = second_child->GetChild("test3");
-  ASSERT_NE(third_child, nullptr);
-  ASSERT_EQ(third_child->parent(), second_child);
-
-  auto* direct = id_to_node_it->second->FindNode("test1/test2/test3");
-  ASSERT_EQ(third_child, direct);
-
-  ASSERT_EQ(third_child->entries()->size(), 1ul);
-
-  auto size = third_child->entries()->find(RawMemoryGraphNode::kNameSize);
-  ASSERT_EQ(10ul, size->second.value_uint64);
-
-  auto& edges = global_node->edges();
-  auto edge_it = edges.begin();
-  ASSERT_EQ(std::distance(edges.begin(), edges.end()), 1l);
-  ASSERT_EQ(edge_it->source(), direct);
-  ASSERT_EQ(edge_it->target(), id_to_node_it->second->FindNode("target"));
-  ASSERT_EQ(edge_it->priority(), 10);
-}
-
-TEST_F(GraphProcessorTest, ComputeSharedFootprintFromGraphSameImportance) {
-  Process* global_process = graph.shared_memory_graph();
-  Node* global_node = global_process->CreateNode(kEmptyId, "global/1", false);
-  global_node->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 100);
-
-  Process* first = graph.CreateGraphForProcess(1);
-  Node* shared_1 = first->CreateNode(kEmptyId, "shared_memory/1", false);
-
-  Process* second = graph.CreateGraphForProcess(2);
-  Node* shared_2 = second->CreateNode(kEmptyId, "shared_memory/2", false);
-
-  graph.AddNodeOwnershipEdge(shared_1, global_node, 1);
-  graph.AddNodeOwnershipEdge(shared_2, global_node, 1);
-
-  auto pid_to_sizes = GraphProcessor::ComputeSharedFootprintFromGraph(graph);
-  ASSERT_EQ(pid_to_sizes[1], 50ul);
-  ASSERT_EQ(pid_to_sizes[2], 50ul);
-}
-
-TEST_F(GraphProcessorTest, ComputeSharedFootprintFromGraphSomeDiffImportance) {
-  Process* global_process = graph.shared_memory_graph();
-
-  Node* global_node = global_process->CreateNode(kEmptyId, "global/1", false);
-  global_node->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 100);
-
-  Process* first = graph.CreateGraphForProcess(1);
-  Node* shared_1 = first->CreateNode(kEmptyId, "shared_memory/1", false);
-
-  Process* second = graph.CreateGraphForProcess(2);
-  Node* shared_2 = second->CreateNode(kEmptyId, "shared_memory/2", false);
-
-  Process* third = graph.CreateGraphForProcess(3);
-  Node* shared_3 = third->CreateNode(kEmptyId, "shared_memory/3", false);
-
-  Process* fourth = graph.CreateGraphForProcess(4);
-  Node* shared_4 = fourth->CreateNode(kEmptyId, "shared_memory/4", false);
-
-  Process* fifth = graph.CreateGraphForProcess(5);
-  Node* shared_5 = fifth->CreateNode(kEmptyId, "shared_memory/5", false);
-
-  graph.AddNodeOwnershipEdge(shared_1, global_node, 1);
-  graph.AddNodeOwnershipEdge(shared_2, global_node, 2);
-  graph.AddNodeOwnershipEdge(shared_3, global_node, 3);
-  graph.AddNodeOwnershipEdge(shared_4, global_node, 3);
-  graph.AddNodeOwnershipEdge(shared_5, global_node, 3);
-
-  auto pid_to_sizes = GraphProcessor::ComputeSharedFootprintFromGraph(graph);
-  ASSERT_EQ(pid_to_sizes[1], 0ul);
-  ASSERT_EQ(pid_to_sizes[2], 0ul);
-  ASSERT_EQ(pid_to_sizes[3], 33ul);
-  ASSERT_EQ(pid_to_sizes[4], 33ul);
-  ASSERT_EQ(pid_to_sizes[5], 33ul);
-}
-
-TEST_F(GraphProcessorTest, MarkWeakParentsSimple) {
-  Process* process = graph.CreateGraphForProcess(1);
-  Node* parent = process->CreateNode(kEmptyId, "parent", false);
-  Node* first = process->CreateNode(kEmptyId, "parent/first", true);
-  Node* second = process->CreateNode(kEmptyId, "parent/second", false);
-
-  // Case where one child is not weak.
-  parent->set_explicit(false);
-  first->set_explicit(true);
-  second->set_explicit(true);
-
-  // The function should be a no-op.
-  MarkImplicitWeakParentsRecursively(parent);
-  ASSERT_FALSE(parent->is_weak());
-  ASSERT_TRUE(first->is_weak());
-  ASSERT_FALSE(second->is_weak());
-
-  // Case where all children is weak.
-  second->set_weak(true);
-
-  // The function should mark parent as weak.
-  MarkImplicitWeakParentsRecursively(parent);
-  ASSERT_TRUE(parent->is_weak());
-  ASSERT_TRUE(first->is_weak());
-  ASSERT_TRUE(second->is_weak());
-}
-
-TEST_F(GraphProcessorTest, MarkWeakParentsComplex) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  // |first| is explicitly strong but |first_child| is implicitly so.
-  Node* parent = process->CreateNode(kEmptyId, "parent", false);
-  Node* first = process->CreateNode(kEmptyId, "parent/f", false);
-  Node* first_child = process->CreateNode(kEmptyId, "parent/f/c", false);
-  Node* first_gchild = process->CreateNode(kEmptyId, "parent/f/c/c", true);
-
-  parent->set_explicit(false);
-  first->set_explicit(true);
-  first_child->set_explicit(false);
-  first_gchild->set_explicit(true);
-
-  // That should lead to |first_child| marked implicitly weak.
-  MarkImplicitWeakParentsRecursively(parent);
-  ASSERT_FALSE(parent->is_weak());
-  ASSERT_FALSE(first->is_weak());
-  ASSERT_TRUE(first_child->is_weak());
-  ASSERT_TRUE(first_gchild->is_weak());
-
-  // Reset and change so that first is now only implicitly strong.
-  first->set_explicit(false);
-  first_child->set_weak(false);
-
-  // The whole chain should now be weak.
-  MarkImplicitWeakParentsRecursively(parent);
-  ASSERT_TRUE(parent->is_weak());
-  ASSERT_TRUE(first->is_weak());
-  ASSERT_TRUE(first_child->is_weak());
-  ASSERT_TRUE(first_gchild->is_weak());
-}
-
-TEST_F(GraphProcessorTest, MarkWeakOwners) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  // Make only the ultimate owned node weak.
-  Node* owner = process->CreateNode(kEmptyId, "owner", false);
-  Node* owned = process->CreateNode(kEmptyId, "owned", false);
-  Node* owned_2 = process->CreateNode(kEmptyId, "owned2", true);
-
-  graph.AddNodeOwnershipEdge(owner, owned, 0);
-  graph.AddNodeOwnershipEdge(owned, owned_2, 0);
-
-  // Starting from leaf node should lead to everything being weak.
-  MarkWeakOwnersAndChildrenRecursively(process->root());
-  ASSERT_TRUE(owner->is_weak());
-  ASSERT_TRUE(owned->is_weak());
-  ASSERT_TRUE(owned_2->is_weak());
-}
-
-TEST_F(GraphProcessorTest, MarkWeakParent) {
-  Process* process = graph.CreateGraphForProcess(1);
-  Node* parent = process->CreateNode(kEmptyId, "parent", true);
-  Node* child = process->CreateNode(kEmptyId, "parent/c", false);
-  Node* child_2 = process->CreateNode(kEmptyId, "parent/c/c", false);
-
-  // Starting from parent node should lead to everything being weak.
-  MarkWeakOwnersAndChildrenRecursively(process->root());
-  ASSERT_TRUE(parent->is_weak());
-  ASSERT_TRUE(child->is_weak());
-  ASSERT_TRUE(child_2->is_weak());
-}
-
-TEST_F(GraphProcessorTest, MarkWeakParentOwner) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  // Make only the parent node weak.
-  Node* parent = process->CreateNode(kEmptyId, "parent", true);
-  Node* child = process->CreateNode(kEmptyId, "parent/c", false);
-  Node* child_2 = process->CreateNode(kEmptyId, "parent/c/c", false);
-  Node* owner = process->CreateNode(kEmptyId, "owner", false);
-
-  graph.AddNodeOwnershipEdge(owner, parent, 0);
-
-  // Starting from parent node should lead to everything being weak.
-  MarkWeakOwnersAndChildrenRecursively(process->root());
-  ASSERT_TRUE(parent->is_weak());
-  ASSERT_TRUE(child->is_weak());
-  ASSERT_TRUE(child_2->is_weak());
-  ASSERT_TRUE(owner->is_weak());
-}
-
-TEST_F(GraphProcessorTest, RemoveWeakNodesRecursively) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  // Make only the child node weak.
-  Node* parent = process->CreateNode(kEmptyId, "parent", false);
-  Node* child = process->CreateNode(kEmptyId, "parent/c", true);
-  process->CreateNode(kEmptyId, "parent/c/c", false);
-  Node* owned = process->CreateNode(kEmptyId, "parent/owned", false);
-
-  graph.AddNodeOwnershipEdge(child, owned, 0);
-
-  // Starting from parent node should lead child and child_2 being
-  // removed and owned to have the edge from it removed.
-  RemoveWeakNodesRecursively(parent);
-
-  ASSERT_EQ(parent->children()->size(), 1ul);
-  ASSERT_EQ(parent->children()->begin()->second, owned);
-
-  ASSERT_TRUE(owned->owned_by_edges()->empty());
-}
-
-TEST_F(GraphProcessorTest, RemoveWeakNodesRecursivelyBetweenGraphs) {
-  Process* f_process = graph.CreateGraphForProcess(1);
-  Process* s_process = graph.CreateGraphForProcess(2);
-
-  // Make only the child node weak.
-  Node* child = f_process->CreateNode(kEmptyId, "c", true);
-  f_process->CreateNode(kEmptyId, "c/c", false);
-  Node* owned = s_process->CreateNode(kEmptyId, "owned", false);
-
-  graph.AddNodeOwnershipEdge(child, owned, 0);
-
-  // Starting from root node should lead child and child_2 being
-  // removed.
-  RemoveWeakNodesRecursively(f_process->root());
-
-  ASSERT_EQ(f_process->root()->children()->size(), 0ul);
-  ASSERT_EQ(s_process->root()->children()->size(), 1ul);
-
-  // This should be false until our next pass.
-  ASSERT_FALSE(owned->owned_by_edges()->empty());
-
-  RemoveWeakNodesRecursively(s_process->root());
-
-  // We should now have cleaned up the owned node's edges.
-  ASSERT_TRUE(owned->owned_by_edges()->empty());
-}
-
-TEST_F(GraphProcessorTest, AssignTracingOverhead) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  // Now add an allocator node.
-  process->CreateNode(kEmptyId, "malloc", false);
-
-  // If the tracing node does not exist, this should do nothing.
-  AssignTracingOverhead("malloc", &graph, process);
-  ASSERT_TRUE(process->root()->GetChild("malloc")->children()->empty());
-
-  // Now add a tracing node.
-  process->CreateNode(kEmptyId, "tracing", false);
-
-  // This should now add a node with the allocator.
-  AssignTracingOverhead("malloc", &graph, process);
-  ASSERT_NE(process->FindNode("malloc/allocated_objects/tracing_overhead"),
-            nullptr);
-}
-
-TEST_F(GraphProcessorTest, AggregateNumericWithNameForNode) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process->CreateNode(kEmptyId, "c2", false);
-  Node* c3 = process->CreateNode(kEmptyId, "c3", false);
-
-  c1->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 100);
-  c2->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 256);
-  c3->AddEntry("other_numeric", Node::Entry::ScalarUnits::kBytes, 1000);
-
-  Node* root = process->root();
-  Node::Entry entry = AggregateNumericWithNameForNode(root, "random_numeric");
-  ASSERT_EQ(entry.value_uint64, 356ul);
-  ASSERT_EQ(entry.units, Node::Entry::ScalarUnits::kBytes);
-}
-
-TEST_F(GraphProcessorTest, AggregateNumericsRecursively) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process->CreateNode(kEmptyId, "c2", false);
-  Node* c2_c1 = process->CreateNode(kEmptyId, "c2/c1", false);
-  Node* c2_c2 = process->CreateNode(kEmptyId, "c2/c2", false);
-  Node* c3_c1 = process->CreateNode(kEmptyId, "c3/c1", false);
-  Node* c3_c2 = process->CreateNode(kEmptyId, "c3/c2", false);
-
-  // If an entry already exists in the parent, the child should not
-  // ovewrite it. If nothing exists, then the child can aggregrate.
-  c1->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 100);
-  c2->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 256);
-  c2_c1->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 256);
-  c2_c2->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 256);
-  c3_c1->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 10);
-  c3_c2->AddEntry("random_numeric", Node::Entry::ScalarUnits::kBytes, 10);
-
-  Node* root = process->root();
-  AggregateNumericsRecursively(root);
-  ASSERT_EQ(root->entries()->size(), 1ul);
-
-  auto entry = root->entries()->begin()->second;
-  ASSERT_EQ(entry.value_uint64, 376ul);
-  ASSERT_EQ(entry.units, Node::Entry::ScalarUnits::kBytes);
-}
-
-TEST_F(GraphProcessorTest, AggregateSizeForDescendantNode) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process->CreateNode(kEmptyId, "c2", false);
-  Node* c2_c1 = process->CreateNode(kEmptyId, "c2/c1", false);
-  Node* c2_c2 = process->CreateNode(kEmptyId, "c2/c2", false);
-  Node* c3_c1 = process->CreateNode(kEmptyId, "c3/c1", false);
-  Node* c3_c2 = process->CreateNode(kEmptyId, "c3/c2", false);
-
-  c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 100);
-  c2_c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 256);
-  c2_c2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 256);
-  c3_c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 10);
-  c3_c2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 10);
-
-  graph.AddNodeOwnershipEdge(c2_c2, c3_c2, 0);
-
-  // Aggregating root should give size of (100 + 256 + 10 * 2) = 376.
-  // |c2_c2| is not counted because it is owns by |c3_c2|.
-  Node* root = process->root();
-  ASSERT_EQ(376ul, *AggregateSizeForDescendantNode(root, root));
-
-  // Aggregating c2 should give size of (256 * 2) = 512. |c2_c2| is counted
-  // because |c3_c2| is not a child of |c2|.
-  ASSERT_EQ(512ul, *AggregateSizeForDescendantNode(c2, c2));
-}
-
-TEST_F(GraphProcessorTest, CalculateSizeForNode) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process->CreateNode(kEmptyId, "c2", false);
-  Node* c2_c1 = process->CreateNode(kEmptyId, "c2/c1", false);
-  Node* c2_c2 = process->CreateNode(kEmptyId, "c2/c2", false);
-  Node* c3 = process->CreateNode(kEmptyId, "c3", false);
-  Node* c3_c1 = process->CreateNode(kEmptyId, "c3/c1", false);
-  Node* c3_c2 = process->CreateNode(kEmptyId, "c3/c2", false);
-
-  c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 600);
-  c2_c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 10);
-  c2_c2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 10);
-  c3->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 600);
-  c3_c1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 256);
-  c3_c2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 256);
-
-  graph.AddNodeOwnershipEdge(c2_c2, c3_c2, 0);
-
-  // Compute size entry for |c2| since computations for |c2_c1| and |c2_c2|
-  // are already complete.
-  CalculateSizeForNode(c2);
-
-  // Check that |c2| now has a size entry of 20 (sum of children).
-  auto c2_entry = c2->entries()->begin()->second;
-  ASSERT_EQ(c2_entry.value_uint64, 20ul);
-  ASSERT_EQ(c2_entry.units, Node::Entry::ScalarUnits::kBytes);
-
-  // Compute size entry for |c3_c2| which should not change in size.
-  CalculateSizeForNode(c3_c2);
-
-  // Check that |c3_c2| now has unchanged size.
-  auto c3_c2_entry = c3_c2->entries()->begin()->second;
-  ASSERT_EQ(c3_c2_entry.value_uint64, 256ul);
-  ASSERT_EQ(c3_c2_entry.units, Node::Entry::ScalarUnits::kBytes);
-
-  // Compute size entry for |c3| which should add an unspecified node.
-  CalculateSizeForNode(c3);
-
-  // Check that |c3| has unchanged size.
-  auto c3_entry = c3->entries()->begin()->second;
-  ASSERT_EQ(c3_entry.value_uint64, 600ul);
-  ASSERT_EQ(c3_entry.units, Node::Entry::ScalarUnits::kBytes);
-
-  // Check that the unspecified node is a child of |c3| and has size
-  // 600 - 512 = 88.
-  Node* c3_child = c3->children()->find("<unspecified>")->second;
-  auto c3_child_entry = c3_child->entries()->begin()->second;
-  ASSERT_EQ(c3_child_entry.value_uint64, 88ul);
-  ASSERT_EQ(c3_child_entry.units, Node::Entry::ScalarUnits::kBytes);
-
-  // Compute size entry for |root| which should aggregate children sizes.
-  CalculateSizeForNode(process->root());
-
-  // Check that |root| has been assigned a size of 600 + 10 + 600 = 1210.
-  // Note that |c2_c2| is not counted because it ows |c3_c2| which is a
-  // descendant of |root|.
-  auto root_entry = process->root()->entries()->begin()->second;
-  ASSERT_EQ(root_entry.value_uint64, 1210ul);
-  ASSERT_EQ(root_entry.units, Node::Entry::ScalarUnits::kBytes);
-}
-
-TEST_F(GraphProcessorTest, CalculateNodeSubSizes) {
-  Process* process_1 = graph.CreateGraphForProcess(1);
-  Process* process_2 = graph.CreateGraphForProcess(2);
-
-  Node* parent_1 = process_1->CreateNode(kEmptyId, "parent", false);
-  Node* child_1 = process_1->CreateNode(kEmptyId, "parent/child", false);
-
-  Node* parent_2 = process_2->CreateNode(kEmptyId, "parent", false);
-  Node* child_2 = process_2->CreateNode(kEmptyId, "parent/child", false);
-
-  graph.AddNodeOwnershipEdge(parent_1, parent_2, 0);
-
-  process_1->root()->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 4);
-  parent_1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 4);
-  child_1->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 4);
-  process_2->root()->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 5);
-  parent_2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 5);
-  child_2->AddEntry("size", Node::Entry::ScalarUnits::kBytes, 5);
-
-  // Each of these nodes should have owner/owned same as size itself.
-  CalculateNodeSubSizes(child_1);
-  ASSERT_EQ(child_1->not_owned_sub_size(), 4ul);
-  ASSERT_EQ(child_1->not_owning_sub_size(), 4ul);
-  CalculateNodeSubSizes(child_2);
-  ASSERT_EQ(child_2->not_owned_sub_size(), 5ul);
-  ASSERT_EQ(child_2->not_owning_sub_size(), 5ul);
-
-  // These nodes should also have size of children.
-  CalculateNodeSubSizes(parent_1);
-  ASSERT_EQ(parent_1->not_owned_sub_size(), 4ul);
-  ASSERT_EQ(parent_1->not_owning_sub_size(), 4ul);
-  CalculateNodeSubSizes(parent_2);
-  ASSERT_EQ(parent_2->not_owned_sub_size(), 5ul);
-  ASSERT_EQ(parent_2->not_owning_sub_size(), 5ul);
-
-  // These nodes should account for edge between parents.
-  CalculateNodeSubSizes(process_1->root());
-  ASSERT_EQ(process_1->root()->not_owned_sub_size(), 4ul);
-  ASSERT_EQ(process_1->root()->not_owning_sub_size(), 0ul);
-  CalculateNodeSubSizes(process_2->root());
-  ASSERT_EQ(process_2->root()->not_owned_sub_size(), 1ul);
-  ASSERT_EQ(process_2->root()->not_owning_sub_size(), 5ul);
-}
-
-TEST_F(GraphProcessorTest, CalculateNodeOwnershipCoefficient) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* owned = process->CreateNode(kEmptyId, "owned", false);
-  Node* owner_1 = process->CreateNode(kEmptyId, "owner1", false);
-  Node* owner_2 = process->CreateNode(kEmptyId, "owner2", false);
-  Node* owner_3 = process->CreateNode(kEmptyId, "owner3", false);
-  Node* owner_4 = process->CreateNode(kEmptyId, "owner4", false);
-
-  graph.AddNodeOwnershipEdge(owner_1, owned, 2);
-  graph.AddNodeOwnershipEdge(owner_2, owned, 2);
-  graph.AddNodeOwnershipEdge(owner_3, owned, 1);
-  graph.AddNodeOwnershipEdge(owner_4, owned, 0);
-
-  // Ensure the owned node has a size otherwise calculations will not happen.
-  owned->AddEntry("size", Node::Entry::kBytes, 10);
-
-  // Setup the owned/owning sub sizes.
-  owned->add_not_owned_sub_size(10);
-  owner_1->add_not_owning_sub_size(6);
-  owner_2->add_not_owning_sub_size(7);
-  owner_3->add_not_owning_sub_size(5);
-  owner_4->add_not_owning_sub_size(8);
-
-  // Perform the computation.
-  CalculateNodeOwnershipCoefficient(owned);
-
-  // Ensure that the coefficients are correct.
-  ASSERT_DOUBLE_EQ(owned->owned_coefficient(), 2.0 / 10.0);
-  ASSERT_DOUBLE_EQ(owner_1->owning_coefficient(), 3.0 / 6.0);
-  ASSERT_DOUBLE_EQ(owner_2->owning_coefficient(), 4.0 / 7.0);
-  ASSERT_DOUBLE_EQ(owner_3->owning_coefficient(), 0.0 / 5.0);
-  ASSERT_DOUBLE_EQ(owner_4->owning_coefficient(), 1.0 / 8.0);
-}
-
-TEST_F(GraphProcessorTest, CalculateNodeCumulativeOwnershipCoefficient) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c1_c1 = process->CreateNode(kEmptyId, "c1/c1", false);
-  Node* c1_c2 = process->CreateNode(kEmptyId, "c1/c2", false);
-  Node* owned = process->CreateNode(kEmptyId, "owned", false);
-
-  graph.AddNodeOwnershipEdge(c1_c2, owned, 2);
-
-  // Ensure all nodes have sizes otherwise calculations will not happen.
-  c1_c1->AddEntry("size", Node::Entry::kBytes, 10);
-  c1_c2->AddEntry("size", Node::Entry::kBytes, 10);
-  owned->AddEntry("size", Node::Entry::kBytes, 10);
-
-  // Setup the owned/owning cummulative coefficients.
-  c1->set_cumulative_owning_coefficient(0.123);
-  c1->set_cumulative_owned_coefficient(0.456);
-  owned->set_cumulative_owning_coefficient(0.789);
-  owned->set_cumulative_owned_coefficient(0.987);
-
-  // Set owning and owned for the children.
-  c1_c1->set_owning_coefficient(0.654);
-  c1_c1->set_owned_coefficient(0.321);
-  c1_c2->set_owning_coefficient(0.135);
-  c1_c2->set_owned_coefficient(0.246);
-
-  // Perform the computation and check our answers.
-  CalculateNodeCumulativeOwnershipCoefficient(c1_c1);
-  ASSERT_DOUBLE_EQ(c1_c1->cumulative_owning_coefficient(), 0.123);
-  ASSERT_DOUBLE_EQ(c1_c1->cumulative_owned_coefficient(), 0.456 * 0.321);
-
-  CalculateNodeCumulativeOwnershipCoefficient(c1_c2);
-  ASSERT_DOUBLE_EQ(c1_c2->cumulative_owning_coefficient(), 0.135 * 0.789);
-  ASSERT_DOUBLE_EQ(c1_c2->cumulative_owned_coefficient(), 0.456 * 0.246);
-}
-
-TEST_F(GraphProcessorTest, CalculateNodeEffectiveSize) {
-  Process* process = graph.CreateGraphForProcess(1);
-
-  Node* c1 = process->CreateNode(kEmptyId, "c1", false);
-  Node* c1_c1 = process->CreateNode(kEmptyId, "c1/c1", false);
-  Node* c1_c2 = process->CreateNode(kEmptyId, "c1/c2", false);
-
-  // Ensure all nodes have sizes otherwise calculations will not happen.
-  c1->AddEntry("size", Node::Entry::kBytes, 200);
-  c1_c1->AddEntry("size", Node::Entry::kBytes, 32);
-  c1_c2->AddEntry("size", Node::Entry::kBytes, 20);
-
-  // Setup the owned/owning cummulative coefficients.
-  c1_c1->set_cumulative_owning_coefficient(0.123);
-  c1_c1->set_cumulative_owned_coefficient(0.456);
-  c1_c2->set_cumulative_owning_coefficient(0.789);
-  c1_c2->set_cumulative_owned_coefficient(0.987);
-
-  // Perform the computation and check our answers.
-  CalculateNodeEffectiveSize(c1_c1);
-  const Node::Entry& entry_c1_c1 =
-      c1_c1->entries()->find("effective_size")->second;
-  uint64_t expected_c1_c1 = static_cast<int>(0.123 * 0.456 * 32);
-  ASSERT_EQ(entry_c1_c1.value_uint64, expected_c1_c1);
-
-  CalculateNodeEffectiveSize(c1_c2);
-  const Node::Entry& entry_c1_c2 =
-      c1_c2->entries()->find("effective_size")->second;
-  uint64_t expected_c1_c2 = static_cast<int>(0.789 * 0.987 * 20);
-  ASSERT_EQ(entry_c1_c2.value_uint64, expected_c1_c2);
-
-  CalculateNodeEffectiveSize(c1);
-  const Node::Entry& entry_c1 = c1->entries()->find("effective_size")->second;
-  ASSERT_EQ(entry_c1.value_uint64, expected_c1_c1 + expected_c1_c2);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/graph_unittest.cc b/src/trace_processor/importers/memory_tracker/graph_unittest.cc
deleted file mode 100644
index 6017c73..0000000
--- a/src/trace_processor/importers/memory_tracker/graph_unittest.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph.h"
-
-#include "perfetto/base/build_config.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-using Node = GlobalNodeGraph::Node;
-using Process = GlobalNodeGraph::Process;
-
-const MemoryAllocatorNodeId kEmptyId;
-
-}  // namespace
-
-TEST(GlobalNodeGraphTest, CreateContainerForProcess) {
-  GlobalNodeGraph global_dump_graph;
-
-  Process* dump = global_dump_graph.CreateGraphForProcess(10);
-  ASSERT_NE(dump, nullptr);
-
-  auto* map = global_dump_graph.process_node_graphs().find(10)->second.get();
-  ASSERT_EQ(dump, map);
-}
-
-TEST(GlobalNodeGraphTest, AddNodeOwnershipEdge) {
-  GlobalNodeGraph global_dump_graph;
-  Node owner(global_dump_graph.shared_memory_graph(), nullptr);
-  Node owned(global_dump_graph.shared_memory_graph(), nullptr);
-
-  global_dump_graph.AddNodeOwnershipEdge(&owner, &owned, 1);
-
-  auto& edges = global_dump_graph.edges();
-  ASSERT_NE(edges.begin(), edges.end());
-
-  auto& edge = *edges.begin();
-  ASSERT_EQ(edge.source(), &owner);
-  ASSERT_EQ(edge.target(), &owned);
-  ASSERT_EQ(edge.priority(), 1);
-}
-
-TEST(GlobalNodeGraphTest, VisitInDepthFirstPostOrder) {
-  GlobalNodeGraph graph;
-  Process* process_1 = graph.CreateGraphForProcess(1);
-  Process* process_2 = graph.CreateGraphForProcess(2);
-
-  Node* c1 = process_1->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process_1->CreateNode(kEmptyId, "c2", false);
-  Node* c2_c1 = process_1->CreateNode(kEmptyId, "c2/c1", false);
-  Node* c2_c2 = process_1->CreateNode(kEmptyId, "c2/c2", false);
-
-  Node* c3 = process_2->CreateNode(kEmptyId, "c3", false);
-  Node* c3_c1 = process_2->CreateNode(kEmptyId, "c3/c1", false);
-  Node* c3_c2 = process_2->CreateNode(kEmptyId, "c3/c2", false);
-
-  // |c3_c2| owns |c2_c2|.
-  graph.AddNodeOwnershipEdge(c3_c2, c2_c2, 1);
-
-  // This method should always call owners and then children before the node
-  // itself.
-  auto iterator = graph.VisitInDepthFirstPostOrder();
-  ASSERT_EQ(iterator.next(), graph.shared_memory_graph()->root());
-  ASSERT_EQ(iterator.next(), c1);
-  ASSERT_EQ(iterator.next(), c2_c1);
-  ASSERT_EQ(iterator.next(), c3_c2);
-  ASSERT_EQ(iterator.next(), c2_c2);
-  ASSERT_EQ(iterator.next(), c2);
-  ASSERT_EQ(iterator.next(), process_1->root());
-  ASSERT_EQ(iterator.next(), c3_c1);
-  ASSERT_EQ(iterator.next(), c3);
-  ASSERT_EQ(iterator.next(), process_2->root());
-  ASSERT_EQ(iterator.next(), nullptr);
-}
-
-TEST(GlobalNodeGraphTest, VisitInDepthFirstPreOrder) {
-  GlobalNodeGraph graph;
-  Process* process_1 = graph.CreateGraphForProcess(1);
-  Process* process_2 = graph.CreateGraphForProcess(2);
-
-  Node* c1 = process_1->CreateNode(kEmptyId, "c1", false);
-  Node* c2 = process_1->CreateNode(kEmptyId, "c2", false);
-  Node* c2_c1 = process_1->CreateNode(kEmptyId, "c2/c1", false);
-  Node* c2_c2 = process_1->CreateNode(kEmptyId, "c2/c2", false);
-
-  Node* c3 = process_2->CreateNode(kEmptyId, "c3", false);
-  Node* c3_c1 = process_2->CreateNode(kEmptyId, "c3/c1", false);
-  Node* c3_c2 = process_2->CreateNode(kEmptyId, "c3/c2", false);
-
-  // |c2_c2| owns |c3_c2|. Note this is opposite of post-order.
-  graph.AddNodeOwnershipEdge(c2_c2, c3_c2, 1);
-
-  // This method should always call owners and then children after the node
-  // itself.
-  auto iterator = graph.VisitInDepthFirstPreOrder();
-  ASSERT_EQ(iterator.next(), graph.shared_memory_graph()->root());
-  ASSERT_EQ(iterator.next(), process_1->root());
-  ASSERT_EQ(iterator.next(), c1);
-  ASSERT_EQ(iterator.next(), c2);
-  ASSERT_EQ(iterator.next(), c2_c1);
-  ASSERT_EQ(iterator.next(), process_2->root());
-  ASSERT_EQ(iterator.next(), c3);
-  ASSERT_EQ(iterator.next(), c3_c1);
-  ASSERT_EQ(iterator.next(), c3_c2);
-  ASSERT_EQ(iterator.next(), c2_c2);
-  ASSERT_EQ(iterator.next(), nullptr);
-}
-
-TEST(ProcessTest, CreateAndFindNode) {
-  GlobalNodeGraph global_dump_graph;
-  Process graph(1, &global_dump_graph);
-
-  Node* first =
-      graph.CreateNode(MemoryAllocatorNodeId(1), "simple/test/1", false);
-  Node* second =
-      graph.CreateNode(MemoryAllocatorNodeId(2), "simple/test/2", false);
-  Node* third =
-      graph.CreateNode(MemoryAllocatorNodeId(3), "simple/other/1", false);
-  Node* fourth =
-      graph.CreateNode(MemoryAllocatorNodeId(4), "complex/path", false);
-  Node* fifth =
-      graph.CreateNode(MemoryAllocatorNodeId(5), "complex/path/child/1", false);
-
-  ASSERT_EQ(graph.FindNode("simple/test/1"), first);
-  ASSERT_EQ(graph.FindNode("simple/test/2"), second);
-  ASSERT_EQ(graph.FindNode("simple/other/1"), third);
-  ASSERT_EQ(graph.FindNode("complex/path"), fourth);
-  ASSERT_EQ(graph.FindNode("complex/path/child/1"), fifth);
-
-  auto& nodes_by_id = global_dump_graph.nodes_by_id();
-  ASSERT_EQ(nodes_by_id.find(MemoryAllocatorNodeId(1))->second, first);
-  ASSERT_EQ(nodes_by_id.find(MemoryAllocatorNodeId(2))->second, second);
-  ASSERT_EQ(nodes_by_id.find(MemoryAllocatorNodeId(3))->second, third);
-  ASSERT_EQ(nodes_by_id.find(MemoryAllocatorNodeId(4))->second, fourth);
-  ASSERT_EQ(nodes_by_id.find(MemoryAllocatorNodeId(5))->second, fifth);
-}
-
-TEST(ProcessTest, CreateNodeParent) {
-  GlobalNodeGraph global_dump_graph;
-  Process graph(1, &global_dump_graph);
-
-  Node* parent = graph.CreateNode(MemoryAllocatorNodeId(1), "simple", false);
-  Node* child =
-      graph.CreateNode(MemoryAllocatorNodeId(1), "simple/child", false);
-
-  ASSERT_EQ(parent->parent(), graph.root());
-  ASSERT_EQ(child->parent(), parent);
-}
-
-TEST(ProcessTest, WeakAndExplicit) {
-  GlobalNodeGraph global_dump_graph;
-  Process graph(1, &global_dump_graph);
-
-  Node* first =
-      graph.CreateNode(MemoryAllocatorNodeId(1), "simple/test/1", true);
-  Node* second =
-      graph.CreateNode(MemoryAllocatorNodeId(2), "simple/test/2", false);
-
-  ASSERT_TRUE(first->is_weak());
-  ASSERT_FALSE(second->is_weak());
-
-  ASSERT_TRUE(first->is_explicit());
-  ASSERT_TRUE(second->is_explicit());
-
-  Node* parent = graph.FindNode("simple/test");
-  ASSERT_NE(parent, nullptr);
-  ASSERT_FALSE(parent->is_weak());
-  ASSERT_FALSE(parent->is_explicit());
-
-  Node* grandparent = graph.FindNode("simple");
-  ASSERT_NE(grandparent, nullptr);
-  ASSERT_FALSE(grandparent->is_weak());
-  ASSERT_FALSE(grandparent->is_explicit());
-}
-
-TEST(NodeTest, GetChild) {
-  GlobalNodeGraph global_dump_graph;
-  Node node(global_dump_graph.shared_memory_graph(), nullptr);
-
-  ASSERT_EQ(node.GetChild("test"), nullptr);
-
-  Node child(global_dump_graph.shared_memory_graph(), &node);
-  node.InsertChild("child", &child);
-  ASSERT_EQ(node.GetChild("child"), &child);
-}
-
-TEST(NodeTest, InsertChild) {
-  GlobalNodeGraph global_dump_graph;
-  Node node(global_dump_graph.shared_memory_graph(), nullptr);
-
-  ASSERT_EQ(node.GetChild("test"), nullptr);
-
-  Node child(global_dump_graph.shared_memory_graph(), &node);
-  node.InsertChild("child", &child);
-  ASSERT_EQ(node.GetChild("child"), &child);
-}
-
-TEST(NodeTest, AddEntry) {
-  GlobalNodeGraph global_dump_graph;
-  Node node(global_dump_graph.shared_memory_graph(), nullptr);
-
-  node.AddEntry("scalar", Node::Entry::ScalarUnits::kBytes, 100ul);
-  ASSERT_EQ(node.entries()->size(), 1ul);
-
-  node.AddEntry("string", "data");
-  ASSERT_EQ(node.entries()->size(), 2ul);
-
-  auto scalar = node.entries()->find("scalar");
-  ASSERT_EQ(scalar->first, "scalar");
-  ASSERT_EQ(scalar->second.units, Node::Entry::ScalarUnits::kBytes);
-  ASSERT_EQ(scalar->second.value_uint64, 100ul);
-
-  auto string = node.entries()->find("string");
-  ASSERT_EQ(string->first, "string");
-  ASSERT_EQ(string->second.value_string, "data");
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc b/src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc
deleted file mode 100644
index 9d80101..0000000
--- a/src/trace_processor/importers/memory_tracker/memory_allocator_node_id.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-MemoryAllocatorNodeId::MemoryAllocatorNodeId(uint64_t id) : id_(id) {}
-
-MemoryAllocatorNodeId::MemoryAllocatorNodeId() : MemoryAllocatorNodeId(0u) {}
-
-std::string MemoryAllocatorNodeId::ToString() const {
-  size_t max_size = 19;  // Max uint64 is 0xFFFFFFFFFFFFFFFF + 1 for null byte.
-  std::string buf;
-  buf.resize(max_size);
-  auto final_size = snprintf(&buf[0], max_size, "%" PRIu64, id_);
-  PERFETTO_DCHECK(final_size >= 0);
-  buf.resize(static_cast<size_t>(final_size));  // Cuts off the final null byte.
-  return buf;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/raw_memory_graph_node.cc b/src/trace_processor/importers/memory_tracker/raw_memory_graph_node.cc
deleted file mode 100644
index 74a9207..0000000
--- a/src/trace_processor/importers/memory_tracker/raw_memory_graph_node.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-const char RawMemoryGraphNode::kNameSize[] = "size";
-const char RawMemoryGraphNode::kNameObjectCount[] = "object_count";
-const char RawMemoryGraphNode::kTypeScalar[] = "scalar";
-const char RawMemoryGraphNode::kTypeString[] = "string";
-const char RawMemoryGraphNode::kUnitsBytes[] = "bytes";
-const char RawMemoryGraphNode::kUnitsObjects[] = "objects";
-
-RawMemoryGraphNode::MemoryNodeEntry::MemoryNodeEntry(const std::string& n,
-                                                     const std::string& u,
-                                                     uint64_t v)
-    : name(n), units(u), entry_type(kUint64), value_uint64(v) {}
-
-RawMemoryGraphNode::MemoryNodeEntry::MemoryNodeEntry(const std::string& n,
-                                                     const std::string& u,
-                                                     const std::string& v)
-    : name(n), units(u), entry_type(kString), value_string(v) {}
-
-bool RawMemoryGraphNode::MemoryNodeEntry::operator==(
-    const MemoryNodeEntry& rhs) const {
-  if (!(name == rhs.name && units == rhs.units && entry_type == rhs.entry_type))
-    return false;
-  switch (entry_type) {
-    case EntryType::kUint64:
-      return value_uint64 == rhs.value_uint64;
-    case EntryType::kString:
-      return value_string == rhs.value_string;
-  }
-  return false;
-}
-
-RawMemoryGraphNode::RawMemoryGraphNode(const std::string& absolute_name,
-                                       LevelOfDetail level,
-                                       MemoryAllocatorNodeId id)
-    : absolute_name_(absolute_name),
-      level_of_detail_(level),
-      id_(id),
-      flags_(Flags::kDefault) {}
-
-RawMemoryGraphNode::RawMemoryGraphNode(
-    const std::string& absolute_name,
-    LevelOfDetail level,
-    MemoryAllocatorNodeId id,
-    std::vector<RawMemoryGraphNode::MemoryNodeEntry>&& entries)
-    : absolute_name_(absolute_name),
-      level_of_detail_(level),
-      entries_(std::move(entries)),
-      id_(id),
-      flags_(Flags::kDefault) {}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc b/src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc
deleted file mode 100644
index faaf084..0000000
--- a/src/trace_processor/importers/memory_tracker/raw_process_memory_node.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <functional>
-#include <memory>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-RawProcessMemoryNode::RawProcessMemoryNode(LevelOfDetail level_of_detail,
-                                           AllocatorNodeEdgesMap&& edges_map,
-                                           MemoryNodesMap&& nodes_map)
-    : level_of_detail_(level_of_detail),
-      allocator_nodes_edges_(std::move(edges_map)),
-      allocator_nodes_(std::move(nodes_map)) {}
-
-RawProcessMemoryNode::RawProcessMemoryNode(RawProcessMemoryNode&&) = default;
-RawProcessMemoryNode::~RawProcessMemoryNode() = default;
-RawProcessMemoryNode& RawProcessMemoryNode::operator=(RawProcessMemoryNode&&) =
-    default;
-
-RawMemoryGraphNode* RawProcessMemoryNode::GetAllocatorNode(
-    const std::string& absolute_name) const {
-  auto it = allocator_nodes_.find(absolute_name);
-  if (it != allocator_nodes_.end())
-    return it->second.get();
-  return nullptr;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/memory_tracker/raw_process_memory_node_unittest.cc b/src/trace_processor/importers/memory_tracker/raw_process_memory_node_unittest.cc
deleted file mode 100644
index 91a27ec..0000000
--- a/src/trace_processor/importers/memory_tracker/raw_process_memory_node_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h"
-
-#include <stddef.h>
-
-#include <unordered_map>
-
-#include "perfetto/base/build_config.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-const LevelOfDetail kLevelOfDetail = LevelOfDetail::kDetailed;
-
-}  // namespace
-
-TEST(RawProcessMemoryNodeTest, MoveConstructor) {
-  const auto source = MemoryAllocatorNodeId(42);
-  const auto target = MemoryAllocatorNodeId(4242);
-
-  std::unique_ptr<RawMemoryGraphNode> mad1(
-      new RawMemoryGraphNode("mad1", kLevelOfDetail, source));
-  std::unique_ptr<RawMemoryGraphNode> mad2(
-      new RawMemoryGraphNode("mad2", kLevelOfDetail, target));
-
-  RawProcessMemoryNode::MemoryNodesMap nodesMap;
-  nodesMap.emplace(mad1->absolute_name(), std::move(mad1));
-  nodesMap.emplace(mad2->absolute_name(), std::move(mad2));
-
-  std::unique_ptr<MemoryGraphEdge> edge(
-      new MemoryGraphEdge(source, target, 10, false));
-
-  RawProcessMemoryNode::AllocatorNodeEdgesMap edgesMap;
-  edgesMap.emplace(edge->source, std::move(edge));
-
-  RawProcessMemoryNode pmd1(kLevelOfDetail, std::move(edgesMap),
-                            std::move(nodesMap));
-
-  RawProcessMemoryNode pmd2(std::move(pmd1));
-
-  EXPECT_EQ(1u, pmd2.allocator_nodes().count("mad1"));
-  EXPECT_EQ(1u, pmd2.allocator_nodes().count("mad2"));
-  EXPECT_EQ(LevelOfDetail::kDetailed, pmd2.level_of_detail());
-  EXPECT_EQ(1u, pmd2.allocator_nodes_edges().size());
-}
-
-TEST(RawProcessMemoryNodeTest, MoveAssignment) {
-  const auto source = MemoryAllocatorNodeId(42);
-  const auto target = MemoryAllocatorNodeId(4242);
-
-  std::unique_ptr<RawMemoryGraphNode> mad1(
-      new RawMemoryGraphNode("mad1", kLevelOfDetail, source));
-  std::unique_ptr<RawMemoryGraphNode> mad2(
-      new RawMemoryGraphNode("mad2", kLevelOfDetail, target));
-
-  RawProcessMemoryNode::MemoryNodesMap nodesMap;
-  nodesMap.emplace(mad1->absolute_name(), std::move(mad1));
-  nodesMap.emplace(mad2->absolute_name(), std::move(mad2));
-
-  std::unique_ptr<MemoryGraphEdge> edge(
-      new MemoryGraphEdge(source, target, 10, false));
-
-  RawProcessMemoryNode::AllocatorNodeEdgesMap edgesMap;
-  edgesMap.emplace(edge->source, std::move(edge));
-
-  RawProcessMemoryNode pmd1(kLevelOfDetail, std::move(edgesMap),
-                            std::move(nodesMap));
-
-  RawProcessMemoryNode pmd2(LevelOfDetail::kBackground);
-
-  pmd2 = std::move(pmd1);
-  EXPECT_EQ(1u, pmd2.allocator_nodes().count("mad1"));
-  EXPECT_EQ(1u, pmd2.allocator_nodes().count("mad2"));
-  EXPECT_EQ(0u, pmd2.allocator_nodes().count("mad3"));
-  EXPECT_EQ(LevelOfDetail::kDetailed, pmd2.level_of_detail());
-  EXPECT_EQ(1u, pmd2.allocator_nodes_edges().size());
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/ninja/ninja_log_parser.cc b/src/trace_processor/importers/ninja/ninja_log_parser.cc
index af668f1..1618bc7 100644
--- a/src/trace_processor/importers/ninja/ninja_log_parser.cc
+++ b/src/trace_processor/importers/ninja/ninja_log_parser.cc
@@ -15,7 +15,6 @@
  */
 
 #include "src/trace_processor/importers/ninja/ninja_log_parser.h"
-
 #include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
@@ -171,8 +170,7 @@
       snprintf(name, sizeof(name), "Worker %zu", workers.size() + 1);
       StringId name_id = ctx_->storage->InternString(name);
       auto utid = ctx_->process_tracker->UpdateThread(worker_id, job.build_id);
-      ctx_->process_tracker->UpdateThreadNameByUtid(utid, name_id,
-                                                    ThreadNamePriority::kOther);
+      ctx_->process_tracker->SetThreadNameIfUnset(utid, name_id);
       TrackId track_id = ctx_->track_tracker->InternThreadTrack(utid);
       workers.emplace_back(Worker{/*busy_until=*/job.end_ms, track_id});
       worker = &workers.back();
diff --git a/src/trace_processor/importers/ninja/ninja_log_parser.h b/src/trace_processor/importers/ninja/ninja_log_parser.h
index f010e73..280fa5a 100644
--- a/src/trace_processor/importers/ninja/ninja_log_parser.h
+++ b/src/trace_processor/importers/ninja/ninja_log_parser.h
@@ -21,10 +21,9 @@
 
 #include <map>
 #include <string>
-#include <vector>
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/importers/common/trace_parser.h"
+#include "src/trace_processor/chunked_trace_reader.h"
+#include "src/trace_processor/trace_parser.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/importers/proto/android_probes_module.cc b/src/trace_processor/importers/proto/android_probes_module.cc
index 6047419..28405d1 100644
--- a/src/trace_processor/importers/proto/android_probes_module.cc
+++ b/src/trace_processor/importers/proto/android_probes_module.cc
@@ -17,10 +17,8 @@
 #include "src/trace_processor/importers/proto/android_probes_module.h"
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/string_writer.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/trace_processor/importers/proto/android_probes_parser.h"
-#include "src/trace_processor/importers/proto/android_probes_tracker.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
 #include "src/trace_processor/trace_sorter.h"
 
@@ -30,46 +28,6 @@
 
 namespace perfetto {
 namespace trace_processor {
-namespace {
-
-const char* MapToFriendlyPowerRailName(base::StringView raw) {
-  if (raw == "S4M_VDD_CPUCL0") {
-    return "cpu.little";
-  } else if (raw == "S3M_VDD_CPUCL1") {
-    return "cpu.mid";
-  } else if (raw == "S2M_VDD_CPUCL2") {
-    return "cpu.big";
-  } else if (raw == "S5M_VDD_INT") {
-    return "system.fabric";
-  } else if (raw == "PPVAR_VSYS_PWR_DISP") {
-    return "display";
-  } else if (raw == "VSYS_PWR_MODEM") {
-    return "modem";
-  } else if (raw == "S1M_VDD_MIF") {
-    return "memory.interface";
-  } else if (raw == "VSYS_PWR_WLAN_BT") {
-    return "wifi.bt";
-  } else if (raw == "L2S_VDD_AOC_RET") {
-    return "aoc.memory";
-  } else if (raw == "S9S_VDD_AOC") {
-    return "aoc.logic";
-  } else if (raw == "S5S_VDDQ_MEM") {
-    return "ddr.a";
-  } else if (raw == "S10S_VDD2L") {
-    return "ddr.b";
-  } else if (raw == "S4S_VDD2H_MEM") {
-    return "ddr.c";
-  } else if (raw == "S2S_VDD_G3D") {
-    return "gpu";
-  } else if (raw == "L9S_GNSS_CORE") {
-    return "gps";
-  } else if (raw == "VSYS_PWR_RFFE") {
-    return "radio.frontend";
-  }
-  return nullptr;
-}
-
-}  // namespace
 
 using perfetto::protos::pbzero::TracePacket;
 
@@ -105,27 +63,24 @@
   auto power_rails = decoder.power_rails();
   protos::pbzero::PowerRails::Decoder evt(power_rails.data, power_rails.size);
 
-  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;
+  // Break out the rail descriptor into its own packet with the same timestamp
+  // as the packet itself.
+  if (evt.has_rail_descriptor()) {
+    protozero::HeapBuffered<protos::pbzero::TracePacket> desc_packet;
+    desc_packet->set_timestamp(static_cast<uint64_t>(packet_timestamp));
+
+    auto* rails = desc_packet->set_power_rails();
+    for (auto it = evt.rail_descriptor(); it; ++it) {
+      protozero::ConstBytes desc = *it;
+      rails->add_rail_descriptor()->AppendRawProtoBytes(desc.data, desc.size);
     }
-    char counter_name[255];
-    base::StringWriter writer(counter_name, base::ArraySize(counter_name));
-    const char* friendly_name = MapToFriendlyPowerRailName(desc.rail_name());
-    if (friendly_name) {
-      writer.AppendStringView("power.rails.");
-      writer.AppendStringView(friendly_name);
-    } else {
-      writer.AppendStringView("power.");
-      writer.AppendStringView(desc.rail_name());
-      writer.AppendStringView("_uws");
-    }
-    AndroidProbesTracker::GetOrCreate(context_)->SetPowerRailName(
-        desc.index(), context_->storage->InternString(writer.GetStringView()));
+
+    std::vector<uint8_t> vec = desc_packet.SerializeAsArray();
+    std::unique_ptr<uint8_t[]> buffer(new uint8_t[vec.size()]);
+    memcpy(buffer.get(), vec.data(), vec.size());
+    context_->sorter->PushTracePacket(
+        packet_timestamp, state,
+        TraceBlobView(std::move(buffer), 0, vec.size()));
   }
 
   // For each energy data message, turn it into its own trace packet
diff --git a/src/trace_processor/importers/proto/android_probes_parser.cc b/src/trace_processor/importers/proto/android_probes_parser.cc
index c001cb5..f308913 100644
--- a/src/trace_processor/importers/proto/android_probes_parser.cc
+++ b/src/trace_processor/importers/proto/android_probes_parser.cc
@@ -58,8 +58,7 @@
   if (evt.has_charge_counter_uah()) {
     TrackId track =
         context_->track_tracker->InternGlobalCounterTrack(batt_charge_id_);
-    context_->event_tracker->PushCounter(
-        ts, static_cast<double>(evt.charge_counter_uah()), track);
+    context_->event_tracker->PushCounter(ts, evt.charge_counter_uah(), track);
   }
   if (evt.has_capacity_percent()) {
     TrackId track =
@@ -70,49 +69,59 @@
   if (evt.has_current_ua()) {
     TrackId track =
         context_->track_tracker->InternGlobalCounterTrack(batt_current_id_);
-    context_->event_tracker->PushCounter(
-        ts, static_cast<double>(evt.current_ua()), track);
+    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, static_cast<double>(evt.current_avg_ua()), track);
+    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);
-
-  // Descriptors should have been processed at tokenization time.
-  PERFETTO_DCHECK(evt.has_energy_data());
-
-  // Because we have some special code in the tokenization phase, we
-  // will only every get one EnergyData message per packet. Therefore,
-  // we can just read the data directly.
-  auto it = evt.energy_data();
-  protos::pbzero::PowerRails::EnergyData::Decoder desc(*it);
-
-  auto opt_rail_name =
-      AndroidProbesTracker::GetOrCreate(context_)->GetPowerRailName(
-          desc.index());
-  if (opt_rail_name) {
-    // The tokenization makes sure that this field is always present and
-    // is equal to the packet's timestamp (as the packet was forged in
-    // the tokenizer).
-    PERFETTO_DCHECK(desc.has_timestamp_ms());
-    PERFETTO_DCHECK(ts / 1000000 == static_cast<int64_t>(desc.timestamp_ms()));
-
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(*opt_rail_name);
-    context_->event_tracker->PushCounter(ts, static_cast<double>(desc.energy()),
-                                         track);
-  } else {
-    context_->storage->IncrementStats(stats::power_rail_unknown_index);
+  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);
+    }
   }
 
-  // DCHECK that we only got one message.
-  PERFETTO_DCHECK(!++it);
+  if (evt.has_energy_data()) {
+    // Because we have some special code in the tokenization phase, we
+    // will only every get one EnergyData message per packet. Therefore,
+    // we can just read the data directly.
+    auto it = evt.energy_data();
+    protos::pbzero::PowerRails::EnergyData::Decoder desc(*it);
+    if (desc.index() < power_rails_strs_id_.size()) {
+      // The tokenization makes sure that this field is always present and
+      // is equal to the packet's timestamp (as the packet was forged in
+      // the tokenizer).
+      PERFETTO_DCHECK(desc.has_timestamp_ms());
+      PERFETTO_DCHECK(ts / 1000000 ==
+                      static_cast<int64_t>(desc.timestamp_ms()));
+
+      TrackId track = context_->track_tracker->InternGlobalCounterTrack(
+          power_rails_strs_id_[desc.index()]);
+      context_->event_tracker->PushCounter(ts, desc.energy(), track);
+    } else {
+      context_->storage->IncrementStats(stats::power_rail_unknown_index);
+    }
+
+    // DCHECK that we only got one message.
+    PERFETTO_DCHECK(!++it);
+  }
 }
 
 void AndroidProbesParser::ParseAndroidLogPacket(ConstBytes blob) {
diff --git a/src/trace_processor/importers/proto/android_probes_parser.h b/src/trace_processor/importers/proto/android_probes_parser.h
index a0da014..8c4994d 100644
--- a/src/trace_processor/importers/proto/android_probes_parser.h
+++ b/src/trace_processor/importers/proto/android_probes_parser.h
@@ -50,6 +50,7 @@
   const StringId batt_current_id_;
   const StringId batt_current_avg_id_;
   const StringId screen_state_id_;
+  std::vector<StringId> power_rails_strs_id_;
 };
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/android_probes_tracker.h b/src/trace_processor/importers/proto/android_probes_tracker.h
index fa0ffe2..6e2e193 100644
--- a/src/trace_processor/importers/proto/android_probes_tracker.h
+++ b/src/trace_processor/importers/proto/android_probes_tracker.h
@@ -51,21 +51,8 @@
     seen_packages_.emplace(std::move(package_name));
   }
 
-  base::Optional<StringId> GetPowerRailName(uint32_t index) {
-    if (index >= power_rails_strs_id_.size())
-      return base::nullopt;
-    return power_rails_strs_id_[index];
-  }
-
-  void SetPowerRailName(uint32_t index, StringId name) {
-    if (power_rails_strs_id_.size() <= index)
-      power_rails_strs_id_.resize(index + 1);
-    power_rails_strs_id_[index] = name;
-  }
-
  private:
   std::set<std::string> seen_packages_;
-  std::vector<StringId> power_rails_strs_id_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/args_table_utils.cc b/src/trace_processor/importers/proto/args_table_utils.cc
new file mode 100644
index 0000000..b1dd2e0
--- /dev/null
+++ b/src/trace_processor/importers/proto/args_table_utils.cc
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/args_table_utils.h"
+
+#include "protos/perfetto/common/descriptor.pbzero.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
+#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+ProtoToArgsTable::ProtoToArgsTable(TraceProcessorContext* context)
+    : context_(context) {
+  constexpr int kDefaultSize = 64;
+  key_prefix_.reserve(kDefaultSize);
+  flat_key_prefix_.reserve(kDefaultSize);
+}
+
+util::Status ProtoToArgsTable::AddProtoFileDescriptor(
+    const uint8_t* proto_descriptor_array,
+    size_t proto_descriptor_array_size) {
+  return pool_.AddFromFileDescriptorSet(proto_descriptor_array,
+                                        proto_descriptor_array_size);
+}
+
+util::Status ProtoToArgsTable::InternProtoFieldsIntoArgsTable(
+    const protozero::ConstBytes& cb,
+    const std::string& type,
+    const std::vector<uint16_t>& fields,
+    ArgsTracker::BoundInserter* inserter,
+    PacketSequenceStateGeneration* sequence_state) {
+  auto idx = pool_.FindDescriptorIdx(type);
+  if (!idx) {
+    return util::Status("Failed to find proto descriptor");
+  }
+
+  auto descriptor = pool_.descriptors()[*idx];
+
+  protozero::ProtoDecoder decoder(cb);
+  for (protozero::Field f = decoder.ReadField(); f.valid();
+       f = decoder.ReadField()) {
+    auto it = std::find(fields.begin(), fields.end(), f.id());
+    if (it == fields.end()) {
+      continue;
+    }
+
+    auto field_idx = descriptor.FindFieldIdxByTag(*it);
+    if (!field_idx) {
+      return util::Status("Failed to find proto descriptor");
+    }
+    auto field = descriptor.fields()[*field_idx];
+    auto status =
+        InternProtoIntoArgsTable(f.as_bytes(), field.resolved_type_name(),
+                                 inserter, sequence_state, field.name());
+
+    if (!status.ok()) {
+      return status;
+    }
+  }
+
+  return util::OkStatus();
+}
+
+util::Status ProtoToArgsTable::InternProtoIntoArgsTable(
+    const protozero::ConstBytes& cb,
+    const std::string& type,
+    ArgsTracker::BoundInserter* inserter,
+    PacketSequenceStateGeneration* sequence_state,
+    const std::string& key_prefix) {
+  key_prefix_.assign(key_prefix);
+  flat_key_prefix_.assign(key_prefix);
+
+  ParsingOverrideState state{context_, sequence_state};
+  return InternProtoIntoArgsTableInternal(cb, type, inserter, state);
+}
+
+util::Status ProtoToArgsTable::InternProtoIntoArgsTableInternal(
+    const protozero::ConstBytes& cb,
+    const std::string& type,
+    ArgsTracker::BoundInserter* inserter,
+    ParsingOverrideState state) {
+  // Given |type| field the proto descriptor for this proto message.
+  auto opt_proto_descriptor_idx = pool_.FindDescriptorIdx(type);
+  if (!opt_proto_descriptor_idx) {
+    return util::Status("Failed to find proto descriptor");
+  }
+  auto proto_descriptor = pool_.descriptors()[*opt_proto_descriptor_idx];
+
+  // For repeated fields, contains mapping from field descriptor index to
+  // current count of how many fields have been serialized with this field.
+  std::unordered_map<size_t, int> repeated_field_index;
+
+  // Parse this message field by field until there are no bytes left.
+  protozero::ProtoDecoder decoder(cb.data, cb.size);
+  for (auto field = decoder.ReadField(); field.valid();
+       field = decoder.ReadField()) {
+    auto opt_field_descriptor_idx =
+        proto_descriptor.FindFieldIdxByTag(field.id());
+    if (!opt_field_descriptor_idx) {
+      // Since the binary descriptor is compiled in it is possible we're seeing
+      // a new message that our descriptors don't have. Just skip the field.
+      continue;
+    }
+    const auto& field_descriptor =
+        proto_descriptor.fields()[*opt_field_descriptor_idx];
+
+    std::string prefix_part = field_descriptor.name();
+    if (field_descriptor.is_repeated()) {
+      std::string number =
+          std::to_string(repeated_field_index[*opt_field_descriptor_idx]);
+      prefix_part.reserve(prefix_part.length() + number.length() + 2);
+      prefix_part.append("[");
+      prefix_part.append(number);
+      prefix_part.append("]");
+      repeated_field_index[*opt_field_descriptor_idx]++;
+    }
+
+    // In the args table we build up message1.message2.field1 as the column
+    // name. This will append the ".field1" suffix to |key_prefix| and then
+    // remove it when it goes out of scope.
+    ScopedStringAppender scoped_prefix(prefix_part, &key_prefix_);
+    ScopedStringAppender scoped_flat_key_prefix(field_descriptor.name(),
+                                                &flat_key_prefix_);
+
+    // If we have an override parser then use that instead and move onto the
+    // next loop.
+    auto it = FindOverride(key_prefix_);
+    if (it != overrides_.end()) {
+      if (it->second(state, field, inserter)) {
+        continue;
+      }
+    }
+
+    // If this is not a message we can just immediately add the column name and
+    // get the value out of |field|. However if it is a message we need to
+    // recurse into it.
+    if (field_descriptor.type() ==
+        protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
+      auto status = InternProtoIntoArgsTableInternal(
+          field.as_bytes(), field_descriptor.resolved_type_name(), inserter,
+          state);
+      if (!status.ok()) {
+        return status;
+      }
+    } else {
+      const StringId key_id =
+          state.context->storage->InternString(base::StringView(key_prefix_));
+      const StringId flat_key_id = state.context->storage->InternString(
+          base::StringView(flat_key_prefix_));
+      inserter->AddArg(
+          flat_key_id, key_id,
+          ConvertProtoTypeToVariadic(field_descriptor, field, state));
+    }
+  }
+  PERFETTO_DCHECK(decoder.bytes_left() == 0);
+  return util::OkStatus();
+}
+
+void ProtoToArgsTable::AddParsingOverride(std::string field,
+                                          ParsingOverride func) {
+  overrides_.emplace_back(std::move(field), func);
+}
+
+ProtoToArgsTable::OverrideIterator ProtoToArgsTable::FindOverride(
+    const std::string& field) {
+  return std::find_if(
+      overrides_.begin(), overrides_.end(),
+      [&field](const std::pair<std::string, ParsingOverride>& overrides) {
+        return overrides.first == field;
+      });
+}
+
+Variadic ProtoToArgsTable::ConvertProtoTypeToVariadic(
+    const FieldDescriptor& descriptor,
+    const protozero::Field& field,
+    ParsingOverrideState state) {
+  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
+  switch (descriptor.type()) {
+    case FieldDescriptorProto::TYPE_INT32:
+    case FieldDescriptorProto::TYPE_SFIXED32:
+    case FieldDescriptorProto::TYPE_FIXED32:
+      return Variadic::Integer(field.as_int32());
+    case FieldDescriptorProto::TYPE_SINT32:
+      return Variadic::Integer(field.as_sint32());
+    case FieldDescriptorProto::TYPE_INT64:
+    case FieldDescriptorProto::TYPE_SFIXED64:
+    case FieldDescriptorProto::TYPE_FIXED64:
+      return Variadic::Integer(field.as_int64());
+    case FieldDescriptorProto::TYPE_SINT64:
+      return Variadic::Integer(field.as_sint64());
+    case FieldDescriptorProto::TYPE_UINT32:
+      return Variadic::UnsignedInteger(field.as_uint32());
+    case FieldDescriptorProto::TYPE_UINT64:
+      return Variadic::UnsignedInteger(field.as_uint64());
+    case FieldDescriptorProto::TYPE_BOOL:
+      return Variadic::Boolean(field.as_bool());
+    case FieldDescriptorProto::TYPE_DOUBLE:
+      return Variadic::Real(field.as_double());
+    case FieldDescriptorProto::TYPE_FLOAT:
+      return Variadic::Real(static_cast<double>(field.as_float()));
+    case FieldDescriptorProto::TYPE_STRING:
+      return Variadic::String(
+          state.context->storage->InternString(field.as_string()));
+    case FieldDescriptorProto::TYPE_ENUM: {
+      auto opt_enum_descriptor_idx =
+          pool_.FindDescriptorIdx(descriptor.resolved_type_name());
+      if (!opt_enum_descriptor_idx) {
+        // Fall back to the integer representation of the field.
+        return Variadic::Integer(field.as_int32());
+      }
+      auto opt_enum_string =
+          pool_.descriptors()[*opt_enum_descriptor_idx].FindEnumString(
+              field.as_int32());
+      if (!opt_enum_string) {
+        // Fall back to the integer representation of the field.
+        return Variadic::Integer(field.as_int32());
+      }
+      return Variadic::String(state.context->storage->InternString(
+          base::StringView(*opt_enum_string)));
+    }
+    default: {
+      PERFETTO_FATAL(
+          "Tried to write value of type field %s (in proto type "
+          "%s) which has type enum %d",
+          descriptor.name().c_str(), descriptor.resolved_type_name().c_str(),
+          descriptor.type());
+    }
+  }
+  return Variadic{};
+}
+
+ProtoToArgsTable::ScopedStringAppender::ScopedStringAppender(
+    const std::string& append,
+    std::string* dest)
+    : old_size_(dest->size()), str_(dest) {
+  if (dest->empty()) {
+    str_->reserve(append.size());
+  } else {
+    str_->reserve(old_size_ + 1 + append.size());
+    str_->append(".");
+  }
+  str_->append(append);
+}
+
+ProtoToArgsTable::ScopedStringAppender::~ScopedStringAppender() {
+  str_->erase(old_size_);
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/args_table_utils.h b/src/trace_processor/importers/proto/args_table_utils.h
new file mode 100644
index 0000000..c103a1f
--- /dev/null
+++ b/src/trace_processor/importers/proto/args_table_utils.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_ARGS_TABLE_UTILS_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ARGS_TABLE_UTILS_H_
+
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/trace_processor/status.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/proto/packet_sequence_state.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/util/descriptors.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// ProtoToArgsTable encapsulates the process of taking an arbitrary proto and
+// associating each field as a column in an args set. This is done by traversing
+// the proto using reflection (with descriptors provided by
+// AddProtoFileDescriptor()) and creating column names equal to this traversal.
+//
+// I.E. given a proto like
+//
+// package perfetto.protos;
+// message SubMessage {
+//   optional int32 field = 1;
+// }
+// message MainMessage {
+//   optional int32 field1 = 1;
+//   optional string field2 = 2;
+//   optional SubMessage field3 = 3;
+// }
+//
+// We will get the args set columns "field1", "field2", "field3.field" and will
+// store the values found inside as the result.
+//
+// Usage of this is as follows:
+//
+// ProtoToArgsTable helper( /* provide current parsing state */ ...);
+// helper.AddProtoFileDescriptor(
+//     /* provide descriptor generated by tools/gen_binary_descriptors */);
+// helper.InternProtoIntoArgs(const_bytes, ".perfetto.protos.MainMessage",
+// row_id);
+//
+// Optionally one can handle particular fields as well by providing a
+// ParsingOverride through AddParsingOverride.
+//
+// helper.AddParsingOverride("field3.field",
+// [](const ProtoToArgsTable::ParsingOverrideState& state,
+//    const protozero::Field& field) {
+//   if (!should_handle()) {
+//     return false;
+//   }
+//   // Parse |field| and add any rows for it to args using |state|.
+//   return true;
+// });
+class ProtoToArgsTable {
+ public:
+  struct ParsingOverrideState {
+    TraceProcessorContext* context;
+    PacketSequenceStateGeneration* sequence_state;
+  };
+  using ParsingOverride = bool (*)(const ParsingOverrideState& state,
+                                   const protozero::Field&,
+                                   ArgsTracker::BoundInserter* inserter);
+
+  // ScopedStringAppender will add |append| to |dest| when constructed and
+  // erases the appended suffix from |dest| when it goes out of scope. Thus
+  // |dest| must be valid for the entire lifetime of ScopedStringAppender.
+  //
+  // This is useful as we descend into a proto since the column names just
+  // appended with ".field_name" as we go lower.
+  //
+  // I.E. message1.message2.field_name1 is a column, but we'll then need to
+  // append message1.message2.field_name2 afterwards so we only need to append
+  // "field_name1" within some scope. This is public so people implementing a
+  // ParsingOverride can follow this same behaviour.
+  class ScopedStringAppender {
+   public:
+    ScopedStringAppender(const std::string& append, std::string* dest);
+    ~ScopedStringAppender();
+
+   private:
+    size_t old_size_;
+    std::string* str_;
+  };
+
+  // |context| provides access to storage.
+  explicit ProtoToArgsTable(TraceProcessorContext* context);
+
+  // Adds a compile time reflection of a set of proto files. You must provide
+  // the descriptor before attempting to parse this with
+  // InternProtoIntoArgsTable().
+  //
+  // To generate |proto_descriptor_array| please see
+  // tools/gen_binary_descriptors and ensure the proto you are interested in is
+  // listed as a whitelisted proto. You can then find your variable inside the
+  // header location specified inside that python script.
+  util::Status AddProtoFileDescriptor(const uint8_t* proto_descriptor_array,
+                                      size_t proto_descriptor_array_size);
+
+  // Given a view of bytes that represent a serialized protozero message of
+  // |type| we will parse each field into the Args table using RowId |row|,
+  // adding |key_prefix| in front of each name (can be an empty string if no
+  // prefix is needed).
+  //
+  // Returns on any error with a status describing the problem. However any
+  // added values before encountering the error will be added to the
+  // args_tracker.
+  //
+  // Note:
+  // |type| must be the fully qualified name, but with a '.' added to the
+  // beginning. I.E. ".perfetto.protos.TrackEvent". And must match one of the
+  // descriptors already added through |AddProtoFileDescriptor|.
+  //
+  // IMPORTANT: currently bytes fields are not supported.
+  //
+  // TODO(b/145578432): Add support for byte fields.
+  util::Status InternProtoIntoArgsTable(
+      const protozero::ConstBytes& cb,
+      const std::string& type,
+      ArgsTracker::BoundInserter* inserter,
+      PacketSequenceStateGeneration* sequence_state,
+      const std::string& key_prefix);
+
+  // Parse several fields with ids given in |fields| using reflection.
+  util::Status InternProtoFieldsIntoArgsTable(
+      const protozero::ConstBytes& cb,
+      const std::string& type,
+      const std::vector<uint16_t>& fields,
+      ArgsTracker::BoundInserter* inserter,
+      PacketSequenceStateGeneration* sequence_state);
+
+  // Installs an override for the field at the specified path. We will invoke
+  // |parsing_override| when the field is encountered.
+  //
+  // If |parsing_override| returns false we will continue and fallback on
+  // default behaviour. However if it returns true we will assume that it added
+  // all required messages to the args_tracker.
+  //
+  // Note |field_path| must be the full path separated by periods. I.E. in the
+  // proto
+  //
+  // message SubMessage {
+  //   optional int32 field = 1;
+  // }
+  // message MainMessage {
+  //   optional SubMessage field1 = 1;
+  //   optional SubMessage field2 = 2;
+  // }
+  //
+  // To override the handling of both SubMessage fields you must add two parsing
+  // overrides. One with a |field_path| == "field1.field" and another with
+  // "field2.field".
+  void AddParsingOverride(std::string field_path,
+                          ParsingOverride parsing_override);
+
+ private:
+  util::Status InternProtoIntoArgsTableInternal(
+      const protozero::ConstBytes& cb,
+      const std::string& type,
+      ArgsTracker::BoundInserter* inserter,
+      ParsingOverrideState state);
+
+  using OverrideIterator =
+      std::vector<std::pair<std::string, ParsingOverride>>::iterator;
+  OverrideIterator FindOverride(const std::string& field);
+
+  Variadic ConvertProtoTypeToVariadic(const FieldDescriptor& descriptor,
+                                      const protozero::Field& field,
+                                      ParsingOverrideState state);
+
+  std::vector<std::pair<std::string, ParsingOverride>> overrides_;
+  DescriptorPool pool_;
+  std::string key_prefix_;
+  std::string flat_key_prefix_;
+  TraceProcessorContext* context_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ARGS_TABLE_UTILS_H_
diff --git a/src/trace_processor/importers/proto/args_table_utils_unittest.cc b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
new file mode 100644
index 0000000..d4c280f
--- /dev/null
+++ b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/args_table_utils.h"
+
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/common/descriptor.pbzero.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
+#include "src/protozero/test/example_proto/test_messages.descriptor.h"
+#include "src/protozero/test/example_proto/test_messages.pbzero.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+constexpr size_t kChunkSize = 42;
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::NiceMock;
+
+class ArgsTableUtilsTest : public ::testing::Test {
+ protected:
+  ArgsTableUtilsTest() {
+    context_.storage.reset(new TraceStorage);
+    storage_ = context_.storage.get();
+    context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
+    context_.args_tracker.reset(new ArgsTracker(&context_));
+    sequence_state_.reset(new PacketSequenceState(&context_));
+  }
+
+  /**
+   * Check whether the argument set contains the value with given flat_key and
+   * key and is equal to the given value.
+   */
+  bool HasArg(ArgSetId set_id,
+              const base::StringView& flat_key,
+              const base::StringView& key,
+              Variadic value) {
+    const auto& args = storage_->arg_table();
+    auto key_id = storage_->string_pool().GetId(key);
+    EXPECT_TRUE(key_id);
+    auto flat_key_id = storage_->string_pool().GetId(flat_key);
+    EXPECT_TRUE(flat_key_id);
+
+    RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
+    bool found = false;
+    for (auto it = rm.IterateRows(); it; it.Next()) {
+      if (args.key()[it.row()] == key_id) {
+        EXPECT_EQ(args.flat_key()[it.row()], flat_key_id);
+        if (storage_->GetArgValue(it.row()) == value) {
+          found = true;
+          break;
+        }
+      }
+    }
+    return found;
+  }
+
+  /**
+   * Implementation of HasArg for a simple case when flat_key is equals to key,
+   * so that two won't have to be repeated for each assertion.
+   */
+  bool HasArg(ArgSetId set_id, const base::StringView& key, Variadic value) {
+    return HasArg(set_id, key, key, value);
+  }
+
+  uint32_t arg_set_id_ = 1;
+  std::unique_ptr<PacketSequenceState> sequence_state_;
+  TraceProcessorContext context_;
+  TraceStorage* storage_;
+};
+
+TEST_F(ArgsTableUtilsTest, EnsureTestMessageProtoParses) {
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+}
+
+TEST_F(ArgsTableUtilsTest, BasicSingleLayerProto) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<EveryField> msg{kChunkSize, kChunkSize};
+  msg->set_field_int32(-1);
+  msg->set_field_int64(-333123456789ll);
+  msg->set_field_uint32(600);
+  msg->set_field_uint64(333123456789ll);
+  msg->set_field_sint32(-5);
+  msg->set_field_sint64(-9000);
+  msg->set_field_fixed32(12345);
+  msg->set_field_fixed64(444123450000ll);
+  msg->set_field_sfixed32(-69999);
+  msg->set_field_sfixed64(-200);
+  msg->set_field_double(0.5555);
+  msg->set_field_bool(true);
+  msg->set_small_enum(SmallEnum::TO_BE);
+  msg->set_signed_enum(SignedEnum::NEGATIVE);
+  msg->set_big_enum(BigEnum::BEGIN);
+  msg->set_nested_enum(EveryField::PONG);
+  msg->set_field_float(3.14f);
+  msg->set_field_string("FizzBuzz");
+  msg->add_repeated_int32(1);
+  msg->add_repeated_int32(-1);
+  msg->add_repeated_int32(100);
+  msg->add_repeated_int32(2000000);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.EveryField", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_int32", Variadic::Integer(-1)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_int64",
+                     Variadic::Integer(-333123456789ll)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_uint32",
+                     Variadic::UnsignedInteger(600)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_uint64",
+                     Variadic::UnsignedInteger(333123456789ll)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_sint32", Variadic::Integer(-5)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_sint64", Variadic::Integer(-9000)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_fixed32", Variadic::Integer(12345)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_fixed64",
+                     Variadic::Integer(444123450000ll)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_sfixed32",
+                     Variadic::Integer(-69999)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_sfixed64", Variadic::Integer(-200)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_double", Variadic::Real(0.5555)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "field_bool", Variadic::Boolean(true)));
+  EXPECT_TRUE(HasArg(
+      ArgSetId(arg_set_id_), "small_enum",
+      Variadic::String(*context_.storage->string_pool().GetId("TO_BE"))));
+  EXPECT_TRUE(HasArg(
+      ArgSetId(arg_set_id_), "signed_enum",
+      Variadic::String(*context_.storage->string_pool().GetId("NEGATIVE"))));
+  EXPECT_TRUE(HasArg(
+      ArgSetId(arg_set_id_), "big_enum",
+      Variadic::String(*context_.storage->string_pool().GetId("BEGIN"))));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "nested_enum",
+             Variadic::String(*context_.storage->string_pool().GetId("PONG"))));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "field_float",
+                     Variadic::Real(static_cast<double>(3.14f))));
+  ASSERT_TRUE(context_.storage->string_pool().GetId("FizzBuzz"));
+  EXPECT_TRUE(HasArg(
+      ArgSetId(arg_set_id_), "field_string",
+      Variadic::String(*context_.storage->string_pool().GetId("FizzBuzz"))));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "repeated_int32",
+                     "repeated_int32[0]", Variadic::Integer(1)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "repeated_int32",
+                     "repeated_int32[1]", Variadic::Integer(-1)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "repeated_int32",
+                     "repeated_int32[2]", Variadic::Integer(100)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "repeated_int32",
+                     "repeated_int32[3]", Variadic::Integer(2000000)));
+}
+
+TEST_F(ArgsTableUtilsTest, NestedProto) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
+  msg->set_super_nested()->set_value_c(3);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.NestedA", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "super_nested.value_c",
+                     Variadic::Integer(3)));
+}
+
+TEST_F(ArgsTableUtilsTest, CamelCaseFieldsProto) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<CamelCaseFields> msg{kChunkSize, kChunkSize};
+  msg->set_barbaz(true);
+  msg->set_moomoo(true);
+  msg->set___bigbang(true);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.CamelCaseFields", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "barBaz", Variadic::Boolean(true)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "MooMoo", Variadic::Boolean(true)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "__bigBang", Variadic::Boolean(true)));
+}
+
+TEST_F(ArgsTableUtilsTest, NestedProtoParsingOverrideHandled) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
+  msg->set_super_nested()->set_value_c(3);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  helper.AddParsingOverride(
+      "super_nested.value_c",
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, ArgsTracker::BoundInserter* inserter) {
+        EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
+        EXPECT_TRUE(state.context);
+        EXPECT_TRUE(state.sequence_state);
+        auto id = state.context->storage->InternString(
+            "super_nested.value_b.replaced");
+        int32_t val = field.as_int32();
+        inserter->AddArg(id, id, Variadic::Integer(val + 1));
+        // We've handled this field by adding the desired args.
+        return true;
+      });
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.NestedA", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "super_nested.value_b.replaced",
+                     Variadic::Integer(4)));
+}
+
+TEST_F(ArgsTableUtilsTest, NestedProtoParsingOverrideSkipped) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
+  msg->set_super_nested()->set_value_c(3);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  helper.AddParsingOverride(
+      "super_nested.value_c",
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, ArgsTracker::BoundInserter*) {
+        static int val = 0;
+        ++val;
+        EXPECT_EQ(1, val);
+        EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
+        EXPECT_TRUE(state.sequence_state);
+        EXPECT_TRUE(state.context);
+        // By returning false we expect this field to be handled like regular.
+        return false;
+      });
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.NestedA", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "super_nested.value_c",
+                     Variadic::Integer(3)));
+}
+
+TEST_F(ArgsTableUtilsTest, LookingUpInternedStateParsingOverride) {
+  using namespace protozero::test::protos::pbzero;
+  // The test proto, we will use |value_c| as the source_location iid.
+  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
+  msg->set_super_nested()->set_value_c(3);
+  auto binary_proto = msg.SerializeAsArray();
+
+  // The interned source location.
+  protozero::HeapBuffered<protos::pbzero::SourceLocation> src_loc{kChunkSize,
+                                                                  kChunkSize};
+  src_loc->set_iid(3);
+  src_loc->set_file_name("test_file_name");
+  // We need to update sequence_state to point to it.
+  auto binary_data = src_loc.SerializeAsArray();
+  std::unique_ptr<uint8_t[]> buffer(new uint8_t[binary_data.size()]);
+  for (size_t i = 0; i < binary_data.size(); ++i) {
+    buffer.get()[i] = binary_data[i];
+  }
+  TraceBlobView blob(std::move(buffer), 0, binary_data.size());
+  sequence_state_->InternMessage(
+      protos::pbzero::InternedData::kSourceLocationsFieldNumber,
+      std::move(blob));
+
+  ProtoToArgsTable helper(&context_);
+  // Now we override the behaviour of |value_c| so we can expand the iid into
+  // multiple args rows.
+  helper.AddParsingOverride(
+      "super_nested.value_c",
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, ArgsTracker::BoundInserter* inserter) {
+        EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
+        auto* decoder = state.sequence_state->LookupInternedMessage<
+            protos::pbzero::InternedData::kSourceLocationsFieldNumber,
+            protos::pbzero::SourceLocation>(field.as_uint64());
+        if (!decoder) {
+          // Lookup failed fall back on default behaviour.
+          return false;
+        }
+        TraceStorage* storage = state.context->storage.get();
+        auto file_name_id = storage->InternString("file_name");
+        auto line_number_id = storage->InternString("line_number");
+        auto file_id = storage->InternString(decoder->file_name());
+        inserter->AddArg(file_name_id, file_name_id, Variadic::String(file_id));
+        inserter->AddArg(line_number_id, line_number_id, Variadic::Integer(2));
+        return true;
+      });
+
+  storage_->mutable_track_table()->Insert({});
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.NestedA", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "");
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+  auto file_name_id = storage_->string_pool().GetId("test_file_name");
+  ASSERT_TRUE(file_name_id);
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "file_name",
+                     Variadic::String(*file_name_id)));
+  EXPECT_TRUE(
+      HasArg(ArgSetId(arg_set_id_), "line_number", Variadic::Integer(2)));
+}
+
+TEST_F(ArgsTableUtilsTest, NonEmptyPrefix) {
+  using namespace protozero::test::protos::pbzero;
+  protozero::HeapBuffered<EveryField> msg{kChunkSize, kChunkSize};
+  msg->add_repeated_int32(1);
+  msg->add_repeated_int32(-1);
+  msg->add_repeated_int32(100);
+  msg->add_repeated_int32(2000000);
+
+  auto binary_proto = msg.SerializeAsArray();
+
+  storage_->mutable_track_table()->Insert({});
+  ProtoToArgsTable helper(&context_);
+  auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
+                                              kTestMessagesDescriptor.size());
+  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
+                           << status.message();
+
+  auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
+  status = helper.InternProtoIntoArgsTable(
+      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
+      ".protozero.test.protos.EveryField", &inserter,
+      sequence_state_->current_generation(), /* key_prefix= */ "prefix");
+
+  EXPECT_TRUE(status.ok()) << "InternProtoIntoArgsTable failed with error: "
+                           << status.message();
+
+  context_.args_tracker->Flush();
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "prefix.repeated_int32",
+                     "prefix.repeated_int32[0]", Variadic::Integer(1)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "prefix.repeated_int32",
+                     "prefix.repeated_int32[1]", Variadic::Integer(-1)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "prefix.repeated_int32",
+                     "prefix.repeated_int32[2]", Variadic::Integer(100)));
+  EXPECT_TRUE(HasArg(ArgSetId(arg_set_id_), "prefix.repeated_int32",
+                     "prefix.repeated_int32[3]", Variadic::Integer(2000000)));
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/async_track_set_tracker.cc b/src/trace_processor/importers/proto/async_track_set_tracker.cc
deleted file mode 100644
index 4f2714c..0000000
--- a/src/trace_processor/importers/proto/async_track_set_tracker.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
-
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-AsyncTrackSetTracker::AsyncTrackSetTracker(TraceProcessorContext* context)
-    : context_(context) {}
-
-AsyncTrackSetTracker::TrackSetId AsyncTrackSetTracker::InternGlobalTrackSet(
-    StringId name) {
-  auto it = global_track_set_ids_.find(name);
-  if (it != global_track_set_ids_.end()) {
-    return it->second;
-  }
-
-  uint32_t id = static_cast<uint32_t>(track_sets_.size());
-  TrackSet set;
-  set.global_track_name = name;
-  set.type = TrackSetType::kGlobal;
-  set.nesting_behaviour = NestingBehaviour::kUnnestable;
-  track_sets_.emplace_back(set);
-
-  return global_track_set_ids_[name] = id;
-}
-
-AsyncTrackSetTracker::TrackSetId AsyncTrackSetTracker::InternAndroidSet(
-    UniquePid upid,
-    StringId name) {
-  AndroidTuple tuple{upid, name};
-
-  auto it = android_track_set_ids_.find(tuple);
-  if (it != android_track_set_ids_.end())
-    return it->second;
-
-  uint32_t id = static_cast<uint32_t>(track_sets_.size());
-
-  TrackSet set;
-  set.android_tuple = tuple;
-  set.type = TrackSetType::kAndroid;
-  set.nesting_behaviour = NestingBehaviour::kLegacySaturatingUnnestable;
-  track_sets_.emplace_back(set);
-
-  android_track_set_ids_[tuple] = id;
-  return id;
-}
-
-AsyncTrackSetTracker::TrackSetId AsyncTrackSetTracker::InternFrameTimelineSet(
-    UniquePid upid,
-    StringId name) {
-  FrameTimelineTuple tuple{upid, name};
-
-  auto it = frame_timeline_track_set_ids_.find(tuple);
-  if (it != frame_timeline_track_set_ids_.end())
-    return it->second;
-
-  uint32_t id = static_cast<uint32_t>(track_sets_.size());
-
-  TrackSet set;
-  set.frame_timeline_tuple = tuple;
-  set.type = TrackSetType::kFrameTimeline;
-  set.nesting_behaviour = NestingBehaviour::kUnnestable;
-  track_sets_.emplace_back(set);
-
-  frame_timeline_track_set_ids_[tuple] = id;
-  return id;
-}
-
-TrackId AsyncTrackSetTracker::Begin(TrackSetId id, int64_t cookie) {
-  PERFETTO_DCHECK(id < track_sets_.size());
-
-  TrackSet& set = track_sets_[id];
-  TrackState& state = GetOrCreateTrackForCookie(set, cookie);
-  switch (set.nesting_behaviour) {
-    case NestingBehaviour::kLegacySaturatingUnnestable:
-      PERFETTO_DCHECK(state.nest_count <= 1);
-      state.nest_count = 1;
-      break;
-    case NestingBehaviour::kUnnestable:
-      PERFETTO_DCHECK(state.nest_count == 0);
-      state.nest_count++;
-      break;
-  }
-  return state.id;
-}
-
-TrackId AsyncTrackSetTracker::End(TrackSetId id, int64_t cookie) {
-  PERFETTO_DCHECK(id < track_sets_.size());
-
-  TrackSet& set = track_sets_[id];
-  TrackState& state = GetOrCreateTrackForCookie(set, cookie);
-
-  // It's possible to have a nest count of 0 even when we know about the track.
-  // Suppose the following sequence of events for some |id| and |cookie|:
-  //   Begin
-  //   (trace starts)
-  //   Begin
-  //   End
-  //   End <- nest count == 0 here even though we have a record of this track.
-  if (state.nest_count > 0)
-    state.nest_count--;
-  return state.id;
-}
-
-TrackId AsyncTrackSetTracker::Scoped(TrackSetId id, int64_t ts, int64_t dur) {
-  PERFETTO_DCHECK(id < track_sets_.size());
-
-  TrackSet& set = track_sets_[id];
-  PERFETTO_DCHECK(set.nesting_behaviour == NestingBehaviour::kUnnestable);
-
-  auto it = std::find_if(
-      set.tracks.begin(), set.tracks.end(), [ts](const TrackState& state) {
-        return state.slice_type == TrackState::SliceType::kTimestamp &&
-               state.ts_end <= ts;
-      });
-  if (it != set.tracks.end())
-    return it->id;
-
-  TrackState state;
-  state.slice_type = TrackState::SliceType::kTimestamp;
-  state.ts_end = ts + dur;
-  state.id = CreateTrackForSet(set);
-  set.tracks.emplace_back(state);
-
-  return state.id;
-}
-
-AsyncTrackSetTracker::TrackState&
-AsyncTrackSetTracker::GetOrCreateTrackForCookie(TrackSet& set, int64_t cookie) {
-  auto it = std::find_if(
-      set.tracks.begin(), set.tracks.end(), [cookie](const TrackState& state) {
-        return state.slice_type == TrackState::SliceType::kCookie &&
-               state.cookie == cookie;
-      });
-  if (it != set.tracks.end())
-    return *it;
-
-  it = std::find_if(
-      set.tracks.begin(), set.tracks.end(), [](const TrackState& state) {
-        return state.slice_type == TrackState::SliceType::kCookie &&
-               state.nest_count == 0;
-      });
-  if (it != set.tracks.end()) {
-    // Adopt this track for the cookie to make sure future slices with this
-    // cookie also get associated to this track.
-    it->cookie = cookie;
-    return *it;
-  }
-
-  TrackState state;
-  state.id = CreateTrackForSet(set);
-  state.slice_type = TrackState::SliceType::kCookie;
-  state.cookie = cookie;
-  state.nest_count = 0;
-  set.tracks.emplace_back(state);
-
-  return set.tracks.back();
-}
-
-TrackId AsyncTrackSetTracker::CreateTrackForSet(const TrackSet& set) {
-  switch (set.type) {
-    case TrackSetType::kGlobal:
-      return context_->track_tracker->CreateGlobalAsyncTrack(
-          set.global_track_name);
-    case TrackSetType::kAndroid:
-      return context_->track_tracker->CreateAndroidAsyncTrack(
-          set.android_tuple.name, set.android_tuple.upid);
-    case TrackSetType::kFrameTimeline:
-      return context_->track_tracker->CreateFrameTimelineAsyncTrack(
-          set.frame_timeline_tuple.name, set.frame_timeline_tuple.upid);
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/async_track_set_tracker.h b/src/trace_processor/importers/proto/async_track_set_tracker.h
deleted file mode 100644
index b3dd836..0000000
--- a/src/trace_processor/importers/proto/async_track_set_tracker.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ASYNC_TRACK_SET_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ASYNC_TRACK_SET_TRACKER_H_
-
-#include <unordered_map>
-
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-class AsyncTrackSetTrackerUnittest;
-
-// Tracker used to reduce the number of trace processor tracks corresponding
-// to a single "UI track".
-//
-// UIs using trace processor want to display all slices in the same context
-// (e.g. same upid) and same name into a single track. However, because trace
-// processor does not allow parallel slices on a single track (because it breaks
-// things like span join, self time computation etc.), at the trace processor
-// level these parallel slices are put on different tracks.
-//
-// Creating a new track for every event, however, leads to an explosion of
-// tracks which is undesirable. This class exists to multiplex slices so that
-// n events correspond to a single track in a way which minimises the number of
-// tracks which needs to be merged by the UI.
-//
-// The intended usage of this class is for callers to first call one of the
-// Intern* methods to obtain a TrackSetId followed by Begin/End just before
-// calling into SliceTracker's Begin/End respectively. For example:
-//  TrackSetId set_id = track_set_tracker->InternAndroidSet(upid, name);
-//  if (event.begin) {
-//    TrackId id = track_set_tracker->Begin(set_id, cookie);
-//    slice_tracker->Begin(ts, id, ...)
-//  } else {
-//    ... (same thing with end)
-//  }
-// Alternatively, instead of Begin/End, Scoped can also be called if supported
-// by the track type.
-class AsyncTrackSetTracker {
- public:
-  using TrackSetId = uint32_t;
-
-  explicit AsyncTrackSetTracker(TraceProcessorContext* context);
-  ~AsyncTrackSetTracker() = default;
-
-  // Interns a set of global async slice tracks associated with the given name.
-  TrackSetId InternGlobalTrackSet(StringId name);
-
-  // Interns a set of Android async slice tracks associated with the given
-  // upid and name.
-  // Scoped is *not* supported for this track set type.
-  TrackSetId InternAndroidSet(UniquePid, StringId name);
-
-  // Starts a new slice on the given async track set which has the given cookie.
-  TrackId Begin(TrackSetId id, int64_t cookie);
-
-  // Interns the expected and actual timeline tracks coming from FrameTimeline
-  // producer for the associated upid.
-  TrackSetId InternFrameTimelineSet(UniquePid, StringId name);
-
-  // Ends a new slice on the given async track set which has the given cookie.
-  TrackId End(TrackSetId id, int64_t cookie);
-
-  // Creates a scoped slice on the given async track set.
-  // This method makes sure that any other slice in this track set does
-  // not happen simultaneously on the returned track.
-  // Only supported on selected track set types; read the documentation for
-  // the Intern* method for your track type to check if supported.
-  TrackId Scoped(TrackSetId id, int64_t ts, int64_t dur);
-
- private:
-  friend class AsyncTrackSetTrackerUnittest;
-
-  struct AndroidTuple {
-    UniquePid upid;
-    StringId name;
-
-    friend bool operator<(const AndroidTuple& l, const AndroidTuple& r) {
-      return std::tie(l.upid, l.name) < std::tie(r.upid, r.name);
-    }
-  };
-
-  struct FrameTimelineTuple {
-    UniquePid upid;
-    StringId name;
-
-    friend bool operator<(const FrameTimelineTuple& l,
-                          const FrameTimelineTuple& r) {
-      return std::tie(l.upid, l.name) < std::tie(r.upid, r.name);
-    }
-  };
-
-  // Indicates the nesting behaviour of slices associated to a single slice
-  // stack.
-  enum class NestingBehaviour {
-    // Indicates that slices are unnestable; that is, it is an error
-    // to call Begin -> Begin with a single cookie without End inbetween.
-    // This pattern should be the default behaviour that most async slices
-    // should use.
-    kUnnestable,
-
-    // Indicates that slices are unnestable but also saturating; that is
-    // calling Begin -> Begin only causes a single Begin to be recorded.
-    // This is only really useful for Android async slices which have this
-    // behaviour for legacy reasons. See the comment in
-    // SystraceParser::ParseSystracePoint for information on why
-    // this behaviour exists.
-    kLegacySaturatingUnnestable,
-  };
-
-  enum class TrackSetType {
-    kGlobal,
-    kAndroid,
-    kFrameTimeline,
-  };
-
-  struct TrackState {
-    TrackId id;
-
-    enum class SliceType { kCookie, kTimestamp };
-    SliceType slice_type;
-
-    union {
-      // Only valid for |slice_type| == |SliceType::kCookie|.
-      int64_t cookie;
-
-      // Only valid for |slice_type| == |SliceType::kTimestamp|.
-      int64_t ts_end;
-    };
-
-    // Only used for |slice_type| == |SliceType::kCookie|.
-    uint32_t nest_count;
-  };
-
-  struct TrackSet {
-    TrackSetType type;
-    union {
-      StringId global_track_name;
-      // Only set when |type| == |TrackSetType::kAndroid|.
-      AndroidTuple android_tuple;
-      // Only set when |type| == |TrackSetType::kFrameTimeline|.
-      FrameTimelineTuple frame_timeline_tuple;
-    };
-    NestingBehaviour nesting_behaviour;
-    std::vector<TrackState> tracks;
-  };
-
-  TrackSetId CreateUnnestableTrackSetForTesting(UniquePid upid, StringId name) {
-    AsyncTrackSetTracker::TrackSet set;
-    set.android_tuple = AndroidTuple{upid, name};
-    set.type = AsyncTrackSetTracker::TrackSetType::kAndroid;
-    set.nesting_behaviour = NestingBehaviour::kUnnestable;
-    track_sets_.emplace_back(set);
-    return static_cast<TrackSetId>(track_sets_.size() - 1);
-  }
-
-  // Returns the state for a track using the following algorithm:
-  // 1. If a track exists with the given cookie in the track set, returns
-  //    that track.
-  // 2. Otherwise, looks for any track in the set which is "open" (i.e.
-  //    does not have another slice currently scheduled).
-  // 3. Otherwise, creates a new track and associates it with the set.
-  TrackState& GetOrCreateTrackForCookie(TrackSet& set, int64_t cookie);
-
-  TrackId CreateTrackForSet(const TrackSet& set);
-
-  std::map<StringId, TrackSetId> global_track_set_ids_;
-  std::map<AndroidTuple, TrackSetId> android_track_set_ids_;
-  std::map<FrameTimelineTuple, TrackSetId> frame_timeline_track_set_ids_;
-  std::vector<TrackSet> track_sets_;
-
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ASYNC_TRACK_SET_TRACKER_H_
diff --git a/src/trace_processor/importers/proto/async_track_set_tracker_unittest.cc b/src/trace_processor/importers/proto/async_track_set_tracker_unittest.cc
deleted file mode 100644
index 852c5c2..0000000
--- a/src/trace_processor/importers/proto/async_track_set_tracker_unittest.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
-
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/global_args_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class AsyncTrackSetTrackerUnittest : public testing::Test {
- public:
-  AsyncTrackSetTrackerUnittest() {
-    context_.storage.reset(new TraceStorage());
-    context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
-    context_.args_tracker.reset(new ArgsTracker(&context_));
-    context_.track_tracker.reset(new TrackTracker(&context_));
-    context_.async_track_set_tracker.reset(new AsyncTrackSetTracker(&context_));
-
-    storage_ = context_.storage.get();
-    tracker_ = context_.async_track_set_tracker.get();
-
-    unnestable_id_ = tracker_->CreateUnnestableTrackSetForTesting(
-        1, storage_->InternString("test"));
-    legacy_unnestable_id_ =
-        tracker_->InternAndroidSet(2, storage_->InternString("test"));
-  }
-
- protected:
-  TraceStorage* storage_ = nullptr;
-  AsyncTrackSetTracker* tracker_ = nullptr;
-
-  AsyncTrackSetTracker::TrackSetId unnestable_id_;
-  AsyncTrackSetTracker::TrackSetId legacy_unnestable_id_;
-
- private:
-  TraceProcessorContext context_;
-};
-
-namespace {
-
-TEST_F(AsyncTrackSetTrackerUnittest, Smoke) {
-  auto set_id = tracker_->InternAndroidSet(1, storage_->InternString("test"));
-
-  auto begin = tracker_->Begin(set_id, 1);
-  auto end = tracker_->End(set_id, 1);
-
-  ASSERT_EQ(begin, end);
-
-  uint32_t row = *storage_->process_track_table().id().IndexOf(begin);
-  ASSERT_EQ(storage_->process_track_table().upid()[row], 1u);
-  ASSERT_EQ(storage_->process_track_table().name()[row],
-            storage_->InternString("test"));
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, EndFirst) {
-  auto end = tracker_->End(unnestable_id_, 1);
-
-  uint32_t row = *storage_->process_track_table().id().IndexOf(end);
-  ASSERT_EQ(storage_->process_track_table().upid()[row], 1u);
-  ASSERT_EQ(storage_->process_track_table().name()[row],
-            storage_->InternString("test"));
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, LegacySaturating) {
-  auto begin = tracker_->Begin(legacy_unnestable_id_, 1);
-  auto begin_2 = tracker_->Begin(legacy_unnestable_id_, 1);
-
-  ASSERT_EQ(begin, begin_2);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, Unnestable) {
-  auto begin = tracker_->Begin(unnestable_id_, 1);
-  auto end = tracker_->End(unnestable_id_, 1);
-  auto begin_2 = tracker_->Begin(unnestable_id_, 1);
-
-  ASSERT_EQ(begin, end);
-  ASSERT_EQ(begin, begin_2);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, UnnestableMultipleEndAfterBegin) {
-  auto begin = tracker_->Begin(unnestable_id_, 1);
-  auto end = tracker_->End(unnestable_id_, 1);
-  auto end_2 = tracker_->End(unnestable_id_, 1);
-
-  ASSERT_EQ(begin, end);
-  ASSERT_EQ(end, end_2);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, OnlyScoped) {
-  TrackId a = tracker_->Scoped(unnestable_id_, 100, 10);
-  TrackId b = tracker_->Scoped(unnestable_id_, 105, 2);
-  TrackId c = tracker_->Scoped(unnestable_id_, 107, 3);
-  TrackId d = tracker_->Scoped(unnestable_id_, 110, 5);
-
-  ASSERT_NE(a, b);
-  ASSERT_EQ(b, c);
-  ASSERT_EQ(a, d);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, MixScopedAndBeginEnd) {
-  TrackId a = tracker_->Scoped(unnestable_id_, 100, 10);
-
-  TrackId begin = tracker_->Begin(unnestable_id_, 777);
-  TrackId end = tracker_->End(unnestable_id_, 777);
-
-  TrackId b = tracker_->Scoped(unnestable_id_, 105, 2);
-
-  ASSERT_NE(a, begin);
-  ASSERT_NE(b, begin);
-  ASSERT_EQ(begin, end);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, DifferentTracksInterleave) {
-  TrackId b1 = tracker_->Begin(unnestable_id_, 666);
-  TrackId b2 = tracker_->Begin(legacy_unnestable_id_, 777);
-  TrackId e1 = tracker_->End(unnestable_id_, 666);
-  TrackId e2 = tracker_->End(legacy_unnestable_id_, 777);
-
-  ASSERT_EQ(b1, e1);
-  ASSERT_EQ(b2, e2);
-  ASSERT_NE(b1, b2);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, DifferentCookieInterleave) {
-  TrackId b1 = tracker_->Begin(legacy_unnestable_id_, 666);
-  TrackId b2 = tracker_->Begin(legacy_unnestable_id_, 777);
-  TrackId e1 = tracker_->End(legacy_unnestable_id_, 666);
-  TrackId e2 = tracker_->End(legacy_unnestable_id_, 777);
-
-  ASSERT_EQ(b1, e1);
-  ASSERT_EQ(b2, e2);
-  ASSERT_NE(b1, b2);
-}
-
-TEST_F(AsyncTrackSetTrackerUnittest, DifferentCookieSequential) {
-  TrackId b1 = tracker_->Begin(legacy_unnestable_id_, 666);
-  TrackId e1 = tracker_->End(legacy_unnestable_id_, 666);
-  TrackId b2 = tracker_->Begin(legacy_unnestable_id_, 777);
-  TrackId e2 = tracker_->End(legacy_unnestable_id_, 777);
-
-  ASSERT_EQ(b1, e1);
-  ASSERT_EQ(b1, b2);
-  ASSERT_EQ(b2, e2);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/chrome_string_lookup.cc b/src/trace_processor/importers/proto/chrome_string_lookup.cc
deleted file mode 100644
index 1559daf..0000000
--- a/src/trace_processor/importers/proto/chrome_string_lookup.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/chrome_string_lookup.h"
-
-#include "perfetto/ext/base/utils.h"
-#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
-#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-using ::perfetto::protos::pbzero::ChromeProcessDescriptor;
-using ::perfetto::protos::pbzero::ChromeThreadDescriptor;
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-struct ProcessName {
-  protos::pbzero::ChromeProcessDescriptor::ProcessType type;
-  const char* name;
-};
-
-constexpr ProcessName kProcessNames[] = {
-    {ChromeProcessDescriptor::PROCESS_UNSPECIFIED, nullptr},
-    {ChromeProcessDescriptor::PROCESS_BROWSER, "Browser"},
-    {ChromeProcessDescriptor::PROCESS_RENDERER, "Renderer"},
-    {ChromeProcessDescriptor::PROCESS_UTILITY, "Utility"},
-    {ChromeProcessDescriptor::PROCESS_ZYGOTE, "SandboxHelper"},
-    {ChromeProcessDescriptor::PROCESS_GPU, "Gpu"},
-    {ChromeProcessDescriptor::PROCESS_PPAPI_PLUGIN, "PpapiPlugin"},
-    {ChromeProcessDescriptor::PROCESS_PPAPI_BROKER, "PpapiBroker"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_NETWORK,
-     "Service: network.mojom.NetworkService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_TRACING,
-     "Service: tracing.mojom.TracingService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_STORAGE,
-     "Service: storage.mojom.StorageService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_AUDIO,
-     "Service: audio.mojom.AudioService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_DATA_DECODER,
-     "Service: data_decoder.mojom.DataDecoderService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_UTIL_WIN,
-     "Service: chrome.mojom.UtilWin"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_PROXY_RESOLVER,
-     "Service: proxy_resolver.mojom.ProxyResolverFactory"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_CDM,
-     "Service: media.mojom.CdmService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_VIDEO_CAPTURE,
-     "Service: video_capture.mojom.VideoCaptureService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_UNZIPPER,
-     "Service: unzip.mojom.Unzipper"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_MIRRORING,
-     "Service: mirroring.mojom.MirroringService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_FILEPATCHER,
-     "Service: patch.mojom.FilePatcher"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_TTS,
-     "Service: chromeos.tts.mojom.TtsService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_PRINTING,
-     "Service: printing.mojom.PrintingService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_QUARANTINE,
-     "Service: quarantine.mojom.Quarantine"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_CROS_LOCALSEARCH,
-     "Service: chromeos.local_search_service.mojom.LocalSearchService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_CROS_ASSISTANT_AUDIO_DECODER,
-     "Service: chromeos.assistant.mojom.AssistantAudioDecoderFactory"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_FILEUTIL,
-     "Service: chrome.mojom.FileUtilService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_PRINTCOMPOSITOR,
-     "Service: printing.mojom.PrintCompositor"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_PAINTPREVIEW,
-     "Service: paint_preview.mojom.PaintPreviewCompositorCollection"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_SPEECHRECOGNITION,
-     "Service: media.mojom.SpeechRecognitionService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_XRDEVICE,
-     "Service: device.mojom.XRDeviceService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_READICON,
-     "Service: chrome.mojom.UtilReadIcon"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_LANGUAGEDETECTION,
-     "Service: language_detection.mojom.LanguageDetectionService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_SHARING,
-     "Service: sharing.mojom.Sharing"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_MEDIAPARSER,
-     "Service: chrome.mojom.MediaParserFactory"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_QRCODEGENERATOR,
-     "Service: qrcode_generator.mojom.QRCodeGeneratorService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_PROFILEIMPORT,
-     "Service: chrome.mojom.ProfileImport"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_IME,
-     "Service: chromeos.ime.mojom.ImeService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_RECORDING,
-     "Service: recording.mojom.RecordingService"},
-    {ChromeProcessDescriptor::PROCESS_SERVICE_SHAPEDETECTION,
-     "Service: shape_detection.mojom.ShapeDetectionService"},
-};
-
-struct ThreadName {
-  protos::pbzero::ChromeThreadDescriptor::ThreadType type;
-  const char* name;
-};
-
-constexpr ThreadName kThreadNames[] = {
-    {ChromeThreadDescriptor::THREAD_UNSPECIFIED, nullptr},
-    {ChromeThreadDescriptor::THREAD_MAIN, "CrProcessMain"},
-    {ChromeThreadDescriptor::THREAD_IO, "ChromeIOThread"},
-    {ChromeThreadDescriptor::THREAD_NETWORK_SERVICE, "NetworkService"},
-    {ChromeThreadDescriptor::THREAD_POOL_BG_WORKER,
-     "ThreadPoolBackgroundWorker&"},
-    {ChromeThreadDescriptor::THREAD_POOL_FG_WORKER,
-     "ThreadPoolForegroundWorker&"},
-    {ChromeThreadDescriptor::THREAD_POOL_BG_BLOCKING,
-     "ThreadPoolSingleThreadBackgroundBlocking&"},
-    {ChromeThreadDescriptor::THREAD_POOL_FG_BLOCKING,
-     "ThreadPoolSingleThreadForegroundBlocking&"},
-    {ChromeThreadDescriptor::THREAD_POOL_SERVICE, "ThreadPoolService"},
-    {ChromeThreadDescriptor::THREAD_COMPOSITOR, "Compositor"},
-    {ChromeThreadDescriptor::THREAD_VIZ_COMPOSITOR, "VizCompositorThread"},
-    {ChromeThreadDescriptor::THREAD_COMPOSITOR_WORKER, "CompositorTileWorker&"},
-    {ChromeThreadDescriptor::THREAD_SERVICE_WORKER, "ServiceWorkerThread&"},
-    {ChromeThreadDescriptor::THREAD_MEMORY_INFRA, "MemoryInfra"},
-    {ChromeThreadDescriptor::THREAD_SAMPLING_PROFILER, "StackSamplingProfiler"},
-
-    {ChromeThreadDescriptor::THREAD_BROWSER_MAIN, "CrBrowserMain"},
-    {ChromeThreadDescriptor::THREAD_RENDERER_MAIN, "CrRendererMain"},
-    {ChromeThreadDescriptor::THREAD_CHILD_IO, "Chrome_ChildIOThread"},
-    {ChromeThreadDescriptor::THREAD_BROWSER_IO, "Chrome_IOThread"},
-    {ChromeThreadDescriptor::THREAD_UTILITY_MAIN, "CrUtilityMain"},
-    {ChromeThreadDescriptor::THREAD_GPU_MAIN, "CrGpuMain"},
-    {ChromeThreadDescriptor::THREAD_CACHE_BLOCKFILE, "CacheThread_BlockFile"},
-    {ChromeThreadDescriptor::ChromeThreadDescriptor::THREAD_MEDIA, "Media"},
-    {ChromeThreadDescriptor::THREAD_AUDIO_OUTPUTDEVICE, "AudioOutputDevice"},
-    {ChromeThreadDescriptor::THREAD_GPU_MEMORY, "GpuMemoryThread"},
-    {ChromeThreadDescriptor::THREAD_GPU_VSYNC, "GpuVSyncThread"},
-    {ChromeThreadDescriptor::THREAD_DXA_VIDEODECODER, "DXVAVideoDecoderThread"},
-    {ChromeThreadDescriptor::THREAD_BROWSER_WATCHDOG, "BrowserWatchdog"},
-    {
-        ChromeThreadDescriptor::THREAD_WEBRTC_NETWORK,
-        "WebRTC_Network",
-    },
-    {ChromeThreadDescriptor::THREAD_WINDOW_OWNER, "Window owner thread"},
-    {ChromeThreadDescriptor::THREAD_WEBRTC_SIGNALING, "WebRTC_Signaling"},
-    {ChromeThreadDescriptor::THREAD_PPAPI_MAIN, "CrPPAPIMain"},
-    {ChromeThreadDescriptor::THREAD_GPU_WATCHDOG, "GpuWatchdog"},
-    {ChromeThreadDescriptor::THREAD_SWAPPER, "swapper"},
-    {ChromeThreadDescriptor::THREAD_GAMEPAD_POLLING, "Gamepad polling thread"},
-    {ChromeThreadDescriptor::THREAD_AUDIO_INPUTDEVICE, "AudioInputDevice"},
-    {ChromeThreadDescriptor::THREAD_WEBRTC_WORKER, "WebRTC_Worker"},
-    {ChromeThreadDescriptor::THREAD_WEBCRYPTO, "WebCrypto"},
-    {ChromeThreadDescriptor::THREAD_DATABASE, "Database thread"},
-    {ChromeThreadDescriptor::THREAD_PROXYRESOLVER, "Proxy Resolver"},
-    {ChromeThreadDescriptor::THREAD_DEVTOOLSADB, "Chrome_DevToolsADBThread"},
-    {ChromeThreadDescriptor::THREAD_NETWORKCONFIGWATCHER,
-     "NetworkConfigWatcher"},
-    {ChromeThreadDescriptor::THREAD_WASAPI_RENDER, "wasapi_render_thread"},
-};
-
-}  // namespace
-
-ChromeStringLookup::ChromeStringLookup(TraceStorage* storage) {
-  for (uint32_t i = 0; i < base::ArraySize(kProcessNames); i++) {
-    chrome_process_name_ids_[kProcessNames[i].type] =
-        kProcessNames[i].name ? storage->InternString(kProcessNames[i].name)
-                              : kNullStringId;
-  }
-
-  for (uint32_t i = 0; i < base::ArraySize(kThreadNames); i++) {
-    chrome_thread_name_ids_[kThreadNames[i].type] =
-        kThreadNames[i].name ? storage->InternString(kThreadNames[i].name)
-                             : kNullStringId;
-  }
-}
-
-StringId ChromeStringLookup::GetProcessName(int32_t process_type) const {
-  auto process_name_it = chrome_process_name_ids_.find(process_type);
-  if (process_name_it != chrome_process_name_ids_.end())
-    return process_name_it->second;
-
-  PERFETTO_DLOG("GetProcessName error: Unknown Chrome process type %u",
-                process_type);
-  return kNullStringId;
-}
-
-StringId ChromeStringLookup::GetThreadName(int32_t thread_type) const {
-  auto thread_name_it = chrome_thread_name_ids_.find(thread_type);
-  if (thread_name_it != chrome_thread_name_ids_.end())
-    return thread_name_it->second;
-
-  PERFETTO_DLOG("GetThreadName error: Unknown Chrome thread type %u",
-                thread_type);
-  return kNullStringId;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/chrome_string_lookup.h b/src/trace_processor/importers/proto/chrome_string_lookup.h
deleted file mode 100644
index 23f8eca..0000000
--- a/src/trace_processor/importers/proto/chrome_string_lookup.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_CHROME_STRING_LOOKUP_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_STRING_LOOKUP_H_
-
-#include <map>
-
-#include "src/trace_processor/storage/trace_storage.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class ChromeStringLookup {
- public:
-  explicit ChromeStringLookup(TraceStorage* storage);
-
-  StringId GetProcessName(int32_t process_type) const;
-  StringId GetThreadName(int32_t thread_type) const;
-
- public:
-  std::map<int32_t /* ChromeProcessDescriptor::ProcessType */, StringId>
-      chrome_process_name_ids_;
-  std::map<int32_t /* ChromeThreadDescriptor::ThreadType */, StringId>
-      chrome_thread_name_ids_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_STRING_LOOKUP_H_
diff --git a/src/trace_processor/importers/proto/chrome_system_probes_module.cc b/src/trace_processor/importers/proto/chrome_system_probes_module.cc
deleted file mode 100644
index 775d64f..0000000
--- a/src/trace_processor/importers/proto/chrome_system_probes_module.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/chrome_system_probes_module.h"
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/chrome_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 {
-
-using perfetto::protos::pbzero::TracePacket;
-
-ChromeSystemProbesModule::ChromeSystemProbesModule(
-    TraceProcessorContext* context)
-    : parser_(context) {
-  RegisterForField(TracePacket::kProcessStatsFieldNumber, context);
-}
-
-void ChromeSystemProbesModule::ParsePacket(const TracePacket::Decoder& decoder,
-                                           const TimestampedTracePiece& ttp,
-                                           uint32_t field_id) {
-  switch (field_id) {
-    case TracePacket::kProcessStatsFieldNumber:
-      parser_.ParseProcessStats(ttp.timestamp, decoder.process_stats());
-      return;
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/chrome_system_probes_module.h b/src/trace_processor/importers/proto/chrome_system_probes_module.h
deleted file mode 100644
index 0fc4615..0000000
--- a/src/trace_processor/importers/proto/chrome_system_probes_module.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_CHROME_SYSTEM_PROBES_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_SYSTEM_PROBES_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/chrome_system_probes_parser.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Parses only the Chrome recorded system stats fields. This is separated from
-// SystemProbesModule due to the binary size impact of the system probes parser.
-class ChromeSystemProbesModule : public ProtoImporterModule {
- public:
-  explicit ChromeSystemProbesModule(TraceProcessorContext* context);
-
-  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                   const TimestampedTracePiece& ttp,
-                   uint32_t field_id) override;
-
- private:
-  ChromeSystemProbesParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_SYSTEM_PROBES_MODULE_H_
diff --git a/src/trace_processor/importers/proto/chrome_system_probes_parser.cc b/src/trace_processor/importers/proto/chrome_system_probes_parser.cc
deleted file mode 100644
index e3c95bd..0000000
--- a/src/trace_processor/importers/proto/chrome_system_probes_parser.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/chrome_system_probes_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/storage/metadata.h"
-#include "src/trace_processor/types/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"
-
-namespace perfetto {
-namespace trace_processor {
-
-ChromeSystemProbesParser::ChromeSystemProbesParser(
-    TraceProcessorContext* context)
-    : context_(context),
-      is_peak_rss_resettable_id_(
-          context->storage->InternString("is_peak_rss_resettable")) {
-  using ProcessStats = protos::pbzero::ProcessStats;
-  proc_stats_process_names_
-      [ProcessStats::Process::kChromePrivateFootprintKbFieldNumber] =
-          context->storage->InternString("chrome.private_footprint_kb");
-  proc_stats_process_names_
-      [ProcessStats::Process::kChromePeakResidentSetKbFieldNumber] =
-          context->storage->InternString("chrome.peak_resident_set_kb");
-}
-
-void ChromeSystemProbesParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
-  protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
-  for (auto it = stats.processes(); it; ++it) {
-    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();
-        break;
-      }
-    }
-
-    for (auto fld = proc.ReadField(); fld.valid(); fld = proc.ReadField()) {
-      if (fld.id() == protos::pbzero::ProcessStats::Process::
-                          kIsPeakRssResettableFieldNumber) {
-        UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
-        context_->process_tracker->AddArgsTo(upid).AddArg(
-            is_peak_rss_resettable_id_, Variadic::Boolean(fld.as_bool()));
-        continue;
-      }
-
-      if (fld.id() >= proc_stats_process_names_.size())
-        continue;
-      const StringId& name = proc_stats_process_names_[fld.id()];
-      if (name == StringId::Null())
-        continue;
-      UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
-      TrackId track =
-          context_->track_tracker->InternProcessCounterTrack(name, upid);
-      int64_t value = fld.as_int64() * 1024;
-      context_->event_tracker->PushCounter(ts, static_cast<double>(value),
-                                           track);
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/chrome_system_probes_parser.h b/src/trace_processor/importers/proto/chrome_system_probes_parser.h
deleted file mode 100644
index 8c65fd4..0000000
--- a/src/trace_processor/importers/proto/chrome_system_probes_parser.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_CHROME_SYSTEM_PROBES_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_SYSTEM_PROBES_PARSER_H_
-
-#include <array>
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class ChromeSystemProbesParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-
-  explicit ChromeSystemProbesParser(TraceProcessorContext*);
-
-  void ParseProcessStats(int64_t ts, ConstBytes);
-
- private:
-  TraceProcessorContext* const context_;
-
-  const StringId is_peak_rss_resettable_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. Also update SystemProbesParser.
-  static constexpr size_t kProcStatsProcessSize = 15;
-  std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_SYSTEM_PROBES_PARSER_H_
diff --git a/src/trace_processor/importers/proto/frame_timeline_event_parser.cc b/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
deleted file mode 100644
index f52931f..0000000
--- a/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/frame_timeline_event_parser.h"
-
-#include <inttypes.h>
-
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-bool IsBadTimestamp(int64_t ts) {
-  // Very small or very large timestamps are likely a mistake.
-  // See b/185978397
-  constexpr int64_t kBadTimestamp =
-      std::numeric_limits<int64_t>::max() - (10LL * 1000 * 1000 * 1000);
-  return std::abs(ts) >= kBadTimestamp;
-}
-
-}  // namespace
-
-using ExpectedDisplayFrameStartDecoder =
-    protos::pbzero::FrameTimelineEvent_ExpectedDisplayFrameStart_Decoder;
-using ActualDisplayFrameStartDecoder =
-    protos::pbzero::FrameTimelineEvent_ActualDisplayFrameStart_Decoder;
-
-using ExpectedSurfaceFrameStartDecoder =
-    protos::pbzero::FrameTimelineEvent_ExpectedSurfaceFrameStart_Decoder;
-using ActualSurfaceFrameStartDecoder =
-    protos::pbzero::FrameTimelineEvent_ActualSurfaceFrameStart_Decoder;
-
-using FrameEndDecoder = protos::pbzero::FrameTimelineEvent_FrameEnd_Decoder;
-
-static StringId JankTypeBitmaskToStringId(TraceProcessorContext* context,
-                                          int32_t jank_type) {
-  if (jank_type == FrameTimelineEvent::JANK_UNSPECIFIED)
-    return context->storage->InternString("Unspecified");
-  if (jank_type == FrameTimelineEvent::JANK_NONE)
-    return context->storage->InternString("None");
-
-  std::vector<std::string> jank_reasons;
-  if (jank_type & FrameTimelineEvent::JANK_SF_SCHEDULING)
-    jank_reasons.emplace_back("SurfaceFlinger Scheduling");
-  if (jank_type & FrameTimelineEvent::JANK_PREDICTION_ERROR)
-    jank_reasons.emplace_back("Prediction Error");
-  if (jank_type & FrameTimelineEvent::JANK_DISPLAY_HAL)
-    jank_reasons.emplace_back("Display HAL");
-  if (jank_type & FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED)
-    jank_reasons.emplace_back("SurfaceFlinger CPU Deadline Missed");
-  if (jank_type & FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED)
-    jank_reasons.emplace_back("SurfaceFlinger GPU Deadline Missed");
-  if (jank_type & FrameTimelineEvent::JANK_APP_DEADLINE_MISSED)
-    jank_reasons.emplace_back("App Deadline Missed");
-  if (jank_type & FrameTimelineEvent::JANK_BUFFER_STUFFING)
-    jank_reasons.emplace_back("Buffer Stuffing");
-  if (jank_type & FrameTimelineEvent::JANK_UNKNOWN)
-    jank_reasons.emplace_back("Unknown Jank");
-  if (jank_type & FrameTimelineEvent::JANK_SF_STUFFING)
-    jank_reasons.emplace_back("SurfaceFlinger Stuffing");
-
-  std::string jank_str(
-      std::accumulate(jank_reasons.begin(), jank_reasons.end(), std::string(),
-                      [](const std::string& l, const std::string& r) {
-                        return l.empty() ? r : l + ", " + r;
-                      }));
-  return context->storage->InternString(base::StringView(jank_str));
-}
-
-static bool DisplayFrameJanky(int32_t jank_type) {
-  if (jank_type == FrameTimelineEvent::JANK_UNSPECIFIED || jank_type == FrameTimelineEvent::JANK_NONE)
-    return false;
-
-  int32_t display_frame_jank_bitmask = FrameTimelineEvent::JANK_SF_SCHEDULING | FrameTimelineEvent::JANK_PREDICTION_ERROR | FrameTimelineEvent::JANK_DISPLAY_HAL | FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED | FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
-  if (jank_type & display_frame_jank_bitmask)
-      return true;
-  return false;
-}
-
-static bool SurfaceFrameJanky(int32_t jank_type) {
-  if (jank_type == FrameTimelineEvent::JANK_UNSPECIFIED || jank_type == FrameTimelineEvent::JANK_NONE)
-    return false;
-
-  int32_t surface_frame_jank_bitmask = FrameTimelineEvent::JANK_APP_DEADLINE_MISSED | FrameTimelineEvent::JANK_UNKNOWN;
-  if (jank_type & surface_frame_jank_bitmask)
-    return true;
-  return false;
-}
-
-static bool ValidatePredictionType(TraceProcessorContext* context,
-                                   int32_t prediction_type) {
-  if (prediction_type >= FrameTimelineEvent::PREDICTION_VALID /*1*/ &&
-      prediction_type <= FrameTimelineEvent::PREDICTION_UNKNOWN /*3*/)
-    return true;
-  context->storage->IncrementStats(stats::frame_timeline_event_parser_errors);
-  return false;
-}
-
-static bool ValidatePresentType(TraceProcessorContext* context,
-                                int32_t present_type) {
-  if (present_type >= FrameTimelineEvent::PRESENT_ON_TIME /*1*/ &&
-      present_type <= FrameTimelineEvent::PRESENT_UNKNOWN /*5*/)
-    return true;
-  context->storage->IncrementStats(stats::frame_timeline_event_parser_errors);
-  return false;
-}
-
-FrameTimelineEventParser::FrameTimelineEventParser(
-    TraceProcessorContext* context)
-    : context_(context),
-      present_type_ids_{
-          {context->storage->InternString(
-               "Unspecified Present") /* PRESENT_UNSPECIFIED */,
-           context->storage->InternString(
-               "On-time Present") /* PRESENT_ON_TIME */,
-           context->storage->InternString("Late Present") /* PRESENT_LATE */,
-           context->storage->InternString("Early Present") /* PRESENT_EARLY */,
-           context->storage->InternString(
-               "Dropped Frame") /* PRESENT_DROPPED */,
-           context->storage->InternString(
-               "Unknown Present") /* PRESENT_UNKNOWN */}},
-      prediction_type_ids_{
-          {context->storage->InternString(
-               "Unspecified Prediction") /* PREDICTION_UNSPECIFIED */,
-           context->storage->InternString(
-               "Valid Prediction") /* PREDICTION_VALID */,
-           context->storage->InternString(
-               "Expired Prediction") /* PREDICTION_EXPIRED */,
-           context->storage->InternString(
-               "Unknown Prediction") /* PREDICTION_UNKNOWN */}},
-      expected_timeline_track_name_(
-          context->storage->InternString("Expected Timeline")),
-      actual_timeline_track_name_(
-          context->storage->InternString("Actual Timeline")),
-      surface_frame_token_id_(
-          context->storage->InternString("Surface frame token")),
-      display_frame_token_id_(
-          context->storage->InternString("Display frame token")),
-      present_type_id_(context->storage->InternString("Present type")),
-      on_time_finish_id_(context->storage->InternString("On time finish")),
-      gpu_composition_id_(context->storage->InternString("GPU composition")),
-      jank_type_id_(context->storage->InternString("Jank type")),
-      layer_name_id_(context->storage->InternString("Layer name")),
-      prediction_type_id_(context->storage->InternString("Prediction type")),
-      is_buffer_id_(context->storage->InternString("Is Buffer?")),
-      jank_tag_none_id_(context->storage->InternString("No Jank")),
-      jank_tag_self_id_(context->storage->InternString("Self Jank")),
-      jank_tag_other_id_(context->storage->InternString("Other Jank")),
-      jank_tag_dropped_id_(context->storage->InternString("Dropped Frame")),
-      jank_tag_buffer_stuffing_id_(
-          context->storage->InternString("Buffer Stuffing")),
-      jank_tag_sf_stuffing_id_(
-          context->storage->InternString("SurfaceFlinger Stuffing")) {}
-
-void FrameTimelineEventParser::ParseExpectedDisplayFrameStart(
-    int64_t timestamp,
-    ConstBytes bufferBlob) {
-  ExpectedDisplayFrameStartDecoder event(bufferBlob.data, bufferBlob.size);
-  if (!event.has_cookie()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_pid()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  int64_t cookie = event.cookie();
-  int64_t token = event.token();
-  StringId name_id =
-      context_->storage->InternString(base::StringView(std::to_string(token)));
-
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(event.pid()));
-  auto expected_track_set_id =
-      context_->async_track_set_tracker->InternFrameTimelineSet(
-          upid, expected_timeline_track_name_);
-  cookie_track_set_id_map_[cookie] = expected_track_set_id;
-
-  tables::ExpectedFrameTimelineSliceTable::Row expected_row;
-  expected_row.ts = timestamp;
-  expected_row.track_id =
-      context_->async_track_set_tracker->Begin(expected_track_set_id, cookie);
-  expected_row.name = name_id;
-
-  expected_row.display_frame_token = token;
-  expected_row.upid = upid;
-
-  context_->slice_tracker->BeginTyped(
-      context_->storage->mutable_expected_frame_timeline_slice_table(),
-      expected_row, [this, token](ArgsTracker::BoundInserter* inserter) {
-        inserter->AddArg(display_frame_token_id_, Variadic::Integer(token));
-      });
-}
-
-void FrameTimelineEventParser::ParseActualDisplayFrameStart(
-    int64_t timestamp,
-    ConstBytes bufferBlob) {
-  ActualDisplayFrameStartDecoder event(bufferBlob.data, bufferBlob.size);
-  if (!event.has_cookie()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-  if (!event.has_pid()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  int64_t cookie = event.cookie();
-  int64_t token = event.token();
-  StringId name_id =
-      context_->storage->InternString(base::StringView(std::to_string(token)));
-
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(event.pid()));
-  auto actual_track_set_id =
-      context_->async_track_set_tracker->InternFrameTimelineSet(
-          upid, actual_timeline_track_name_);
-  cookie_track_set_id_map_[cookie] = actual_track_set_id;
-
-  tables::ActualFrameTimelineSliceTable::Row actual_row;
-  actual_row.ts = timestamp;
-  actual_row.track_id =
-      context_->async_track_set_tracker->Begin(actual_track_set_id, cookie);
-  actual_row.name = name_id;
-  actual_row.display_frame_token = token;
-  actual_row.upid = upid;
-  StringId present_type = present_type_ids_[0];
-  if (event.has_present_type() &&
-      ValidatePresentType(context_, event.present_type())) {
-    present_type = present_type_ids_[static_cast<size_t>(event.present_type())];
-  }
-  actual_row.present_type = present_type;
-  actual_row.on_time_finish = event.on_time_finish();
-  actual_row.gpu_composition = event.gpu_composition();
-  StringId jank_type = JankTypeBitmaskToStringId(context_, event.jank_type());
-  actual_row.jank_type = jank_type;
-  StringId prediction_type = prediction_type_ids_[0];
-  if (event.has_prediction_type() &&
-      ValidatePredictionType(context_, event.prediction_type())) {
-    prediction_type =
-        prediction_type_ids_[static_cast<size_t>(event.prediction_type())];
-  }
-  actual_row.prediction_type = prediction_type;
-  if (DisplayFrameJanky(event.jank_type())) {
-    actual_row.jank_tag = jank_tag_self_id_;
-  } else if (event.jank_type() == FrameTimelineEvent::JANK_SF_STUFFING) {
-    actual_row.jank_tag = jank_tag_sf_stuffing_id_;
-  } else {
-    actual_row.jank_tag = jank_tag_none_id_;
-  }
-
-  base::Optional<SliceId> opt_slice_id =
-      context_->slice_tracker->BeginTyped(
-          context_->storage->mutable_actual_frame_timeline_slice_table(),
-          actual_row,
-          [this, token, jank_type, present_type, prediction_type,
-           &event](ArgsTracker::BoundInserter* inserter) {
-            inserter->AddArg(display_frame_token_id_, Variadic::Integer(token));
-            inserter->AddArg(present_type_id_, Variadic::String(present_type));
-            inserter->AddArg(on_time_finish_id_,
-                             Variadic::Integer(event.on_time_finish()));
-            inserter->AddArg(gpu_composition_id_,
-                             Variadic::Integer(event.gpu_composition()));
-            inserter->AddArg(jank_type_id_, Variadic::String(jank_type));
-            inserter->AddArg(prediction_type_id_,
-                             Variadic::String(prediction_type));
-          });
-
-  // SurfaceFrames will always be parsed before the matching DisplayFrame
-  // (since the app works on the frame before SurfaceFlinger does). Because
-  // of this it's safe to add all the flow events here and then forget the
-  // surface_slice id - we shouldn't see more surfaces_slices that should be
-  // connected to this slice after this point.
-  auto range = display_token_to_surface_slice_.equal_range(token);
-  if (opt_slice_id) {
-    for (auto it = range.first; it != range.second; ++it) {
-      SliceId display_slice = *opt_slice_id;  // SurfaceFlinger
-      SliceId surface_slice = it->second;     // App
-      context_->flow_tracker->InsertFlow(display_slice, surface_slice);
-    }
-  }
-  display_token_to_surface_slice_.erase(range.first, range.second);
-}
-
-void FrameTimelineEventParser::ParseExpectedSurfaceFrameStart(
-    int64_t timestamp,
-    ConstBytes bufferBlob) {
-  ExpectedSurfaceFrameStartDecoder event(bufferBlob.data, bufferBlob.size);
-
-  if (!event.has_cookie()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_display_frame_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_pid()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  int64_t cookie = event.cookie();
-  int64_t token = event.token();
-  int64_t display_frame_token = event.display_frame_token();
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(event.pid()));
-  auto token_set_it = expected_timeline_token_map_.find(upid);
-  if (token_set_it != expected_timeline_token_map_.end()) {
-    auto& token_set = token_set_it->second;
-    if (token_set.find(token) != token_set.end()) {
-      // If we already have an expected timeline for a token, the expectations
-      // are same for all frames that use the token. No need to add duplicate
-      // entries.
-      return;
-    }
-  }
-  // This is the first time we are seeing this token for this process. Add to
-  // the map.
-  expected_timeline_token_map_[upid].insert(token);
-
-  StringId layer_name_id = event.has_layer_name()
-                               ? context_->storage->InternString(
-                                     base::StringView(event.layer_name()))
-                               : kNullStringId;
-  StringId name_id =
-      context_->storage->InternString(base::StringView(std::to_string(token)));
-
-  auto expected_track_set_id =
-      context_->async_track_set_tracker->InternFrameTimelineSet(
-          upid, expected_timeline_track_name_);
-  cookie_track_set_id_map_[cookie] = expected_track_set_id;
-
-  tables::ExpectedFrameTimelineSliceTable::Row expected_row;
-  expected_row.ts = timestamp;
-  expected_row.track_id =
-      context_->async_track_set_tracker->Begin(expected_track_set_id, cookie);
-  expected_row.name = name_id;
-
-  expected_row.surface_frame_token = token;
-  expected_row.display_frame_token = display_frame_token;
-  expected_row.upid = upid;
-  expected_row.layer_name = layer_name_id;
-  context_->slice_tracker->BeginTyped(
-      context_->storage->mutable_expected_frame_timeline_slice_table(),
-      expected_row,
-      [this, token, layer_name_id](ArgsTracker::BoundInserter* inserter) {
-        inserter->AddArg(display_frame_token_id_, Variadic::Integer(token));
-        inserter->AddArg(layer_name_id_, Variadic::String(layer_name_id));
-      });
-}
-
-void FrameTimelineEventParser::ParseActualSurfaceFrameStart(
-    int64_t timestamp,
-    ConstBytes bufferBlob) {
-  ActualSurfaceFrameStartDecoder event(bufferBlob.data, bufferBlob.size);
-
-  if (!event.has_cookie()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_display_frame_token()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (!event.has_pid()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  int64_t cookie = event.cookie();
-  int64_t token = event.token();
-  int64_t display_frame_token = event.display_frame_token();
-
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(event.pid()));
-  StringId layer_name_id;
-  if (event.has_layer_name())
-    layer_name_id =
-        context_->storage->InternString(base::StringView(event.layer_name()));
-  StringId name_id =
-      context_->storage->InternString(base::StringView(std::to_string(token)));
-
-  auto actual_track_set_id =
-      context_->async_track_set_tracker->InternFrameTimelineSet(
-          upid, actual_timeline_track_name_);
-  cookie_track_set_id_map_[cookie] = actual_track_set_id;
-
-  tables::ActualFrameTimelineSliceTable::Row actual_row;
-  actual_row.ts = timestamp;
-  actual_row.track_id =
-      context_->async_track_set_tracker->Begin(actual_track_set_id, cookie);
-  actual_row.name = name_id;
-  actual_row.surface_frame_token = token;
-  actual_row.display_frame_token = display_frame_token;
-  actual_row.upid = upid;
-  actual_row.layer_name = layer_name_id;
-  StringId present_type = present_type_ids_[0];
-  bool present_type_validated = false;
-  if (event.has_present_type() &&
-      ValidatePresentType(context_, event.present_type())) {
-    present_type_validated = true;
-    present_type = present_type_ids_[static_cast<size_t>(event.present_type())];
-  }
-  actual_row.present_type = present_type;
-  actual_row.on_time_finish = event.on_time_finish();
-  actual_row.gpu_composition = event.gpu_composition();
-  StringId jank_type = JankTypeBitmaskToStringId(context_, event.jank_type());
-  actual_row.jank_type = jank_type;
-  StringId prediction_type = prediction_type_ids_[0];
-  if (event.has_prediction_type() &&
-      ValidatePredictionType(context_, event.prediction_type())) {
-    prediction_type =
-        prediction_type_ids_[static_cast<size_t>(event.prediction_type())];
-  }
-  actual_row.prediction_type = prediction_type;
-  if (SurfaceFrameJanky(event.jank_type())) {
-    actual_row.jank_tag = jank_tag_self_id_;
-  } else if (DisplayFrameJanky(event.jank_type())) {
-    actual_row.jank_tag = jank_tag_other_id_;
-  } else if (event.jank_type() == FrameTimelineEvent::JANK_BUFFER_STUFFING) {
-    actual_row.jank_tag = jank_tag_buffer_stuffing_id_;
-  } else if (present_type_validated &&
-             event.present_type() == FrameTimelineEvent::PRESENT_DROPPED) {
-    actual_row.jank_tag = jank_tag_dropped_id_;
-  } else {
-    actual_row.jank_tag = jank_tag_none_id_;
-  }
-  StringId is_buffer = context_->storage->InternString("Unspecified");
-  if (event.has_is_buffer()) {
-    if (event.is_buffer())
-      is_buffer = context_->storage->InternString("Yes");
-    else
-      is_buffer = context_->storage->InternString("No");
-  }
-
-  base::Optional<SliceId> opt_slice_id =
-      context_->slice_tracker->BeginTyped(
-          context_->storage->mutable_actual_frame_timeline_slice_table(),
-          actual_row,
-          [this, jank_type, present_type, token, layer_name_id,
-           display_frame_token, prediction_type, is_buffer,
-           &event](ArgsTracker::BoundInserter* inserter) {
-            inserter->AddArg(surface_frame_token_id_, Variadic::Integer(token));
-            inserter->AddArg(display_frame_token_id_,
-                             Variadic::Integer(display_frame_token));
-            inserter->AddArg(layer_name_id_, Variadic::String(layer_name_id));
-            inserter->AddArg(present_type_id_, Variadic::String(present_type));
-            inserter->AddArg(on_time_finish_id_,
-                             Variadic::Integer(event.on_time_finish()));
-            inserter->AddArg(gpu_composition_id_,
-                             Variadic::Integer(event.gpu_composition()));
-            inserter->AddArg(jank_type_id_, Variadic::String(jank_type));
-            inserter->AddArg(prediction_type_id_,
-                             Variadic::String(prediction_type));
-            inserter->AddArg(is_buffer_id_, Variadic::String(is_buffer));
-          });
-
-  if (opt_slice_id) {
-    display_token_to_surface_slice_.emplace(display_frame_token, *opt_slice_id);
-  }
-}
-
-void FrameTimelineEventParser::ParseFrameEnd(int64_t timestamp,
-                                             ConstBytes bufferBlob) {
-  FrameEndDecoder event(bufferBlob.data, bufferBlob.size);
-
-  if (!event.has_cookie()) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  int64_t cookie = event.cookie();
-  auto it = cookie_track_set_id_map_.find(cookie);
-  if (it == cookie_track_set_id_map_.end())
-    return;
-  auto track_set_id = it->second;
-  auto track_id = context_->async_track_set_tracker->End(track_set_id, cookie);
-  context_->slice_tracker->End(timestamp, track_id);
-  cookie_track_set_id_map_.erase(it);
-}
-
-void FrameTimelineEventParser::ParseFrameTimelineEvent(int64_t timestamp,
-                                                       ConstBytes blob) {
-  protos::pbzero::FrameTimelineEvent_Decoder frame_event(blob.data, blob.size);
-
-  if (IsBadTimestamp(timestamp)) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return;
-  }
-
-  if (frame_event.has_expected_display_frame_start()) {
-    ParseExpectedDisplayFrameStart(timestamp,
-                                   frame_event.expected_display_frame_start());
-  } else if (frame_event.has_actual_display_frame_start()) {
-    ParseActualDisplayFrameStart(timestamp,
-                                 frame_event.actual_display_frame_start());
-  } else if (frame_event.has_expected_surface_frame_start()) {
-    ParseExpectedSurfaceFrameStart(timestamp,
-                                   frame_event.expected_surface_frame_start());
-  } else if (frame_event.has_actual_surface_frame_start()) {
-    ParseActualSurfaceFrameStart(timestamp,
-                                 frame_event.actual_surface_frame_start());
-  } else if (frame_event.has_frame_end()) {
-    ParseFrameEnd(timestamp, frame_event.frame_end());
-  } else {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-  }
-}
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/frame_timeline_event_parser.h b/src/trace_processor/importers/proto/frame_timeline_event_parser.h
deleted file mode 100644
index c4e3ee8..0000000
--- a/src/trace_processor/importers/proto/frame_timeline_event_parser.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FRAME_TIMELINE_EVENT_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_FRAME_TIMELINE_EVENT_PARSER_H_
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-#include "protos/perfetto/trace/android/frame_timeline_event.pbzero.h"
-
-#include <map>
-#include <unordered_map>
-#include <unordered_set>
-
-namespace perfetto {
-
-namespace trace_processor {
-
-using FrameTimelineEvent = protos::pbzero::FrameTimelineEvent;
-using FrameTimelineEventDecoder = protos::pbzero::FrameTimelineEvent_Decoder;
-
-class TraceProcessorContext;
-
-// Class for parsing graphics frame related events.
-class FrameTimelineEventParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-  using TrackSetId = AsyncTrackSetTracker::TrackSetId;
-  explicit FrameTimelineEventParser(TraceProcessorContext*);
-
-  void ParseFrameTimelineEvent(int64_t timestamp, ConstBytes);
-
- private:
-  void ParseExpectedDisplayFrameStart(int64_t timestamp, ConstBytes);
-  void ParseActualDisplayFrameStart(int64_t timestamp, ConstBytes);
-
-  void ParseExpectedSurfaceFrameStart(int64_t timestamp, ConstBytes);
-  void ParseActualSurfaceFrameStart(int64_t timestamp, ConstBytes);
-
-  void ParseFrameEnd(int64_t timestamp, ConstBytes);
-
-  TraceProcessorContext* const context_;
-  // Cookie -> TrackSetId map. Since cookies are globally unique per slice, this
-  // helps in allowing the producer to send only the cookie as the End marker
-  // without the need for any other fields. The TrackSets could be interned
-  // based on any number of fields in the Start marker but the global uniqueness
-  // of the cookie makes it so that we can end a slice with just the cookie and
-  // the TrackSetId.
-  std::map<int64_t, TrackSetId> cookie_track_set_id_map_;
-  std::array<StringId, 6> present_type_ids_;
-  std::array<StringId, 4> prediction_type_ids_;
-  StringId expected_timeline_track_name_;
-  StringId actual_timeline_track_name_;
-
-  StringId surface_frame_token_id_;
-  StringId display_frame_token_id_;
-  StringId present_type_id_;
-  StringId on_time_finish_id_;
-  StringId gpu_composition_id_;
-  StringId jank_type_id_;
-  StringId layer_name_id_;
-  StringId prediction_type_id_;
-  StringId is_buffer_id_;
-
-  StringId jank_tag_none_id_;
-  StringId jank_tag_self_id_;
-  StringId jank_tag_other_id_;
-  StringId jank_tag_dropped_id_;
-  StringId jank_tag_buffer_stuffing_id_;
-  StringId jank_tag_sf_stuffing_id_;
-
-  // upid -> set of tokens map. The expected timeline is the same for a given
-  // token no matter how many times its seen. We can safely ignore duplicates
-  // for the expected timeline slices by caching the set of tokens seen so far
-  // per upid. upid is used as a dimension here because we show the timeline
-  // tracks for every process group.
-  // This map is used only for SurfaceFrames because there is no way two
-  // DisplayFrames use the same token unless there is something wrong with
-  // SurfaceFlinger.
-  std::unordered_map<UniquePid, std::unordered_set<int64_t>>
-      expected_timeline_token_map_;
-
-  std::multimap<int64_t, SliceId> display_token_to_surface_slice_;
-};
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_FRAME_TIMELINE_EVENT_PARSER_H_
diff --git a/src/trace_processor/importers/proto/gpu_event_parser.cc b/src/trace_processor/importers/proto/gpu_event_parser.cc
index 317e7b4..4ba14d8 100644
--- a/src/trace_processor/importers/proto/gpu_event_parser.cc
+++ b/src/trace_processor/importers/proto/gpu_event_parser.cc
@@ -112,14 +112,7 @@
                              "UNKNOWN_SEVERITY") /* must be last */}},
       vk_event_track_id_(context->storage->InternString("Vulkan Events")),
       vk_event_scope_id_(context->storage->InternString("vulkan_events")),
-      vk_queue_submit_id_(context->storage->InternString("vkQueueSubmit")),
-      gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
-      gpu_mem_total_unit_id_(context->storage->InternString(
-          std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
-      gpu_mem_total_global_desc_id_(context->storage->InternString(
-          "Total GPU memory used by the entire system")),
-      gpu_mem_total_proc_desc_id_(context->storage->InternString(
-          "Total GPU memory used by this process")) {}
+      vk_queue_submit_id_(context->storage->InternString("vkQueueSubmit")) {}
 
 void GpuEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
   protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
@@ -210,38 +203,28 @@
         gpu_counter_track_ids_.emplace(counter_id, track);
         context_->storage->IncrementStats(stats::gpu_counters_missing_spec);
       }
-      double counter_val = counter.has_int_value()
-                               ? static_cast<double>(counter.int_value())
-                               : counter.double_value();
-      context_->event_tracker->PushCounter(ts, counter_val,
-                                           gpu_counter_track_ids_[counter_id]);
+      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]);
+      }
     }
   }
 }
 
 const StringId GpuEventParser::GetFullStageName(
-    PacketSequenceStateGeneration* sequence_state,
     const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
+  size_t stage_id = static_cast<size_t>(event.stage_id());
   StringId stage_name;
-  if (event.has_stage_iid()) {
-    auto stage_iid = event.stage_iid();
-    auto* decoder = sequence_state->LookupInternedMessage<
-        protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
-        protos::pbzero::InternedGpuRenderStageSpecification>(stage_iid);
-    if (!decoder) {
-      return kNullStringId;
-    }
-    stage_name = context_->storage->InternString(decoder->name());
-  } else {
-    uint64_t stage_id = static_cast<uint64_t>(event.stage_id());
 
-    if (stage_id < gpu_render_stage_ids_.size()) {
-      stage_name = gpu_render_stage_ids_[static_cast<size_t>(stage_id)].first;
-    } else {
-      char buffer[64];
-      snprintf(buffer, sizeof(buffer), "render stage(%" PRIu64 ")", stage_id);
-      stage_name = context_->storage->InternString(buffer);
-    }
+  if (stage_id < gpu_render_stage_ids_.size()) {
+    stage_name = gpu_render_stage_ids_[stage_id].first;
+  } else {
+    char buffer[64];
+    snprintf(buffer, sizeof(buffer), "render stage(%zu)", stage_id);
+    stage_name = context_->storage->InternString(buffer);
   }
   return stage_name;
 }
@@ -307,38 +290,7 @@
   }
 }
 
-const StringId GpuEventParser::ParseRenderSubpasses(
-    const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
-  if (!event.has_render_subpass_index_mask()) {
-    return kNullStringId;
-  }
-  char buf[256];
-  base::StringWriter writer(buf, sizeof(buf));
-  uint32_t bit_index = 0;
-  bool first = true;
-  for (auto it = event.render_subpass_index_mask(); it; ++it) {
-    auto subpasses_bits = *it;
-    do {
-      if ((subpasses_bits & 1) != 0) {
-        if (!first) {
-          writer.AppendChar(',');
-        }
-        first = false;
-        writer.AppendUnsignedInt(bit_index);
-      }
-      subpasses_bits >>= 1;
-      ++bit_index;
-    } while (subpasses_bits != 0);
-    // Round up to the next multiple of 64.
-    bit_index = ((bit_index - 1) / 64 + 1) * 64;
-  }
-  return context_->storage->InternString(writer.GetStringView());
-}
-
-void GpuEventParser::ParseGpuRenderStageEvent(
-    int64_t ts,
-    PacketSequenceStateGeneration* sequence_state,
-    ConstBytes blob) {
+void GpuEventParser::ParseGpuRenderStageEvent(int64_t ts, ConstBytes blob) {
   protos::pbzero::GpuRenderStageEvent::Decoder event(blob.data, blob.size);
 
   if (event.has_specifications()) {
@@ -362,26 +314,12 @@
     }
   }
 
-  auto args_callback = [this, &event,
-                        sequence_state](ArgsTracker::BoundInserter* inserter) {
-    if (event.has_stage_iid()) {
-      size_t stage_iid = static_cast<size_t>(event.stage_iid());
-      auto* decoder = sequence_state->LookupInternedMessage<
-          protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
-          protos::pbzero::InternedGpuRenderStageSpecification>(stage_iid);
-      if (decoder) {
-        // TODO: Add RenderStageCategory to gpu_slice table.
-        inserter->AddArg(description_id_,
-                         Variadic::String(context_->storage->InternString(
-                             decoder->description())));
-      }
-    } else if (event.has_stage_id()) {
-      size_t stage_id = static_cast<size_t>(event.stage_id());
-      if (stage_id < gpu_render_stage_ids_.size()) {
-        auto description = gpu_render_stage_ids_[stage_id].second;
-        if (description != kNullStringId) {
-          inserter->AddArg(description_id_, Variadic::String(description));
-        }
+  auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
+    size_t stage_id = static_cast<size_t>(event.stage_id());
+    if (stage_id < gpu_render_stage_ids_.size()) {
+      auto description = gpu_render_stage_ids_[stage_id].second;
+      if (description != kNullStringId) {
+        inserter->AddArg(description_id_, Variadic::String(description));
       }
     }
     for (auto it = event.extra_data(); it; ++it) {
@@ -395,52 +333,33 @@
 
   if (event.has_event_id()) {
     TrackId track_id;
-    uint64_t hw_queue_id = 0;
-    if (event.has_hw_queue_iid()) {
-      hw_queue_id = event.hw_queue_iid();
-      auto* decoder = sequence_state->LookupInternedMessage<
-          protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
-          protos::pbzero::InternedGpuRenderStageSpecification>(hw_queue_id);
-      if (!decoder) {
-        // Skip
-        return;
-      }
-      // TODO: Add RenderStageCategory to gpu_track table.
-      tables::GpuTrackTable::Row track(
-          context_->storage->InternString(decoder->name()));
-      track.scope = gpu_render_stage_scope_id_;
-      track.description =
-          context_->storage->InternString(decoder->description());
-      track_id = context_->track_tracker->InternGpuTrack(track);
+    uint32_t hw_queue_id = static_cast<uint32_t>(event.hw_queue_id());
+    if (hw_queue_id < gpu_hw_queue_ids_.size() &&
+        gpu_hw_queue_ids_[hw_queue_id].has_value()) {
+      track_id = gpu_hw_queue_ids_[hw_queue_id].value();
     } else {
-      uint32_t id = static_cast<uint32_t>(event.hw_queue_id());
-      if (id < gpu_hw_queue_ids_.size() && gpu_hw_queue_ids_[id].has_value()) {
-        track_id = gpu_hw_queue_ids_[id].value();
+      // If the event has a hw_queue_id that does not have a Specification,
+      // create a new track for it.
+      char buf[128];
+      base::StringWriter writer(buf, sizeof(buf));
+      writer.AppendLiteral("Unknown GPU Queue ");
+      if (hw_queue_id > 1024) {
+        // We don't expect this to happen, but just in case there is a corrupt
+        // packet, make sure we don't allocate a ridiculous amount of memory.
+        hw_queue_id = 1024;
+        context_->storage->IncrementStats(
+            stats::gpu_render_stage_parser_errors);
+        PERFETTO_ELOG("Invalid hw_queue_id.");
       } else {
-        // If the event has a hw_queue_id that does not have a Specification,
-        // create a new track for it.
-        char buf[128];
-        base::StringWriter writer(buf, sizeof(buf));
-        writer.AppendLiteral("Unknown GPU Queue ");
-        if (id > 1024) {
-          // We don't expect this to happen, but just in case there is a corrupt
-          // packet, make sure we don't allocate a ridiculous amount of memory.
-          id = 1024;
-          context_->storage->IncrementStats(
-              stats::gpu_render_stage_parser_errors);
-          PERFETTO_ELOG("Invalid hw_queue_id.");
-        } else {
-          writer.AppendInt(event.hw_queue_id());
-        }
-        StringId track_name =
-            context_->storage->InternString(writer.GetStringView());
-        tables::GpuTrackTable::Row track(track_name);
-        track.scope = gpu_render_stage_scope_id_;
-        track_id = context_->track_tracker->InternGpuTrack(track);
-        gpu_hw_queue_ids_.resize(id + 1);
-        gpu_hw_queue_ids_[id] = track_id;
+        writer.AppendInt(event.hw_queue_id());
       }
-      hw_queue_id = id;
+      StringId track_name =
+          context_->storage->InternString(writer.GetStringView());
+      tables::GpuTrackTable::Row track(track_name);
+      track.scope = gpu_render_stage_scope_id_;
+      track_id = context_->track_tracker->InternGpuTrack(track);
+      gpu_hw_queue_ids_.resize(hw_queue_id + 1);
+      gpu_hw_queue_ids_[hw_queue_id] = track_id;
     }
 
     auto render_target_name =
@@ -465,23 +384,19 @@
     tables::GpuSliceTable::Row row;
     row.ts = ts;
     row.track_id = track_id;
-    row.name = GetFullStageName(sequence_state, event);
+    row.name = GetFullStageName(event);
     row.dur = static_cast<int64_t>(event.duration());
-    // TODO: Create table for graphics context and lookup
-    // InternedGraphicsContext.
     row.context_id = static_cast<int64_t>(event.context());
     row.render_target = static_cast<int64_t>(event.render_target_handle());
     row.render_target_name = render_target_name_id;
     row.render_pass = static_cast<int64_t>(event.render_pass_handle());
     row.render_pass_name = render_pass_name_id;
-    row.render_subpasses = ParseRenderSubpasses(event);
     row.command_buffer = static_cast<int64_t>(event.command_buffer_handle());
     row.command_buffer_name = command_buffer_name_id;
     row.submission_id = event.submission_id();
-    row.hw_queue_id = static_cast<int64_t>(hw_queue_id);
+    row.hw_queue_id = hw_queue_id;
 
-    context_->slice_tracker->ScopedTyped(
-        context_->storage->mutable_gpu_slice_table(), row, args_callback);
+    context_->slice_tracker->ScopedGpu(row, args_callback);
   }
 }
 
@@ -518,8 +433,7 @@
       track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
                                                                  upid);
       context_->event_tracker->PushCounter(
-          event.timestamp(),
-          static_cast<double>(vulkan_driver_memory_counters_[allocation_scope]),
+          event.timestamp(), vulkan_driver_memory_counters_[allocation_scope],
           track);
       break;
 
@@ -547,9 +461,7 @@
                                                                  upid);
       context_->event_tracker->PushCounter(
           event.timestamp(),
-          static_cast<double>(
-              vulkan_device_memory_counters_allocate_[memory_type]),
-          track);
+          vulkan_device_memory_counters_allocate_[memory_type], track);
       break;
 
     case VulkanMemoryEvent::SOURCE_BUFFER:
@@ -575,8 +487,7 @@
       track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
                                                                  upid);
       context_->event_tracker->PushCounter(
-          event.timestamp(),
-          static_cast<double>(vulkan_device_memory_counters_bind_[memory_type]),
+          event.timestamp(), vulkan_device_memory_counters_bind_[memory_type],
           track);
       break;
     case VulkanMemoryEvent::SOURCE_UNSPECIFIED:
@@ -697,8 +608,7 @@
   row.track_id = track_id;
   row.name = severity_id;
   row.dur = 0;
-  context_->slice_tracker->ScopedTyped(
-      context_->storage->mutable_gpu_slice_table(), row, args_callback);
+  context_->slice_tracker->ScopedGpu(row, args_callback);
 }
 
 void GpuEventParser::ParseVulkanApiEvent(int64_t ts, ConstBytes blob) {
@@ -733,32 +643,9 @@
       inserter->AddArg(context_->storage->InternString("tid"),
                        Variadic::Integer(event.tid()));
     };
-    context_->slice_tracker->ScopedTyped(
-        context_->storage->mutable_gpu_slice_table(), row, args_callback);
+    context_->slice_tracker->ScopedGpu(row, args_callback);
   }
 }
 
-void GpuEventParser::ParseGpuMemTotalEvent(int64_t ts, ConstBytes blob) {
-  protos::pbzero::GpuMemTotalEvent::Decoder gpu_mem_total(blob.data, blob.size);
-
-  TrackId track = kInvalidTrackId;
-  const uint32_t pid = gpu_mem_total.pid();
-  if (pid == 0) {
-    // Pid 0 is used to indicate the global total
-    track = context_->track_tracker->InternGlobalCounterTrack(
-        gpu_mem_total_name_id_, gpu_mem_total_unit_id_,
-        gpu_mem_total_global_desc_id_);
-  } else {
-    // Process emitting the packet can be different from the pid in the event.
-    UniqueTid utid = context_->process_tracker->UpdateThread(pid, pid);
-    UniquePid upid = context_->storage->thread_table().upid()[utid].value_or(0);
-    track = context_->track_tracker->InternProcessCounterTrack(
-        gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
-        gpu_mem_total_proc_desc_id_);
-  }
-  context_->event_tracker->PushCounter(
-      ts, static_cast<double>(gpu_mem_total.size()), track);
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/gpu_event_parser.h b/src/trace_processor/importers/proto/gpu_event_parser.h
index b79b65f..175f62c 100644
--- a/src/trace_processor/importers/proto/gpu_event_parser.h
+++ b/src/trace_processor/importers/proto/gpu_event_parser.h
@@ -22,7 +22,6 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/string_writer.h"
 #include "perfetto/protozero/field.h"
-#include "protos/perfetto/trace/android/gpu_mem_event.pbzero.h"
 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/proto/proto_incremental_state.h"
@@ -61,10 +60,7 @@
   explicit GpuEventParser(TraceProcessorContext*);
 
   void ParseGpuCounterEvent(int64_t ts, ConstBytes);
-  void ParseGpuRenderStageEvent(int64_t ts,
-                                PacketSequenceStateGeneration*,
-                                ConstBytes);
-  void ParseGraphicsFrameEvent(int64_t timestamp, ConstBytes);
+  void ParseGpuRenderStageEvent(int64_t ts, ConstBytes);
   void ParseGpuLog(int64_t ts, ConstBytes);
 
   void ParseVulkanMemoryEvent(PacketSequenceStateGeneration*, ConstBytes);
@@ -73,19 +69,14 @@
 
   void ParseVulkanApiEvent(int64_t, ConstBytes);
 
-  void ParseGpuMemTotalEvent(int64_t, ConstBytes);
-
  private:
   const StringId GetFullStageName(
-      PacketSequenceStateGeneration* sequence_state,
       const protos::pbzero::GpuRenderStageEvent_Decoder& event) const;
   void InsertGpuTrack(
       const protos::pbzero::
           GpuRenderStageEvent_Specifications_Description_Decoder& hw_queue);
   base::Optional<std::string> FindDebugName(int32_t vk_object_type,
                                             uint64_t vk_handle) const;
-  const StringId ParseRenderSubpasses(
-      const protos::pbzero::GpuRenderStageEvent_Decoder& event) const;
 
   TraceProcessorContext* const context_;
   VulkanMemoryTracker vulkan_memory_tracker_;
@@ -123,11 +114,6 @@
   StringId vk_event_track_id_;
   StringId vk_event_scope_id_;
   StringId vk_queue_submit_id_;
-  // For GpuMemTotalEvent
-  const StringId gpu_mem_total_name_id_;
-  const StringId gpu_mem_total_unit_id_;
-  const StringId gpu_mem_total_global_desc_id_;
-  const StringId gpu_mem_total_proc_desc_id_;
 };
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/graphics_event_module.cc b/src/trace_processor/importers/proto/graphics_event_module.cc
index 46d8838..432b3bd 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.cc
+++ b/src/trace_processor/importers/proto/graphics_event_module.cc
@@ -22,14 +22,10 @@
 using perfetto::protos::pbzero::TracePacket;
 
 GraphicsEventModule::GraphicsEventModule(TraceProcessorContext* context)
-    : parser_(context),
-      frame_parser_(context),
-      frame_timeline_parser_(context) {
-  RegisterForField(TracePacket::kFrameTimelineEventFieldNumber, context);
+    : parser_(context), frame_parser_(context) {
   RegisterForField(TracePacket::kGpuCounterEventFieldNumber, context);
   RegisterForField(TracePacket::kGpuRenderStageEventFieldNumber, context);
   RegisterForField(TracePacket::kGpuLogFieldNumber, context);
-  RegisterForField(TracePacket::kGpuMemTotalEventFieldNumber, context);
   RegisterForField(TracePacket::kGraphicsFrameEventFieldNumber, context);
   RegisterForField(TracePacket::kVulkanMemoryEventFieldNumber, context);
   RegisterForField(TracePacket::kVulkanApiEventFieldNumber, context);
@@ -41,16 +37,11 @@
                                       const TimestampedTracePiece& ttp,
                                       uint32_t field_id) {
   switch (field_id) {
-    case TracePacket::kFrameTimelineEventFieldNumber:
-      frame_timeline_parser_.ParseFrameTimelineEvent(
-          ttp.timestamp, decoder.frame_timeline_event());
-      return;
     case TracePacket::kGpuCounterEventFieldNumber:
       parser_.ParseGpuCounterEvent(ttp.timestamp, decoder.gpu_counter_event());
       return;
     case TracePacket::kGpuRenderStageEventFieldNumber:
       parser_.ParseGpuRenderStageEvent(ttp.timestamp,
-                                       ttp.packet_data.sequence_state.get(),
                                        decoder.gpu_render_stage_event());
       return;
     case TracePacket::kGpuLogFieldNumber:
@@ -62,16 +53,12 @@
       return;
     case TracePacket::kVulkanMemoryEventFieldNumber:
       PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
-      parser_.ParseVulkanMemoryEvent(ttp.packet_data.sequence_state.get(),
+      parser_.ParseVulkanMemoryEvent(ttp.packet_data.sequence_state,
                                      decoder.vulkan_memory_event());
       return;
     case TracePacket::kVulkanApiEventFieldNumber:
       parser_.ParseVulkanApiEvent(ttp.timestamp, decoder.vulkan_api_event());
       return;
-    case TracePacket::kGpuMemTotalEventFieldNumber:
-      parser_.ParseGpuMemTotalEvent(ttp.timestamp,
-                                    decoder.gpu_mem_total_event());
-      return;
   }
 }
 
diff --git a/src/trace_processor/importers/proto/graphics_event_module.h b/src/trace_processor/importers/proto/graphics_event_module.h
index b550382..f84b2c5 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.h
+++ b/src/trace_processor/importers/proto/graphics_event_module.h
@@ -18,7 +18,6 @@
 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_MODULE_H_
 
 #include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/frame_timeline_event_parser.h"
 #include "src/trace_processor/importers/proto/gpu_event_parser.h"
 #include "src/trace_processor/importers/proto/graphics_frame_event_parser.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
@@ -42,7 +41,6 @@
  private:
   GpuEventParser parser_;
   GraphicsFrameEventParser frame_parser_;
-  FrameTimelineEventParser frame_timeline_parser_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/graphics_frame_event_parser.cc b/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
index b115d14..e33ed9c 100644
--- a/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
@@ -78,30 +78,12 @@
     return false;
   }
 
-  // Use buffer id + layer name as key because sometimes the same buffer can be
-  // used by different layers.
-  char event_key_buffer[4096];
-  base::StringWriter event_key_str(event_key_buffer,
-                                   base::ArraySize(event_key_buffer));
-  const uint32_t buffer_id = event.buffer_id();
-  StringId layer_name_id;
-  event_key_str.AppendUnsignedInt(buffer_id);
-
-  if (event.has_layer_name()) {
-    layer_name_id = context_->storage->InternString(event.layer_name());
-    event_key_str.AppendString(base::StringView(event.layer_name()));
-  } else {
-    layer_name_id = no_layer_name_name_id_;
-  }
-  StringId event_key =
-      context_->storage->InternString(event_key_str.GetStringView());
-
   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];
-      graphics_frame_stats_map_[event_key][type] = timestamp;
+      graphics_frame_stats_map_[event.buffer_id()][type] = timestamp;
     } else {
       context_->storage->IncrementStats(
           stats::graphics_frame_event_parser_errors);
@@ -113,12 +95,20 @@
     PERFETTO_ELOG("GraphicsFrameEvent with missing type field.");
   }
 
+  const uint32_t buffer_id = event.buffer_id();
+  StringId layer_name_id;
+
+  if (event.has_layer_name()) {
+    auto layer_name_str = event.layer_name();
+    const base::StringView layer_name(layer_name_str);
+    layer_name_id = context_->storage->InternString(layer_name);
+  } else {
+    layer_name_id = no_layer_name_name_id_;
+  }
   char buffer[4096];
-  base::StringWriter track_name(buffer, base::ArraySize(buffer));
+  base::StringWriter track_name(buffer, sizeof(buffer));
   track_name.AppendLiteral("Buffer: ");
   track_name.AppendUnsignedInt(buffer_id);
-  track_name.AppendLiteral(" ");
-  track_name.AppendString(base::StringView(event.layer_name()));
 
   const StringId track_name_id =
       context_->storage->InternString(track_name.GetStringView());
@@ -130,8 +120,6 @@
   track.scope = graphics_event_scope_id_;
   TrackId track_id = context_->track_tracker->InternGpuTrack(track);
 
-  auto* graphics_frame_slice_table =
-      context_->storage->mutable_graphics_frame_slice_table();
   {
     tables::GraphicsFrameSliceTable::Row row;
     row.ts = timestamp;
@@ -142,28 +130,27 @@
     row.layer_name = layer_name_id;
     if (event.type() == GraphicsFrameEvent::PRESENT_FENCE) {
       auto acquire_ts =
-          graphics_frame_stats_map_[event_key]
+          graphics_frame_stats_map_[event.buffer_id()]
                                    [GraphicsFrameEvent::ACQUIRE_FENCE];
-      auto queue_ts =
-          graphics_frame_stats_map_[event_key][GraphicsFrameEvent::QUEUE];
-      auto latch_ts =
-          graphics_frame_stats_map_[event_key][GraphicsFrameEvent::LATCH];
+      auto queue_ts = graphics_frame_stats_map_[event.buffer_id()]
+                                               [GraphicsFrameEvent::QUEUE];
+      auto latch_ts = graphics_frame_stats_map_[event.buffer_id()]
+                                               [GraphicsFrameEvent::LATCH];
 
       row.queue_to_acquire_time =
           std::max(acquire_ts - queue_ts, static_cast<int64_t>(0));
       row.acquire_to_latch_time = latch_ts - acquire_ts;
       row.latch_to_present_time = timestamp - latch_ts;
     }
-    base::Optional<SliceId> opt_slice_id =
-        context_->slice_tracker->ScopedTyped(graphics_frame_slice_table, row);
+    auto slice_id = context_->slice_tracker->ScopedFrameEvent(row);
     if (event.type() == GraphicsFrameEvent::DEQUEUE) {
-      if (opt_slice_id) {
-        dequeue_slice_ids_[event_key] = *opt_slice_id;
-      }
+      dequeue_slice_ids_[buffer_id] = slice_id;
     } else if (event.type() == GraphicsFrameEvent::QUEUE) {
-      auto it = dequeue_slice_ids_.find(event_key);
+      auto it = dequeue_slice_ids_.find(buffer_id);
       if (it != dequeue_slice_ids_.end()) {
         auto dequeue_slice_id = it->second;
+        auto* graphics_frame_slice_table =
+            context_->storage->mutable_graphics_frame_slice_table();
         uint32_t row_idx =
             *graphics_frame_slice_table->id().IndexOf(dequeue_slice_id);
         graphics_frame_slice_table->mutable_frame_number()->Set(row_idx,
@@ -174,30 +161,6 @@
   return true;
 }
 
-void GraphicsFrameEventParser::InvalidatePhaseEvent(int64_t timestamp,
-                                                    TrackId track_id,
-                                                    bool reset_name) {
-  const auto opt_slice_id = context_->slice_tracker->End(timestamp, track_id);
-
-  if (opt_slice_id) {
-    auto* graphics_frame_slice_table =
-        context_->storage->mutable_graphics_frame_slice_table();
-    uint32_t row_idx = *graphics_frame_slice_table->id().IndexOf(*opt_slice_id);
-    if (reset_name) {
-      // Set the name (frame_number) to be 0 since there is no frame number
-      // associated, example : dequeue event.
-      StringId frame_name_id = context_->storage->InternString("0");
-      graphics_frame_slice_table->mutable_name()->Set(row_idx, frame_name_id);
-      graphics_frame_slice_table->mutable_frame_number()->Set(row_idx, 0);
-    }
-
-    // Set the duration to -1 so that this slice will be ignored by the
-    // UI. Setting any other duration results in wrong data which we want
-    // to avoid at all costs.
-    graphics_frame_slice_table->mutable_dur()->Set(row_idx, -1);
-  }
-}
-
 // Here we convert the buffer events into Phases(slices)
 // APP: Dequeue to Queue
 // Wait for GPU: Queue to Acquire
@@ -206,30 +169,22 @@
 void GraphicsFrameEventParser::CreatePhaseEvent(
     int64_t timestamp,
     GraphicsFrameEventDecoder& event) {
-  // Use buffer id + layer name as key because sometimes the same buffer can be
-  // used by different layers.
-  char event_key_buffer[4096];
-  base::StringWriter event_key_str(event_key_buffer,
-                                   base::ArraySize(event_key_buffer));
   const uint32_t buffer_id = event.buffer_id();
   uint32_t frame_number = event.has_frame_number() ? event.frame_number() : 0;
-  event_key_str.AppendUnsignedInt(buffer_id);
   StringId layer_name_id;
   if (event.has_layer_name()) {
-    layer_name_id = context_->storage->InternString(event.layer_name());
-    event_key_str.AppendString(base::StringView(event.layer_name()));
+    auto layer_name_str = event.layer_name();
+    const base::StringView layer_name(layer_name_str);
+    layer_name_id = context_->storage->InternString(layer_name);
   } else {
     layer_name_id = no_layer_name_name_id_;
   }
-  StringId event_key =
-      context_->storage->InternString(event_key_str.GetStringView());
-
   char track_buffer[4096];
   char slice_buffer[4096];
   // We'll be using the name StringWriter and name_id for writing track names
   // and slice names.
-  base::StringWriter track_name(track_buffer, base::ArraySize(track_buffer));
-  base::StringWriter slice_name(slice_buffer, base::ArraySize(slice_buffer));
+  base::StringWriter track_name(track_buffer, sizeof(track_buffer));
+  base::StringWriter slice_name(slice_buffer, sizeof(slice_buffer));
   StringId track_name_id;
   TrackId track_id;
   bool start_slice = true;
@@ -240,36 +195,21 @@
       track_name.reset();
       track_name.AppendLiteral("APP_");
       track_name.AppendUnsignedInt(buffer_id);
-      track_name.AppendLiteral(" ");
-      track_name.AppendString(base::StringView(event.layer_name()));
       track_name_id =
           context_->storage->InternString(track_name.GetStringView());
       tables::GpuTrackTable::Row app_track(track_name_id);
       app_track.scope = graphics_event_scope_id_;
       track_id = context_->track_tracker->InternGpuTrack(app_track);
-
-      // Error handling
-      auto dequeue_time = dequeue_map_.find(event_key);
-      if (dequeue_time != dequeue_map_.end()) {
-        InvalidatePhaseEvent(timestamp, dequeue_time->second, true);
-        dequeue_map_.erase(dequeue_time);
-      }
-      auto queue_time = queue_map_.find(event_key);
-      if (queue_time != queue_map_.end()) {
-        InvalidatePhaseEvent(timestamp, queue_time->second);
-        queue_map_.erase(queue_time);
-      }
-
-      dequeue_map_[event_key] = track_id;
-      last_dequeued_[event_key] = timestamp;
+      dequeue_map_[buffer_id] = track_id;
+      last_dequeued_[buffer_id] = timestamp;
       break;
     }
 
     case GraphicsFrameEvent::QUEUE: {
-      auto dequeue_time = dequeue_map_.find(event_key);
-      if (dequeue_time != dequeue_map_.end()) {
-        const auto opt_slice_id =
-            context_->slice_tracker->End(timestamp, dequeue_time->second);
+      auto dequeueTime = dequeue_map_.find(buffer_id);
+      if (dequeueTime != dequeue_map_.end()) {
+        const auto opt_slice_id = context_->slice_tracker->EndFrameEvent(
+            timestamp, dequeueTime->second);
         slice_name.reset();
         slice_name.AppendUnsignedInt(frame_number);
         if (opt_slice_id) {
@@ -285,71 +225,88 @@
                                                           frame_name_id);
           graphics_frame_slice_table->mutable_frame_number()->Set(row_idx,
                                                                   frame_number);
-          dequeue_map_.erase(dequeue_time);
+          dequeue_map_.erase(dequeueTime);
         }
       }
       // The AcquireFence might be signaled before receiving a QUEUE event
       // sometimes. In that case, we shouldn't start a slice.
-      if (last_acquired_[event_key] > last_dequeued_[event_key] &&
-          last_acquired_[event_key] < timestamp) {
+      if (last_acquired_[buffer_id] > last_dequeued_[buffer_id] &&
+          last_acquired_[buffer_id] < timestamp) {
         start_slice = false;
         break;
       }
       track_name.reset();
       track_name.AppendLiteral("GPU_");
       track_name.AppendUnsignedInt(buffer_id);
-      track_name.AppendLiteral(" ");
-      track_name.AppendString(base::StringView(event.layer_name()));
       track_name_id =
           context_->storage->InternString(track_name.GetStringView());
       tables::GpuTrackTable::Row gpu_track(track_name_id);
       gpu_track.scope = graphics_event_scope_id_;
       track_id = context_->track_tracker->InternGpuTrack(gpu_track);
-      queue_map_[event_key] = track_id;
+      queue_map_[buffer_id] = track_id;
       break;
     }
     case GraphicsFrameEvent::ACQUIRE_FENCE: {
-      auto queue_time = queue_map_.find(event_key);
-      if (queue_time != queue_map_.end()) {
-        context_->slice_tracker->End(timestamp, queue_time->second);
-        queue_map_.erase(queue_time);
+      auto queueTime = queue_map_.find(buffer_id);
+      if (queueTime != queue_map_.end()) {
+        context_->slice_tracker->EndFrameEvent(timestamp, queueTime->second);
+        queue_map_.erase(queueTime);
       }
-      last_acquired_[event_key] = timestamp;
+      last_acquired_[buffer_id] = timestamp;
       start_slice = false;
       break;
     }
     case GraphicsFrameEvent::LATCH: {
       // b/157578286 - Sometimes Queue event goes missing. To prevent having a
       // wrong slice info, we try to close any existing APP slice.
-      auto dequeue_time = dequeue_map_.find(event_key);
-      if (dequeue_time != dequeue_map_.end()) {
-        InvalidatePhaseEvent(timestamp, dequeue_time->second, true);
-        dequeue_map_.erase(dequeue_time);
+      auto dequeueTime = dequeue_map_.find(buffer_id);
+      if (dequeueTime != dequeue_map_.end()) {
+        auto args_callback = [this](ArgsTracker::BoundInserter* inserter) {
+          inserter->AddArg(context_->storage->InternString("Details"),
+                           Variadic::String(queue_lost_message_id_));
+        };
+        const auto opt_slice_id = context_->slice_tracker->EndFrameEvent(
+            timestamp, dequeueTime->second, args_callback);
+        slice_name.reset();
+        slice_name.AppendUnsignedInt(frame_number);
+        if (opt_slice_id) {
+          auto* graphics_frame_slice_table =
+              context_->storage->mutable_graphics_frame_slice_table();
+          // Set the name of the slice to be the frame number since dequeue did
+          // not have a frame number at that time.
+          uint32_t row_idx =
+              *graphics_frame_slice_table->id().IndexOf(*opt_slice_id);
+          StringId frame_name_id =
+              context_->storage->InternString(slice_name.GetStringView());
+          graphics_frame_slice_table->mutable_name()->Set(row_idx,
+                                                          frame_name_id);
+          graphics_frame_slice_table->mutable_frame_number()->Set(row_idx,
+                                                                  frame_number);
+          dequeue_map_.erase(dequeueTime);
+        }
       }
       track_name.reset();
       track_name.AppendLiteral("SF_");
       track_name.AppendUnsignedInt(buffer_id);
-      track_name.AppendLiteral(" ");
-      track_name.AppendString(base::StringView(event.layer_name()));
       track_name_id =
           context_->storage->InternString(track_name.GetStringView());
       tables::GpuTrackTable::Row sf_track(track_name_id);
       sf_track.scope = graphics_event_scope_id_;
       track_id = context_->track_tracker->InternGpuTrack(sf_track);
-      latch_map_[event_key] = track_id;
+      latch_map_[buffer_id] = track_id;
       break;
     }
 
     case GraphicsFrameEvent::PRESENT_FENCE: {
-      auto latch_time = latch_map_.find(event_key);
-      if (latch_time != latch_map_.end()) {
-        context_->slice_tracker->End(timestamp, latch_time->second);
-        latch_map_.erase(latch_time);
+      auto latchTime = latch_map_.find(buffer_id);
+      if (latchTime != latch_map_.end()) {
+        context_->slice_tracker->EndFrameEvent(timestamp, latchTime->second);
+        latch_map_.erase(latchTime);
       }
-      auto display_time = display_map_.find(layer_name_id);
-      if (display_time != display_map_.end()) {
-        context_->slice_tracker->End(timestamp, display_time->second);
-        display_map_.erase(display_time);
+      auto displayTime = display_map_.find(layer_name_id);
+      if (displayTime != display_map_.end()) {
+        context_->slice_tracker->EndFrameEvent(timestamp, displayTime->second);
+        display_map_.erase(displayTime);
       }
       base::StringView layerName(event.layer_name());
       track_name.reset();
@@ -387,8 +344,7 @@
     }
     slice.name = context_->storage->InternString(slice_name.GetStringView());
     slice.frame_number = frame_number;
-    context_->slice_tracker->BeginTyped(
-        context_->storage->mutable_graphics_frame_slice_table(), slice);
+    context_->slice_tracker->BeginFrameEvent(slice);
   }
 }
 
diff --git a/src/trace_processor/importers/proto/graphics_frame_event_parser.h b/src/trace_processor/importers/proto/graphics_frame_event_parser.h
index 957e6ad..e23fa73 100644
--- a/src/trace_processor/importers/proto/graphics_frame_event_parser.h
+++ b/src/trace_processor/importers/proto/graphics_frame_event_parser.h
@@ -49,10 +49,6 @@
   using GraphicsFrameEvent = protos::pbzero::GraphicsFrameEvent;
   bool CreateBufferEvent(int64_t timestamp, GraphicsFrameEventDecoder& event);
   void CreatePhaseEvent(int64_t timestamp, GraphicsFrameEventDecoder& event);
-  // Invalidate a phase slice that has one of the events missing
-  void InvalidatePhaseEvent(int64_t timestamp,
-                            TrackId track_id,
-                            bool reset_name = false);
 
   TraceProcessorContext* const context_;
   const StringId graphics_event_scope_id_;
@@ -61,27 +57,26 @@
   const StringId layer_name_key_id_;
   std::array<StringId, 14> event_type_name_ids_;
   const StringId queue_lost_message_id_;
-  // Map of (buffer ID + layer name) -> slice id of the dequeue event
-  std::unordered_map<StringId, SliceId> dequeue_slice_ids_;
+  // Map of buffer ID -> slice id of the dequeue event
+  std::unordered_map<uint32_t, SliceId> dequeue_slice_ids_;
 
   // Row indices of frame stats table. Used to populate the slice_id after
   // inserting the rows.
   std::vector<uint32_t> graphics_frame_stats_idx_;
-  // Map of (buffer ID + layer name)
-  //    -> (Map of GraphicsFrameEvent -> ts of that event)
-  std::unordered_map<StringId, std::unordered_map<uint64_t, int64_t>>
+  // Map of buffer ID -> (Map of GraphicsFrameEvent -> ts of that event)
+  std::unordered_map<uint32_t, std::unordered_map<uint64_t, int64_t>>
       graphics_frame_stats_map_;
 
-  // Maps of (buffer id + layer name) -> track id
-  std::unordered_map<StringId, TrackId> dequeue_map_;
-  std::unordered_map<StringId, TrackId> queue_map_;
-  std::unordered_map<StringId, TrackId> latch_map_;
+  // Maps of buffer id -> track id
+  std::unordered_map<uint32_t, TrackId> dequeue_map_;
+  std::unordered_map<uint32_t, TrackId> queue_map_;
+  std::unordered_map<uint32_t, TrackId> latch_map_;
   // Map of layer name -> track id
   std::unordered_map<StringId, TrackId> display_map_;
 
-  // Maps of (buffer id + layer name) -> timestamp
-  std::unordered_map<StringId, int64_t> last_dequeued_;
-  std::unordered_map<StringId, int64_t> last_acquired_;
+  // Maps of buffer id -> timestamp
+  std::unordered_map<uint32_t, int64_t> last_dequeued_;
+  std::unordered_map<uint32_t, int64_t> last_acquired_;
 };
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index 530c14b..102473b 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -18,11 +18,9 @@
 
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/importers/proto/profiler_util.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
 #include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
 
 namespace perfetto {
@@ -67,35 +65,6 @@
   }
 }
 
-const char* HeapGraphTypeKindToString(int32_t type) {
-  switch (type) {
-    case protos::pbzero::HeapGraphType::KIND_NORMAL:
-      return "KIND_NORMAL";
-    case protos::pbzero::HeapGraphType::KIND_NOREFERENCES:
-      return "KIND_NOREFERENCES";
-    case protos::pbzero::HeapGraphType::KIND_STRING:
-      return "KIND_STRING";
-    case protos::pbzero::HeapGraphType::KIND_ARRAY:
-      return "KIND_ARRAY";
-    case protos::pbzero::HeapGraphType::KIND_CLASS:
-      return "KIND_CLASS";
-    case protos::pbzero::HeapGraphType::KIND_CLASSLOADER:
-      return "KIND_CLASSLOADER";
-    case protos::pbzero::HeapGraphType::KIND_DEXCACHE:
-      return "KIND_DEXCACHE";
-    case protos::pbzero::HeapGraphType::KIND_SOFT_REFERENCE:
-      return "KIND_SOFT_REFERENCE";
-    case protos::pbzero::HeapGraphType::KIND_WEAK_REFERENCE:
-      return "KIND_WEAK_REFERENCE";
-    case protos::pbzero::HeapGraphType::KIND_FINALIZER_REFERENCE:
-      return "KIND_FINALIZER_REFERENCE";
-    case protos::pbzero::HeapGraphType::KIND_PHANTOM_REFERENCE:
-      return "KIND_PHANTOM_REFERENCE";
-    default:
-      return "KIND_UNKNOWN";
-  }
-}
-
 // Iterate over a repeated field of varints, independent of whether it is
 // packed or not.
 template <int32_t field_no, typename T, typename F>
@@ -154,36 +123,22 @@
   for (auto it = heap_graph.objects(); it; ++it) {
     protos::pbzero::HeapGraphObject::Decoder object(*it);
     HeapGraphTracker::SourceObject obj;
-    if (object.id_delta()) {
-      obj.object_id =
-          heap_graph_tracker->GetLastObjectId(seq_id) + object.id_delta();
-    } else {
-      obj.object_id = object.id();
-    }
+    obj.object_id = object.id();
     obj.self_size = object.self_size();
     obj.type_id = object.type_id();
 
-    uint64_t base_obj_id = object.reference_field_id_base();
+    std::vector<uint64_t> field_ids;
+    std::vector<uint64_t> object_ids;
 
-    // In S+ traces, this field will not be set for normal instances. It will be
-    // set in the corresponding HeapGraphType instead. It will still be set for
-    // class objects.
-    //
-    // grep-friendly: reference_field_id
     bool parse_error = ForEachVarInt<
         protos::pbzero::HeapGraphObject::kReferenceFieldIdFieldNumber>(
-        object,
-        [&obj](uint64_t value) { obj.field_name_ids.push_back(value); });
+        object, [&field_ids](uint64_t value) { field_ids.push_back(value); });
 
     if (!parse_error) {
-      // grep-friendly: reference_object_id
       parse_error = ForEachVarInt<
           protos::pbzero::HeapGraphObject::kReferenceObjectIdFieldNumber>(
-          object, [&obj, base_obj_id](uint64_t value) {
-            if (value)
-              value += base_obj_id;
-            obj.referred_objects.push_back(value);
-          });
+          object,
+          [&object_ids](uint64_t value) { object_ids.push_back(value); });
     }
 
     if (parse_error) {
@@ -191,47 +146,35 @@
           stats::heap_graph_malformed_packet, static_cast<int>(upid));
       break;
     }
-    if (!obj.field_name_ids.empty() &&
-        (obj.field_name_ids.size() != obj.referred_objects.size())) {
+    if (field_ids.size() != object_ids.size()) {
       context_->storage->IncrementIndexedStats(
           stats::heap_graph_malformed_packet, static_cast<int>(upid));
       continue;
     }
+    for (size_t i = 0; i < field_ids.size(); ++i) {
+      HeapGraphTracker::SourceObject::Reference ref;
+      ref.field_name_id = field_ids[i];
+      ref.owned_object_id = object_ids[i];
+      obj.references.emplace_back(std::move(ref));
+    }
     heap_graph_tracker->AddObject(seq_id, upid, ts, std::move(obj));
   }
   for (auto it = heap_graph.types(); it; ++it) {
-    std::vector<uint64_t> field_name_ids;
     protos::pbzero::HeapGraphType::Decoder entry(*it);
     const char* str = reinterpret_cast<const char*>(entry.class_name().data);
     auto str_view = base::StringView(str, entry.class_name().size);
 
-    // grep-friendly: reference_field_id
-    bool parse_error = ForEachVarInt<
-        protos::pbzero::HeapGraphType::kReferenceFieldIdFieldNumber>(
-        entry,
-        [&field_name_ids](uint64_t value) { field_name_ids.push_back(value); });
-
-    if (parse_error) {
-      context_->storage->IncrementIndexedStats(
-          stats::heap_graph_malformed_packet, static_cast<int>(upid));
-      continue;
-    }
-
-    bool no_fields =
-        entry.kind() == protos::pbzero::HeapGraphType::KIND_NOREFERENCES ||
-        entry.kind() == protos::pbzero::HeapGraphType::KIND_ARRAY ||
-        entry.kind() == protos::pbzero::HeapGraphType::KIND_STRING;
-
-    StringPool::Id kind = context_->storage->InternString(
-        HeapGraphTypeKindToString(entry.kind()));
-    base::Optional<uint64_t> location_id;
-    if (entry.has_location_id())
-      location_id = entry.location_id();
-
     heap_graph_tracker->AddInternedType(
         seq_id, entry.id(), context_->storage->InternString(str_view),
-        location_id, entry.object_size(), std::move(field_name_ids),
-        entry.superclass_id(), entry.classloader_id(), no_fields, kind);
+        entry.location_id());
+  }
+  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);
+
+    heap_graph_tracker->AddInternedTypeName(
+        seq_id, entry.iid(), context_->storage->InternString(str_view));
   }
   for (auto it = heap_graph.field_names(); it; ++it) {
     protos::pbzero::InternedString::Decoder entry(*it);
@@ -255,7 +198,6 @@
 
     HeapGraphTracker::SourceRoot src_root;
     src_root.root_type = context_->storage->InternString(str_view);
-    // grep-friendly: object_ids
     bool parse_error =
         ForEachVarInt<protos::pbzero::HeapGraphRoot::kObjectIdsFieldNumber>(
             entry, [&src_root](uint64_t value) {
@@ -283,22 +225,23 @@
                                       obfuscated_class_name_id);
 
   if (cls_objects) {
+    heap_graph_tracker->AddDeobfuscationMapping(
+        package_name_id, obfuscated_class_name_id,
+        context_->storage->InternString(
+            base::StringView(cls.deobfuscated_name())));
+
     for (tables::HeapGraphClassTable::Id id : *cls_objects) {
       uint32_t row =
           *context_->storage->heap_graph_class_table().id().IndexOf(id);
-      const StringPool::Id obfuscated_type_name_id =
+      const StringPool::Id obfuscated_type_name =
           context_->storage->heap_graph_class_table().name()[row];
-      const base::StringView obfuscated_type_name =
-          context_->storage->GetString(obfuscated_type_name_id);
-      NormalizedType normalized_type = GetNormalizedType(obfuscated_type_name);
-      std::string deobfuscated_type_name =
-          DenormalizeTypeName(normalized_type, cls.deobfuscated_name());
-      StringPool::Id deobfuscated_type_name_id =
-          context_->storage->InternString(
-              base::StringView(deobfuscated_type_name));
+      StringPool::Id deobfuscated_type_name =
+          heap_graph_tracker->MaybeDeobfuscate(package_name_id,
+                                               obfuscated_type_name);
+      PERFETTO_CHECK(!deobfuscated_type_name.is_null());
       context_->storage->mutable_heap_graph_class_table()
           ->mutable_deobfuscated_name()
-          ->Set(row, deobfuscated_type_name_id);
+          ->Set(row, deobfuscated_type_name);
     }
   } else {
     PERFETTO_DLOG("Class %s not found",
@@ -339,8 +282,17 @@
       std::string merged_obfuscated = cls.obfuscated_name().ToStdString() +
                                       "." +
                                       member.obfuscated_name().ToStdString();
-      std::string merged_deobfuscated =
-          FullyQualifiedDeobfuscatedName(cls, member);
+      std::string merged_deobfuscated;
+      std::string member_deobfuscated_name =
+          member.deobfuscated_name().ToStdString();
+      if (member_deobfuscated_name.find('.') == std::string::npos) {
+        // Name relative to class.
+        merged_deobfuscated = cls.deobfuscated_name().ToStdString() + "." +
+                              member_deobfuscated_name;
+      } else {
+        // Fully qualified name.
+        merged_deobfuscated = std::move(member_deobfuscated_name);
+      }
 
       auto obfuscated_field_name_id = context_->storage->string_pool().GetId(
           base::StringView(merged_obfuscated));
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
index 76f4146..b1816b0 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.h
+++ b/src/trace_processor/importers/proto/heap_graph_module.h
@@ -22,7 +22,6 @@
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
 
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index e9b400d..e320f6e 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -16,30 +16,44 @@
 
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/importers/proto/profiler_util.h"
-#include "src/trace_processor/tables/profiler_tables.h"
 
 #include <set>
-#include <utility>
 
 namespace perfetto {
 namespace trace_processor {
 
 namespace {
+base::Optional<base::StringView> PackageFromApp(base::StringView location) {
+  location = location.substr(base::StringView("/data/app/").size());
+  size_t slash = location.find('/');
+  if (slash == std::string::npos) {
+    return base::nullopt;
+  }
+  size_t second_slash = location.find('/', slash + 1);
+  if (second_slash == std::string::npos) {
+    location = location.substr(0, slash);
+  } else {
+    location = location.substr(slash + 1, second_slash - slash);
+  }
+  size_t minus = location.find('-');
+  if (minus == std::string::npos) {
+    return base::nullopt;
+  }
+  return location.substr(0, minus);
+}
 
-template <typename F>
-void ForReferenceSet(const TraceStorage& storage,
-                     tables::HeapGraphObjectTable::Id id,
-                     F fn) {
+std::set<tables::HeapGraphObjectTable::Id> GetChildren(
+    const TraceStorage& storage,
+    tables::HeapGraphObjectTable::Id id) {
   uint32_t row = *storage.heap_graph_object_table().id().IndexOf(id);
   base::Optional<uint32_t> reference_set_id =
       storage.heap_graph_object_table().reference_set_id()[row];
   if (!reference_set_id)
-    return;
+    return {};
   uint32_t cur_reference_set_id;
+  std::set<tables::HeapGraphObjectTable::Id> children;
   for (uint32_t reference_row = *reference_set_id;
        reference_row < storage.heap_graph_reference_table().row_count();
        ++reference_row) {
@@ -47,142 +61,14 @@
         storage.heap_graph_reference_table().reference_set_id()[reference_row];
     if (cur_reference_set_id != *reference_set_id)
       break;
-    if (!fn(reference_row))
-      break;
+
+    PERFETTO_CHECK(
+        storage.heap_graph_reference_table().owner_id()[reference_row] == id);
+    children.emplace(
+        storage.heap_graph_reference_table().owned_id()[reference_row]);
   }
-}
-
-std::set<tables::HeapGraphObjectTable::Id> GetChildren(
-    const TraceStorage& storage,
-    tables::HeapGraphObjectTable::Id id) {
-  uint32_t obj_row = *storage.heap_graph_object_table().id().IndexOf(id);
-  uint32_t cls_row = *storage.heap_graph_class_table().id().IndexOf(
-      storage.heap_graph_object_table().type_id()[obj_row]);
-
-  StringPool::Id kind = storage.heap_graph_class_table().kind()[cls_row];
-  base::Optional<StringPool::Id> weakref_kind =
-      storage.string_pool().GetId("KIND_WEAK_REFERENCE");
-  base::Optional<StringPool::Id> softref_kind =
-      storage.string_pool().GetId("KIND_SOFT_REFERENCE");
-  base::Optional<StringPool::Id> finalizerref_kind =
-      storage.string_pool().GetId("KIND_FINALIZER_REFERENCE");
-  base::Optional<StringPool::Id> phantomref_kind =
-      storage.string_pool().GetId("KIND_PHANTOM_REFERENCE");
-
-  if ((weakref_kind && kind == *weakref_kind) ||
-      (softref_kind && kind == *softref_kind) ||
-      (finalizerref_kind && kind == *finalizerref_kind) ||
-      (phantomref_kind && kind == *phantomref_kind)) {
-    // Do not follow weak / soft / finalizer / phantom references.
-    return {};
-  }
-
-  std::set<tables::HeapGraphObjectTable::Id> children;
-  ForReferenceSet(
-      storage, id, [&storage, &children, id](uint32_t reference_row) {
-        PERFETTO_CHECK(
-            storage.heap_graph_reference_table().owner_id()[reference_row] ==
-            id);
-        auto opt_owned =
-            storage.heap_graph_reference_table().owned_id()[reference_row];
-        if (opt_owned) {
-          children.emplace(*opt_owned);
-        }
-        return true;
-      });
   return children;
 }
-
-struct ClassDescriptor {
-  StringId name;
-  base::Optional<StringId> location;
-
-  bool operator<(const ClassDescriptor& other) const {
-    return std::tie(name, location) < std::tie(other.name, other.location);
-  }
-};
-
-ClassDescriptor GetClassDescriptor(const TraceStorage& storage,
-                                   tables::HeapGraphObjectTable::Id obj_id) {
-  auto obj_idx = storage.heap_graph_object_table().id().IndexOf(obj_id).value();
-  auto type_id = storage.heap_graph_object_table().type_id()[obj_idx];
-  auto type_idx =
-      storage.heap_graph_class_table().id().IndexOf(type_id).value();
-  return {storage.heap_graph_class_table().name()[type_idx],
-          storage.heap_graph_class_table().location()[type_idx]};
-}
-
-base::Optional<tables::HeapGraphObjectTable::Id> GetReferredObj(
-    const TraceStorage& storage,
-    uint32_t ref_set_id,
-    const std::string& field_name) {
-  const auto& refs_tbl = storage.heap_graph_reference_table();
-
-  auto filtered = refs_tbl.Filter(
-      {refs_tbl.reference_set_id().eq(ref_set_id),
-       refs_tbl.field_name().eq(NullTermStringView(field_name))});
-  auto refs_it = filtered.IterateRows();
-  if (!refs_it) {
-    return {};
-  }
-
-  SqlValue sql_owned = refs_it.Get(static_cast<uint32_t>(
-      tables::HeapGraphReferenceTable::ColumnIndex::owned_id));
-  if (sql_owned.is_null()) {
-    return base::nullopt;
-  }
-  return tables::HeapGraphObjectTable::Id(
-      static_cast<uint32_t>(sql_owned.AsLong()));
-}
-
-// Maps from normalized class name and location, to superclass.
-std::map<ClassDescriptor, ClassDescriptor>
-BuildSuperclassMap(UniquePid upid, int64_t ts, TraceStorage* storage) {
-  std::map<ClassDescriptor, ClassDescriptor> superclass_map;
-
-  // Resolve superclasses by iterating heap graph objects and identifying the
-  // superClass field.
-  const auto& objects_tbl = storage->heap_graph_object_table();
-  auto filtered = objects_tbl.Filter(
-      {objects_tbl.upid().eq(upid), objects_tbl.graph_sample_ts().eq(ts)});
-  for (auto obj_it = filtered.IterateRows(); obj_it; obj_it.Next()) {
-    auto obj_id = tables::HeapGraphObjectTable::Id(static_cast<uint32_t>(
-        obj_it
-            .Get(static_cast<uint32_t>(
-                tables::HeapGraphObjectTable::ColumnIndex::id))
-            .AsLong()));
-    auto class_descriptor = GetClassDescriptor(*storage, obj_id);
-    auto normalized =
-        GetNormalizedType(storage->GetString(class_descriptor.name));
-    // superClass ptrs are stored on the static class objects
-    // ignore arrays (as they are generated objects)
-    if (!normalized.is_static_class || normalized.number_of_arrays > 0)
-      continue;
-
-    auto opt_ref_set_id = obj_it.Get(static_cast<uint32_t>(
-        tables::HeapGraphObjectTable::ColumnIndex::reference_set_id));
-    if (opt_ref_set_id.is_null())
-      continue;
-    auto ref_set_id = static_cast<uint32_t>(opt_ref_set_id.AsLong());
-    auto super_obj_id =
-        GetReferredObj(*storage, ref_set_id, "java.lang.Class.superClass");
-    if (!super_obj_id) {
-      // This is expected to be missing for Object and primitive types
-      continue;
-    }
-
-    // Lookup the super obj type id
-    auto super_class_descriptor = GetClassDescriptor(*storage, *super_obj_id);
-    auto super_class_name =
-        NormalizeTypeName(storage->GetString(super_class_descriptor.name));
-    StringId super_class_id = storage->InternString(super_class_name);
-    StringId class_id = storage->InternString(normalized.name);
-    superclass_map[{class_id, class_descriptor.location}] = {
-        super_class_id, super_class_descriptor.location};
-  }
-  return superclass_map;
-}
-
 }  // namespace
 
 void MarkRoot(TraceStorage* storage,
@@ -277,6 +163,94 @@
 HeapGraphTracker::HeapGraphTracker(TraceProcessorContext* context)
     : context_(context) {}
 
+base::Optional<std::string> HeapGraphTracker::PackageFromLocation(
+    base::StringView location) {
+  // List of some hardcoded apps that do not follow the scheme used in
+  // PackageFromApp. Ask for yours to be added.
+  //
+  // TODO(b/153632336): Get rid of the hardcoded list of system apps.
+  base::StringView sysui(
+      "/system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk");
+  if (location.size() >= sysui.size() &&
+      location.substr(0, sysui.size()) == sysui) {
+    return "com.android.systemui";
+  }
+
+  base::StringView phonesky("/product/priv-app/Phonesky/Phonesky.apk");
+  if (location.size() >= phonesky.size() &&
+      location.substr(0, phonesky.size()) == phonesky) {
+    return "com.android.vending";
+  }
+
+  base::StringView maps("/product/app/Maps/Maps.apk");
+  if (location.size() >= maps.size() &&
+      location.substr(0, maps.size()) == maps) {
+    return "com.google.android.apps.maps";
+  }
+
+  base::StringView launcher(
+      "/system_ext/priv-app/NexusLauncherRelease/NexusLauncherRelease.apk");
+  if (location.size() >= launcher.size() &&
+      location.substr(0, launcher.size()) == launcher) {
+    return "com.google.android.apps.nexuslauncher";
+  }
+
+  base::StringView photos("/product/app/Photos/Photos.apk");
+  if (location.size() >= photos.size() &&
+      location.substr(0, photos.size()) == photos) {
+    return "com.google.android.apps.photos";
+  }
+
+  base::StringView wellbeing(
+      "/product/priv-app/WellbeingPrebuilt/WellbeingPrebuilt.apk");
+  if (location.size() >= wellbeing.size() &&
+      location.substr(0, wellbeing.size()) == wellbeing) {
+    return "com.google.android.apps.wellbeing";
+  }
+
+  base::StringView matchmaker("MatchMaker");
+  if (location.size() >= matchmaker.size() &&
+      location.find(matchmaker) != base::StringView::npos) {
+    return "com.google.android.as";
+  }
+
+  base::StringView gm("/product/app/PrebuiltGmail/PrebuiltGmail.apk");
+  if (location.size() >= gm.size() && location.substr(0, gm.size()) == gm) {
+    return "com.google.android.gm";
+  }
+
+  base::StringView gmscore("/product/priv-app/PrebuiltGmsCore/PrebuiltGmsCore");
+  if (location.size() >= gmscore.size() &&
+      location.substr(0, gmscore.size()) == gmscore) {
+    return "com.google.android.gms";
+  }
+
+  base::StringView velvet("/product/priv-app/Velvet/Velvet.apk");
+  if (location.size() >= velvet.size() &&
+      location.substr(0, velvet.size()) == velvet) {
+    return "com.google.android.googlequicksearchbox";
+  }
+
+  base::StringView inputmethod(
+      "/product/app/LatinIMEGooglePrebuilt/LatinIMEGooglePrebuilt.apk");
+  if (location.size() >= inputmethod.size() &&
+      location.substr(0, inputmethod.size()) == inputmethod) {
+    return "com.google.android.inputmethod.latin";
+  }
+
+  base::StringView data_app("/data/app/");
+  if (location.substr(0, data_app.size()) == data_app) {
+    auto package = PackageFromApp(location);
+    if (!package) {
+      PERFETTO_DLOG("Failed to parse %s", location.ToStdString().c_str());
+      context_->storage->IncrementStats(stats::heap_graph_location_parse_error);
+      return base::nullopt;
+    }
+    return package->ToStdString();
+  }
+  return base::nullopt;
+}
+
 HeapGraphTracker::SequenceState& HeapGraphTracker::GetOrCreateSequence(
     uint32_t seq_id) {
   return sequence_state_[seq_id];
@@ -345,8 +319,6 @@
   if (!SetPidAndTimestamp(&sequence_state, upid, ts))
     return;
 
-  sequence_state.last_object_id = obj.object_id;
-
   tables::HeapGraphObjectTable::Id owner_id =
       GetOrInsertObject(&sequence_state, obj.object_id);
   tables::HeapGraphClassTable::Id type_id =
@@ -358,19 +330,15 @@
   hgo->mutable_self_size()->Set(row, static_cast<int64_t>(obj.self_size));
   hgo->mutable_type_id()->Set(row, type_id);
 
-  if (obj.self_size == 0)
-    sequence_state.deferred_size_objects_for_type_[type_id].push_back(owner_id);
-
   uint32_t reference_set_id =
       context_->storage->heap_graph_reference_table().row_count();
   bool any_references = false;
-
-  for (size_t i = 0; i < obj.referred_objects.size(); ++i) {
-    uint64_t owned_object_id = obj.referred_objects[i];
+  for (const SourceObject::Reference& ref : obj.references) {
     // This is true for unset reference fields.
-    base::Optional<tables::HeapGraphObjectTable::Id> owned_id;
-    if (owned_object_id != 0)
-      owned_id = GetOrInsertObject(&sequence_state, owned_object_id);
+    if (ref.owned_object_id == 0)
+      continue;
+    tables::HeapGraphObjectTable::Id owned_id =
+        GetOrInsertObject(&sequence_state, ref.owned_object_id);
 
     auto ref_id_and_row =
         context_->storage->mutable_heap_graph_reference_table()->Insert(
@@ -380,10 +348,8 @@
              {},
              {},
              /*deobfuscated_field_name=*/base::nullopt});
-    if (!obj.field_name_ids.empty()) {
-      sequence_state.references_for_field_name_id[obj.field_name_ids[i]]
-          .push_back(ref_id_and_row.id);
-    }
+    sequence_state.references_for_field_name_id[ref.field_name_id].push_back(
+        ref_id_and_row.id);
     any_references = true;
   }
   if (any_references) {
@@ -392,10 +358,6 @@
     context_->storage->mutable_heap_graph_object_table()
         ->mutable_reference_set_id()
         ->Set(owner_row, reference_set_id);
-    if (obj.field_name_ids.empty()) {
-      sequence_state.deferred_reference_objects_for_type_[type_id].push_back(
-          owner_id);
-    }
   }
 }
 
@@ -417,26 +379,20 @@
   sequence_state.interned_location_names.emplace(intern_id, strid);
 }
 
+void HeapGraphTracker::AddInternedTypeName(uint32_t seq_id,
+                                           uint64_t intern_id,
+                                           StringPool::Id strid) {
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  sequence_state.interned_types[intern_id].name = strid;
+}
+
 void HeapGraphTracker::AddInternedType(uint32_t seq_id,
                                        uint64_t intern_id,
                                        StringPool::Id strid,
-                                       base::Optional<uint64_t> location_id,
-                                       uint64_t object_size,
-                                       std::vector<uint64_t> field_name_ids,
-                                       uint64_t superclass_id,
-                                       uint64_t classloader_id,
-                                       bool no_fields,
-                                       StringPool::Id kind) {
+                                       uint64_t location_id) {
   SequenceState& sequence_state = GetOrCreateSequence(seq_id);
   sequence_state.interned_types[intern_id].name = strid;
   sequence_state.interned_types[intern_id].location_id = location_id;
-  sequence_state.interned_types[intern_id].object_size = object_size;
-  sequence_state.interned_types[intern_id].field_name_ids =
-      std::move(field_name_ids);
-  sequence_state.interned_types[intern_id].superclass_id = superclass_id;
-  sequence_state.interned_types[intern_id].classloader_id = classloader_id;
-  sequence_state.interned_types[intern_id].no_fields = no_fields;
-  sequence_state.interned_types[intern_id].kind = kind;
 }
 
 void HeapGraphTracker::AddInternedFieldName(uint32_t seq_id,
@@ -451,10 +407,6 @@
   }
   StringPool::Id field_name = context_->storage->InternString(str);
   StringPool::Id type_name = context_->storage->InternString(type);
-
-  sequence_state.interned_fields.emplace(intern_id,
-                                         InternedField{field_name, type_name});
-
   auto it = sequence_state.references_for_field_name_id.find(intern_id);
   if (it != sequence_state.references_for_field_name_id.end()) {
     auto hgr = context_->storage->mutable_heap_graph_reference_table();
@@ -481,7 +433,6 @@
   }
 
   if (dropped_packet) {
-    sequence_state.truncated = true;
     if (sequence_state.prev_index) {
       PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
                     *sequence_state.prev_index, index);
@@ -496,31 +447,9 @@
   sequence_state.prev_index = index;
 }
 
-// This only works on Android S+ traces. We need to have ingested the whole
-// profile before calling this function (e.g. in FinalizeProfile).
-HeapGraphTracker::InternedType* HeapGraphTracker::GetSuperClass(
-    SequenceState* sequence_state,
-    const InternedType* current_type) {
-  if (current_type->superclass_id) {
-    auto it = sequence_state->interned_types.find(current_type->superclass_id);
-    if (it != sequence_state->interned_types.end())
-      return &it->second;
-  }
-  context_->storage->IncrementIndexedStats(
-      stats::heap_graph_malformed_packet,
-      static_cast<int>(sequence_state->current_upid));
-  return nullptr;
-}
-
 void HeapGraphTracker::FinalizeProfile(uint32_t seq_id) {
   SequenceState& sequence_state = GetOrCreateSequence(seq_id);
-  if (sequence_state.truncated) {
-    truncated_graphs_.emplace(
-        std::make_pair(sequence_state.current_upid, sequence_state.current_ts));
-  }
 
-  // We do this in FinalizeProfile because the interned_location_names get
-  // written at the end of the dump.
   for (const auto& p : sequence_state.interned_types) {
     uint64_t id = p.first;
     const InternedType& interned_type = p.second;
@@ -532,6 +461,7 @@
         context_->storage->IncrementIndexedStats(
             stats::heap_graph_invalid_string_id,
             static_cast<int>(sequence_state.current_upid));
+
       } else {
         location_name = it->second;
       }
@@ -539,77 +469,11 @@
     tables::HeapGraphClassTable::Id type_id =
         GetOrInsertType(&sequence_state, id);
 
-    auto sz_obj_it =
-        sequence_state.deferred_size_objects_for_type_.find(type_id);
-    if (sz_obj_it != sequence_state.deferred_size_objects_for_type_.end()) {
-      for (tables::HeapGraphObjectTable::Id obj_id : sz_obj_it->second) {
-        auto* hgo = context_->storage->mutable_heap_graph_object_table();
-        uint32_t row = *hgo->id().IndexOf(obj_id);
-        hgo->mutable_self_size()->Set(
-            row, static_cast<int64_t>(interned_type.object_size));
-      }
-      sequence_state.deferred_size_objects_for_type_.erase(sz_obj_it);
-    }
-
-    auto ref_obj_it =
-        sequence_state.deferred_reference_objects_for_type_.find(type_id);
-    if (ref_obj_it !=
-        sequence_state.deferred_reference_objects_for_type_.end()) {
-      for (tables::HeapGraphObjectTable::Id obj_id : ref_obj_it->second) {
-        const InternedType* current_type = &interned_type;
-        if (interned_type.no_fields) {
-          continue;
-        }
-        size_t field_offset_in_cls = 0;
-        ForReferenceSet(
-            *context_->storage, obj_id,
-            [this, &current_type, &sequence_state,
-             &field_offset_in_cls](uint32_t reference_row) {
-              while (current_type && field_offset_in_cls >=
-                                         current_type->field_name_ids.size()) {
-                size_t prev_type_size = current_type->field_name_ids.size();
-                current_type = GetSuperClass(&sequence_state, current_type);
-                field_offset_in_cls -= prev_type_size;
-              }
-
-              if (!current_type) {
-                return false;
-              }
-
-              uint64_t field_id =
-                  current_type->field_name_ids[field_offset_in_cls++];
-              auto it = sequence_state.interned_fields.find(field_id);
-              if (it == sequence_state.interned_fields.end()) {
-                PERFETTO_ELOG("Invalid field id.");
-                context_->storage->IncrementIndexedStats(
-                    stats::heap_graph_malformed_packet,
-                    static_cast<int>(sequence_state.current_upid));
-                return true;
-              }
-              const InternedField& field = it->second;
-              auto hgr =
-                  context_->storage->mutable_heap_graph_reference_table();
-              hgr->mutable_field_name()->Set(reference_row, field.name);
-              hgr->mutable_field_type_name()->Set(reference_row,
-                                                  field.type_name);
-              field_to_rows_[field.name].emplace_back(reference_row);
-              return true;
-            });
-      }
-      sequence_state.deferred_reference_objects_for_type_.erase(ref_obj_it);
-    }
-
     auto* hgc = context_->storage->mutable_heap_graph_class_table();
     uint32_t row = *hgc->id().IndexOf(type_id);
     hgc->mutable_name()->Set(row, interned_type.name);
-    if (interned_type.classloader_id) {
-      auto classloader_object_id =
-          GetOrInsertObject(&sequence_state, interned_type.classloader_id);
-      hgc->mutable_classloader_id()->Set(row, classloader_object_id.value);
-    }
     if (location_name)
       hgc->mutable_location()->Set(row, *location_name);
-    hgc->mutable_kind()->Set(row, interned_type.kind);
 
     base::StringView normalized_type =
         NormalizeTypeName(context_->storage->GetString(interned_type.name));
@@ -625,8 +489,7 @@
 
     if (location_name && !is_base_apk) {
       base::Optional<std::string> package_name =
-          PackageFromLocation(context_->storage.get(),
-                              context_->storage->GetString(*location_name));
+          PackageFromLocation(context_->storage->GetString(*location_name));
       if (package_name) {
         class_to_rows_[std::make_pair(
                            context_->storage->InternString(
@@ -649,18 +512,6 @@
     }
   }
 
-  if (!sequence_state.deferred_size_objects_for_type_.empty()) {
-    context_->storage->IncrementIndexedStats(
-        stats::heap_graph_malformed_packet,
-        static_cast<int>(sequence_state.current_upid));
-  }
-
-  if (!sequence_state.deferred_reference_objects_for_type_.empty()) {
-    context_->storage->IncrementIndexedStats(
-        stats::heap_graph_malformed_packet,
-        static_cast<int>(sequence_state.current_upid));
-  }
-
   for (const SourceRoot& root : sequence_state.current_roots) {
     for (uint64_t obj_id : root.object_ids) {
       auto it = sequence_state.object_id_to_db_id.find(obj_id);
@@ -670,64 +521,17 @@
         continue;
 
       tables::HeapGraphObjectTable::Id db_id = it->second;
-      auto it_and_success = roots_[std::make_pair(sequence_state.current_upid,
-                                                  sequence_state.current_ts)]
-                                .emplace(db_id);
-      if (it_and_success.second)
-        MarkRoot(context_->storage.get(), db_id, root.root_type);
+      roots_[std::make_pair(sequence_state.current_upid,
+                            sequence_state.current_ts)]
+          .emplace_back(db_id);
+      MarkRoot(context_->storage.get(), db_id, root.root_type);
     }
   }
 
-  PopulateSuperClasses(sequence_state);
   sequence_state_.erase(seq_id);
 }
 
-// TODO(fmayer): For Android S+ traces, use the superclass_id from the trace.
-void HeapGraphTracker::PopulateSuperClasses(const SequenceState& seq) {
-  // Maps from normalized class name and location, to superclass.
-  std::map<ClassDescriptor, ClassDescriptor> superclass_map =
-      BuildSuperclassMap(seq.current_upid, seq.current_ts,
-                         context_->storage.get());
-
-  auto* classes_tbl = context_->storage->mutable_heap_graph_class_table();
-  std::map<ClassDescriptor, tables::HeapGraphClassTable::Id> class_to_id;
-  for (uint32_t idx = 0; idx < classes_tbl->row_count(); ++idx) {
-    class_to_id[{classes_tbl->name()[idx], classes_tbl->location()[idx]}] =
-        classes_tbl->id()[idx];
-  }
-
-  // Iterate through the classes table and annotate with superclasses.
-  // We iterate all rows on the classes table (even though the superclass
-  // mapping was generated on the current sequence) - if we cannot identify
-  // a superclass we will just skip.
-  for (uint32_t idx = 0; idx < classes_tbl->row_count(); ++idx) {
-    auto name = context_->storage->GetString(classes_tbl->name()[idx]);
-    auto location = classes_tbl->location()[idx];
-    auto normalized = GetNormalizedType(name);
-    if (normalized.is_static_class || normalized.number_of_arrays > 0)
-      continue;
-
-    StringId class_name_id = context_->storage->InternString(normalized.name);
-    auto map_it = superclass_map.find({class_name_id, location});
-    if (map_it == superclass_map.end()) {
-      continue;
-    }
-
-    // Find the row for the superclass id
-    auto superclass_it = class_to_id.find(map_it->second);
-    if (superclass_it == class_to_id.end()) {
-      // This can happen for traces was captured before the patch to
-      // explicitly emit interned types (meaning classes without live
-      // instances would not appear here).
-      continue;
-    }
-    auto superclass_id = superclass_it->second;
-    // Mutate the superclass column
-    classes_tbl->mutable_superclass_id()->Set(idx, superclass_id);
-  }
-}
-
-void FindPathFromRoot(TraceStorage* storage,
+void FindPathFromRoot(const TraceStorage& storage,
                       tables::HeapGraphObjectTable::Id id,
                       PathFromRoot* path) {
   // We have long retention chains (e.g. from LinkedList). If we use the stack
@@ -746,7 +550,7 @@
 
   while (!stack.empty()) {
     tables::HeapGraphObjectTable::Id n = stack.back().node;
-    uint32_t row = *storage->heap_graph_object_table().id().IndexOf(n);
+    uint32_t row = *storage.heap_graph_object_table().id().IndexOf(n);
     size_t parent_id = stack.back().parent_id;
     uint32_t depth = stack.back().depth;
     size_t& i = stack.back().i;
@@ -754,31 +558,14 @@
         stack.back().children;
 
     tables::HeapGraphClassTable::Id type_id =
-        storage->heap_graph_object_table().type_id()[row];
-
-    uint32_t type_row =
-        *storage->heap_graph_class_table().id().IndexOf(type_id);
-    base::Optional<StringPool::Id> opt_class_name_id =
-        storage->heap_graph_class_table().deobfuscated_name()[type_row];
-    if (!opt_class_name_id) {
-      opt_class_name_id = storage->heap_graph_class_table().name()[type_row];
-    }
-    PERFETTO_CHECK(opt_class_name_id);
-    StringPool::Id class_name_id = *opt_class_name_id;
-    base::Optional<StringPool::Id> root_type =
-        storage->heap_graph_object_table().root_type()[row];
-    if (root_type) {
-      class_name_id = storage->InternString(base::StringView(
-          storage->GetString(class_name_id).ToStdString() + " [" +
-          storage->GetString(*root_type).ToStdString() + "]"));
-    }
-    auto it = path->nodes[parent_id].children.find(class_name_id);
+        storage.heap_graph_object_table().type_id()[row];
+    auto it = path->nodes[parent_id].children.find(type_id);
     if (it == path->nodes[parent_id].children.end()) {
       size_t path_id = path->nodes.size();
       path->nodes.emplace_back(PathFromRoot::Node{});
       std::tie(it, std::ignore) =
-          path->nodes[parent_id].children.emplace(class_name_id, path_id);
-      path->nodes.back().class_name_id = class_name_id;
+          path->nodes[parent_id].children.emplace(type_id, path_id);
+      path->nodes.back().type_id = type_id;
       path->nodes.back().depth = depth;
       path->nodes.back().parent_id = parent_id;
     }
@@ -789,10 +576,10 @@
       // This is the first time we are looking at this node, so add its
       // size to the relevant node in the resulting tree.
       output_tree_node->size +=
-          storage->heap_graph_object_table().self_size()[row];
+          storage.heap_graph_object_table().self_size()[row];
       output_tree_node->count++;
       std::set<tables::HeapGraphObjectTable::Id> children_set =
-          GetChildren(*storage, n);
+          GetChildren(storage, n);
       children.assign(children_set.cbegin(), children_set.cend());
       PERFETTO_CHECK(children.size() == children_set.size());
     }
@@ -802,14 +589,14 @@
       PERFETTO_CHECK(i < children.size());
       tables::HeapGraphObjectTable::Id child = children[i];
       uint32_t child_row =
-          *storage->heap_graph_object_table().id().IndexOf(child);
+          *storage.heap_graph_object_table().id().IndexOf(child);
       if (++i == children.size())
         stack.pop_back();
 
       int32_t child_distance =
-          storage->heap_graph_object_table().root_distance()[child_row];
+          storage.heap_graph_object_table().root_distance()[child_row];
       int32_t n_distance =
-          storage->heap_graph_object_table().root_distance()[row];
+          storage.heap_graph_object_table().root_distance()[row];
       PERFETTO_CHECK(n_distance >= 0);
       PERFETTO_CHECK(child_distance >= 0);
 
@@ -828,44 +615,22 @@
 std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
 HeapGraphTracker::BuildFlamegraph(const int64_t current_ts,
                                   const UniquePid current_upid) {
-  auto profile_type = context_->storage->InternString("graph");
-  auto java_mapping = context_->storage->InternString("JAVA");
+  auto it = roots_.find(std::make_pair(current_upid, current_ts));
+  if (it == roots_.end())
+    return nullptr;
+
+  const std::vector<tables::HeapGraphObjectTable::Id>& roots = it->second;
 
   std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
       new tables::ExperimentalFlamegraphNodesTable(
           context_->storage->mutable_string_pool(), nullptr));
 
-  auto it = roots_.find(std::make_pair(current_upid, current_ts));
-  if (it == roots_.end()) {
-    // TODO(fmayer): This should not be within the flame graph but some marker
-    // in the UI.
-    if (IsTruncated(current_upid, current_ts)) {
-      tables::ExperimentalFlamegraphNodesTable::Row alloc_row{};
-      alloc_row.ts = current_ts;
-      alloc_row.upid = current_upid;
-      alloc_row.profile_type = profile_type;
-      alloc_row.depth = 0;
-      alloc_row.name =
-          context_->storage->InternString("ERROR: INCOMPLETE GRAPH");
-      alloc_row.map_name = java_mapping;
-      alloc_row.count = 1;
-      alloc_row.cumulative_count = 1;
-      alloc_row.size = 1;
-      alloc_row.cumulative_size = 1;
-      alloc_row.parent_id = base::nullopt;
-      tbl->Insert(alloc_row);
-      return tbl;
-    }
-    // We haven't seen this graph, so we should raise an error.
-    return nullptr;
-  }
-
-  const std::set<tables::HeapGraphObjectTable::Id>& roots = it->second;
-
   PathFromRoot init_path;
   for (tables::HeapGraphObjectTable::Id root : roots) {
-    FindPathFromRoot(context_->storage.get(), root, &init_path);
+    FindPathFromRoot(*context_->storage, root, &init_path);
   }
+  auto profile_type = context_->storage->InternString("graph");
+  auto java_mapping = context_->storage->InternString("JAVA");
 
   std::vector<int32_t> node_to_cumulative_size(init_path.nodes.size());
   std::vector<int32_t> node_to_cumulative_count(init_path.nodes.size());
@@ -889,12 +654,22 @@
       parent_id = node_to_id[node.parent_id];
     const uint32_t depth = node.depth;
 
+    uint32_t type_row =
+        *context_->storage->heap_graph_class_table().id().IndexOf(node.type_id);
+    base::Optional<StringPool::Id> name =
+        context_->storage->heap_graph_class_table()
+            .deobfuscated_name()[type_row];
+    if (!name) {
+      name = context_->storage->heap_graph_class_table().name()[type_row];
+    }
+    PERFETTO_CHECK(name);
+
     tables::ExperimentalFlamegraphNodesTable::Row alloc_row{};
     alloc_row.ts = current_ts;
     alloc_row.upid = current_upid;
     alloc_row.profile_type = profile_type;
     alloc_row.depth = depth;
-    alloc_row.name = node.class_name_id;
+    alloc_row.name = *name;
     alloc_row.map_name = java_mapping;
     alloc_row.count = static_cast<int64_t>(node.count);
     alloc_row.cumulative_count =
@@ -911,29 +686,32 @@
 void HeapGraphTracker::NotifyEndOfFile() {
   if (!sequence_state_.empty()) {
     context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
-    // There might still be valuable data even though the trace is truncated.
-    while (!sequence_state_.empty()) {
-      FinalizeProfile(sequence_state_.begin()->first);
-    }
   }
 }
 
-bool HeapGraphTracker::IsTruncated(UniquePid upid, int64_t ts) {
-  // The graph was finalized but was missing packets.
-  if (truncated_graphs_.find(std::make_pair(upid, ts)) !=
-      truncated_graphs_.end()) {
-    return true;
-  }
+StringPool::Id HeapGraphTracker::MaybeDeobfuscate(
+    base::Optional<StringPool::Id> package_name,
+    StringPool::Id id) {
+  base::StringView type_name = context_->storage->GetString(id);
+  auto normalized_type = GetNormalizedType(type_name);
+  auto it = deobfuscation_mapping_.find(std::make_pair(
+      package_name, context_->storage->InternString(normalized_type.name)));
+  if (it == deobfuscation_mapping_.end())
+    return id;
 
-  // Or the graph was never finalized, so is missing packets at the end.
-  for (const auto& p : sequence_state_) {
-    const SequenceState& sequence_state = p.second;
-    if (sequence_state.current_upid == upid &&
-        sequence_state.current_ts == ts) {
-      return true;
-    }
-  }
-  return false;
+  base::StringView normalized_deobfuscated_name =
+      context_->storage->GetString(it->second);
+  std::string result =
+      DenormalizeTypeName(normalized_type, normalized_deobfuscated_name);
+  return context_->storage->InternString(base::StringView(result));
+}
+
+void HeapGraphTracker::AddDeobfuscationMapping(
+    base::Optional<StringPool::Id> package_name,
+    StringPool::Id obfuscated_name,
+    StringPool::Id deobfuscated_name) {
+  deobfuscation_mapping_.emplace(std::make_pair(package_name, obfuscated_name),
+                                 deobfuscated_name);
 }
 
 HeapGraphTracker::~HeapGraphTracker() = default;
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index 1cf31e2..da02fde 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -19,7 +19,6 @@
 
 #include <map>
 #include <set>
-#include <utility>
 #include <vector>
 
 #include "perfetto/ext/base/optional.h"
@@ -48,8 +47,8 @@
     size_t parent_id = 0;
     int64_t size = 0;
     int64_t count = 0;
-    StringId class_name_id = {};
-    std::map<StringId, size_t> children;
+    tables::HeapGraphClassTable::Id type_id = {};
+    std::map<tables::HeapGraphClassTable::Id, size_t> children;
   };
   std::vector<Node> nodes{Node{}};
   std::set<tables::HeapGraphObjectTable::Id> visited;
@@ -58,10 +57,11 @@
 void MarkRoot(TraceStorage* s,
               tables::HeapGraphObjectTable::Id id,
               StringPool::Id type);
-void FindPathFromRoot(TraceStorage* storage,
+void FindPathFromRoot(const TraceStorage& s,
                       tables::HeapGraphObjectTable::Id id,
                       PathFromRoot* path);
 
+base::Optional<std::string> PackageFromLocation(base::StringView location);
 base::Optional<base::StringView> GetStaticClassTypeName(base::StringView type);
 size_t NumberOfArrays(base::StringView type);
 NormalizedType GetNormalizedType(base::StringView type);
@@ -74,12 +74,14 @@
   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<uint64_t> field_name_ids;
-    std::vector<uint64_t> referred_objects;
+    std::vector<Reference> references;
   };
 
   struct SourceRoot {
@@ -98,16 +100,13 @@
 
   void AddRoot(uint32_t seq_id, UniquePid upid, int64_t ts, SourceRoot root);
   void AddObject(uint32_t seq_id, UniquePid upid, int64_t ts, SourceObject obj);
+  void AddInternedTypeName(uint32_t seq_id,
+                           uint64_t intern_id,
+                           StringPool::Id strid);
   void AddInternedType(uint32_t seq_id,
                        uint64_t intern_id,
                        StringPool::Id strid,
-                       base::Optional<uint64_t> location_id,
-                       uint64_t object_size,
-                       std::vector<uint64_t> field_name_ids,
-                       uint64_t superclass_id,
-                       uint64_t classloader_id,
-                       bool no_fields,
-                       StringPool::Id kind);
+                       uint64_t location_id);
   void AddInternedFieldName(uint32_t seq_id,
                             uint64_t intern_id,
                             base::StringView str);
@@ -120,6 +119,12 @@
   ~HeapGraphTracker() override;
   void NotifyEndOfFile();
 
+  void AddDeobfuscationMapping(base::Optional<StringPool::Id> package_name,
+                               StringPool::Id obfuscated_name,
+                               StringPool::Id deobfuscated_name);
+  StringPool::Id MaybeDeobfuscate(base::Optional<StringPool::Id> package_name,
+                                  StringPool::Id);
+
   const std::vector<tables::HeapGraphClassTable::Id>* RowsForType(
       base::Optional<StringPool::Id> package_name,
       StringPool::Id type_name) const {
@@ -140,9 +145,8 @@
       const int64_t current_ts,
       const UniquePid current_upid);
 
-  uint64_t GetLastObjectId(uint32_t seq_id) {
-    return GetOrCreateSequence(seq_id).last_object_id;
-  }
+  // public for testing.
+  base::Optional<std::string> PackageFromLocation(base::StringView location);
 
  private:
   struct InternedField {
@@ -152,17 +156,10 @@
   struct InternedType {
     StringPool::Id name;
     base::Optional<uint64_t> location_id;
-    uint64_t object_size;
-    std::vector<uint64_t> field_name_ids;
-    uint64_t superclass_id;
-    bool no_fields;
-    uint64_t classloader_id;
-    StringPool::Id kind;
   };
   struct SequenceState {
     UniquePid current_upid = 0;
     int64_t current_ts = 0;
-    uint64_t last_object_id = 0;
     std::vector<SourceRoot> current_roots;
     std::map<uint64_t, InternedType> interned_types;
     std::map<uint64_t, StringPool::Id> interned_location_names;
@@ -170,19 +167,7 @@
     std::map<uint64_t, tables::HeapGraphClassTable::Id> type_id_to_db_id;
     std::map<uint64_t, std::vector<tables::HeapGraphReferenceTable::Id>>
         references_for_field_name_id;
-    std::map<uint64_t, InternedField> interned_fields;
-    std::map<tables::HeapGraphClassTable::Id,
-             std::vector<tables::HeapGraphObjectTable::Id>>
-        deferred_reference_objects_for_type_;
     base::Optional<uint64_t> prev_index;
-    // For most objects, we need not store the size in the object's message
-    // itself, because all instances of the type have the same type. In this
-    // case, we defer setting self_size in the table until we process the class
-    // message in FinalizeProfile.
-    std::map<tables::HeapGraphClassTable::Id,
-             std::vector<tables::HeapGraphObjectTable::Id>>
-        deferred_size_objects_for_type_;
-    bool truncated = false;
   };
 
   SequenceState& GetOrCreateSequence(uint32_t seq_id);
@@ -192,10 +177,6 @@
   tables::HeapGraphClassTable::Id GetOrInsertType(SequenceState* sequence_state,
                                                   uint64_t type_id);
   bool SetPidAndTimestamp(SequenceState* seq, UniquePid upid, int64_t ts);
-  void PopulateSuperClasses(const SequenceState& seq);
-  InternedType* GetSuperClass(SequenceState* sequence_state,
-                              const InternedType* current_type);
-  bool IsTruncated(UniquePid upid, int64_t ts);
 
   TraceProcessorContext* const context_;
   std::map<uint32_t, SequenceState> sequence_state_;
@@ -209,9 +190,8 @@
            StringPool::Id>
       deobfuscation_mapping_;
   std::map<std::pair<UniquePid, int64_t>,
-           std::set<tables::HeapGraphObjectTable::Id>>
+           std::vector<tables::HeapGraphObjectTable::Id>>
       roots_;
-  std::set<std::pair<UniquePid, int64_t>> truncated_graphs_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
index 26b0ca5..ccac303 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
@@ -16,8 +16,6 @@
 
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 
-#include "src/trace_processor/importers/proto/profiler_util.h"
-
 #include "perfetto/base/logging.h"
 #include "test/gtest_and_gmock.h"
 
@@ -28,22 +26,17 @@
 using ::testing::UnorderedElementsAre;
 
 TEST(HeapGraphTrackerTest, PackageFromLocationApp) {
-  TraceStorage storage;
-  EXPECT_EQ(
-      PackageFromLocation(&storage,
-                          "/data/app/~~ASDFGH1234QWerT==/"
-                          "com.twitter.android-MNBVCX7890SDTst6==/test.apk"),
-      "com.twitter.android");
-  EXPECT_EQ(PackageFromLocation(
-                &storage,
+  TraceProcessorContext context;
+  context.storage.reset(new TraceStorage);
+  HeapGraphTracker tracker(&context);
+  EXPECT_EQ(tracker.PackageFromLocation(
+                "/data/app/~~ASDFGH1234QWerT==/"
+                "com.twitter.android-MNBVCX7890SDTst6==/test.apk"),
+            "com.twitter.android");
+  EXPECT_EQ(tracker.PackageFromLocation(
                 "/data/app/com.google.android.webview-6XfQhnaSkFwGK0sYL9is0G==/"
                 "base.apk"),
             "com.google.android.webview");
-  EXPECT_EQ(PackageFromLocation(&storage,
-                                "/data/app/"
-                                "com.google.android.apps.wellbeing-"
-                                "qfQCaB4uJ7P0OPpZQqOu0Q==/oat/arm64/base.odex"),
-            "com.google.android.apps.wellbeing");
 }
 
 TEST(HeapGraphTrackerTest, BuildFlamegraph) {
@@ -63,67 +56,38 @@
   HeapGraphTracker tracker(&context);
 
   constexpr uint64_t kField = 1;
-  constexpr uint64_t kLocation = 0;
 
   constexpr uint64_t kX = 1;
   constexpr uint64_t kY = 2;
   constexpr uint64_t kA = 3;
   constexpr uint64_t kB = 4;
-  constexpr uint64_t kWeakRef = 5;
 
   base::StringView field = base::StringView("foo");
   StringPool::Id x = context.storage->InternString("X");
   StringPool::Id y = context.storage->InternString("Y");
   StringPool::Id a = context.storage->InternString("A");
   StringPool::Id b = context.storage->InternString("B");
-  StringPool::Id weak_ref = context.storage->InternString("WeakReference");
 
-  StringPool::Id normal_kind = context.storage->InternString("KIND_NORMAL");
-  StringPool::Id weak_ref_kind =
-      context.storage->InternString("KIND_WEAK_REFERENCE");
   tracker.AddInternedFieldName(kSeqId, kField, field);
 
-  tracker.AddInternedLocationName(kSeqId, kLocation,
-                                  context.storage->InternString("location"));
-  tracker.AddInternedType(kSeqId, kX, x, kLocation, /*object_size=*/0,
-                          /*field_name_ids=*/{}, /*superclass_id=*/0,
-                          /*classloader_id=*/0, /*no_fields=*/false,
-                          /*kind=*/normal_kind);
-  tracker.AddInternedType(kSeqId, kY, y, kLocation, /*object_size=*/0,
-                          /*field_name_ids=*/{}, /*superclass_id=*/0,
-                          /*classloader_id=*/0, /*no_fields=*/false,
-                          /*kind=*/normal_kind);
-  tracker.AddInternedType(kSeqId, kA, a, kLocation, /*object_size=*/0,
-                          /*field_name_ids=*/{}, /*superclass_id=*/0,
-                          /*classloader_id=*/0, /*no_fields=*/false,
-                          /*kind=*/normal_kind);
-  tracker.AddInternedType(kSeqId, kB, b, kLocation, /*object_size=*/0,
-                          /*field_name_ids=*/{}, /*superclass_id=*/0,
-                          /*classloader_id=*/0, /*no_fields=*/false,
-                          /*kind=*/normal_kind);
-  tracker.AddInternedType(kSeqId, kWeakRef, weak_ref, kLocation,
-                          /*object_size=*/0,
-                          /*field_name_ids=*/{}, /*superclass_id=*/0,
-                          /*classloader_id=*/0, /*no_fields=*/false,
-                          /*kind=*/weak_ref_kind);
-  {
-    HeapGraphTracker::SourceObject obj;
-    obj.object_id = 999;
-    obj.self_size = 999;
-    obj.type_id = kWeakRef;
-    obj.field_name_ids = {kField};
-    obj.referred_objects = {5};
-
-    tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
-  }
+  tracker.AddInternedTypeName(kSeqId, kX, x);
+  tracker.AddInternedTypeName(kSeqId, kY, y);
+  tracker.AddInternedTypeName(kSeqId, kA, a);
+  tracker.AddInternedTypeName(kSeqId, kB, b);
 
   {
     HeapGraphTracker::SourceObject obj;
     obj.object_id = 1;
     obj.self_size = 1;
     obj.type_id = kX;
-    obj.field_name_ids = {kField, kField};
-    obj.referred_objects = {2, 3};
+    HeapGraphTracker::SourceObject::Reference ref;
+    ref.field_name_id = kField;
+    ref.owned_object_id = 2;
+    obj.references.emplace_back(std::move(ref));
+
+    ref.field_name_id = kField;
+    ref.owned_object_id = 3;
+    obj.references.emplace_back(std::move(ref));
 
     tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
   }
@@ -141,8 +105,14 @@
     obj.object_id = 3;
     obj.self_size = 3;
     obj.type_id = kY;
-    obj.field_name_ids = {kField, kField};
-    obj.referred_objects = {4, 5};
+    HeapGraphTracker::SourceObject::Reference ref;
+    ref.field_name_id = kField;
+    ref.owned_object_id = 4;
+    obj.references.emplace_back(std::move(ref));
+
+    ref.field_name_id = kField;
+    ref.owned_object_id = 5;
+    obj.references.emplace_back(std::move(ref));
 
     tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
   }
@@ -166,7 +136,6 @@
   HeapGraphTracker::SourceRoot root;
   root.root_type = context.storage->InternString("ROOT");
   root.object_ids.emplace_back(1);
-  root.object_ids.emplace_back(999);
   tracker.AddRoot(kSeqId, kPid, kTimestamp, root);
 
   tracker.FinalizeProfile(kSeqId);
@@ -175,16 +144,16 @@
   ASSERT_NE(flame, nullptr);
 
   auto cumulative_sizes = flame->cumulative_size().ToVectorForTesting();
-  EXPECT_THAT(cumulative_sizes, UnorderedElementsAre(15, 4, 14, 5, 999));
+  EXPECT_THAT(cumulative_sizes, UnorderedElementsAre(15, 4, 14, 5));
 
   auto cumulative_counts = flame->cumulative_count().ToVectorForTesting();
-  EXPECT_THAT(cumulative_counts, UnorderedElementsAre(5, 4, 1, 1, 1));
+  EXPECT_THAT(cumulative_counts, UnorderedElementsAre(5, 4, 1, 1));
 
   auto sizes = flame->size().ToVectorForTesting();
-  EXPECT_THAT(sizes, UnorderedElementsAre(1, 5, 4, 5, 999));
+  EXPECT_THAT(sizes, UnorderedElementsAre(1, 5, 4, 5));
 
   auto counts = flame->count().ToVectorForTesting();
-  EXPECT_THAT(counts, UnorderedElementsAre(1, 2, 1, 1, 1));
+  EXPECT_THAT(counts, UnorderedElementsAre(1, 2, 1, 1));
 }
 
 static const char kArray[] = "X[]";
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker.cc b/src/trace_processor/importers/proto/heap_profile_tracker.cc
index 968da7d..14d99be 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_profile_tracker.cc
@@ -59,10 +59,7 @@
 
   if (!symbol_set_id) {
     StringId frame_name = frames_tbl.name()[frame_idx];
-    base::Optional<StringId> deobfuscated_name =
-        frames_tbl.deobfuscated_name()[frame_idx];
-    return {{deobfuscated_name ? *deobfuscated_name : frame_name, mapping_name,
-             base::nullopt}};
+    return {{frame_name, mapping_name, base::nullopt}};
   }
 
   std::vector<MergedCallsite> result;
@@ -77,7 +74,6 @@
     result.emplace_back(
         MergedCallsite{symbols_tbl.name()[i], mapping_name, base::nullopt});
   }
-  std::reverse(result.begin(), result.end());
   return result;
 }
 }  // namespace
@@ -110,14 +106,11 @@
     auto opt_parent_id = callsites_tbl.parent_id()[i];
     if (opt_parent_id) {
       parent_idx = callsites_tbl.id().IndexOf(*opt_parent_id);
-      // Make sure what we index into has been populated already.
-      PERFETTO_CHECK(*parent_idx < i);
       parent_idx = callsite_to_merged_callsite[*parent_idx];
+      PERFETTO_CHECK(*parent_idx < i);
     }
 
     auto callsites = GetMergedCallsites(storage, i);
-    // Loop below needs to run at least once for parent_idx to get updated.
-    PERFETTO_CHECK(!callsites.empty());
     for (MergedCallsite& merged_callsite : callsites) {
       merged_callsite.parent_idx = parent_idx;
       auto it = merged_callsites_to_table_idx.find(merged_callsite);
@@ -144,7 +137,6 @@
       }
       parent_idx = it->second;
     }
-
     PERFETTO_CHECK(parent_idx);
     callsite_to_merged_callsite[i] = *parent_idx;
   }
@@ -177,15 +169,9 @@
     uint32_t merged_idx =
         callsite_to_merged_callsite[*callsites_tbl.id().IndexOf(
             CallsiteId(static_cast<uint32_t>(callsite_id)))];
-    // On old heapprofd producers, the count field is incorrectly set and we
-    // zero it in proto_trace_parser.cc.
-    // As such, we cannot depend on count == 0 to imply size == 0, so we check
-    // for both of them separately.
-    if (size > 0) {
+    if (count > 0) {
       tbl->mutable_alloc_size()->Set(merged_idx,
                                      tbl->alloc_size()[merged_idx] + size);
-    }
-    if (count > 0) {
       tbl->mutable_alloc_count()->Set(merged_idx,
                                       tbl->alloc_count()[merged_idx] + count);
     }
@@ -265,12 +251,12 @@
 
 void HeapProfileTracker::AddAllocation(
     uint32_t seq_id,
-    SequenceStackProfileTracker* sequence_stack_profile_tracker,
+    StackProfileTracker* stack_profile_tracker,
     const SourceAllocation& alloc,
-    const SequenceStackProfileTracker::InternLookup* intern_lookup) {
+    const StackProfileTracker::InternLookup* intern_lookup) {
   SequenceState& sequence_state = sequence_state_[seq_id];
 
-  auto opt_callstack_id = sequence_stack_profile_tracker->FindOrInsertCallstack(
+  auto opt_callstack_id = stack_profile_tracker->FindOrInsertCallstack(
       alloc.callstack_id, intern_lookup);
   if (!opt_callstack_id)
     return;
@@ -281,18 +267,12 @@
       static_cast<uint32_t>(alloc.pid));
 
   tables::HeapProfileAllocationTable::Row alloc_row{
-      alloc.timestamp,
-      upid,
-      alloc.heap_name,
-      callstack_id,
+      alloc.timestamp, upid, callstack_id,
       static_cast<int64_t>(alloc.alloc_count),
       static_cast<int64_t>(alloc.self_allocated)};
 
   tables::HeapProfileAllocationTable::Row free_row{
-      alloc.timestamp,
-      upid,
-      alloc.heap_name,
-      callstack_id,
+      alloc.timestamp, upid, callstack_id,
       -static_cast<int64_t>(alloc.free_count),
       -static_cast<int64_t>(alloc.self_freed)};
 
@@ -315,8 +295,7 @@
   tables::HeapProfileAllocationTable::Row& prev_free = prev_free_it->second;
 
   std::set<CallsiteId>& callstacks_for_source_callstack_id =
-      sequence_state.seen_callstacks[SourceAllocationIndex{
-          upid, alloc.callstack_id, alloc.heap_name}];
+      sequence_state.seen_callstacks[std::make_pair(upid, alloc.callstack_id)];
   bool new_callstack;
   std::tie(std::ignore, new_callstack) =
       callstacks_for_source_callstack_id.emplace(callstack_id);
@@ -359,12 +338,11 @@
     return;
   }
 
-  // Dump at max profiles do not have .count set.
-  if (alloc_delta.count || alloc_delta.size) {
+  if (alloc_delta.count) {
     context_->storage->mutable_heap_profile_allocation_table()->Insert(
         alloc_delta);
   }
-  if (free_delta.count || free_delta.size) {
+  if (free_delta.count) {
     context_->storage->mutable_heap_profile_allocation_table()->Insert(
         free_delta);
   }
@@ -381,20 +359,20 @@
 
 void HeapProfileTracker::CommitAllocations(
     uint32_t seq_id,
-    SequenceStackProfileTracker* sequence_stack_profile_tracker,
-    const SequenceStackProfileTracker::InternLookup* intern_lookup) {
+    StackProfileTracker* stack_profile_tracker,
+    const StackProfileTracker::InternLookup* intern_lookup) {
   SequenceState& sequence_state = sequence_state_[seq_id];
   for (const auto& p : sequence_state.pending_allocs)
-    AddAllocation(seq_id, sequence_stack_profile_tracker, p, intern_lookup);
+    AddAllocation(seq_id, stack_profile_tracker, p, intern_lookup);
   sequence_state.pending_allocs.clear();
 }
 
 void HeapProfileTracker::FinalizeProfile(
     uint32_t seq_id,
-    SequenceStackProfileTracker* sequence_stack_profile_tracker,
-    const SequenceStackProfileTracker::InternLookup* intern_lookup) {
-  CommitAllocations(seq_id, sequence_stack_profile_tracker, intern_lookup);
-  sequence_stack_profile_tracker->ClearIndices();
+    StackProfileTracker* stack_profile_tracker,
+    const StackProfileTracker::InternLookup* intern_lookup) {
+  CommitAllocations(seq_id, stack_profile_tracker, intern_lookup);
+  stack_profile_tracker->ClearIndices();
 }
 
 void HeapProfileTracker::NotifyEndOfFile() {
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker.h b/src/trace_processor/importers/proto/heap_profile_tracker.h
index 066c238..91cfe72 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker.h
+++ b/src/trace_processor/importers/proto/heap_profile_tracker.h
@@ -39,8 +39,7 @@
     // This is int64_t, because we get this from the TraceSorter which also
     // converts this for us.
     int64_t timestamp = 0;
-    StringPool::Id heap_name;
-    SequenceStackProfileTracker::SourceCallstackId callstack_id = 0;
+    StackProfileTracker::SourceCallstackId callstack_id = 0;
     uint64_t self_allocated = 0;
     uint64_t self_freed = 0;
     uint64_t alloc_count = 0;
@@ -56,17 +55,15 @@
   // 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(
-      uint32_t seq_id,
-      SequenceStackProfileTracker* sequence_stack_profile_tracker,
-      const SequenceStackProfileTracker::InternLookup* lookup);
+  void FinalizeProfile(uint32_t seq_id,
+                       StackProfileTracker* stack_profile_tracker,
+                       const StackProfileTracker::InternLookup* lookup);
 
   // Only commit the allocations that had been stored using StoreAllocations.
   // This is only needed in tests, use FinalizeProfile instead.
-  void CommitAllocations(
-      uint32_t seq_id,
-      SequenceStackProfileTracker* sequence_stack_profile_tracker,
-      const SequenceStackProfileTracker::InternLookup* lookup);
+  void CommitAllocations(uint32_t seq_id,
+                         StackProfileTracker* stack_profile_tracker,
+                         const StackProfileTracker::InternLookup* lookup);
 
   void NotifyEndOfFile();
 
@@ -75,18 +72,10 @@
  private:
   void AddAllocation(
       uint32_t seq_id,
-      SequenceStackProfileTracker* sequence_stack_profile_tracker,
+      StackProfileTracker* stack_profile_tracker,
       const SourceAllocation&,
-      const SequenceStackProfileTracker::InternLookup* intern_lookup = nullptr);
-  struct SourceAllocationIndex {
-    UniquePid upid;
-    SequenceStackProfileTracker::SourceCallstackId src_callstack_id;
-    StringPool::Id heap_name;
-    bool operator<(const SourceAllocationIndex& o) const {
-      return std::tie(upid, src_callstack_id, heap_name) <
-             std::tie(o.upid, o.src_callstack_id, o.heap_name);
-    }
-  };
+      const StackProfileTracker::InternLookup* intern_lookup = nullptr);
+
   struct SequenceState {
     std::vector<SourceAllocation> pending_allocs;
 
@@ -107,11 +96,13 @@
     // one, and then handle it as normal. If it is the first time we see a
     // SourceCallstackId for a CallsiteId, we put the previous value into
     // the correction maps below.
-    std::map<SourceAllocationIndex, std::set<CallsiteId>> seen_callstacks;
-    std::map<SequenceStackProfileTracker::SourceCallstackId,
+    std::map<std::pair<UniquePid, StackProfileTracker::SourceCallstackId>,
+             std::set<CallsiteId>>
+        seen_callstacks;
+    std::map<StackProfileTracker::SourceCallstackId,
              tables::HeapProfileAllocationTable::Row>
         alloc_correction;
-    std::map<SequenceStackProfileTracker::SourceCallstackId,
+    std::map<StackProfileTracker::SourceCallstackId,
              tables::HeapProfileAllocationTable::Row>
         free_correction;
 
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc b/src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc
index 0ac2608..1a4e493 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc
@@ -56,9 +56,7 @@
  public:
   HeapProfileTrackerDupTest() {
     context.storage.reset(new TraceStorage());
-    context.global_stack_profile_tracker.reset(new GlobalStackProfileTracker());
-    sequence_stack_profile_tracker.reset(
-        new SequenceStackProfileTracker(&context));
+    stack_profile_tracker.reset(new StackProfileTracker(&context));
     context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
 
     mapping_name = context.storage->InternString("[mapping]");
@@ -69,12 +67,11 @@
 
  protected:
   void InsertMapping(const Packet& packet) {
-    sequence_stack_profile_tracker->AddString(packet.mapping_name_id,
-                                              "[mapping]");
+    stack_profile_tracker->AddString(packet.mapping_name_id, "[mapping]");
 
-    sequence_stack_profile_tracker->AddString(packet.build_id, kBuildIDName);
+    stack_profile_tracker->AddString(packet.build_id, kBuildIDName);
 
-    SequenceStackProfileTracker::SourceMapping first_frame;
+    StackProfileTracker::SourceMapping first_frame;
     first_frame.build_id = packet.build_id;
     first_frame.exact_offset = kMappingExactOffset;
     first_frame.start_offset = kMappingStartOffset;
@@ -83,27 +80,27 @@
     first_frame.load_bias = kMappingLoadBias;
     first_frame.name_ids = {packet.mapping_name_id};
 
-    sequence_stack_profile_tracker->AddMapping(packet.mapping_id, first_frame);
+    stack_profile_tracker->AddMapping(packet.mapping_id, first_frame);
   }
 
   void InsertFrame(const Packet& packet) {
     InsertMapping(packet);
-    sequence_stack_profile_tracker->AddString(packet.frame_name_id, "[frame]");
+    stack_profile_tracker->AddString(packet.frame_name_id, "[frame]");
 
-    SequenceStackProfileTracker::SourceFrame first_frame;
+    StackProfileTracker::SourceFrame first_frame;
     first_frame.name_id = packet.frame_name_id;
     first_frame.mapping_id = packet.mapping_id;
     first_frame.rel_pc = kFrameRelPc;
 
-    sequence_stack_profile_tracker->AddFrame(packet.frame_id, first_frame);
+    stack_profile_tracker->AddFrame(packet.frame_id, first_frame);
   }
 
   void InsertCallsite(const Packet& packet) {
     InsertFrame(packet);
 
-    SequenceStackProfileTracker::SourceCallstack first_callsite = {
-        packet.frame_id, packet.frame_id};
-    sequence_stack_profile_tracker->AddCallstack(kCallstackId, first_callsite);
+    StackProfileTracker::SourceCallstack first_callsite = {packet.frame_id,
+                                                           packet.frame_id};
+    stack_profile_tracker->AddCallstack(kCallstackId, first_callsite);
   }
 
   StringId mapping_name;
@@ -111,7 +108,7 @@
   StringId build;
   StringId frame_name;
   TraceProcessorContext context;
-  std::unique_ptr<SequenceStackProfileTracker> sequence_stack_profile_tracker;
+  std::unique_ptr<StackProfileTracker> stack_profile_tracker;
 };
 
 // Insert the same mapping from two different packets, with different strings
@@ -119,10 +116,10 @@
 TEST_F(HeapProfileTrackerDupTest, Mapping) {
   InsertMapping(kFirstPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertMapping(kSecondPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   EXPECT_THAT(context.storage->stack_profile_mapping_table().build_id()[0],
               context.storage->InternString({kBuildIDHexName}));
@@ -145,10 +142,10 @@
 TEST_F(HeapProfileTrackerDupTest, Frame) {
   InsertFrame(kFirstPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertFrame(kSecondPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   const auto& frames = context.storage->stack_profile_frame_table();
   EXPECT_THAT(frames.name()[0], frame_name);
@@ -161,10 +158,10 @@
 TEST_F(HeapProfileTrackerDupTest, Callstack) {
   InsertCallsite(kFirstPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertCallsite(kSecondPacket);
   context.heap_profile_tracker->FinalizeProfile(
-      kDefaultSequence, sequence_stack_profile_tracker.get(), nullptr);
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   const auto& callsite_table = context.storage->stack_profile_callsite_table();
   const auto& depth = callsite_table.depth();
@@ -198,12 +195,10 @@
 TEST(HeapProfileTrackerTest, SourceMappingPath) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
-  context.global_stack_profile_tracker.reset(new GlobalStackProfileTracker());
   context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
 
   HeapProfileTracker* hpt = context.heap_profile_tracker.get();
-  std::unique_ptr<SequenceStackProfileTracker> spt(
-      new SequenceStackProfileTracker(&context));
+  std::unique_ptr<StackProfileTracker> spt(new StackProfileTracker(&context));
 
   constexpr auto kBuildId = 1u;
   constexpr auto kMappingNameId1 = 2u;
@@ -213,7 +208,7 @@
   spt->AddString(kMappingNameId1, "foo");
   spt->AddString(kMappingNameId2, "bar");
 
-  SequenceStackProfileTracker::SourceMapping mapping;
+  StackProfileTracker::SourceMapping mapping;
   mapping.build_id = kBuildId;
   mapping.exact_offset = 1;
   mapping.start_offset = 1;
@@ -233,12 +228,10 @@
 TEST(HeapProfileTrackerTest, Functional) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
-  context.global_stack_profile_tracker.reset(new GlobalStackProfileTracker());
   context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
 
   HeapProfileTracker* hpt = context.heap_profile_tracker.get();
-  std::unique_ptr<SequenceStackProfileTracker> spt(
-      new SequenceStackProfileTracker(&context));
+  std::unique_ptr<StackProfileTracker> spt(new StackProfileTracker(&context));
 
   uint32_t next_string_intern_id = 1;
 
@@ -252,8 +245,8 @@
   for (size_t i = 0; i < base::ArraySize(mapping_names); ++i)
     mapping_name_ids[i] = next_string_intern_id++;
 
-  SequenceStackProfileTracker::SourceMapping
-      mappings[base::ArraySize(mapping_names)] = {};
+  StackProfileTracker::SourceMapping mappings[base::ArraySize(mapping_names)] =
+      {};
   mappings[0].build_id = build_id_ids[0];
   mappings[0].exact_offset = 1;
   mappings[0].start_offset = 1;
@@ -283,8 +276,7 @@
   for (size_t i = 0; i < base::ArraySize(function_names); ++i)
     function_name_ids[i] = next_string_intern_id++;
 
-  SequenceStackProfileTracker::SourceFrame
-      frames[base::ArraySize(function_names)];
+  StackProfileTracker::SourceFrame frames[base::ArraySize(function_names)];
   frames[0].name_id = function_name_ids[0];
   frames[0].mapping_id = 0;
   frames[0].rel_pc = 123;
@@ -301,7 +293,7 @@
   frames[3].mapping_id = 2;
   frames[3].rel_pc = 123;
 
-  SequenceStackProfileTracker::SourceCallstack callstacks[3];
+  StackProfileTracker::SourceCallstack callstacks[3];
   callstacks[0] = {2, 1, 0};
   callstacks[1] = {2, 1, 0, 1, 0};
   callstacks[2] = {0, 2, 0, 1, 2};
@@ -332,8 +324,7 @@
 
   for (size_t i = 0; i < base::ArraySize(callstacks); ++i) {
     base::Optional<CallsiteId> parent;
-    const SequenceStackProfileTracker::SourceCallstack& callstack =
-        callstacks[i];
+    const StackProfileTracker::SourceCallstack& callstack = callstacks[i];
     for (size_t depth = 0; depth < callstack.size(); ++depth) {
       auto frame_id = spt->GetDatabaseFrameIdForTesting(callstack[depth]);
       base::Optional<CallsiteId> self = FindCallstack(
diff --git a/src/trace_processor/importers/proto/memory_tracker_snapshot_module.cc b/src/trace_processor/importers/proto/memory_tracker_snapshot_module.cc
deleted file mode 100644
index cd4dde2..0000000
--- a/src/trace_processor/importers/proto/memory_tracker_snapshot_module.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using perfetto::protos::pbzero::TracePacket;
-
-MemoryTrackerSnapshotModule::MemoryTrackerSnapshotModule(
-    TraceProcessorContext* context)
-    : parser_(context) {
-  RegisterForField(TracePacket::kMemoryTrackerSnapshotFieldNumber, context);
-}
-
-MemoryTrackerSnapshotModule::~MemoryTrackerSnapshotModule() = default;
-
-void MemoryTrackerSnapshotModule::ParsePacket(
-    const TracePacket::Decoder& decoder,
-    const TimestampedTracePiece& ttp,
-    uint32_t field_id) {
-  switch (field_id) {
-    case TracePacket::kMemoryTrackerSnapshotFieldNumber:
-      parser_.ParseMemoryTrackerSnapshot(ttp.timestamp,
-                                         decoder.memory_tracker_snapshot());
-      return;
-  }
-}
-
-void MemoryTrackerSnapshotModule::NotifyEndOfFile() {
-  parser_.NotifyEndOfFile();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/memory_tracker_snapshot_module.h b/src/trace_processor/importers/proto/memory_tracker_snapshot_module.h
deleted file mode 100644
index 730b7e3..0000000
--- a/src/trace_processor/importers/proto/memory_tracker_snapshot_module.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_MODULE_H_
-
-#include "src/trace_processor/importers/proto/memory_tracker_snapshot_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 MemoryTrackerSnapshotModule : public ProtoImporterModule {
- public:
-  explicit MemoryTrackerSnapshotModule(TraceProcessorContext* context);
-
-  ~MemoryTrackerSnapshotModule() override;
-
-  void ParsePacket(const protos::pbzero::TracePacket::Decoder&,
-                   const TimestampedTracePiece&,
-                   uint32_t field_id) override;
-
-  void NotifyEndOfFile() override;
-
- private:
-  MemoryTrackerSnapshotParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_MODULE_H_
diff --git a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc b/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc
deleted file mode 100644
index 3c1683f..0000000
--- a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/memory_tracker_snapshot_parser.h"
-
-#include "perfetto/ext/base/string_view.h"
-#include "protos/perfetto/trace/memory_graph.pbzero.h"
-#include "src/trace_processor/containers/string_pool.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/tables/memory_tables.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-MemoryTrackerSnapshotParser::MemoryTrackerSnapshotParser(
-    TraceProcessorContext* context)
-    : context_(context),
-      level_of_detail_ids_{{context_->storage->InternString("background"),
-                            context_->storage->InternString("light"),
-                            context_->storage->InternString("detailed")}},
-      unit_ids_{{context_->storage->InternString("objects"),
-                 context_->storage->InternString("bytes")}},
-      aggregate_raw_nodes_(),
-      last_snapshot_timestamp_(-1),
-      last_snapshot_level_of_detail_(LevelOfDetail::kFirst) {}
-
-void MemoryTrackerSnapshotParser::ParseMemoryTrackerSnapshot(int64_t ts,
-                                                             ConstBytes blob) {
-  PERFETTO_DCHECK(last_snapshot_timestamp_ <= ts);
-  if (!aggregate_raw_nodes_.empty() && ts != last_snapshot_timestamp_) {
-    GenerateGraphFromRawNodesAndEmitRows();
-  }
-  ReadProtoSnapshot(blob, aggregate_raw_nodes_, last_snapshot_level_of_detail_);
-  last_snapshot_timestamp_ = ts;
-}
-
-void MemoryTrackerSnapshotParser::NotifyEndOfFile() {
-  if (!aggregate_raw_nodes_.empty()) {
-    GenerateGraphFromRawNodesAndEmitRows();
-  }
-}
-
-void MemoryTrackerSnapshotParser::ReadProtoSnapshot(
-    ConstBytes blob,
-    RawMemoryNodeMap& raw_nodes,
-    LevelOfDetail& level_of_detail) {
-  protos::pbzero::MemoryTrackerSnapshot::Decoder snapshot(blob.data, blob.size);
-  level_of_detail = LevelOfDetail::kDetailed;
-
-  switch (snapshot.level_of_detail()) {
-    case 0:  // FULL
-      level_of_detail = LevelOfDetail::kDetailed;
-      break;
-    case 1:  // LIGHT
-      level_of_detail = LevelOfDetail::kLight;
-      break;
-    case 2:  // BACKGROUND
-      level_of_detail = LevelOfDetail::kBackground;
-      break;
-  }
-
-  for (auto process_it = snapshot.process_memory_dumps(); process_it;
-       ++process_it) {
-    protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::Decoder
-        process_memory_dump(*process_it);
-
-    base::PlatformProcessId pid =
-        static_cast<base::PlatformProcessId>(process_memory_dump.pid());
-
-    RawProcessMemoryNode::MemoryNodesMap nodes_map;
-    RawProcessMemoryNode::AllocatorNodeEdgesMap edges_map;
-
-    for (auto node_it = process_memory_dump.allocator_dumps(); node_it;
-         ++node_it) {
-      protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode::
-          Decoder node(*node_it);
-
-      MemoryAllocatorNodeId node_id(node.id());
-      const std::string absolute_name = node.absolute_name().ToStdString();
-      int flags;
-      if (node.weak()) {
-        flags = RawMemoryGraphNode::kWeak;
-      } else {
-        flags = RawMemoryGraphNode::kDefault;
-      }
-
-      std::vector<RawMemoryGraphNode::MemoryNodeEntry> entries;
-
-      if (node.has_size_bytes()) {
-        entries.emplace_back("size", RawMemoryGraphNode::kUnitsBytes,
-                             node.size_bytes());
-      }
-
-      for (auto entry_it = node.entries(); entry_it; ++entry_it) {
-        protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::MemoryNode::
-            MemoryNodeEntry::Decoder entry(*entry_it);
-
-        std::string unit;
-
-        switch (entry.units()) {
-          case 1:  // BYTES
-            unit = RawMemoryGraphNode::kUnitsBytes;
-            break;
-          case 2:  // COUNT
-            unit = RawMemoryGraphNode::kUnitsObjects;
-            break;
-        }
-        if (entry.has_value_uint64()) {
-          entries.emplace_back(entry.name().ToStdString(), unit,
-                               entry.value_uint64());
-        } else if (entry.has_value_string()) {
-          entries.emplace_back(entry.name().ToStdString(), unit,
-                               entry.value_string().ToStdString());
-        } else {
-          context_->storage->IncrementStats(
-              stats::memory_snapshot_parser_failure);
-        }
-      }
-      std::unique_ptr<RawMemoryGraphNode> raw_graph_node(new RawMemoryGraphNode(
-          absolute_name, level_of_detail, node_id, std::move(entries)));
-      raw_graph_node->set_flags(flags);
-      nodes_map.insert(
-          std::make_pair(absolute_name, std::move(raw_graph_node)));
-    }
-
-    for (auto edge_it = process_memory_dump.memory_edges(); edge_it;
-         ++edge_it) {
-      protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::MemoryEdge::
-          Decoder edge(*edge_it);
-
-      std::unique_ptr<MemoryGraphEdge> graph_edge(new MemoryGraphEdge(
-          MemoryAllocatorNodeId(edge.source_id()),
-          MemoryAllocatorNodeId(edge.target_id()),
-          static_cast<int>(edge.importance()), edge.overridable()));
-
-      edges_map.insert(std::make_pair(MemoryAllocatorNodeId(edge.source_id()),
-                                      std::move(graph_edge)));
-    }
-    std::unique_ptr<RawProcessMemoryNode> raw_node(new RawProcessMemoryNode(
-        level_of_detail, std::move(edges_map), std::move(nodes_map)));
-    raw_nodes.insert(std::make_pair(pid, std::move(raw_node)));
-  }
-}
-
-std::unique_ptr<GlobalNodeGraph> MemoryTrackerSnapshotParser::GenerateGraph(
-    RawMemoryNodeMap& raw_nodes) {
-  auto graph = GraphProcessor::CreateMemoryGraph(raw_nodes);
-  GraphProcessor::CalculateSizesForGraph(graph.get());
-  return graph;
-}
-
-void MemoryTrackerSnapshotParser::EmitRows(int64_t ts,
-                                           GlobalNodeGraph& graph,
-                                           LevelOfDetail level_of_detail) {
-  IdNodeMap id_node_map;
-
-  // For now, we use the existing global instant event track for chrome events,
-  // since memory dumps are global.
-  TrackId track_id =
-      context_->track_tracker->GetOrCreateLegacyChromeGlobalInstantTrack();
-
-  tables::MemorySnapshotTable::Row snapshot_row(
-      ts, track_id, level_of_detail_ids_[static_cast<size_t>(level_of_detail)]);
-  tables::MemorySnapshotTable::Id snapshot_row_id =
-      context_->storage->mutable_memory_snapshot_table()
-          ->Insert(snapshot_row)
-          .id;
-
-  for (auto const& it_process : graph.process_node_graphs()) {
-    tables::ProcessMemorySnapshotTable::Row process_row;
-    process_row.upid = context_->process_tracker->GetOrCreateProcess(
-        static_cast<uint32_t>(it_process.first));
-    process_row.snapshot_id = snapshot_row_id;
-    tables::ProcessMemorySnapshotTable::Id proc_snapshot_row_id =
-        context_->storage->mutable_process_memory_snapshot_table()
-            ->Insert(process_row)
-            .id;
-    EmitMemorySnapshotNodeRows(*(it_process.second->root()),
-                               proc_snapshot_row_id, id_node_map);
-  }
-
-  // For each snapshot nodes from shared_memory_graph will be associated
-  // with a fabricated process_memory_snapshot entry whose pid == 0.
-  // TODO(mobica-google-contributors@mobica.com): Track the shared memory graph
-  // in a separate table.
-  tables::ProcessMemorySnapshotTable::Row fake_process_row;
-  fake_process_row.upid = context_->process_tracker->GetOrCreateProcess(0u);
-  fake_process_row.snapshot_id = snapshot_row_id;
-  tables::ProcessMemorySnapshotTable::Id fake_proc_snapshot_row_id =
-      context_->storage->mutable_process_memory_snapshot_table()
-          ->Insert(fake_process_row)
-          .id;
-  EmitMemorySnapshotNodeRows(*(graph.shared_memory_graph()->root()),
-                             fake_proc_snapshot_row_id, id_node_map);
-
-  for (const auto& edge : graph.edges()) {
-    tables::MemorySnapshotEdgeTable::Row edge_row;
-    auto source_it = id_node_map.find(edge.source()->id());
-    if (source_it == id_node_map.end())
-      continue;
-    edge_row.source_node_id =
-        static_cast<tables::MemorySnapshotNodeTable::Id>(source_it->second);
-    auto target_it = id_node_map.find(edge.target()->id());
-    if (target_it == id_node_map.end())
-      continue;
-    edge_row.target_node_id =
-        static_cast<tables::MemorySnapshotNodeTable::Id>(target_it->second);
-    edge_row.importance = static_cast<uint32_t>(edge.priority());
-    context_->storage->mutable_memory_snapshot_edge_table()->Insert(edge_row);
-  }
-}
-
-void MemoryTrackerSnapshotParser::EmitMemorySnapshotNodeRows(
-    GlobalNodeGraph::Node& root_node_graph,
-    ProcessMemorySnapshotId& proc_snapshot_row_id,
-    IdNodeMap& id_node_map) {
-  EmitMemorySnapshotNodeRowsRecursively(root_node_graph, std::string(),
-                                        base::nullopt, proc_snapshot_row_id,
-                                        id_node_map);
-}
-
-void MemoryTrackerSnapshotParser::EmitMemorySnapshotNodeRowsRecursively(
-    GlobalNodeGraph::Node& node,
-    const std::string& path,
-    base::Optional<tables::MemorySnapshotNodeTable::Id> parent_node_row_id,
-    ProcessMemorySnapshotId& proc_snapshot_row_id,
-    IdNodeMap& id_node_map) {
-  base::Optional<tables::MemorySnapshotNodeTable::Id> node_id;
-  // Skip emitting the root node into the tables - it is not a real node.
-  if (!path.empty()) {
-    node_id = EmitNode(node, path, parent_node_row_id, proc_snapshot_row_id,
-                       id_node_map);
-  }
-
-  for (const auto& name_and_child : *node.children()) {
-    std::string child_path = path;
-    if (!child_path.empty())
-      child_path += "/";
-    child_path += name_and_child.first;
-
-    EmitMemorySnapshotNodeRowsRecursively(*(name_and_child.second), child_path,
-                                          /*parent_node_row_id=*/node_id,
-                                          proc_snapshot_row_id, id_node_map);
-  }
-}
-
-base::Optional<tables::MemorySnapshotNodeTable::Id>
-MemoryTrackerSnapshotParser::EmitNode(
-    const GlobalNodeGraph::Node& node,
-    const std::string& path,
-    base::Optional<tables::MemorySnapshotNodeTable::Id> parent_node_row_id,
-    ProcessMemorySnapshotId& proc_snapshot_row_id,
-    IdNodeMap& id_node_map) {
-  tables::MemorySnapshotNodeTable::Row node_row;
-  node_row.process_snapshot_id = proc_snapshot_row_id;
-  node_row.parent_node_id = parent_node_row_id;
-  node_row.path = context_->storage->InternString(base::StringView(path));
-
-  tables::MemorySnapshotNodeTable::Id node_row_id =
-      context_->storage->mutable_memory_snapshot_node_table()
-          ->Insert(node_row)
-          .id;
-
-  auto* node_table = context_->storage->mutable_memory_snapshot_node_table();
-  uint32_t node_row_index =
-      static_cast<uint32_t>(*node_table->id().IndexOf(node_row_id));
-  ArgsTracker::BoundInserter args =
-      context_->args_tracker->AddArgsTo(node_row_id);
-
-  for (const auto& entry : node.const_entries()) {
-    switch (entry.second.type) {
-      case GlobalNodeGraph::Node::Entry::Type::kUInt64: {
-        int64_t value_int = static_cast<int64_t>(entry.second.value_uint64);
-
-        if (entry.first == "size") {
-          node_table->mutable_size()->Set(node_row_index, value_int);
-        } else if (entry.first == "effective_size") {
-          node_table->mutable_effective_size()->Set(node_row_index, value_int);
-        } else {
-          args.AddArg(context_->storage->InternString(
-                          base::StringView(entry.first + ".value")),
-                      Variadic::Integer(value_int));
-          if (entry.second.units < unit_ids_.size()) {
-            args.AddArg(context_->storage->InternString(
-                            base::StringView(entry.first + ".unit")),
-                        Variadic::String(unit_ids_[entry.second.units]));
-          }
-        }
-        break;
-      }
-      case GlobalNodeGraph::Node::Entry::Type::kString: {
-        args.AddArg(context_->storage->InternString(
-                        base::StringView(entry.first + ".value")),
-                    Variadic::String(context_->storage->InternString(
-                        base::StringView(entry.second.value_string))));
-        break;
-      }
-    }
-  }
-  id_node_map.emplace(std::make_pair(node.id(), node_row_id));
-  return node_row_id;
-}
-
-void MemoryTrackerSnapshotParser::GenerateGraphFromRawNodesAndEmitRows() {
-  std::unique_ptr<GlobalNodeGraph> graph = GenerateGraph(aggregate_raw_nodes_);
-  EmitRows(last_snapshot_timestamp_, *graph, last_snapshot_level_of_detail_);
-  aggregate_raw_nodes_.clear();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.h b/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.h
deleted file mode 100644
index 32119c2..0000000
--- a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_PARSER_H_
-
-#include "perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
-#include "protos/perfetto/trace/memory_graph.pbzero.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class MemoryTrackerSnapshotParser {
- public:
-  explicit MemoryTrackerSnapshotParser(TraceProcessorContext* context);
-  void ParseMemoryTrackerSnapshot(int64_t ts, protozero::ConstBytes blob);
-
-  void NotifyEndOfFile();
-
- private:
-  using RawMemoryNodeMap =
-      std::map<base::PlatformProcessId, std::unique_ptr<RawProcessMemoryNode>>;
-  using IdNodeMap =
-      std::map<MemoryAllocatorNodeId, tables::MemorySnapshotNodeTable::Id>;
-  using ConstBytes = protozero::ConstBytes;
-
-  class ChildNode {
-   public:
-    ChildNode() : table_index_(-1) {}
-    GlobalNodeGraph::Node* node_;
-    std::string path_;
-    uint64_t size_;
-    uint64_t effective_size_;
-    int32_t table_index_;
-  };
-
-  // Reads the proto-encoded memory snapshot of a process (message
-  // MemoryTrackerSnapshot) in given |blob| in order to get:
-  // - map of RawProcessMemoryNode containers |raw_nodes|. It
-  //   is need to generates GlobalNodeGraph via GraphProcessor.
-  // - level of detail of the memory graph |level_of_detail|.
-  void ReadProtoSnapshot(ConstBytes blob,
-                         RawMemoryNodeMap& raw_nodes,
-                         LevelOfDetail& level_of_detail);
-
-  // Generates GlobalNodeGraph via GraphProcessor for given map |raw_nodes|.
-  std::unique_ptr<GlobalNodeGraph> GenerateGraph(RawMemoryNodeMap& raw_nodes);
-
-  // Fills out MemorySnapshotTable, ProcessMemorySnapshotTable,
-  // MemorySnapshotNodeTable, MemorySnapshotEdgeTable with given
-  // timestamp |ts|, |graph|, |level_of_detail|.
-  void EmitRows(int64_t ts,
-                GlobalNodeGraph& graph,
-                LevelOfDetail level_of_detail);
-
-  // Fills out MemorySnapshotNodeTable for given root node
-  // |root_node_graph| and ProcessMemorySnapshotId |proc_snapshot_row_id|.
-  // Generates map of MemoryAllocatorNodeId and MemorySnapshotNodeTable::Id
-  // |id_node_map| which is used at time of filling out of
-  // MemorySnapshotEdgeTable.
-  void EmitMemorySnapshotNodeRows(GlobalNodeGraph::Node& root_node_graph,
-                                  ProcessMemorySnapshotId& proc_snapshot_row_id,
-                                  IdNodeMap& id_node_map);
-
-  // Recursively traverses through list of children of |node| to generate full
-  // |path| to every node in MemorySnapshotNodeTable for given
-  // ProcessMemorySnapshotId |proc_snapshot_row_id|.
-  // Generates map of MemoryAllocatorNodeId and MemorySnapshotNodeTable::Id
-  // |id_node_map| which is used at time of filling out of
-  // MemorySnapshotEdgeTable.
-  void EmitMemorySnapshotNodeRowsRecursively(
-      GlobalNodeGraph::Node& node,
-      const std::string&,
-      base::Optional<tables::MemorySnapshotNodeTable::Id> parent_node_row_id,
-      ProcessMemorySnapshotId& proc_snapshot_row_id,
-      IdNodeMap& id_node_map);
-
-  // Fills out MemorySnapshotNodeTable for given Node
-  // |node|, |path|, MemorySnapshotNodeTable::Id |parent_node_row_id| and
-  // ProcessMemorySnapshotId |proc_snapshot_row_id|. Generates map of
-  // MemoryAllocatorNodeId and MemorySnapshotNodeTable::Id |id_node_map| which
-  // is used at time of filling out of MemorySnapshotEdgeTable.
-  base::Optional<tables::MemorySnapshotNodeTable::Id> EmitNode(
-      const GlobalNodeGraph::Node& node,
-      const std::string& path,
-      base::Optional<tables::MemorySnapshotNodeTable::Id> parent_node_row_id,
-      ProcessMemorySnapshotId& proc_snapshot_row_id,
-      IdNodeMap& id_node_map);
-
-  void GenerateGraphFromRawNodesAndEmitRows();
-
-  TraceProcessorContext* context_;
-  std::array<StringId, 3> level_of_detail_ids_;
-  std::array<StringId, 2> unit_ids_;
-  RawMemoryNodeMap aggregate_raw_nodes_;
-  int64_t last_snapshot_timestamp_;
-  LevelOfDetail last_snapshot_level_of_detail_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_MEMORY_TRACKER_SNAPSHOT_PARSER_H_
diff --git a/src/trace_processor/importers/proto/metadata_module.cc b/src/trace_processor/importers/proto/metadata_module.cc
deleted file mode 100644
index b6a082f..0000000
--- a/src/trace_processor/importers/proto/metadata_module.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/metadata_module.h"
-
-#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/importers/proto/metadata_tracker.h"
-
-#include "protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
-#include "protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
-#include "protos/perfetto/trace/trigger.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using perfetto::protos::pbzero::TracePacket;
-
-MetadataModule::MetadataModule(TraceProcessorContext* context)
-    : context_(context) {
-  RegisterForField(TracePacket::kUiStateFieldNumber, context);
-  RegisterForField(TracePacket::kChromeMetadataFieldNumber, context);
-  RegisterForField(TracePacket::kChromeBenchmarkMetadataFieldNumber, context);
-  RegisterForField(TracePacket::kTriggerFieldNumber, context);
-}
-
-ModuleResult MetadataModule::TokenizePacket(
-    const protos::pbzero::TracePacket::Decoder& decoder,
-    TraceBlobView*,
-    int64_t,
-    PacketSequenceState*,
-    uint32_t field_id) {
-  switch (field_id) {
-    case TracePacket::kUiStateFieldNumber: {
-      auto ui_state = decoder.ui_state();
-      std::string base64 = base::Base64Encode(ui_state.data, ui_state.size);
-      StringId id = context_->storage->InternString(base::StringView(base64));
-      context_->metadata_tracker->SetMetadata(metadata::ui_state,
-                                              Variadic::String(id));
-      return ModuleResult::Handled();
-    }
-    case TracePacket::kChromeMetadataFieldNumber: {
-      ParseChromeMetadataPacket(decoder.chrome_metadata());
-      // Metadata packets may also contain untyped metadata due to a bug in
-      // Chrome <M92.
-      // TODO(crbug.com/1194914): Replace this with Handled() once the
-      // Chrome-side fix has propagated into all release channels.
-      return ModuleResult::Ignored();
-    }
-    case TracePacket::kChromeBenchmarkMetadataFieldNumber: {
-      ParseChromeBenchmarkMetadata(decoder.chrome_benchmark_metadata());
-      return ModuleResult::Handled();
-    }
-  }
-  return ModuleResult::Ignored();
-}
-
-void MetadataModule::ParsePacket(
-    const protos::pbzero::TracePacket::Decoder& decoder,
-    const TimestampedTracePiece& ttp,
-    uint32_t field_id) {
-  switch (field_id) {
-    case TracePacket::kTriggerFieldNumber:
-      // We handle triggers at parse time rather at tokenization because
-      // we add slices to tables which need to happen post-sorting.
-      ParseTrigger(ttp.timestamp, decoder.trigger());
-      break;
-  }
-}
-
-void MetadataModule::ParseChromeBenchmarkMetadata(ConstBytes blob) {
-  TraceStorage* storage = context_->storage.get();
-  MetadataTracker* metadata = context_->metadata_tracker.get();
-
-  protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
-  if (packet.has_benchmark_name()) {
-    auto benchmark_name_id = storage->InternString(packet.benchmark_name());
-    metadata->SetMetadata(metadata::benchmark_name,
-                          Variadic::String(benchmark_name_id));
-  }
-  if (packet.has_benchmark_description()) {
-    auto benchmark_description_id =
-        storage->InternString(packet.benchmark_description());
-    metadata->SetMetadata(metadata::benchmark_description,
-                          Variadic::String(benchmark_description_id));
-  }
-  if (packet.has_label()) {
-    auto label_id = storage->InternString(packet.label());
-    metadata->SetMetadata(metadata::benchmark_label,
-                          Variadic::String(label_id));
-  }
-  if (packet.has_story_name()) {
-    auto story_name_id = storage->InternString(packet.story_name());
-    metadata->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);
-    metadata->AppendMetadata(metadata::benchmark_story_tags,
-                             Variadic::String(story_tag_id));
-  }
-  if (packet.has_benchmark_start_time_us()) {
-    metadata->SetMetadata(metadata::benchmark_start_time_us,
-                          Variadic::Integer(packet.benchmark_start_time_us()));
-  }
-  if (packet.has_story_run_time_us()) {
-    metadata->SetMetadata(metadata::benchmark_story_run_time_us,
-                          Variadic::Integer(packet.story_run_time_us()));
-  }
-  if (packet.has_story_run_index()) {
-    metadata->SetMetadata(metadata::benchmark_story_run_index,
-                          Variadic::Integer(packet.story_run_index()));
-  }
-  if (packet.has_had_failures()) {
-    metadata->SetMetadata(metadata::benchmark_had_failures,
-                          Variadic::Integer(packet.had_failures()));
-  }
-}
-
-void MetadataModule::ParseChromeMetadataPacket(ConstBytes blob) {
-  TraceStorage* storage = context_->storage.get();
-  MetadataTracker* metadata = context_->metadata_tracker.get();
-
-  // Typed chrome metadata proto. The untyped metadata is parsed below in
-  // ParseChromeEvents().
-  protos::pbzero::ChromeMetadataPacket::Decoder packet(blob.data, blob.size);
-
-  if (packet.has_chrome_version_code()) {
-    metadata->SetDynamicMetadata(
-        storage->InternString("cr-playstore_version_code"),
-        Variadic::Integer(packet.chrome_version_code()));
-  }
-  if (packet.has_enabled_categories()) {
-    auto categories_id = storage->InternString(packet.enabled_categories());
-    metadata->SetDynamicMetadata(storage->InternString("cr-enabled_categories"),
-                                 Variadic::String(categories_id));
-  }
-}
-
-void MetadataModule::ParseTrigger(int64_t ts, ConstBytes blob) {
-  protos::pbzero::Trigger::Decoder trigger(blob.data, blob.size);
-  StringId cat_id = kNullStringId;
-  TrackId track_id = context_->track_tracker->GetOrCreateTriggerTrack();
-  StringId name_id = context_->storage->InternString(trigger.trigger_name());
-  context_->slice_tracker->Scoped(
-      ts, track_id, cat_id, name_id,
-      /* duration = */ 0,
-      [&trigger, this](ArgsTracker::BoundInserter* args_table) {
-        StringId producer_name_key =
-            context_->storage->InternString("producer_name");
-        args_table->AddArg(producer_name_key,
-                           Variadic::String(context_->storage->InternString(
-                               trigger.producer_name())));
-        StringId trusted_producer_uid_key =
-            context_->storage->InternString("trusted_producer_uid");
-        args_table->AddArg(trusted_producer_uid_key,
-                           Variadic::Integer(trigger.trusted_producer_uid()));
-      });
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/metadata_module.h b/src/trace_processor/importers/proto/metadata_module.h
deleted file mode 100644
index 55ac666..0000000
--- a/src/trace_processor/importers/proto/metadata_module.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_METADATA_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_METADATA_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class MetadataModule : public ProtoImporterModule {
- public:
-  using ConstBytes = protozero::ConstBytes;
-  explicit MetadataModule(TraceProcessorContext* context);
-
-  ModuleResult TokenizePacket(
-      const protos::pbzero::TracePacket::Decoder& decoder,
-      TraceBlobView* packet,
-      int64_t packet_timestamp,
-      PacketSequenceState* state,
-      uint32_t field_id) override;
-
-  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                   const TimestampedTracePiece& ttp,
-                   uint32_t field_id) override;
-
- private:
-  void ParseChromeBenchmarkMetadata(ConstBytes);
-  void ParseChromeMetadataPacket(ConstBytes);
-  void ParseTrigger(int64_t ts, ConstBytes);
-
-  TraceProcessorContext* context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_METADATA_MODULE_H_
diff --git a/src/trace_processor/importers/proto/metadata_tracker.cc b/src/trace_processor/importers/proto/metadata_tracker.cc
index a0f9c3d..757ac1a 100644
--- a/src/trace_processor/importers/proto/metadata_tracker.cc
+++ b/src/trace_processor/importers/proto/metadata_tracker.cc
@@ -33,7 +33,7 @@
   }
 }
 
-MetadataId MetadataTracker::SetMetadata(metadata::KeyId key, Variadic value) {
+MetadataId MetadataTracker::SetMetadata(metadata::KeyIDs key, Variadic value) {
   PERFETTO_DCHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
   PERFETTO_DCHECK(value.type == metadata::kValueTypes[key]);
 
@@ -55,18 +55,7 @@
   return id_and_row.id;
 }
 
-SqlValue MetadataTracker::GetMetadataForTesting(metadata::KeyId key) {
-  // KeyType::kMulti not yet supported by this method:
-  PERFETTO_CHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
-
-  auto* metadata_table = context_->storage->mutable_metadata_table();
-  uint32_t key_idx = static_cast<uint32_t>(key);
-  uint32_t row =
-      metadata_table->name().IndexOf(metadata::kNames[key_idx]).value();
-  return metadata_table->mutable_str_value()->Get(row);
-}
-
-MetadataId MetadataTracker::AppendMetadata(metadata::KeyId key,
+MetadataId MetadataTracker::AppendMetadata(metadata::KeyIDs key,
                                            Variadic value) {
   PERFETTO_DCHECK(key < metadata::kNumKeys);
   PERFETTO_DCHECK(metadata::kKeyTypes[key] == metadata::KeyType::kMulti);
@@ -83,17 +72,6 @@
   return id_and_row.id;
 }
 
-MetadataId MetadataTracker::SetDynamicMetadata(StringId key, Variadic value) {
-  tables::MetadataTable::Row row;
-  row.name = key;
-  row.key_type = key_type_ids_[static_cast<size_t>(metadata::KeyType::kSingle)];
-
-  auto* metadata_table = context_->storage->mutable_metadata_table();
-  auto id_and_row = metadata_table->Insert(row);
-  WriteValue(id_and_row.row, value);
-  return id_and_row.id;
-}
-
 void MetadataTracker::WriteValue(uint32_t row, Variadic value) {
   auto* metadata_table = context_->storage->mutable_metadata_table();
   switch (value.type) {
@@ -104,8 +82,6 @@
       metadata_table->mutable_str_value()->Set(row, value.string_value);
       break;
     case Variadic::Type::kJson:
-      metadata_table->mutable_str_value()->Set(row, value.json_value);
-      break;
     case Variadic::Type::kBool:
     case Variadic::Type::kPointer:
     case Variadic::Type::kUint:
diff --git a/src/trace_processor/importers/proto/metadata_tracker.h b/src/trace_processor/importers/proto/metadata_tracker.h
index dabdda0..b2ecda3 100644
--- a/src/trace_processor/importers/proto/metadata_tracker.h
+++ b/src/trace_processor/importers/proto/metadata_tracker.h
@@ -33,30 +33,17 @@
   // SetMetadata(metadata::benchmark_name,
   //             Variadic::String(storage->InternString("foo"));
   // Returns the id of the new entry.
-  MetadataId SetMetadata(metadata::KeyId key, Variadic value);
+  MetadataId SetMetadata(metadata::KeyIDs key, Variadic value);
 
   // Example usage:
   // AppendMetadata(metadata::benchmark_story_tags,
   //                Variadic::String(storage->InternString("bar"));
   // Returns the id of the new entry.
-  MetadataId AppendMetadata(metadata::KeyId key, Variadic value);
-
-  // Sets a metadata entry using any interned string as key.
-  // Returns the id of the new entry.
-  MetadataId SetDynamicMetadata(StringId key, Variadic value);
-
-  // Reads back a set metadata value.
-  // For use in tests only.
-  SqlValue GetMetadataForTesting(metadata::KeyId key);
-
-  // Tracks how many ChromeMetadata bundles have been parsed.
-  uint32_t IncrementChromeMetadataBundleCount() {
-    return ++chrome_metadata_bundle_count_;
-  }
+  MetadataId AppendMetadata(metadata::KeyIDs key, Variadic value);
 
  private:
   static constexpr size_t kNumKeys =
-      static_cast<size_t>(metadata::KeyId::kNumKeys);
+      static_cast<size_t>(metadata::KeyIDs::kNumKeys);
   static constexpr size_t kNumKeyTypes =
       static_cast<size_t>(metadata::KeyType::kNumKeyTypes);
 
@@ -64,7 +51,6 @@
 
   std::array<StringId, kNumKeys> key_ids_;
   std::array<StringId, kNumKeyTypes> key_type_ids_;
-  uint32_t chrome_metadata_bundle_count_ = 0;
 
   TraceProcessorContext* context_;
 };
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.cc b/src/trace_processor/importers/proto/packet_sequence_state.cc
index 2eb2350..c63c2d7 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.cc
+++ b/src/trace_processor/importers/proto/packet_sequence_state.cc
@@ -51,21 +51,5 @@
                           message_size) == 0));
 }
 
-InternedMessageView* PacketSequenceStateGeneration::GetInternedMessageView(
-    uint32_t field_id,
-    uint64_t iid) {
-  auto field_it = interned_data_.find(field_id);
-  if (field_it != interned_data_.end()) {
-    auto* message_map = &field_it->second;
-    auto it = message_map->find(iid);
-    if (it != message_map->end()) {
-      return &it->second;
-    }
-  }
-  state_->context()->storage->IncrementStats(
-      stats::interned_data_tokenizer_errors);
-  return nullptr;
-}
-
 }  // 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
index fc5288c..1bd9cae 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -24,9 +24,9 @@
 
 #include "perfetto/base/compiler.h"
 #include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
@@ -86,7 +86,7 @@
       PERFETTO_FATAL(
           "Interning entry accessed under different types! previous type: "
           "%s. new type: %s.",
-          decoder_type_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
+          decoder_type_, __PRETTY_FUNCTION__);
     }
     return reinterpret_cast<typename MessageType::Decoder*>(decoder_.get());
   }
@@ -157,7 +157,6 @@
   template <uint32_t FieldId, typename MessageType>
   typename MessageType::Decoder* LookupInternedMessage(uint64_t iid);
 
-  InternedMessageView* GetInternedMessageView(uint32_t field_id, uint64_t iid);
   // Returns |nullptr| if no defaults were set.
   InternedMessageView* GetTracePacketDefaultsView() {
     if (!trace_packet_defaults_)
@@ -191,7 +190,6 @@
   }
 
   PacketSequenceState* state() const { return state_; }
-  size_t generation_index() const { return generation_index_; }
 
  private:
   friend class PacketSequenceState;
@@ -226,9 +224,9 @@
 class PacketSequenceState {
  public:
   PacketSequenceState(TraceProcessorContext* context)
-      : context_(context), sequence_stack_profile_tracker_(context) {
-    current_generation_.reset(
-        new PacketSequenceStateGeneration(this, generation_index_++));
+      : context_(context), stack_profile_tracker_(context) {
+    generations_.emplace_back(
+        new PacketSequenceStateGeneration(this, generations_.size()));
   }
 
   int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
@@ -251,23 +249,23 @@
 
   // Intern a message into the current generation.
   void InternMessage(uint32_t field_id, TraceBlobView message) {
-    current_generation_->InternMessage(field_id, std::move(message));
+    generations_.back()->InternMessage(field_id, std::move(message));
   }
 
   // Set the trace packet defaults for the current generation. If the current
   // generation already has defaults set, starts a new generation without
   // invalidating other incremental state (such as interned data).
   void UpdateTracePacketDefaults(TraceBlobView defaults) {
-    if (!current_generation_->GetTracePacketDefaultsView()) {
-      current_generation_->SetTracePacketDefaults(std::move(defaults));
+    if (!generations_.back()->GetTracePacketDefaultsView()) {
+      generations_.back()->SetTracePacketDefaults(std::move(defaults));
       return;
     }
 
     // The new defaults should only apply to subsequent messages on the
     // sequence. Add a new generation with the updated defaults but the
     // current generation's interned data state.
-    current_generation_.reset(new PacketSequenceStateGeneration(
-        this, generation_index_++, current_generation_->interned_data_,
+    generations_.emplace_back(new PacketSequenceStateGeneration(
+        this, generations_.size(), generations_.back()->interned_data_,
         std::move(defaults)));
   }
 
@@ -293,19 +291,19 @@
   // Starts a new generation with clean-slate incremental state and defaults.
   void OnIncrementalStateCleared() {
     packet_loss_ = false;
-    current_generation_.reset(
-        new PacketSequenceStateGeneration(this, generation_index_++));
+    generations_.emplace_back(
+        new PacketSequenceStateGeneration(this, generations_.size()));
   }
 
   bool IsIncrementalStateValid() const { return !packet_loss_; }
 
-  SequenceStackProfileTracker& sequence_stack_profile_tracker() {
-    return sequence_stack_profile_tracker_;
+  StackProfileTracker& stack_profile_tracker() {
+    return stack_profile_tracker_;
   }
 
-  // Returns a ref-counted ptr to the current generation.
-  std::shared_ptr<PacketSequenceStateGeneration> current_generation() const {
-    return current_generation_;
+  // Returns a pointer to the current generation.
+  PacketSequenceStateGeneration* current_generation() const {
+    return generations_.back().get();
   }
 
   bool track_event_timestamps_valid() const {
@@ -320,9 +318,12 @@
   TraceProcessorContext* context() const { return context_; }
 
  private:
-  TraceProcessorContext* context_;
+  // TODO(eseckler): Reference count the generations so that we can get rid of
+  // past generations once all packets referring to them have been parsed.
+  using GenerationList =
+      std::vector<std::unique_ptr<PacketSequenceStateGeneration>>;
 
-  size_t generation_index_ = 0;
+  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
@@ -349,18 +350,27 @@
   int64_t track_event_thread_timestamp_ns_ = 0;
   int64_t track_event_thread_instruction_count_ = 0;
 
-  std::shared_ptr<PacketSequenceStateGeneration> current_generation_;
-  SequenceStackProfileTracker sequence_stack_profile_tracker_;
+  GenerationList generations_;
+  StackProfileTracker stack_profile_tracker_;
 };
 
 template <uint32_t FieldId, typename MessageType>
 typename MessageType::Decoder*
 PacketSequenceStateGeneration::LookupInternedMessage(uint64_t iid) {
-  auto* interned_message_view = GetInternedMessageView(FieldId, iid);
-  if (!interned_message_view)
-    return nullptr;
-
-  return interned_message_view->template GetOrCreateDecoder<MessageType>();
+  auto field_it = interned_data_.find(FieldId);
+  if (field_it != interned_data_.end()) {
+    auto* message_map = &field_it->second;
+    auto it = message_map->find(iid);
+    if (it != message_map->end()) {
+      return it->second.GetOrCreateDecoder<MessageType>();
+    }
+  }
+  state_->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_index_, iid);
+  return nullptr;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/perf_sample_tracker.cc b/src/trace_processor/importers/proto/perf_sample_tracker.cc
index d14d2aa..06b5ffa 100644
--- a/src/trace_processor/importers/proto/perf_sample_tracker.cc
+++ b/src/trace_processor/importers/proto/perf_sample_tracker.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,87 +15,94 @@
  */
 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
 
-#include <inttypes.h>
-#include <stdio.h>
+#include <vector>
 
+#include <inttypes.h>
+
+#include "perfetto/ext/base/optional.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
-#include "protos/perfetto/common/perf_events.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <cxxabi.h>
+#endif
 
 namespace perfetto {
 namespace trace_processor {
-
 namespace {
-// Follow perf tool naming convention.
-const char* StringifyCounter(int32_t counter) {
-  using protos::pbzero::PerfEvents;
-  switch (counter) {
-    case (PerfEvents::SW_CPU_CLOCK):
-      return "cpu-clock";
-    case (PerfEvents::SW_PAGE_FAULTS):
-      return "page-faults";
-    case (PerfEvents::HW_CPU_CYCLES):
-      return "cpu-cycles";
-    case (PerfEvents::HW_INSTRUCTIONS):
-      return "instructions";
-    default:
-      break;
-  }
-  return "unknown";
-}
-
-StringId InternTimebaseCounterName(
-    protos::pbzero::TracePacketDefaults::Decoder* defaults,
-    TraceProcessorContext* context) {
-  using namespace protos::pbzero;
-  PerfSampleDefaults::Decoder perf_defaults(defaults->perf_sample_defaults());
-  PerfEvents::Timebase::Decoder timebase(perf_defaults.timebase());
-
-  if (timebase.counter() != PerfEvents::UNKNOWN_COUNTER) {
-    return context->storage->InternString(StringifyCounter(timebase.counter()));
-  }
-  PerfEvents::Tracepoint::Decoder tracepoint(timebase.tracepoint());
-  return context->storage->InternString(tracepoint.name());
-}
+// TODO(rsavitski): consider using the sampling rate from the trace config.
+constexpr int64_t kFixedStackSliceDurationNs = 1 * 1000 * 1000;
 }  // namespace
 
-PerfSampleTracker::SamplingStreamInfo PerfSampleTracker::GetSamplingStreamInfo(
-    uint32_t seq_id,
-    uint32_t cpu,
-    protos::pbzero::TracePacketDefaults::Decoder* nullable_defaults) {
-  auto seq_it = seq_state_.find(seq_id);
-  if (seq_it == seq_state_.end()) {
-    seq_it = seq_state_.emplace(seq_id, next_perf_session_id_++).first;
-  }
-  SequenceState* seq_state = &seq_it->second;
-  uint32_t session_id = seq_state->perf_session_id;
+void PerfSampleTracker::AddStackToSliceTrack(int64_t timestamp,
+                                             CallsiteId leaf_id,
+                                             uint32_t pid,
+                                             uint32_t tid,
+                                             uint32_t cpu) {
+  UniquePid upid =
+      context_->process_tracker->GetOrCreateProcess(static_cast<uint32_t>(pid));
 
-  auto cpu_it = seq_state->per_cpu.find(cpu);
-  if (cpu_it != seq_state->per_cpu.end())
-    return {seq_state->perf_session_id, cpu_it->second.timebase_track_id};
+  TrackId track_id = context_->track_tracker->InternPerfStackTrack(upid);
+  const auto& callsites = context_->storage->stack_profile_callsite_table();
+  const auto& frames = context_->storage->stack_profile_frame_table();
+  const auto& mappings = context_->storage->stack_profile_mapping_table();
 
-  // No defaults means legacy producer implementation, assume default timebase
-  // of per-cpu timer. Always the case for Android R builds, and it isn't worth
-  // guaranteeing support for intermediate S builds in this aspect.
-  StringId name_id = kNullStringId;
-  if (!nullable_defaults || !nullable_defaults->has_perf_sample_defaults()) {
-    name_id = context_->storage->InternString(
-        StringifyCounter(protos::pbzero::PerfEvents::SW_CPU_CLOCK));
-  } else {
-    name_id = InternTimebaseCounterName(nullable_defaults, context_);
+  // Synthetic frame for more context, as the track is process-wide.
+  char buf[128] = {};
+  snprintf(buf, sizeof(buf), "cpu: [%" PRIu32 "]; thread: [%" PRIi32 "]", cpu,
+           tid);
+  StringId synth = context_->storage->InternString(buf);
+  context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId, synth,
+                                  kFixedStackSliceDurationNs);
+
+  // The callstack id references the leaf frame, while we want the slice stack
+  // to have the root frame at the top in the UI, so walk the chain in reverse.
+  std::vector<uint32_t> callsite_rows;
+  callsite_rows.reserve(64);
+  base::Optional<CallsiteId> cs_id = leaf_id;
+  while (cs_id) {
+    uint32_t row = *callsites.id().IndexOf(*cs_id);
+    callsite_rows.push_back(row);
+    cs_id = callsites.parent_id()[row];
   }
 
-  TrackId timebase_track_id = context_->track_tracker->CreatePerfCounterTrack(
-      name_id, session_id, cpu, /*is_timebase=*/true);
+  for (auto rit = callsite_rows.rbegin(); rit != callsite_rows.rend(); ++rit) {
+    uint32_t callsite_row = *rit;
+    FrameId frame_id = callsites.frame_id()[callsite_row];
+    uint32_t frame_row = *frames.id().IndexOf(frame_id);
 
-  seq_state->per_cpu.emplace(cpu, timebase_track_id);
+    MappingId mapping_id = frames.mapping()[frame_row];
+    uint32_t mapping_row = *mappings.id().IndexOf(mapping_id);
 
-  return {session_id, timebase_track_id};
+    StringId mangled_fname = frames.name()[frame_row];
+    StringId mname = mappings.name()[mapping_row];
+
+    StringId fname = MaybeDemangle(mangled_fname);
+    context_->slice_tracker->Scoped(timestamp, track_id, mname, fname,
+                                    kFixedStackSliceDurationNs);
+  }
 }
 
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
+  StringId ret = fname;
+  const char* raw_fname = context_->storage->GetString(fname).c_str();
+  int ignored;
+  char* data = abi::__cxa_demangle(raw_fname, nullptr, nullptr, &ignored);
+  if (data) {
+    ret = context_->storage->InternString(data);
+    free(data);
+  }
+  return ret;
+}
+#else
+StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
+  return fname;
+}
+#endif
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/perf_sample_tracker.h b/src/trace_processor/importers/proto/perf_sample_tracker.h
index 82f40d0..81dd73e 100644
--- a/src/trace_processor/importers/proto/perf_sample_tracker.h
+++ b/src/trace_processor/importers/proto/perf_sample_tracker.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,56 +19,27 @@
 
 #include <stdint.h>
 
-#include <unordered_map>
-
 #include "src/trace_processor/storage/trace_storage.h"
 
 namespace perfetto {
-namespace protos {
-namespace pbzero {
-class TracePacketDefaults_Decoder;
-}  // namespace pbzero
-}  // namespace protos
 namespace trace_processor {
+
 class TraceProcessorContext;
 
 class PerfSampleTracker {
  public:
-  struct SamplingStreamInfo {
-    uint32_t perf_session_id = 0;
-    TrackId timebase_track_id = kInvalidTrackId;
-
-    SamplingStreamInfo(uint32_t _perf_session_id, TrackId _timebase_track_id)
-        : perf_session_id(_perf_session_id),
-          timebase_track_id(_timebase_track_id) {}
-  };
-
   explicit PerfSampleTracker(TraceProcessorContext* context)
       : context_(context) {}
 
-  SamplingStreamInfo GetSamplingStreamInfo(
-      uint32_t seq_id,
-      uint32_t cpu,
-      protos::pbzero::TracePacketDefaults_Decoder* nullable_defaults);
+  // Interim UI track for visualizing stack samples as stacks of slices.
+  void AddStackToSliceTrack(int64_t timestamp,
+                            CallsiteId leaf_id,
+                            uint32_t pid,
+                            uint32_t tid,
+                            uint32_t cpu);
 
  private:
-  struct CpuSequenceState {
-    TrackId timebase_track_id = kInvalidTrackId;
-
-    CpuSequenceState(TrackId _timebase_track_id)
-        : timebase_track_id(_timebase_track_id) {}
-  };
-
-  struct SequenceState {
-    uint32_t perf_session_id = 0;
-    std::unordered_map<uint32_t, CpuSequenceState> per_cpu;
-
-    SequenceState(uint32_t _perf_session_id)
-        : perf_session_id(_perf_session_id) {}
-  };
-
-  std::unordered_map<uint32_t, SequenceState> seq_state_;
-  uint32_t next_perf_session_id_ = 0;
+  StringId MaybeDemangle(StringId original);
 
   TraceProcessorContext* const context_;
 };
diff --git a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc b/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
deleted file mode 100644
index 16c65b3..0000000
--- a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/perf_sample_tracker.h"
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/common/perf_events.gen.h"
-#include "protos/perfetto/trace/profiling/profile_packet.gen.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.gen.h"
-#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class PerfSampleTrackerTest : public ::testing::Test {
- public:
-  PerfSampleTrackerTest() {
-    context.storage.reset(new TraceStorage());
-    context.track_tracker.reset(new TrackTracker(&context));
-    context.perf_sample_tracker.reset(new PerfSampleTracker(&context));
-  }
-
- protected:
-  TraceProcessorContext context;
-};
-
-TEST_F(PerfSampleTrackerTest, PerCpuCounterTracks) {
-  uint32_t seq_id = 42;
-  uint32_t cpu0 = 0;
-  uint32_t cpu1 = 1;
-
-  auto stream = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu0, /*nullable_defaults=*/nullptr);
-  auto stream2 = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu1, /*nullable_defaults=*/nullptr);
-
-  // same session, different counter tracks
-  EXPECT_EQ(stream.perf_session_id, stream2.perf_session_id);
-  EXPECT_NE(stream.timebase_track_id, stream2.timebase_track_id);
-
-  // re-querying one of the existing streams gives the same ids
-  auto stream3 = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu1, /*nullable_defaults=*/nullptr);
-
-  EXPECT_EQ(stream2.perf_session_id, stream3.perf_session_id);
-  EXPECT_EQ(stream2.timebase_track_id, stream3.timebase_track_id);
-}
-
-TEST_F(PerfSampleTrackerTest, TimebaseTrackName_Counter) {
-  uint32_t seq_id = 42;
-  uint32_t cpu0 = 0;
-
-  protos::gen::TracePacketDefaults defaults;
-  auto* perf_defaults = defaults.mutable_perf_sample_defaults();
-  perf_defaults->mutable_timebase()->set_frequency(100);
-  perf_defaults->mutable_timebase()->set_counter(
-      protos::gen::PerfEvents::SW_PAGE_FAULTS);
-  auto defaults_pb = defaults.SerializeAsString();
-  protos::pbzero::TracePacketDefaults::Decoder defaults_decoder(defaults_pb);
-
-  auto stream = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu0, &defaults_decoder);
-
-  TrackId track_id = stream.timebase_track_id;
-  const auto& track_table = context.storage->perf_counter_track_table();
-  auto row_id = track_table.id().IndexOf(track_id);
-
-  // track exists and looks sensible
-  ASSERT_TRUE(row_id.has_value());
-  EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
-  EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
-  EXPECT_TRUE(track_table.is_timebase()[*row_id]);
-
-  // Name derived from the timebase.
-  std::string track_name =
-      context.storage->GetString(track_table.name()[*row_id]).ToStdString();
-  ASSERT_EQ(track_name, "page-faults");
-}
-
-TEST_F(PerfSampleTrackerTest, TimebaseTrackName_Tracepoint) {
-  uint32_t seq_id = 42;
-  uint32_t cpu0 = 0;
-
-  protos::gen::TracePacketDefaults defaults;
-  auto* perf_defaults = defaults.mutable_perf_sample_defaults();
-  perf_defaults->mutable_timebase()->set_frequency(100);
-  perf_defaults->mutable_timebase()->mutable_tracepoint()->set_name(
-      "sched:sched_switch");
-  auto defaults_pb = defaults.SerializeAsString();
-  protos::pbzero::TracePacketDefaults::Decoder defaults_decoder(defaults_pb);
-
-  auto stream = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu0, &defaults_decoder);
-
-  TrackId track_id = stream.timebase_track_id;
-  const auto& track_table = context.storage->perf_counter_track_table();
-  auto row_id = track_table.id().IndexOf(track_id);
-
-  // track exists and looks sensible
-  ASSERT_TRUE(row_id.has_value());
-  EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
-  EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
-  EXPECT_TRUE(track_table.is_timebase()[*row_id]);
-
-  // Name derived from the timebase.
-  std::string track_name =
-      context.storage->GetString(track_table.name()[*row_id]).ToStdString();
-  ASSERT_EQ(track_name, "sched:sched_switch");
-}
-
-TEST_F(PerfSampleTrackerTest, UnknownCounterTreatedAsCpuClock) {
-  uint32_t seq_id = 42;
-  uint32_t cpu0 = 0;
-
-  auto stream = context.perf_sample_tracker->GetSamplingStreamInfo(
-      seq_id, cpu0, /*nullable_defaults=*/nullptr);
-
-  TrackId track_id = stream.timebase_track_id;
-  const auto& track_table = context.storage->perf_counter_track_table();
-  auto row_id = track_table.id().IndexOf(track_id);
-
-  // track exists and looks sensible
-  ASSERT_TRUE(row_id.has_value());
-  EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
-  EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
-  EXPECT_TRUE(track_table.is_timebase()[*row_id]);
-
-  // If the trace doesn't have a PerfSampleDefaults describing the timebase
-  // counter, we assume cpu-clock.
-  std::string track_name =
-      context.storage->GetString(track_table.name()[*row_id]).ToStdString();
-  ASSERT_EQ(track_name, "cpu-clock");
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/profile_module.cc b/src/trace_processor/importers/proto/profile_module.cc
index ca72192..f133712 100644
--- a/src/trace_processor/importers/proto/profile_module.cc
+++ b/src/trace_processor/importers/proto/profile_module.cc
@@ -18,10 +18,8 @@
 
 #include "perfetto/base/logging.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
-#include "src/trace_processor/importers/common/event_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
 #include "src/trace_processor/importers/proto/profile_packet_utils.h"
 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
@@ -31,7 +29,6 @@
 #include "src/trace_processor/types/trace_processor_context.h"
 
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
-#include "protos/perfetto/common/perf_events.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 
 namespace perfetto {
@@ -43,7 +40,6 @@
 ProfileModule::ProfileModule(TraceProcessorContext* context)
     : context_(context) {
   RegisterForField(TracePacket::kStreamingProfilePacketFieldNumber, context);
-  RegisterForField(TracePacket::kPerfSampleFieldNumber, context);
 }
 
 ProfileModule::~ProfileModule() = default;
@@ -67,15 +63,9 @@
   switch (field_id) {
     case TracePacket::kStreamingProfilePacketFieldNumber:
       PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
-      ParseStreamingProfilePacket(ttp.timestamp,
-                                  ttp.packet_data.sequence_state.get(),
+      ParseStreamingProfilePacket(ttp.timestamp, ttp.packet_data.sequence_state,
                                   decoder.streaming_profile_packet());
       return;
-    case TracePacket::kPerfSampleFieldNumber:
-      PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
-      ParsePerfSample(ttp.timestamp, ttp.packet_data.sequence_state.get(),
-                      decoder);
-      return;
   }
 }
 
@@ -122,8 +112,8 @@
 
   ProcessTracker* procs = context_->process_tracker.get();
   TraceStorage* storage = context_->storage.get();
-  SequenceStackProfileTracker& sequence_stack_profile_tracker =
-      sequence_state->state()->sequence_stack_profile_tracker();
+  StackProfileTracker& stack_profile_tracker =
+      sequence_state->state()->stack_profile_tracker();
   ProfilePacketInternLookup intern_lookup(sequence_state);
 
   uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
@@ -141,10 +131,11 @@
       break;
     }
 
-    auto opt_cs_id = sequence_stack_profile_tracker.FindOrInsertCallstack(
+    auto opt_cs_id = stack_profile_tracker.FindOrInsertCallstack(
         *callstack_it, &intern_lookup);
     if (!opt_cs_id) {
       context_->storage->IncrementStats(stats::stackprofile_parser_error);
+      PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
       continue;
     }
 
@@ -157,98 +148,5 @@
   }
 }
 
-void ProfileModule::ParsePerfSample(
-    int64_t ts,
-    PacketSequenceStateGeneration* sequence_state,
-    const TracePacket::Decoder& decoder) {
-  using PerfSample = protos::pbzero::PerfSample;
-  const auto& sample_raw = decoder.perf_sample();
-  PerfSample::Decoder sample(sample_raw.data, sample_raw.size);
-
-  uint32_t seq_id = decoder.trusted_packet_sequence_id();
-  PerfSampleTracker::SamplingStreamInfo sampling_stream =
-      context_->perf_sample_tracker->GetSamplingStreamInfo(
-          seq_id, sample.cpu(), sequence_state->GetTracePacketDefaults());
-
-  // Not a sample, but an indication of data loss in the ring buffer shared with
-  // the kernel.
-  if (sample.kernel_records_lost() > 0) {
-    PERFETTO_DCHECK(sample.pid() == 0);
-
-    context_->storage->IncrementIndexedStats(
-        stats::perf_cpu_lost_records, static_cast<int>(sample.cpu()),
-        static_cast<int64_t>(sample.kernel_records_lost()));
-    return;
-  }
-
-  // Sample that looked relevant for the tracing session, but had to be skipped.
-  // Either we failed to look up the procfs file descriptors necessary for
-  // remote stack unwinding (not unexpected in most cases), or the unwind queue
-  // was out of capacity (producer lost data on its own).
-  if (sample.has_sample_skipped_reason()) {
-    context_->storage->IncrementStats(stats::perf_samples_skipped);
-
-    if (sample.sample_skipped_reason() ==
-        PerfSample::PROFILER_SKIP_UNWIND_ENQUEUE)
-      context_->storage->IncrementStats(stats::perf_samples_skipped_dataloss);
-
-    return;
-  }
-
-  // Not a sample, but an event from the producer.
-  // TODO(rsavitski): this stat is indexed by the session id, but the older
-  // stats (see above) aren't. The indexing is relevant if a trace contains more
-  // than one profiling data source. So the older stats should be changed to
-  // being indexed as well.
-  if (sample.has_producer_event()) {
-    PerfSample::ProducerEvent::Decoder producer_event(sample.producer_event());
-    if (producer_event.source_stop_reason() ==
-        PerfSample::ProducerEvent::PROFILER_STOP_GUARDRAIL) {
-      context_->storage->SetIndexedStats(
-          stats::perf_guardrail_stop_ts,
-          static_cast<int>(sampling_stream.perf_session_id), ts);
-    }
-    return;
-  }
-
-  // Proper sample, populate the |perf_sample| table with everything except the
-  // recorded counter values, which go to |counter|.
-  context_->event_tracker->PushCounter(
-      ts, static_cast<double>(sample.timebase_count()),
-      sampling_stream.timebase_track_id);
-
-  // TODO(rsavitski): empty callsite is not an error for counter-only samples.
-  // But consider identifying sequences which *should* have a callstack in every
-  // sample, as an invalid stack there is a bug.
-  SequenceStackProfileTracker& stack_tracker =
-      sequence_state->state()->sequence_stack_profile_tracker();
-  ProfilePacketInternLookup intern_lookup(sequence_state);
-  uint64_t callstack_iid = sample.callstack_iid();
-  base::Optional<CallsiteId> cs_id =
-      stack_tracker.FindOrInsertCallstack(callstack_iid, &intern_lookup);
-
-  UniqueTid utid =
-      context_->process_tracker->UpdateThread(sample.tid(), sample.pid());
-
-  using protos::pbzero::Profiling;
-  TraceStorage* storage = context_->storage.get();
-
-  auto cpu_mode = static_cast<Profiling::CpuMode>(sample.cpu_mode());
-  StringPool::Id cpu_mode_id =
-      storage->InternString(ProfilePacketUtils::StringifyCpuMode(cpu_mode));
-
-  base::Optional<StringPool::Id> unwind_error_id;
-  if (sample.has_unwind_error()) {
-    auto unwind_error =
-        static_cast<Profiling::StackUnwindError>(sample.unwind_error());
-    unwind_error_id = storage->InternString(
-        ProfilePacketUtils::StringifyStackUnwindError(unwind_error));
-  }
-  tables::PerfSampleTable::Row sample_row(ts, utid, sample.cpu(), cpu_mode_id,
-                                          cs_id, unwind_error_id,
-                                          sampling_stream.perf_session_id);
-  context_->storage->mutable_perf_sample_table()->Insert(sample_row);
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/profile_module.h b/src/trace_processor/importers/proto/profile_module.h
index f2fd43b..fe30e03 100644
--- a/src/trace_processor/importers/proto/profile_module.h
+++ b/src/trace_processor/importers/proto/profile_module.h
@@ -27,7 +27,8 @@
 namespace trace_processor {
 
 // Importer module for heap and CPU sampling profile data.
-// TODO(eseckler): consider moving heap profiles here as well.
+// TODO(eseckler): Currently handles only StreamingProfilePackets. Also move
+// other profiling data import functionality into this module.
 class ProfileModule : public ProtoImporterModule {
  public:
   explicit ProfileModule(TraceProcessorContext* context);
@@ -54,10 +55,6 @@
       PacketSequenceStateGeneration*,
       protozero::ConstBytes streaming_profile_packet);
 
-  void ParsePerfSample(int64_t ts,
-                       PacketSequenceStateGeneration* sequence_state,
-                       const protos::pbzero::TracePacket::Decoder& decoder);
-
   TraceProcessorContext* context_;
 };
 
diff --git a/src/trace_processor/importers/proto/profile_packet_utils.h b/src/trace_processor/importers/proto/profile_packet_utils.h
index 2dde388..8b32126 100644
--- a/src/trace_processor/importers/proto/profile_packet_utils.h
+++ b/src/trace_processor/importers/proto/profile_packet_utils.h
@@ -24,16 +24,15 @@
 
 #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"
 
 namespace perfetto {
 namespace trace_processor {
 
 class ProfilePacketUtils {
  public:
-  static SequenceStackProfileTracker::SourceMapping MakeSourceMapping(
+  static StackProfileTracker::SourceMapping MakeSourceMapping(
       const protos::pbzero::Mapping::Decoder& entry) {
-    SequenceStackProfileTracker::SourceMapping src_mapping{};
+    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();
@@ -47,100 +46,46 @@
     return src_mapping;
   }
 
-  static SequenceStackProfileTracker::SourceFrame MakeSourceFrame(
+  static StackProfileTracker::SourceFrame MakeSourceFrame(
       const protos::pbzero::Frame::Decoder& entry) {
-    SequenceStackProfileTracker::SourceFrame src_frame;
+    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;
   }
 
-  static SequenceStackProfileTracker::SourceCallstack MakeSourceCallstack(
+  static StackProfileTracker::SourceCallstack MakeSourceCallstack(
       const protos::pbzero::Callstack::Decoder& entry) {
-    SequenceStackProfileTracker::SourceCallstack src_callstack;
+    StackProfileTracker::SourceCallstack src_callstack;
     for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
       src_callstack.emplace_back(*frame_it);
     return src_callstack;
   }
-
-  static const char* StringifyCpuMode(
-      protos::pbzero::Profiling::CpuMode cpu_mode) {
-    using protos::pbzero::Profiling;
-    switch (cpu_mode) {
-      case Profiling::MODE_UNKNOWN:
-        return "unknown";
-      case Profiling::MODE_KERNEL:
-        return "kernel";
-      case Profiling::MODE_USER:
-        return "user";
-      case Profiling::MODE_HYPERVISOR:
-        return "hypervisor";
-      case Profiling::MODE_GUEST_KERNEL:
-        return "guest_kernel";
-      case Profiling::MODE_GUEST_USER:
-        return "guest_user";
-    }
-    return "unknown";  // switch should be complete, but gcc needs a hint
-  }
-
-  static const char* StringifyStackUnwindError(
-      protos::pbzero::Profiling::StackUnwindError unwind_error) {
-    using protos::pbzero::Profiling;
-    switch (unwind_error) {
-      case Profiling::UNWIND_ERROR_UNKNOWN:
-        return "unknown";
-      case Profiling::UNWIND_ERROR_NONE:
-        return "none";  // should never see this serialized by traced_perf, the
-                        // field should be unset instead
-      case Profiling::UNWIND_ERROR_MEMORY_INVALID:
-        return "memory_invalid";
-      case Profiling::UNWIND_ERROR_UNWIND_INFO:
-        return "unwind_info";
-      case Profiling::UNWIND_ERROR_UNSUPPORTED:
-        return "unsupported";
-      case Profiling::UNWIND_ERROR_INVALID_MAP:
-        return "invalid_map";
-      case Profiling::UNWIND_ERROR_MAX_FRAMES_EXCEEDED:
-        return "max_frames_exceeded";
-      case Profiling::UNWIND_ERROR_REPEATED_FRAME:
-        return "repeated_frame";
-      case Profiling::UNWIND_ERROR_INVALID_ELF:
-        return "invalid_elf";
-      case Profiling::UNWIND_ERROR_SYSTEM_CALL:
-        return "system_call";
-      case Profiling::UNWIND_ERROR_THREAD_TIMEOUT:
-        return "thread_timeout";
-      case Profiling::UNWIND_ERROR_THREAD_DOES_NOT_EXIST:
-        return "thread_does_not_exist";
-    }
-    return "unknown";  // switch should be complete, but gcc needs a hint
-  }
 };
 
-class ProfilePacketInternLookup
-    : public SequenceStackProfileTracker::InternLookup {
+class ProfilePacketInternLookup : public StackProfileTracker::InternLookup {
  public:
   explicit ProfilePacketInternLookup(PacketSequenceStateGeneration* seq_state)
       : seq_state_(seq_state) {}
   ~ProfilePacketInternLookup() override;
 
   base::Optional<base::StringView> GetString(
-      SequenceStackProfileTracker::SourceStringId iid,
-      SequenceStackProfileTracker::InternedStringType type) const override {
+      StackProfileTracker::SourceStringId iid,
+      StackProfileTracker::InternedStringType type) const override {
     protos::pbzero::InternedString::Decoder* decoder = nullptr;
     switch (type) {
-      case SequenceStackProfileTracker::InternedStringType::kBuildId:
+      case StackProfileTracker::InternedStringType::kBuildId:
         decoder = seq_state_->LookupInternedMessage<
             protos::pbzero::InternedData::kBuildIdsFieldNumber,
             protos::pbzero::InternedString>(iid);
         break;
-      case SequenceStackProfileTracker::InternedStringType::kFunctionName:
+      case StackProfileTracker::InternedStringType::kFunctionName:
         decoder = seq_state_->LookupInternedMessage<
             protos::pbzero::InternedData::kFunctionNamesFieldNumber,
             protos::pbzero::InternedString>(iid);
         break;
-      case SequenceStackProfileTracker::InternedStringType::kMappingPath:
+      case StackProfileTracker::InternedStringType::kMappingPath:
         decoder = seq_state_->LookupInternedMessage<
             protos::pbzero::InternedData::kMappingPathsFieldNumber,
             protos::pbzero::InternedString>(iid);
@@ -152,8 +97,8 @@
                             decoder->str().size);
   }
 
-  base::Optional<SequenceStackProfileTracker::SourceMapping> GetMapping(
-      SequenceStackProfileTracker::SourceMappingId iid) const override {
+  base::Optional<StackProfileTracker::SourceMapping> GetMapping(
+      StackProfileTracker::SourceMappingId iid) const override {
     auto* decoder = seq_state_->LookupInternedMessage<
         protos::pbzero::InternedData::kMappingsFieldNumber,
         protos::pbzero::Mapping>(iid);
@@ -162,8 +107,8 @@
     return ProfilePacketUtils::MakeSourceMapping(*decoder);
   }
 
-  base::Optional<SequenceStackProfileTracker::SourceFrame> GetFrame(
-      SequenceStackProfileTracker::SourceFrameId iid) const override {
+  base::Optional<StackProfileTracker::SourceFrame> GetFrame(
+      StackProfileTracker::SourceFrameId iid) const override {
     auto* decoder = seq_state_->LookupInternedMessage<
         protos::pbzero::InternedData::kFramesFieldNumber,
         protos::pbzero::Frame>(iid);
@@ -172,16 +117,14 @@
     return ProfilePacketUtils::MakeSourceFrame(*decoder);
   }
 
-  base::Optional<SequenceStackProfileTracker::SourceCallstack> GetCallstack(
-      SequenceStackProfileTracker::SourceCallstackId iid) const override {
-    auto* interned_message_view = seq_state_->GetInternedMessageView(
-        protos::pbzero::InternedData::kCallstacksFieldNumber, iid);
-    if (!interned_message_view)
+  base::Optional<StackProfileTracker::SourceCallstack> GetCallstack(
+      StackProfileTracker::SourceCallstackId iid) const override {
+    auto* decoder = seq_state_->LookupInternedMessage<
+        protos::pbzero::InternedData::kCallstacksFieldNumber,
+        protos::pbzero::Callstack>(iid);
+    if (!decoder)
       return base::nullopt;
-    protos::pbzero::Callstack::Decoder decoder(
-        interned_message_view->message().data(),
-        interned_message_view->message().length());
-    return ProfilePacketUtils::MakeSourceCallstack(std::move(decoder));
+    return ProfilePacketUtils::MakeSourceCallstack(*decoder);
   }
 
  private:
diff --git a/src/trace_processor/importers/proto/profiler_util.cc b/src/trace_processor/importers/proto/profiler_util.cc
deleted file mode 100644
index 175942f..0000000
--- a/src/trace_processor/importers/proto/profiler_util.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/profiler_util.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-base::Optional<base::StringView> PackageFromApp(base::StringView location) {
-  location = location.substr(base::StringView("/data/app/").size());
-  size_t start = 0;
-  if (location.at(0) == '~') {
-    size_t slash = location.find('/');
-    if (slash == std::string::npos) {
-      return base::nullopt;
-    }
-    start = slash + 1;
-  }
-  size_t end = location.find('/', start + 1);
-  if (end == std::string::npos) {
-    return base::nullopt;
-  }
-  location = location.substr(start, end);
-  size_t minus = location.find('-');
-  if (minus == std::string::npos) {
-    return base::nullopt;
-  }
-  return location.substr(0, minus);
-}
-
-}  // namespace
-
-base::Optional<std::string> PackageFromLocation(TraceStorage* storage,
-                                                base::StringView location) {
-  // List of some hardcoded apps that do not follow the scheme used in
-  // PackageFromApp. Ask for yours to be added.
-  //
-  // TODO(b/153632336): Get rid of the hardcoded list of system apps.
-  base::StringView sysui(
-      "/system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk");
-  if (location.size() >= sysui.size() &&
-      location.substr(0, sysui.size()) == sysui) {
-    return "com.android.systemui";
-  }
-
-  base::StringView phonesky("/product/priv-app/Phonesky/Phonesky.apk");
-  if (location.size() >= phonesky.size() &&
-      location.substr(0, phonesky.size()) == phonesky) {
-    return "com.android.vending";
-  }
-
-  base::StringView maps("/product/app/Maps/Maps.apk");
-  if (location.size() >= maps.size() &&
-      location.substr(0, maps.size()) == maps) {
-    return "com.google.android.apps.maps";
-  }
-
-  base::StringView launcher(
-      "/system_ext/priv-app/NexusLauncherRelease/NexusLauncherRelease.apk");
-  if (location.size() >= launcher.size() &&
-      location.substr(0, launcher.size()) == launcher) {
-    return "com.google.android.apps.nexuslauncher";
-  }
-
-  base::StringView photos("/product/app/Photos/Photos.apk");
-  if (location.size() >= photos.size() &&
-      location.substr(0, photos.size()) == photos) {
-    return "com.google.android.apps.photos";
-  }
-
-  base::StringView wellbeing(
-      "/product/priv-app/WellbeingPrebuilt/WellbeingPrebuilt.apk");
-  if (location.size() >= wellbeing.size() &&
-      location.substr(0, wellbeing.size()) == wellbeing) {
-    return "com.google.android.apps.wellbeing";
-  }
-
-  if (location.find("DevicePersonalizationPrebuilt") !=
-          base::StringView::npos ||
-      location.find("MatchMaker") != base::StringView::npos) {
-    return "com.google.android.as";
-  }
-
-  base::StringView gm("/product/app/PrebuiltGmail/PrebuiltGmail.apk");
-  if (location.size() >= gm.size() && location.substr(0, gm.size()) == gm) {
-    return "com.google.android.gm";
-  }
-
-  if (location.find("PrebuiltGmsCore") != std::string::npos) {
-    return "com.google.android.gms";
-  }
-
-  base::StringView velvet("/product/priv-app/Velvet/Velvet.apk");
-  if (location.size() >= velvet.size() &&
-      location.substr(0, velvet.size()) == velvet) {
-    return "com.google.android.googlequicksearchbox";
-  }
-
-  base::StringView inputmethod(
-      "/product/app/LatinIMEGooglePrebuilt/LatinIMEGooglePrebuilt.apk");
-  if (location.size() >= inputmethod.size() &&
-      location.substr(0, inputmethod.size()) == inputmethod) {
-    return "com.google.android.inputmethod.latin";
-  }
-
-  base::StringView messaging("/product/app/PrebuiltBugle/PrebuiltBugle.apk");
-  if (location.size() >= messaging.size() &&
-      location.substr(0, messaging.size()) == messaging) {
-    return "com.google.android.apps.messaging";
-  }
-
-  base::StringView data_app("/data/app/");
-  if (location.substr(0, data_app.size()) == data_app) {
-    auto package = PackageFromApp(location);
-    if (!package) {
-      PERFETTO_DLOG("Failed to parse %s", location.ToStdString().c_str());
-      storage->IncrementStats(stats::deobfuscate_location_parse_error);
-      return base::nullopt;
-    }
-    return package->ToStdString();
-  }
-  return base::nullopt;
-}
-
-std::string FullyQualifiedDeobfuscatedName(
-    protos::pbzero::ObfuscatedClass::Decoder& cls,
-    protos::pbzero::ObfuscatedMember::Decoder& member) {
-  std::string member_deobfuscated_name =
-      member.deobfuscated_name().ToStdString();
-  if (base::Contains(member_deobfuscated_name, '.')) {
-    // Fully qualified name.
-    return member_deobfuscated_name;
-  } else {
-    // Name relative to class.
-    return cls.deobfuscated_name().ToStdString() + "." +
-           member_deobfuscated_name;
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/profiler_util.h b/src/trace_processor/importers/proto/profiler_util.h
deleted file mode 100644
index 3870340..0000000
--- a/src/trace_processor/importers/proto/profiler_util.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILER_UTIL_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILER_UTIL_H_
-
-#include <string>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-std::string FullyQualifiedDeobfuscatedName(
-    protos::pbzero::ObfuscatedClass::Decoder& cls,
-    protos::pbzero::ObfuscatedMember::Decoder& member);
-
-base::Optional<std::string> PackageFromLocation(TraceStorage* storage,
-                                                base::StringView location);
-
-}
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILER_UTIL_H_
diff --git a/src/trace_processor/importers/proto/proto_importer_module.cc b/src/trace_processor/importers/proto/proto_importer_module.cc
index 7bc1cec..4f23f21 100644
--- a/src/trace_processor/importers/proto/proto_importer_module.cc
+++ b/src/trace_processor/importers/proto/proto_importer_module.cc
@@ -44,9 +44,10 @@
 void ProtoImporterModule::RegisterForField(uint32_t field_id,
                                            TraceProcessorContext* context) {
   if (context->modules_by_field.size() <= field_id) {
-    context->modules_by_field.resize(field_id + 1);
+    context->modules_by_field.resize(field_id + 1, nullptr);
   }
-  context->modules_by_field[field_id].push_back(this);
+  PERFETTO_DCHECK(!context->modules_by_field[field_id]);
+  context->modules_by_field[field_id] = this;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/proto_importer_module.h b/src/trace_processor/importers/proto/proto_importer_module.h
index d0a023a..909eb14 100644
--- a/src/trace_processor/importers/proto/proto_importer_module.h
+++ b/src/trace_processor/importers/proto/proto_importer_module.h
@@ -19,7 +19,7 @@
 
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
+#include "src/trace_processor/trace_blob_view.h"
 
 namespace perfetto {
 
@@ -36,7 +36,7 @@
 struct TimestampedTracePiece;
 class TraceProcessorContext;
 
-// This file contains a base class for ProtoTraceReader/Parser modules.
+// This file contains a base class for ProtoTraceTokenizer/Parser modules.
 // A module implements support for a subset of features of the TracePacket
 // proto format.
 // To add and integrate a new module:
@@ -98,7 +98,7 @@
 
   virtual ~ProtoImporterModule();
 
-  // Called by ProtoTraceReader during the tokenization stage, i.e. before
+  // Called by ProtoTraceTokenizer during the tokenization stage, i.e. before
   // sorting. It's called for each TracePacket that contains fields for which
   // the module was registered. If this returns a result other than
   // ModuleResult::Ignored(), tokenization of the packet will be aborted after
@@ -110,13 +110,6 @@
       PacketSequenceState*,
       uint32_t field_id);
 
-  // Called by ProtoTraceReader during the tokenization stage i.e. before
-  // sorting. Indicates that sequence with id |packet_sequence_id| has cleared
-  // its incremental state. This should be used to clear any cached state the
-  // tokenizer has built up while reading packets until this point for this
-  // packet sequence.
-  virtual void OnIncrementalStateCleared(uint32_t /* packet_sequence_id */) {}
-
   // Called by ProtoTraceParser after the sorting stage for each non-ftrace
   // TracePacket that contains fields for which the module was registered.
   virtual void ParsePacket(const protos::pbzero::TracePacket_Decoder&,
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 26383f2..d11afc4 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -29,42 +29,38 @@
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/base/uuid.h"
 #include "perfetto/trace_processor/status.h"
-
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/importers/config.descriptor.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/proto/heap_profile_tracker.h"
 #include "src/trace_processor/importers/proto/metadata_tracker.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
+#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
 #include "src/trace_processor/importers/proto/profile_packet_utils.h"
-#include "src/trace_processor/importers/proto/profiler_util.h"
 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
 #include "src/trace_processor/storage/metadata.h"
-#include "src/trace_processor/storage/stats.h"
-#include "src/trace_processor/tables/profiler_tables.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 #include "src/trace_processor/types/variadic.h"
-#include "src/trace_processor/util/descriptors.h"
-#include "src/trace_processor/util/protozero_to_text.h"
 
 #include "protos/perfetto/common/builtin_clock.pbzero.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/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
+#include "protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "protos/perfetto/trace/profiling/smaps.pbzero.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/trigger.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -99,7 +95,7 @@
   const TraceBlobView& blob = data->packet;
   protos::pbzero::TracePacket::Decoder packet(blob.data(), blob.length());
 
-  ParseTracePacketImpl(ts, ttp, data->sequence_state.get(), packet);
+  ParseTracePacketImpl(ts, std::move(ttp), data, 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
@@ -110,32 +106,14 @@
 
 void ProtoTraceParser::ParseTracePacketImpl(
     int64_t ts,
-    const TimestampedTracePiece& ttp,
-    PacketSequenceStateGeneration* sequence_state,
+    TimestampedTracePiece ttp,
+    const TracePacketData* data,
     const protos::pbzero::TracePacket::Decoder& packet) {
-  // This needs to get handled both by the HeapGraphModule and
-  // ProtoTraceParser (for StackProfileTracker).
-  if (packet.has_deobfuscation_mapping()) {
-    ParseDeobfuscationMapping(ts, sequence_state,
-                              packet.trusted_packet_sequence_id(),
-                              packet.deobfuscation_mapping());
-  }
-
-  // Chrome doesn't honor the one-of in TracePacket for this field and sets it
-  // together with chrome_metadata, which is handled by a module. Thus, we have
-  // to parse this field before the modules get to parse other fields.
-  // TODO(crbug/1194914): Move this back after the modules (or into a separate
-  // module) once the Chrome-side fix has propagated into all release channels.
-  if (packet.has_chrome_events()) {
-    ParseChromeEvents(ts, packet.chrome_events());
-  }
-
   // TODO(eseckler): Propagate statuses from modules.
   auto& modules = context_->modules_by_field;
   for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
-    if (!modules[field_id].empty() && packet.Get(field_id).valid()) {
-      for (ProtoImporterModule* module : modules[field_id])
-        module->ParsePacket(packet, ttp, field_id);
+    if (modules[field_id] && packet.Get(field_id).valid()) {
+      modules[field_id]->ParsePacket(packet, ttp, field_id);
       return;
     }
   }
@@ -144,10 +122,23 @@
     ParseTraceStats(packet.trace_stats());
 
   if (packet.has_profile_packet()) {
-    ParseProfilePacket(ts, sequence_state, packet.trusted_packet_sequence_id(),
+    ParseProfilePacket(ts, data->sequence_state,
+                       packet.trusted_packet_sequence_id(),
                        packet.profile_packet());
   }
 
+  if (packet.has_perf_sample()) {
+    ParsePerfSample(ts, data->sequence_state, packet.perf_sample());
+  }
+
+  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());
   }
@@ -160,6 +151,14 @@
     ParseModuleSymbols(packet.module_symbols());
   }
 
+  if (packet.has_trigger()) {
+    ParseTrigger(ts, packet.trigger());
+  }
+
+  if (packet.has_service_event()) {
+    ParseServiceEvent(ts, packet.service_event());
+  }
+
   if (packet.has_smaps_packet()) {
     ParseSmapsPacket(ts, packet.smaps_packet());
   }
@@ -243,7 +242,7 @@
 }
 
 void ProtoTraceParser::ParseProfilePacket(
-    int64_t ts,
+    int64_t,
     PacketSequenceStateGeneration* sequence_state,
     uint32_t seq_id,
     ConstBytes blob) {
@@ -255,31 +254,31 @@
 
     const char* str = reinterpret_cast<const char*>(entry.str().data);
     auto str_view = base::StringView(str, entry.str().size);
-    sequence_state->state()->sequence_stack_profile_tracker().AddString(
-        entry.iid(), str_view);
+    sequence_state->state()->stack_profile_tracker().AddString(entry.iid(),
+                                                               str_view);
   }
 
   for (auto it = packet.mappings(); it; ++it) {
     protos::pbzero::Mapping::Decoder entry(*it);
-    SequenceStackProfileTracker::SourceMapping src_mapping =
+    StackProfileTracker::SourceMapping src_mapping =
         ProfilePacketUtils::MakeSourceMapping(entry);
-    sequence_state->state()->sequence_stack_profile_tracker().AddMapping(
-        entry.iid(), src_mapping);
+    sequence_state->state()->stack_profile_tracker().AddMapping(entry.iid(),
+                                                                src_mapping);
   }
 
   for (auto it = packet.frames(); it; ++it) {
     protos::pbzero::Frame::Decoder entry(*it);
-    SequenceStackProfileTracker::SourceFrame src_frame =
+    StackProfileTracker::SourceFrame src_frame =
         ProfilePacketUtils::MakeSourceFrame(entry);
-    sequence_state->state()->sequence_stack_profile_tracker().AddFrame(
-        entry.iid(), src_frame);
+    sequence_state->state()->stack_profile_tracker().AddFrame(entry.iid(),
+                                                              src_frame);
   }
 
   for (auto it = packet.callstacks(); it; ++it) {
     protos::pbzero::Callstack::Decoder entry(*it);
-    SequenceStackProfileTracker::SourceCallstack src_callstack =
+    StackProfileTracker::SourceCallstack src_callstack =
         ProfilePacketUtils::MakeSourceCallstack(entry);
-    sequence_state->state()->sequence_stack_profile_tracker().AddCallstack(
+    sequence_state->state()->stack_profile_tracker().AddCallstack(
         entry.iid(), src_callstack);
   }
 
@@ -297,8 +296,6 @@
     int64_t timestamp = *maybe_timestamp;
 
     int pid = static_cast<int>(entry.pid());
-    context_->storage->SetIndexedStats(stats::heapprofd_last_profile_timestamp,
-                                       pid, ts);
 
     if (entry.disconnected())
       context_->storage->IncrementIndexedStats(
@@ -306,69 +303,31 @@
     if (entry.buffer_corrupted())
       context_->storage->IncrementIndexedStats(
           stats::heapprofd_buffer_corrupted, pid);
-    if (entry.buffer_overran() ||
-        entry.client_error() ==
-            protos::pbzero::ProfilePacket::ProcessHeapSamples::
-                CLIENT_ERROR_HIT_TIMEOUT) {
+    if (entry.buffer_overran())
       context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
                                                pid);
-    }
-    if (entry.client_error()) {
-      context_->storage->SetIndexedStats(stats::heapprofd_client_error, pid,
-                                         entry.client_error());
-    }
     if (entry.rejected_concurrent())
       context_->storage->IncrementIndexedStats(
           stats::heapprofd_rejected_concurrent, pid);
     if (entry.hit_guardrail())
       context_->storage->IncrementIndexedStats(stats::heapprofd_hit_guardrail,
                                                pid);
-    if (entry.orig_sampling_interval_bytes()) {
-      context_->storage->SetIndexedStats(
-          stats::heapprofd_sampling_interval_adjusted, pid,
-          static_cast<int64_t>(entry.sampling_interval_bytes()) -
-              static_cast<int64_t>(entry.orig_sampling_interval_bytes()));
-    }
-
-    protos::pbzero::ProfilePacket::ProcessStats::Decoder stats(entry.stats());
-    context_->storage->IncrementIndexedStats(
-        stats::heapprofd_unwind_time_us, static_cast<int>(entry.pid()),
-        static_cast<int64_t>(stats.total_unwinding_time_us()));
-    context_->storage->IncrementIndexedStats(
-        stats::heapprofd_unwind_samples, static_cast<int>(entry.pid()),
-        static_cast<int64_t>(stats.heap_samples()));
-    context_->storage->IncrementIndexedStats(
-        stats::heapprofd_client_spinlock_blocked, static_cast<int>(entry.pid()),
-        static_cast<int64_t>(stats.client_spinlock_blocked_us()));
-
-    // orig_sampling_interval_bytes was introduced slightly after a bug with
-    // self_max_count was fixed in the producer. We use this as a proxy
-    // whether or not we are getting this data from a fixed producer or not.
-    bool trustworthy_max_count = entry.orig_sampling_interval_bytes() > 0;
 
     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();
-      if (entry.heap_name().size != 0) {
-        src_allocation.heap_name =
-            context_->storage->InternString(entry.heap_name());
-      } else {
-        src_allocation.heap_name = context_->storage->InternString("malloc");
-      }
       src_allocation.timestamp = timestamp;
       src_allocation.callstack_id = sample.callstack_id();
-      if (sample.has_self_max()) {
+      if (sample.self_max()) {
         src_allocation.self_allocated = sample.self_max();
-        if (trustworthy_max_count)
-          src_allocation.alloc_count = sample.self_max_count();
       } else {
         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();
       }
+      src_allocation.alloc_count = sample.alloc_count();
+      src_allocation.free_count = sample.free_count();
 
       context_->heap_profile_tracker->StoreAllocation(seq_id, src_allocation);
     }
@@ -377,69 +336,108 @@
     PERFETTO_CHECK(sequence_state);
     ProfilePacketInternLookup intern_lookup(sequence_state);
     context_->heap_profile_tracker->FinalizeProfile(
-        seq_id, &sequence_state->state()->sequence_stack_profile_tracker(),
+        seq_id, &sequence_state->state()->stack_profile_tracker(),
         &intern_lookup);
   }
 }
 
-void ProtoTraceParser::ParseDeobfuscationMapping(int64_t,
-                                                 PacketSequenceStateGeneration*,
-                                                 uint32_t /* seq_id */,
-                                                 ConstBytes blob) {
-  protos::pbzero::DeobfuscationMapping::Decoder deobfuscation_mapping(
-      blob.data, blob.size);
-  if (deobfuscation_mapping.package_name().size == 0)
+void ProtoTraceParser::ParsePerfSample(
+    int64_t ts,
+    PacketSequenceStateGeneration* sequence_state,
+    ConstBytes blob) {
+  using PerfSample = protos::pbzero::PerfSample;
+  PerfSample::Decoder sample(blob.data, blob.size);
+
+  // Not a sample, but an indication of data loss in the ring buffer shared with
+  // the kernel.
+  if (sample.kernel_records_lost() > 0) {
+    PERFETTO_DCHECK(sample.pid() == 0);
+
+    context_->storage->IncrementIndexedStats(
+        stats::perf_cpu_lost_records, static_cast<int>(sample.cpu()),
+        static_cast<int64_t>(sample.kernel_records_lost()));
     return;
+  }
 
-  auto opt_package_name_id = context_->storage->string_pool().GetId(
-      deobfuscation_mapping.package_name());
-  auto opt_memfd_id = context_->storage->string_pool().GetId("memfd");
-  if (!opt_package_name_id && !opt_memfd_id)
+  // Sample that looked relevant for the tracing session, but had to be skipped.
+  // Either we failed to look up the procfs file descriptors necessary for
+  // remote stack unwinding (not unexpected in most cases), or the unwind queue
+  // was out of capacity (producer lost data on its own).
+  if (sample.has_sample_skipped_reason()) {
+    context_->storage->IncrementStats(stats::perf_samples_skipped);
+
+    if (sample.sample_skipped_reason() ==
+        PerfSample::PROFILER_SKIP_UNWIND_ENQUEUE)
+      context_->storage->IncrementStats(stats::perf_samples_skipped_dataloss);
+
     return;
+  }
 
-  for (auto class_it = deobfuscation_mapping.obfuscated_classes(); class_it;
-       ++class_it) {
-    protos::pbzero::ObfuscatedClass::Decoder cls(*class_it);
-    for (auto member_it = cls.obfuscated_methods(); member_it; ++member_it) {
-      protos::pbzero::ObfuscatedMember::Decoder member(*member_it);
-      std::string merged_obfuscated = cls.obfuscated_name().ToStdString() +
-                                      "." +
-                                      member.obfuscated_name().ToStdString();
-      auto merged_obfuscated_id = context_->storage->string_pool().GetId(
-          base::StringView(merged_obfuscated));
-      if (!merged_obfuscated_id)
-        continue;
-      std::string merged_deobfuscated =
-          FullyQualifiedDeobfuscatedName(cls, member);
+  uint64_t callstack_iid = sample.callstack_iid();
+  StackProfileTracker& stack_tracker =
+      sequence_state->state()->stack_profile_tracker();
+  ProfilePacketInternLookup intern_lookup(sequence_state);
 
-      std::vector<tables::StackProfileFrameTable::Id> frames;
-      if (opt_package_name_id) {
-        const std::vector<tables::StackProfileFrameTable::Id>* pkg_frames =
-            context_->global_stack_profile_tracker->JavaFramesForName(
-                {*merged_obfuscated_id, *opt_package_name_id});
-        if (pkg_frames) {
-          frames.insert(frames.end(), pkg_frames->begin(), pkg_frames->end());
-        }
-      }
-      if (opt_memfd_id) {
-        const std::vector<tables::StackProfileFrameTable::Id>* memfd_frames =
-            context_->global_stack_profile_tracker->JavaFramesForName(
-                {*merged_obfuscated_id, *opt_memfd_id});
-        if (memfd_frames) {
-          frames.insert(frames.end(), memfd_frames->begin(),
-                        memfd_frames->end());
-        }
-      }
+  base::Optional<CallsiteId> cs_id =
+      stack_tracker.FindOrInsertCallstack(callstack_iid, &intern_lookup);
+  if (!cs_id) {
+    context_->storage->IncrementStats(stats::stackprofile_parser_error);
+    PERFETTO_ELOG("PerfSample referencing invalid callstack iid [%" PRIu64
+                  "] at timestamp [%" PRIi64 "]",
+                  callstack_iid, ts);
+    return;
+  }
 
-      for (tables::StackProfileFrameTable::Id frame_id : frames) {
-        auto* frames_tbl =
-            context_->storage->mutable_stack_profile_frame_table();
-        frames_tbl->mutable_deobfuscated_name()->Set(
-            *frames_tbl->id().IndexOf(frame_id),
-            context_->storage->InternString(
-                base::StringView(merged_deobfuscated)));
-      }
-    }
+  context_->perf_sample_tracker->AddStackToSliceTrack(
+      ts, *cs_id, sample.pid(), sample.tid(), sample.cpu());
+}
+
+void ProtoTraceParser::ParseChromeBenchmarkMetadata(ConstBytes blob) {
+  TraceStorage* storage = context_->storage.get();
+  MetadataTracker* metadata = context_->metadata_tracker.get();
+
+  protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
+  if (packet.has_benchmark_name()) {
+    auto benchmark_name_id = storage->InternString(packet.benchmark_name());
+    metadata->SetMetadata(metadata::benchmark_name,
+                          Variadic::String(benchmark_name_id));
+  }
+  if (packet.has_benchmark_description()) {
+    auto benchmark_description_id =
+        storage->InternString(packet.benchmark_description());
+    metadata->SetMetadata(metadata::benchmark_description,
+                          Variadic::String(benchmark_description_id));
+  }
+  if (packet.has_label()) {
+    auto label_id = storage->InternString(packet.label());
+    metadata->SetMetadata(metadata::benchmark_label,
+                          Variadic::String(label_id));
+  }
+  if (packet.has_story_name()) {
+    auto story_name_id = storage->InternString(packet.story_name());
+    metadata->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);
+    metadata->AppendMetadata(metadata::benchmark_story_tags,
+                             Variadic::String(story_tag_id));
+  }
+  if (packet.has_benchmark_start_time_us()) {
+    metadata->SetMetadata(metadata::benchmark_start_time_us,
+                          Variadic::Integer(packet.benchmark_start_time_us()));
+  }
+  if (packet.has_story_run_time_us()) {
+    metadata->SetMetadata(metadata::benchmark_story_run_time_us,
+                          Variadic::Integer(packet.story_run_time_us()));
+  }
+  if (packet.has_story_run_index()) {
+    metadata->SetMetadata(metadata::benchmark_story_run_index,
+                          Variadic::Integer(packet.story_run_index()));
+  }
+  if (packet.has_had_failures()) {
+    metadata->SetMetadata(metadata::benchmark_had_failures,
+                          Variadic::Integer(packet.had_failures()));
   }
 }
 
@@ -453,13 +451,10 @@
                    .id;
     auto inserter = args.AddArgsTo(id);
 
-    uint32_t bundle_index =
-        context_->metadata_tracker->IncrementChromeMetadataBundleCount();
-
-    // The legacy untyped metadata is proxied via a special event in the raw
-    // table to JSON export.
+    // 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 =
@@ -474,23 +469,7 @@
         context_->storage->IncrementStats(stats::empty_chrome_metadata);
         continue;
       }
-
-      StringId name_id = storage->InternString(metadata.name());
       args.AddArgsTo(id).AddArg(name_id, value);
-
-      char buffer[2048];
-      base::StringWriter writer(buffer, sizeof(buffer));
-      writer.AppendString("cr-");
-      // If we have data from multiple Chrome instances, append a suffix
-      // to differentiate them.
-      if (bundle_index > 1) {
-        writer.AppendUnsignedInt(bundle_index);
-        writer.AppendChar('-');
-      }
-      writer.AppendString(metadata.name());
-
-      auto metadata_id = storage->InternString(writer.GetStringView());
-      context_->metadata_tracker->SetDynamicMetadata(metadata_id, value);
     }
   }
 
@@ -657,17 +636,6 @@
     context_->metadata_tracker->SetMetadata(metadata::unique_session_name,
                                             Variadic::String(id));
   }
-
-  DescriptorPool pool;
-  pool.AddFromFileDescriptorSet(kConfigDescriptor.data(),
-                                kConfigDescriptor.size());
-
-  std::string text = protozero_to_text::ProtozeroToText(
-      pool, ".perfetto.protos.TraceConfig", blob,
-      protozero_to_text::kIncludeNewLines);
-  StringId id = context_->storage->InternString(base::StringView(text));
-  context_->metadata_tracker->SetMetadata(metadata::trace_config_pbtxt,
-                                          Variadic::String(id));
 }
 
 void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
@@ -682,7 +650,7 @@
         module_symbols.build_id().data, module_symbols.build_id().size)));
   }
 
-  auto mapping_ids = context_->global_stack_profile_tracker->FindMappingRow(
+  auto mapping_ids = context_->storage->FindMappingRow(
       context_->storage->InternString(module_symbols.path()), build_id);
   if (mapping_ids.empty()) {
     context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
@@ -707,9 +675,8 @@
     }
     bool frame_found = false;
     for (MappingId mapping_id : mapping_ids) {
-      std::vector<FrameId> frame_ids =
-          context_->global_stack_profile_tracker->FindFrameIds(
-              mapping_id, address_symbols.address());
+      std::vector<FrameId> frame_ids = context_->storage->FindFrameIds(
+          mapping_id, address_symbols.address());
 
       for (const FrameId frame_id : frame_ids) {
         auto* frames = context_->storage->mutable_stack_profile_frame_table();
@@ -723,6 +690,36 @@
       context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
       continue;
     }
+
+  }
+}
+
+void ProtoTraceParser::ParseTrigger(int64_t ts, ConstBytes blob) {
+  protos::pbzero::Trigger::Decoder trigger(blob.data, blob.size);
+  StringId cat_id = kNullStringId;
+  TrackId track_id = context_->track_tracker->GetOrCreateTriggerTrack();
+  StringId name_id = context_->storage->InternString(trigger.trigger_name());
+  context_->slice_tracker->Scoped(
+      ts, track_id, cat_id, name_id,
+      /* duration = */ 0,
+      [&trigger, this](ArgsTracker::BoundInserter* args_table) {
+        StringId producer_name_key =
+            context_->storage->InternString("producer_name");
+        args_table->AddArg(producer_name_key,
+                           Variadic::String(context_->storage->InternString(
+                               trigger.producer_name())));
+        StringId trusted_producer_uid_key =
+            context_->storage->InternString("trusted_producer_uid");
+        args_table->AddArg(trusted_producer_uid_key,
+                           Variadic::Integer(trigger.trusted_producer_uid()));
+      });
+}
+
+void ProtoTraceParser::ParseServiceEvent(int64_t ts, ConstBytes blob) {
+  protos::pbzero::TracingServiceEvent::Decoder tse(blob.data, blob.size);
+  if (tse.all_data_sources_started()) {
+    context_->metadata_tracker->SetMetadata(
+        metadata::all_data_source_started_ns, Variadic::Integer(ts));
   }
 }
 
@@ -736,18 +733,7 @@
         {upid, ts, context_->storage->InternString(e.path()),
          static_cast<int64_t>(e.size_kb()),
          static_cast<int64_t>(e.private_dirty_kb()),
-         static_cast<int64_t>(e.swap_kb()),
-         context_->storage->InternString(e.file_name()),
-         static_cast<int64_t>(e.start_address()),
-         static_cast<int64_t>(e.module_timestamp()),
-         context_->storage->InternString(e.module_debugid()),
-         context_->storage->InternString(e.module_debug_path()),
-         static_cast<int32_t>(e.protection_flags()),
-         static_cast<int64_t>(e.private_clean_resident_kb()),
-         static_cast<int64_t>(e.shared_dirty_resident_kb()),
-         static_cast<int64_t>(e.shared_clean_resident_kb()),
-         static_cast<int64_t>(e.locked_kb()),
-         static_cast<int64_t>(e.proportional_resident_kb())});
+         static_cast<int64_t>(e.swap_kb())});
   }
 }
 
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index 53a6099..87bdcfc 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -25,10 +25,10 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/protozero/field.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
-#include "src/trace_processor/importers/common/trace_parser.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_parser.h"
 
 namespace perfetto {
 
@@ -57,8 +57,8 @@
                          TimestampedTracePiece) override;
 
   void ParseTracePacketImpl(int64_t ts,
-                            const TimestampedTracePiece&,
-                            PacketSequenceStateGeneration*,
+                            TimestampedTracePiece,
+                            const TracePacketData*,
                             const protos::pbzero::TracePacket_Decoder&);
 
   void ParseTraceStats(ConstBytes);
@@ -66,14 +66,14 @@
                           PacketSequenceStateGeneration*,
                           uint32_t seq_id,
                           ConstBytes);
-  void ParseDeobfuscationMapping(int64_t ts,
-                                 PacketSequenceStateGeneration*,
-                                 uint32_t seq_id,
-                                 ConstBytes);
+  void ParsePerfSample(int64_t ts, PacketSequenceStateGeneration*, ConstBytes);
+  void ParseChromeBenchmarkMetadata(ConstBytes);
   void ParseChromeEvents(int64_t ts, ConstBytes);
   void ParseMetatraceEvent(int64_t ts, ConstBytes);
   void ParseTraceConfig(ConstBytes);
   void ParseModuleSymbols(ConstBytes);
+  void ParseTrigger(int64_t ts, ConstBytes);
+  void ParseServiceEvent(int64_t ts, ConstBytes);
   void ParseSmapsPacket(int64_t ts, ConstBytes);
 
  private:
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index 1812f14..34d9ccf 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/importers/proto/proto_trace_reader.h"
+#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/string_view.h"
@@ -23,7 +23,6 @@
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
@@ -35,15 +34,12 @@
 #include "src/trace_processor/storage/metadata.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/util/descriptors.h"
 #include "test/gtest_and_gmock.h"
 
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
 #include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-#include "protos/perfetto/config/trace_config.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_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"
@@ -59,7 +55,6 @@
 #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/chrome_thread_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 #include "protos/perfetto/trace/track_event/log_message.pbzero.h"
@@ -77,11 +72,8 @@
 using ::testing::_;
 using ::testing::Args;
 using ::testing::AtLeast;
-using ::testing::DoAll;
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
-using ::testing::HasSubstr;
-using ::testing::IgnoreResult;
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::InvokeArgument;
@@ -147,20 +139,15 @@
   MockProcessTracker(TraceProcessorContext* context)
       : ProcessTracker(context) {}
 
-  MOCK_METHOD4(SetProcessMetadata,
+  MOCK_METHOD3(SetProcessMetadata,
                UniquePid(uint32_t pid,
                          base::Optional<uint32_t> ppid,
-                         base::StringView process_name,
-                         base::StringView cmdline));
+                         base::StringView process_name));
 
-  MOCK_METHOD3(UpdateThreadName,
-               UniqueTid(uint32_t tid,
-                         StringId thread_name_id,
-                         ThreadNamePriority priority));
-  MOCK_METHOD3(UpdateThreadNameByUtid,
-               void(UniqueTid utid,
-                    StringId thread_name_id,
-                    ThreadNamePriority priority));
+  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));
@@ -191,42 +178,24 @@
   MockSliceTracker(TraceProcessorContext* context) : SliceTracker(context) {}
 
   MOCK_METHOD5(Begin,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       StringId cat,
-                                       StringId name,
-                                       SetArgsCallback args_callback));
+               base::Optional<uint32_t>(int64_t timestamp,
+                                        TrackId track_id,
+                                        StringId cat,
+                                        StringId name,
+                                        SetArgsCallback args_callback));
   MOCK_METHOD5(End,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       StringId cat,
-                                       StringId name,
-                                       SetArgsCallback args_callback));
+               base::Optional<uint32_t>(int64_t timestamp,
+                                        TrackId track_id,
+                                        StringId cat,
+                                        StringId name,
+                                        SetArgsCallback args_callback));
   MOCK_METHOD6(Scoped,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       StringId cat,
-                                       StringId name,
-                                       int64_t duration,
-                                       SetArgsCallback args_callback));
-  MOCK_METHOD4(StartSlice,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       SetArgsCallback args_callback,
-                                       std::function<SliceId()> inserter));
-};
-
-class MockFlowTracker : public FlowTracker {
- public:
-  MockFlowTracker(TraceProcessorContext* context) : FlowTracker(context) {}
-
-  MOCK_METHOD2(Begin, void(TrackId track_id, FlowId flow_id));
-  MOCK_METHOD2(Step, void(TrackId track_id, FlowId flow_id));
-  MOCK_METHOD4(End,
-               void(TrackId track_id,
-                    FlowId flow_id,
-                    bool bind_enclosing,
-                    bool close_flow));
+               base::Optional<uint32_t>(int64_t timestamp,
+                                        TrackId track_id,
+                                        StringId cat,
+                                        StringId name,
+                                        int64_t duration,
+                                        SetArgsCallback args_callback));
 };
 
 class ProtoTraceParserTest : public ::testing::Test {
@@ -236,8 +205,6 @@
     context_.storage.reset(storage_);
     context_.track_tracker.reset(new TrackTracker(&context_));
     context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
-    context_.global_stack_profile_tracker.reset(
-        new GlobalStackProfileTracker());
     context_.args_tracker.reset(new ArgsTracker(&context_));
     context_.metadata_tracker.reset(new MetadataTracker(&context_));
     event_ = new MockEventTracker(&context_);
@@ -248,27 +215,29 @@
     context_.process_tracker.reset(process_);
     slice_ = new MockSliceTracker(&context_);
     context_.slice_tracker.reset(slice_);
-    flow_ = new MockFlowTracker(&context_);
-    context_.flow_tracker.reset(flow_);
     clock_ = new ClockTracker(&context_);
     context_.clock_tracker.reset(clock_);
     context_.sorter.reset(new TraceSorter(CreateParser(), 0 /*window size*/));
-    context_.descriptor_pool_.reset(new DescriptorPool());
 
     RegisterDefaultModules(&context_);
     RegisterAdditionalModules(&context_);
   }
 
-  void ResetTraceBuffers() { trace_.Reset(); }
+  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 = trace_.SerializeAsArray();
+    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 ProtoTraceReader(&context_));
+    context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
     auto status =
         context_.chunk_reader->Parse(std::move(raw_trace), trace_bytes.size());
 
@@ -297,13 +266,14 @@
     return std::unique_ptr<TraceParser>(new ProtoTraceParser(&context_));
   }
 
-  protozero::HeapBuffered<protos::pbzero::Trace> trace_;
+  std::unique_ptr<protozero::ScatteredHeapBuffer> heap_buf_;
+  std::unique_ptr<protozero::ScatteredStreamWriter> stream_writer_;
+  protos::pbzero::Trace trace_;
   TraceProcessorContext context_;
   MockEventTracker* event_;
   MockSchedEventTracker* sched_;
   MockProcessTracker* process_;
   MockSliceTracker* slice_;
-  MockFlowTracker* flow_;
   ClockTracker* clock_;
   TraceStorage* storage_;
 };
@@ -311,7 +281,7 @@
 // TODO(eseckler): Refactor these into a new file for ftrace tests.
 
 TEST_F(ProtoTraceParserTest, LoadSingleEvent) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
 
   auto* event = bundle->add_event();
@@ -336,7 +306,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadEventsIntoRaw) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
 
   // This event is unknown and will only appear in
@@ -383,12 +353,12 @@
   ASSERT_EQ(args.int_value()[4], 20);
   ASSERT_STREQ(args.string_value().GetString(5).c_str(), buf_value);
 
-  // TODO(hjd): Add test ftrace event with all field types
+  // TODO(taylori): Add test ftrace event with all field types
   // and test here.
 }
 
 TEST_F(ProtoTraceParserTest, LoadGenericFtrace) {
-  auto* packet = trace_->add_packet();
+  auto* packet = trace_.add_packet();
   packet->set_timestamp(100);
 
   auto* bundle = packet->set_ftrace_events();
@@ -441,7 +411,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
 
   auto* event = bundle->add_event();
@@ -484,7 +454,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadMultiplePackets) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
 
   auto* event = bundle->add_event();
@@ -502,7 +472,7 @@
   sched_switch->set_next_pid(100);
   sched_switch->set_next_prio(1024);
 
-  bundle = trace_->add_packet()->set_ftrace_events();
+  bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
 
   event = bundle->add_event();
@@ -529,7 +499,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, RepeatedLoadSinglePacket) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
   auto* event = bundle->add_event();
   event->set_timestamp(1000);
@@ -549,7 +519,7 @@
                               32, 100, base::StringView(kProcName1), 1024));
   Tokenize();
 
-  bundle = trace_->add_packet()->set_ftrace_events();
+  bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(10);
   event = bundle->add_event();
   event->set_timestamp(1001);
@@ -570,7 +540,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadCpuFreq) {
-  auto* bundle = trace_->add_packet()->set_ftrace_events();
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
   bundle->set_cpu(12);
   auto* event = bundle->add_event();
   event->set_timestamp(1000);
@@ -586,7 +556,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadMemInfo) {
-  auto* packet = trace_->add_packet();
+  auto* packet = trace_.add_packet();
   uint64_t ts = 1000;
   packet->set_timestamp(ts);
   auto* bundle = packet->set_sys_stats();
@@ -603,7 +573,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadVmStats) {
-  auto* packet = trace_->add_packet();
+  auto* packet = trace_.add_packet();
   uint64_t ts = 1000;
   packet->set_timestamp(ts);
   auto* bundle = packet->set_sys_stats();
@@ -620,7 +590,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, LoadProcessPacket) {
-  auto* tree = trace_->add_packet()->set_process_tree();
+  auto* tree = trace_.add_packet()->set_process_tree();
   auto* process = tree->add_processes();
   static const char kProcName1[] = "proc1";
 
@@ -629,13 +599,12 @@
   process->set_ppid(3);
 
   EXPECT_CALL(*process_,
-              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1),
-                                 base::StringView(kProcName1)));
+              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1)));
   Tokenize();
 }
 
 TEST_F(ProtoTraceParserTest, LoadProcessPacket_FirstCmdline) {
-  auto* tree = trace_->add_packet()->set_process_tree();
+  auto* tree = trace_.add_packet()->set_process_tree();
   auto* process = tree->add_processes();
   static const char kProcName1[] = "proc1";
   static const char kProcName2[] = "proc2";
@@ -646,13 +615,12 @@
   process->set_ppid(3);
 
   EXPECT_CALL(*process_,
-              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1),
-                                 base::StringView("proc1 proc2")));
+              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1)));
   Tokenize();
 }
 
 TEST_F(ProtoTraceParserTest, LoadThreadPacket) {
-  auto* tree = trace_->add_packet()->set_process_tree();
+  auto* tree = trace_.add_packet()->set_process_tree();
   auto* thread = tree->add_threads();
   thread->set_tid(1);
   thread->set_tgid(2);
@@ -665,7 +633,7 @@
   context_.sorter.reset(new TraceSorter(
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     auto* process_desc = packet->set_process_descriptor();
@@ -673,7 +641,7 @@
     process_desc->set_process_name("OldProcessName");
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     auto* process_desc = packet->set_process_descriptor();
@@ -681,7 +649,7 @@
     process_desc->set_process_name("NewProcessName");
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(2);
     packet->set_incremental_state_cleared(true);
     auto* process_desc = packet->set_process_descriptor();
@@ -710,7 +678,7 @@
   context_.sorter.reset(new TraceSorter(
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -721,7 +689,7 @@
     thread_desc->set_thread_name("OldThreadName");
   }
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -732,7 +700,7 @@
     thread_desc->set_thread_name("NewThreadName");
   }
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -747,16 +715,14 @@
       .WillRepeatedly(testing::Return(1u));
   EXPECT_CALL(*process_, UpdateThread(11, 15)).WillOnce(testing::Return(2u));
 
-  EXPECT_CALL(*process_, UpdateThreadNameByUtid(
-                             1u, storage_->InternString("OldThreadName"),
-                             ThreadNamePriority::kTrackDescriptor));
+  EXPECT_CALL(*process_, SetThreadNameIfUnset(
+                             1u, storage_->InternString("OldThreadName")));
   // Packet with same thread, but different name should update the name.
-  EXPECT_CALL(*process_, UpdateThreadNameByUtid(
-                             1u, storage_->InternString("NewThreadName"),
-                             ThreadNamePriority::kTrackDescriptor));
-  EXPECT_CALL(*process_, UpdateThreadNameByUtid(
-                             2u, storage_->InternString("DifferentThreadName"),
-                             ThreadNamePriority::kTrackDescriptor));
+  EXPECT_CALL(*process_, SetThreadNameIfUnset(
+                             1u, storage_->InternString("NewThreadName")));
+  EXPECT_CALL(
+      *process_,
+      SetThreadNameIfUnset(2u, storage_->InternString("DifferentThreadName")));
 
   Tokenize();
   context_.sorter->ExtractEventsForced();
@@ -767,7 +733,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -777,7 +743,7 @@
     thread_desc->set_reference_thread_time_us(2000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -788,7 +754,7 @@
     legacy_event->set_phase('B');
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -799,7 +765,7 @@
     legacy_event->set_phase('E');
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1005);
@@ -833,30 +799,27 @@
   // Only the begin thread time can be imported into the counter table.
   EXPECT_CALL(*event_, PushCounter(1005000, testing::DoubleEq(2003000),
                                    thread_time_track));
-  EXPECT_CALL(*slice_, StartSlice(1005000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_,
+              Scoped(1005000, track, kNullStringId, kNullStringId, 23000, _))
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(0u)));
   EXPECT_CALL(*event_, PushCounter(1010000, testing::DoubleEq(2005000),
                                    thread_time_track));
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(1u))));
+  EXPECT_CALL(*slice_, Begin(1010000, track, unknown_cat, kNullStringId, _))
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(2010000),
                                    thread_time_track));
   EXPECT_CALL(*slice_, End(1020000, track, unknown_cat, kNullStringId, _))
-      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(SliceId(1u))));
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
 
   context_.sorter->ExtractEventsForced();
 
-  EXPECT_EQ(storage_->thread_slice_table().id().row_map().size(), 2u);
-  auto id_0 = storage_->thread_slice_table().id().IndexOf(SliceId(0u));
-  EXPECT_TRUE(id_0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_0], 2003000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_0], 12000);
-  auto id_1 = storage_->thread_slice_table().id().IndexOf(SliceId(1u));
-  EXPECT_TRUE(id_1);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_1], 2005000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_1], 5000);
+  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) {
@@ -864,7 +827,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -874,7 +837,7 @@
     thread_desc->set_reference_thread_time_us(2000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -885,7 +848,7 @@
     legacy_event->set_name_iid(1);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -896,7 +859,7 @@
     legacy_event->set_name_iid(1);
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1015);
@@ -919,6 +882,7 @@
   MockBoundInserter inserter;
 
   StringId unknown_cat1 = storage_->InternString("unknown(1)");
+  StringId unknown_cat2 = storage_->InternString("unknown(2)");
 
   constexpr TrackId track{0u};
   constexpr TrackId thread_time_track{1u};
@@ -926,30 +890,27 @@
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
   EXPECT_CALL(*event_, PushCounter(1010000, testing::DoubleEq(2005000),
                                    thread_time_track));
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_, Begin(1010000, track, unknown_cat1, kNullStringId, _))
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(0u)));
   EXPECT_CALL(*event_, PushCounter(1015000, testing::DoubleEq(2007000),
                                    thread_time_track));
-  EXPECT_CALL(*slice_, StartSlice(1015000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(1u))));
+  EXPECT_CALL(*slice_,
+              Scoped(1015000, track, unknown_cat2, kNullStringId, 0, _))
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(1u)));
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(2010000),
                                    thread_time_track));
   EXPECT_CALL(*slice_, End(1020000, track, unknown_cat1, kNullStringId, _))
-      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(SliceId(0u))));
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(0u)));
 
   context_.sorter->ExtractEventsForced();
 
-  EXPECT_EQ(storage_->thread_slice_table().id().row_map().size(), 2u);
-  auto id_0 = storage_->thread_slice_table().id().IndexOf(SliceId(0u));
-  EXPECT_TRUE(id_0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_0], 2005000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_0], 5000);
-  auto id_1 = storage_->thread_slice_table().id().IndexOf(SliceId(1u));
-  EXPECT_TRUE(id_1);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_1], 2007000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_1], 0);
+  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) {
@@ -957,7 +918,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -968,7 +929,7 @@
     thread_desc->set_reference_thread_instruction_count(3000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -988,7 +949,7 @@
     ev1->set_name("ev1");
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1040);
@@ -1000,7 +961,7 @@
     legacy_event->set_phase('I');
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1050);
@@ -1012,7 +973,7 @@
         protos::pbzero::TrackEvent::LegacyEvent::SCOPE_PROCESS);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1024,7 +985,7 @@
     legacy_event->set_phase('E');
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1005);
@@ -1039,8 +1000,9 @@
     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_OUT);
+        protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
 
     auto* interned_data = packet->set_interned_data();
     auto cat2 = interned_data->add_event_categories();
@@ -1054,37 +1016,6 @@
     ev2->set_name("ev2");
   }
 
-  {
-    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);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1005);
-    event->add_category_iids(2);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(4);
-    legacy_event->set_phase('t');
-    legacy_event->set_unscoped_id(220);
-  }
-
-  {
-    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);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1005);
-    event->add_category_iids(2);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(4);
-    legacy_event->set_phase('f');
-    legacy_event->set_unscoped_id(330);
-    legacy_event->set_bind_to_enclosing(false);
-  }
-
   Tokenize();
 
   EXPECT_CALL(*process_, UpdateThread(16, 15))
@@ -1099,6 +1030,8 @@
   constexpr TrackId thread_instruction_count_track{2u};
   constexpr TrackId process_2_track{3u};
 
+  StringId cat_2_3 = storage_->InternString("cat2,cat3");
+  StringId ev_2 = storage_->InternString("ev2");
   StringId cat_1 = storage_->InternString("cat1");
   StringId ev_1 = storage_->InternString("ev1");
 
@@ -1110,71 +1043,56 @@
                                    thread_time_track));
   EXPECT_CALL(*event_, PushCounter(1005000, testing::DoubleEq(3010),
                                    thread_instruction_count_track));
-  EXPECT_CALL(*slice_, StartSlice(1005000, thread_1_track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
-
-  EXPECT_CALL(*flow_, Begin(_, _));
-
-  EXPECT_CALL(*flow_, Step(_, _));
-
-  EXPECT_CALL(*flow_, End(_, _, false, false));
+  EXPECT_CALL(*slice_, Scoped(1005000, thread_1_track, cat_2_3, ev_2, 23000, _))
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(0u)));
+  EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(9999u), _));
+  EXPECT_CALL(inserter, AddArg(_, _, Variadic::Boolean(true), _));
+  EXPECT_CALL(inserter, AddArg(_, _, _, _));
 
   EXPECT_CALL(*event_, PushCounter(1010000, testing::DoubleEq(2005000),
                                    thread_time_track));
   EXPECT_CALL(*event_, PushCounter(1010000, testing::DoubleEq(3020),
                                    thread_instruction_count_track));
-  EXPECT_CALL(*slice_, StartSlice(1010000, thread_1_track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(1u))));
+  EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, cat_1, ev_1, _))
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
 
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(2010000),
                                    thread_time_track));
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(3040),
                                    thread_instruction_count_track));
   EXPECT_CALL(*slice_, End(1020000, thread_1_track, cat_1, ev_1, _))
-      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(SliceId(1u))));
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
 
   EXPECT_CALL(*event_, PushCounter(1040000, testing::DoubleEq(2030000),
                                    thread_time_track));
   EXPECT_CALL(*event_, PushCounter(1040000, testing::DoubleEq(3100),
                                    thread_instruction_count_track));
-  EXPECT_CALL(*slice_, StartSlice(1040000, thread_1_track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(2u))));
+  EXPECT_CALL(*slice_, Scoped(1040000, thread_1_track, cat_1, ev_1, 0, _))
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(2u)));
 
   EXPECT_CALL(*slice_, Scoped(1050000, process_2_track, cat_1, ev_1, 0, _))
-      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(SliceId(3u))));
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(3u)));
   // Second slice should have a legacy_event.passthrough_utid arg.
   EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(1u), _));
 
   context_.sorter->ExtractEventsForced();
 
-  EXPECT_EQ(storage_->thread_slice_table().id().row_map().size(), 3u);
-  auto id_0 = storage_->thread_slice_table().id().IndexOf(SliceId(0u));
-  EXPECT_TRUE(id_0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_0], 2003000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_0], 12000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_count()[*id_0],
-            3010);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_delta()[*id_0],
-            50);
-  auto id_1 = storage_->thread_slice_table().id().IndexOf(SliceId(1u));
-  EXPECT_TRUE(id_1);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_1], 2005000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_1], 5000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_count()[*id_1],
-            3020);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_delta()[*id_1],
-            20);
-  auto id_2 = storage_->thread_slice_table().id().IndexOf(SliceId(2u));
-  EXPECT_TRUE(id_2);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_2], 2030000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_2], 0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_count()[*id_2],
-            3100);
-  EXPECT_EQ(storage_->thread_slice_table().thread_instruction_delta()[*id_2],
-            0);
+  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) {
@@ -1182,7 +1100,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -1193,7 +1111,7 @@
     thread_desc->set_reference_thread_instruction_count(3000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1215,7 +1133,7 @@
     ev1->set_name("ev1");
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1229,7 +1147,7 @@
     legacy_event->set_use_async_tts(true);
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1015);
@@ -1246,7 +1164,7 @@
   }
   {
     // Different category but same global_id -> separate track.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1018);
@@ -1262,7 +1180,7 @@
     cat2->set_name("cat2");
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_absolute_us(1030);
@@ -1297,7 +1215,7 @@
   EXPECT_CALL(*event_, PushCounter(1010000, testing::DoubleEq(3020),
                                    thread_instruction_count_track));
   EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, cat_1, ev_1, _))
-      .WillOnce(Return(SliceId(0u)));
+      .WillOnce(Return(0u));
   EXPECT_CALL(*slice_, Scoped(1015000, TrackId{1}, cat_1, ev_2, 0, _));
   EXPECT_CALL(*slice_, Scoped(1018000, TrackId{4}, cat_2, ev_2, 0, _));
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(2010000),
@@ -1305,7 +1223,7 @@
   EXPECT_CALL(*event_, PushCounter(1020000, testing::DoubleEq(3040),
                                    thread_instruction_count_track));
   EXPECT_CALL(*slice_, End(1020000, TrackId{1}, cat_1, ev_1, _))
-      .WillOnce(Return(SliceId(SliceId(0u))));
+      .WillOnce(Return(0u));
   EXPECT_CALL(*slice_, Scoped(1030000, TrackId{5}, cat_2, ev_2, 0, _));
 
   context_.sorter->ExtractEventsForced();
@@ -1323,7 +1241,7 @@
   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], SliceId(0u));
+  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],
@@ -1339,7 +1257,7 @@
 
   // Sequence 1.
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     packet->set_timestamp(1000000);
@@ -1349,12 +1267,9 @@
     auto* thread_desc = track_desc->set_thread();
     thread_desc->set_pid(15);
     thread_desc->set_tid(16);
-    auto* chrome_thread = track_desc->set_chrome_thread();
-    chrome_thread->set_thread_type(
-        protos::pbzero::ChromeThreadDescriptor::THREAD_SAMPLING_PROFILER);
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_timestamp(1000000);
     auto* track_desc = packet->set_track_descriptor();
@@ -1363,7 +1278,7 @@
   }
   {
     // Async event started on "Async track 1".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_timestamp(1010000);
     auto* event = packet->set_track_event();
@@ -1386,7 +1301,7 @@
   }
   {
     // Instant event on "Thread track 1".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_timestamp(1015000);
     auto* event = packet->set_track_event();
@@ -1407,7 +1322,7 @@
 
   // Sequence 2.
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(2);
     packet->set_incremental_state_cleared(true);
     packet->set_timestamp(1000000);
@@ -1420,7 +1335,7 @@
   }
   {
     // Async event completed on "Async track 1".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(2);
     packet->set_timestamp(1020000);
     auto* event = packet->set_track_event();
@@ -1433,7 +1348,7 @@
   }
   {
     // Instant event on "Thread track 2".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(2);
     packet->set_timestamp(1016000);
     auto* event = packet->set_track_event();
@@ -1452,16 +1367,6 @@
     ev1->set_name("ev3");
   }
 
-  EXPECT_CALL(*process_,
-              UpdateThreadNameByUtid(
-                  1u, storage_->InternString("StackSamplingProfiler"),
-                  ThreadNamePriority::kTrackDescriptorThreadType));
-  EXPECT_CALL(*process_,
-              UpdateThreadNameByUtid(2u, kNullStringId,
-                                     ThreadNamePriority::kTrackDescriptor));
-  EXPECT_CALL(*process_,
-              UpdateThreadNameByUtid(1u, kNullStringId,
-                                     ThreadNamePriority::kTrackDescriptor));
   EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
   EXPECT_CALL(*process_, UpdateThread(17, 15)).WillRepeatedly(Return(2));
 
@@ -1477,41 +1382,46 @@
 
   StringId cat_1 = storage_->InternString("cat1");
   StringId ev_1 = storage_->InternString("ev1");
+  StringId cat_2 = storage_->InternString("cat2");
+  StringId ev_2 = storage_->InternString("ev2");
+  StringId cat_3 = storage_->InternString("cat3");
+  StringId ev_3 = storage_->InternString("ev3");
 
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
 
   EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, cat_1, ev_1, _))
-      .WillOnce(Return(SliceId(2u)));
+      .WillOnce(Return(0u));
 
   EXPECT_CALL(*event_,
-              PushCounter(1015000, testing::DoubleEq(2007000), TrackId{3}));
-  EXPECT_CALL(*slice_, StartSlice(1015000, TrackId{0}, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()), Return(SliceId(0u))));
+              PushCounter(1015000, testing::DoubleEq(2007000), TrackId{4}));
+  EXPECT_CALL(*slice_, Scoped(1015000, TrackId{0}, cat_2, ev_2, 0, _))
+      .WillOnce(Return(1u));
 
   EXPECT_CALL(*event_,
-              PushCounter(1016000, testing::DoubleEq(2008000), TrackId{4}));
-  EXPECT_CALL(*slice_, StartSlice(1016000, TrackId{2}, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()), Return(SliceId(1u))));
+              PushCounter(1016000, testing::DoubleEq(2008000), TrackId{5}));
+  EXPECT_CALL(*slice_, Scoped(1016000, TrackId{3}, cat_3, ev_3, 0, _))
+      .WillOnce(Return(2u));
 
   EXPECT_CALL(*slice_,
               End(1020000, TrackId{1}, kNullStringId, kNullStringId, _))
-      .WillOnce(Return(SliceId(2u)));
+      .WillOnce(Return(0u));
 
   context_.sorter->ExtractEventsForced();
 
   // First track is "Thread track 1"; second is "Async track 1", third is global
   // default track (parent of async track), fourth is "Thread track 2", fifth &
   // sixth are thread time tracks for thread 1 and 2.
-  EXPECT_EQ(storage_->track_table().row_count(), 5u);
+  EXPECT_EQ(storage_->track_table().row_count(), 6u);
   EXPECT_EQ(storage_->track_table().name().GetString(0), "Thread track 1");
   EXPECT_EQ(storage_->track_table().name().GetString(1), "Async track 1");
-  EXPECT_EQ(storage_->track_table().name().GetString(2), "Thread track 2");
+  EXPECT_EQ(storage_->track_table().name().GetString(2), "Default Track");
+  EXPECT_EQ(storage_->track_table().name().GetString(3), "Thread track 2");
   EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
   EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
   EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
 
   EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
-  EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], SliceId(2u));
+  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],
@@ -1519,24 +1429,17 @@
   EXPECT_EQ(storage_->virtual_track_slices().thread_instruction_deltas()[0],
             20);
 
-  EXPECT_EQ(storage_->thread_slice_table().id().row_map().size(), 2u);
-  auto id_0 = storage_->thread_slice_table().id().IndexOf(SliceId(0u));
-  EXPECT_TRUE(id_0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_0], 2007000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_0], 0);
-  // There was no thread instructions in the packets above.
-  EXPECT_FALSE(
-      storage_->thread_slice_table().thread_instruction_count()[*id_0]);
-  EXPECT_FALSE(
-      storage_->thread_slice_table().thread_instruction_delta()[*id_0]);
-  auto id_1 = storage_->thread_slice_table().id().IndexOf(SliceId(1u));
-  EXPECT_TRUE(id_1);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_1], 2008000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_1], 0);
-  EXPECT_FALSE(
-      storage_->thread_slice_table().thread_instruction_count()[*id_1]);
-  EXPECT_FALSE(
-      storage_->thread_slice_table().thread_instruction_delta()[*id_1]);
+  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, TrackEventWithResortedCounterDescriptor) {
@@ -1547,7 +1450,7 @@
   // in the order they appear here, but then resorted before parsing to appear
   // after the events below.
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     packet->set_timestamp(3000);
@@ -1565,7 +1468,7 @@
     track_event_defaults->add_extra_counter_track_uuids(10);
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_timestamp(3000);
     auto* track_desc = packet->set_track_descriptor();
@@ -1582,7 +1485,7 @@
     // counter values should still be imported as counter values and as args for
     // JSON export. Should appear on default track "t1" with
     // extra_counter_values for "c1".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_sequence_flags(
         protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
@@ -1595,7 +1498,7 @@
   }
   {
     // End for "ev1".
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_timestamp(1100);
     auto* event = packet->set_track_event();
@@ -1611,21 +1514,23 @@
 
   Tokenize();
 
+  StringId cat_1 = storage_->InternString("cat1");
+  StringId ev_1 = storage_->InternString("ev1");
+
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
 
   EXPECT_CALL(*event_,
               PushCounter(1000, testing::DoubleEq(1000000), TrackId{1}));
-  EXPECT_CALL(*slice_, StartSlice(1000, TrackId{0}, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_, Begin(1000, TrackId{0}, cat_1, ev_1, _))
+      .WillOnce(Return(0u));
 
   EXPECT_CALL(*event_,
               PushCounter(1100, testing::DoubleEq(1010000), TrackId{1}));
   EXPECT_CALL(*slice_, End(1100, TrackId{0}, kNullStringId, kNullStringId, _))
-      .WillOnce(Return(SliceId(0u)));
+      .WillOnce(Return(0u));
 
   EXPECT_CALL(*process_,
-              UpdateThreadNameByUtid(1u, storage_->InternString("t1"),
-                                     ThreadNamePriority::kTrackDescriptor));
+              SetThreadNameIfUnset(1u, storage_->InternString("t1")));
 
   context_.sorter->ExtractEventsForced();
 
@@ -1635,11 +1540,10 @@
   EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
 
   // Counter values should also be imported into thread slices.
-  EXPECT_EQ(storage_->thread_slice_table().id().row_map().size(), 1u);
-  auto id_0 = storage_->thread_slice_table().id().IndexOf(SliceId(0u));
-  EXPECT_TRUE(id_0);
-  EXPECT_EQ(storage_->thread_slice_table().thread_ts()[*id_0], 1000000);
-  EXPECT_EQ(storage_->thread_slice_table().thread_dur()[*id_0], 10000);
+  EXPECT_EQ(storage_->thread_slices().slice_count(), 1u);
+  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 0u);
+  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 1000000);
+  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 10000);
 }
 
 TEST_F(ProtoTraceParserTest, TrackEventWithoutIncrementalStateReset) {
@@ -1647,7 +1551,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* thread_desc = packet->set_thread_descriptor();
     thread_desc->set_pid(15);
@@ -1658,7 +1562,7 @@
   {
     // Event should be discarded because delta timestamps require valid
     // incremental state + thread descriptor.
-    auto* packet = trace_->add_packet();
+    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.
@@ -1671,7 +1575,7 @@
   {
     // Event should be discarded because it specifies
     // SEQ_NEEDS_INCREMENTAL_STATE.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_timestamp(2000000);
     packet->set_trusted_packet_sequence_id(1);
     packet->set_sequence_flags(
@@ -1684,7 +1588,7 @@
   {
     // Event should be accepted because it does not specify
     // SEQ_NEEDS_INCREMENTAL_STATE and uses absolute timestamps.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_timestamp(2100000);
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
@@ -1699,7 +1603,7 @@
   StringId ev2 = storage_->InternString("ev2");
 
   EXPECT_CALL(*slice_, Scoped(2100000, TrackId{0}, cat1, ev2, 0, _))
-      .WillOnce(Return(SliceId(0u)));
+      .WillOnce(Return(0u));
   context_.sorter->ExtractEventsForced();
 }
 
@@ -1710,7 +1614,7 @@
   {
     // Event should be discarded because it specifies delta timestamps and no
     // thread descriptor was seen yet.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     auto* event = packet->set_track_event();
@@ -1724,7 +1628,7 @@
   {
     // Events that specify SEQ_NEEDS_INCREMENTAL_STATE should be accepted even
     // if there's no valid thread descriptor.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_timestamp(2000000);
     packet->set_trusted_packet_sequence_id(1);
     packet->set_sequence_flags(
@@ -1741,7 +1645,7 @@
   StringId ev1 = storage_->InternString("ev1");
 
   EXPECT_CALL(*slice_, Scoped(2000000, TrackId{0}, cat1, ev1, 0, _))
-      .WillOnce(Return(SliceId(0u)));
+      .WillOnce(Return(0u));
   context_.sorter->ExtractEventsForced();
 }
 
@@ -1750,7 +1654,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -1759,7 +1663,7 @@
     thread_desc->set_reference_timestamp_us(1000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1770,7 +1674,7 @@
   }
   {
     // Event should be dropped because data loss occurred before.
-    auto* packet = trace_->add_packet();
+    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();
@@ -1782,7 +1686,7 @@
   }
   {
     // Event should be dropped because incremental state is invalid.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* event = packet->set_track_event();
     event->set_timestamp_delta_us(10);
@@ -1793,7 +1697,7 @@
   }
   {
     // Event should be dropped because no new thread descriptor was seen yet.
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
     auto* event = packet->set_track_event();
@@ -1804,7 +1708,7 @@
     legacy_event->set_phase('E');
   }
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* thread_desc = packet->set_thread_descriptor();
     thread_desc->set_pid(15);
@@ -1812,7 +1716,7 @@
     thread_desc->set_reference_timestamp_us(2000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1833,7 +1737,7 @@
   StringId unknown_cat = storage_->InternString("unknown(1)");
   constexpr TrackId track{0u};
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _));
+  EXPECT_CALL(*slice_, Begin(1010000, track, unknown_cat, kNullStringId, _));
   EXPECT_CALL(*slice_, End(2010000, track, unknown_cat, kNullStringId, _));
 
   context_.sorter->ExtractEventsForced();
@@ -1844,7 +1748,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -1853,7 +1757,7 @@
     thread_desc->set_reference_timestamp_us(1000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1871,7 +1775,7 @@
     ev1->set_name("ev1");
   }
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -1880,7 +1784,7 @@
     thread_desc->set_reference_timestamp_us(995);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1898,7 +1802,7 @@
     ev2->set_name("ev2");
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1908,7 +1812,7 @@
     legacy_event->set_phase('E');
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -1941,8 +1845,8 @@
   constexpr TrackId thread_1_track{1u};
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
 
-  EXPECT_CALL(*slice_, StartSlice(1005000, thread_2_track, _, _));
-  EXPECT_CALL(*slice_, StartSlice(1010000, thread_1_track, _, _));
+  EXPECT_CALL(*slice_, Begin(1005000, thread_2_track, cat_1, ev_2, _));
+  EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, cat_1, ev_1, _));
   EXPECT_CALL(*slice_, End(1015000, thread_2_track, cat_1, ev_2, _));
   EXPECT_CALL(*slice_, End(1020000, thread_1_track, cat_1, ev_1, _));
 
@@ -1955,7 +1859,7 @@
   MockBoundInserter inserter;
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -1964,7 +1868,7 @@
     thread_desc->set_reference_timestamp_us(1000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -2016,7 +1920,7 @@
     an2->set_name("an2");
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -2105,9 +2009,8 @@
 
   constexpr TrackId track{0u};
 
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_, Begin(1010000, track, cat_1, ev_1, _))
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
   EXPECT_CALL(inserter, AddArg(debug_an_1, debug_an_1,
                                Variadic::UnsignedInteger(10u), _));
 
@@ -2124,7 +2027,7 @@
                                Variadic::Integer(23), _));
 
   EXPECT_CALL(*slice_, End(1020000, track, cat_1, ev_1, _))
-      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(SliceId(0u))));
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
 
   EXPECT_CALL(inserter,
               AddArg(debug_an_3, debug_an_3, Variadic::Integer(-3), _));
@@ -2157,7 +2060,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -2166,7 +2069,7 @@
     thread_desc->set_reference_timestamp_us(1000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -2201,15 +2104,16 @@
 
   constexpr TrackId track{0u};
 
+  StringId cat_1 = storage_->InternString("cat1");
+  StringId ev_1 = storage_->InternString("ev1");
   StringId file_1 = storage_->InternString("file1");
   StringId func_1 = storage_->InternString("func1");
 
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
 
   MockBoundInserter inserter;
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_, Begin(1010000, track, cat_1, ev_1, _))
+      .WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
   EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(file_1), _));
   EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(func_1), _));
   EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(42), _));
@@ -2222,7 +2126,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -2231,7 +2135,7 @@
     thread_desc->set_reference_timestamp_us(1000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -2273,15 +2177,16 @@
   row.upid = 1u;
   storage_->mutable_thread_table()->Insert(row);
 
+  StringId cat_1 = storage_->InternString("cat1");
+  StringId ev_1 = storage_->InternString("ev1");
   StringId body_1 = storage_->InternString("body1");
 
   constexpr TrackId track{0};
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
 
   MockBoundInserter inserter;
-  EXPECT_CALL(*slice_, StartSlice(1010000, track, _, _))
-      .WillOnce(DoAll(IgnoreResult(InvokeArgument<3>()),
-                      InvokeArgument<2>(&inserter), Return(SliceId(0u))));
+  EXPECT_CALL(*slice_, Scoped(1010000, track, cat_1, ev_1, 0, _))
+      .WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(1u)));
 
   // Call with logMessageBody (body1 in this case).
   EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(body_1), _));
@@ -2298,7 +2203,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -2308,7 +2213,7 @@
     thread_desc->set_reference_thread_time_us(2000);
   }
   {
-    auto* packet = trace_->add_packet();
+    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.
@@ -2323,7 +2228,11 @@
     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(true);
+    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);
@@ -2372,7 +2281,7 @@
   EXPECT_EQ(raw_table.utid()[0], 1u);
   EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
 
-  EXPECT_GE(storage_->arg_table().row_count(), 10u);
+  EXPECT_GE(storage_->arg_table().row_count(), 13u);
 
   EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.category"),
                      Variadic::String(cat_1)));
@@ -2394,6 +2303,13 @@
                      Variadic::UnsignedInteger(99u)));
   EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.id_scope"),
                      Variadic::String(scope_1)));
+  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, debug_an_1, Variadic::UnsignedInteger(10u)));
 }
 
@@ -2405,7 +2321,7 @@
                        {protos::pbzero::BUILTIN_CLOCK_MONOTONIC, 1000000}});
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -2414,7 +2330,7 @@
     thread_desc->set_reference_timestamp_us(1000);  // MONOTONIC.
   }
   {
-    auto* packet = trace_->add_packet();
+    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).
@@ -2434,9 +2350,10 @@
 
   constexpr TrackId track{0u};
   InSequence in_sequence;  // Below slices should be sorted by timestamp.
+  StringId unknown_cat = storage_->InternString("unknown(1)");
 
   // Timestamp should be adjusted to trace time (BOOTTIME).
-  EXPECT_CALL(*slice_, StartSlice(10000, track, _, _));
+  EXPECT_CALL(*slice_, Begin(10000, track, unknown_cat, kNullStringId, _));
 
   context_.sorter->ExtractEventsForced();
 }
@@ -2446,7 +2363,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_timestamp(1000);
     packet->set_timestamp_clock_id(3);
     packet->set_trusted_packet_sequence_id(1);
@@ -2475,7 +2392,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_timestamp(1000);
     packet->set_timestamp_clock_id(3);
     packet->set_trusted_packet_sequence_id(1);
@@ -2505,54 +2422,6 @@
                      Variadic::Integer(kIntValue)));
 }
 
-// TODO(crbug.com/1194914): Remove this test once the Chrome-side fix has
-// propagated into all release channels.
-TEST_F(ProtoTraceParserTest, ParseChromeCombinedMetadataPacket) {
-  static const char kStringName[] = "string_name";
-  static const char kStringValue[] = "string_value";
-
-  context_.sorter.reset(new TraceSorter(
-      CreateParser(), 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* chrome_metadata = packet->set_chrome_metadata();
-    chrome_metadata->set_chrome_version_code(123);
-    auto* bundle = packet->set_chrome_events();
-    auto* metadata = bundle->add_metadata();
-    metadata->set_name(kStringName);
-    metadata->set_string_value(kStringValue);
-  }
-
-  Tokenize();
-  context_.sorter->ExtractEventsForced();
-
-  // Typed metadata should be in metadata table.
-  bool found = false;
-  for (uint32_t row = 0; row < storage_->metadata_table().row_count(); row++) {
-    if (storage_->metadata_table().name()[row] ==
-        storage_->InternString("cr-playstore_version_code")) {
-      found = true;
-      EXPECT_EQ(storage_->metadata_table().int_value()[0], 123);
-    }
-  }
-  EXPECT_TRUE(found);
-
-  // Untyped metadata should be in raw table.
-  const auto& raw_table = storage_->raw_table();
-  EXPECT_EQ(raw_table.row_count(), 1u);
-  EXPECT_EQ(raw_table.name()[0],
-            storage_->InternString("chrome_event.metadata"));
-  EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
-
-  EXPECT_EQ(storage_->arg_table().row_count(), 1u);
-  EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
-                     Variadic::String(storage_->InternString(kStringValue))));
-}
-
 TEST_F(ProtoTraceParserTest, ParseChromeLegacyFtraceIntoRawTable) {
   static const char kDataPart0[] = "aaa";
   static const char kDataPart1[] = "bbb";
@@ -2562,7 +2431,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* bundle = packet->set_chrome_events();
     bundle->add_legacy_ftrace_output(kDataPart0);
@@ -2592,7 +2461,7 @@
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
   {
-    auto* packet = trace_->add_packet();
+    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();
@@ -2625,7 +2494,7 @@
   context_.sorter.reset(new TraceSorter(
       CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
 
-  auto* metadata = trace_->add_packet()->set_chrome_benchmark_metadata();
+  auto* metadata = trace_.add_packet()->set_chrome_benchmark_metadata();
   metadata->set_benchmark_name(kName);
   metadata->add_story_tags(kTag1);
   metadata->add_story_tags(kTag2);
@@ -2652,55 +2521,8 @@
                                          std::make_pair(tags, kTag2)}));
 }
 
-TEST_F(ProtoTraceParserTest, LoadChromeMetadata) {
-  context_.sorter.reset(new TraceSorter(
-      CreateParser(), std::numeric_limits<int64_t>::max() /*window size*/));
-
-  auto* track_event = trace_->add_packet()->set_chrome_events();
-  {
-    auto* metadata = track_event->add_metadata();
-    metadata->set_name("str_name");
-    metadata->set_string_value("foostr");
-  }
-
-  {
-    auto* metadata = track_event->add_metadata();
-    metadata->set_name("int_name");
-    metadata->set_int_value(42);
-  }
-
-  {
-    auto* metadata = track_event->add_metadata();
-    metadata->set_name("bool_name");
-    metadata->set_bool_value(true);
-  }
-
-  {
-    auto* metadata = track_event->add_metadata();
-    metadata->set_name("json_name");
-    metadata->set_json_value("{key: value}");
-  }
-
-  Tokenize();
-  context_.sorter->ExtractEventsForced();
-
-  const auto& metadata = storage_->metadata_table();
-
-  EXPECT_STREQ(metadata.name().GetString(0).c_str(), "cr-str_name");
-  EXPECT_STREQ(metadata.str_value().GetString(0).c_str(), "foostr");
-
-  EXPECT_STREQ(metadata.name().GetString(1).c_str(), "cr-int_name");
-  EXPECT_EQ(metadata.int_value()[1], 42);
-
-  EXPECT_STREQ(metadata.name().GetString(2).c_str(), "cr-bool_name");
-  EXPECT_EQ(metadata.int_value()[2], 1);
-
-  EXPECT_STREQ(metadata.name().GetString(3).c_str(), "cr-json_name");
-  EXPECT_STREQ(metadata.str_value().GetString(3).c_str(), "{key: value}");
-}
-
 TEST_F(ProtoTraceParserTest, AndroidPackagesList) {
-  auto* packet = trace_->add_packet();
+  auto* packet = trace_.add_packet();
   auto* pkg_list = packet->set_packages_list();
 
   pkg_list->set_read_error(false);
@@ -2752,7 +2574,7 @@
 }
 
 TEST_F(ProtoTraceParserTest, AndroidPackagesListDuplicate) {
-  auto* packet = trace_->add_packet();
+  auto* packet = trace_.add_packet();
   auto* pkg_list = packet->set_packages_list();
 
   pkg_list->set_read_error(false);
@@ -2798,7 +2620,7 @@
 
 TEST_F(ProtoTraceParserTest, ParseCPUProfileSamplesIntoTable) {
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
 
@@ -2838,7 +2660,7 @@
   }
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
 
     auto* samples = packet->set_streaming_profile_packet();
@@ -2851,7 +2673,7 @@
   }
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     auto* samples = packet->set_streaming_profile_packet();
 
@@ -2894,7 +2716,7 @@
 
 TEST_F(ProtoTraceParserTest, CPUProfileSamplesTimestampsAreClockMonotonic) {
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(0);
 
     // 1000 us monotonic == 10000 us boottime.
@@ -2908,7 +2730,7 @@
   }
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
     packet->set_incremental_state_cleared(true);
 
@@ -2939,7 +2761,7 @@
   }
 
   {
-    auto* packet = trace_->add_packet();
+    auto* packet = trace_.add_packet();
     packet->set_trusted_packet_sequence_id(1);
 
     auto* samples = packet->set_streaming_profile_packet();
@@ -2960,29 +2782,6 @@
   EXPECT_EQ(samples.utid()[0], 1u);
 }
 
-TEST_F(ProtoTraceParserTest, ConfigUuid) {
-  auto* config = trace_->add_packet()->set_trace_config();
-  config->set_trace_uuid_lsb(1);
-  config->set_trace_uuid_msb(2);
-
-  ASSERT_TRUE(Tokenize().ok());
-
-  SqlValue value =
-      context_.metadata_tracker->GetMetadataForTesting(metadata::trace_uuid);
-  EXPECT_STREQ(value.string_value, "00000000-0000-0002-0000-000000000001");
-}
-
-TEST_F(ProtoTraceParserTest, ConfigPbtxt) {
-  auto* config = trace_->add_packet()->set_trace_config();
-  config->add_buffers()->set_size_kb(42);
-
-  ASSERT_TRUE(Tokenize().ok());
-
-  SqlValue value = context_.metadata_tracker->GetMetadataForTesting(
-      metadata::trace_config_pbtxt);
-  EXPECT_THAT(value.string_value, HasSubstr("size_kb: 42"));
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_reader.cc b/src/trace_processor/importers/proto/proto_trace_reader.cc
deleted file mode 100644
index ee03db3..0000000
--- a/src/trace_processor/importers/proto/proto_trace_reader.cc
+++ /dev/null
@@ -1,456 +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_reader.h"
-
-#include <string>
-
-#include "perfetto/base/build_config.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/importers/common/clock_tracker.h"
-#include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/gzip/gzip_utils.h"
-#include "src/trace_processor/importers/proto/metadata_tracker.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/storage/stats.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/util/descriptors.h"
-
-#include "protos/perfetto/common/builtin_clock.pbzero.h"
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/extension_descriptor.pbzero.h"
-#include "protos/perfetto/trace/perfetto/tracing_service_event.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 {
-
-ProtoTraceReader::ProtoTraceReader(TraceProcessorContext* ctx)
-    : context_(ctx) {}
-ProtoTraceReader::~ProtoTraceReader() = default;
-
-util::Status ProtoTraceReader::Parse(std::unique_ptr<uint8_t[]> owned_buf,
-                                     size_t size) {
-  return tokenizer_.Tokenize(
-      std::move(owned_buf), size,
-      [this](TraceBlobView packet) { return ParsePacket(std::move(packet)); });
-}
-
-util::Status ProtoTraceReader::ParseExtensionDescriptor(ConstBytes descriptor) {
-  protos::pbzero::ExtensionDescriptor::Decoder decoder(descriptor.data,
-                                                       descriptor.size);
-
-  auto extension = decoder.extension_set();
-  return context_->descriptor_pool_->AddFromFileDescriptorSet(
-      extension.data, extension.size,
-      /*merge_existing_messages=*/true);
-}
-
-util::Status ProtoTraceReader::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.");
-  }
-
-  // Any compressed packets should have been handled by the tokenizer.
-  PERFETTO_CHECK(!decoder.has_compressed_packets());
-
-  const uint32_t seq_id = decoder.trusted_packet_sequence_id();
-  auto* state = GetIncrementalStateForPacketSequence(seq_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);
-  }
-
-  // It is important that we parse defaults before parsing other fields such as
-  // the timestamp, since the defaults could affect them.
-  if (decoder.has_trace_packet_defaults()) {
-    auto field = decoder.trace_packet_defaults();
-    const size_t offset = packet.offset_of(field.data);
-    ParseTracePacketDefaults(decoder, packet.slice(offset, field.size));
-  }
-
-  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_clock_snapshot()) {
-    return ParseClockSnapshot(decoder.clock_snapshot(),
-                              decoder.trusted_packet_sequence_id());
-  }
-
-  if (decoder.has_service_event()) {
-    PERFETTO_DCHECK(decoder.has_timestamp());
-    int64_t ts = static_cast<int64_t>(decoder.timestamp());
-    return ParseServiceEvent(ts, decoder.service_event());
-  }
-
-  if (decoder.has_extension_descriptor()) {
-    return ParseExtensionDescriptor(decoder.extension_descriptor());
-  }
-
-  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();
-    }
-  }
-
-  // Workaround a bug in the frame timeline traces which is emitting packets
-  // with zero timestamp (b/179905685).
-  // TODO(primiano): around mid-2021 there should be no traces that have this
-  // bug and we should be able to remove this workaround.
-  if (decoder.has_frame_timeline_event() && decoder.timestamp() == 0) {
-    context_->storage->IncrementStats(
-        stats::frame_timeline_event_parser_errors);
-    return util::OkStatus();
-  }
-
-  protos::pbzero::TracePacketDefaults::Decoder* defaults =
-      state->current_generation()->GetTracePacketDefaults();
-
-  int64_t timestamp;
-  if (decoder.has_timestamp()) {
-    timestamp = static_cast<int64_t>(decoder.timestamp());
-
-    uint32_t timestamp_clock_id =
-        decoder.has_timestamp_clock_id()
-            ? decoder.timestamp_clock_id()
-            : (defaults ? defaults->timestamp_clock_id() : 0);
-
-    if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
-        (!timestamp_clock_id ||
-         timestamp_clock_id == protos::pbzero::BUILTIN_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::BUILTIN_CLOCK_MONOTONIC, timestamp);
-      if (trace_ts.has_value())
-        timestamp = trace_ts.value();
-    } else if (timestamp_clock_id) {
-      // If the TracePacket specifies a non-zero clock-id, translate the
-      // timestamp into the trace-time clock domain.
-      ClockTracker::ClockId converted_clock_id = timestamp_clock_id;
-      bool is_seq_scoped =
-          ClockTracker::IsReservedSeqScopedClockId(converted_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)",
-              timestamp_clock_id);
-        }
-        converted_clock_id =
-            ClockTracker::SeqScopedClockIdToGlobal(seq_id, timestamp_clock_id);
-      }
-      auto trace_ts =
-          context_->clock_tracker->ToTraceTime(converted_clock_id, timestamp);
-      if (!trace_ts.has_value()) {
-        // ToTraceTime() will increase the |clock_sync_failure| stat on failure.
-        // We don't return an error here as it will cause the trace to stop
-        // parsing. Instead, we rely on the stat increment in ToTraceTime() to
-        // inform the user about the error.
-        return util::OkStatus();
-      }
-      timestamp = trace_ts.value();
-    }
-  } else {
-    timestamp = std::max(latest_timestamp_, context_->sorter->max_timestamp());
-  }
-  latest_timestamp_ = std::max(timestamp, latest_timestamp_);
-
-  auto& modules = context_->modules_by_field;
-  for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
-    if (!modules[field_id].empty() && decoder.Get(field_id).valid()) {
-      for (ProtoImporterModule* module : modules[field_id]) {
-        ModuleResult res = module->TokenizePacket(decoder, &packet, timestamp,
-                                                  state, field_id);
-        if (!res.ignored())
-          return res.ToStatus();
-      }
-    }
-  }
-
-  if (decoder.has_trace_config()) {
-    ParseTraceConfig(decoder.trace_config());
-  }
-
-  // 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 ProtoTraceReader::ParseTraceConfig(protozero::ConstBytes blob) {
-  protos::pbzero::TraceConfig::Decoder trace_config(blob);
-  // If we're forcing a full sort, we can keep using the INT_MAX duration set
-  // when we created the sorter.
-  const auto& cfg = context_->config;
-  if (cfg.sorting_mode == SortingMode::kForceFullSort) {
-    return;
-  }
-
-  base::Optional<int64_t> flush_period_window_size_ns;
-  if (trace_config.has_flush_period_ms() &&
-      trace_config.flush_period_ms() > 0) {
-    flush_period_window_size_ns =
-        static_cast<int64_t>(trace_config.flush_period_ms()) * 2 * 1000 * 1000;
-  }
-
-  // If we're trying to force flush period based sorting, use that as the
-  // window size if it exists.
-  if (cfg.sorting_mode == SortingMode::kForceFlushPeriodWindowedSort &&
-      flush_period_window_size_ns.has_value()) {
-    context_->sorter->SetWindowSizeNs(flush_period_window_size_ns.value());
-    return;
-  }
-
-  // If we end up here, we should use heuristics because either the sorting mode
-  // was set as such or we don't have a flush period to force the window size
-  // to.
-
-  // If we're not forcing anything 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 (trace_config.write_into_file()) {
-    int64_t window_size_ns;
-    if (flush_period_window_size_ns.has_value()) {
-      window_size_ns = flush_period_window_size_ns.value();
-    } 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);
-  }
-}
-
-void ProtoTraceReader::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();
-  for (auto& module : context_->modules) {
-    module->OnIncrementalStateCleared(
-        packet_decoder.trusted_packet_sequence_id());
-  }
-}
-
-void ProtoTraceReader::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 ProtoTraceReader::ParseTracePacketDefaults(
-    const protos::pbzero::TracePacket_Decoder& packet_decoder,
-    TraceBlobView trace_packet_defaults) {
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG(
-        "TracePacketDefaults packet without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-    return;
-  }
-
-  auto* state = GetIncrementalStateForPacketSequence(
-      packet_decoder.trusted_packet_sequence_id());
-  state->UpdateTracePacketDefaults(std::move(trace_packet_defaults));
-}
-
-void ProtoTraceReader::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 ProtoTraceReader::ParseClockSnapshot(ConstBytes blob,
-                                                  uint32_t seq_id) {
-  std::vector<ClockTracker::ClockValue> clocks;
-  protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
-  if (evt.primary_trace_clock()) {
-    context_->clock_tracker->SetTraceTimeClock(
-        static_cast<ClockTracker::ClockId>(evt.primary_trace_clock()));
-  }
-  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());
-    }
-    int64_t unit_multiplier_ns =
-        clk.unit_multiplier_ns()
-            ? static_cast<int64_t>(clk.unit_multiplier_ns())
-            : 1;
-    clocks.emplace_back(clock_id, clk.timestamp(), unit_multiplier_ns,
-                        clk.is_incremental());
-  }
-
-  uint32_t snapshot_id = context_->clock_tracker->AddSnapshot(clocks);
-
-  // Add the all the clock values to the clock snapshot table.
-  base::Optional<int64_t> trace_ts_for_check;
-  for (const auto& clock : clocks) {
-    // If the clock is incremental, we need to use 0 to map correctly to
-    // |absolute_timestamp|.
-    int64_t ts_to_convert = clock.is_incremental ? 0 : clock.absolute_timestamp;
-    base::Optional<int64_t> opt_trace_ts =
-        context_->clock_tracker->ToTraceTime(clock.clock_id, ts_to_convert);
-    if (!opt_trace_ts) {
-      // This can happen if |AddSnapshot| failed to resolve this clock. Just
-      // ignore this and move on.
-      continue;
-    }
-
-    // Double check that all the clocks in this snapshot resolve to the same
-    // trace timestamp value.
-    PERFETTO_DCHECK(!trace_ts_for_check || opt_trace_ts == trace_ts_for_check);
-    trace_ts_for_check = *opt_trace_ts;
-
-    tables::ClockSnapshotTable::Row row;
-    row.ts = *opt_trace_ts;
-    row.clock_id = static_cast<int64_t>(clock.clock_id);
-    row.clock_value = clock.absolute_timestamp;
-    row.clock_name = GetBuiltinClockNameOrNull(clock.clock_id);
-    row.snapshot_id = snapshot_id;
-
-    auto* snapshot_table = context_->storage->mutable_clock_snapshot_table();
-    snapshot_table->Insert(row);
-  }
-  return util::OkStatus();
-}
-
-base::Optional<StringId> ProtoTraceReader::GetBuiltinClockNameOrNull(
-    uint64_t clock_id) {
-  switch (clock_id) {
-    case protos::pbzero::ClockSnapshot::Clock::REALTIME:
-      return context_->storage->InternString("REALTIME");
-    case protos::pbzero::ClockSnapshot::Clock::REALTIME_COARSE:
-      return context_->storage->InternString("REALTIME_COARSE");
-    case protos::pbzero::ClockSnapshot::Clock::MONOTONIC:
-      return context_->storage->InternString("MONOTONIC");
-    case protos::pbzero::ClockSnapshot::Clock::MONOTONIC_COARSE:
-      return context_->storage->InternString("MONOTONIC_COARSE");
-    case protos::pbzero::ClockSnapshot::Clock::MONOTONIC_RAW:
-      return context_->storage->InternString("MONOTONIC_RAW");
-    case protos::pbzero::ClockSnapshot::Clock::BOOTTIME:
-      return context_->storage->InternString("BOOTTIME");
-    default:
-      return base::nullopt;
-  }
-}
-
-util::Status ProtoTraceReader::ParseServiceEvent(int64_t ts, ConstBytes blob) {
-  protos::pbzero::TracingServiceEvent::Decoder tse(blob);
-  if (tse.tracing_started()) {
-    context_->metadata_tracker->SetMetadata(metadata::tracing_started_ns,
-                                            Variadic::Integer(ts));
-  }
-  if (tse.tracing_disabled()) {
-    context_->metadata_tracker->SetMetadata(metadata::tracing_disabled_ns,
-                                            Variadic::Integer(ts));
-  }
-  if (tse.all_data_sources_started()) {
-    context_->metadata_tracker->SetMetadata(
-        metadata::all_data_source_started_ns, Variadic::Integer(ts));
-  }
-  return util::OkStatus();
-}
-
-void ProtoTraceReader::NotifyEndOfFile() {}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_reader.h b/src/trace_processor/importers/proto/proto_trace_reader.h
deleted file mode 100644
index 1adb841..0000000
--- a/src/trace_processor/importers/proto/proto_trace_reader.h
+++ /dev/null
@@ -1,104 +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_READER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_READER_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-
-namespace protozero {
-struct ConstBytes;
-}
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TracePacket_Decoder;
-class TraceConfig_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class PacketSequenceState;
-class TraceProcessorContext;
-class TraceSorter;
-class TraceStorage;
-
-// Implementation of ChunkedTraceReader for proto traces. Tokenizes a proto
-// trace into packets, handles parsing of any packets which need to be
-// handled in trace-order and passes the remainder to TraceSorter to sort
-// into timestamp order.
-class ProtoTraceReader : 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 ProtoTraceReader(TraceProcessorContext*);
-  ~ProtoTraceReader() override;
-
-  // ChunkedTraceReader implementation.
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
-  void NotifyEndOfFile() override;
-
- private:
-  using ConstBytes = protozero::ConstBytes;
-  util::Status ParsePacket(TraceBlobView);
-  util::Status ParseServiceEvent(int64_t ts, ConstBytes);
-  util::Status ParseClockSnapshot(ConstBytes blob, uint32_t seq_id);
-  void HandleIncrementalStateCleared(
-      const protos::pbzero::TracePacket_Decoder&);
-  void HandlePreviousPacketDropped(const protos::pbzero::TracePacket_Decoder&);
-  void ParseTracePacketDefaults(const protos::pbzero::TracePacket_Decoder&,
-                                TraceBlobView trace_packet_defaults);
-  void ParseInternedData(const protos::pbzero::TracePacket_Decoder&,
-                         TraceBlobView interned_data);
-  void ParseTraceConfig(ConstBytes);
-
-  base::Optional<StringId> GetBuiltinClockNameOrNull(uint64_t clock_id);
-
-  PacketSequenceState* GetIncrementalStateForPacketSequence(
-      uint32_t sequence_id) {
-    if (!incremental_state)
-      incremental_state.reset(new ProtoIncrementalState(context_));
-    return incremental_state->GetOrCreateStateForPacketSequence(sequence_id);
-  }
-  util::Status ParseExtensionDescriptor(ConstBytes descriptor);
-
-  TraceProcessorContext* context_;
-
-  ProtoTraceTokenizer tokenizer_;
-
-  // 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_READER_H_
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index fdc7bcd..da3baa5 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -16,15 +16,46 @@
 
 #include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 
+#include <string>
+
+#include "perfetto/base/build_config.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/importers/common/clock_tracker.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/ftrace/ftrace_module.h"
+#include "src/trace_processor/importers/gzip/gzip_utils.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/storage/stats.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_sorter.h"
+
+#include "protos/perfetto/common/builtin_clock.pbzero.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 {
 
-ProtoTraceTokenizer::ProtoTraceTokenizer() = default;
+using protozero::proto_utils::MakeTagLengthDelimited;
+using protozero::proto_utils::ParseVarInt;
 
-util::Status ProtoTraceTokenizer::Decompress(TraceBlobView input,
-                                             TraceBlobView* output) {
+namespace {
+
+constexpr uint8_t kTracePacketTag =
+    MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+
+TraceBlobView Decompress(GzipDecompressor* decompressor, TraceBlobView input) {
   PERFETTO_DCHECK(gzip::IsGzipSupported());
 
   uint8_t out[4096];
@@ -33,27 +64,419 @@
   data.reserve(input.length());
 
   // Ensure that the decompressor is able to cope with a new stream of data.
-  decompressor_.Reset();
-  decompressor_.SetInput(input.data(), input.length());
+  decompressor->Reset();
+  decompressor->SetInput(input.data(), input.length());
 
   using ResultCode = GzipDecompressor::ResultCode;
   for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
-    auto res = decompressor_.Decompress(out, base::ArraySize(out));
+    auto res = decompressor->Decompress(out, base::ArraySize(out));
     ret = res.ret;
     if (ret == ResultCode::kError || ret == ResultCode::kNoProgress ||
-        ret == ResultCode::kNeedsMoreInput) {
-      return util::ErrStatus("Failed to decompress (error code: %d)",
-                             static_cast<int>(ret));
-    }
+        ret == ResultCode::kNeedsMoreInput)
+      return TraceBlobView(nullptr, 0, 0);
 
     data.insert(data.end(), out, out + res.bytes_written);
   }
 
-  std::unique_ptr<uint8_t[]> out_data(new uint8_t[data.size()]);
-  memcpy(out_data.get(), data.data(), data.size());
-  *output = TraceBlobView(std::move(out_data), 0, data.size());
+  std::unique_ptr<uint8_t[]> output(new uint8_t[data.size()]);
+  memcpy(output.get(), data.data(), data.size());
+  return TraceBlobView(std::move(output), 0, data.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.");
+
+  const uint32_t seq_id = decoder.trusted_packet_sequence_id();
+  auto* state = GetIncrementalStateForPacketSequence(seq_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);
+  }
+
+  // It is important that we parse defaults before parsing other fields such as
+  // the timestamp, since the defaults could affect them.
+  if (decoder.has_trace_packet_defaults()) {
+    auto field = decoder.trace_packet_defaults();
+    const size_t offset = packet.offset_of(field.data);
+    ParseTracePacketDefaults(decoder, packet.slice(offset, field.size));
+  }
+
+  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_clock_snapshot()) {
+    return ParseClockSnapshot(decoder.clock_snapshot(),
+                              decoder.trusted_packet_sequence_id());
+  }
+
+  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();
+    }
+  }
+
+  protos::pbzero::TracePacketDefaults::Decoder* defaults =
+      state->current_generation()->GetTracePacketDefaults();
+
+  int64_t timestamp;
+  if (decoder.has_timestamp()) {
+    timestamp = static_cast<int64_t>(decoder.timestamp());
+
+    uint32_t timestamp_clock_id =
+        decoder.has_timestamp_clock_id()
+            ? decoder.timestamp_clock_id()
+            : (defaults ? defaults->timestamp_clock_id() : 0);
+
+    if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
+        (!timestamp_clock_id ||
+         timestamp_clock_id == protos::pbzero::BUILTIN_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::BUILTIN_CLOCK_MONOTONIC, timestamp);
+      if (trace_ts.has_value())
+        timestamp = trace_ts.value();
+    } else if (timestamp_clock_id) {
+      // If the TracePacket specifies a non-zero clock-id, translate the
+      // timestamp into the trace-time clock domain.
+      ClockTracker::ClockId converted_clock_id = timestamp_clock_id;
+      bool is_seq_scoped =
+          ClockTracker::IsReservedSeqScopedClockId(converted_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)",
+              timestamp_clock_id);
+        }
+        converted_clock_id =
+            ClockTracker::SeqScopedClockIdToGlobal(seq_id, timestamp_clock_id);
+      }
+      auto trace_ts =
+          context_->clock_tracker->ToTraceTime(converted_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",
+            timestamp_clock_id, seq_id, is_seq_scoped ? seq_extra_err : "");
+      }
+      timestamp = trace_ts.value();
+    }
+  } else {
+    timestamp = std::max(latest_timestamp_, context_->sorter->max_timestamp());
+  }
+  latest_timestamp_ = std::max(timestamp, latest_timestamp_);
+
+  auto& modules = context_->modules_by_field;
+  for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
+    if (modules[field_id] && decoder.Get(field_id).valid()) {
+      ModuleResult res = modules[field_id]->TokenizePacket(
+          decoder, &packet, timestamp, state, field_id);
+      if (!res.ignored())
+        return res.ToStatus();
+    }
+  }
+
+  if (decoder.has_compressed_packets()) {
+    if (!gzip::IsGzipSupported())
+      return util::Status("Cannot decode compressed packets. Zlib not enabled");
+
+    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(&decompressor_, 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();
+  context_->track_tracker->OnIncrementalStateCleared(
+      packet_decoder.trusted_packet_sequence_id());
+}
+
+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::ParseTracePacketDefaults(
+    const protos::pbzero::TracePacket_Decoder& packet_decoder,
+    TraceBlobView trace_packet_defaults) {
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG(
+        "TracePacketDefaults packet without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+    return;
+  }
+
+  auto* state = GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id());
+  state->UpdateTracePacketDefaults(std::move(trace_packet_defaults));
+}
+
+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::vector<ClockTracker::ClockValue> clocks;
+  protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
+  if (evt.primary_trace_clock()) {
+    context_->clock_tracker->SetTraceTimeClock(
+        static_cast<ClockTracker::ClockId>(evt.primary_trace_clock()));
+  }
+  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());
+    }
+    int64_t unit_multiplier_ns =
+        clk.unit_multiplier_ns()
+            ? static_cast<int64_t>(clk.unit_multiplier_ns())
+            : 1;
+    clocks.emplace_back(clock_id, clk.timestamp(), unit_multiplier_ns,
+                        clk.is_incremental());
+  }
+  context_->clock_tracker->AddSnapshot(clocks);
+  return util::OkStatus();
+}
+
+void ProtoTraceTokenizer::NotifyEndOfFile() {}
+
 }  // 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
index 76a0f42..62ddb39 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.h
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -17,173 +17,83 @@
 #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 "perfetto/protozero/proto_utils.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/importers/gzip/gzip_utils.h"
-#include "src/trace_processor/util/status_macros.h"
+#include "src/trace_processor/importers/proto/proto_incremental_state.h"
+#include "src/trace_processor/trace_blob_view.h"
 
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.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 {
+class ProtoTraceTokenizer : public ChunkedTraceReader {
  public:
-  ProtoTraceTokenizer();
+  // |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;
 
-  template <typename Callback = util::Status(TraceBlobView)>
-  util::Status Tokenize(std::unique_ptr<uint8_t[]> owned_buf,
-                        size_t size,
-                        Callback callback) {
-    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;
-      // We cannot do &partial_buf_[partial_buf_.size()] because that crashes
-      // on MSVC STL debug builds, so does &*partial_buf_.end().
-      const uint8_t* next = protozero::proto_utils::ParseVarInt(
-          ++pos, &partial_buf_.front() + partial_buf_.size(), &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.
-        RETURN_IF_ERROR(ParseInternal(std::move(buf), buf_start,
-                                      size_incl_header, callback));
-      } else {
-        partial_buf_.insert(partial_buf_.end(), data, &data[size]);
-        return util::OkStatus();
-      }
-    }
-    return ParseInternal(std::move(owned_buf), data, size, callback);
-  }
+  // ChunkedTraceReader implementation.
+  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
+  void NotifyEndOfFile() override;
 
  private:
-  static constexpr uint8_t kTracePacketTag =
-      protozero::proto_utils::MakeTagLengthDelimited(
-          protos::pbzero::Trace::kPacketFieldNumber);
-
-  template <typename Callback = util::Status(TraceBlobView)>
+  using ConstBytes = protozero::ConstBytes;
   util::Status ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
                              uint8_t* data,
-                             size_t size,
-                             Callback callback) {
-    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);
-      TraceBlobView sliced = whole_buf.slice(field_offset, packet.size);
-      RETURN_IF_ERROR(ParsePacket(std::move(sliced), callback));
-    }
-
-    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();
+                             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 ParseTracePacketDefaults(const protos::pbzero::TracePacket_Decoder&,
+                                TraceBlobView trace_packet_defaults);
+  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);
   }
 
-  template <typename Callback = util::Status(TraceBlobView)>
-  util::Status ParsePacket(TraceBlobView packet, Callback callback) {
-    protos::pbzero::TracePacket::Decoder decoder(packet.data(),
-                                                 packet.length());
-    if (decoder.has_compressed_packets()) {
-      if (!gzip::IsGzipSupported()) {
-        return util::Status(
-            "Cannot decode compressed packets. Zlib not enabled");
-      }
-
-      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(nullptr, 0, 0);
-
-      RETURN_IF_ERROR(Decompress(std::move(compressed_packets), &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 = protozero::proto_utils::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");
-
-        TraceBlobView sliced =
-            packets.slice(packet_offset, static_cast<size_t>(packet_size));
-        RETURN_IF_ERROR(ParsePacket(std::move(sliced), callback));
-      }
-      return util::OkStatus();
-    }
-    return callback(std::move(packet));
-  }
-
-  util::Status Decompress(TraceBlobView input, TraceBlobView* output);
+  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;
+
   // Allows support for compressed trace packets.
   GzipDecompressor decompressor_;
 };
diff --git a/src/trace_processor/importers/proto/stack_profile_tracker.cc b/src/trace_processor/importers/proto/stack_profile_tracker.cc
index 52e4dbd..d86ebe0 100644
--- a/src/trace_processor/importers/proto/stack_profile_tracker.cc
+++ b/src/trace_processor/importers/proto/stack_profile_tracker.cc
@@ -16,7 +16,6 @@
 
 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
 
-#include "src/trace_processor/importers/proto/profiler_util.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 #include "perfetto/base/logging.h"
@@ -25,15 +24,14 @@
 namespace perfetto {
 namespace trace_processor {
 
-SequenceStackProfileTracker::InternLookup::~InternLookup() = default;
+StackProfileTracker::InternLookup::~InternLookup() = default;
 
-SequenceStackProfileTracker::SequenceStackProfileTracker(
-    TraceProcessorContext* context)
+StackProfileTracker::StackProfileTracker(TraceProcessorContext* context)
     : context_(context), empty_(kNullStringId) {}
 
-SequenceStackProfileTracker::~SequenceStackProfileTracker() = default;
+StackProfileTracker::~StackProfileTracker() = default;
 
-StringId SequenceStackProfileTracker::GetEmptyStringId() {
+StringId StackProfileTracker::GetEmptyStringId() {
   if (empty_ == kNullStringId) {
     empty_ = context_->storage->InternString({"", 0});
   }
@@ -41,12 +39,11 @@
   return empty_;
 }
 
-void SequenceStackProfileTracker::AddString(SourceStringId id,
-                                            base::StringView str) {
+void StackProfileTracker::AddString(SourceStringId id, base::StringView str) {
   string_map_.emplace(id, str.ToStdString());
 }
 
-base::Optional<MappingId> SequenceStackProfileTracker::AddMapping(
+base::Optional<MappingId> StackProfileTracker::AddMapping(
     SourceMappingId id,
     const SourceMapping& mapping,
     const InternLookup* intern_lookup) {
@@ -70,7 +67,7 @@
   NullTermStringView raw_build_id_str =
       context_->storage->GetString(raw_build_id);
   StringId build_id = GetEmptyStringId();
-  if (!raw_build_id_str.empty()) {
+  if (raw_build_id_str.size() > 0) {
     // If the build_id is 33 characters long, we assume it's a Breakpad debug
     // identifier which is already in Hex and doesn't need conversion.
     // TODO(b/148109467): Remove workaround once all active Chrome versions
@@ -102,8 +99,7 @@
     cur_id = it->second;
   } else {
     std::vector<MappingId> db_mappings =
-        context_->global_stack_profile_tracker->FindMappingRow(row.name,
-                                                               row.build_id);
+        context_->storage->FindMappingRow(row.name, row.build_id);
     for (const MappingId preexisting_mapping : db_mappings) {
       uint32_t preexisting_row = *mappings->id().IndexOf(preexisting_mapping);
       tables::StackProfileMappingTable::Row preexisting_data{
@@ -121,8 +117,7 @@
     }
     if (!cur_id) {
       MappingId mapping_id = mappings->Insert(row).id;
-      context_->global_stack_profile_tracker->InsertMappingId(
-          row.name, row.build_id, mapping_id);
+      context_->storage->InsertMappingId(row.name, row.build_id, mapping_id);
       cur_id = mapping_id;
     }
     mapping_idx_.emplace(row, *cur_id);
@@ -131,31 +126,26 @@
   return cur_id;
 }
 
-base::Optional<FrameId> SequenceStackProfileTracker::AddFrame(
+base::Optional<FrameId> StackProfileTracker::AddFrame(
     SourceFrameId id,
     const SourceFrame& frame,
     const InternLookup* intern_lookup) {
-  base::Optional<std::string> opt_name = FindOrInsertString(
-      frame.name_id, intern_lookup, InternedStringType::kFunctionName);
-  if (!opt_name) {
+  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_DLOG("Invalid string.");
     return base::nullopt;
   }
-  const std::string& name = *opt_name;
-  const StringId str_id =
-      context_->storage->InternString(base::StringView(name));
+  const StringId& str_id = opt_str_id.value();
 
   auto opt_mapping = FindOrInsertMapping(frame.mapping_id, intern_lookup);
   if (!opt_mapping) {
     context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
+    PERFETTO_ELOG("Invalid mapping for frame %" PRIu64, id);
     return base::nullopt;
   }
   MappingId mapping_id = *opt_mapping;
-  const auto& mappings = context_->storage->stack_profile_mapping_table();
-  StringId mapping_name_id =
-      mappings.name()[*mappings.id().IndexOf(mapping_id)];
-  auto mapping_name = context_->storage->GetString(mapping_name_id);
 
   tables::StackProfileFrameTable::Row row{str_id, mapping_id,
                                           static_cast<int64_t>(frame.rel_pc)};
@@ -168,8 +158,7 @@
     cur_id = it->second;
   } else {
     std::vector<FrameId> db_frames =
-        context_->global_stack_profile_tracker->FindFrameIds(mapping_id,
-                                                             frame.rel_pc);
+        context_->storage->FindFrameIds(mapping_id, frame.rel_pc);
     for (const FrameId preexisting_frame : db_frames) {
       uint32_t preexisting_row_id = *frames->id().IndexOf(preexisting_frame);
       tables::StackProfileFrameTable::Row preexisting_row{
@@ -183,23 +172,8 @@
     }
     if (!cur_id) {
       cur_id = frames->Insert(row).id;
-      context_->global_stack_profile_tracker->InsertFrameRow(
+      context_->storage->InsertFrameRow(
           mapping_id, static_cast<uint64_t>(row.rel_pc), *cur_id);
-      if (name.find('.') != std::string::npos) {
-        // Java frames always contain a '.'
-        base::Optional<std::string> package =
-            PackageFromLocation(context_->storage.get(), mapping_name);
-        if (package) {
-          NameInPackage nip{str_id, context_->storage->InternString(
-                                        base::StringView(*package))};
-          context_->global_stack_profile_tracker->InsertJavaFrameForName(
-              nip, *cur_id);
-        } else if (mapping_name.find("/memfd:") == 0) {
-          NameInPackage nip{str_id, context_->storage->InternString("memfd")};
-          context_->global_stack_profile_tracker->InsertJavaFrameForName(
-              nip, *cur_id);
-        }
-      }
     }
     frame_idx_.emplace(row, *cur_id);
   }
@@ -207,11 +181,11 @@
   return cur_id;
 }
 
-base::Optional<CallsiteId> SequenceStackProfileTracker::AddCallstack(
+base::Optional<CallsiteId> StackProfileTracker::AddCallstack(
     SourceCallstackId id,
     const SourceCallstack& frame_ids,
     const InternLookup* intern_lookup) {
-  if (frame_ids.empty())
+  if (frame_ids.size() == 0)
     return base::nullopt;
 
   base::Optional<CallsiteId> parent_id;
@@ -219,6 +193,7 @@
     auto opt_frame_id = FindOrInsertFrame(frame_ids[depth], intern_lookup);
     if (!opt_frame_id) {
       context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
+      PERFETTO_ELOG("Unknown frame in callstack; ignoring.");
       return base::nullopt;
     }
     FrameId frame_id = *opt_frame_id;
@@ -241,7 +216,7 @@
   return parent_id;
 }
 
-FrameId SequenceStackProfileTracker::GetDatabaseFrameIdForTesting(
+FrameId StackProfileTracker::GetDatabaseFrameIdForTesting(
     SourceFrameId frame_id) {
   auto it = frame_ids_.find(frame_id);
   if (it == frame_ids_.end()) {
@@ -251,10 +226,10 @@
   return it->second;
 }
 
-base::Optional<StringId> SequenceStackProfileTracker::FindAndInternString(
+base::Optional<StringId> StackProfileTracker::FindAndInternString(
     SourceStringId id,
     const InternLookup* intern_lookup,
-    SequenceStackProfileTracker::InternedStringType type) {
+    StackProfileTracker::InternedStringType type) {
   if (id == 0)
     return GetEmptyStringId();
 
@@ -265,10 +240,10 @@
   return context_->storage->InternString(base::StringView(*opt_str));
 }
 
-base::Optional<std::string> SequenceStackProfileTracker::FindOrInsertString(
+base::Optional<std::string> StackProfileTracker::FindOrInsertString(
     SourceStringId id,
     const InternLookup* intern_lookup,
-    SequenceStackProfileTracker::InternedStringType type) {
+    StackProfileTracker::InternedStringType type) {
   if (id == 0)
     return "";
 
@@ -290,7 +265,7 @@
   return it->second;
 }
 
-base::Optional<MappingId> SequenceStackProfileTracker::FindOrInsertMapping(
+base::Optional<MappingId> StackProfileTracker::FindOrInsertMapping(
     SourceMappingId mapping_id,
     const InternLookup* intern_lookup) {
   base::Optional<MappingId> res;
@@ -304,13 +279,15 @@
       }
     }
     context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
+    PERFETTO_ELOG("Unknown mapping %" PRIu64 " : %zu", mapping_id,
+                  mapping_ids_.size());
     return res;
   }
   res = it->second;
   return res;
 }
 
-base::Optional<FrameId> SequenceStackProfileTracker::FindOrInsertFrame(
+base::Optional<FrameId> StackProfileTracker::FindOrInsertFrame(
     SourceFrameId frame_id,
     const InternLookup* intern_lookup) {
   base::Optional<FrameId> res;
@@ -332,7 +309,7 @@
   return res;
 }
 
-base::Optional<CallsiteId> SequenceStackProfileTracker::FindOrInsertCallstack(
+base::Optional<CallsiteId> StackProfileTracker::FindOrInsertCallstack(
     SourceCallstackId callstack_id,
     const InternLookup* intern_lookup) {
   base::Optional<CallsiteId> res;
@@ -352,7 +329,7 @@
   return res;
 }
 
-void SequenceStackProfileTracker::ClearIndices() {
+void StackProfileTracker::ClearIndices() {
   string_map_.clear();
   mapping_ids_.clear();
   callstack_ids_.clear();
diff --git a/src/trace_processor/importers/proto/stack_profile_tracker.h b/src/trace_processor/importers/proto/stack_profile_tracker.h
index b260b81..27ae226 100644
--- a/src/trace_processor/importers/proto/stack_profile_tracker.h
+++ b/src/trace_processor/importers/proto/stack_profile_tracker.h
@@ -25,10 +25,11 @@
 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/profiler_tables.h"
+
+namespace std {
 
 template <>
-struct std::hash<std::pair<uint32_t, int64_t>> {
+struct hash<std::pair<uint32_t, int64_t>> {
   using argument_type = std::pair<uint32_t, int64_t>;
   using result_type = size_t;
 
@@ -38,7 +39,7 @@
 };
 
 template <>
-struct std::hash<std::pair<uint32_t, perfetto::trace_processor::CallsiteId>> {
+struct hash<std::pair<uint32_t, perfetto::trace_processor::CallsiteId>> {
   using argument_type =
       std::pair<uint32_t, perfetto::trace_processor::CallsiteId>;
   using result_type = size_t;
@@ -50,7 +51,7 @@
 };
 
 template <>
-struct std::hash<std::pair<uint32_t, perfetto::trace_processor::MappingId>> {
+struct hash<std::pair<uint32_t, perfetto::trace_processor::MappingId>> {
   using argument_type =
       std::pair<uint32_t, perfetto::trace_processor::MappingId>;
   using result_type = size_t;
@@ -62,7 +63,7 @@
 };
 
 template <>
-struct std::hash<std::pair<uint32_t, perfetto::trace_processor::FrameId>> {
+struct hash<std::pair<uint32_t, perfetto::trace_processor::FrameId>> {
   using argument_type = std::pair<uint32_t, perfetto::trace_processor::FrameId>;
   using result_type = size_t;
 
@@ -73,7 +74,7 @@
 };
 
 template <>
-struct std::hash<std::vector<uint64_t>> {
+struct hash<std::vector<uint64_t>> {
   using argument_type = std::vector<uint64_t>;
   using result_type = size_t;
 
@@ -85,76 +86,15 @@
   }
 };
 
+}  // namespace std
 namespace perfetto {
 namespace trace_processor {
 
-struct NameInPackage {
-  StringId name;
-  StringId package;
-
-  bool operator<(const NameInPackage& b) const {
-    return std::tie(name, package) < std::tie(b.name, b.package);
-  }
-};
-
 class TraceProcessorContext;
 
-class GlobalStackProfileTracker {
- public:
-  std::vector<MappingId> FindMappingRow(StringId name,
-                                        StringId build_id) const {
-    auto it = stack_profile_mapping_index_.find(std::make_pair(name, build_id));
-    if (it == stack_profile_mapping_index_.end())
-      return {};
-    return it->second;
-  }
-
-  void InsertMappingId(StringId name, StringId build_id, MappingId row) {
-    auto pair = std::make_pair(name, build_id);
-    stack_profile_mapping_index_[pair].emplace_back(row);
-  }
-
-  std::vector<FrameId> FindFrameIds(MappingId mapping_row,
-                                    uint64_t rel_pc) const {
-    auto it =
-        stack_profile_frame_index_.find(std::make_pair(mapping_row, rel_pc));
-    if (it == stack_profile_frame_index_.end())
-      return {};
-    return it->second;
-  }
-
-  void InsertFrameRow(MappingId mapping_row, uint64_t rel_pc, FrameId row) {
-    auto pair = std::make_pair(mapping_row, rel_pc);
-    stack_profile_frame_index_[pair].emplace_back(row);
-  }
-
-  const std::vector<tables::StackProfileFrameTable::Id>* JavaFramesForName(
-      NameInPackage name) {
-    auto it = java_frames_for_name_.find(name);
-    if (it == java_frames_for_name_.end())
-      return nullptr;
-    return &it->second;
-  }
-
-  void InsertJavaFrameForName(NameInPackage name,
-                              tables::StackProfileFrameTable::Id id) {
-    java_frames_for_name_[name].push_back(id);
-  }
-
- private:
-  using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
-  std::map<MappingKey, std::vector<MappingId>> stack_profile_mapping_index_;
-
-  using FrameKey = std::pair<MappingId, uint64_t /* rel_pc */>;
-  std::map<FrameKey, std::vector<FrameId>> stack_profile_frame_index_;
-
-  std::map<NameInPackage, std::vector<tables::StackProfileFrameTable::Id>>
-      java_frames_for_name_;
-};
-
 // TODO(lalitm): Overhaul this class to make row vs id consistent and use
 // base::Optional instead of int64_t.
-class SequenceStackProfileTracker {
+class StackProfileTracker {
  public:
   using SourceStringId = uint64_t;
 
@@ -210,8 +150,8 @@
         SourceCallstackId) const = 0;
   };
 
-  explicit SequenceStackProfileTracker(TraceProcessorContext* context);
-  ~SequenceStackProfileTracker();
+  explicit StackProfileTracker(TraceProcessorContext* context);
+  ~StackProfileTracker();
 
   void AddString(SourceStringId, base::StringView);
   base::Optional<MappingId> AddMapping(
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 214c0fa..7b29d4d 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -19,7 +19,6 @@
 #include <set>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/traced/sys_stats_counters.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
@@ -68,11 +67,7 @@
       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")),
-      thread_time_in_state_id_(context->storage->InternString("time_in_state")),
-      thread_time_in_state_cpu_id_(
-          context_->storage->InternString("time_in_state_cpu_id")),
-      cpu_freq_id_(context_->storage->InternString("freq")) {
+      oom_score_adj_id_(context->storage->InternString("oom_score_adj")) {
   for (const auto& name : BuildMeminfoCounterNames()) {
     meminfo_strs_id_.emplace_back(context->storage->InternString(name));
   }
@@ -115,22 +110,7 @@
     // /proc/meminfo counters are in kB, convert to bytes
     TrackId track = context_->track_tracker->InternGlobalCounterTrack(
         meminfo_strs_id_[key]);
-    context_->event_tracker->PushCounter(
-        ts, static_cast<double>(mi.value()) * 1024., track);
-  }
-
-  for (auto it = sys_stats.devfreq(); it; ++it) {
-    protos::pbzero::SysStats::DevfreqValue::Decoder vm(*it);
-    auto key = static_cast<base::StringView>(vm.key());
-    // Append " Frequency" to align names with FtraceParser::ParseClockSetRate
-    base::StringView devfreq_subtitle("Frequency");
-    char counter_name[255];
-    snprintf(counter_name, sizeof(counter_name), "%.*s %.*s", int(key.size()),
-             key.data(), int(devfreq_subtitle.size()), devfreq_subtitle.data());
-    StringId name = context_->storage->InternString(counter_name);
-    TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
-    context_->event_tracker->PushCounter(ts, static_cast<double>(vm.value()),
-                                         track);
+    context_->event_tracker->PushCounter(ts, mi.value() * 1024L, track);
   }
 
   for (auto it = sys_stats.vmstat(); it; ++it) {
@@ -143,8 +123,7 @@
     }
     TrackId track =
         context_->track_tracker->InternGlobalCounterTrack(vmstat_strs_id_[key]);
-    context_->event_tracker->PushCounter(ts, static_cast<double>(vm.value()),
-                                         track);
+    context_->event_tracker->PushCounter(ts, vm.value(), track);
   }
 
   for (auto it = sys_stats.cpu_stat(); it; ++it) {
@@ -157,38 +136,31 @@
 
     TrackId track = context_->track_tracker->InternCpuCounterTrack(
         cpu_times_user_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, static_cast<double>(ct.user_ns()),
-                                         track);
+    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, static_cast<double>(ct.user_ice_ns()), track);
+    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, static_cast<double>(ct.system_mode_ns()), track);
+    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, static_cast<double>(ct.idle_ns()),
-                                         track);
+    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, static_cast<double>(ct.io_wait_ns()), track);
+    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, static_cast<double>(ct.irq_ns()),
-                                         track);
+    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, static_cast<double>(ct.softirq_ns()), track);
+    context_->event_tracker->PushCounter(ts, ct.softirq_ns(), track);
   }
 
   for (auto it = sys_stats.num_irq(); it; ++it) {
@@ -196,8 +168,7 @@
 
     TrackId track = context_->track_tracker->InternIrqCounterTrack(
         num_irq_name_id_, ic.irq());
-    context_->event_tracker->PushCounter(ts, static_cast<double>(ic.count()),
-                                         track);
+    context_->event_tracker->PushCounter(ts, ic.count(), track);
   }
 
   for (auto it = sys_stats.num_softirq(); it; ++it) {
@@ -205,29 +176,26 @@
 
     TrackId track = context_->track_tracker->InternSoftirqCounterTrack(
         num_softirq_name_id_, ic.irq());
-    context_->event_tracker->PushCounter(ts, static_cast<double>(ic.count()),
-                                         track);
+    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, static_cast<double>(sys_stats.num_forks()), track);
+    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, static_cast<double>(sys_stats.num_irq_total()), track);
+    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, static_cast<double>(sys_stats.num_softirq_total()), track);
+    context_->event_tracker->PushCounter(ts, sys_stats.num_softirq_total(),
+                                         track);
   }
 }
 
@@ -244,24 +212,14 @@
     // 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, base::StringView());
+      context_->process_tracker->SetProcessMetadata(kKthreaddPid, base::nullopt,
+                                                    kKthreaddName);
       context_->process_tracker->UpdateThread(pid, kKthreaddPid);
     } else {
-      auto raw_cmdline = proc.cmdline();
-      base::StringView argv0 = raw_cmdline ? *raw_cmdline : base::StringView();
-
-      std::string cmdline_str;
-      for (auto cmdline_it = raw_cmdline; cmdline_it;) {
-        auto cmdline_part = *cmdline_it;
-        cmdline_str.append(cmdline_part.data, cmdline_part.size);
-
-        if (++cmdline_it)
-          cmdline_str.append(" ");
-      }
-      base::StringView cmdline = base::StringView(cmdline_str);
-      UniquePid upid = context_->process_tracker->SetProcessMetadata(
-          pid, ppid, argv0, cmdline);
+      auto args = proc.cmdline();
+      base::StringView argv0 = args ? *args : base::StringView();
+      UniquePid upid =
+          context_->process_tracker->SetProcessMetadata(pid, ppid, argv0);
       if (proc.has_uid()) {
         context_->process_tracker->SetProcessUid(
             upid, static_cast<uint32_t>(proc.uid()));
@@ -277,14 +235,12 @@
 
     if (thd.has_name()) {
       StringId thread_name_id = context_->storage->InternString(thd.name());
-      context_->process_tracker->UpdateThreadName(
-          tid, thread_name_id, ThreadNamePriority::kProcessTree);
+      context_->process_tracker->UpdateThreadName(tid, thread_name_id);
     }
   }
 }
 
 void SystemProbesParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
-  using Process = protos::pbzero::ProcessStats::Process;
   protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
   const auto kOomScoreAdjFieldNumber =
       protos::pbzero::ProcessStats::Process::kOomScoreAdjFieldNumber;
@@ -304,7 +260,7 @@
       if (fld.id() ==
           protos::pbzero::ProcessStats::Process::kThreadsFieldNumber) {
         if (PERFETTO_UNLIKELY(ms_per_tick_ == 0 ||
-                              thread_time_in_state_cpus_.empty())) {
+                              thread_time_in_state_cpu_str_ids_.empty())) {
           context_->storage->IncrementStats(
               stats::thread_time_in_state_out_of_order);
           continue;
@@ -322,33 +278,23 @@
                                        : fld.as_int64() * 1024;
         has_counter[fld.id()] = true;
       } else {
-        // Chrome fields are processed by ChromeSystemProbesParser.
-        if (fld.id() == Process::kIsPeakRssResettableFieldNumber ||
-            fld.id() == Process::kChromePrivateFootprintKbFieldNumber ||
-            fld.id() == Process::kChromePrivateFootprintKbFieldNumber) {
-          continue;
-        }
         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] || field_id ==
-                                        protos::pbzero::ProcessStats::Process::
-                                            kIsPeakRssResettableFieldNumber) {
+      if (!has_counter[field_id])
         continue;
-      }
 
       // Lookup the interned string id from the field name using the
       // pre-cached |proc_stats_process_names_| map.
-      const StringId& name = proc_stats_process_names_[field_id];
+      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);
-      int64_t value = counter_values[field_id];
-      context_->event_tracker->PushCounter(ts, static_cast<double>(value),
-                                           track);
+      context_->event_tracker->PushCounter(ts, value, track);
     }
   }
 }
@@ -359,10 +305,9 @@
   protos::pbzero::ProcessStats::Thread::Decoder stats(blob.data, blob.size);
   UniqueTid utid = context_->process_tracker->UpdateThread(
       static_cast<uint32_t>(stats.tid()), pid);
-  TrackId track_id = context_->track_tracker->InternThreadCounterTrack(
-      thread_time_in_state_id_, utid);
+  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
 
-  std::vector<uint64_t> ticks(thread_time_in_state_cpu_freqs_.size());
+  std::vector<uint64_t> ticks(thread_time_in_state_cpu_freq_ids_.size());
   auto index_it = stats.cpu_freq_indices();
   auto tick_it = stats.cpu_freq_ticks();
   for (; index_it && tick_it; index_it++, tick_it++) {
@@ -376,22 +321,21 @@
   }
 
   for (uint32_t cpu : thread_time_in_state_cpus_) {
-    size_t start = thread_time_in_state_freq_index_[cpu];
-    size_t end = thread_time_in_state_freq_index_[cpu + 1];
-    for (size_t freq_index = start; freq_index < end; freq_index++) {
-      if (stats.cpu_freq_full() || ticks[freq_index] > 0) {
-        context_->event_tracker->PushCounter(
-            ts, static_cast<double>(ticks[freq_index] * ms_per_tick_), track_id,
-            [cpu, freq_index, this](ArgsTracker::BoundInserter* args_table) {
-              args_table->AddArg(thread_time_in_state_cpu_id_,
-                                 Variadic::UnsignedInteger(cpu));
+    StringId cpu_str_id = thread_time_in_state_cpu_str_ids_[cpu];
+    context_->slice_tracker->Scoped(
+        ts, track_id, kNullStringId, cpu_str_id,
+        /* duration */ 0,
+        [&stats, &ticks, &cpu, this](ArgsTracker::BoundInserter* args_table) {
+          size_t start = thread_time_in_state_freq_index_[cpu];
+          size_t end = thread_time_in_state_freq_index_[cpu + 1];
+          for (size_t freq_index = start; freq_index < end; freq_index++) {
+            if (stats.cpu_freq_full() || ticks[freq_index] > 0) {
               args_table->AddArg(
-                  cpu_freq_id_,
-                  Variadic::UnsignedInteger(
-                      thread_time_in_state_cpu_freqs_[freq_index]));
-            });
-      }
-    }
+                  thread_time_in_state_cpu_freq_ids_[freq_index],
+                  Variadic::UnsignedInteger(ticks[freq_index] * ms_per_tick_));
+            }
+          }
+        });
   }
 }
 
@@ -403,19 +347,14 @@
                                              utsname_blob.size);
     base::StringView machine = utsname.machine();
     SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
-    if (machine == "aarch64") {
+    if (machine == "aarch64" || machine == "armv8l") {
       syscall_tracker->SetArchitecture(kAarch64);
-    } else if (machine == "armv8l") {
-      syscall_tracker->SetArchitecture(kArmEabi);
-    } else if (machine == "armv7l") {
-      syscall_tracker->SetArchitecture(kAarch32);
     } else if (machine == "x86_64") {
       syscall_tracker->SetArchitecture(kX86_64);
     } else if (machine == "i686") {
       syscall_tracker->SetArchitecture(kX86);
     } else {
-      PERFETTO_ELOG("Unknown architecture %s. Syscall traces will not work.",
-                    machine.ToStdString().c_str());
+      PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
     }
 
     SystemInfoTracker* system_info_tracker =
@@ -454,10 +393,9 @@
 }
 
 void SystemProbesParser::ParseCpuInfo(ConstBytes blob) {
-  // invalid_freq is used as the guard in thread_time_in_state_cpu_freq_ids_,
-  // see IsValidCpuFreqIndex.
-  uint32_t invalid_freq = 0;
-  thread_time_in_state_cpu_freqs_.push_back(invalid_freq);
+  // Frequency index 0 is invalid.
+  StringId invalid_str_id = context_->storage->InternString("invalid");
+  thread_time_in_state_cpu_freq_ids_.push_back(invalid_str_id);
 
   protos::pbzero::CpuInfo::Decoder packet(blob.data, blob.size);
   uint32_t cpu_index = 0;
@@ -466,6 +404,10 @@
   std::vector<uint32_t> last_cpu_freqs;
   for (auto it = packet.cpus(); it; it++) {
     thread_time_in_state_freq_index_.push_back(freq_index);
+    std::string cpu_string = "time_in_state.cpu" + std::to_string(cpu_index);
+    base::StringView cpu_string_view(cpu_string);
+    thread_time_in_state_cpu_str_ids_.push_back(
+        context_->storage->InternString(cpu_string_view));
 
     protos::pbzero::CpuInfo::Cpu::Decoder cpu(*it);
     tables::CpuTable::Row cpu_row;
@@ -489,19 +431,25 @@
       cpu_freq_row.cpu_id = cpu_row_id;
       cpu_freq_row.freq = freq;
       context_->storage->mutable_cpu_freq_table()->Insert(cpu_freq_row);
-      thread_time_in_state_cpu_freqs_.push_back(freq);
+      std::string freq_string = std::to_string(freq);
+      base::StringView freq_string_view(freq_string);
+      thread_time_in_state_cpu_freq_ids_.push_back(
+          context_->storage->InternString(freq_string_view));
       freq_index++;
     }
 
     cpu_index++;
   }
   thread_time_in_state_freq_index_.push_back(freq_index);
-  thread_time_in_state_cpu_freqs_.push_back(invalid_freq);
+
+  thread_time_in_state_cpu_str_ids_.push_back(invalid_str_id);
+  thread_time_in_state_cpu_freq_ids_.push_back(invalid_str_id);
 }
 
 bool SystemProbesParser::IsValidCpuFreqIndex(uint32_t freq_index) const {
   // Frequency index 0 is invalid.
-  return freq_index > 0 && freq_index < thread_time_in_state_cpu_freqs_.size();
+  return freq_index > 0 &&
+         freq_index < thread_time_in_state_cpu_freq_ids_.size();
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/system_probes_parser.h b/src/trace_processor/importers/proto/system_probes_parser.h
index c9f66c0..a304034 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.h
+++ b/src/trace_processor/importers/proto/system_probes_parser.h
@@ -17,7 +17,6 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_PARSER_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_PARSER_H_
 
-#include <array>
 #include <set>
 #include <vector>
 
@@ -61,25 +60,24 @@
   const StringId cpu_times_irq_ns_id_;
   const StringId cpu_times_softirq_ns_id_;
   const StringId oom_score_adj_id_;
-  const StringId thread_time_in_state_id_;
-  const StringId thread_time_in_state_cpu_id_;
-  const StringId cpu_freq_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. Also update the value in
-  // ChromeSystemProbesParser.
-  static constexpr size_t kProcStatsProcessSize = 15;
+  // id of ProcessStats::Process.
+  static constexpr size_t kProcStatsProcessSize = 11;
   std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
 
   uint64_t ms_per_tick_ = 0;
 
-  // Maps CPU frequency indices to frequencies from the cpu_freq table to be
-  // stored in the args table as a dimension of the time_in_state counter.
-  // Includes guards at both ends.
-  std::vector<uint32_t> thread_time_in_state_cpu_freqs_;
+  // Maps CPU indices to CPU strings: time_in_state.cpuN.
+  // Includes a guard at the end.
+  std::vector<StringId> thread_time_in_state_cpu_str_ids_;
+
+  // Maps CPU frequency indices to frequency strings for the args table.
+  // Includes a guard at the end.
+  std::vector<StringId> thread_time_in_state_cpu_freq_ids_;
 
   // thread_time_in_state_freq_index_[cpu] points to the first frequency for
   // cpu in thread_time_in_state_cpu_freq_ids_. Includes a guard at the end.
diff --git a/src/trace_processor/importers/proto/track_event.descriptor.h b/src/trace_processor/importers/proto/track_event.descriptor.h
index 47ab150..3a2143c 100644
--- a/src/trace_processor/importers/proto/track_event.descriptor.h
+++ b/src/trace_processor/importers/proto/track_event.descriptor.h
@@ -25,16 +25,16 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// e5c244903aa00cad06faf3d126918306a7fe811e
+// 3df80477da2ea38cc659967487b37051a154bb69
 // SHA1(protos/perfetto/trace/track_event/track_event.proto)
-// 0c3776094b678fe0d7981a20564efbc002e321d9
+// f591683d79fb6881014e72c0a55379bbcfde4b63
 
 // This is the proto TrackEvent encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 21868> kTrackEventDescriptor{
+constexpr std::array<uint8_t, 18185> kTrackEventDescriptor{
     {0x0a, 0x96, 0x08, 0x0a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
      0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
@@ -151,1272 +151,1106 @@
      0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x73, 0x74,
      0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x69, 0x69, 0x64, 0x18,
      0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x74, 0x65,
-     0x64, 0x46, 0x72, 0x6f, 0x6d, 0x49, 0x69, 0x64, 0x0a, 0xdb, 0x03, 0x0a,
-     0x45, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x64, 0x46, 0x72, 0x6f, 0x6d, 0x49, 0x69, 0x64, 0x0a, 0xd2, 0x01, 0x0a,
+     0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f,
-     0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0x80, 0x03, 0x0a, 0x1a, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
-     0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x6f,
-     0x0a, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
-     0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x0e, 0x32, 0x42, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
-     0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,
-     0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x10, 0x61,
-     0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x22, 0xf0, 0x01, 0x0a, 0x16, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
-     0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50,
-     0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54,
-     0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
-     0x00, 0x12, 0x2c, 0x0a, 0x28, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41,
-     0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x48,
-     0x41, 0x53, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x5f, 0x41,
-     0x43, 0x54, 0x49, 0x56, 0x49, 0x54, 0x49, 0x45, 0x53, 0x10, 0x01, 0x12,
-     0x2b, 0x0a, 0x27, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49,
-     0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x48, 0x41, 0x53,
-     0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49,
-     0x56, 0x49, 0x54, 0x49, 0x45, 0x53, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28,
-     0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
-     0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x48, 0x41, 0x53, 0x5f, 0x53, 0x54,
-     0x4f, 0x50, 0x50, 0x45, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x49,
-     0x54, 0x49, 0x45, 0x53, 0x10, 0x03, 0x12, 0x2e, 0x0a, 0x2a, 0x41, 0x50,
-     0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54,
-     0x41, 0x54, 0x45, 0x5f, 0x48, 0x41, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x54,
-     0x52, 0x4f, 0x59, 0x45, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x49,
-     0x54, 0x49, 0x45, 0x53, 0x10, 0x04, 0x0a, 0xd2, 0x01, 0x0a, 0x37, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61,
-     0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75,
-     0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
-     0x85, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69,
-     0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64,
-     0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
-     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c,
-     0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e,
-     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
-     0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69,
-     0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d,
-     0x62, 0x65, 0x72, 0x0a, 0xb5, 0x4d, 0x0a, 0x49, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f,
-     0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74,
-     0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e,
-     0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
-     0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
-     0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65,
-     0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x52,
-     0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x63, 0x68,
-     0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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,
-     0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x0c, 0x73, 0x74,
-     0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x3f,
-     0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f,
-     0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42,
-     0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75,
-     0x72, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x1e, 0x62, 0x65, 0x67, 0x69, 0x6e,
-     0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
-     0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x61, 0x73,
-     0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x62, 0x65, 0x67,
-     0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44,
-     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12,
-     0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62,
-     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74,
-     0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x70,
-     0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x5b, 0x0a, 0x2b,
-     0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65,
-     0x64, 0x5f, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x5f, 0x64,
-     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x26, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61,
-     0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65,
-     0x64, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x44, 0x65, 0x61,
-     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x73, 0x6b, 0x69,
-     0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
-     0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63,
-     0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x1f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64,
-     0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52,
-     0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79,
-     0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x61,
-     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32,
-     0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03,
+     0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69,
+     0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66,
+     0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66,
+     0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63,
+     0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
+     0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x4e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x0a, 0xb5, 0x4d, 0x0a, 0x49, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+     0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f,
+     0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+     0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f,
+     0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
+     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x22, 0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
      0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63,
-     0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f,
-     0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x41, 0x63, 0x74,
-     0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a, 0x0d, 0x64, 0x65, 0x61, 0x64, 0x6c,
-     0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01,
-     0x28, 0x0e, 0x32, 0x4a, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
-     0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70,
-     0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69,
-     0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x61, 0x64,
-     0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
-     0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18,
-     0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c,
-     0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x65, 0x61,
-     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
-     0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
-     0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74,
-     0x55, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f, 0x75, 0x73,
-     0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x55,
-     0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f,
-     0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
-     0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69,
-     0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x4e, 0x0a,
-     0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64,
-     0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
-     0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
-     0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1f, 0x6e, 0x6f,
-     0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53,
-     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x44, 0x65,
-     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x62, 0x65, 0x67,
+     0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61,
+     0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x2d, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x0c,
+     0x73, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
+     0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e,
+     0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e,
+     0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x1e, 0x62, 0x65, 0x67,
      0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
-     0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67,
-     0x73, 0x52, 0x12, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x65, 0x0a,
-     0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74,
-     0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x52, 0x17, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
-     0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x62, 0x65, 0x67, 0x69,
-     0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72,
-     0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x15, 0x62, 0x65, 0x67, 0x69,
-     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x19, 0x63, 0x6f, 0x6d,
-     0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x69,
-     0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x11,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
-     0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d,
-     0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x17,
-     0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69,
-     0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22,
-     0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70,
-     0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69,
-     0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x45,
-     0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f,
-     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e,
-     0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
-     0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e,
-     0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44,
-     0x49, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45,
-     0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f,
-     0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x03, 0x12, 0x16, 0x0a,
-     0x12, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f,
-     0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12, 0x19, 0x0a,
-     0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f,
-     0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x05,
-     0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43,
-     0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x59, 0x0a,
-     0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 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, 0x6d, 0x70, 0x6f,
-     0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61,
-     0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x6f,
-     0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x65, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x74,
+     0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x61, 0x73,
+     0x6b, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+     0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x5b,
+     0x0a, 0x2b, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61,
+     0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x73,
+     0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64,
+     0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x26, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64,
+     0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x69, 0x73,
+     0x73, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x44,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x73,
+     0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64,
+     0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x73, 0x6b, 0x69, 0x70, 0x70,
+     0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54,
+     0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e,
+     0x63, 0x79, 0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65,
+     0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28,
+     0x0e, 0x32, 0x30, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
-     0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
-     0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a,
-     0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61,
-     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
-     0x30, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63,
-     0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f,
-     0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f,
-     0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
-     0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c,
-     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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61,
-     0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49,
-     0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
-     0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c,
-     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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61,
-     0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d,
-     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
-     0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
-     0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0e, 0x32, 0x50, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
-     0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
-     0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x52, 0x17, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65,
-     0x64, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61,
-     0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53, 0x2e, 0x70,
+     0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x41,
+     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a, 0x0d, 0x64, 0x65, 0x61,
+     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x4a, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+     0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
+     0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65,
+     0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1f,
+     0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75,
+     0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61,
+     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x64,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65,
+     0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18,
+     0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x65, 0x61, 0x64, 0x6c,
+     0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64,
+     0x41, 0x74, 0x55, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f,
+     0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f,
+     0x77, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e, 0x6f, 0x77, 0x5f, 0x74,
+     0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+     0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+     0x4e, 0x0a, 0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65,
+     0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64,
+     0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74,
+     0x61, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1f,
+     0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+     0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74,
+     0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67,
+     0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+     0x72, 0x67, 0x73, 0x52, 0x12, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d,
+     0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12,
+     0x65, 0x0a, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
+     0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
+     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x10,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75,
+     0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x15, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x19, 0x63,
+     0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x69,
+     0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
+     0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54,
+     0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
+     0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+     0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72,
+     0x79, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
+     0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19,
+     0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44,
+     0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+     0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c,
+     0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e,
+     0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x41, 0x44, 0x4c,
+     0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4d, 0x4d,
+     0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15,
+     0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44,
+     0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x03, 0x12,
+     0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
+     0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12,
+     0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
+     0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
+     0x10, 0x05, 0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
+     0x59, 0x0a, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 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, 0x6d,
      0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
      0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f,
-     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65,
-     0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d,
-     0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x11, 0x66,
-     0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49,
-     0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
-     0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
-     0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
-     0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49,
-     0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x42, 0x45, 0x47,
-     0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d,
-     0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x42, 0x45, 0x47,
-     0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x24,
-     0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c,
-     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44,
-     0x45, 0x5f, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x03,
-     0x22, 0x93, 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61,
-     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
-     0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41,
-     0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53,
-     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19,
-     0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
-     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10,
-     0x01, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d,
-     0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x45,
-     0x4e, 0x54, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49,
-     0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
-     0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x4f,
-     0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x22, 0xf4, 0x01, 0x0a, 0x17, 0x4c,
-     0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
-     0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
-     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
-     0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46,
-     0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12,
-     0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45,
-     0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49,
-     0x56, 0x45, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x41, 0x59, 0x45,
-     0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
-     0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12,
-     0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45,
-     0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54,
-     0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53,
-     0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x31,
-     0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
-     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49,
-     0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54,
-     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
-     0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64,
-     0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65,
-     0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19,
-     0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41,
-     0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
-     0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, 0x43, 0x45,
-     0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x44, 0x4c,
-     0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x4f, 0x52, 0x43, 0x45,
-     0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49,
-     0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4d,
-     0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x46, 0x4f, 0x52,
-     0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
-     0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x41,
-     0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12,
-     0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45,
-     0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47,
-     0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x10, 0x04, 0x1a,
-     0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
-     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
-     0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65,
-     0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x75, 0x72,
-     0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d,
-     0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x22, 0x6c, 0x61, 0x73, 0x74, 0x5f,
-     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
-     0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x66,
-     0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
-     0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75,
-     0x6d, 0x62, 0x65, 0x72, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x65,
-     0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x20, 0x6c,
-     0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75,
-     0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x70, 0x65,
-     0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
-     0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x72, 0x61, 0x77, 0x50, 0x65,
-     0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x52, 0x0a, 0x27, 0x6c,
-     0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75,
-     0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
-     0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65,
-     0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x6c, 0x61,
-     0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
-     0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72,
-     0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64,
-     0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x06, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x07, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x12, 0x59,
-     0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62,
-     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
-     0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72,
-     0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x24, 0x64, 0x69, 0x64, 0x53, 0x65, 0x6e, 0x64,
-     0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x2e, 0x64, 0x69, 0x64,
-     0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69,
-     0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65,
-     0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x27, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79,
-     0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65,
-     0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x5d, 0x0a, 0x2d, 0x64, 0x69,
-     0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67,
-     0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
-     0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x26, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79,
-     0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65,
-     0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x23, 0x77, 0x61, 0x6e,
-     0x74, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
-     0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
-     0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x1e, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e,
-     0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x35,
-     0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
-     0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64,
-     0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x64, 0x69, 0x64,
-     0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f,
-     0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x0c, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x1f, 0x64, 0x69, 0x64, 0x49, 0x6e, 0x76, 0x61,
-     0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54,
-     0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b,
-     0x12, 0x48, 0x0a, 0x21, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x66,
-     0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64,
-     0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f,
-     0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x64, 0x69, 0x64,
-     0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6d, 0x70, 0x6c, 0x53,
-     0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69,
-     0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x72,
-     0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18,
-     0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x64, 0x50, 0x72,
-     0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4e,
-     0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76,
-     0x65, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61,
-     0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-     0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x63, 0x6f, 0x6e,
-     0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x43, 0x68, 0x65, 0x63,
-     0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x6e, 0x69, 0x6d,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65,
-     0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x13, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x75,
-     0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x63,
-     0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61,
-     0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x75, 0x72,
-     0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74,
-     0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69,
-     0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x29, 0x73, 0x75,
-     0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x57, 0x69,
-     0x74, 0x68, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x61, 0x79,
-     0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
-     0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73,
-     0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x18, 0x12, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65, 0x64, 0x72,
-     0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f,
-     0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65,
-     0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e, 0x65, 0x65,
-     0x64, 0x73, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c,
-     0x65, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f,
-     0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13,
-     0x6e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61,
-     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6e,
-     0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f, 0x6e, 0x65, 0x5f, 0x62, 0x65, 0x67,
-     0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6e, 0x65, 0x65,
-     0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d,
-     0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76,
-     0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x39, 0x0a,
-     0x19, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x75, 0x73,
-     0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x62, 0x65,
-     0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72,
-     0x63, 0x65, 0x50, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08,
-     0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x18, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x07, 0x63, 0x61, 0x6e, 0x44, 0x72, 0x61, 0x77, 0x12,
-     0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c,
-     0x65, 0x73, 0x73, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x19, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-     0x6c, 0x65, 0x73, 0x73, 0x44, 0x72, 0x61, 0x77, 0x12, 0x28, 0x0a, 0x10,
-     0x68, 0x61, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
-     0x74, 0x72, 0x65, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e,
-     0x68, 0x61, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72,
-     0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
-     0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65,
-     0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69,
-     0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
-     0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x41,
-     0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a,
-     0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65,
-     0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74,
-     0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x18, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4e,
-     0x65, 0x65, 0x64, 0x73, 0x46, 0x69, 0x72, 0x73, 0x74, 0x44, 0x72, 0x61,
-     0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f,
-     0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64,
-     0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x1d, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54,
-     0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f,
-     0x44, 0x72, 0x61, 0x77, 0x12, 0x6c, 0x0a, 0x35, 0x64, 0x69, 0x64, 0x5f,
-     0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69,
-     0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x69,
-     0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72,
-     0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e,
-     0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x2d, 0x64, 0x69, 0x64,
-     0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x49, 0x6e, 0x69,
-     0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74,
-     0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x6a, 0x0a, 0x0d, 0x74, 0x72,
-     0x65, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18,
-     0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 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, 0x6d, 0x70, 0x6f, 0x73,
-     0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
-     0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f,
-     0x72, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x65, 0x50, 0x72,
-     0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x7d, 0x0a, 0x14, 0x73, 0x63,
-     0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0e,
-     0x32, 0x4b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x61, 0x6a, 0x6f,
+     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x69,
+     0x6e, 0x6f, 0x72, 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, 0x43, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+     0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
+     0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x1a, 0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74,
+     0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x0e, 0x32, 0x30, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+     0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x41, 0x63, 0x74,
+     0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x4c, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
      0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
-     0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53,
-     0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x12, 0x73, 0x63, 0x72, 0x6f, 0x6c,
-     0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
-     0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63,
-     0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x61,
-     0x73, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x63, 0x72,
-     0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
-     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x41, 0x63,
-     0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x73, 0x46, 0x61, 0x73, 0x74,
-     0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72,
-     0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x6c,
-     0x61, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
-     0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x6d, 0x61, 0x69, 0x6e,
-     0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64,
-     0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
-     0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x78,
-     0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65,
-     0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79,
-     0x18, 0x23, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x73, 0x6b, 0x69, 0x70,
-     0x4e, 0x65, 0x78, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69,
-     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75,
-     0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a,
-     0x18, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73,
-     0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x76, 0x69, 0x64,
-     0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x65,
-     0x66, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
-     0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x13, 0x64, 0x65, 0x66, 0x65, 0x72, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
-     0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
-     0x69, 0x74, 0x5f, 0x68, 0x61, 0x64, 0x5f, 0x6e, 0x6f, 0x5f, 0x75, 0x70,
-     0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x16, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48,
-     0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12,
-     0x32, 0x0a, 0x16, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f,
-     0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x18, 0x27, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x69, 0x64,
-     0x44, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72,
-     0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x18, 0x64, 0x69, 0x64, 0x5f, 0x73,
-     0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73,
-     0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
-     0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
-     0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x69, 0x6d, 0x70,
-     0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c,
-     0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x29, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x19, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x49, 0x6d, 0x70, 0x6c,
-     0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
-     0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x63, 0x75, 0x72, 0x72,
-     0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
-     0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c,
-     0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x6e, 0x64,
-     0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x49, 0x6d, 0x70,
-     0x6c, 0x53, 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x23, 0x70, 0x72, 0x65,
-     0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
-     0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x69,
-     0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2b, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x1e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73,
-     0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x57,
-     0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12, 0x5f,
-     0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
-     0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77,
-     0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f,
-     0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18,
-     0x2c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x28, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f,
-     0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12,
-     0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
-     0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
-     0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72,
-     0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65,
-     0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x29, 0x70, 0x72, 0x6f,
+     0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x4c, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
+     0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b, 0x6c, 0x61, 0x79, 0x65,
+     0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x50, 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, 0x6d, 0x70, 0x6f, 0x73,
+     0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
+     0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65,
+     0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x52, 0x17, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72,
+     0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x13, 0x66, 0x6f, 0x72,
+     0x63, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x73,
+     0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53,
+     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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61,
+     0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x6f, 0x72,
+     0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54,
+     0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+     0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61,
+     0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+     0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49,
+     0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x42,
+     0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52,
+     0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x42,
+     0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02,
+     0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d,
+     0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53,
+     0x49, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+     0x10, 0x03, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e,
+     0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
+     0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55,
+     0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+     0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41,
+     0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c,
+     0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e,
+     0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
+     0x53, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x4f, 0x5f,
+     0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x22, 0xf4, 0x01, 0x0a,
+     0x17, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52,
+     0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19,
+     0x0a, 0x15, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
+     0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
+     0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x43,
+     0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x41,
+     0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10,
+     0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
+     0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41,
+     0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49,
+     0x52, 0x53, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04,
+     0x12, 0x31, 0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52,
+     0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49,
+     0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52,
+     0x53, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f,
+     0x4e, 0x10, 0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a, 0x46, 0x6f, 0x72, 0x63,
+     0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69,
+     0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d,
+     0x0a, 0x19, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44,
+     0x52, 0x41, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+     0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52,
+     0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49,
+     0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x4f, 0x52,
+     0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
+     0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x43,
+     0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x46,
+     0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57,
+     0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
+     0x03, 0x12, 0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f,
+     0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49,
+     0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x10,
+     0x04, 0x1a, 0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d,
+     0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65,
+     0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d,
+     0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63,
+     0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x22, 0x6c, 0x61, 0x73,
+     0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
+     0x65, 0x72, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x70, 0x65,
+     0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
+     0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x46, 0x0a,
+     0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+     0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f,
+     0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x72, 0x61, 0x77,
+     0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x52, 0x0a,
+     0x27, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+     0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+     0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21,
+     0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d,
+     0x62, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a,
+     0x08, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77,
+     0x12, 0x59, 0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x64,
+     0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x63, 0x75,
+     0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64, 0x69, 0x64, 0x53, 0x65,
+     0x6e, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65,
+     0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x2e, 0x64,
+     0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63,
+     0x74, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x27, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69,
+     0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63,
+     0x74, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x5d, 0x0a, 0x2d,
+     0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65,
+     0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f, 0x6e, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x26, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69,
+     0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63,
+     0x74, 0x65, 0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x23, 0x77,
+     0x61, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
+     0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f,
+     0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
+     0x12, 0x35, 0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
+     0x69, 0x74, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64,
+     0x69, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x69,
+     0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x64,
+     0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
+     0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18,
+     0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x64, 0x69, 0x64, 0x49, 0x6e,
+     0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x79, 0x65,
+     0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69,
+     0x6e, 0x6b, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x65,
+     0x72, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73,
+     0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
+     0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x64,
+     0x69, 0x64, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6d, 0x70,
+     0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+     0x61, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x69, 0x64, 0x5f,
+     0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65,
+     0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x64,
+     0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73,
+     0x12, 0x4e, 0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74,
+     0x69, 0x76, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62,
+     0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x63,
+     0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x43, 0x68,
+     0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x6e,
+     0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15,
+     0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x6d,
+     0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+     0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+     0x12, 0x63, 0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63,
+     0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72,
+     0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+     0x73, 0x69, 0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x29,
+     0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+     0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c,
+     0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65,
+     0x64, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x18, 0x12, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65,
+     0x64, 0x72, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x65, 0x64,
+     0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69,
+     0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e,
+     0x65, 0x65, 0x64, 0x73, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54,
+     0x69, 0x6c, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6e, 0x65, 0x65, 0x64,
+     0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e,
+     0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a,
+     0x1a, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f, 0x6e, 0x65, 0x5f, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6e,
+     0x65, 0x65, 0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e,
+     0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+     0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12,
+     0x39, 0x0a, 0x19, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61,
+     0x75, 0x73, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16,
+     0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x19,
+     0x0a, 0x08, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x18,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x61, 0x6e, 0x44, 0x72, 0x61,
+     0x77, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x19,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x44, 0x72, 0x61, 0x77, 0x12, 0x28,
+     0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+     0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x0e, 0x68, 0x61, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+     0x54, 0x72, 0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x70, 0x65, 0x6e, 0x64,
+     0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f,
+     0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63,
+     0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1b, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54,
+     0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x46, 0x6f,
+     0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+     0x3e, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72,
+     0x65, 0x65, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x72,
+     0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x1c, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65,
+     0x65, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x46, 0x69, 0x72, 0x73, 0x74, 0x44,
+     0x72, 0x61, 0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76,
+     0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65,
+     0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18,
+     0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76,
+     0x65, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79,
+     0x54, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x12, 0x6c, 0x0a, 0x35, 0x64, 0x69,
+     0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64,
+     0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f,
+     0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
+     0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
+     0x69, 0x6e, 0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x2d, 0x64,
+     0x69, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x49,
+     0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x46, 0x69, 0x72,
+     0x73, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x6a, 0x0a, 0x0d,
+     0x74, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
+     0x79, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 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, 0x6d, 0x70,
+     0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d,
+     0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72,
+     0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x65,
+     0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x7d, 0x0a, 0x14,
+     0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+     0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x20, 0x20, 0x01,
+     0x28, 0x0e, 0x32, 0x4b, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
+     0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x2e, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c,
+     0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x12, 0x73, 0x63, 0x72,
+     0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63, 0x72, 0x69, 0x74, 0x69,
+     0x63, 0x61, 0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
+     0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+     0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x5f,
+     0x66, 0x61, 0x73, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26,
+     0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f,
+     0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x73, 0x46, 0x61,
+     0x73, 0x74, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64,
+     0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x6d, 0x61,
+     0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x69, 0x73, 0x73,
+     0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e,
+     0x65, 0x78, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
+     0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+     0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e,
+     0x63, 0x79, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x73, 0x6b,
+     0x69, 0x70, 0x4e, 0x65, 0x78, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65,
+     0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12,
+     0x37, 0x0a, 0x18, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6e, 0x65, 0x65,
+     0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x76,
+     0x69, 0x64, 0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67,
+     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16,
+     0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+     0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x25,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65, 0x66, 0x65, 0x72, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f,
+     0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x64, 0x5f, 0x6e, 0x6f, 0x5f,
+     0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
+     0x74, 0x48, 0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+     0x73, 0x12, 0x32, 0x0a, 0x16, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61,
+     0x77, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64,
+     0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x18, 0x64, 0x69, 0x64,
+     0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6c,
+     0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x53, 0x75, 0x62, 0x6d,
+     0x69, 0x74, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x69,
+     0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76,
+     0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x29, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x19, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x49, 0x6d,
+     0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+     0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x63, 0x75,
+     0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+     0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x69, 0x6d,
+     0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2a, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x65,
+     0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x49,
+     0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x23, 0x70,
+     0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64,
+     0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x77, 0x61, 0x73,
+     0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2b,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
+     0x75, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
+     0x65, 0x57, 0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65,
+     0x12, 0x5f, 0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69,
+     0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f,
+     0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65,
+     0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x28, 0x70, 0x72, 0x6f,
      0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61,
      0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73,
-     0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72,
-     0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x77,
-     0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f,
-     0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
-     0x18, 0x2e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x69, 0x6e, 0x74, 0x57,
-     0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65,
-     0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x22, 0xb8, 0x01,
-     0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69,
-     0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50,
-     0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50,
-     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2e, 0x0a,
-     0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49,
-     0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f,
-     0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54,
-     0x48, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x01, 0x12, 0x2b, 0x0a,
-     0x27, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49,
-     0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f, 0x4f, 0x54, 0x48, 0x4e, 0x45, 0x53,
-     0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f,
-     0x52, 0x49, 0x54, 0x59, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28, 0x54, 0x52,
-     0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
-     0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f,
-     0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49,
-     0x54, 0x59, 0x10, 0x03, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53, 0x63, 0x72,
-     0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x43, 0x52, 0x4f, 0x4c,
-     0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x5f, 0x55, 0x4e,
+     0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65,
+     0x65, 0x12, 0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66,
+     0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74,
+     0x72, 0x65, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x29, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69,
+     0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65,
+     0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+     0x54, 0x72, 0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x69, 0x6e, 0x74,
+     0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f,
+     0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72,
+     0x65, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x70, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x69, 0x6e,
+     0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72,
+     0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x22,
+     0xb8, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f,
+     0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x45, 0x45,
+     0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e,
      0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
-     0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x41, 0x46,
-     0x46, 0x45, 0x43, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c,
-     0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x01, 0x12, 0x29,
-     0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x45,
-     0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x46, 0x46, 0x45, 0x43, 0x54,
-     0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44,
-     0x4c, 0x45, 0x52, 0x10, 0x02, 0x22, 0x8f, 0x05, 0x0a, 0x0e, 0x42, 0x65,
-     0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73,
-     0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e,
-     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
-     0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
-     0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
-     0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x6f, 0x75,
-     0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x71,
-     0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
-     0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x65, 0x71, 0x75,
-     0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x22,
-     0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-     0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x12, 0x1f,
-     0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75,
-     0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61,
-     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69,
-     0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74,
-     0x61, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f,
-     0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74,
-     0x61, 0x55, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x6e, 0x5f, 0x63, 0x72,
-     0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18,
-     0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x6e, 0x43, 0x72, 0x69,
-     0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a,
-     0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x6c,
-     0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6e, 0x69,
-     0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x13,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28,
-     0x04, 0x48, 0x00, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c,
-     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64, 0x12, 0x4a,
-     0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
-     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70,
-     0x65, 0x12, 0x25, 0x0a, 0x21, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46,
-     0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59,
-     0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
-     0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x42, 0x45, 0x47, 0x49,
-     0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53,
-     0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49,
-     0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e,
-     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f,
-     0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10,
-     0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46,
-     0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59,
-     0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x42,
-     0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66,
-     0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05, 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69,
-     0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
-     0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
-     0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
-     0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
-     0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
-     0x41, 0x74, 0x55, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74,
-     0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a,
-     0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67,
-     0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
-     0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72,
-     0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c,
-     0x61, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67,
-     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48,
-     0x00, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12,
-     0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-     0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
-     0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
-     0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-     0x73, 0x49, 0x6e, 0x55, 0x73, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x73,
-     0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x1a, 0xad, 0x02,
-     0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73,
-     0x49, 0x6e, 0x55, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65,
-     0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
-     0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x15, 0x6e,
-     0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
-     0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61,
-     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x34,
-     0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-     0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x74,
-     0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x66, 0x72, 0x61,
-     0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4e, 0x6f, 0x77, 0x44,
-     0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x1c, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65,
-     0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c,
-     0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03,
-     0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e,
-     0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
-     0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
-     0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a,
-     0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
-     0x65, 0x22, 0x38, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18,
-     0x0a, 0x14, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
-     0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x00,
-     0x12, 0x15, 0x0a, 0x11, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52,
-     0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x42,
-     0x06, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x17,
-     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62,
-     0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
-     0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x62,
-     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61,
-     0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64,
-     0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x52, 0x0a, 0x15,
-     0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
-     0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73,
-     0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc5, 0x01, 0x0a,
-     0x15, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
-     0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b,
-     0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65,
-     0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x75,
-     0x73, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6f,
-     0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x62, 0x73, 0x65, 0x72,
-     0x76, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74,
-     0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x6c, 0x61,
-     0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
-     0x41, 0x72, 0x67, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x17, 0x43, 0x6f, 0x6d,
-     0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e,
-     0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x31,
-     0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x63,
-     0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69,
-     0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75,
-     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2a, 0x62, 0x65, 0x67,
-     0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51,
-     0x75, 0x65, 0x75, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
-     0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74,
-     0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a, 0x35, 0x62, 0x65, 0x67, 0x69, 0x6e,
-     0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
-     0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x72,
-     0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d,
-     0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2d, 0x62, 0x65, 0x67, 0x69,
-     0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75,
-     0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63,
-     0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
-     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x76, 0x0a, 0x3b, 0x62, 0x65, 0x67,
-     0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72,
-     0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
-     0x69, 0x74, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f,
-     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69,
-     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54,
-     0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x6d,
-     0x69, 0x74, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
-     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x5d, 0x0a, 0x2d, 0x63, 0x6f, 0x6d,
-     0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79,
-     0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
-     0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65,
-     0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x6f, 0x52, 0x65,
-     0x61, 0x64, 0x79, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
-     0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c,
-     0x74, 0x61, 0x55, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x70, 0x72, 0x65, 0x70,
-     0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x73,
-     0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x70,
-     0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x45,
-     0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
-     0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
-     0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f,
-     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
-     0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74,
-     0x61, 0x55, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x72, 0x61, 0x77, 0x5f,
-     0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c,
-     0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x13, 0x64, 0x72, 0x61, 0x77, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
-     0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x2a, 0xb0, 0x05, 0x0a,
-     0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
-     0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
-     0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f,
-     0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
-     0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50,
-     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a,
-     0x18, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
-     0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e,
-     0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a, 0x29, 0x43, 0x43, 0x5f, 0x53, 0x43,
-     0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
-     0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x45, 0x47, 0x49,
-     0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
-     0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
-     0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
-     0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x12, 0x2a,
-     0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
-     0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f,
-     0x54, 0x52, 0x45, 0x45, 0x10, 0x04, 0x12, 0x28, 0x0a, 0x24, 0x43, 0x43,
-     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
-     0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49,
-     0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x05,
-     0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
-     0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
-     0x44, 0x52, 0x41, 0x57, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x10,
-     0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45,
-     0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e,
-     0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10,
-     0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45,
-     0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e,
-     0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52,
-     0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
-     0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4f,
-     0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x43, 0x5f, 0x53, 0x43,
-     0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
-     0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x5f, 0x54,
-     0x49, 0x4c, 0x45, 0x53, 0x10, 0x09, 0x12, 0x38, 0x0a, 0x34, 0x43, 0x43,
-     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
-     0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49,
-     0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
-     0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49,
-     0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36, 0x0a, 0x32, 0x43, 0x43, 0x5f, 0x53,
-     0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
-     0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x5f,
-     0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x49, 0x4e,
-     0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b,
-     0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
-     0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
-     0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e,
-     0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
-     0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44,
-     0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c, 0x10, 0x0c, 0x12, 0x41, 0x0a, 0x3d,
-     0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
-     0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49,
-     0x46, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49,
-     0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f,
-     0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x4f,
-     0x4e, 0x10, 0x0d, 0x0a, 0xb1, 0x01, 0x0a, 0x4a, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x74,
-     0x74, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f,
-     0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0x52, 0x0a, 0x1e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x74,
-     0x69, 0x6e, 0x67, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66,
-     0x6f, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f,
-     0x6f, 0x66, 0x5f, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x6e, 0x75, 0x6d,
-     0x62, 0x65, 0x72, 0x4f, 0x66, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69,
-     0x6f, 0x6e, 0x73, 0x0a, 0xe0, 0x04, 0x0a, 0x3d, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72,
-     0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x22, 0x8d, 0x04, 0x0a, 0x13, 0x43, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
-     0x65, 0x72, 0x12, 0x40, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x06,
-     0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
-     0x32, 0x34, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
-     0x65, 0x72, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x72, 0x6f, 0x70,
-     0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73,
-     0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
-     0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x0d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x71, 0x75,
-     0x65, 0x6e, 0x63, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x66, 0x66, 0x65,
-     0x63, 0x74, 0x73, 0x5f, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x6e, 0x65,
-     0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x66,
-     0x66, 0x65, 0x63, 0x74, 0x73, 0x53, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x6e,
-     0x65, 0x73, 0x73, 0x22, 0x6d, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65,
-     0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4e, 0x4f,
-     0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x44, 0x45, 0x53, 0x49,
-     0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41,
-     0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x45, 0x44,
-     0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54,
-     0x41, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x45,
-     0x44, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x41, 0x4c, 0x10, 0x02, 0x12,
-     0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x44, 0x52, 0x4f,
-     0x50, 0x50, 0x45, 0x44, 0x10, 0x03, 0x22, 0x7e, 0x0a, 0x0f, 0x46, 0x72,
-     0x61, 0x6d, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f,
-     0x6e, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f,
+     0x2e, 0x0a, 0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+     0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x52,
+     0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x42,
+     0x4f, 0x54, 0x48, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x01, 0x12,
+     0x2b, 0x0a, 0x27, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+     0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f, 0x4f, 0x54, 0x48, 0x4e,
+     0x45, 0x53, 0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52,
+     0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28,
+     0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54,
+     0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e,
+     0x54, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+     0x52, 0x49, 0x54, 0x59, 0x10, 0x03, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53,
+     0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x43, 0x52,
+     0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x5f,
      0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f,
-     0x44, 0x49, 0x53, 0x50, 0x4c, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x50,
-     0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12,
-     0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f,
-     0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18,
-     0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e,
-     0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52,
-     0x10, 0x03, 0x0a, 0x86, 0x02, 0x0a, 0x3f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65,
-     0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f,
-     0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61,
-     0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f,
+     0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x52, 0x4f,
+     0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x01,
+     0x12, 0x29, 0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x44,
+     0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x46, 0x46, 0x45,
+     0x43, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41,
+     0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x02, 0x22, 0x8f, 0x05, 0x0a, 0x0e,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67,
+     0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79,
+     0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73,
+     0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
+     0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x65,
+     0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+     0x12, 0x22, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69,
+     0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73,
+     0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
+     0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x2a, 0x0a,
+     0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65,
+     0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65,
+     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x6e, 0x5f,
+     0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74,
+     0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x6e, 0x43,
+     0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12,
+     0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x6f,
+     0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61,
+     0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x30,
+     0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64,
+     0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
+     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00,
+     0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61,
+     0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a, 0x12, 0x42, 0x65, 0x67,
+     0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54,
+     0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x42, 0x45, 0x47, 0x49, 0x4e,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+     0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52,
+     0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41,
+     0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47,
+     0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47,
+     0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
+     0x4c, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x45, 0x44, 0x10,
+     0x03, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+     0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05, 0x0a, 0x12, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x41, 0x72, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61,
+     0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
+     0x41, 0x74, 0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x69,
+     0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
+     0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x73, 0x74,
+     0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0x35, 0x0a, 0x0d, 0x48, 0x69, 0x73, 0x74, 0x6f,
-     0x67, 0x72, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03,
-     0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69,
-     0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x7b,
-     0x0a, 0x15, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74,
-     0x6f, 0x67, 0x72, 0x61, 0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12,
-     0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65,
-     0x48, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x12, 0x16, 0x0a, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
-     0x12, 0x19, 0x0a, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6e, 0x61, 0x6d, 0x65,
-     0x49, 0x69, 0x64, 0x0a, 0x79, 0x0a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65,
-     0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f,
-     0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x22, 0x28, 0x0a, 0x12, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4b, 0x65,
-     0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12,
-     0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-     0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x89, 0x0d, 0x0a, 0x3b, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61,
-     0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f,
-     0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70,
+     0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12,
+     0x44, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61,
+     0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0xb8, 0x0c, 0x0a, 0x11, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66,
-     0x6f, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69,
-     0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x72, 0x61,
-     0x63, 0x65, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x04, 0x73, 0x74, 0x65, 0x70,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e,
-     0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x65, 0x70, 0x52,
-     0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x2b, 0x0a, 0x12, 0x66, 0x72, 0x61,
-     0x6d, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x64, 0x65,
-     0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65,
-     0x49, 0x64, 0x12, 0x57, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e,
-     0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e,
-     0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
-     0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e,
-     0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x69,
-     0x73, 0x5f, 0x63, 0x6f, 0x61, 0x6c, 0x65, 0x73, 0x63, 0x65, 0x64, 0x18,
-     0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x43, 0x6f, 0x61,
-     0x6c, 0x65, 0x73, 0x63, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x65,
-     0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c,
-     0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67,
-     0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c,
-     0x49, 0x64, 0x1a, 0x88, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
-     0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5e, 0x0a, 0x0e,
-     0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79,
-     0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74,
-     0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x61, 0x74,
-     0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e,
-     0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
-     0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07,
-     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x06, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x22, 0xf2, 0x02,
-     0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54,
-     0x45, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
-     0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x45, 0x50,
-     0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f,
-     0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x49, 0x10, 0x03, 0x12, 0x20,
-     0x0a, 0x1c, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c,
-     0x45, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
-     0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x10, 0x05, 0x12, 0x28, 0x0a, 0x24,
-     0x53, 0x54, 0x45, 0x50, 0x5f, 0x44, 0x49, 0x44, 0x5f, 0x48, 0x41, 0x4e,
-     0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x41, 0x4e,
-     0x44, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c,
-     0x10, 0x08, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x48,
-     0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f,
-     0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x10, 0x04,
-     0x12, 0x22, 0x0a, 0x1e, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x4d, 0x41, 0x49,
-     0x4e, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x53, 0x43, 0x52,
-     0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02,
-     0x12, 0x27, 0x0a, 0x23, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x48, 0x41, 0x4e,
-     0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56,
-     0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x43, 0x4f, 0x4d,
-     0x4d, 0x49, 0x54, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x53, 0x54, 0x45,
-     0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e,
-     0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x41,
-     0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x10, 0x09,
-     0x12, 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x48, 0x41, 0x4e,
-     0x44, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45,
-     0x56, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x10, 0x0a, 0x12,
-     0x15, 0x0a, 0x11, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x53, 0x57, 0x41, 0x50,
-     0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x10, 0x06, 0x12, 0x16,
-     0x0a, 0x12, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f,
-     0x41, 0x4e, 0x44, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x10, 0x07, 0x22, 0xf5,
-     0x05, 0x0a, 0x14, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f,
-     0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12,
-     0x19, 0x0a, 0x15, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54,
-     0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
-     0x10, 0x00, 0x12, 0x2b, 0x0a, 0x27, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e,
-     0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56,
-     0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
-     0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x52, 0x57, 0x48, 0x10, 0x01, 0x12,
-     0x38, 0x0a, 0x34, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54,
-     0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54,
-     0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x53, 0x43, 0x52,
-     0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4f,
-     0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x3e, 0x0a,
-     0x3a, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49,
-     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c,
-     0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54,
-     0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44, 0x41,
-     0x54, 0x45, 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x10,
-     0x03, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45,
-     0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45,
-     0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x4f,
-     0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x24, 0x0a,
-     0x20, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49,
-     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c,
-     0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x49, 0x10, 0x05, 0x12,
-     0x2f, 0x0a, 0x2b, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54,
-     0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54,
-     0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x4e,
-     0x44, 0x45, 0x52, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x10, 0x06,
-     0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e,
-     0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
-     0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x52, 0x45,
-     0x4e, 0x44, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x43, 0x48, 0x45,
-     0x44, 0x55, 0x4c, 0x45, 0x44, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x10, 0x07,
-     0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e,
-     0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
-     0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x52, 0x45,
-     0x4e, 0x44, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x43, 0x48, 0x45,
-     0x44, 0x55, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x10, 0x08,
-     0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e,
-     0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
-     0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x53, 0x43,
-     0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f,
-     0x4c, 0x41, 0x53, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x10, 0x09,
-     0x12, 0x29, 0x0a, 0x25, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e,
-     0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
-     0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x41, 0x43,
-     0x4b, 0x5f, 0x52, 0x57, 0x48, 0x10, 0x0a, 0x12, 0x2f, 0x0a, 0x2b, 0x43,
-     0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50,
-     0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54,
-     0x45, 0x4e, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x45,
-     0x52, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x10, 0x0b, 0x12, 0x2f, 0x0a, 0x2b,
-     0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x49,
-     0x53, 0x50, 0x4c, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53,
-     0x49, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45,
-     0x44, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x0c, 0x12, 0x29, 0x0a,
-     0x25, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49,
-     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x47,
-     0x50, 0x55, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x42, 0x55, 0x46, 0x46,
-     0x45, 0x52, 0x10, 0x0d, 0x12, 0x2c, 0x0a, 0x28, 0x43, 0x4f, 0x4d, 0x50,
-     0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f,
-     0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43,
-     0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x57, 0x41, 0x50,
-     0x10, 0x0e, 0x0a, 0xb8, 0x08, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65,
-     0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f,
-     0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 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, 0xe9, 0x07,
-     0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61,
-     0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x52, 0x0a, 0x0d, 0x6d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49,
-     0x70, 0x63, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c,
-     0x61, 0x73, 0x73, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x4c, 0x69, 0x6e, 0x65, 0x22, 0xde, 0x06, 0x0a, 0x0c, 0x4d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x15, 0x0a,
-     0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10,
-     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x4d, 0x41,
-     0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c,
-     0x41, 0x53, 0x53, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12,
-     0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x41, 0x47,
-     0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53,
-     0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x43,
-     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x49, 0x44, 0x47, 0x45, 0x54, 0x10,
-     0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x49,
-     0x4e, 0x50, 0x55, 0x54, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c,
-     0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x07, 0x12, 0x10,
-     0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x4f, 0x52, 0x4b,
-     0x45, 0x52, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53,
-     0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11,
-     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x43, 0x48,
-     0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b, 0x43,
-     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x0b,
-     0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x50,
-     0x41, 0x50, 0x49, 0x10, 0x0c, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41,
-     0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x10, 0x0d, 0x12,
-     0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x44, 0x52, 0x41,
-     0x47, 0x10, 0x0e, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53,
-     0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f,
-     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53,
-     0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41,
-     0x53, 0x53, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55,
-     0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x11, 0x12, 0x14,
-     0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42, 0x4c, 0x49, 0x4e,
-     0x4b, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13,
-     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53,
-     0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x13, 0x12, 0x13, 0x0a,
-     0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x52, 0x45,
-     0x4e, 0x44, 0x45, 0x52, 0x10, 0x14, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c,
-     0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x4f, 0x54, 0x49,
-     0x4e, 0x47, 0x10, 0x15, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4c, 0x41, 0x53,
-     0x53, 0x5f, 0x42, 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x5f, 0x50, 0x4c,
-     0x55, 0x47, 0x49, 0x4e, 0x10, 0x16, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4c,
-     0x41, 0x53, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x5f,
-     0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x17, 0x12, 0x13,
-     0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c,
-     0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x18, 0x12, 0x19, 0x0a, 0x15, 0x43,
-     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54,
-     0x45, 0x44, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x19, 0x12, 0x0e,
-     0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x41, 0x53, 0x54,
-     0x10, 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
-     0x47, 0x49, 0x4e, 0x5f, 0x4a, 0x41, 0x56, 0x41, 0x5f, 0x42, 0x52, 0x49,
-     0x44, 0x47, 0x45, 0x10, 0x1b, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4c, 0x41,
-     0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x5f, 0x55, 0x54,
-     0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x49,
-     0x4e, 0x47, 0x10, 0x1c, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53,
-     0x53, 0x5f, 0x4f, 0x5a, 0x4f, 0x4e, 0x45, 0x5f, 0x47, 0x50, 0x55, 0x10,
-     0x1d, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57,
-     0x45, 0x42, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x1e, 0x12, 0x17, 0x0a,
-     0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x45, 0x54, 0x57, 0x4f,
-     0x52, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54, 0x53, 0x10, 0x1f, 0x12, 0x1f,
-     0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45,
-     0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54,
-     0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x43,
-     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x56,
-     0x49, 0x45, 0x57, 0x10, 0x21, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4c, 0x41,
-     0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x4c, 0x41,
-     0x59, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x47, 0x41, 0x54, 0x45,
-     0x10, 0x22, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
-     0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x4f,
-     0x52, 0x4b, 0x45, 0x52, 0x10, 0x23, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4c,
-     0x41, 0x53, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x52, 0x45, 0x53, 0x4f, 0x55,
-     0x52, 0x43, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x10, 0x24,
-     0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e,
-     0x46, 0x52, 0x45, 0x45, 0x5a, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46, 0x52,
-     0x41, 0x4d, 0x45, 0x10, 0x25, 0x0a, 0x98, 0x01, 0x0a, 0x3b, 0x70, 0x72,
+     0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x75,
+     0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x3e, 0x0a,
+     0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67,
+     0x73, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x72, 0x67,
+     0x73, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+     0x6d, 0x70, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x41, 0x72, 0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+     0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x52, 0x0e, 0x74, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x1a,
+     0xad, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+     0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x31, 0x0a,
+     0x15, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
+     0x12, 0x34, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69,
+     0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f, 0x77, 0x5f, 0x64, 0x65,
+     0x6c, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4e, 0x6f,
+     0x77, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x1c, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+     0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x44, 0x65, 0x61,
+     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x10,
+     0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
+     0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c,
+     0x69, 0x6e, 0x65, 0x22, 0x38, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x12, 0x18, 0x0a, 0x14, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52,
+     0x41, 0x4d, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44,
+     0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
+     0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53, 0x49, 0x4e, 0x47, 0x10,
+     0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xa6, 0x01,
+     0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+     0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x15, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x52,
+     0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc5,
+     0x01, 0x0a, 0x15, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
+     0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x6f, 0x75,
+     0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75,
+     0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70,
+     0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d,
+     0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x62, 0x73,
+     0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61,
+     0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12,
+     0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x17, 0x43,
+     0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d,
+     0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x65,
+     0x0a, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65,
+     0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73,
+     0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2a, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63,
+     0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
+     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a, 0x35, 0x62, 0x65, 0x67,
+     0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
+     0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74,
+     0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+     0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2d, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x51, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74, 0x43, 0x72, 0x69, 0x74,
+     0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+     0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x76, 0x0a, 0x3b, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x6f,
+     0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f,
+     0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+     0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72,
+     0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x43, 0x6f,
+     0x6d, 0x6d, 0x69, 0x74, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+     0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x5d, 0x0a, 0x2d, 0x63,
+     0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61,
+     0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
+     0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f,
+     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x6f,
+     0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76,
+     0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44,
+     0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x70, 0x72,
+     0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x5f,
+     0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x1b, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65,
+     0x73, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c,
+     0x74, 0x61, 0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x63, 0x74, 0x69,
+     0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+     0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
+     0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
+     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x72, 0x61,
+     0x77, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64,
+     0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x13, 0x64, 0x72, 0x61, 0x77, 0x45, 0x73, 0x74, 0x69, 0x6d,
+     0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x2a, 0xb0,
+     0x05, 0x0a, 0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
+     0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
+     0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23,
+     0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+     0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e,
+     0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+     0x1c, 0x0a, 0x18, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55,
+     0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e,
+     0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a, 0x29, 0x43, 0x43, 0x5f,
+     0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43,
+     0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x43, 0x5f, 0x53,
+     0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
+     0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03,
+     0x12, 0x2a, 0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+     0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+     0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e,
+     0x43, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x04, 0x12, 0x28, 0x0a, 0x24,
+     0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57,
+     0x5f, 0x49, 0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45,
+     0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+     0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+     0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45,
+     0x44, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43, 0x43, 0x5f, 0x53, 0x43,
+     0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+     0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x41, 0x42, 0x4f, 0x52,
+     0x54, 0x10, 0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43, 0x43, 0x5f, 0x53, 0x43,
+     0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+     0x4f, 0x4e, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x59,
+     0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
+     0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x43, 0x5f,
+     0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43,
+     0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45,
+     0x5f, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x09, 0x12, 0x38, 0x0a, 0x34,
+     0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x41,
+     0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52,
+     0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
+     0x53, 0x49, 0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36, 0x0a, 0x32, 0x43, 0x43,
+     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
+     0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52,
+     0x4d, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f,
+     0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e,
+     0x10, 0x0b, 0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+     0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+     0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47,
+     0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54,
+     0x45, 0x44, 0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c, 0x10, 0x0c, 0x12, 0x41,
+     0x0a, 0x3d, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+     0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f,
+     0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d,
+     0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f,
+     0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x53,
+     0x4f, 0x4f, 0x4e, 0x10, 0x0d, 0x0a, 0xb4, 0x01, 0x0a, 0x3f, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
      0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x70,
-     0x75, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x22, 0x48, 0x0a, 0x11, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75, 0x6d, 0x70, 0x12,
-     0x33, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73,
-     0x61, 0x67, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x75,
-     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x73, 0x65, 0x6e,
-     0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x49, 0x6e, 0x51,
-     0x75, 0x65, 0x75, 0x65, 0x0a, 0xa9, 0x01, 0x0a, 0x3e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b,
-     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x5f, 0x6d, 0x6f, 0x6a, 0x6f, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
-     0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0x56, 0x0a, 0x13, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x4d, 0x6f, 0x6a, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49,
-     0x6e, 0x66, 0x6f, 0x12, 0x3f, 0x0a, 0x1c, 0x77, 0x61, 0x74, 0x63, 0x68,
-     0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x69, 0x6e,
-     0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x67, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x77, 0x61, 0x74, 0x63, 0x68,
-     0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65,
-     0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x0a, 0xb7, 0x02, 0x0a,
-     0x47, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
-     0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x43, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+     0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e,
+     0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x04, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68,
+     0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06,
+     0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x79, 0x0a, 0x3c,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f, 0x73,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
      0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x5c, 0x0a, 0x1c, 0x43, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x53,
-     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x3c, 0x0a, 0x09, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6d, 0x6f,
-     0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x28, 0x0a, 0x12, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76,
+     0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x0a,
+     0x89, 0x0d, 0x0a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e,
+     0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x61, 0x74,
+     0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xb8, 0x0c, 0x0a,
+     0x11, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e,
+     0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3b, 0x0a,
+     0x04, 0x73, 0x74, 0x65, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
+     0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
+     0x53, 0x74, 0x65, 0x70, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x2b,
+     0x0a, 0x12, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65,
+     0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x65,
+     0x65, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x57, 0x0a, 0x0e, 0x63,
+     0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66,
+     0x6f, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
+     0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x63,
+     0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f,
+     0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x61, 0x6c, 0x65,
+     0x73, 0x63, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
+     0x69, 0x73, 0x43, 0x6f, 0x61, 0x6c, 0x65, 0x73, 0x63, 0x65, 0x64, 0x12,
+     0x2a, 0x0a, 0x11, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73,
+     0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53,
+     0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x49, 0x64, 0x1a, 0x88, 0x01, 0x0a, 0x0d,
+     0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66,
+     0x6f, 0x12, 0x5e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65,
+     0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x0e, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
+     0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66,
+     0x6f, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x6d,
+     0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d,
+     0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x74, 0x69, 0x6d, 0x65,
+     0x55, 0x73, 0x22, 0xf2, 0x02, 0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12,
+     0x14, 0x0a, 0x10, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50,
+     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a,
+     0x18, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x49,
+     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55,
+     0x49, 0x10, 0x03, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x54, 0x45, 0x50, 0x5f,
+     0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x10,
+     0x05, 0x12, 0x28, 0x0a, 0x24, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x44, 0x49,
+     0x44, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50,
+     0x55, 0x54, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x53,
+     0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x10, 0x08, 0x12, 0x20, 0x0a, 0x1c, 0x53,
+     0x54, 0x45, 0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49,
+     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d,
+     0x41, 0x49, 0x4e, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x54, 0x45,
+     0x50, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x41,
+     0x44, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44,
+     0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x54, 0x45,
+     0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x50,
+     0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x41, 0x49,
+     0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x01, 0x12, 0x29,
+     0x0a, 0x25, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c,
+     0x45, 0x44, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45,
+     0x4e, 0x54, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x49,
+     0x4d, 0x50, 0x4c, 0x10, 0x09, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x45,
+     0x50, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e,
+     0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4d,
+     0x50, 0x4c, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x45, 0x50,
+     0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52,
+     0x53, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x45, 0x50, 0x5f,
+     0x44, 0x52, 0x41, 0x57, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x53, 0x57, 0x41,
+     0x50, 0x10, 0x07, 0x22, 0xf5, 0x05, 0x0a, 0x14, 0x4c, 0x61, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
+     0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4f, 0x4d, 0x50,
+     0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2b, 0x0a, 0x27, 0x43,
+     0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50,
+     0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54,
+     0x45, 0x4e, 0x43, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x52,
+     0x57, 0x48, 0x10, 0x01, 0x12, 0x38, 0x0a, 0x34, 0x43, 0x4f, 0x4d, 0x50,
+     0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f,
+     0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43,
+     0x59, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x44,
+     0x41, 0x54, 0x45, 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c,
+     0x10, 0x02, 0x12, 0x3e, 0x0a, 0x3a, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e,
+     0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56,
+     0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
+     0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c,
+     0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x52, 0x49, 0x47,
+     0x49, 0x4e, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x4f,
+     0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55,
+     0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45,
+     0x4e, 0x43, 0x59, 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x4c,
+     0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e,
+     0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56,
+     0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
+     0x55, 0x49, 0x10, 0x05, 0x12, 0x2f, 0x0a, 0x2b, 0x43, 0x4f, 0x4d, 0x50,
+     0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f,
+     0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43,
+     0x59, 0x5f, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x45, 0x52, 0x5f, 0x4d,
+     0x41, 0x49, 0x4e, 0x10, 0x06, 0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d,
+     0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e,
+     0x43, 0x59, 0x5f, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x49, 0x4e, 0x47,
+     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x44, 0x5f, 0x4d,
+     0x41, 0x49, 0x4e, 0x10, 0x07, 0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d,
+     0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e,
+     0x43, 0x59, 0x5f, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x49, 0x4e, 0x47,
+     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x44, 0x5f, 0x49,
+     0x4d, 0x50, 0x4c, 0x10, 0x08, 0x12, 0x3a, 0x0a, 0x36, 0x43, 0x4f, 0x4d,
+     0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e,
+     0x43, 0x59, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50,
+     0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x41, 0x53, 0x54, 0x5f, 0x45, 0x56,
+     0x45, 0x4e, 0x54, 0x10, 0x09, 0x12, 0x29, 0x0a, 0x25, 0x43, 0x4f, 0x4d,
+     0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e,
+     0x43, 0x59, 0x5f, 0x41, 0x43, 0x4b, 0x5f, 0x52, 0x57, 0x48, 0x10, 0x0a,
+     0x12, 0x2f, 0x0a, 0x2b, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e,
+     0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e,
+     0x54, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x52, 0x45,
+     0x4e, 0x44, 0x45, 0x52, 0x45, 0x52, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x10,
+     0x0b, 0x12, 0x2f, 0x0a, 0x2b, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45,
+     0x4e, 0x54, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4c, 0x41, 0x59, 0x5f, 0x43,
+     0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45,
+     0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x10, 0x0c, 0x12, 0x29, 0x0a, 0x25, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e,
+     0x45, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56,
+     0x45, 0x4e, 0x54, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x53, 0x57, 0x41, 0x50,
+     0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x10, 0x0d, 0x12, 0x2c, 0x0a,
+     0x28, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x49,
+     0x4e, 0x50, 0x55, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4c,
+     0x41, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x53, 0x57, 0x41, 0x50, 0x10, 0x0e, 0x0a, 0xb8, 0x08, 0x0a, 0x39,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f,
+     0x69, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x52, 0x41, 0x49,
-     0x4c, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x72, 0x61, 0x69, 0x6c, 0x4d,
-     0x6f, 0x64, 0x65, 0x2a, 0x7d, 0x0a, 0x0e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x52, 0x41, 0x49, 0x4c, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a,
-     0x0e, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e,
-     0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x41, 0x49,
-     0x4c, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f,
-     0x4e, 0x53, 0x45, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x41, 0x49,
-     0x4c, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x4e, 0x49, 0x4d, 0x41,
-     0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x41,
-     0x49, 0x4c, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45,
-     0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x41, 0x49, 0x4c, 0x5f, 0x4d,
-     0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x0a, 0x98,
+     0x6f, 0x73, 0x22, 0xe9, 0x07, 0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x52,
+     0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c,
+     0x61, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65,
+     0x67, 0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x2e, 0x4d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x0c, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x21,
+     0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69,
+     0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xde, 0x06,
+     0x0a, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61,
+     0x73, 0x73, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41,
+     0x55, 0x54, 0x4f, 0x4d, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12,
+     0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53,
+     0x53, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x04,
+     0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x49,
+     0x44, 0x47, 0x45, 0x54, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x06, 0x12,
+     0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x53,
+     0x54, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x10, 0x08, 0x12, 0x0e, 0x0a,
+     0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x10,
+     0x09, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47,
+     0x50, 0x55, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x0a,
+     0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45,
+     0x44, 0x49, 0x41, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41,
+     0x53, 0x53, 0x5f, 0x50, 0x50, 0x41, 0x50, 0x49, 0x10, 0x0c, 0x12, 0x10,
+     0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f,
+     0x4d, 0x45, 0x10, 0x0d, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53,
+     0x53, 0x5f, 0x44, 0x52, 0x41, 0x47, 0x10, 0x0e, 0x12, 0x0f, 0x0a, 0x0b,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x10,
+     0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45,
+     0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x1b,
+     0x0a, 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x58, 0x54,
+     0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e,
+     0x54, 0x10, 0x11, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10,
+     0x12, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41,
+     0x43, 0x43, 0x45, 0x53, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59,
+     0x10, 0x13, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+     0x50, 0x52, 0x45, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x10, 0x14, 0x12,
+     0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52,
+     0x4f, 0x4d, 0x4f, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x15, 0x12, 0x18, 0x0a,
+     0x14, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42, 0x52, 0x4f, 0x57, 0x53,
+     0x45, 0x52, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x16, 0x12,
+     0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x4e, 0x44,
+     0x52, 0x4f, 0x49, 0x44, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45,
+     0x57, 0x10, 0x17, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x18,
+     0x12, 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x4e,
+     0x43, 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x44, 0x49,
+     0x41, 0x10, 0x19, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x43, 0x41, 0x53, 0x54, 0x10, 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x49, 0x4e, 0x5f, 0x4a, 0x41, 0x56,
+     0x41, 0x5f, 0x42, 0x52, 0x49, 0x44, 0x47, 0x45, 0x10, 0x1b, 0x12, 0x21,
+     0x0a, 0x1d, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f,
+     0x4d, 0x45, 0x5f, 0x55, 0x54, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50,
+     0x52, 0x49, 0x4e, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x1c, 0x12, 0x13, 0x0a,
+     0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4f, 0x5a, 0x4f, 0x4e, 0x45,
+     0x5f, 0x47, 0x50, 0x55, 0x10, 0x1d, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x54, 0x45, 0x53, 0x54,
+     0x10, 0x1e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+     0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54,
+     0x53, 0x10, 0x1f, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f,
+     0x47, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x20,
+     0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x55,
+     0x45, 0x53, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x21, 0x12, 0x1f,
+     0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49,
+     0x41, 0x5f, 0x50, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4c,
+     0x45, 0x47, 0x41, 0x54, 0x45, 0x10, 0x22, 0x12, 0x1a, 0x0a, 0x16, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49,
+     0x4f, 0x4e, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x10, 0x23, 0x12,
+     0x1c, 0x0a, 0x18, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x53, 0x55, 0x42,
+     0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x46, 0x49, 0x4c,
+     0x54, 0x45, 0x52, 0x10, 0x24, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41,
+     0x53, 0x53, 0x5f, 0x55, 0x4e, 0x46, 0x52, 0x45, 0x45, 0x5a, 0x41, 0x42,
+     0x4c, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x25, 0x0a, 0x98,
      0x01, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
      0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65,
      0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
@@ -1429,435 +1263,294 @@
      0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
      0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68,
      0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61,
-     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x0a, 0xaa, 0x01,
-     0x0a, 0x47, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x0a, 0xed, 0x1a,
+     0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
      0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
      0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
-     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f,
-     0x77, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x65, 0x76, 0x65,
-     0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x4e, 0x0a, 0x1b, 0x43, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x48, 0x61,
-     0x6e, 0x64, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66,
-     0x6f, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x03, 0x64, 0x70, 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x6d,
-     0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x49, 0x64, 0x0a, 0xdb, 0x26, 0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x38,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x64, 0x65,
+     0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+     0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x6c, 0x6f, 0x67, 0x5f,
+     0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
+     0x2f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74,
+     0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x49, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61,
+     0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+     0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x1a, 0x3f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
+     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f,
+     0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f,
      0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74,
      0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65,
-     0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65,
-     0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x1a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
-     0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
-     0x6e, 0x74, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e,
-     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x1a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
-     0x2f, 0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65,
-     0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x1a, 0x45, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e,
-     0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70,
-     0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61,
-     0x74, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x1a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
-     0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
-     0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64,
-     0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x4a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
-     0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
-     0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63,
-     0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
-     0x6e, 0x67, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e,
-     0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3d, 0x70, 0x72,
+     0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f,
+     0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b,
+     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x6e,
+     0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
      0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x70,
-     0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x3f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67,
-     0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
-     0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
-     0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b,
-     0x65, 0x79, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x66,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72, 0x6f,
+     0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70,
+     0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72, 0x6f,
      0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
      0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b,
      0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x75, 0x6d,
-     0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b,
-     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x5f, 0x6d, 0x6f, 0x6a, 0x6f, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
-     0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x47, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
-     0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x1a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
-     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x47, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
-     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
-     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
-     0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e,
-     0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x1a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
-     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfa, 0x1b,
-     0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74,
-     0x12, 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
-     0x5f, 0x69, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52,
-     0x0c, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x69, 0x64,
-     0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
-     0x69, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63,
-     0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1b, 0x0a,
-     0x08, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x0a, 0x20,
-     0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x6e, 0x61, 0x6d, 0x65, 0x49,
-     0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x17,
-     0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01,
-     0x28, 0x0e, 0x32, 0x20, 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, 0x2e, 0x54, 0x79, 0x70, 0x65,
-     0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72,
-     0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01,
-     0x28, 0x04, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x55, 0x75, 0x69,
-     0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x61, 0x63,
-     0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28,
-     0x04, 0x52, 0x16, 0x65, 0x78, 0x74, 0x72, 0x61, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x55, 0x75, 0x69, 0x64,
-     0x73, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
-     0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x03, 0x52, 0x12, 0x65, 0x78, 0x74,
-     0x72, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x6c, 0x6f, 0x77, 0x5f,
-     0x69, 0x64, 0x73, 0x18, 0x24, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x66,
-     0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x65,
-     0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x6c,
-     0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x2a, 0x20, 0x03, 0x28, 0x04,
-     0x52, 0x12, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e,
-     0x67, 0x46, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x12, 0x4d, 0x0a, 0x11,
-     0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
-     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
-     0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x41,
-     0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x64,
-     0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x61, 0x73, 0x6b, 0x5f,
-     0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x61,
-     0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-     0x0d, 0x74, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
-     0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0b, 0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65,
-     0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x1b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x4d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x12, 0x63, 0x63, 0x5f, 0x73,
-     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61,
-     0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x6d,
-     0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
-     0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x10, 0x63,
-     0x63, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d,
      0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
-     0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45,
-     0x76, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x55, 0x0a,
-     0x14, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x65,
-     0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72,
-     0x76, 0x69, 0x63, 0x65, 0x52, 0x12, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-     0x12, 0x4c, 0x0a, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c,
-     0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x18, 0x1b, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x70,
-     0x63, 0x52, 0x0f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67,
-     0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x5e, 0x0a, 0x17, 0x63, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72,
-     0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x1c, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
-     0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x15, 0x63, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
-     0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x52, 0x0a, 0x13, 0x63, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79,
-     0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52,
-     0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e,
-     0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x58, 0x0a, 0x15, 0x63, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x72,
-     0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72,
-     0x74, 0x65, 0x72, 0x52, 0x13, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72,
-     0x12, 0x6e, 0x0a, 0x1d, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x61,
-     0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x27, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f,
-     0x52, 0x1a, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c,
-     0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65,
-     0x49, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x1f, 0x63, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f,
-     0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74,
-     0x61, 0x74, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x52, 0x65,
-     0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
-     0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x1c, 0x63, 0x68,
-     0x72, 0x6f, 0x6d, 0x65, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72,
-     0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61,
-     0x74, 0x65, 0x12, 0x72, 0x0a, 0x1f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
-     0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x68, 0x61, 0x6e, 0x64,
-     0x6c, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66,
-     0x6f, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa6, 0x14, 0x0a, 0x0a, 0x54,
+     0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a,
+     0x0d, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x69,
+     0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x61,
+     0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x69, 0x64, 0x73, 0x12, 0x1e,
+     0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73,
+     0x18, 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x65,
+     0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x08, 0x6e, 0x61,
+     0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04,
+     0x48, 0x00, 0x52, 0x07, 0x6e, 0x61, 0x6d, 0x65, 0x49, 0x69, 0x64, 0x12,
+     0x14, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28,
+     0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a,
+     0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32,
+     0x20, 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, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
+     0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x6b,
+     0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52,
+     0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x12, 0x23,
+     0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61,
+     0x6c, 0x75, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63,
+     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+     0x39, 0x0a, 0x19, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75,
+     0x75, 0x69, 0x64, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x52, 0x16,
+     0x65, 0x78, 0x74, 0x72, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+     0x54, 0x72, 0x61, 0x63, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x73, 0x12, 0x30,
+     0x0a, 0x14, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+     0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x0c,
+     0x20, 0x03, 0x28, 0x03, 0x52, 0x12, 0x65, 0x78, 0x74, 0x72, 0x61, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
+     0x12, 0x4d, 0x0a, 0x11, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e,
+     0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x65,
+     0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x52, 0x10, 0x64, 0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f,
+     0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74,
+     0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+     0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65,
      0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x57, 0x69, 0x6e, 0x64,
-     0x6f, 0x77, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e,
-     0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x1b, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-     0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x48, 0x61, 0x6e, 0x64, 0x6c,
-     0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x7b,
-     0x0a, 0x22, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
-     0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-     0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
-     0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x74, 0x65,
-     0x6e, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x76,
-     0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x1e, 0x63, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x65,
-     0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49,
-     0x6e, 0x66, 0x6f, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x21,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53,
-     0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
-     0x6e, 0x48, 0x01, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c,
-     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x73,
-     0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x22, 0x20, 0x01, 0x28, 0x04,
-     0x48, 0x01, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64, 0x12, 0x52, 0x0a,
-     0x13, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73,
-     0x61, 0x67, 0x65, 0x5f, 0x70, 0x75, 0x6d, 0x70, 0x18, 0x23, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75,
-     0x6d, 0x70, 0x52, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4d, 0x65,
-     0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75, 0x6d, 0x70, 0x12, 0x59, 0x0a,
-     0x16, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6d, 0x6f, 0x6a, 0x6f,
-     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
-     0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4d, 0x6f, 0x6a, 0x6f, 0x45, 0x76,
-     0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x13, 0x63, 0x68, 0x72,
-     0x6f, 0x6d, 0x65, 0x4d, 0x6f, 0x6a, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74,
-     0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65,
-     0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
-     0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x10,
-     0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x44, 0x65, 0x6c,
-     0x74, 0x61, 0x55, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65,
-     0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75,
-     0x74, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x48,
-     0x02, 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-     0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x55, 0x73, 0x12, 0x31,
-     0x0a, 0x14, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d,
-     0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x03, 0x48, 0x03, 0x52, 0x11, 0x74, 0x68, 0x72, 0x65,
-     0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55,
-     0x73, 0x12, 0x37, 0x0a, 0x17, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f,
-     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74,
-     0x65, 0x5f, 0x75, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x48, 0x03,
-     0x52, 0x14, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65,
-     0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x55, 0x73, 0x12, 0x45,
-     0x0a, 0x1e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73,
-     0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75,
-     0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01,
-     0x28, 0x03, 0x48, 0x04, 0x52, 0x1b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
-     0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x4b, 0x0a,
-     0x21, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74,
-     0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
-     0x74, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x18, 0x14,
-     0x20, 0x01, 0x28, 0x03, 0x48, 0x04, 0x52, 0x1e, 0x74, 0x68, 0x72, 0x65,
-     0x61, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f,
-     0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75,
-     0x74, 0x65, 0x12, 0x4a, 0x0a, 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79,
-     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 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, 0x72, 0x61, 0x63, 0x6b,
-     0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79,
-     0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x6c, 0x65, 0x67, 0x61, 0x63,
-     0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0xfa, 0x06, 0x0a, 0x0b, 0x4c,
-     0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19,
-     0x0a, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6e, 0x61, 0x6d, 0x65, 0x49, 0x69,
-     0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12,
-     0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
-     0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75,
-     0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x12, 0x2c, 0x0a, 0x12,
-     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x10, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x44, 0x75, 0x72, 0x61,
-     0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x74, 0x68,
-     0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63,
-     0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0f,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
-     0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44,
-     0x65, 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0b, 0x75, 0x6e, 0x73, 0x63,
-     0x6f, 0x70, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
-     0x04, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x73, 0x63, 0x6f, 0x70, 0x65,
-     0x64, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
-     0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52,
-     0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09,
-     0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20,
-     0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x08, 0x67, 0x6c, 0x6f, 0x62, 0x61,
-     0x6c, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x73, 0x63,
-     0x6f, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69,
-     0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x73,
-     0x65, 0x5f, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x74, 0x73, 0x18,
-     0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x41, 0x73,
-     0x79, 0x6e, 0x63, 0x54, 0x74, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x69,
-     0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52,
-     0x06, 0x62, 0x69, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x62,
-     0x69, 0x6e, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
-     0x73, 0x69, 0x6e, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
-     0x62, 0x69, 0x6e, 0x64, 0x54, 0x6f, 0x45, 0x6e, 0x63, 0x6c, 0x6f, 0x73,
-     0x69, 0x6e, 0x67, 0x12, 0x5c, 0x0a, 0x0e, 0x66, 0x6c, 0x6f, 0x77, 0x5f,
-     0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20,
-     0x01, 0x28, 0x0e, 0x32, 0x35, 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, 0x2e, 0x4c, 0x65, 0x67,
-     0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x6c, 0x6f,
-     0x77, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d,
-     0x66, 0x6c, 0x6f, 0x77, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
-     0x6e, 0x12, 0x69, 0x0a, 0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74,
-     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65,
-     0x18, 0x0e, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x70, 0x65, 0x72,
+     0x73, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65,
+     0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0b, 0x6c, 0x6f,
+     0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x15, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4c, 0x6f,
+     0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x6c, 0x6f,
+     0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x12,
+     0x63, 0x63, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x2f, 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, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x52, 0x10, 0x63, 0x63, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
+     0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x11, 0x63,
+     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65,
+     0x76, 0x65, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x55,
+     0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x63, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e,
+     0x74, 0x12, 0x55, 0x0a, 0x14, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f,
+     0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+     0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65,
+     0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x12, 0x63, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72,
+     0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x11, 0x63, 0x68, 0x72, 0x6f,
+     0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70,
+     0x63, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61,
+     0x63, 0x79, 0x49, 0x70, 0x63, 0x52, 0x0f, 0x63, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x5e,
+     0x0a, 0x17, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73,
+     0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+     0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74,
+     0x6f, 0x67, 0x72, 0x61, 0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52,
+     0x15, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f,
+     0x67, 0x72, 0x61, 0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x52,
+     0x0a, 0x13, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x61, 0x74,
+     0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x1d, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49,
+     0x6e, 0x66, 0x6f, 0x52, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c,
+     0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e,
+     0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
+     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x03, 0x48, 0x01, 0x52, 0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+     0x61, 0x6d, 0x70, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x34,
+     0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
+     0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x75, 0x73, 0x18,
+     0x10, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x13, 0x74, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75,
+     0x74, 0x65, 0x55, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74,
+     0x61, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02,
+     0x52, 0x11, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65,
+     0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x17, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61,
+     0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x11,
+     0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x14, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75,
+     0x74, 0x65, 0x55, 0x73, 0x12, 0x45, 0x0a, 0x1e, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69,
+     0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x03, 0x52, 0x1b,
+     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75,
+     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x44, 0x65,
+     0x6c, 0x74, 0x61, 0x12, 0x4b, 0x0a, 0x21, 0x74, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f,
+     0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x62, 0x73, 0x6f,
+     0x6c, 0x75, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x48, 0x03,
+     0x52, 0x1e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73, 0x74,
+     0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x12, 0x4a, 0x0a, 0x0c,
+     0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
+     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, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e,
-     0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e,
-     0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74,
-     0x53, 0x63, 0x6f, 0x70, 0x65, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65,
-     0x12, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72,
-     0x72, 0x69, 0x64, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
-     0x70, 0x69, 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12,
-     0x21, 0x0a, 0x0c, 0x74, 0x69, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72,
-     0x69, 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x74,
-     0x69, 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x22, 0x50,
-     0x0a, 0x0d, 0x46, 0x6c, 0x6f, 0x77, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
-     0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, 0x4f, 0x57, 0x5f,
-     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e,
-     0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x4f,
-     0x55, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4c, 0x4f, 0x57,
-     0x5f, 0x49, 0x4e, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x22, 0x61, 0x0a, 0x11,
-     0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74,
-     0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x43, 0x4f,
-     0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
-     0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x43, 0x4f, 0x50,
-     0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x11,
-     0x0a, 0x0d, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x43,
-     0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x43, 0x4f,
-     0x50, 0x45, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x10, 0x03, 0x42,
-     0x04, 0x0a, 0x02, 0x69, 0x64, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22,
-     0x6a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54,
-     0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-     0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50,
-     0x45, 0x5f, 0x53, 0x4c, 0x49, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49,
-     0x4e, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x59, 0x50, 0x45, 0x5f,
-     0x53, 0x4c, 0x49, 0x43, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x12,
-     0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x54,
-     0x41, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
-     0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x04, 0x2a,
-     0x06, 0x08, 0xe8, 0x07, 0x10, 0xac, 0x4d, 0x2a, 0x06, 0x08, 0xac, 0x4d,
-     0x10, 0x91, 0x4e, 0x42, 0x0c, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
-     0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x17, 0x0a, 0x15, 0x73, 0x6f, 0x75,
-     0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-     0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x69,
-     0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0x0a, 0x0b, 0x74,
-     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x1a,
-     0x0a, 0x18, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73,
-     0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75,
-     0x6e, 0x74, 0x22, 0x6e, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45,
-     0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73,
-     0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75,
-     0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x72,
-     0x61, 0x63, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x19, 0x65,
-     0x78, 0x74, 0x72, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x73,
-     0x18, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x52, 0x16, 0x65, 0x78, 0x74, 0x72,
-     0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x63,
-     0x6b, 0x55, 0x75, 0x69, 0x64, 0x73, 0x22, 0x35, 0x0a, 0x0d, 0x45, 0x76,
-     0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12,
-     0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x22, 0x31, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x61,
-     0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-     0x6e, 0x61, 0x6d, 0x65}};
+     0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
+     0x0b, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74,
+     0x1a, 0xfa, 0x06, 0x0a, 0x0b, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45,
+     0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x61, 0x6d, 0x65,
+     0x5f, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07,
+     0x6e, 0x61, 0x6d, 0x65, 0x49, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70,
+     0x68, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
+     0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x55, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x73,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73,
+     0x12, 0x38, 0x0a, 0x18, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69,
+     0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64,
+     0x65, 0x6c, 0x74, 0x61, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16,
+     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75,
+     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x21,
+     0x0a, 0x0b, 0x75, 0x6e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x5f, 0x69,
+     0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0a, 0x75,
+     0x6e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x49, 0x64, 0x12, 0x1b, 0x0a,
+     0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20,
+     0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+     0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+     0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52,
+     0x08, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x19, 0x0a,
+     0x08, 0x69, 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65,
+     0x12, 0x22, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x73, 0x79, 0x6e,
+     0x63, 0x5f, 0x74, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x0b, 0x75, 0x73, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x54, 0x74, 0x73,
+     0x12, 0x17, 0x0a, 0x07, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18,
+     0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x62, 0x69, 0x6e, 0x64, 0x49,
+     0x64, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x74, 0x6f,
+     0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x0c,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x69, 0x6e, 0x64, 0x54, 0x6f,
+     0x45, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x5c, 0x0a,
+     0x0e, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+     0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 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, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x44, 0x69, 0x72, 0x65, 0x63,
+     0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x69,
+     0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x69, 0x0a, 0x13, 0x69,
+     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
+     0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x39, 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, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79,
+     0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+     0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x52,
+     0x11, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e,
+     0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x69,
+     0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x12,
+     0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x69, 0x64, 0x4f, 0x76, 0x65,
+     0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x64,
+     0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x13, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x0b, 0x74, 0x69, 0x64, 0x4f, 0x76, 0x65, 0x72,
+     0x72, 0x69, 0x64, 0x65, 0x22, 0x50, 0x0a, 0x0d, 0x46, 0x6c, 0x6f, 0x77,
+     0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a,
+     0x10, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x46,
+     0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08,
+     0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0e,
+     0x0a, 0x0a, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e, 0x4f, 0x55, 0x54,
+     0x10, 0x03, 0x22, 0x61, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+     0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12,
+     0x15, 0x0a, 0x11, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10,
+     0x0a, 0x0c, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42,
+     0x41, 0x4c, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x43, 0x4f, 0x50,
+     0x45, 0x5f, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12,
+     0x10, 0x0a, 0x0c, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x54, 0x48, 0x52,
+     0x45, 0x41, 0x44, 0x10, 0x03, 0x42, 0x04, 0x0a, 0x02, 0x69, 0x64, 0x4a,
+     0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x6a, 0x0a, 0x04, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e,
+     0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+     0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x49, 0x43,
+     0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x12, 0x0a,
+     0x0e, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x49, 0x43, 0x45, 0x5f,
+     0x45, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
+     0x45, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x54, 0x10, 0x03, 0x12,
+     0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e,
+     0x54, 0x45, 0x52, 0x10, 0x04, 0x42, 0x0c, 0x0a, 0x0a, 0x6e, 0x61, 0x6d,
+     0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x74,
+     0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0x0a, 0x0b,
+     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42,
+     0x1a, 0x0a, 0x18, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e,
+     0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x22, 0x6e, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x63, 0x6b,
+     0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+     0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75,
+     0x75, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74,
+     0x72, 0x61, 0x63, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x19,
+     0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+     0x72, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64,
+     0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x52, 0x16, 0x65, 0x78, 0x74,
+     0x72, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x54, 0x72, 0x61,
+     0x63, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x73, 0x22, 0x35, 0x0a, 0x0d, 0x45,
+     0x76, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
+     0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x22, 0x31, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e,
+     0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65}};
 
 }  // namespace perfetto
 
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
index eb9d536..a2fcf28 100644
--- a/src/trace_processor/importers/proto/track_event_module.cc
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -18,7 +18,6 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/importers/proto/track_event_tracker.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
@@ -32,9 +31,7 @@
 using perfetto::protos::pbzero::TracePacket;
 
 TrackEventModule::TrackEventModule(TraceProcessorContext* context)
-    : track_event_tracker_(new TrackEventTracker(context)),
-      tokenizer_(context, track_event_tracker_.get()),
-      parser_(context, track_event_tracker_.get()) {
+    : tokenizer_(context), parser_(context) {
   RegisterForField(TracePacket::kTrackEventFieldNumber, context);
   RegisterForField(TracePacket::kTrackDescriptorFieldNumber, context);
   RegisterForField(TracePacket::kThreadDescriptorFieldNumber, context);
@@ -90,9 +87,5 @@
   }
 }
 
-void TrackEventModule::OnIncrementalStateCleared(uint32_t packet_sequence_id) {
-  track_event_tracker_->OnIncrementalStateCleared(packet_sequence_id);
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_module.h b/src/trace_processor/importers/proto/track_event_module.h
index 0632747..de31d47 100644
--- a/src/trace_processor/importers/proto/track_event_module.h
+++ b/src/trace_processor/importers/proto/track_event_module.h
@@ -39,14 +39,11 @@
       PacketSequenceState* state,
       uint32_t field_id) override;
 
-  void OnIncrementalStateCleared(uint32_t) override;
-
   void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
                    const TimestampedTracePiece& ttp,
                    uint32_t field_id) override;
 
  private:
-  std::unique_ptr<TrackEventTracker> track_event_tracker_;
   TrackEventTokenizer tokenizer_;
   TrackEventParser parser_;
 };
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 8ad8177..5257a73 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -16,28 +16,23 @@
 
 #include "src/trace_processor/importers/proto/track_event_parser.h"
 
-#include <iostream>
 #include <string>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/string_writer.h"
 #include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/json/json_utils.h"
+#include "src/trace_processor/importers/proto/args_table_utils.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/track_event_tracker.h"
-#include "src/trace_processor/util/proto_to_args_parser.h"
+#include "src/trace_processor/importers/proto/track_event.descriptor.h"
 #include "src/trace_processor/util/status_macros.h"
 
-#include "protos/perfetto/trace/extension_descriptor.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
-#include "protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
@@ -65,94 +60,50 @@
 constexpr int64_t kPendingThreadDuration = -1;
 constexpr int64_t kPendingThreadInstructionDelta = -1;
 
-class TrackEventArgsParser : public util::ProtoToArgsParser::Delegate {
- public:
-  TrackEventArgsParser(BoundInserter& inserter,
-                       TraceStorage& storage,
-                       PacketSequenceStateGeneration& sequence_state)
-      : inserter_(inserter),
-        storage_(storage),
-        sequence_state_(sequence_state) {}
-  ~TrackEventArgsParser() override;
+void AddStringToArgsTable(const char* field,
+                          const protozero::ConstChars& str,
+                          const ProtoToArgsTable::ParsingOverrideState& state,
+                          BoundInserter* inserter) {
+  auto val = state.context->storage->InternString(base::StringView(str));
+  auto key = state.context->storage->InternString(base::StringView(field));
+  inserter->AddArg(key, Variadic::String(val));
+}
 
-  using Key = util::ProtoToArgsParser::Key;
-
-  void AddInteger(const Key& key, int64_t value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::Integer(value));
-  }
-  void AddUnsignedInteger(const Key& key, uint64_t value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::UnsignedInteger(value));
-  }
-  void AddString(const Key& key, const protozero::ConstChars& value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::String(storage_.InternString(value)));
-  }
-  void AddDouble(const Key& key, double value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::Real(value));
-  }
-  void AddPointer(const Key& key, const void* value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::Pointer(reinterpret_cast<uintptr_t>(value)));
-  }
-  void AddBoolean(const Key& key, bool value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::Boolean(value));
-  }
-  void AddJson(const Key& key, const protozero::ConstChars& value) final {
-    inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
-                     storage_.InternString(base::StringView(key.key)),
-                     Variadic::Json(storage_.InternString(value)));
-  }
-
-  InternedMessageView* GetInternedMessageView(uint32_t field_id,
-                                              uint64_t iid) final {
-    return sequence_state_.GetInternedMessageView(field_id, iid);
-  }
-
- private:
-  BoundInserter& inserter_;
-  TraceStorage& storage_;
-  PacketSequenceStateGeneration& sequence_state_;
-};
-
-TrackEventArgsParser::~TrackEventArgsParser() = default;
-
-base::Optional<base::Status> MaybeParseSourceLocation(
+bool MaybeParseSourceLocation(
     std::string prefix,
+    const ProtoToArgsTable::ParsingOverrideState& state,
     const protozero::Field& field,
-    util::ProtoToArgsParser::Delegate& delegate) {
-  auto* decoder = delegate.GetInternedMessage(
-      protos::pbzero::InternedData::kSourceLocations, field.as_uint64());
+    BoundInserter* inserter) {
+  auto* decoder = state.sequence_state->LookupInternedMessage<
+      protos::pbzero::InternedData::kSourceLocationsFieldNumber,
+      protos::pbzero::SourceLocation>(field.as_uint64());
   if (!decoder) {
     // Lookup failed fall back on default behaviour which will just put
     // the source_location_iid into the args table.
-    return base::nullopt;
+    return false;
   }
-
-  delegate.AddString(util::ProtoToArgsParser::Key(prefix + ".file_name"),
-                     decoder->file_name());
-  delegate.AddString(util::ProtoToArgsParser::Key(prefix + ".function_name"),
-                     decoder->function_name());
-  delegate.AddInteger(util::ProtoToArgsParser::Key(prefix + ".line_number"),
-                      decoder->line_number());
-
-  return base::OkStatus();
+  {
+    ProtoToArgsTable::ScopedStringAppender scoped("file_name", &prefix);
+    AddStringToArgsTable(prefix.c_str(), decoder->file_name(), state, inserter);
+  }
+  {
+    ProtoToArgsTable::ScopedStringAppender scoped("function_name", &prefix);
+    AddStringToArgsTable(prefix.c_str(), decoder->function_name(), state,
+                         inserter);
+  }
+  ProtoToArgsTable::ScopedStringAppender scoped("line_number", &prefix);
+  auto key = state.context->storage->InternString(base::StringView(prefix));
+  inserter->AddArg(key, Variadic::Integer(decoder->line_number()));
+  // By returning false we expect this field to be handled like regular.
+  return true;
 }
 
-std::string SanitizeDebugAnnotationName(const std::string& raw_name) {
+std::string SafeDebugAnnotationName(const std::string& raw_name) {
   std::string result = raw_name;
   std::replace(result.begin(), result.end(), '.', '_');
   std::replace(result.begin(), result.end(), '[', '_');
   std::replace(result.begin(), result.end(), ']', '_');
+  result = "debug." + result;
   return result;
 }
 }  // namespace
@@ -164,16 +115,15 @@
                 TrackEventData* event_data,
                 ConstBytes blob)
       : context_(parser->context_),
-        track_event_tracker_(parser->track_event_tracker_),
         storage_(context_->storage.get()),
         parser_(parser),
         ts_(ts),
         event_data_(event_data),
-        sequence_state_(event_data->sequence_state.get()),
+        sequence_state_(event_data_->sequence_state),
         blob_(std::move(blob)),
         event_(blob_),
         legacy_event_(event_.legacy_event()),
-        defaults_(event_data->sequence_state->GetTrackEventDefaults()) {}
+        defaults_(sequence_state_->GetTrackEventDefaults()) {}
 
   util::Status Import() {
     // TODO(eseckler): This legacy event field will eventually be replaced by
@@ -187,7 +137,7 @@
     RETURN_IF_ERROR(ParseTrackAssociation());
 
     // Counter-type events don't support arguments (those are on the
-    // CounterDescriptor instead). All they have is a |{double_,}counter_value|.
+    // CounterDescriptor instead). All they have is a |counter_value|.
     if (event_.type() == TrackEvent::TYPE_COUNTER) {
       ParseCounterEvent();
       return util::OkStatus();
@@ -204,34 +154,24 @@
 
     // TODO(eseckler): Replace phase with type and remove handling of
     // legacy_event_.phase() once it is no longer used by producers.
-    char phase = static_cast<char>(ParsePhaseOrType());
+    int32_t phase = ParsePhaseOrType();
 
-    switch (phase) {
+    switch (static_cast<char>(phase)) {
       case 'B':  // TRACE_EVENT_PHASE_BEGIN.
         return ParseThreadBeginEvent();
       case 'E':  // TRACE_EVENT_PHASE_END.
         return ParseThreadEndEvent();
       case 'X':  // TRACE_EVENT_PHASE_COMPLETE.
         return ParseThreadCompleteEvent();
-      case 's':  // TRACE_EVENT_PHASE_FLOW_BEGIN.
-      case 't':  // TRACE_EVENT_PHASE_FLOW_STEP.
-      case 'f':  // TRACE_EVENT_PHASE_FLOW_END.
-        return ParseFlowEventV1(phase);
       case 'i':
       case 'I':  // TRACE_EVENT_PHASE_INSTANT.
-      case 'R':  // TRACE_EVENT_PHASE_MARK.
-        return ParseThreadInstantEvent(phase);
+        return ParseThreadInstantEvent();
       case 'b':  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN
-      case 'S':
-        return ParseAsyncBeginEvent(phase);
+        return ParseAsyncBeginEvent();
       case 'e':  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_END
-      case 'F':
         return ParseAsyncEndEvent();
       case 'n':  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
         return ParseAsyncInstantEvent();
-      case 'T':
-      case 'p':
-        return ParseAsyncStepEvent(phase);
       case 'M':  // TRACE_EVENT_PHASE_METADATA (process and thread names).
         return ParseMetadataEvent();
       default:
@@ -333,19 +273,18 @@
     // Determine track from track_uuid specified in either TrackEvent or
     // TrackEventDefaults. If a non-default track is not set, we either:
     //   a) fall back to the track specified by the sequence's (or event's) pid
-    //      + tid (only in case of legacy tracks/events, i.e. events that don't
+    //   +
+    //      tid (only in case of legacy tracks/events, i.e. events that don't
     //      specify an explicit track uuid or use legacy event phases instead of
     //      TrackEvent types), or
     //   b) a default track.
     if (track_uuid_) {
       base::Optional<TrackId> opt_track_id =
-          track_event_tracker_->GetDescriptorTrack(track_uuid_, name_id_);
+          track_tracker->GetDescriptorTrack(track_uuid_);
       if (!opt_track_id) {
-        track_event_tracker_->ReserveDescriptorChildTrack(track_uuid_,
-                                                          /*parent_uuid=*/0,
-                                                          name_id_);
-        opt_track_id =
-            track_event_tracker_->GetDescriptorTrack(track_uuid_, name_id_);
+        track_tracker->ReserveDescriptorChildTrack(track_uuid_,
+                                                   /*parent_uuid=*/0, name_id_);
+        opt_track_id = track_tracker->GetDescriptorTrack(track_uuid_);
       }
       track_id_ = *opt_track_id;
 
@@ -419,7 +358,7 @@
         upid_ = storage_->thread_table().upid()[*utid_];
         track_id_ = track_tracker->InternThreadTrack(*utid_);
       } else {
-        track_id_ = track_event_tracker_->GetOrCreateDefaultDescriptorTrack();
+        track_id_ = track_tracker->GetOrCreateDefaultDescriptorTrack();
       }
     }
 
@@ -431,11 +370,7 @@
     switch (legacy_event_.phase()) {
       case 'b':
       case 'e':
-      case 'n':
-      case 'S':
-      case 'T':
-      case 'p':
-      case 'F': {
+      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;
@@ -457,12 +392,8 @@
 
         // Catapult treats nestable async events of different categories with
         // the same ID as separate tracks. We replicate the same behavior
-        // here. For legacy async events, it uses different tracks based on
-        // event names.
-        const bool legacy_async =
-            legacy_event_.phase() == 'S' || legacy_event_.phase() == 'T' ||
-            legacy_event_.phase() == 'p' || legacy_event_.phase() == 'F';
-        StringId id_scope = legacy_async ? name_id_ : category_id_;
+        // 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();
@@ -537,11 +468,10 @@
     // Tokenizer ensures that TYPE_COUNTER events are associated with counter
     // tracks and have values.
     PERFETTO_DCHECK(storage_->counter_track_table().id().IndexOf(track_id_));
-    PERFETTO_DCHECK(event_.has_counter_value() ||
-                    event_.has_double_counter_value());
+    PERFETTO_DCHECK(event_.has_counter_value());
 
-    context_->event_tracker->PushCounter(
-        ts_, static_cast<double>(event_data_->counter_value), track_id_);
+    context_->event_tracker->PushCounter(ts_, event_data_->counter_value,
+                                         track_id_);
   }
 
   void ParseLegacyThreadTimeAndInstructionsAsCounters() {
@@ -556,76 +486,55 @@
     if (event_data_->thread_timestamp) {
       TrackId track_id = context_->track_tracker->InternThreadCounterTrack(
           parser_->counter_name_thread_time_id_, *utid_);
-      context_->event_tracker->PushCounter(
-          ts_, static_cast<double>(*event_data_->thread_timestamp), track_id);
+      context_->event_tracker->PushCounter(ts_, event_data_->thread_timestamp,
+                                           track_id);
     }
     if (event_data_->thread_instruction_count) {
       TrackId track_id = context_->track_tracker->InternThreadCounterTrack(
           parser_->counter_name_thread_instruction_count_id_, *utid_);
       context_->event_tracker->PushCounter(
-          ts_, static_cast<double>(*event_data_->thread_instruction_count),
-          track_id);
+          ts_, event_data_->thread_instruction_count, track_id);
     }
   }
 
   void ParseExtraCounterValues() {
-    if (!event_.has_extra_counter_values() &&
-        !event_.has_extra_double_counter_values()) {
+    if (!event_.has_extra_counter_values())
       return;
-    }
 
-    // Add integer extra counter values.
-    size_t index = 0;
     protozero::RepeatedFieldIterator<uint64_t> track_uuid_it;
     if (event_.has_extra_counter_track_uuids()) {
       track_uuid_it = event_.extra_counter_track_uuids();
     } else if (defaults_ && defaults_->has_extra_counter_track_uuids()) {
       track_uuid_it = defaults_->extra_counter_track_uuids();
     }
+
+    size_t index = 0;
     for (auto value_it = event_.extra_counter_values(); value_it;
          ++value_it, ++track_uuid_it, ++index) {
-      AddExtraCounterValue(track_uuid_it, index);
-    }
+      // Tokenizer ensures that there aren't more values than uuids, that we
+      // don't have more values than kMaxNumExtraCounters and that the
+      // track_uuids are for valid counter tracks.
+      PERFETTO_DCHECK(track_uuid_it);
+      PERFETTO_DCHECK(index < TrackEventData::kMaxNumExtraCounters);
 
-    // Add double extra counter values.
-    track_uuid_it = protozero::RepeatedFieldIterator<uint64_t>();
-    if (event_.has_extra_double_counter_track_uuids()) {
-      track_uuid_it = event_.extra_double_counter_track_uuids();
-    } else if (defaults_ && defaults_->has_extra_double_counter_track_uuids()) {
-      track_uuid_it = defaults_->extra_double_counter_track_uuids();
-    }
-    for (auto value_it = event_.extra_double_counter_values(); value_it;
-         ++value_it, ++track_uuid_it, ++index) {
-      AddExtraCounterValue(track_uuid_it, index);
-    }
-  }
+      base::Optional<TrackId> track_id =
+          context_->track_tracker->GetDescriptorTrack(*track_uuid_it);
+      base::Optional<uint32_t> counter_row =
+          storage_->counter_track_table().id().IndexOf(*track_id);
 
-  void AddExtraCounterValue(
-      protozero::RepeatedFieldIterator<uint64_t> track_uuid_it,
-      size_t index) {
-    // Tokenizer ensures that there aren't more values than uuids, that we
-    // don't have more values than kMaxNumExtraCounters and that the
-    // track_uuids are for valid counter tracks.
-    PERFETTO_DCHECK(track_uuid_it);
-    PERFETTO_DCHECK(index < TrackEventData::kMaxNumExtraCounters);
+      int64_t value = event_data_->extra_counter_values[index];
+      context_->event_tracker->PushCounter(ts_, value, *track_id);
 
-    base::Optional<TrackId> track_id =
-        track_event_tracker_->GetDescriptorTrack(*track_uuid_it);
-    base::Optional<uint32_t> counter_row =
-        storage_->counter_track_table().id().IndexOf(*track_id);
-
-    double value = event_data_->extra_counter_values[index];
-    context_->event_tracker->PushCounter(ts_, value, *track_id);
-
-    // Also import thread_time and thread_instruction_count counters into
-    // slice columns to simplify JSON export.
-    StringId counter_name =
-        storage_->counter_track_table().name()[*counter_row];
-    if (counter_name == parser_->counter_name_thread_time_id_) {
-      event_data_->thread_timestamp = static_cast<int64_t>(value);
-    } else if (counter_name ==
-               parser_->counter_name_thread_instruction_count_id_) {
-      event_data_->thread_instruction_count = static_cast<int64_t>(value);
+      // Also import thread_time and thread_instruction_count counters into
+      // slice columns to simplify JSON export.
+      StringId counter_name =
+          storage_->counter_track_table().name()[*counter_row];
+      if (counter_name == parser_->counter_name_thread_time_id_) {
+        event_data_->thread_timestamp = value;
+      } else if (counter_name ==
+                 parser_->counter_name_thread_instruction_count_id_) {
+        event_data_->thread_instruction_count = value;
+      }
     }
   }
 
@@ -635,13 +544,17 @@
           "TrackEvent with phase B without thread association");
     }
 
-    auto* thread_slices = storage_->mutable_thread_slice_table();
-    auto opt_slice_id = context_->slice_tracker->BeginTyped(
-        thread_slices, MakeThreadSliceRow(),
+    auto opt_slice_id = context_->slice_tracker->Begin(
+        ts_, track_id_, category_id_, name_id_,
         [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
-
     if (opt_slice_id.has_value()) {
-      MaybeParseFlowEvents();
+      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(), event_data_->thread_timestamp,
+          kPendingThreadDuration, event_data_->thread_instruction_count,
+          kPendingThreadInstructionDelta);
     }
 
     return util::OkStatus();
@@ -657,21 +570,10 @@
         ts_, track_id_, category_id_, name_id_,
         [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
     if (opt_slice_id.has_value()) {
-      auto* thread_slices = storage_->mutable_thread_slice_table();
-      auto maybe_row = thread_slices->id().IndexOf(*opt_slice_id);
-      PERFETTO_DCHECK(maybe_row.has_value());
-      auto tts = thread_slices->thread_ts()[*maybe_row];
-      if (tts) {
-        PERFETTO_DCHECK(event_data_->thread_timestamp);
-        thread_slices->mutable_thread_dur()->Set(
-            *maybe_row, *event_data_->thread_timestamp - *tts);
-      }
-      auto tic = thread_slices->thread_instruction_count()[*maybe_row];
-      if (tic) {
-        PERFETTO_DCHECK(event_data_->thread_instruction_count);
-        thread_slices->mutable_thread_instruction_delta()->Set(
-            *maybe_row, *event_data_->thread_instruction_count - *tic);
-      }
+      auto* thread_slices = storage_->mutable_thread_slices();
+      thread_slices->UpdateThreadDeltasForSliceId(
+          opt_slice_id.value(), event_data_->thread_timestamp,
+          event_data_->thread_instruction_count);
     }
 
     return util::OkStatus();
@@ -686,195 +588,56 @@
     auto duration_ns = legacy_event_.duration_us() * 1000;
     if (duration_ns < 0)
       return util::ErrStatus("TrackEvent with phase X with negative duration");
-
-    auto* thread_slices = storage_->mutable_thread_slice_table();
-    tables::ThreadSliceTable::Row row = MakeThreadSliceRow();
-    row.dur = duration_ns;
-    if (legacy_event_.has_thread_duration_us()) {
-      row.thread_dur = legacy_event_.thread_duration_us() * 1000;
-    }
-    if (legacy_event_.has_thread_instruction_delta()) {
-      row.thread_instruction_delta = legacy_event_.thread_instruction_delta();
-    }
-    auto opt_slice_id = context_->slice_tracker->ScopedTyped(
-        thread_slices, std::move(row),
+    auto opt_slice_id = context_->slice_tracker->Scoped(
+        ts_, track_id_, category_id_, name_id_, duration_ns,
         [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
-
     if (opt_slice_id.has_value()) {
-      MaybeParseFlowEvents();
+      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(), event_data_->thread_timestamp,
+          thread_duration_ns, event_data_->thread_instruction_count,
+          legacy_event_.thread_instruction_delta());
     }
 
     return util::OkStatus();
   }
 
-  base::Optional<uint64_t> GetLegacyEventId() {
-    if (legacy_event_.has_unscoped_id())
-      return legacy_event_.unscoped_id();
-    // TODO(andrewbb): Catapult doesn't support global_id and local_id on flow
-    // events. We could add support in trace processor (e.g. because there seem
-    // to be some callsites supplying local_id in chromium), but we would have
-    // to consider the process ID for local IDs and use a separate ID scope for
-    // global_id and unscoped_id.
-    return base::nullopt;
-  }
-
-  util::Status ParseFlowEventV1(char phase) {
-    auto opt_source_id = GetLegacyEventId();
-    if (!opt_source_id) {
-      storage_->IncrementStats(stats::flow_invalid_id);
-      return util::ErrStatus("Invalid id for flow event v1");
-    }
-    FlowId flow_id = context_->flow_tracker->GetFlowIdForV1Event(
-        opt_source_id.value(), category_id_, name_id_);
-    switch (phase) {
-      case 's':
-        context_->flow_tracker->Begin(track_id_, flow_id);
-        break;
-      case 't':
-        context_->flow_tracker->Step(track_id_, flow_id);
-        break;
-      case 'f':
-        context_->flow_tracker->End(track_id_, flow_id,
-                                    legacy_event_.bind_to_enclosing(),
-                                    /* close_flow = */ false);
-        break;
-    }
-    return util::OkStatus();
-  }
-
-  void MaybeParseTrackEventFlows() {
-    if (event_.has_flow_ids()) {
-      auto it = event_.flow_ids();
-      for (; it; ++it) {
-        FlowId flow_id = *it;
-        if (!context_->flow_tracker->IsActive(flow_id)) {
-          context_->flow_tracker->Begin(track_id_, flow_id);
-          continue;
-        }
-        context_->flow_tracker->Step(track_id_, flow_id);
-      }
-    }
-    if (event_.has_terminating_flow_ids()) {
-      auto it = event_.terminating_flow_ids();
-      for (; it; ++it) {
-        FlowId flow_id = *it;
-        if (!context_->flow_tracker->IsActive(flow_id)) {
-          // If we should terminate a flow, do not begin a new one if it's not
-          // active already.
-          continue;
-        }
-        context_->flow_tracker->End(track_id_, flow_id,
-                                    /* bind_enclosing_slice = */ true,
-                                    /* close_flow = */ true);
-      }
-    }
-  }
-
-  void MaybeParseFlowEventV2() {
-    if (!legacy_event_.has_bind_id()) {
-      return;
-    }
-    if (!legacy_event_.has_flow_direction()) {
-      storage_->IncrementStats(stats::flow_without_direction);
-      return;
-    }
-
-    auto bind_id = legacy_event_.bind_id();
-    switch (legacy_event_.flow_direction()) {
-      case LegacyEvent::FLOW_OUT:
-        context_->flow_tracker->Begin(track_id_, bind_id);
-        break;
-      case LegacyEvent::FLOW_INOUT:
-        context_->flow_tracker->Step(track_id_, bind_id);
-        break;
-      case LegacyEvent::FLOW_IN:
-        context_->flow_tracker->End(track_id_, bind_id,
-                                    /* bind_enclosing_slice = */ true,
-                                    /* close_flow = */ false);
-        break;
-      default:
-        storage_->IncrementStats(stats::flow_without_direction);
-    }
-  }
-
-  void MaybeParseFlowEvents() {
-    MaybeParseFlowEventV2();
-    MaybeParseTrackEventFlows();
-  }
-
-  util::Status ParseThreadInstantEvent(char phase) {
+  util::Status ParseThreadInstantEvent() {
     // 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;
-    base::Optional<tables::SliceTable::Id> opt_slice_id;
-    auto args_inserter = [this, phase](BoundInserter* inserter) {
-      ParseTrackEventArgs(inserter);
-      // For legacy MARK event, add phase for JSON exporter.
-      if (phase == 'R') {
-        std::string phase_string(1, static_cast<char>(phase));
-        StringId phase_id = storage_->InternString(phase_string.c_str());
-        inserter->AddArg(parser_->legacy_event_phase_key_id_,
-                         Variadic::String(phase_id));
-      }
-    };
-    if (utid_) {
-      auto* thread_slices = storage_->mutable_thread_slice_table();
-      tables::ThreadSliceTable::Row row = MakeThreadSliceRow();
-      row.dur = duration_ns;
-      if (event_data_->thread_timestamp) {
-        row.thread_dur = duration_ns;
-      }
-      if (event_data_->thread_instruction_count) {
-        row.thread_instruction_delta = tidelta;
-      }
-      opt_slice_id = context_->slice_tracker->ScopedTyped(
-          thread_slices, row, std::move(args_inserter));
-    } else {
-      opt_slice_id = context_->slice_tracker->Scoped(
-          ts_, track_id_, category_id_, name_id_, duration_ns,
-          std::move(args_inserter));
+    auto opt_slice_id = context_->slice_tracker->Scoped(
+        ts_, track_id_, category_id_, name_id_, duration_ns,
+        [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
+    if (utid_ && 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(), event_data_->thread_timestamp, duration_ns,
+          event_data_->thread_instruction_count, tidelta);
     }
-    if (!opt_slice_id.has_value()) {
-      return util::OkStatus();
-    }
-    MaybeParseFlowEvents();
     return util::OkStatus();
   }
 
-  util::Status ParseAsyncBeginEvent(char phase) {
-    auto args_inserter = [this, phase](BoundInserter* inserter) {
-      ParseTrackEventArgs(inserter);
-
-      if (phase == 'b')
-        return;
-      PERFETTO_DCHECK(phase == 'S');
-      // For legacy ASYNC_BEGIN, add phase for JSON exporter.
-      std::string phase_string(1, static_cast<char>(phase));
-      StringId phase_id = storage_->InternString(phase_string.c_str());
-      inserter->AddArg(parser_->legacy_event_phase_key_id_,
-                       Variadic::String(phase_id));
-    };
+  util::Status ParseAsyncBeginEvent() {
     auto opt_slice_id = context_->slice_tracker->Begin(
-        ts_, track_id_, category_id_, name_id_, args_inserter);
-    if (!opt_slice_id.has_value()) {
-      return util::OkStatus();
-    }
-    MaybeParseFlowEvents();
-    // For the time being, we only create vtrack slice rows if we need to
+        ts_, track_id_, category_id_, name_id_,
+        [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
+    // For the time beeing, we only create vtrack slice rows if we need to
     // store thread timestamps/counters.
-    if (legacy_event_.use_async_tts()) {
+    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());
-      int64_t tts =
-          event_data_->thread_timestamp ? *event_data_->thread_timestamp : 0;
-      int64_t tic = event_data_->thread_instruction_count
-                        ? *event_data_->thread_instruction_count
-                        : 0;
-      vtrack_slices->AddVirtualTrackSlice(opt_slice_id.value(), tts,
-                                          kPendingThreadDuration, tic,
-                                          kPendingThreadInstructionDelta);
+      vtrack_slices->AddVirtualTrackSlice(
+          opt_slice_id.value(), event_data_->thread_timestamp,
+          kPendingThreadDuration, event_data_->thread_instruction_count,
+          kPendingThreadInstructionDelta);
     }
     return util::OkStatus();
   }
@@ -885,38 +648,13 @@
         [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
     if (legacy_event_.use_async_tts() && opt_slice_id.has_value()) {
       auto* vtrack_slices = storage_->mutable_virtual_track_slices();
-      int64_t tts =
-          event_data_->thread_timestamp ? *event_data_->thread_timestamp : 0;
-      int64_t tic = event_data_->thread_instruction_count
-                        ? *event_data_->thread_instruction_count
-                        : 0;
-      vtrack_slices->UpdateThreadDeltasForSliceId(opt_slice_id.value(), tts,
-                                                  tic);
+      vtrack_slices->UpdateThreadDeltasForSliceId(
+          opt_slice_id.value(), event_data_->thread_timestamp,
+          event_data_->thread_instruction_count);
     }
     return util::OkStatus();
   }
 
-  util::Status ParseAsyncStepEvent(char phase) {
-    // Parse step events as instant events. Reconstructing the begin/end times
-    // of the child slice would be too complicated, see b/178540838. For JSON
-    // export, we still record the original step's phase in an arg.
-    int64_t duration_ns = 0;
-    context_->slice_tracker->Scoped(
-        ts_, track_id_, category_id_, name_id_, duration_ns,
-        [this, phase](BoundInserter* inserter) {
-          ParseTrackEventArgs(inserter);
-
-          PERFETTO_DCHECK(phase == 'T' || phase == 'p');
-          std::string phase_string(1, static_cast<char>(phase));
-          StringId phase_id = storage_->InternString(phase_string.c_str());
-          inserter->AddArg(parser_->legacy_event_phase_key_id_,
-                           Variadic::String(phase_id));
-        });
-    // Step events don't support thread timestamps, so no need to add a row to
-    // virtual_track_slices.
-    return util::OkStatus();
-  }
-
   util::Status ParseAsyncInstantEvent() {
     // Handle instant events as slices with zero duration, so that they end
     // up nested underneath their parent slices.
@@ -925,21 +663,13 @@
     auto opt_slice_id = context_->slice_tracker->Scoped(
         ts_, track_id_, category_id_, name_id_, duration_ns,
         [this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
-    if (!opt_slice_id.has_value()) {
-      return util::OkStatus();
-    }
-    MaybeParseFlowEvents();
-    if (legacy_event_.use_async_tts()) {
+    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());
-      int64_t tts =
-          event_data_->thread_timestamp ? *event_data_->thread_timestamp : 0;
-      int64_t tic = event_data_->thread_instruction_count
-                        ? *event_data_->thread_instruction_count
-                        : 0;
-      vtrack_slices->AddVirtualTrackSlice(opt_slice_id.value(), tts,
-                                          duration_ns, tic, tidelta);
+      vtrack_slices->AddVirtualTrackSlice(
+          opt_slice_id.value(), event_data_->thread_timestamp, duration_ns,
+          event_data_->thread_instruction_count, tidelta);
     }
     return util::OkStatus();
   }
@@ -969,9 +699,8 @@
       if (!thread_name.size)
         return util::OkStatus();
       auto thread_name_id = storage_->InternString(thread_name);
-      procs->UpdateThreadNameByUtid(
-          *utid_, thread_name_id,
-          ThreadNamePriority::kTrackDescriptorThreadType);
+      // Don't override system-provided names.
+      procs->SetThreadNameIfUnset(*utid_, thread_name_id);
       return util::OkStatus();
     }
     if (strcmp(event_name.c_str(), "process_name") == 0) {
@@ -989,8 +718,7 @@
       auto process_name = annotation.string_value();
       if (!process_name.size)
         return util::OkStatus();
-      auto process_name_id =
-          storage_->InternString(base::StringView(process_name));
+      auto process_name_id = storage_->InternString(process_name);
       // Don't override system-provided names.
       procs->SetProcessNameIfUnset(*upid_, process_name_id);
       return util::OkStatus();
@@ -1028,7 +756,7 @@
 
     if (event_data_->thread_timestamp) {
       inserter.AddArg(parser_->legacy_event_thread_timestamp_ns_key_id_,
-                      Variadic::Integer(*event_data_->thread_timestamp));
+                      Variadic::Integer(event_data_->thread_timestamp));
       if (legacy_event_.has_thread_duration_us()) {
         inserter.AddArg(
             parser_->legacy_event_thread_duration_ns_key_id_,
@@ -1037,9 +765,8 @@
     }
 
     if (event_data_->thread_instruction_count) {
-      inserter.AddArg(
-          parser_->legacy_event_thread_instruction_count_key_id_,
-          Variadic::Integer(*event_data_->thread_instruction_count));
+      inserter.AddArg(parser_->legacy_event_thread_instruction_count_key_id_,
+                      Variadic::Integer(event_data_->thread_instruction_count));
       if (legacy_event_.has_thread_instruction_delta()) {
         inserter.AddArg(
             parser_->legacy_event_thread_instruction_delta_key_id_,
@@ -1093,11 +820,7 @@
     };
 
     for (auto it = event_.debug_annotations(); it; ++it) {
-      log_errors(ParseDebugAnnotation(*it, inserter));
-    }
-
-    if (event_.has_source_location_iid()) {
-      log_errors(AddSourceLocationArgs(event_.source_location_iid(), inserter));
+      log_errors(ParseDebugAnnotationArgs(*it, inserter));
     }
 
     if (event_.has_task_execution()) {
@@ -1106,37 +829,57 @@
     if (event_.has_log_message()) {
       log_errors(ParseLogMessage(event_.log_message(), inserter));
     }
-    if (event_.has_chrome_histogram_sample()) {
-      log_errors(
-          ParseHistogramName(event_.chrome_histogram_sample(), inserter));
-    }
 
-    TrackEventArgsParser args_writer(*inserter, *storage_, *sequence_state_);
-    log_errors(parser_->args_parser_.ParseMessage(
-        blob_, ".perfetto.protos.TrackEvent", &parser_->reflect_fields_,
-        args_writer));
+    log_errors(parser_->proto_to_args_.InternProtoFieldsIntoArgsTable(
+        blob_, ".perfetto.protos.TrackEvent", parser_->reflect_fields_,
+        inserter, sequence_state_));
 
     if (legacy_passthrough_utid_) {
       inserter->AddArg(parser_->legacy_event_passthrough_utid_id_,
                        Variadic::UnsignedInteger(*legacy_passthrough_utid_),
                        ArgsTracker::UpdatePolicy::kSkipIfExists);
     }
+
+    // TODO(eseckler): Parse legacy flow events into flow events table once we
+    // have a design for it.
+    if (legacy_event_.has_bind_id()) {
+      inserter->AddArg(parser_->legacy_event_bind_id_key_id_,
+                       Variadic::UnsignedInteger(legacy_event_.bind_id()));
+    }
+
+    if (legacy_event_.bind_to_enclosing()) {
+      inserter->AddArg(parser_->legacy_event_bind_to_enclosing_key_id_,
+                       Variadic::Boolean(true));
+    }
+
+    if (legacy_event_.flow_direction()) {
+      StringId value = kNullStringId;
+      switch (legacy_event_.flow_direction()) {
+        case LegacyEvent::FLOW_IN:
+          value = parser_->flow_direction_value_in_id_;
+          break;
+        case LegacyEvent::FLOW_OUT:
+          value = parser_->flow_direction_value_out_id_;
+          break;
+        case LegacyEvent::FLOW_INOUT:
+          value = parser_->flow_direction_value_inout_id_;
+          break;
+        default:
+          PERFETTO_ELOG("Unknown flow direction: %d",
+                        legacy_event_.flow_direction());
+          break;
+      }
+      inserter->AddArg(parser_->legacy_event_flow_direction_key_id_,
+                       Variadic::String(value));
+    }
   }
 
-  util::Status ParseDebugAnnotation(ConstBytes data, BoundInserter* inserter) {
-    protos::pbzero::DebugAnnotation::Decoder annotation(data);
+  util::Status ParseDebugAnnotationArgs(ConstBytes debug_annotation,
+                                        BoundInserter* inserter) {
+    protos::pbzero::DebugAnnotation::Decoder annotation(debug_annotation);
 
-    std::string name;
-    util::Status name_parse_result = ParseDebugAnnotationName(annotation, name);
-    if (!name_parse_result.ok())
-      return name_parse_result;
+    StringId name_id = kNullStringId;
 
-    return ParseDebugAnnotationValue(annotation, inserter, "debug." + name);
-  }
-
-  util::Status ParseDebugAnnotationName(
-      protos::pbzero::DebugAnnotation::Decoder& annotation,
-      std::string& result) {
     uint64_t name_iid = annotation.name_iid();
     if (PERFETTO_LIKELY(name_iid)) {
       auto* decoder = sequence_state_->LookupInternedMessage<
@@ -1145,20 +888,14 @@
       if (!decoder)
         return util::ErrStatus("Debug annotation with invalid name_iid");
 
-      result = SanitizeDebugAnnotationName(decoder->name().ToStdString());
+      std::string name_prefixed =
+          SafeDebugAnnotationName(decoder->name().ToStdString());
+      name_id = storage_->InternString(base::StringView(name_prefixed));
     } else if (annotation.has_name()) {
-      result = SanitizeDebugAnnotationName(annotation.name().ToStdString());
+      name_id = storage_->InternString(annotation.name());
     } else {
       return util::ErrStatus("Debug annotation without name");
     }
-    return util::OkStatus();
-  }
-
-  util::Status ParseDebugAnnotationValue(
-      protos::pbzero::DebugAnnotation::Decoder& annotation,
-      BoundInserter* inserter,
-      const std::string& context_name) {
-    StringId name_id = storage_->InternString(base::StringView(context_name));
 
     if (annotation.has_bool_value()) {
       inserter->AddArg(name_id, Variadic::Boolean(annotation.bool_value()));
@@ -1175,34 +912,6 @@
           Variadic::String(storage_->InternString(annotation.string_value())));
     } else if (annotation.has_pointer_value()) {
       inserter->AddArg(name_id, Variadic::Pointer(annotation.pointer_value()));
-    } else if (annotation.has_dict_entries()) {
-      for (auto it = annotation.dict_entries(); it; ++it) {
-        protos::pbzero::DebugAnnotation::Decoder key_value(*it);
-        std::string key;
-        util::Status key_parse_result =
-            ParseDebugAnnotationName(key_value, key);
-        if (!key_parse_result.ok())
-          return key_parse_result;
-
-        std::string child_flat_key = context_name + "." + key;
-        util::Status value_parse_result =
-            ParseDebugAnnotationValue(key_value, inserter, child_flat_key);
-        if (!value_parse_result.ok())
-          return value_parse_result;
-      }
-    } else if (annotation.has_array_values()) {
-      size_t index = 0;
-      for (auto it = annotation.array_values(); it; ++it) {
-        protos::pbzero::DebugAnnotation::Decoder value(*it);
-
-        std::string child_flat_key =
-            context_name + "[" + std::to_string(index) + "]";
-        util::Status value_parse_result =
-            ParseDebugAnnotationValue(value, inserter, child_flat_key);
-        if (!value_parse_result.ok())
-          return value_parse_result;
-        ++index;
-      }
     } else if (annotation.has_legacy_json_value()) {
       if (!json::IsJsonSupported())
         return util::ErrStatus("Ignoring legacy_json_value (no json support)");
@@ -1256,8 +965,7 @@
         auto value_it = value.dict_values();
         bool inserted = false;
         for (; key_it && value_it; ++key_it, ++value_it) {
-          std::string child_name =
-              SanitizeDebugAnnotationName((*key_it).ToStdString());
+          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;
@@ -1317,33 +1025,6 @@
     return util::OkStatus();
   }
 
-  util::Status AddSourceLocationArgs(uint64_t iid, BoundInserter* inserter) {
-    if (!iid)
-      return util::ErrStatus("SourceLocation with invalid iid");
-
-    auto* decoder = sequence_state_->LookupInternedMessage<
-        protos::pbzero::InternedData::kSourceLocationsFieldNumber,
-        protos::pbzero::SourceLocation>(iid);
-    if (!decoder)
-      return util::ErrStatus("SourceLocation with invalid iid");
-
-    StringId file_name_id = kNullStringId;
-    StringId function_name_id = kNullStringId;
-    uint32_t line_number = 0;
-
-    file_name_id = storage_->InternString(decoder->file_name());
-    function_name_id = storage_->InternString(decoder->function_name());
-    line_number = decoder->line_number();
-
-    inserter->AddArg(parser_->source_location_file_name_key_id_,
-                     Variadic::String(file_name_id));
-    inserter->AddArg(parser_->source_location_function_name_key_id_,
-                     Variadic::String(function_name_id));
-    inserter->AddArg(parser_->source_location_line_number_key_id_,
-                     Variadic::UnsignedInteger(line_number));
-    return util::OkStatus();
-  }
-
   util::Status ParseLogMessage(ConstBytes blob, BoundInserter* inserter) {
     if (!utid_)
       return util::ErrStatus("LogMessage without thread association");
@@ -1375,43 +1056,7 @@
     return util::OkStatus();
   }
 
-  util::Status ParseHistogramName(ConstBytes blob, BoundInserter* inserter) {
-    protos::pbzero::ChromeHistogramSample::Decoder sample(blob);
-    if (!sample.has_name_iid())
-      return util::OkStatus();
-
-    if (sample.has_name()) {
-      return util::ErrStatus(
-          "name is already set for ChromeHistogramSample: only one of name and "
-          "name_iid can be set.");
-    }
-
-    auto* decoder = sequence_state_->LookupInternedMessage<
-        protos::pbzero::InternedData::kHistogramNamesFieldNumber,
-        protos::pbzero::HistogramName>(sample.name_iid());
-    if (!decoder)
-      return util::ErrStatus("HistogramName with invalid name_iid");
-
-    inserter->AddArg(parser_->histogram_name_key_id_,
-                     Variadic::String(storage_->InternString(decoder->name())));
-    return util::OkStatus();
-  }
-
-  tables::ThreadSliceTable::Row MakeThreadSliceRow() {
-    tables::ThreadSliceTable::Row row;
-    row.ts = ts_;
-    row.track_id = track_id_;
-    row.category = category_id_;
-    row.name = name_id_;
-    row.thread_ts = event_data_->thread_timestamp;
-    row.thread_dur = base::nullopt;
-    row.thread_instruction_count = event_data_->thread_instruction_count;
-    row.thread_instruction_delta = base::nullopt;
-    return row;
-  }
-
   TraceProcessorContext* context_;
-  TrackEventTracker* track_event_tracker_;
   TraceStorage* storage_;
   TrackEventParser* parser_;
   int64_t ts_;
@@ -1436,11 +1081,9 @@
   base::Optional<UniqueTid> legacy_passthrough_utid_;
 };
 
-TrackEventParser::TrackEventParser(TraceProcessorContext* context,
-                                   TrackEventTracker* track_event_tracker)
-    : args_parser_(*context->descriptor_pool_.get()),
-      context_(context),
-      track_event_tracker_(track_event_tracker),
+TrackEventParser::TrackEventParser(TraceProcessorContext* context)
+    : context_(context),
+      proto_to_args_(context_),
       counter_name_thread_time_id_(
           context->storage->InternString("thread_time")),
       counter_name_thread_instruction_count_id_(
@@ -1453,12 +1096,6 @@
           context->storage->InternString("task.posted_from.line_number")),
       log_message_body_key_id_(
           context->storage->InternString("track_event.log_message")),
-      source_location_function_name_key_id_(
-          context->storage->InternString("source.function_name")),
-      source_location_file_name_key_id_(
-          context->storage->InternString("source.file_name")),
-      source_location_line_number_key_id_(
-          context->storage->InternString("source.line_number")),
       raw_legacy_event_id_(
           context->storage->InternString("track_event.legacy_event")),
       legacy_event_passthrough_utid_id_(
@@ -1497,8 +1134,6 @@
           context->storage->InternString("legacy_event.bind_to_enclosing")),
       legacy_event_flow_direction_key_id_(
           context->storage->InternString("legacy_event.flow_direction")),
-      histogram_name_key_id_(
-          context->storage->InternString("chrome_histogram_sample.name")),
       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")),
@@ -1506,43 +1141,99 @@
           context->storage->InternString("legacy_ipc.class")),
       chrome_legacy_ipc_line_args_key_id_(
           context->storage->InternString("legacy_ipc.line")),
-      chrome_host_app_package_name_id_(
-          context->storage->InternString("chrome.host_app_package_name")),
-      chrome_crash_trace_id_name_id_(
-          context->storage->InternString("chrome.crash_trace_id")),
-      chrome_string_lookup_(context->storage.get()),
+      chrome_legacy_ipc_class_ids_{
+          {context->storage->InternString("UNSPECIFIED"),
+           context->storage->InternString("AUTOMATION"),
+           context->storage->InternString("FRAME"),
+           context->storage->InternString("PAGE"),
+           context->storage->InternString("VIEW"),
+           context->storage->InternString("WIDGET"),
+           context->storage->InternString("INPUT"),
+           context->storage->InternString("TEST"),
+           context->storage->InternString("WORKER"),
+           context->storage->InternString("NACL"),
+           context->storage->InternString("GPU_CHANNEL"),
+           context->storage->InternString("MEDIA"),
+           context->storage->InternString("PPAPI"),
+           context->storage->InternString("CHROME"),
+           context->storage->InternString("DRAG"),
+           context->storage->InternString("PRINT"),
+           context->storage->InternString("EXTENSION"),
+           context->storage->InternString("TEXT_INPUT_CLIENT"),
+           context->storage->InternString("BLINK_TEST"),
+           context->storage->InternString("ACCESSIBILITY"),
+           context->storage->InternString("PRERENDER"),
+           context->storage->InternString("CHROMOTING"),
+           context->storage->InternString("BROWSER_PLUGIN"),
+           context->storage->InternString("ANDROID_WEB_VIEW"),
+           context->storage->InternString("NACL_HOST"),
+           context->storage->InternString("ENCRYPTED_MEDIA"),
+           context->storage->InternString("CAST"),
+           context->storage->InternString("GIN_JAVA_BRIDGE"),
+           context->storage->InternString("CHROME_UTILITY_PRINTING"),
+           context->storage->InternString("OZONE_GPU"),
+           context->storage->InternString("WEB_TEST"),
+           context->storage->InternString("NETWORK_HINTS"),
+           context->storage->InternString("EXTENSIONS_GUEST_VIEW"),
+           context->storage->InternString("GUEST_VIEW"),
+           context->storage->InternString("MEDIA_PLAYER_DELEGATE"),
+           context->storage->InternString("EXTENSION_WORKER"),
+           context->storage->InternString("SUBRESOURCE_FILTER"),
+           context->storage->InternString("UNFREEZABLE_FRAME")}},
+      chrome_process_name_ids_{
+          {kNullStringId, 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")}},
+      chrome_thread_name_ids_{
+          {kNullStringId, context_->storage->InternString("CrProcessMain"),
+           context_->storage->InternString("ChromeIOThread"),
+           context_->storage->InternString("ThreadPoolBackgroundWorker&"),
+           context_->storage->InternString("ThreadPoolForegroundWorker&"),
+           context_->storage->InternString(
+               "ThreadPoolSingleThreadForegroundBlocking&"),
+           context_->storage->InternString(
+               "ThreadPoolSingleThreadBackgroundBlocking&"),
+           context_->storage->InternString("ThreadPoolService"),
+           context_->storage->InternString("Compositor"),
+           context_->storage->InternString("VizCompositorThread"),
+           context_->storage->InternString("CompositorTileWorker&"),
+           context_->storage->InternString("ServiceWorkerThread&"),
+           context_->storage->InternString("MemoryInfra"),
+           context_->storage->InternString("StackSamplingProfiler")}},
       counter_unit_ids_{{kNullStringId, context_->storage->InternString("ns"),
                          context_->storage->InternString("count"),
                          context_->storage->InternString("bytes")}} {
+  auto status = proto_to_args_.AddProtoFileDescriptor(
+      kTrackEventDescriptor.data(), kTrackEventDescriptor.size());
+  PERFETTO_DCHECK(status.ok());
+
   // Switch |source_location_iid| into its interned data variant.
-  args_parser_.AddParsingOverride(
+  proto_to_args_.AddParsingOverride(
       "begin_impl_frame_args.current_args.source_location_iid",
-      [](const protozero::Field& field,
-         util::ProtoToArgsParser::Delegate& delegate) {
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, BoundInserter* inserter) {
         return MaybeParseSourceLocation("begin_impl_frame_args.current_args",
-                                        field, delegate);
+                                        state, field, inserter);
       });
-  args_parser_.AddParsingOverride(
+  proto_to_args_.AddParsingOverride(
       "begin_impl_frame_args.last_args.source_location_iid",
-      [](const protozero::Field& field,
-         util::ProtoToArgsParser::Delegate& delegate) {
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, BoundInserter* inserter) {
         return MaybeParseSourceLocation("begin_impl_frame_args.last_args",
-                                        field, delegate);
+                                        state, field, inserter);
       });
-  args_parser_.AddParsingOverride(
+  proto_to_args_.AddParsingOverride(
       "begin_frame_observer_state.last_begin_frame_args.source_location_iid",
-      [](const protozero::Field& field,
-         util::ProtoToArgsParser::Delegate& delegate) {
+      [](const ProtoToArgsTable::ParsingOverrideState& state,
+         const protozero::Field& field, BoundInserter* inserter) {
         return MaybeParseSourceLocation(
-            "begin_frame_observer_state.last_begin_frame_args", field,
-            delegate);
-      });
-  args_parser_.AddParsingOverride(
-      "chrome_memory_pressure_notification.creation_location_iid",
-      [](const protozero::Field& field,
-         util::ProtoToArgsParser::Delegate& delegate) {
-        return MaybeParseSourceLocation("chrome_memory_pressure_notification",
-                                        field, delegate);
+            "begin_frame_observer_state.last_begin_frame_args", state, field,
+            inserter);
       });
 
   for (uint16_t index : kReflectFields) {
@@ -1556,7 +1247,8 @@
 
   // Ensure that the track and its parents are resolved. This may start a new
   // process and/or thread (i.e. new upid/utid).
-  TrackId track_id = *track_event_tracker_->GetDescriptorTrack(decoder.uuid());
+  TrackId track_id =
+      *context_->track_tracker->GetDescriptorTrack(decoder.uuid());
 
   if (decoder.has_thread()) {
     UniqueTid utid = ParseThreadDescriptor(decoder.thread());
@@ -1588,14 +1280,14 @@
     context_->process_tracker->SetProcessNameIfUnset(
         upid, context_->storage->InternString(decoder.process_name()));
   }
-  if (decoder.has_start_timestamp_ns() && decoder.start_timestamp_ns() > 0) {
-    context_->process_tracker->SetStartTsIfUnset(upid,
-                                                 decoder.start_timestamp_ns());
-  }
   // TODO(skyostil): Remove parsing for legacy chrome_process_type field.
   if (decoder.has_chrome_process_type()) {
-    StringId name_id =
-        chrome_string_lookup_.GetProcessName(decoder.chrome_process_type());
+    auto process_type = decoder.chrome_process_type();
+    size_t name_index =
+        static_cast<size_t>(process_type) < chrome_process_name_ids_.size()
+            ? static_cast<size_t>(process_type)
+            : 0u;
+    StringId name_id = chrome_process_name_ids_[name_index];
     // Don't override system-provided names.
     context_->process_tracker->SetProcessNameIfUnset(upid, name_id);
   }
@@ -1607,23 +1299,14 @@
     protozero::ConstBytes chrome_process_descriptor) {
   protos::pbzero::ChromeProcessDescriptor::Decoder decoder(
       chrome_process_descriptor);
-
-  StringId name_id =
-      chrome_string_lookup_.GetProcessName(decoder.process_type());
+  auto process_type = decoder.process_type();
+  size_t name_index =
+      static_cast<size_t>(process_type) < chrome_process_name_ids_.size()
+          ? static_cast<size_t>(process_type)
+          : 0u;
+  StringId name_id = chrome_process_name_ids_[name_index];
   // Don't override system-provided names.
   context_->process_tracker->SetProcessNameIfUnset(upid, name_id);
-
-  ArgsTracker::BoundInserter process_args =
-      context_->process_tracker->AddArgsTo(upid);
-  if (decoder.has_host_app_package_name()) {
-    process_args.AddArg(chrome_host_app_package_name_id_,
-                        Variadic::String(context_->storage->InternString(
-                            decoder.host_app_package_name())));
-  }
-  if (decoder.has_crash_trace_id()) {
-    process_args.AddArg(chrome_crash_trace_id_name_id_,
-                        Variadic::UnsignedInteger(decoder.crash_trace_id()));
-  }
 }
 
 UniqueTid TrackEventParser::ParseThreadDescriptor(
@@ -1637,10 +1320,17 @@
     name_id = context_->storage->InternString(decoder.thread_name());
   } else if (decoder.has_chrome_thread_type()) {
     // TODO(skyostil): Remove parsing for legacy chrome_thread_type field.
-    name_id = chrome_string_lookup_.GetThreadName(decoder.chrome_thread_type());
+    auto thread_type = decoder.chrome_thread_type();
+    size_t name_index =
+        static_cast<size_t>(thread_type) < chrome_thread_name_ids_.size()
+            ? static_cast<size_t>(thread_type)
+            : 0u;
+    name_id = chrome_thread_name_ids_[name_index];
   }
-  context_->process_tracker->UpdateThreadNameByUtid(
-      utid, name_id, ThreadNamePriority::kTrackDescriptor);
+  if (name_id != kNullStringId) {
+    // Don't override system-provided names.
+    context_->process_tracker->SetThreadNameIfUnset(utid, name_id);
+  }
   return utid;
 }
 
@@ -1652,9 +1342,13 @@
   if (!decoder.has_thread_type())
     return;
 
-  StringId name_id = chrome_string_lookup_.GetThreadName(decoder.thread_type());
-  context_->process_tracker->UpdateThreadNameByUtid(
-      utid, name_id, ThreadNamePriority::kTrackDescriptorThreadType);
+  auto thread_type = decoder.thread_type();
+  size_t name_index =
+      static_cast<size_t>(thread_type) < chrome_thread_name_ids_.size()
+          ? static_cast<size_t>(thread_type)
+          : 0u;
+  StringId name_id = chrome_thread_name_ids_[name_index];
+  context_->process_tracker->SetThreadNameIfUnset(utid, name_id);
 }
 
 void TrackEventParser::ParseCounterDescriptor(
@@ -1669,30 +1363,25 @@
   if (unit_index >= counter_unit_ids_.size())
     unit_index = CounterDescriptor::UNIT_UNSPECIFIED;
 
-  auto opt_track_idx = counter_tracks->id().IndexOf(track_id);
-  if (!opt_track_idx) {
-    context_->storage->IncrementStats(stats::track_event_parser_errors);
-    return;
-  }
-
-  auto track_idx = *opt_track_idx;
-
   switch (decoder.type()) {
     case CounterDescriptor::COUNTER_UNSPECIFIED:
       break;
     case CounterDescriptor::COUNTER_THREAD_TIME_NS:
       unit_index = CounterDescriptor::UNIT_TIME_NS;
-      counter_tracks->mutable_name()->Set(track_idx,
-                                          counter_name_thread_time_id_);
+      counter_tracks->mutable_name()->Set(
+          *counter_tracks->id().IndexOf(track_id),
+          counter_name_thread_time_id_);
       break;
     case CounterDescriptor::COUNTER_THREAD_INSTRUCTION_COUNT:
       unit_index = CounterDescriptor::UNIT_COUNT;
       counter_tracks->mutable_name()->Set(
-          track_idx, counter_name_thread_instruction_count_id_);
+          *counter_tracks->id().IndexOf(track_id),
+          counter_name_thread_instruction_count_id_);
       break;
   }
 
-  counter_tracks->mutable_unit()->Set(track_idx, counter_unit_ids_[unit_index]);
+  counter_tracks->mutable_unit()->Set(*counter_tracks->id().IndexOf(track_id),
+                                      counter_unit_ids_[unit_index]);
 }
 
 void TrackEventParser::ParseTrackEvent(int64_t ts,
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index 2b80701..b3abc4c 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -17,17 +17,13 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_PARSER_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_PARSER_H_
 
-#include <array>
-#include <map>
-
 #include "perfetto/base/build_config.h"
 #include "perfetto/protozero/field.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/importers/proto/chrome_string_lookup.h"
+#include "src/trace_processor/importers/proto/args_table_utils.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/util/proto_to_args_parser.h"
 
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
 
@@ -36,22 +32,21 @@
 }
 
 namespace perfetto {
+
 namespace trace_processor {
 
 // Field numbers to be added to args table automatically via reflection
 //
 // TODO(ddrone): replace with a predicate on field id to import new fields
 // automatically
-static constexpr uint16_t kReflectFields[] = {24, 25, 26, 27, 28, 29, 32, 33,
-                                              34, 35, 38, 39, 40, 41, 42, 43};
+static constexpr uint16_t kReflectFields[] = {24, 25, 26, 27, 28, 29};
 
 class PacketSequenceStateGeneration;
 class TraceProcessorContext;
-class TrackEventTracker;
 
 class TrackEventParser {
  public:
-  TrackEventParser(TraceProcessorContext*, TrackEventTracker*);
+  explicit TrackEventParser(TraceProcessorContext* context);
 
   void ParseTrackDescriptor(protozero::ConstBytes);
   UniquePid ParseProcessDescriptor(protozero::ConstBytes);
@@ -68,11 +63,8 @@
   void ParseChromeThreadDescriptor(UniqueTid, protozero::ConstBytes);
   void ParseCounterDescriptor(TrackId, protozero::ConstBytes);
 
-  // Reflection-based proto TrackEvent field parser.
-  util::ProtoToArgsParser args_parser_;
-
   TraceProcessorContext* context_;
-  TrackEventTracker* track_event_tracker_;
+  ProtoToArgsTable proto_to_args_;
 
   const StringId counter_name_thread_time_id_;
   const StringId counter_name_thread_instruction_count_id_;
@@ -80,9 +72,6 @@
   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 source_location_function_name_key_id_;
-  const StringId source_location_file_name_key_id_;
-  const StringId source_location_line_number_key_id_;
   const StringId raw_legacy_event_id_;
   const StringId legacy_event_passthrough_utid_id_;
   const StringId legacy_event_category_key_id_;
@@ -101,16 +90,15 @@
   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 histogram_name_key_id_;
   const StringId flow_direction_value_in_id_;
   const StringId flow_direction_value_out_id_;
   const StringId flow_direction_value_inout_id_;
   const StringId chrome_legacy_ipc_class_args_key_id_;
   const StringId chrome_legacy_ipc_line_args_key_id_;
-  const StringId chrome_host_app_package_name_id_;
-  const StringId chrome_crash_trace_id_name_id_;
 
-  ChromeStringLookup chrome_string_lookup_;
+  std::array<StringId, 38> chrome_legacy_ipc_class_ids_;
+  std::array<StringId, 9> chrome_process_name_ids_;
+  std::array<StringId, 14> chrome_thread_name_ids_;
   std::array<StringId, 4> counter_unit_ids_;
 
   std::vector<uint16_t> reflect_fields_;
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
index 9d28e46..a09f4e2 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.cc
@@ -19,13 +19,12 @@
 #include "perfetto/base/logging.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/proto_trace_reader.h"
-#include "src/trace_processor/importers/proto/track_event_tracker.h"
+#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/storage/stats.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/trace_sorter.h"
 
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
@@ -45,10 +44,8 @@
 using protos::pbzero::CounterDescriptor;
 }
 
-TrackEventTokenizer::TrackEventTokenizer(TraceProcessorContext* context,
-                                         TrackEventTracker* track_event_tracker)
+TrackEventTokenizer::TrackEventTokenizer(TraceProcessorContext* context)
     : context_(context),
-      track_event_tracker_(track_event_tracker),
       counter_name_thread_time_id_(
           context_->storage->InternString("thread_time")),
       counter_name_thread_instruction_count_id_(
@@ -87,7 +84,7 @@
       TokenizeThreadDescriptor(state, thread);
     }
 
-    track_event_tracker_->ReserveDescriptorThreadTrack(
+    context_->track_tracker->ReserveDescriptorThreadTrack(
         track.uuid(), track.parent_uuid(), name_id,
         static_cast<uint32_t>(thread.pid()),
         static_cast<uint32_t>(thread.tid()), packet_timestamp);
@@ -101,7 +98,7 @@
       return ModuleResult::Handled();
     }
 
-    track_event_tracker_->ReserveDescriptorProcessTrack(
+    context_->track_tracker->ReserveDescriptorProcessTrack(
         track.uuid(), name_id, static_cast<uint32_t>(process.pid()),
         packet_timestamp);
   } else if (track.has_counter()) {
@@ -128,7 +125,7 @@
     // threads, in which case it has to use absolute values on a different
     // track_uuid. Right now these absolute values are imported onto a separate
     // counter track than the other thread's regular thread time values.)
-    if (name_id.is_null()) {
+    if (name_id == kNullStringId) {
       switch (counter.type()) {
         case CounterDescriptor::COUNTER_UNSPECIFIED:
           break;
@@ -141,16 +138,16 @@
       }
     }
 
-    track_event_tracker_->ReserveDescriptorCounterTrack(
+    context_->track_tracker->ReserveDescriptorCounterTrack(
         track.uuid(), track.parent_uuid(), name_id, category_id,
         counter.unit_multiplier(), counter.is_incremental(),
         packet.trusted_packet_sequence_id());
   } else {
-    track_event_tracker_->ReserveDescriptorChildTrack(
+    context_->track_tracker->ReserveDescriptorChildTrack(
         track.uuid(), track.parent_uuid(), name_id);
   }
 
-  // Let ProtoTraceReader forward the packet to the parser.
+  // Let ProtoTraceTokenizer forward the packet to the parser.
   return ModuleResult::Ignored();
 }
 
@@ -176,7 +173,7 @@
   protos::pbzero::ThreadDescriptor::Decoder thread(packet.thread_descriptor());
   TokenizeThreadDescriptor(state, thread);
 
-  // Let ProtoTraceReader forward the packet to the parser.
+  // Let ProtoTraceTokenizer forward the packet to the parser.
   return ModuleResult::Ignored();
 }
 
@@ -279,6 +276,8 @@
     data->thread_instruction_count = event.thread_instruction_count_absolute();
   }
 
+  // TODO(eseckler): Also convert & attach counter values from TYPE_COUNTER
+  // events and extra_counter_* fields.
   if (event.type() == protos::pbzero::TrackEvent::TYPE_COUNTER) {
     // Consider track_uuid from the packet and TrackEventDefaults.
     uint64_t track_uuid;
@@ -293,26 +292,19 @@
       return;
     }
 
-    if (!event.has_counter_value() && !event.has_double_counter_value()) {
+    if (!event.has_counter_value()) {
       PERFETTO_DLOG(
-          "Ignoring TrackEvent with TYPE_COUNTER but without counter_value or "
-          "double_counter_value for "
+          "Ignoring TrackEvent with TYPE_COUNTER but without counter_value for "
           "track_uuid %" PRIu64,
           track_uuid);
       context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
       return;
     }
 
-    base::Optional<double> value;
-    if (event.has_counter_value()) {
-      value = track_event_tracker_->ConvertToAbsoluteCounterValue(
-          track_uuid, packet.trusted_packet_sequence_id(),
-          static_cast<double>(event.counter_value()));
-    } else {
-      value = track_event_tracker_->ConvertToAbsoluteCounterValue(
-          track_uuid, packet.trusted_packet_sequence_id(),
-          event.double_counter_value());
-    }
+    base::Optional<int64_t> value =
+        context_->track_tracker->ConvertToAbsoluteCounterValue(
+            track_uuid, packet.trusted_packet_sequence_id(),
+            event.counter_value());
 
     if (!value) {
       PERFETTO_DLOG("Ignoring TrackEvent with invalid track_uuid %" PRIu64,
@@ -324,78 +316,53 @@
     data->counter_value = *value;
   }
 
-  size_t index = 0;
-  const protozero::RepeatedFieldIterator<uint64_t> kEmptyIterator;
-  auto result = AddExtraCounterValues(
-      *data, index, packet.trusted_packet_sequence_id(),
-      event.extra_counter_values(), event.extra_counter_track_uuids(),
-      defaults ? defaults->extra_counter_track_uuids() : kEmptyIterator);
-  if (!result.ok()) {
-    PERFETTO_DLOG("%s", result.c_message());
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-  result = AddExtraCounterValues(
-      *data, index, packet.trusted_packet_sequence_id(),
-      event.extra_double_counter_values(),
-      event.extra_double_counter_track_uuids(),
-      defaults ? defaults->extra_double_counter_track_uuids() : kEmptyIterator);
-  if (!result.ok()) {
-    PERFETTO_DLOG("%s", result.c_message());
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
+  if (event.has_extra_counter_values()) {
+    // Consider extra_counter_track_uuids from the packet and
+    // TrackEventDefaults.
+    protozero::RepeatedFieldIterator<uint64_t> track_uuid_it;
+    if (event.has_extra_counter_track_uuids()) {
+      track_uuid_it = event.extra_counter_track_uuids();
+    } else if (defaults && defaults->has_extra_counter_track_uuids()) {
+      track_uuid_it = defaults->extra_counter_track_uuids();
+    } else {
+      PERFETTO_DLOG(
+          "Ignoring TrackEvent with extra_counter_values but without "
+          "extra_counter_track_uuids");
+      context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+      return;
+    }
+
+    size_t index = 0;
+    for (auto value_it = event.extra_counter_values(); value_it;
+         ++value_it, ++track_uuid_it, ++index) {
+      if (!track_uuid_it) {
+        PERFETTO_DLOG(
+            "Ignoring TrackEvent with more extra_counter_values than "
+            "extra_counter_track_uuids");
+        context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+        return;
+      }
+      if (index >= TrackEventData::kMaxNumExtraCounters) {
+        PERFETTO_ELOG(
+            "Ignoring TrackEvent with more extra_counter_values than "
+            "TrackEventData::kMaxNumExtraCounters");
+        context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+        return;
+      }
+      base::Optional<int64_t> value =
+          context_->track_tracker->ConvertToAbsoluteCounterValue(
+              *track_uuid_it, packet.trusted_packet_sequence_id(), *value_it);
+      if (!value) {
+        PERFETTO_DLOG("Ignoring TrackEvent with invalid extra counter track");
+        context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+        return;
+      }
+      data->extra_counter_values[index] = *value;
+    }
   }
 
   context_->sorter->PushTrackEventPacket(timestamp, std::move(data));
 }
 
-template <typename T>
-base::Status TrackEventTokenizer::AddExtraCounterValues(
-    TrackEventData& data,
-    size_t& index,
-    uint32_t trusted_packet_sequence_id,
-    protozero::RepeatedFieldIterator<T> value_it,
-    protozero::RepeatedFieldIterator<uint64_t> packet_track_uuid_it,
-    protozero::RepeatedFieldIterator<uint64_t> default_track_uuid_it) {
-  if (!value_it)
-    return base::OkStatus();
-
-  // Consider extra_{double_,}counter_track_uuids from the packet and
-  // TrackEventDefaults.
-  protozero::RepeatedFieldIterator<uint64_t> track_uuid_it;
-  if (packet_track_uuid_it) {
-    track_uuid_it = packet_track_uuid_it;
-  } else if (default_track_uuid_it) {
-    track_uuid_it = default_track_uuid_it;
-  } else {
-    return base::Status(
-        "Ignoring TrackEvent with extra_{double_,}counter_values but without "
-        "extra_{double_,}counter_track_uuids");
-  }
-
-  for (; value_it; ++value_it, ++track_uuid_it, ++index) {
-    if (!*track_uuid_it) {
-      return base::Status(
-          "Ignoring TrackEvent with more extra_{double_,}counter_values than "
-          "extra_{double_,}counter_track_uuids");
-    }
-    if (index >= TrackEventData::kMaxNumExtraCounters) {
-      return base::Status(
-          "Ignoring TrackEvent with more extra_{double_,}counter_values than "
-          "TrackEventData::kMaxNumExtraCounters");
-    }
-    base::Optional<double> abs_value =
-        track_event_tracker_->ConvertToAbsoluteCounterValue(
-            *track_uuid_it, trusted_packet_sequence_id,
-            static_cast<double>(*value_it));
-    if (!abs_value) {
-      return base::Status(
-          "Ignoring TrackEvent with invalid extra counter track");
-    }
-    data.extra_counter_values[index] = *abs_value;
-  }
-  return base::OkStatus();
-}
-
 }  // 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
index 0dc41f8..6657a48 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.h
@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 
-#include "perfetto/protozero/proto_decoder.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/storage/trace_storage.h"
 
@@ -39,12 +38,10 @@
 class PacketSequenceState;
 class TraceProcessorContext;
 class TraceBlobView;
-class TrackEventTracker;
-struct TrackEventData;
 
 class TrackEventTokenizer {
  public:
-  explicit TrackEventTokenizer(TraceProcessorContext*, TrackEventTracker*);
+  explicit TrackEventTokenizer(TraceProcessorContext* context);
 
   ModuleResult TokenizeTrackDescriptorPacket(
       PacketSequenceState* state,
@@ -62,17 +59,8 @@
   void TokenizeThreadDescriptor(
       PacketSequenceState* state,
       const protos::pbzero::ThreadDescriptor_Decoder&);
-  template <typename T>
-  base::Status AddExtraCounterValues(
-      TrackEventData& data,
-      size_t& index,
-      uint32_t trusted_packet_sequence_id,
-      protozero::RepeatedFieldIterator<T> value_it,
-      protozero::RepeatedFieldIterator<uint64_t> packet_track_uuid_it,
-      protozero::RepeatedFieldIterator<uint64_t> default_track_uuid_it);
 
   TraceProcessorContext* context_;
-  TrackEventTracker* track_event_tracker_;
 
   const StringId counter_name_thread_time_id_;
   const StringId counter_name_thread_instruction_count_id_;
diff --git a/src/trace_processor/importers/proto/track_event_tracker.cc b/src/trace_processor/importers/proto/track_event_tracker.cc
deleted file mode 100644
index bed158a..0000000
--- a/src/trace_processor/importers/proto/track_event_tracker.cc
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/importers/proto/track_event_tracker.h"
-
-#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/track_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// static
-constexpr uint64_t TrackEventTracker::kDefaultDescriptorTrackUuid;
-
-TrackEventTracker::TrackEventTracker(TraceProcessorContext* context)
-    : source_key_(context->storage->InternString("source")),
-      source_id_key_(context->storage->InternString("source_id")),
-      is_root_in_scope_key_(context->storage->InternString("is_root_in_scope")),
-      category_key_(context->storage->InternString("category")),
-      descriptor_source_(context->storage->InternString("descriptor")),
-      default_descriptor_track_name_(
-          context->storage->InternString("Default Track")),
-      context_(context) {}
-
-void TrackEventTracker::ReserveDescriptorProcessTrack(uint64_t uuid,
-                                                      StringId name,
-                                                      uint32_t pid,
-                                                      int64_t timestamp) {
-  DescriptorTrackReservation reservation;
-  reservation.min_timestamp = timestamp;
-  reservation.pid = pid;
-  reservation.name = name;
-
-  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
-  bool inserted;
-  std::tie(it, inserted) =
-      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
-
-  if (inserted)
-    return;
-
-  if (!it->second.IsForSameTrack(reservation)) {
-    // Process tracks should not be reassigned to a different pid later (neither
-    // should the type of the track change).
-    PERFETTO_DLOG("New track reservation for process track with uuid %" PRIu64
-                  " doesn't match earlier one",
-                  uuid);
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
-}
-
-void TrackEventTracker::ReserveDescriptorThreadTrack(uint64_t uuid,
-                                                     uint64_t parent_uuid,
-                                                     StringId name,
-                                                     uint32_t pid,
-                                                     uint32_t tid,
-                                                     int64_t timestamp) {
-  DescriptorTrackReservation reservation;
-  reservation.min_timestamp = timestamp;
-  reservation.parent_uuid = parent_uuid;
-  reservation.pid = pid;
-  reservation.tid = tid;
-  reservation.name = name;
-
-  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
-  bool inserted;
-  std::tie(it, inserted) =
-      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
-
-  if (inserted)
-    return;
-
-  if (!it->second.IsForSameTrack(reservation)) {
-    // Thread tracks should not be reassigned to a different pid/tid later
-    // (neither should the type of the track change).
-    PERFETTO_DLOG("New track reservation for thread track with uuid %" PRIu64
-                  " doesn't match earlier one",
-                  uuid);
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
-}
-
-void TrackEventTracker::ReserveDescriptorCounterTrack(
-    uint64_t uuid,
-    uint64_t parent_uuid,
-    StringId name,
-    StringId category,
-    int64_t unit_multiplier,
-    bool is_incremental,
-    uint32_t packet_sequence_id) {
-  DescriptorTrackReservation reservation;
-  reservation.parent_uuid = parent_uuid;
-  reservation.is_counter = true;
-  reservation.name = name;
-  reservation.category = category;
-  reservation.unit_multiplier = unit_multiplier;
-  reservation.is_incremental = is_incremental;
-  // Incrementally encoded counters are only valid on a single sequence.
-  if (is_incremental)
-    reservation.packet_sequence_id = packet_sequence_id;
-
-  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
-  bool inserted;
-  std::tie(it, inserted) =
-      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
-
-  if (inserted || it->second.IsForSameTrack(reservation))
-    return;
-
-  // Counter tracks should not be reassigned to a different parent track later
-  // (neither should the type of the track change).
-  PERFETTO_DLOG("New track reservation for counter track with uuid %" PRIu64
-                " doesn't match earlier one",
-                uuid);
-  context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-}
-
-void TrackEventTracker::ReserveDescriptorChildTrack(uint64_t uuid,
-                                                    uint64_t parent_uuid,
-                                                    StringId name) {
-  DescriptorTrackReservation reservation;
-  reservation.parent_uuid = parent_uuid;
-  reservation.name = name;
-
-  std::map<uint64_t, DescriptorTrackReservation>::iterator it;
-  bool inserted;
-  std::tie(it, inserted) =
-      reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
-
-  if (inserted || it->second.IsForSameTrack(reservation))
-    return;
-
-  // Child tracks should not be reassigned to a different parent track later
-  // (neither should the type of the track change).
-  PERFETTO_DLOG("New track reservation for child track with uuid %" PRIu64
-                " doesn't match earlier one",
-                uuid);
-  context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-}
-
-base::Optional<TrackId> TrackEventTracker::GetDescriptorTrack(
-    uint64_t uuid,
-    StringId event_name) {
-  base::Optional<TrackId> track_id = GetDescriptorTrackImpl(uuid);
-  if (!track_id || event_name.is_null())
-    return track_id;
-
-  // Update the name of the track if unset and the track is not the primary
-  // track of a process/thread or a counter track.
-  auto* tracks = context_->storage->mutable_track_table();
-  uint32_t row = *tracks->id().IndexOf(*track_id);
-  if (!tracks->name()[row].is_null())
-    return track_id;
-
-  // Check reservation for track type.
-  auto reservation_it = reserved_descriptor_tracks_.find(uuid);
-  PERFETTO_CHECK(reservation_it != reserved_descriptor_tracks_.end());
-
-  if (reservation_it->second.pid || reservation_it->second.tid ||
-      reservation_it->second.is_counter) {
-    return track_id;
-  }
-  tracks->mutable_name()->Set(row, event_name);
-  return track_id;
-}
-
-base::Optional<TrackId> TrackEventTracker::GetDescriptorTrackImpl(
-    uint64_t uuid) {
-  auto it = descriptor_tracks_.find(uuid);
-  if (it != descriptor_tracks_.end())
-    return it->second;
-
-  base::Optional<ResolvedDescriptorTrack> resolved_track =
-      ResolveDescriptorTrack(uuid, nullptr);
-  if (!resolved_track)
-    return base::nullopt;
-
-  // The reservation must exist as |resolved_track| would have been nullopt
-  // otherwise.
-  auto reserved_it = reserved_descriptor_tracks_.find(uuid);
-  PERFETTO_CHECK(reserved_it != reserved_descriptor_tracks_.end());
-
-  const auto& reservation = reserved_it->second;
-  TrackId track_id = CreateTrackFromResolved(*resolved_track);
-  descriptor_tracks_[uuid] = track_id;
-
-  auto args = context_->args_tracker->AddArgsTo(track_id);
-  args.AddArg(source_key_, Variadic::String(descriptor_source_))
-      .AddArg(source_id_key_, Variadic::Integer(static_cast<int64_t>(uuid)))
-      .AddArg(is_root_in_scope_key_,
-              Variadic::Boolean(resolved_track->is_root_in_scope()));
-  if (!reservation.category.is_null())
-    args.AddArg(category_key_, Variadic::String(reservation.category));
-
-  if (reservation.name.is_null())
-    return track_id;
-
-  // Initialize the track name here, so that, if a name was given in the
-  // reservation, it is set immediately after resolution takes place.
-  auto* tracks = context_->storage->mutable_track_table();
-  tracks->mutable_name()->Set(*tracks->id().IndexOf(track_id),
-                              reservation.name);
-  return track_id;
-}
-
-TrackId TrackEventTracker::CreateTrackFromResolved(
-    const ResolvedDescriptorTrack& track) {
-  if (track.is_root_in_scope()) {
-    switch (track.scope()) {
-      case ResolvedDescriptorTrack::Scope::kThread:
-        return context_->track_tracker->InternThreadTrack(track.utid());
-      case ResolvedDescriptorTrack::Scope::kProcess:
-        return context_->track_tracker->InternProcessTrack(track.upid());
-      case ResolvedDescriptorTrack::Scope::kGlobal:
-        // Will be handled below.
-        break;
-    }
-  }
-
-  switch (track.scope()) {
-    case ResolvedDescriptorTrack::Scope::kThread: {
-      if (track.is_counter()) {
-        tables::ThreadCounterTrackTable::Row row;
-        row.utid = track.utid();
-
-        auto* thread_counter_tracks =
-            context_->storage->mutable_thread_counter_track_table();
-        return thread_counter_tracks->Insert(row).id;
-      }
-
-      tables::ThreadTrackTable::Row row;
-      row.utid = track.utid();
-
-      auto* thread_tracks = context_->storage->mutable_thread_track_table();
-      return thread_tracks->Insert(row).id;
-    }
-    case ResolvedDescriptorTrack::Scope::kProcess: {
-      if (track.is_counter()) {
-        tables::ProcessCounterTrackTable::Row row;
-        row.upid = track.upid();
-
-        auto* process_counter_tracks =
-            context_->storage->mutable_process_counter_track_table();
-        return process_counter_tracks->Insert(row).id;
-      }
-
-      tables::ProcessTrackTable::Row row;
-      row.upid = track.upid();
-
-      auto* process_tracks = context_->storage->mutable_process_track_table();
-      return process_tracks->Insert(row).id;
-    }
-    case ResolvedDescriptorTrack::Scope::kGlobal: {
-      if (track.is_counter())
-        return context_->storage->mutable_counter_track_table()->Insert({}).id;
-      return context_->storage->mutable_track_table()->Insert({}).id;
-    }
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-base::Optional<TrackEventTracker::ResolvedDescriptorTrack>
-TrackEventTracker::ResolveDescriptorTrack(
-    uint64_t uuid,
-    std::vector<uint64_t>* descendent_uuids) {
-  auto it = resolved_descriptor_tracks_.find(uuid);
-  if (it != resolved_descriptor_tracks_.end())
-    return it->second;
-
-  auto reservation_it = reserved_descriptor_tracks_.find(uuid);
-  if (reservation_it == reserved_descriptor_tracks_.end())
-    return base::nullopt;
-
-  auto resolved_track = ResolveDescriptorTrackImpl(uuid, reservation_it->second,
-                                                   descendent_uuids);
-  resolved_descriptor_tracks_[uuid] = resolved_track;
-  return resolved_track;
-}
-
-TrackEventTracker::ResolvedDescriptorTrack
-TrackEventTracker::ResolveDescriptorTrackImpl(
-    uint64_t uuid,
-    const DescriptorTrackReservation& reservation,
-    std::vector<uint64_t>* descendent_uuids) {
-  static constexpr size_t kMaxAncestors = 10;
-
-  // Try to resolve any parent tracks recursively, too.
-  base::Optional<ResolvedDescriptorTrack> parent_resolved_track;
-  if (reservation.parent_uuid) {
-    // Input data may contain loops or extremely long ancestor track chains. To
-    // avoid stack overflow in these situations, we keep track of the ancestors
-    // seen in the recursion.
-    std::unique_ptr<std::vector<uint64_t>> owned_descendent_uuids;
-    if (!descendent_uuids) {
-      owned_descendent_uuids.reset(new std::vector<uint64_t>());
-      descendent_uuids = owned_descendent_uuids.get();
-    }
-    descendent_uuids->push_back(uuid);
-
-    if (descendent_uuids->size() > kMaxAncestors) {
-      PERFETTO_ELOG(
-          "Too many ancestors in parent_track_uuid hierarchy at track %" PRIu64
-          " with parent %" PRIu64,
-          uuid, reservation.parent_uuid);
-    } else if (std::find(descendent_uuids->begin(), descendent_uuids->end(),
-                         reservation.parent_uuid) != descendent_uuids->end()) {
-      PERFETTO_ELOG(
-          "Loop detected in parent_track_uuid hierarchy at track %" PRIu64
-          " with parent %" PRIu64,
-          uuid, reservation.parent_uuid);
-    } else {
-      parent_resolved_track =
-          ResolveDescriptorTrack(reservation.parent_uuid, descendent_uuids);
-      if (!parent_resolved_track) {
-        PERFETTO_ELOG("Unknown parent track %" PRIu64 " for track %" PRIu64,
-                      reservation.parent_uuid, uuid);
-      }
-    }
-
-    descendent_uuids->pop_back();
-    if (owned_descendent_uuids)
-      descendent_uuids = nullptr;
-  }
-
-  if (reservation.tid) {
-    UniqueTid utid = context_->process_tracker->UpdateThread(*reservation.tid,
-                                                             *reservation.pid);
-    auto it_and_inserted =
-        descriptor_uuids_by_utid_.insert(std::make_pair<>(utid, uuid));
-    if (!it_and_inserted.second) {
-      // We already saw a another track with a different uuid for this thread.
-      // Since there should only be one descriptor track for each thread, we
-      // assume that its tid was reused. So, start a new thread.
-      uint64_t old_uuid = it_and_inserted.first->second;
-      PERFETTO_DCHECK(old_uuid != uuid);  // Every track is only resolved once.
-
-      PERFETTO_DLOG("Detected tid reuse (pid: %" PRIu32 " tid: %" PRIu32
-                    ") from track descriptors (old uuid: %" PRIu64
-                    " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
-                    *reservation.pid, *reservation.tid, old_uuid, uuid,
-                    reservation.min_timestamp);
-
-      utid = context_->process_tracker->StartNewThread(base::nullopt,
-                                                       *reservation.tid);
-
-      // Associate the new thread with its process.
-      PERFETTO_CHECK(context_->process_tracker->UpdateThread(
-                         *reservation.tid, *reservation.pid) == utid);
-
-      descriptor_uuids_by_utid_[utid] = uuid;
-    }
-    return ResolvedDescriptorTrack::Thread(utid, false /* is_counter */,
-                                           true /* is_root*/);
-  }
-
-  if (reservation.pid) {
-    UniquePid upid =
-        context_->process_tracker->GetOrCreateProcess(*reservation.pid);
-    auto it_and_inserted =
-        descriptor_uuids_by_upid_.insert(std::make_pair<>(upid, uuid));
-    if (!it_and_inserted.second) {
-      // We already saw a another track with a different uuid for this process.
-      // Since there should only be one descriptor track for each process, we
-      // assume that its pid was reused. So, start a new process.
-      uint64_t old_uuid = it_and_inserted.first->second;
-      PERFETTO_DCHECK(old_uuid != uuid);  // Every track is only resolved once.
-
-      PERFETTO_DLOG("Detected pid reuse (pid: %" PRIu32
-                    ") from track descriptors (old uuid: %" PRIu64
-                    " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
-                    *reservation.pid, old_uuid, uuid,
-                    reservation.min_timestamp);
-
-      upid = context_->process_tracker->StartNewProcess(
-          base::nullopt, base::nullopt, *reservation.pid, kNullStringId);
-
-      descriptor_uuids_by_upid_[upid] = uuid;
-    }
-    return ResolvedDescriptorTrack::Process(upid, false /* is_counter */,
-                                            true /* is_root*/);
-  }
-
-  if (parent_resolved_track) {
-    switch (parent_resolved_track->scope()) {
-      case ResolvedDescriptorTrack::Scope::kThread:
-        // If parent is a thread track, create another thread-associated track.
-        return ResolvedDescriptorTrack::Thread(parent_resolved_track->utid(),
-                                               reservation.is_counter,
-                                               false /* is_root*/);
-      case ResolvedDescriptorTrack::Scope::kProcess:
-        // If parent is a process track, create another process-associated
-        // track.
-        return ResolvedDescriptorTrack::Process(parent_resolved_track->upid(),
-                                                reservation.is_counter,
-                                                false /* is_root*/);
-      case ResolvedDescriptorTrack::Scope::kGlobal:
-        break;
-    }
-  }
-
-  // Otherwise create a global track.
-
-  // The global track with no uuid is the default global track (e.g. for
-  // global instant events). Any other global tracks are considered children
-  // of the default track.
-  bool is_root_in_scope = !parent_resolved_track;
-  if (!parent_resolved_track && uuid) {
-    // Detect loops where the default track has a parent that itself is a
-    // global track (and thus should be parent of the default track).
-    if (descendent_uuids &&
-        std::find(descendent_uuids->begin(), descendent_uuids->end(),
-                  kDefaultDescriptorTrackUuid) != descendent_uuids->end()) {
-      PERFETTO_ELOG(
-          "Loop detected in parent_track_uuid hierarchy at track %" PRIu64
-          " with parent %" PRIu64,
-          uuid, kDefaultDescriptorTrackUuid);
-    } else {
-      // This track will be implicitly a child of the default global track.
-      is_root_in_scope = false;
-    }
-  }
-  return ResolvedDescriptorTrack::Global(reservation.is_counter,
-                                         is_root_in_scope);
-}
-
-TrackId TrackEventTracker::GetOrCreateDefaultDescriptorTrack() {
-  // If the default track was already reserved (e.g. because a producer emitted
-  // a descriptor for it) or created, resolve and return it.
-  base::Optional<TrackId> track_id =
-      GetDescriptorTrack(kDefaultDescriptorTrackUuid);
-  if (track_id)
-    return *track_id;
-
-  // Otherwise reserve a new track and resolve it.
-  ReserveDescriptorChildTrack(kDefaultDescriptorTrackUuid, /*parent_uuid=*/0,
-                              default_descriptor_track_name_);
-  return *GetDescriptorTrack(kDefaultDescriptorTrackUuid);
-}
-
-base::Optional<double> TrackEventTracker::ConvertToAbsoluteCounterValue(
-    uint64_t counter_track_uuid,
-    uint32_t packet_sequence_id,
-    double value) {
-  auto reservation_it = reserved_descriptor_tracks_.find(counter_track_uuid);
-  if (reservation_it == reserved_descriptor_tracks_.end()) {
-    PERFETTO_DLOG("Unknown counter track with uuid %" PRIu64,
-                  counter_track_uuid);
-    return base::nullopt;
-  }
-
-  DescriptorTrackReservation& reservation = reservation_it->second;
-  if (!reservation.is_counter) {
-    PERFETTO_DLOG("Track with uuid %" PRIu64 " is not a counter track",
-                  counter_track_uuid);
-    return base::nullopt;
-  }
-
-  if (reservation.unit_multiplier > 0)
-    value *= static_cast<double>(reservation.unit_multiplier);
-
-  if (reservation.is_incremental) {
-    if (reservation.packet_sequence_id != packet_sequence_id) {
-      PERFETTO_DLOG(
-          "Incremental counter track with uuid %" PRIu64
-          " was updated from the wrong packet sequence (expected: %" PRIu32
-          " got:%" PRIu32 ")",
-          counter_track_uuid, reservation.packet_sequence_id,
-          packet_sequence_id);
-      return base::nullopt;
-    }
-
-    reservation.latest_value += value;
-    value = reservation.latest_value;
-  }
-
-  return value;
-}
-
-void TrackEventTracker::OnIncrementalStateCleared(uint32_t packet_sequence_id) {
-  // TODO(eseckler): Improve on the runtime complexity of this. At O(hundreds)
-  // of packet sequences, incremental state clearing at O(trace second), and
-  // total number of tracks in O(thousands), a linear scan through all tracks
-  // here might not be fast enough.
-  for (auto& entry : reserved_descriptor_tracks_) {
-    DescriptorTrackReservation& reservation = entry.second;
-    // Only consider incremental counter tracks for current sequence.
-    if (!reservation.is_counter || !reservation.is_incremental ||
-        reservation.packet_sequence_id != packet_sequence_id) {
-      continue;
-    }
-    // Reset their value to 0, see CounterDescriptor's |is_incremental|.
-    reservation.latest_value = 0;
-  }
-}
-
-TrackEventTracker::ResolvedDescriptorTrack
-TrackEventTracker::ResolvedDescriptorTrack::Process(UniquePid upid,
-                                                    bool is_counter,
-                                                    bool is_root) {
-  ResolvedDescriptorTrack track;
-  track.scope_ = Scope::kProcess;
-  track.is_counter_ = is_counter;
-  track.is_root_in_scope_ = is_root;
-  track.upid_ = upid;
-  return track;
-}
-
-TrackEventTracker::ResolvedDescriptorTrack
-TrackEventTracker::ResolvedDescriptorTrack::Thread(UniqueTid utid,
-                                                   bool is_counter,
-                                                   bool is_root) {
-  ResolvedDescriptorTrack track;
-  track.scope_ = Scope::kThread;
-  track.is_counter_ = is_counter;
-  track.is_root_in_scope_ = is_root;
-  track.utid_ = utid;
-  return track;
-}
-
-TrackEventTracker::ResolvedDescriptorTrack
-TrackEventTracker::ResolvedDescriptorTrack::Global(bool is_counter,
-                                                   bool is_root) {
-  ResolvedDescriptorTrack track;
-  track.scope_ = Scope::kGlobal;
-  track.is_counter_ = is_counter;
-  track.is_root_in_scope_ = is_root;
-  return track;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_tracker.h b/src/trace_processor/importers/proto/track_event_tracker.h
deleted file mode 100644
index cd21656..0000000
--- a/src/trace_processor/importers/proto/track_event_tracker.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_
-
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Tracks and stores tracks based on track types, ids and scopes.
-class TrackEventTracker {
- public:
-  explicit TrackEventTracker(TraceProcessorContext*);
-
-  // Associate a TrackDescriptor track identified by the given |uuid| with a
-  // process's |pid|. This is called during tokenization. If a reservation for
-  // the same |uuid| already exists, verifies that the present reservation
-  // matches the new one.
-  //
-  // The track will be resolved to the process track (see InternProcessTrack())
-  // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
-  // time, |pid| will also be resolved to a |upid|.
-  void ReserveDescriptorProcessTrack(uint64_t uuid,
-                                     StringId name,
-                                     uint32_t pid,
-                                     int64_t timestamp);
-
-  // Associate a TrackDescriptor track identified by the given |uuid| with a
-  // thread's |pid| and |tid|. This is called during tokenization. If a
-  // reservation for the same |uuid| already exists, verifies that the present
-  // reservation matches the new one.
-  //
-  // The track will be resolved to the thread track (see InternThreadTrack())
-  // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
-  // time, |pid| will also be resolved to a |upid|.
-  void ReserveDescriptorThreadTrack(uint64_t uuid,
-                                    uint64_t parent_uuid,
-                                    StringId name,
-                                    uint32_t pid,
-                                    uint32_t tid,
-                                    int64_t timestamp);
-
-  // Associate a TrackDescriptor track identified by the given |uuid| with a
-  // parent track (usually a process- or thread-associated track). This is
-  // called during tokenization. If a reservation for the same |uuid| already
-  // exists, will attempt to update it.
-  //
-  // The track will be created upon the first call to GetDescriptorTrack() with
-  // the same |uuid|. If |parent_uuid| is 0, the track will become a global
-  // track. Otherwise, it will become a new track of the same type as its parent
-  // track.
-  void ReserveDescriptorChildTrack(uint64_t uuid,
-                                   uint64_t parent_uuid,
-                                   StringId name);
-
-  // Associate a counter-type TrackDescriptor track identified by the given
-  // |uuid| with a parent track (usually a process or thread track). This is
-  // called during tokenization. If a reservation for the same |uuid| already
-  // exists, will attempt to update it. The provided |category| will be stored
-  // into the track's args.
-  //
-  // If |is_incremental| is true, the counter will only be valid on the packet
-  // sequence identified by |packet_sequence_id|. |unit_multiplier| is an
-  // optional multiplication factor applied to counter values. Values for the
-  // counter will be translated during tokenization via
-  // ConvertToAbsoluteCounterValue().
-  //
-  // The track will be created upon the first call to GetDescriptorTrack() with
-  // the same |uuid|. If |parent_uuid| is 0, the track will become a global
-  // track. Otherwise, it will become a new counter track for the same
-  // process/thread as its parent track.
-  void ReserveDescriptorCounterTrack(uint64_t uuid,
-                                     uint64_t parent_uuid,
-                                     StringId name,
-                                     StringId category,
-                                     int64_t unit_multiplier,
-                                     bool is_incremental,
-                                     uint32_t packet_sequence_id);
-
-  // Returns the ID of the track for the TrackDescriptor with the given |uuid|.
-  // This is called during parsing. The first call to GetDescriptorTrack() for
-  // each |uuid| resolves and inserts the track (and its parent tracks,
-  // following the parent_uuid chain recursively) based on reservations made for
-  // the |uuid|. If the track is a child track and doesn't have a name yet,
-  // updates the track's name to event_name. Returns nullopt if no track for a
-  // descriptor with this |uuid| has been reserved.
-  // TODO(lalitm): this method needs to be split up and moved back to
-  // TrackTracker.
-  base::Optional<TrackId> GetDescriptorTrack(
-      uint64_t uuid,
-      StringId event_name = kNullStringId);
-
-  // Converts the given counter value to an absolute value in the unit of the
-  // counter, applying incremental delta encoding or unit multipliers as
-  // necessary. If the counter uses incremental encoding, |packet_sequence_id|
-  // must match the one in its track reservation. Returns base::nullopt if the
-  // counter track is unknown or an invalid |packet_sequence_id| was passed.
-  base::Optional<double> ConvertToAbsoluteCounterValue(
-      uint64_t counter_track_uuid,
-      uint32_t packet_sequence_id,
-      double value);
-
-  // Returns the ID of the implicit trace-global default TrackDescriptor track.
-  // TODO(lalitm): this method needs to be moved back to TrackTracker once
-  // GetDescriptorTrack is moved back.
-  TrackId GetOrCreateDefaultDescriptorTrack();
-
-  // Called by ProtoTraceReader whenever incremental state is cleared on a
-  // packet sequence. Resets counter values for any incremental counters of
-  // the sequence identified by |packet_sequence_id|.
-  void OnIncrementalStateCleared(uint32_t packet_sequence_id);
-
- private:
-  struct DescriptorTrackReservation {
-    uint64_t parent_uuid = 0;
-    base::Optional<uint32_t> pid;
-    base::Optional<uint32_t> tid;
-    int64_t min_timestamp = 0;  // only set if |pid| and/or |tid| is set.
-    StringId name = kNullStringId;
-
-    // For counter tracks.
-    bool is_counter = false;
-    StringId category = kNullStringId;
-    int64_t unit_multiplier = 1;
-    bool is_incremental = false;
-    uint32_t packet_sequence_id = 0;
-    double latest_value = 0;
-
-    // Whether |other| is a valid descriptor for this track reservation. A track
-    // should always remain nested underneath its original parent.
-    bool IsForSameTrack(const DescriptorTrackReservation& other) {
-      // Note that |min_timestamp|, |latest_value|, and |name| are ignored for
-      // this comparison.
-      return std::tie(parent_uuid, pid, tid, is_counter, category,
-                      unit_multiplier, is_incremental, packet_sequence_id) ==
-             std::tie(other.parent_uuid, pid, tid, is_counter, category,
-                      unit_multiplier, is_incremental, packet_sequence_id);
-    }
-  };
-
-  class ResolvedDescriptorTrack {
-   public:
-    enum class Scope {
-      kThread,
-      kProcess,
-      kGlobal,
-    };
-
-    static ResolvedDescriptorTrack Process(UniquePid upid,
-                                           bool is_counter,
-                                           bool is_root);
-    static ResolvedDescriptorTrack Thread(UniqueTid utid,
-                                          bool is_counter,
-                                          bool is_root);
-    static ResolvedDescriptorTrack Global(bool is_counter, bool is_root);
-
-    Scope scope() const { return scope_; }
-    bool is_counter() const { return is_counter_; }
-    UniqueTid utid() const {
-      PERFETTO_DCHECK(scope() == Scope::kThread);
-      return utid_;
-    }
-    UniquePid upid() const {
-      PERFETTO_DCHECK(scope() == Scope::kProcess);
-      return upid_;
-    }
-    UniqueTid is_root_in_scope() const { return is_root_in_scope_; }
-
-   private:
-    Scope scope_;
-    bool is_counter_;
-    bool is_root_in_scope_;
-
-    // Only set when |scope| == |Scope::kThread|.
-    UniqueTid utid_;
-
-    // Only set when |scope| == |Scope::kProcess|.
-    UniquePid upid_;
-  };
-
-  base::Optional<TrackId> GetDescriptorTrackImpl(uint64_t uuid);
-  TrackId CreateTrackFromResolved(const ResolvedDescriptorTrack&);
-  base::Optional<ResolvedDescriptorTrack> ResolveDescriptorTrack(
-      uint64_t uuid,
-      std::vector<uint64_t>* descendent_uuids);
-  ResolvedDescriptorTrack ResolveDescriptorTrackImpl(
-      uint64_t uuid,
-      const DescriptorTrackReservation&,
-      std::vector<uint64_t>* descendent_uuids);
-
-  static constexpr uint64_t kDefaultDescriptorTrackUuid = 0u;
-
-  std::map<UniqueTid, TrackId> thread_tracks_;
-  std::map<UniquePid, TrackId> process_tracks_;
-
-  std::map<uint64_t /* uuid */, DescriptorTrackReservation>
-      reserved_descriptor_tracks_;
-  std::map<uint64_t /* uuid */, ResolvedDescriptorTrack>
-      resolved_descriptor_tracks_;
-  std::map<uint64_t /* uuid */, TrackId> descriptor_tracks_;
-
-  // Stores the descriptor uuid used for the primary process/thread track
-  // for the given upid / utid. Used for pid/tid reuse detection.
-  std::map<UniquePid, uint64_t /*uuid*/> descriptor_uuids_by_upid_;
-  std::map<UniqueTid, uint64_t /*uuid*/> descriptor_uuids_by_utid_;
-
-  const StringId source_key_ = kNullStringId;
-  const StringId source_id_key_ = kNullStringId;
-  const StringId is_root_in_scope_key_ = kNullStringId;
-  const StringId category_key_ = kNullStringId;
-
-  const StringId descriptor_source_ = kNullStringId;
-
-  const StringId default_descriptor_track_name_ = kNullStringId;
-
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_
diff --git a/src/trace_processor/importers/syscalls/syscall_tracker.h b/src/trace_processor/importers/syscalls/syscall_tracker.h
index 666a220..c31ffe8 100644
--- a/src/trace_processor/importers/syscalls/syscall_tracker.h
+++ b/src/trace_processor/importers/syscalls/syscall_tracker.h
@@ -45,7 +45,7 @@
  public:
   SyscallTracker(const SyscallTracker&) = delete;
   SyscallTracker& operator=(const SyscallTracker&) = delete;
-  ~SyscallTracker() override;
+  virtual ~SyscallTracker();
   static SyscallTracker* GetOrCreate(TraceProcessorContext* context) {
     if (!context->syscall_tracker) {
       context->syscall_tracker.reset(new SyscallTracker(context));
diff --git a/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc b/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
index 7bbc73b..17733eb 100644
--- a/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
+++ b/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
@@ -24,7 +24,6 @@
 namespace {
 
 using ::testing::_;
-using ::testing::DoAll;
 using ::testing::Return;
 using ::testing::SaveArg;
 
@@ -34,17 +33,17 @@
   virtual ~MockSliceTracker() = default;
 
   MOCK_METHOD5(Begin,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       StringId cat,
-                                       StringId name,
-                                       SetArgsCallback args_callback));
+               base::Optional<uint32_t>(int64_t timestamp,
+                                        TrackId track_id,
+                                        StringId cat,
+                                        StringId name,
+                                        SetArgsCallback args_callback));
   MOCK_METHOD5(End,
-               base::Optional<SliceId>(int64_t timestamp,
-                                       TrackId track_id,
-                                       StringId cat,
-                                       StringId name,
-                                       SetArgsCallback args_callback));
+               base::Optional<uint32_t>(int64_t timestamp,
+                                        TrackId track_id,
+                                        StringId cat,
+                                        StringId name,
+                                        SetArgsCallback args_callback));
 };
 
 class SyscallTrackerTest : public ::testing::Test {
diff --git a/src/trace_processor/importers/systrace/systrace_line_parser.cc b/src/trace_processor/importers/systrace/systrace_line_parser.cc
index d412458..8119338 100644
--- a/src/trace_processor/importers/systrace/systrace_line_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_line_parser.cc
@@ -38,18 +38,13 @@
 
 SystraceLineParser::SystraceLineParser(TraceProcessorContext* ctx)
     : context_(ctx),
-      rss_stat_tracker_(context_),
       sched_wakeup_name_id_(ctx->storage->InternString("sched_wakeup")),
-      cpuidle_name_id_(ctx->storage->InternString("cpuidle")),
-      workqueue_name_id_(ctx->storage->InternString("workqueue")),
-      sched_blocked_reason_id_(
-          ctx->storage->InternString("sched_blocked_reason")),
-      io_wait_id_(ctx->storage->InternString("io_wait")) {}
+      cpuidle_name_id_(ctx->storage->InternString("cpuidle")) {}
 
 util::Status SystraceLineParser::ParseLine(const SystraceLine& line) {
-  auto utid = context_->process_tracker->UpdateThreadName(
-      line.pid, context_->storage->InternString(base::StringView(line.task)),
-      ThreadNamePriority::kFtrace);
+  context_->process_tracker->GetOrCreateThread(line.pid);
+  context_->process_tracker->UpdateThreadName(
+      line.pid, context_->storage->InternString(base::StringView(line.task)));
 
   if (!line.tgid_str.empty() && line.tgid_str != "-----") {
     base::Optional<uint32_t> tgid = base::StringToUInt32(line.tgid_str);
@@ -62,12 +57,6 @@
   for (base::StringSplitter ss(line.args_str, ' '); ss.Next();) {
     std::string key;
     std::string value;
-    if (!base::Contains(ss.cur_token(), "=")) {
-      key = "name";
-      value = ss.cur_token();
-      args.emplace(std::move(key), std::move(value));
-      continue;
-    }
     for (base::StringSplitter inner(ss.cur_token(), '='); inner.Next();) {
       if (key.empty()) {
         key = inner.cur_token();
@@ -109,8 +98,8 @@
     }
 
     StringId name_id = context_->storage->InternString(base::StringView(comm));
-    auto wakee_utid = context_->process_tracker->UpdateThreadName(
-        wakee_pid.value(), name_id, ThreadNamePriority::kFtrace);
+    auto wakee_utid =
+        context_->process_tracker->UpdateThreadName(wakee_pid.value(), name_id);
     context_->event_tracker->PushInstant(line.ts, sched_wakeup_name_id_,
                                          wakee_utid, RefType::kRefUtid);
   } else if (line.event_name == "cpu_idle") {
@@ -176,88 +165,6 @@
     }
     BinderTracker::GetOrCreate(context_)->TransactionAllocBuf(
         line.ts, line.pid, data_size.value(), offsets_size.value());
-  } else if (line.event_name == "clock_set_rate" ||
-             line.event_name == "clock_enable" ||
-             line.event_name == "clock_disable") {
-    std::string subtitle =
-        line.event_name == "clock_set_rate" ? " Frequency" : " State";
-    auto rate = base::StringToUInt32(args["state"]);
-    if (!rate.has_value()) {
-      return util::Status("Could not convert state");
-    }
-    std::string clock_name_str = args["name"] + subtitle;
-    StringId clock_name =
-        context_->storage->InternString(base::StringView(clock_name_str));
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(clock_name);
-    context_->event_tracker->PushCounter(line.ts, rate.value(), track);
-  } else if (line.event_name == "workqueue_execute_start") {
-    auto split = base::SplitString(line.args_str, "function ");
-    StringId name_id =
-        context_->storage->InternString(base::StringView(split[1]));
-    TrackId track = context_->track_tracker->InternThreadTrack(utid);
-    context_->slice_tracker->Begin(line.ts, track, workqueue_name_id_, name_id);
-  } else if (line.event_name == "workqueue_execute_end") {
-    TrackId track = context_->track_tracker->InternThreadTrack(utid);
-    context_->slice_tracker->End(line.ts, track, workqueue_name_id_);
-  } else if (line.event_name == "thermal_temperature") {
-    std::string thermal_zone = args["thermal_zone"] + " Temperature";
-    StringId track_name =
-        context_->storage->InternString(base::StringView(thermal_zone));
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(track_name);
-    auto temp = base::StringToInt32(args["temp"]);
-    if (!temp.has_value()) {
-      return util::Status("Could not convert temp");
-    }
-    context_->event_tracker->PushCounter(line.ts, temp.value(), track);
-  } else if (line.event_name == "cdev_update") {
-    std::string type = args["type"] + " Cooling Device";
-    StringId track_name =
-        context_->storage->InternString(base::StringView(type));
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(track_name);
-    auto target = base::StringToDouble(args["target"]);
-    if (!target.has_value()) {
-      return util::Status("Could not convert target");
-    }
-    context_->event_tracker->PushCounter(line.ts, target.value(), track);
-  } else if (line.event_name == "sched_blocked_reason") {
-    auto wakee_pid = base::StringToUInt32(args["pid"]);
-    if (!wakee_pid.has_value()) {
-      return util::Status("sched_blocked_reason: could not parse wakee_pid");
-    }
-    auto wakee_utid = context_->process_tracker->GetOrCreateThread(*wakee_pid);
-
-    InstantId id = context_->event_tracker->PushInstant(
-        line.ts, sched_blocked_reason_id_, wakee_utid, RefType::kRefUtid,
-        false);
-
-    auto inserter = context_->args_tracker->AddArgsTo(id);
-    auto io_wait = base::StringToInt32(args["iowait"]);
-    if (!io_wait.has_value()) {
-      return util::Status("sched_blocked_reason: could not parse io_wait");
-    }
-    inserter.AddArg(io_wait_id_, Variadic::Boolean(*io_wait));
-    context_->args_tracker->Flush();
-  } else if (line.event_name == "rss_stat") {
-    // Format: rss_stat: size=8437760 member=1 curr=1 mm_id=2824390453
-    auto size = base::StringToInt64(args["size"]);
-    auto member = base::StringToUInt32(args["member"]);
-    auto mm_id = base::StringToInt64(args["mm_id"]);
-    auto opt_curr = base::StringToUInt32(args["curr"]);
-    if (!size.has_value()) {
-      return util::Status("rss_stat: could not parse size");
-    }
-    if (!member.has_value()) {
-      return util::Status("rss_stat: could not parse member");
-    }
-    base::Optional<bool> curr;
-    if (!opt_curr.has_value()) {
-      curr = base::make_optional(static_cast<bool>(*opt_curr));
-    }
-    rss_stat_tracker_.ParseRssStat(line.ts, line.pid, *size, *member, curr,
-                                   mm_id);
   }
 
   return util::OkStatus();
diff --git a/src/trace_processor/importers/systrace/systrace_line_parser.h b/src/trace_processor/importers/systrace/systrace_line_parser.h
index 071ee31..00346a3 100644
--- a/src/trace_processor/importers/systrace/systrace_line_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_line_parser.h
@@ -19,9 +19,8 @@
 
 #include "perfetto/trace_processor/status.h"
 
-#include "src/trace_processor/importers/common/trace_parser.h"
-#include "src/trace_processor/importers/ftrace/rss_stat_tracker.h"
 #include "src/trace_processor/importers/systrace/systrace_line.h"
+#include "src/trace_processor/trace_parser.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 namespace perfetto {
@@ -35,12 +34,8 @@
 
  private:
   TraceProcessorContext* const context_;
-  RssStatTracker rss_stat_tracker_;
   const StringId sched_wakeup_name_id_ = kNullStringId;
   const StringId cpuidle_name_id_ = kNullStringId;
-  const StringId workqueue_name_id_ = kNullStringId;
-  const StringId sched_blocked_reason_id_ = kNullStringId;
-  const StringId io_wait_id_ = kNullStringId;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index 607b2ba..f31dcfd 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -21,7 +21,6 @@
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -29,8 +28,7 @@
 SystraceParser::SystraceParser(TraceProcessorContext* ctx)
     : context_(ctx),
       lmk_id_(ctx->storage->InternString("mem.lmk")),
-      screen_state_id_(ctx->storage->InternString("ScreenState")),
-      cookie_id_(ctx->storage->InternString("cookie")) {}
+      screen_state_id_(ctx->storage->InternString("ScreenState")) {}
 
 SystraceParser::~SystraceParser() = default;
 
@@ -55,20 +53,12 @@
                                     uint32_t pid,
                                     int32_t flag,
                                     base::StringView name,
-                                    uint32_t /* tgid */,
+                                    uint32_t tgid,
                                     int64_t value) {
   systrace_utils::SystraceTracePoint point{};
   point.name = name;
-  point.value = static_cast<double>(value);
-
-  // Hardcode the tgid to 0 (i.e. no tgid available) because zero events can
-  // come from kernel threads and as we group kernel threads into the kthreadd
-  // process, we would want |point.tgid == kKthreaddPid|. However, we don't have
-  // acces to the ppid of this process so we have to not associate to any
-  // process and leave the resolution of process to other events.
-  // TODO(lalitm): remove this hack once we move kernel thread grouping to
-  // the UI.
-  point.tgid = 0;
+  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;
@@ -88,13 +78,13 @@
   ParseSystracePoint(ts, pid, point);
 }
 
-void SystraceParser::ParseTracingMarkWrite(int64_t ts,
-                                           uint32_t pid,
-                                           char trace_type,
-                                           bool trace_begin,
-                                           base::StringView trace_name,
-                                           uint32_t /* tgid */,
-                                           int64_t value) {
+void SystraceParser::ParseSdeTracingMarkWrite(int64_t ts,
+                                              uint32_t pid,
+                                              char trace_type,
+                                              bool trace_begin,
+                                              base::StringView trace_name,
+                                              uint32_t /* tgid */,
+                                              int64_t value) {
   systrace_utils::SystraceTracePoint point{};
   point.name = trace_name;
 
@@ -108,7 +98,7 @@
   // the UI.
   point.tgid = 0;
 
-  point.value = static_cast<double>(value);
+  point.value = value;
   // Some versions of this trace point fill trace_type with one of (B/E/C),
   // others use the trace_begin boolean and only support begin/end events:
   if (trace_type == 0) {
@@ -168,36 +158,11 @@
       UniquePid upid =
           context_->process_tracker->GetOrCreateProcess(point.tgid);
 
-      auto track_set_id =
-          context_->async_track_set_tracker->InternAndroidSet(upid, name_id);
-
+      TrackId track_id = context_->track_tracker->InternAndroidAsyncTrack(
+          name_id, upid, cookie);
       if (point.phase == 'S') {
-        // Historically, async slices on Android did not support nesting async
-        // slices (i.e. you could not have a stack of async slices). If clients
-        // were implemented correctly, we would simply be able to use the normal
-        // Begin method and we could rely on the traced code to never emit two
-        // 'S' events back to back on the same track.
-        // However, there exists buggy code in Android (in Wakelock class of
-        // PowerManager) which emits an arbitrary number of 'S' events and
-        // expects only the first one to be tracked. Moreover, this issue is
-        // compounded by an unfortunate implementation of async slices in
-        // Catapult (the legacy trace viewer) which simply tracks the details of
-        // the *most recent* emitted 'S' event which leads even more inaccurate
-        // behaviour. To support these quirks, we have the special 'unnestable'
-        // slice concept which implements workarounds for these very specific
-        // issues. No other code should ever use this method.
-        tables::SliceTable::Row row;
-        row.ts = ts;
-        row.track_id =
-            context_->async_track_set_tracker->Begin(track_set_id, cookie);
-        row.name = name_id;
-        context_->slice_tracker->BeginLegacyUnnestable(
-            row, [this, cookie](ArgsTracker::BoundInserter* inserter) {
-              inserter->AddArg(cookie_id_, Variadic::Integer(cookie));
-            });
+        context_->slice_tracker->Begin(ts, track_id, kNullStringId, name_id);
       } else {
-        TrackId track_id =
-            context_->async_track_set_tracker->End(track_set_id, cookie);
         context_->slice_tracker->End(ts, track_id);
       }
       break;
@@ -226,24 +191,14 @@
         context_->event_tracker->PushCounter(ts, point.value, track);
         return;
       }
-
+      // 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_id;
-      if (point.tgid == 0) {
-        // If tgid is 0 (likely because this is a kernel thread), we can do no
-        // better than using a thread track with the pid of the process.
-        UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-        track_id =
-            context_->track_tracker->InternThreadCounterTrack(name_id, utid);
-      } else {
-        // 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);
-        track_id =
-            context_->track_tracker->InternProcessCounterTrack(name_id, upid);
-      }
-      context_->event_tracker->PushCounter(ts, point.value, track_id);
+      TrackId track =
+          context_->track_tracker->InternProcessCounterTrack(name_id, upid);
+      context_->event_tracker->PushCounter(ts, point.value, track);
     }
   }
 }
diff --git a/src/trace_processor/importers/systrace/systrace_parser.h b/src/trace_processor/importers/systrace/systrace_parser.h
index 2531150..ae5eec6 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_parser.h
@@ -155,10 +155,8 @@
       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.empty()) {
-        static const char kEmptySliceName[] = "[empty slice name]";
-        out->name = base::StringView(kEmptySliceName);
-      }
+      if (out->name.size() == 0)
+        return SystraceParseResult::kFailure;
       return SystraceParseResult::kSuccess;
     }
     case 'E': {
@@ -232,13 +230,13 @@
 
   void ParsePrintEvent(int64_t ts, uint32_t pid, base::StringView event);
 
-  void ParseTracingMarkWrite(int64_t ts,
-                             uint32_t pid,
-                             char trace_type,
-                             bool trace_begin,
-                             base::StringView trace_name,
-                             uint32_t tgid,
-                             int64_t value);
+  void ParseSdeTracingMarkWrite(int64_t ts,
+                                uint32_t pid,
+                                char trace_type,
+                                bool trace_begin,
+                                base::StringView trace_name,
+                                uint32_t tgid,
+                                int64_t value);
 
   void ParseZeroEvent(int64_t ts,
                       uint32_t pid,
@@ -256,7 +254,6 @@
   TraceProcessorContext* const context_;
   const StringId lmk_id_;
   const StringId screen_state_id_;
-  const StringId cookie_id_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/systrace/systrace_parser_unittest.cc b/src/trace_processor/importers/systrace/systrace_parser_unittest.cc
index b0e9de1..5c65514 100644
--- a/src/trace_processor/importers/systrace/systrace_parser_unittest.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser_unittest.cc
@@ -41,9 +41,7 @@
   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::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::B(42, "[empty slice name]"));
+  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"));
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
index d333af3..ba0acbd 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
@@ -93,12 +93,10 @@
         state_ = ParseState::kTraceDataSection;
       }
     } else if (state_ == ParseState::kTraceDataSection) {
-      if (base::StartsWith(buffer, "#") && base::Contains(buffer, "TASK-PID")) {
+      if (base::StartsWith(buffer, "#")) {
         state_ = ParseState::kSystrace;
       } else if (base::StartsWith(buffer, "PROCESS DUMP")) {
         state_ = ParseState::kProcessDumpLong;
-      } else if (base::StartsWith(buffer, "CGROUP DUMP")) {
-        state_ = ParseState::kCgroupDump;
       } else if (base::Contains(buffer, R"(</script>)")) {
         state_ = ParseState::kHtmlBeforeSystrace;
       }
@@ -109,11 +107,9 @@
       } else if (!base::StartsWith(buffer, "#") && !buffer.empty()) {
         SystraceLine line;
         util::Status status = line_tokenizer_.Tokenize(buffer, &line);
-        if (status.ok()) {
-          line_parser_.ParseLine(std::move(line));
-        } else {
-          ctx_->storage->IncrementStats(stats::systrace_parse_failure);
-        }
+        if (!status.ok())
+          return status;
+        line_parser_.ParseLine(std::move(line));
       }
     } else if (state_ == ParseState::kProcessDumpLong ||
                state_ == ParseState::kProcessDumpShort) {
@@ -144,8 +140,7 @@
             PERFETTO_ELOG("Could not parse line '%s'", buffer.c_str());
             return util::ErrStatus("Could not parse PROCESS DUMP line");
           }
-          ctx_->process_tracker->SetProcessMetadata(pid.value(), ppid, name,
-                                                    base::StringView());
+          ctx_->process_tracker->SetProcessMetadata(pid.value(), ppid, name);
         } else if (state_ == ParseState::kProcessDumpShort &&
                    tokens.size() >= 4) {
           // Format is:
@@ -167,15 +162,9 @@
           }
           UniqueTid utid =
               ctx_->process_tracker->UpdateThread(tid.value(), tgid.value());
-          ctx_->process_tracker->UpdateThreadNameByUtid(
-              utid, cmd_id, ThreadNamePriority::kOther);
+          ctx_->process_tracker->SetThreadNameIfUnset(utid, cmd_id);
         }
       }
-    } else if (state_ == ParseState::kCgroupDump) {
-      if (base::Contains(buffer, R"(</script>)")) {
-        state_ = ParseState::kHtmlBeforeSystrace;
-      }
-      // TODO(lalitm): see if it is important to parse this.
     }
     start_it = line_it + 1;
   }
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.h b/src/trace_processor/importers/systrace/systrace_trace_parser.h
index bcb5ea8..09c82bb 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.h
@@ -20,7 +20,7 @@
 #include <deque>
 #include <regex>
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/importers/systrace/systrace_line_parser.h"
 #include "src/trace_processor/importers/systrace/systrace_line_tokenizer.h"
 #include "src/trace_processor/storage/trace_storage.h"
@@ -46,7 +46,6 @@
     kSystrace,
     kProcessDumpLong,
     kProcessDumpShort,
-    kCgroupDump,
     kEndOfSystrace,
   };
 
diff --git a/src/trace_processor/iterator_impl.cc b/src/trace_processor/iterator_impl.cc
deleted file mode 100644
index 6539e9a..0000000
--- a/src/trace_processor/iterator_impl.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/iterator_impl.h"
-
-#include "perfetto/base/time.h"
-#include "perfetto/trace_processor/trace_processor_storage.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/trace_processor_impl.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
-                           sqlite3* db,
-                           ScopedStmt stmt,
-                           uint32_t column_count,
-                           util::Status status,
-                           uint32_t sql_stats_row)
-    : trace_processor_(trace_processor),
-      db_(db),
-      stmt_(std::move(stmt)),
-      column_count_(column_count),
-      status_(status),
-      sql_stats_row_(sql_stats_row) {}
-
-IteratorImpl::~IteratorImpl() {
-  if (trace_processor_) {
-    base::TimeNanos t_end = base::GetWallTimeNs();
-    auto* sql_stats =
-        trace_processor_.get()->context_.storage->mutable_sql_stats();
-    sql_stats->RecordQueryEnd(sql_stats_row_, t_end.count());
-  }
-}
-
-void IteratorImpl::RecordFirstNextInSqlStats() {
-  base::TimeNanos t_first_next = base::GetWallTimeNs();
-  auto* sql_stats =
-      trace_processor_.get()->context_.storage->mutable_sql_stats();
-  sql_stats->RecordQueryFirstNext(sql_stats_row_, t_first_next.count());
-}
-
-Iterator::Iterator(std::unique_ptr<IteratorImpl> iterator)
-    : iterator_(std::move(iterator)) {}
-Iterator::~Iterator() = default;
-
-Iterator::Iterator(Iterator&&) noexcept = default;
-Iterator& Iterator::operator=(Iterator&&) = default;
-
-bool Iterator::Next() {
-  return iterator_->Next();
-}
-
-SqlValue Iterator::Get(uint32_t col) {
-  return iterator_->Get(col);
-}
-
-std::string Iterator::GetColumnName(uint32_t col) {
-  return iterator_->GetColumnName(col);
-}
-
-uint32_t Iterator::ColumnCount() {
-  return iterator_->ColumnCount();
-}
-
-util::Status Iterator::Status() {
-  return iterator_->Status();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/iterator_impl.h b/src/trace_processor/iterator_impl.h
deleted file mode 100644
index f286f2c..0000000
--- a/src/trace_processor/iterator_impl.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_ITERATOR_IMPL_H_
-#define SRC_TRACE_PROCESSOR_ITERATOR_IMPL_H_
-
-#include <sqlite3.h>
-
-#include <memory>
-#include <vector>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/export.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/iterator.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorImpl;
-
-class IteratorImpl {
- public:
-  IteratorImpl(TraceProcessorImpl* impl,
-               sqlite3* db,
-               ScopedStmt,
-               uint32_t column_count,
-               util::Status,
-               uint32_t sql_stats_row);
-  ~IteratorImpl();
-
-  IteratorImpl(IteratorImpl&) noexcept = delete;
-  IteratorImpl& operator=(IteratorImpl&) = delete;
-
-  IteratorImpl(IteratorImpl&&) noexcept = default;
-  IteratorImpl& operator=(IteratorImpl&&) = default;
-
-  // Methods called by the base Iterator class.
-  bool Next() {
-    // Delegate to the cc file to prevent trace_storage.h include in this file.
-    if (!called_next_) {
-      RecordFirstNextInSqlStats();
-      called_next_ = true;
-    }
-
-    if (!status_.ok())
-      return false;
-
-    int ret = sqlite3_step(*stmt_);
-    if (PERFETTO_UNLIKELY(ret != SQLITE_ROW && ret != SQLITE_DONE)) {
-      status_ = util::ErrStatus("%s", sqlite3_errmsg(db_));
-      return false;
-    }
-    return ret == SQLITE_ROW;
-  }
-
-  SqlValue Get(uint32_t col) {
-    auto column = static_cast<int>(col);
-    auto col_type = sqlite3_column_type(*stmt_, column);
-    SqlValue value;
-    switch (col_type) {
-      case SQLITE_INTEGER:
-        value.type = SqlValue::kLong;
-        value.long_value = sqlite3_column_int64(*stmt_, column);
-        break;
-      case SQLITE_TEXT:
-        value.type = SqlValue::kString;
-        value.string_value =
-            reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, column));
-        break;
-      case SQLITE_FLOAT:
-        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;
-    }
-    return value;
-  }
-
-  std::string GetColumnName(uint32_t col) {
-    return sqlite3_column_name(stmt_.get(), static_cast<int>(col));
-  }
-
-  uint32_t ColumnCount() { return column_count_; }
-
-  util::Status Status() { return status_; }
-
- private:
-  // Dummy function to pass to ScopedResource.
-  static int DummyClose(TraceProcessorImpl*) { return 0; }
-
-  // Iterators hold onto an instance of TraceProcessor to track when the query
-  // ends in the sql stats table. As iterators are movable, we need to null out
-  // the TraceProcessor in the moved out iterator to avoid double recording
-  // query ends. We could manually define a move constructor instead, but given
-  // the error prone nature of keeping functions up to date, this seems like a
-  // nicer approach.
-  using ScopedTraceProcessor =
-      base::ScopedResource<TraceProcessorImpl*, &DummyClose, nullptr>;
-
-  void RecordFirstNextInSqlStats();
-
-  ScopedTraceProcessor trace_processor_;
-  sqlite3* db_ = nullptr;
-  ScopedStmt stmt_;
-  uint32_t column_count_ = 0;
-  util::Status status_;
-
-  uint32_t sql_stats_row_ = 0;
-  bool called_next_ = false;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_ITERATOR_IMPL_H_
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 00a1e4e..0712a47 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -17,77 +17,40 @@
 
 sql_files = [
   "trace_metadata.sql",
-  "trace_stats.sql",
   "android/android_batt.sql",
   "android/android_cpu.sql",
-  "android/android_surfaceflinger.sql",
   "android/android_cpu_agg.sql",
   "android/android_cpu_raw_metrics_per_core.sql",
-  "android/android_dma_heap.sql",
-  "android/android_fastrpc.sql",
-  "android/android_gpu.sql",
-  "android/android_hwui_threads.sql",
   "android/android_mem.sql",
   "android/android_mem_unagg.sql",
   "android/android_ion.sql",
-  "android/composer_execution.sql",
-  "android/composition_layers.sql",
-  "android/frame_missed.sql",
-  "android/android_jank.sql",
   "android/android_lmk_reason.sql",
   "android/android_lmk.sql",
   "android/android_powrails.sql",
-  "android/android_proxy_power.sql",
   "android/android_startup_launches.sql",
+  "android/android_task_state.sql",
   "android/android_startup.sql",
   "android/android_package_list.sql",
   "android/android_task_names.sql",
   "android/android_thread_time_in_state.sql",
   "android/cpu_info.sql",
   "android/display_metrics.sql",
-  "android/g2d.sql",
-  "android/g2d_duration.sql",
+  "android/heap_profile_callsites.sql",
   "android/hsc_startups.sql",
-  "android/android_hwcomposer.sql",
   "android/android_hwui_metric.sql",
   "android/java_heap_histogram.sql",
   "android/java_heap_stats.sql",
-  "android/power_drain_in_watts.sql",
-  "android/power_profile_data.sql",
   "android/process_unagg_mem_view.sql",
   "android/process_mem.sql",
   "android/process_metadata.sql",
   "android/process_oom_score.sql",
   "android/mem_stats_priority_breakdown.sql",
   "android/span_view_stats.sql",
-  "android/android_sysui_cuj.sql",
   "android/process_counter_span_view.sql",
-  "android/global_counter_span_view.sql",
+  "android/counter_span_view.sql",
+  "android/unmapped_java_symbols.sql",
   "android/unsymbolized_frames.sql",
-  "chrome/actual_power_by_category.sql",
-  "chrome/actual_power_by_rail_mode.sql",
-  "chrome/chrome_event_metadata.sql",
   "chrome/chrome_processes.sql",
-  "chrome/chrome_thread_slice_with_cpu_time.sql",
-  "chrome/cpu_time_by_category.sql",
-  "chrome/cpu_time_by_rail_mode.sql",
-  "chrome/estimated_power_by_category.sql",
-  "chrome/estimated_power_by_rail_mode.sql",
-  "chrome/rail_modes.sql",
-  "chrome/scroll_jank.sql",
-  "chrome/scroll_jank_cause.sql",
-  "chrome/scroll_jank_cause_blocking_task.sql",
-  "chrome/scroll_jank_cause_blocking_touch_move.sql",
-  "chrome/scroll_jank_cause_get_bitmap.sql",
-  "chrome/scroll_jank_cause_queuing_delay.sql",
-  "chrome/scroll_flow_event.sql",
-  "chrome/scroll_flow_event_queuing_delay.sql",
-  "chrome/test_chrome_metric.sql",
-  "experimental/blink_gc_metric.sql",
-  "experimental/frame_times.sql",
-  "experimental/media_metric.sql",
-  "experimental/reported_by_page.sql",
-  "webview/webview_power_usage.sql",
 ]
 
 config("gen_config") {
@@ -106,52 +69,12 @@
   public_configs = [ ":gen_config" ]
 }
 
-action("gen_cc_metrics_descriptor") {
-  descriptor_target = "../../../protos/perfetto/metrics:descriptor"
-  generated_header = "${target_gen_dir}/metrics.descriptor.h"
-
-  descriptor_file_path = get_label_info(descriptor_target, "target_gen_dir") +
-                         "/metrics.descriptor"
-
-  script = "../../../tools/gen_cc_proto_descriptor.py"
-  deps = [ descriptor_target ]
-  args = [
-    "--gen_dir",
-    rebase_path(root_gen_dir, root_build_dir),
-    "--cpp_out",
-    rebase_path(generated_header, root_build_dir),
-    rebase_path(descriptor_file_path, root_build_dir),
-  ]
-  inputs = [ descriptor_file_path ]
-  outputs = [ generated_header ]
-  public_configs = [ ":gen_config" ]
-}
-
-action("gen_cc_all_chrome_metrics_descriptor") {
-  descriptor_target = "../../../protos/perfetto/metrics/chrome:descriptor"
-  generated_header = "${target_gen_dir}/chrome/all_chrome_metrics.descriptor.h"
-
-  descriptor_file_path = get_label_info(descriptor_target, "target_gen_dir") +
-                         "/all_chrome_metrics.descriptor"
-
-  script = "../../../tools/gen_cc_proto_descriptor.py"
-  deps = [ descriptor_target ]
-  args = [
-    "--gen_dir",
-    rebase_path(root_gen_dir, root_build_dir),
-    "--cpp_out",
-    rebase_path(generated_header, root_build_dir),
-    rebase_path(descriptor_file_path, root_build_dir),
-  ]
-  inputs = [ descriptor_file_path ]
-  outputs = [ generated_header ]
-  public_configs = [ ":gen_config" ]
-}
-
 if (enable_perfetto_trace_processor_sqlite) {
   source_set("lib") {
     sources = [
+      "custom_options.descriptor.h",
       "metrics.cc",
+      "metrics.descriptor.h",
       "metrics.h",
     ]
     deps = [
@@ -160,16 +83,15 @@
       "../../../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_cc_all_chrome_metrics_descriptor",
-      ":gen_cc_metrics_descriptor",
       ":gen_merged_sql_metrics",
-      "../util",
       "../util:descriptors",
     ]
   }
diff --git a/src/trace_processor/metrics/android/android_batt.sql b/src/trace_processor/metrics/android/android_batt.sql
index db0fbf3..349fc0d 100644
--- a/src/trace_processor/metrics/android/android_batt.sql
+++ b/src/trace_processor/metrics/android/android_batt.sql
@@ -13,7 +13,6 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
-DROP VIEW IF EXISTS battery_view;
 CREATE VIEW battery_view AS
 SELECT
   all_ts.ts as ts,
@@ -53,177 +52,49 @@
 ) USING(ts)
 ORDER BY ts;
 
-DROP TABLE IF EXISTS android_batt_wakelocks_merged;
-CREATE TABLE android_batt_wakelocks_merged AS
+DROP TABLE IF EXISTS android_batt_wakelocks_raw_;
+CREATE TABLE android_batt_wakelocks_raw_ AS
 SELECT
-  MIN(ts) AS ts,
-  MAX(ts_end) AS ts_end
-FROM (
-    SELECT
-        *,
-        SUM(new_group) OVER (ORDER BY ts) AS group_id
-    FROM (
-        SELECT
-            ts,
-            ts + dur AS ts_end,
-            -- There is a new group if there was a gap before this wakelock.
-            -- i.e. the max end timestamp of all preceding wakelocks is before
-            -- the start timestamp of this one.
-            -- The null check is for the first row which is always a new group.
-            IFNULL(
-                MAX(ts + dur) OVER (
-                    ORDER BY ts
-                    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
-                ) < ts,
-                true
-            ) AS new_group
-        FROM slice
-        WHERE slice.name LIKE 'WakeLock %' AND dur != -1
-    )
-)
-GROUP BY group_id;
+  ts,
+  dur,
+  ts+dur AS ts_end
+FROM slice
+WHERE slice.name LIKE 'WakeLock %' AND dur != -1;
 
--- Different device kernels log different actions when suspending. This table
--- tells us the action that straddles the actual suspend period.
-DROP TABLE IF EXISTS device_action_mapping;
-CREATE TABLE device_action_mapping (device TEXT, action TEXT);
-INSERT INTO device_action_mapping VALUES
-('blueline', 'timekeeping_freeze'),
-('crosshatch', 'timekeeping_freeze'),
-('bonito', 'timekeeping_freeze'),
-('sargo', 'timekeeping_freeze'),
-('coral', 'timekeeping_freeze'),
-('flame', 'timekeeping_freeze'),
-('sunfish', 'timekeeping_freeze'),
-('redfin', 'syscore_resume'),
-('bramble', 'syscore_resume');
-
-DROP TABLE IF EXISTS device_action;
-CREATE TABLE device_action AS
-SELECT action
-FROM device_action_mapping dam
-WHERE EXISTS (
-  SELECT 1 FROM metadata
-  WHERE name = 'android_build_fingerprint' AND str_value LIKE '%' || dam.device || '%');
-
-DROP TABLE IF EXISTS suspend_slice_;
-CREATE TABLE suspend_slice_ AS
--- Traces from after b/70292203 was fixed have the action string so just look
--- for it.
+DROP TABLE IF EXISTS android_batt_wakelocks_labelled_;
+CREATE TABLE android_batt_wakelocks_labelled_ AS
 SELECT
-    ts,
-    dur,
-    true as trustworthy
-FROM (
-    SELECT
-        ts,
-        LEAD(ts) OVER (ORDER BY ts, start DESC) - ts AS dur,
-        start
-    FROM (
-        SELECT
-               ts,
-               EXTRACT_ARG(arg_set_id, 'action') AS action,
-               EXTRACT_ARG(arg_set_id, 'start') AS start
-        FROM raw
-        WHERE name = 'suspend_resume'
-    ) JOIN device_action USING(action)
-)
-WHERE start = 1
-UNION ALL
--- Traces from before b/70292203 was fixed (approx Nov 2020) do not have the
--- action string so we do some convoluted pattern matching that mostly works.
--- TODO(simonmacm) remove this when enough time has passed (mid 2021?)
+  *,
+  NOT EXISTS (
+    SELECT *
+    FROM android_batt_wakelocks_raw_ AS t2
+    WHERE t2.ts < t1.ts
+      AND t2.ts_end >= t1.ts
+  ) AS no_overlap_at_start,
+  NOT EXISTS (
+    SELECT *
+    FROM android_batt_wakelocks_raw_ AS t2
+    WHERE t2.ts_end > t1.ts_end
+      AND t2.ts <= t1.ts_end
+  ) AS no_overlap_at_end
+FROM android_batt_wakelocks_raw_ AS t1;
+
+CREATE VIEW android_batt_wakelocks_merged AS
 SELECT
-    ts,
-    dur,
-    false as trustworthy
-FROM (
-    SELECT
-       ts,
-       ts - lag(ts) OVER w AS lag_dur,
-       lead(ts) OVER w - ts AS dur,
-       action,
-       start,
-       event,
-       lag(start) OVER w AS lag_start,
-       lag(event) OVER w AS lag_event,
-       lag(start, 2) OVER w AS lag_2_start,
-       lag(event, 2) OVER w AS lag_2_event,
-       lead(start) OVER w AS lead_start,
-       lead(event) OVER w AS lead_event,
-       lead(start, 2) OVER w AS lead_2_start,
-       lead(event, 2) OVER w AS lead_2_event
-    FROM (
-        SELECT
-               ts,
-               EXTRACT_ARG(arg_set_id, 'action') AS action,
-               EXTRACT_ARG(arg_set_id, 'start') AS start,
-               EXTRACT_ARG(arg_set_id, 'val') AS event
-        FROM raw
-        WHERE name = 'suspend_resume'
-    )
-    WINDOW w AS (ORDER BY ts)
-)
-WHERE action IS NULL AND (
--- We want to find the start and end events with action='timekeeping_freeze'.
--- In practice, these events often show up in a sequence like the following:
--- start = 1, event = 1     [string would have been 'machine_suspend']
--- start = 1, event = (any) [string would have been 'timekeeping_freeze'] *
---
---                             (sleep happens here)
---
--- start = 0, event = (any) [string would have been 'timekeeping_freeze']
--- start = 0, event = 1     [string would have been 'machine_suspend']
---
--- So we look for this pattern of start and event, anchored on the event marked
--- with "*".
-    (
-        lag_start = 1 AND lag_event = 1
-        AND start = 1
-        AND lead_start = 0
-        AND lead_2_start = 0 AND lead_2_event = 1
-    )
--- Or in newer kernels we seem to have a very different pattern. We can take
--- advantage of that fact that we get several events with identical timestamp
--- just before sleeping (normally this never happens):
--- gap = 0, start = 1, event = 3
--- gap = 0, start = 0, event = 3
--- gap = 0, start = 1, event = 0
---
---  (sleep happens here)
---
--- gap = (any), start = 0, event = 0
-    OR (
-        lag_dur = 0
-        AND lead_start = 0 AND lead_event = 0
-        AND start = 1 AND event = 0
-        AND lag_start = 0 AND lag_event = 3
-        AND lag_2_start = 1 AND lag_2_event = 3
-    )
-);
+  ts,
+  (
+    SELECT min(ts_end)
+    FROM android_batt_wakelocks_labelled_ AS ends
+    WHERE no_overlap_at_end
+      AND ends.ts_end >= starts.ts
+  ) AS ts_end
+FROM android_batt_wakelocks_labelled_ AS starts
+WHERE no_overlap_at_start;
 
-DROP TABLE device_action_mapping;
-DROP TABLE device_action;
-
-SELECT RUN_METRIC('android/global_counter_span_view.sql',
+SELECT RUN_METRIC('android/counter_span_view.sql',
   'table_name', 'screen_state',
   'counter_name', 'ScreenState');
 
-DROP TABLE IF EXISTS screen_state_span_with_suspend;
-CREATE VIRTUAL TABLE screen_state_span_with_suspend
-    USING span_join(screen_state_span, suspend_slice_);
-
-DROP VIEW IF EXISTS android_batt_event;
-CREATE VIEW android_batt_event AS
-SELECT
-       ts,
-       dur,
-       'Suspended' AS slice_name,
-       'Suspend / resume' AS track_name,
-       'slice' AS track_type
-FROM suspend_slice_;
-
-DROP VIEW IF EXISTS android_batt_output;
 CREATE VIEW android_batt_output AS
 SELECT AndroidBatteryMetric(
   'battery_counters', (
@@ -239,40 +110,21 @@
     FROM battery_view
   ),
   'battery_aggregates', (
-    SELECT NULL_IF_EMPTY(AndroidBatteryMetric_BatteryAggregates(
+    SELECT AndroidBatteryMetric_BatteryAggregates(
       'total_screen_off_ns',
-      SUM(CASE WHEN state = 1.0 AND tbl = 'total' THEN dur ELSE 0 END),
+      SUM(CASE WHEN screen_state_val = 1.0 THEN dur ELSE 0 END),
       'total_screen_on_ns',
-      SUM(CASE WHEN state = 2.0 AND tbl = 'total' THEN dur ELSE 0 END),
+      SUM(CASE WHEN screen_state_val = 2.0 THEN dur ELSE 0 END),
       'total_screen_doze_ns',
-      SUM(CASE WHEN state = 3.0 AND tbl = 'total' THEN dur ELSE 0 END),
-      'sleep_ns',
-      (SELECT SUM(dur) FROM suspend_slice_),
-      'sleep_screen_off_ns',
-      SUM(CASE WHEN state = 1.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
-      'sleep_screen_on_ns',
-      SUM(CASE WHEN state = 2.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
-      'sleep_screen_doze_ns',
-      SUM(CASE WHEN state = 3.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
-      'total_wakelock_ns',
-      (SELECT SUM(ts_end - ts) FROM android_batt_wakelocks_merged)
-    ))
-    FROM (
-         SELECT dur, screen_state_val AS state, 'total' AS tbl
-         FROM screen_state_span
-         UNION ALL
-         SELECT dur, screen_state_val AS state, 'sleep' AS tbl
-         FROM screen_state_span_with_suspend
+      SUM(CASE WHEN screen_state_val = 3.0 THEN dur ELSE 0 END)
     )
+    FROM screen_state_span
   ),
-  'suspend_period', (
-    SELECT RepeatedField(
-      AndroidBatteryMetric_SuspendPeriod(
-        'timestamp_ns', ts,
-        'duration_ns', dur
-      )
+  'battery_aggregates', (
+    SELECT AndroidBatteryMetric_BatteryAggregates(
+      'total_wakelock_ns',
+      SUM(ts_end - ts)
     )
-    FROM suspend_slice_
-    WHERE trustworthy
+    FROM android_batt_wakelocks_merged
   )
 );
diff --git a/src/trace_processor/metrics/android/android_cpu.sql b/src/trace_processor/metrics/android/android_cpu.sql
index 2af9faf..ad139db 100644
--- a/src/trace_processor/metrics/android/android_cpu.sql
+++ b/src/trace_processor/metrics/android/android_cpu.sql
@@ -16,11 +16,11 @@
 
 -- Create all the views used to generate the Android Cpu metrics proto.
 SELECT RUN_METRIC('android/android_cpu_agg.sql');
+SELECT RUN_METRIC('android/cpu_info.sql');
 SELECT RUN_METRIC('android/android_cpu_raw_metrics_per_core.sql',
   'input_table', 'cpu_freq_sched_per_thread',
   'output_table', 'raw_metrics_per_core');
 
-DROP VIEW IF EXISTS metrics_per_core_type;
 CREATE VIEW metrics_per_core_type AS
 SELECT
   utid,
@@ -40,7 +40,6 @@
 GROUP BY utid, core_type;
 
 -- Aggregate everything per thread.
-DROP VIEW IF EXISTS core_proto_per_thread;
 CREATE VIEW core_proto_per_thread AS
 SELECT
   utid,
@@ -59,7 +58,6 @@
 FROM raw_metrics_per_core
 GROUP BY utid;
 
-DROP VIEW IF EXISTS core_type_proto_per_thread;
 CREATE VIEW core_type_proto_per_thread AS
 SELECT
   utid,
@@ -72,7 +70,6 @@
 FROM metrics_per_core_type
 GROUP BY utid;
 
-DROP VIEW IF EXISTS metrics_proto_per_thread;
 CREATE VIEW metrics_proto_per_thread AS
 SELECT
   utid,
@@ -89,7 +86,6 @@
 GROUP BY utid;
 
 -- Aggregate everything per perocess
-DROP VIEW IF EXISTS thread_proto_per_process;
 CREATE VIEW thread_proto_per_process AS
 SELECT
   upid,
@@ -107,7 +103,6 @@
 LEFT JOIN metrics_proto_per_thread USING(utid)
 GROUP BY upid;
 
-DROP VIEW IF EXISTS core_metrics_per_process;
 CREATE VIEW core_metrics_per_process AS
 SELECT
   upid,
@@ -127,7 +122,6 @@
 JOIN thread USING (utid)
 GROUP BY upid, cpu;
 
-DROP VIEW IF EXISTS core_proto_per_process;
 CREATE VIEW core_proto_per_process AS
 SELECT
   upid,
@@ -140,7 +134,6 @@
 FROM core_metrics_per_process
 GROUP BY upid;
 
-DROP VIEW IF EXISTS core_type_metrics_per_process;
 CREATE VIEW core_type_metrics_per_process AS
 SELECT
   upid,
@@ -160,7 +153,6 @@
 JOIN thread USING (utid)
 GROUP BY upid, core_type;
 
-DROP VIEW IF EXISTS core_type_proto_per_process;
 CREATE VIEW core_type_proto_per_process AS
 SELECT
   upid,
@@ -173,7 +165,6 @@
 FROM core_type_metrics_per_process
 GROUP BY upid;
 
-DROP VIEW IF EXISTS metrics_proto_per_process;
 CREATE VIEW metrics_proto_per_process AS
 SELECT
   upid,
@@ -190,7 +181,6 @@
 JOIN thread USING (utid)
 GROUP BY upid;
 
-DROP VIEW IF EXISTS android_cpu_output;
 CREATE VIEW android_cpu_output AS
 SELECT AndroidCpuMetric(
   'process_info', (
diff --git a/src/trace_processor/metrics/android/android_cpu_agg.sql b/src/trace_processor/metrics/android/android_cpu_agg.sql
index d5f145e..521f580 100644
--- a/src/trace_processor/metrics/android/android_cpu_agg.sql
+++ b/src/trace_processor/metrics/android/android_cpu_agg.sql
@@ -16,7 +16,6 @@
 
 -- Create all the views used to aggregate CPU data.
 -- View with start and end ts for each cpu frequency, per cpu.
-DROP VIEW IF EXISTS cpu_freq_view;
 CREATE VIEW cpu_freq_view AS
 SELECT
   cpu,
@@ -29,6 +28,5 @@
 WHERE name = 'cpufreq';
 
 -- View that joins the cpufreq table with the slice table.
-DROP TABLE IF EXISTS cpu_freq_sched_per_thread;
 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_cpu_raw_metrics_per_core.sql b/src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql
index bd1ec7d..1635a43 100644
--- a/src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql
+++ b/src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql
@@ -13,14 +13,22 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-SELECT RUN_METRIC('android/cpu_info.sql');
-
-DROP TABLE IF EXISTS {{output_table}};
 CREATE TABLE {{output_table}} AS
 SELECT
   utid,
   cpu,
-  IFNULL(core_type_per_cpu.core_type, 'unknown') core_type,
+  (
+    SELECT
+      CASE
+        WHEN layout = 'big_little_bigger' AND cpu < 4 THEN 'little'
+        WHEN layout = 'big_little_bigger' AND cpu < 7 THEN 'big'
+        WHEN layout = 'big_little_bigger' AND cpu = 7 THEN 'bigger'
+        WHEN layout = 'big_little' AND cpu < 4 THEN 'little'
+        WHEN layout = 'big_little' AND cpu < 8 THEN 'big'
+        ELSE 'unknown'
+      END
+    FROM core_layout_type
+  ) AS core_type,
   -- We divide by 1e3 here as dur is in ns and freq_khz in khz. In total
   -- this means we need to divide the duration by 1e9 and multiply the
   -- frequency by 1e3 then multiply again by 1e3 to get millicycles
@@ -28,7 +36,7 @@
   -- We use millicycles as we want to preserve this level of precision
   -- for future calculations.
   SUM(dur * freq_khz / 1000) AS millicycles,
-  CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) AS mcycles,
+  CAST(SUM(dur * freq_khz / 1000000 / 1000000) AS INT) AS mcycles,
   SUM(dur) AS runtime_ns,
   MIN(freq_khz) AS min_freq_khz,
   MAX(freq_khz) AS max_freq_khz,
@@ -37,5 +45,4 @@
   -- overflows.
   CAST(SUM(dur * freq_khz / 1000) / SUM(dur / 1000) AS INT) AS avg_freq_khz
 FROM {{input_table}}
-LEFT JOIN core_type_per_cpu USING (cpu)
 GROUP BY utid, cpu;
diff --git a/src/trace_processor/metrics/android/android_dma_heap.sql b/src/trace_processor/metrics/android/android_dma_heap.sql
deleted file mode 100644
index afdab08..0000000
--- a/src/trace_processor/metrics/android/android_dma_heap.sql
+++ /dev/null
@@ -1,78 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 dma_heap_timeline;
-CREATE VIEW dma_heap_timeline AS
-SELECT
-  ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
-    OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
-  track_id,
-  value
-FROM counter JOIN counter_track
-  ON counter.track_id = counter_track.id
-WHERE (name = 'mem.dma_heap');
-
-DROP VIEW IF EXISTS dma_heap_stats;
-CREATE VIEW dma_heap_stats AS
-SELECT
-  SUM(value * dur) / SUM(dur) AS avg_size,
-  MIN(value) AS min_size,
-  MAX(value) AS max_size
-FROM dma_heap_timeline;
-
-DROP VIEW IF EXISTS dma_heap_raw_allocs;
-CREATE VIEW dma_heap_raw_allocs AS
-SELECT
-  ts,
-  value AS instant_value,
-  SUM(value) OVER win AS value
-FROM counter c JOIN thread_counter_track t ON c.track_id = t.id
-WHERE (name = 'mem.dma_heap_change') AND value > 0
-WINDOW win AS (
-  PARTITION BY name ORDER BY ts
-  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-);
-
-DROP VIEW IF EXISTS dma_heap_total_stats;
-CREATE VIEW dma_heap_total_stats AS
-SELECT
-  SUM(instant_value) AS total_alloc_size_bytes
-FROM dma_heap_raw_allocs;
-
--- We need to group by ts here as we can have two ion events from
--- different processes occurring at the same timestamp. We take the
--- max as this will take both allocations into account at that
--- timestamp.
-DROP VIEW IF EXISTS android_dma_heap_event;
-CREATE VIEW android_dma_heap_event AS
-SELECT
-  'counter' AS track_type,
-  printf('Buffers created from DMA-BUF heaps: ') AS track_name,
-  ts,
-  MAX(value) AS value
-FROM dma_heap_raw_allocs
-GROUP BY 1, 2, 3;
-
-DROP VIEW IF EXISTS android_dma_heap_output;
-CREATE VIEW android_dma_heap_output AS
-SELECT AndroidDmaHeapMetric(
-      'avg_size_bytes', avg_size,
-      'min_size_bytes', min_size,
-      'max_size_bytes', max_size,
-      'total_alloc_size_bytes', total_alloc_size_bytes
-  )
-FROM dma_heap_stats JOIN dma_heap_total_stats;
diff --git a/src/trace_processor/metrics/android/android_fastrpc.sql b/src/trace_processor/metrics/android/android_fastrpc.sql
deleted file mode 100644
index 81da811..0000000
--- a/src/trace_processor/metrics/android/android_fastrpc.sql
+++ /dev/null
@@ -1,72 +0,0 @@
-DROP VIEW IF EXISTS fastrpc_timeline;
-CREATE VIEW fastrpc_timeline AS
-SELECT
-  ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
-    OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
-  RTRIM(SUBSTR(name, 13), ']') AS subsystem_name,
-  track_id,
-  value
-FROM counter JOIN counter_track
-  ON counter.track_id = counter_track.id
-WHERE (name LIKE 'mem.fastrpc[%');
-
-DROP VIEW IF EXISTS fastrpc_subsystem_stats;
-CREATE VIEW fastrpc_subsystem_stats AS
-SELECT
-  subsystem_name,
-  SUM(value * dur) / SUM(dur) AS avg_size,
-  MIN(value) AS min_size,
-  MAX(value) AS max_size
-FROM fastrpc_timeline
-GROUP BY 1;
-
-DROP VIEW IF EXISTS fastrpc_raw_allocs;
-CREATE VIEW fastrpc_raw_allocs AS
-SELECT
-  RTRIM(SUBSTR(name, 20), ']') AS subsystem_name,
-  ts,
-  value AS instant_value,
-  SUM(value) OVER win AS value
-FROM counter c JOIN thread_counter_track t ON c.track_id = t.id
-WHERE name LIKE 'mem.fastrpc_change%' AND value > 0
-WINDOW win AS (
-  PARTITION BY name ORDER BY ts
-  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-);
-
-DROP VIEW IF EXISTS fastrpc_alloc_stats;
-CREATE VIEW fastrpc_alloc_stats AS
-SELECT
-  subsystem_name,
-  SUM(instant_value) AS total_alloc_size_bytes
-FROM fastrpc_raw_allocs
-GROUP BY 1;
-
--- We need to group by ts here as we can have two events from
--- different processes occurring at the same timestamp. We take the
--- max as this will take both allocations into account at that
--- timestamp.
-DROP VIEW IF EXISTS android_fastrpc_event;
-CREATE VIEW android_fastrpc_event AS
-SELECT
-  'counter' AS track_type,
-  printf('fastrpc allocations (subsystem: %s)', subsystem_name) AS track_name,
-  ts,
-  MAX(value) AS value
-FROM fastrpc_raw_allocs
-GROUP BY 1, 2, 3;
-
-DROP VIEW IF EXISTS android_fastrpc_output;
-CREATE VIEW android_fastrpc_output AS
-SELECT AndroidFastrpcMetric(
-  'subsystem', RepeatedField(
-    AndroidFastrpcMetric_Subsystem(
-      'name', subsystem_name,
-      'avg_size_bytes', avg_size,
-      'min_size_bytes', min_size,
-      'max_size_bytes', max_size,
-      'total_alloc_size_bytes', total_alloc_size_bytes
-    )
-  ))
-FROM fastrpc_subsystem_stats JOIN fastrpc_alloc_stats USING (subsystem_name);
diff --git a/src/trace_processor/metrics/android/android_gpu.sql b/src/trace_processor/metrics/android/android_gpu.sql
deleted file mode 100644
index 644f00d..0000000
--- a/src/trace_processor/metrics/android/android_gpu.sql
+++ /dev/null
@@ -1,67 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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/global_counter_span_view.sql',
-  'table_name', 'global_gpu_memory',
-  'counter_name', 'GPU Memory');
-
-SELECT RUN_METRIC('android/process_counter_span_view.sql',
-  'table_name', 'proc_gpu_memory',
-  'counter_name', 'GPU Memory');
-
-DROP VIEW IF EXISTS proc_gpu_memory_view;
-CREATE VIEW proc_gpu_memory_view AS
-SELECT
-  upid,
-  MAX(proc_gpu_memory_val) as mem_max,
-  MIN(proc_gpu_memory_val) as mem_min,
-  SUM(proc_gpu_memory_val * dur) as mem_valxdur,
-  SUM(dur) as mem_dur
-FROM proc_gpu_memory_span
-GROUP BY upid;
-
-DROP VIEW IF EXISTS agg_proc_gpu_view;
-CREATE VIEW agg_proc_gpu_view AS
-SELECT
-  name,
-  MAX(mem_max) as mem_max,
-  MIN(mem_min) as mem_min,
-  SUM(mem_valxdur) / SUM(mem_dur) as mem_avg
-FROM process
-JOIN proc_gpu_memory_view
-USING(upid)
-GROUP BY name;
-
-DROP VIEW IF EXISTS proc_gpu_view;
-CREATE VIEW proc_gpu_view AS
-SELECT
-  AndroidGpuMetric_Process(
-    'name', name,
-    'mem_max', CAST(mem_max as INT64),
-    'mem_min', CAST(mem_min as INT64),
-    'mem_avg', CAST(mem_avg as INT64)
-  ) AS proto
-FROM agg_proc_gpu_view;
-
-DROP VIEW IF EXISTS android_gpu_output;
-CREATE VIEW android_gpu_output AS
-SELECT AndroidGpuMetric(
-  'processes', (SELECT RepeatedField(proto) FROM proc_gpu_view),
-  'mem_max', CAST(MAX(global_gpu_memory_val) as INT64),
-  'mem_min', CAST(MIN(global_gpu_memory_val) as INT64),
-  'mem_avg', CAST(SUM(global_gpu_memory_val * dur) / SUM(dur) as INT64)
-)
-FROM global_gpu_memory_span;
diff --git a/src/trace_processor/metrics/android/android_hwcomposer.sql b/src/trace_processor/metrics/android/android_hwcomposer.sql
deleted file mode 100644
index 7c46107..0000000
--- a/src/trace_processor/metrics/android/android_hwcomposer.sql
+++ /dev/null
@@ -1,83 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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/composition_layers.sql',
-  'track_name', 'HWComposer: Total Layer',
-  'output', 'total_layers'
-);
-
-SELECT RUN_METRIC(
-  'android/composition_layers.sql',
-  'track_name', 'HWComposer: DPU Layer',
-  'output', 'dpu_layers'
-);
-
-SELECT RUN_METRIC(
-  'android/composition_layers.sql',
-  'track_name', 'HWComposer: GPU Layer',
-  'output', 'gpu_layers'
-);
-
-SELECT RUN_METRIC(
-  'android/composition_layers.sql',
-  'track_name', 'HWComposer: DPU Cached Layer',
-  'output', 'dpu_cached_layers'
-);
-
-SELECT RUN_METRIC(
-  'android/composition_layers.sql',
-  'track_name', 'HWComposer: SF Cached Layer',
-  'output', 'sf_cached_layers'
-);
-
-SELECT RUN_METRIC(
-  'android/composer_execution.sql',
-  'output', 'hwc_execution_spans'
-);
-
-DROP VIEW IF EXISTS android_hwcomposer_output;
-CREATE VIEW android_hwcomposer_output AS
-SELECT AndroidHwcomposerMetrics(
-  'composition_total_layers', (SELECT AVG(value) FROM total_layers),
-  'composition_dpu_layers', (SELECT AVG(value) FROM dpu_layers),
-  'composition_gpu_layers', (SELECT AVG(value) FROM gpu_layers),
-  'composition_dpu_cached_layers', (SELECT AVG(value) FROM dpu_cached_layers),
-  'composition_sf_cached_layers', (SELECT AVG(value) FROM sf_cached_layers),
-  'skipped_validation_count',
-      (SELECT COUNT(*) FROM hwc_execution_spans
-      WHERE validation_type = 'skipped_validation'),
-  'unskipped_validation_count',
-      (SELECT COUNT(*) FROM hwc_execution_spans
-      WHERE validation_type = 'unskipped_validation'),
-  'separated_validation_count',
-      (SELECT COUNT(*) FROM hwc_execution_spans
-      WHERE validation_type = 'separated_validation'),
-  'unknown_validation_count',
-      (SELECT COUNT(*) FROM hwc_execution_spans
-      WHERE validation_type = 'unknown'),
-  'avg_all_execution_time_ms',
-      (SELECT AVG(execution_time_ns) / 1e6 FROM hwc_execution_spans
-      WHERE validation_type != 'unknown'),
-  'avg_skipped_execution_time_ms',
-      (SELECT AVG(execution_time_ns) / 1e6 FROM hwc_execution_spans
-      WHERE validation_type = 'skipped_validation'),
-  'avg_unskipped_execution_time_ms',
-      (SELECT AVG(execution_time_ns) / 1e6 FROM hwc_execution_spans
-      WHERE validation_type = 'unskipped_validation'),
-  'avg_separated_execution_time_ms',
-      (SELECT AVG(execution_time_ns) / 1e6 FROM hwc_execution_spans
-      WHERE validation_type = 'separated_validation')
-);
diff --git a/src/trace_processor/metrics/android/android_hwui_metric.sql b/src/trace_processor/metrics/android/android_hwui_metric.sql
index 585e515..4943f2e 100644
--- a/src/trace_processor/metrics/android/android_hwui_metric.sql
+++ b/src/trace_processor/metrics/android/android_hwui_metric.sql
@@ -16,7 +16,6 @@
 
 
 -- TOP processes that have a RenderThread, sorted by CPU time on RT
-DROP VIEW IF EXISTS hwui_processes;
 CREATE VIEW hwui_processes AS
 SELECT
   process.name as process_name,
@@ -29,7 +28,6 @@
 GROUP BY process.name
 ORDER BY rt_cpu_time_ms DESC;
 
-DROP VIEW IF EXISTS hwui_draw_frame;
 CREATE VIEW hwui_draw_frame AS
 SELECT
   count(*) as draw_frame_count,
@@ -39,10 +37,9 @@
   thread_track.utid as render_thread_id
 FROM slice
 INNER JOIN thread_track ON (thread_track.id = slice.track_id)
-WHERE slice.name LIKE 'DrawFrame%' AND slice.dur >= 0
+WHERE slice.name='DrawFrame' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_flush_commands;
 CREATE VIEW hwui_flush_commands AS
 SELECT
   count(*) as flush_count,
@@ -55,7 +52,6 @@
 WHERE slice.name='flush commands' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_prepare_tree;
 CREATE VIEW hwui_prepare_tree AS
 SELECT
   count(*) as prepare_tree_count,
@@ -68,7 +64,6 @@
 WHERE slice.name='prepareTree' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_gpu_completion;
 CREATE VIEW hwui_gpu_completion AS
 SELECT
   count(*) as gpu_completion_count,
@@ -82,7 +77,6 @@
 WHERE slice.name LIKE 'waiting for GPU completion%' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_ui_record;
 CREATE VIEW hwui_ui_record AS
 SELECT
   count(*) as ui_record_count,
@@ -97,7 +91,6 @@
 WHERE slice.name='Record View#draw()' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_shader_compile;
 CREATE VIEW hwui_shader_compile AS
 SELECT
   count(*) as shader_compile_count,
@@ -109,7 +102,6 @@
 WHERE slice.name='shader_compile' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_cache_hit;
 CREATE VIEW hwui_cache_hit AS
 SELECT
   count(*) as cache_hit_count,
@@ -121,7 +113,6 @@
 WHERE slice.name='cache_hit' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_cache_miss;
 CREATE VIEW hwui_cache_miss AS
 SELECT
   count(*) as cache_miss_count,
@@ -133,7 +124,6 @@
 WHERE slice.name='cache_miss' AND slice.dur >= 0
 GROUP BY thread_track.utid;
 
-DROP VIEW IF EXISTS hwui_graphics_cpu_mem;
 CREATE VIEW hwui_graphics_cpu_mem AS
 SELECT
   max(value) as graphics_cpu_mem_max,
@@ -145,7 +135,6 @@
 WHERE name='HWUI CPU Memory' AND counter.value >= 0
 GROUP BY process_counter_track.upid;
 
-DROP VIEW IF EXISTS hwui_graphics_gpu_mem;
 CREATE VIEW hwui_graphics_gpu_mem AS
 SELECT
   max(value) as graphics_gpu_mem_max,
@@ -157,7 +146,6 @@
 WHERE name='HWUI Misc Memory' AND counter.value >= 0
 GROUP BY process_counter_track.upid;
 
-DROP VIEW IF EXISTS hwui_texture_mem;
 CREATE VIEW hwui_texture_mem AS
 SELECT
   max(value) as texture_mem_max,
@@ -169,7 +157,6 @@
 WHERE name='HWUI Texture Memory' AND counter.value >= 0
 GROUP BY process_counter_track.upid;
 
-DROP VIEW IF EXISTS hwui_all_mem;
 CREATE VIEW hwui_all_mem AS
 SELECT
   max(value) as all_mem_max,
@@ -181,7 +168,6 @@
 WHERE name='HWUI All Memory' AND counter.value >= 0
 GROUP BY process_counter_track.upid;
 
-DROP VIEW IF EXISTS android_hwui_metric_output;
 CREATE VIEW android_hwui_metric_output AS
 SELECT AndroidHwuiMetric(
   'process_info', (
diff --git a/src/trace_processor/metrics/android/android_hwui_threads.sql b/src/trace_processor/metrics/android/android_hwui_threads.sql
deleted file mode 100644
index 942005b..0000000
--- a/src/trace_processor/metrics/android/android_hwui_threads.sql
+++ /dev/null
@@ -1,122 +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_prefix}}_main_thread;
-CREATE VIEW {{table_name_prefix}}_main_thread AS
-  SELECT
-    process.name as process_name,
-    thread.utid
-  FROM thread
-  JOIN {{process_allowlist_table}} process USING (upid)
-  WHERE thread.is_main_thread;
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_render_thread;
-CREATE VIEW {{table_name_prefix}}_render_thread AS
-  SELECT
-    process.name as process_name,
-    thread.utid
-  FROM thread
-  JOIN {{process_allowlist_table}} process USING (upid)
-  WHERE thread.name = 'RenderThread';
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_gpu_completion_thread;
-CREATE VIEW {{table_name_prefix}}_gpu_completion_thread AS
-  SELECT
-    process.name as process_name,
-    thread.utid
-  FROM thread
-  JOIN {{process_allowlist_table}} process USING (upid)
-  WHERE thread.name = 'GPU completion';
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_hwc_release_thread;
-CREATE VIEW {{table_name_prefix}}_hwc_release_thread AS
-  SELECT
-    process.name as process_name,
-    thread.utid
-  FROM thread
-  JOIN {{process_allowlist_table}} process USING (upid)
-  WHERE thread.name = 'HWC release';
-
-DROP TABLE IF EXISTS {{table_name_prefix}}_main_thread_slices;
-CREATE TABLE {{table_name_prefix}}_main_thread_slices AS
-  SELECT
-    process_name,
-    thread.utid,
-    slice.*,
-    ts + dur AS ts_end
-  FROM slice
-  JOIN thread_track ON slice.track_id = thread_track.id
-  JOIN {{table_name_prefix}}_main_thread thread USING (utid)
-  WHERE dur > 0;
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_do_frame_slices;
-CREATE VIEW {{table_name_prefix}}_do_frame_slices AS
-  SELECT
-    *,
-    CAST(STR_SPLIT(name, ' ', 1) AS INTEGER) as vsync
-  FROM {{table_name_prefix}}_main_thread_slices
-  WHERE name LIKE 'Choreographer#doFrame%';
-
-DROP TABLE IF EXISTS {{table_name_prefix}}_render_thread_slices;
-CREATE TABLE {{table_name_prefix}}_render_thread_slices AS
-  SELECT
-    process_name,
-    thread.utid,
-    slice.*,
-    ts + dur AS ts_end
-  FROM slice
-  JOIN thread_track ON slice.track_id = thread_track.id
-  JOIN {{table_name_prefix}}_render_thread thread USING (utid)
-  WHERE dur > 0;
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_draw_frame_slices;
-CREATE VIEW {{table_name_prefix}}_draw_frame_slices AS
-  SELECT
-    *,
-    CAST(STR_SPLIT(name, ' ', 1) AS INTEGER) as vsync
-  FROM {{table_name_prefix}}_render_thread_slices
-  WHERE name LIKE 'DrawFrame%';
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_gpu_completion_slices;
-CREATE VIEW {{table_name_prefix}}_gpu_completion_slices AS
-  SELECT
-    process_name,
-    thread.utid,
-    slice.*,
-    ts + dur AS ts_end,
-    -- Extracts 1234 from 'waiting for GPU completion 1234'
-    CAST(STR_SPLIT(slice.name, ' ', 4) AS INTEGER) as idx
-  FROM slice
-  JOIN thread_track ON slice.track_id = thread_track.id
-  JOIN {{table_name_prefix}}_gpu_completion_thread thread USING (utid)
-  WHERE slice.name LIKE 'waiting for GPU completion %'
-  AND dur > 0;
-
-DROP VIEW IF EXISTS {{table_name_prefix}}_hwc_release_slices;
-CREATE VIEW {{table_name_prefix}}_hwc_release_slices AS
-  SELECT
-    process_name,
-    thread.utid,
-    slice.*,
-    ts + dur as ts_end,
-    -- Extracts 1234 from 'waiting for HWC release 1234'
-    CAST(STR_SPLIT(slice.name, ' ', 4) AS INTEGER) as idx
-  FROM slice
-  JOIN thread_track ON slice.track_id = thread_track.id
-  JOIN {{table_name_prefix}}_hwc_release_thread thread USING (utid)
-  WHERE slice.name LIKE 'waiting for HWC release %'
-  AND dur > 0;
diff --git a/src/trace_processor/metrics/android/android_ion.sql b/src/trace_processor/metrics/android/android_ion.sql
index 93fe8ac..b2a72fe 100644
--- a/src/trace_processor/metrics/android/android_ion.sql
+++ b/src/trace_processor/metrics/android/android_ion.sql
@@ -14,8 +14,7 @@
 -- limitations under the License.
 --
 
-DROP VIEW IF EXISTS ion_timeline;
-CREATE VIEW ion_timeline AS
+CREATE VIEW IF NOT EXISTS ion_timeline AS
 SELECT
   ts,
   LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
@@ -30,8 +29,7 @@
   ON counter.track_id = counter_track.id
 WHERE (name LIKE 'mem.ion.%' OR name = 'mem.ion');
 
-DROP VIEW IF EXISTS ion_heap_stats;
-CREATE VIEW ion_heap_stats AS
+CREATE VIEW IF NOT EXISTS ion_heap_stats AS
 SELECT
   heap_name,
   SUM(value * dur) / SUM(dur) AS avg_size,
@@ -40,8 +38,7 @@
 FROM ion_timeline
 GROUP BY 1;
 
-DROP VIEW IF EXISTS ion_raw_allocs;
-CREATE VIEW ion_raw_allocs AS
+CREATE VIEW IF NOT EXISTS ion_raw_allocs AS
 SELECT
   CASE name
     WHEN 'mem.ion_change' THEN 'all'
@@ -57,8 +54,7 @@
   ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
 );
 
-DROP VIEW IF EXISTS ion_alloc_stats;
-CREATE VIEW ion_alloc_stats AS
+CREATE VIEW IF NOT EXISTS ion_alloc_stats AS
 SELECT
   heap_name,
   SUM(instant_value) AS total_alloc_size_bytes
@@ -69,8 +65,7 @@
 -- different processes occurring at the same timestamp. We take the
 -- max as this will take both allocations into account at that
 -- timestamp.
-DROP VIEW IF EXISTS android_ion_event;
-CREATE VIEW android_ion_event AS
+CREATE VIEW IF NOT EXISTS android_ion_annotations AS
 SELECT
   'counter' AS track_type,
   printf('ION allocations (heap: %s)', heap_name) AS track_name,
@@ -79,8 +74,7 @@
 FROM ion_raw_allocs
 GROUP BY 1, 2, 3;
 
-DROP VIEW IF EXISTS android_ion_output;
-CREATE VIEW android_ion_output AS
+CREATE VIEW IF NOT EXISTS android_ion_output AS
 SELECT AndroidIonMetric(
   'buffer', RepeatedField(
     AndroidIonMetric_Buffer(
diff --git a/src/trace_processor/metrics/android/android_jank.sql b/src/trace_processor/metrics/android/android_jank.sql
deleted file mode 100644
index 44f7d81..0000000
--- a/src/trace_processor/metrics/android/android_jank.sql
+++ /dev/null
@@ -1,284 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 android_jank_process_allowlist;
-CREATE TABLE android_jank_process_allowlist AS
-SELECT process.name, process.upid
-FROM process
-WHERE process.name IN (
-  'com.android.systemui',
-  'com.google.android.apps.nexuslauncher',
-  'com.google.android.inputmethod.latin'
-);
-
-SELECT RUN_METRIC(
-  'android/android_hwui_threads.sql',
-  'table_name_prefix', 'android_jank',
-  'process_allowlist_table', 'android_jank_process_allowlist');
-
-DROP TABLE IF EXISTS android_jank_thread_state_running;
-CREATE TABLE android_jank_thread_state_running AS
-SELECT utid, ts, dur, state
-FROM thread_state
-WHERE utid IN (SELECT utid FROM android_jank_main_thread_slices)
-AND state = 'Running'
-AND dur > 0;
-
-DROP TABLE IF EXISTS android_jank_thread_state_scheduled;
-CREATE TABLE android_jank_thread_state_scheduled AS
-SELECT utid, ts, dur, state
-FROM thread_state
-WHERE utid IN (SELECT utid FROM android_jank_main_thread_slices)
-AND (state = 'R' OR state = 'R+')
-AND dur > 0;
-
-DROP TABLE IF EXISTS android_jank_thread_state_io_wait;
-CREATE TABLE android_jank_thread_state_io_wait AS
-SELECT utid, ts, dur, state
-FROM thread_state
-WHERE utid IN (SELECT utid FROM android_jank_main_thread_slices)
-AND (((state = 'D' OR state = 'DK') AND io_wait) OR (state = 'DK' AND io_wait IS NULL))
-AND dur > 0;
-
---
--- Main Thread alerts
---
-
--- Expensive measure/layout
-
-DROP TABLE IF EXISTS android_jank_measure_layout_slices;
-CREATE TABLE android_jank_measure_layout_slices AS
-SELECT
-  process_name,
-  utid,
-  id,
-  ts,
-  dur
-FROM android_jank_main_thread_slices
-WHERE name in ('measure', 'layout')
-AND dur >= 3000000;
-
-CREATE VIRTUAL TABLE IF NOT EXISTS android_jank_measure_layout_slices_state
-USING span_join(android_jank_measure_layout_slices PARTITIONED utid, android_jank_thread_state_running PARTITIONED utid);
-
-DROP TABLE IF EXISTS android_jank_measure_layout_slices_high_cpu;
-CREATE TABLE android_jank_measure_layout_slices_high_cpu AS
-SELECT id FROM android_jank_measure_layout_slices_state
-GROUP BY id
-HAVING SUM(dur) > 3000000;
-
-DROP TABLE IF EXISTS android_jank_measure_layout_alerts;
-CREATE TABLE android_jank_measure_layout_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Expensive measure/layout pass' as alert_name,
-  id
-FROM android_jank_measure_layout_slices
-JOIN android_jank_measure_layout_slices_high_cpu USING (id);
-
--- Inflation during ListView recycling
--- as additional alerts for expensive layout slices
-
-DROP TABLE IF EXISTS android_jank_listview_inflation_alerts;
-CREATE TABLE android_jank_listview_inflation_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Inflation during ListView recycling' as alert_name
-FROM android_jank_main_thread_slices
-WHERE name IN ('obtainView', 'setupListItem')
-AND EXISTS (
-  SELECT 1
-  FROM descendant_slice(android_jank_main_thread_slices.id)
-  WHERE name = 'inflate')
-AND EXISTS(
-  SELECT 1
-  FROM android_jank_measure_layout_alerts
-  JOIN ancestor_slice(android_jank_main_thread_slices.id) USING (id)
-);
-
--- Long View#draw()
-
-DROP TABLE IF EXISTS android_jank_view_draw_slices;
-CREATE TABLE android_jank_view_draw_slices AS
-SELECT
-  process_name,
-  utid,
-  id,
-  ts,
-  dur
-FROM android_jank_main_thread_slices
-WHERE name in ('getDisplayList', 'Record View#draw()')
-AND dur >= 3000000;
-
-CREATE VIRTUAL TABLE IF NOT EXISTS android_jank_view_draw_slices_state
-USING span_join(android_jank_view_draw_slices PARTITIONED utid, android_jank_thread_state_running PARTITIONED utid);
-
-DROP TABLE IF EXISTS android_jank_view_draw_slices_high_cpu;
-CREATE TABLE android_jank_view_draw_slices_high_cpu AS
-SELECT id FROM android_jank_view_draw_slices_state
-GROUP BY id
-HAVING SUM(dur) > 3000000;
-
-DROP TABLE IF EXISTS android_jank_view_draw_alerts;
-CREATE TABLE android_jank_view_draw_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Long View#draw()' as alert_name
-FROM android_jank_main_thread_slices
-JOIN android_jank_view_draw_slices_high_cpu USING (id);
-
--- Scheduling delay and Blocking I/O delay
-
-DROP TABLE IF EXISTS android_jank_long_do_frame_slices;
-CREATE TABLE android_jank_long_do_frame_slices AS
-SELECT
-  process_name,
-  utid,
-  id,
-  ts,
-  dur
-FROM android_jank_main_thread_slices
-WHERE name LIKE 'Choreographer#doFrame%'
-AND dur >= 5000000;
-
-CREATE VIRTUAL TABLE IF NOT EXISTS android_jank_do_frame_slices_state_scheduled
-USING span_join(android_jank_long_do_frame_slices PARTITIONED utid, android_jank_thread_state_scheduled PARTITIONED utid);
-
-
-DROP TABLE IF EXISTS android_jank_do_frame_slices_long_scheduled;
-CREATE TABLE android_jank_do_frame_slices_long_scheduled AS
-SELECT id FROM android_jank_do_frame_slices_state_scheduled
-GROUP BY id
-HAVING SUM(dur) > 5000000;
-
-DROP TABLE IF EXISTS android_jank_scheduling_delay_alerts;
-CREATE TABLE android_jank_scheduling_delay_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Scheduling delay' as alert_name
-FROM android_jank_long_do_frame_slices
-JOIN android_jank_do_frame_slices_long_scheduled USING (id);
-
-CREATE VIRTUAL TABLE IF NOT EXISTS android_jank_do_frame_slices_state_io_wait
-USING span_join(android_jank_long_do_frame_slices PARTITIONED utid, android_jank_thread_state_io_wait PARTITIONED utid);
-
-DROP TABLE IF EXISTS android_jank_do_frame_slices_long_io_wait;
-CREATE TABLE android_jank_do_frame_slices_long_io_wait AS
-SELECT id FROM android_jank_do_frame_slices_state_io_wait
-GROUP BY id
-HAVING SUM(dur) > 5000000;
-
-DROP TABLE IF EXISTS android_jank_blocking_delay_alerts;
-CREATE TABLE android_jank_blocking_delay_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Blocking I/O delay' as alert_name
-FROM android_jank_do_frame_slices
-JOIN android_jank_do_frame_slices_long_io_wait USING (id);
-
---
--- Render Thread alerts
---
-
--- Expensive Canvas#saveLayer()
-
-DROP TABLE IF EXISTS android_jank_save_layer_alerts;
-CREATE TABLE android_jank_save_layer_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Expensive rendering with Canvas#saveLayer()' as alert_name
-FROM android_jank_render_thread_slices
-WHERE name LIKE '%alpha caused %saveLayer %'
-AND dur >= 1000000;
-
--- Path texture churn
-
-DROP TABLE IF EXISTS android_jank_generate_path_alerts;
-CREATE TABLE android_jank_generate_path_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Path texture churn' as alert_name
-FROM android_jank_render_thread_slices
-WHERE name = 'Generate Path Texture'
-AND dur >= 3000000;
-
--- Expensive Bitmap uploads
-
-DROP TABLE IF EXISTS android_jank_upload_texture_alerts;
-CREATE TABLE android_jank_upload_texture_alerts AS
-SELECT
-  process_name,
-  ts,
-  dur,
-  'Expensive Bitmap uploads' as alert_name
-FROM android_jank_render_thread_slices
-WHERE name LIKE 'Upload %x% Texture'
-AND dur >= 3000000;
-
--- Merge all alerts tables into one table
-DROP TABLE IF EXISTS android_jank_alerts;
-CREATE TABLE android_jank_alerts AS
-SELECT process_name, ts, dur, alert_name FROM android_jank_measure_layout_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_listview_inflation_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_scheduling_delay_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_blocking_delay_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_save_layer_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_generate_path_alerts
-UNION ALL
-SELECT process_name, ts, dur, alert_name FROM android_jank_upload_texture_alerts;
-
-DROP VIEW IF EXISTS android_jank_event;
-CREATE VIEW android_jank_event AS
-SELECT
-  'slice' as track_type,
-  process_name || ' warnings' as track_name,
-  ts,
-  0 as dur,
-  group_concat(alert_name) as slice_name
-FROM android_jank_alerts
-GROUP BY track_type, track_name, ts;
-
-DROP VIEW IF EXISTS android_jank_output;
-CREATE VIEW android_jank_output AS
-SELECT AndroidJankMetrics(
-  'warnings', (
-    SELECT RepeatedField(
-      AndroidJankMetrics_Warning(
-       'ts', ts,
-       'dur', dur,
-       'process_name', process_name,
-       'warning_text', alert_name))
-    FROM android_jank_alerts
-    ORDER BY process_name, ts, dur));
diff --git a/src/trace_processor/metrics/android/android_lmk.sql b/src/trace_processor/metrics/android/android_lmk.sql
index e4f6974..3081a9d 100644
--- a/src/trace_processor/metrics/android/android_lmk.sql
+++ b/src/trace_processor/metrics/android/android_lmk.sql
@@ -17,8 +17,7 @@
 SELECT RUN_METRIC('android/process_oom_score.sql');
 
 -- All LMK events ordered by timestamp
-DROP TABLE IF EXISTS lmk_events;
-CREATE TABLE lmk_events AS
+CREATE TABLE IF NOT EXISTS lmk_events AS
 WITH raw_events AS (
   SELECT ref AS upid, MIN(ts) AS ts
   FROM instants
@@ -36,8 +35,7 @@
       raw_events.ts < oom_scores.ts + oom_scores.dur)
 ORDER BY 1;
 
-DROP VIEW IF EXISTS android_lmk_event;
-CREATE VIEW android_lmk_event AS
+CREATE VIEW IF NOT EXISTS android_lmk_annotations AS
 WITH raw_events AS (
   SELECT
     ts,
@@ -69,8 +67,7 @@
   END AS slice_name
 FROM lmks_with_proc_name as lmk;
 
-DROP VIEW IF EXISTS android_lmk_output;
-CREATE VIEW android_lmk_output AS
+CREATE VIEW IF NOT EXISTS android_lmk_output AS
 WITH lmk_counts AS (
   SELECT score, COUNT(1) AS count
   FROM lmk_events
diff --git a/src/trace_processor/metrics/android/android_lmk_reason.sql b/src/trace_processor/metrics/android/android_lmk_reason.sql
index 0772c30..1024bd6 100644
--- a/src/trace_processor/metrics/android/android_lmk_reason.sql
+++ b/src/trace_processor/metrics/android/android_lmk_reason.sql
@@ -19,8 +19,7 @@
 SELECT RUN_METRIC('android/process_mem.sql');
 SELECT RUN_METRIC('android/process_metadata.sql');
 
-DROP VIEW IF EXISTS android_lmk_reason_output;
-CREATE VIEW android_lmk_reason_output AS
+CREATE VIEW IF NOT EXISTS android_lmk_reason_output AS
 WITH
 total_ion_name AS (
   SELECT
diff --git a/src/trace_processor/metrics/android/android_mem.sql b/src/trace_processor/metrics/android/android_mem.sql
index d50b85a..919e26d 100644
--- a/src/trace_processor/metrics/android/android_mem.sql
+++ b/src/trace_processor/metrics/android/android_mem.sql
@@ -37,7 +37,6 @@
 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).
-DROP VIEW IF EXISTS mem_all_processes;
 CREATE VIEW mem_all_processes AS
 SELECT DISTINCT process_name
 FROM
@@ -53,7 +52,6 @@
   SELECT process_name FROM java_heap_stats_proto
 );
 
-DROP VIEW IF EXISTS mem_all_process_priorities;
 CREATE VIEW mem_all_process_priorities AS
 SELECT DISTINCT process_name, priority
 FROM
@@ -69,7 +67,6 @@
   SELECT process_name, priority FROM java_heap_by_priority_stats_proto
 );
 
-DROP VIEW IF EXISTS process_priority_view;
 CREATE VIEW process_priority_view AS
 SELECT
   process_name,
@@ -90,7 +87,6 @@
 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);
 
-DROP VIEW IF EXISTS process_metrics_view;
 CREATE VIEW process_metrics_view AS
 SELECT
   AndroidMemoryMetric_ProcessMetrics(
@@ -116,7 +112,6 @@
   LEFT JOIN anon_and_swap_stats_proto USING (process_name)
   LEFT JOIN java_heap_stats_proto USING (process_name);
 
-DROP VIEW IF EXISTS android_mem_output;
 CREATE VIEW android_mem_output AS
 SELECT
   AndroidMemoryMetric(
diff --git a/src/trace_processor/metrics/android/android_mem_unagg.sql b/src/trace_processor/metrics/android/android_mem_unagg.sql
index da06751..5d147d0 100644
--- a/src/trace_processor/metrics/android/android_mem_unagg.sql
+++ b/src/trace_processor/metrics/android/android_mem_unagg.sql
@@ -28,7 +28,6 @@
 SELECT RUN_METRIC('android/process_unagg_mem_view.sql',
   'table_name', 'anon_and_swap');
 
-DROP VIEW IF EXISTS process_unagg_metrics_view;
 CREATE VIEW process_unagg_metrics_view AS
 SELECT
   AndroidMemoryUnaggregatedMetric_ProcessValues(
@@ -53,7 +52,6 @@
 WHERE
   process.name IS NOT NULL;
 
-DROP VIEW IF EXISTS android_mem_unagg_output;
 CREATE VIEW android_mem_unagg_output AS
 SELECT
   AndroidMemoryUnaggregatedMetric(
diff --git a/src/trace_processor/metrics/android/android_package_list.sql b/src/trace_processor/metrics/android/android_package_list.sql
index 1c21678..5e05281 100644
--- a/src/trace_processor/metrics/android/android_package_list.sql
+++ b/src/trace_processor/metrics/android/android_package_list.sql
@@ -14,7 +14,6 @@
 -- limitations under the License.
 --
 
-DROP VIEW IF EXISTS android_package_list_output;
 CREATE VIEW android_package_list_output AS
 SELECT AndroidPackageList(
   'packages', (
diff --git a/src/trace_processor/metrics/android/android_powrails.sql b/src/trace_processor/metrics/android/android_powrails.sql
index d05324a..b8f72b9 100644
--- a/src/trace_processor/metrics/android/android_powrails.sql
+++ b/src/trace_processor/metrics/android/android_powrails.sql
@@ -15,14 +15,12 @@
 --
 
 -- View of Power Rail counters with ts converted from ns to ms.
-DROP VIEW IF EXISTS power_rails_counters;
 CREATE VIEW power_rails_counters AS
 SELECT value, ts/1000000 AS ts, name
 FROM counter c
 JOIN counter_track t on c.track_id = t.id
 WHERE name LIKE 'power.%';
 
-DROP VIEW IF EXISTS power_rails_view;
 CREATE VIEW power_rails_view AS
 WITH RECURSIVE name AS (SELECT DISTINCT name FROM power_rails_counters)
 SELECT
@@ -41,7 +39,6 @@
 GROUP BY name
 ORDER BY ts ASC;
 
-DROP VIEW IF EXISTS android_powrails_output;
 CREATE VIEW android_powrails_output AS
 SELECT AndroidPowerRails(
   'power_rails', (
diff --git a/src/trace_processor/metrics/android/android_proxy_power.sql b/src/trace_processor/metrics/android/android_proxy_power.sql
deleted file mode 100644
index c356edd..0000000
--- a/src/trace_processor/metrics/android/android_proxy_power.sql
+++ /dev/null
@@ -1,83 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
--- This metric assigns a power drain rate in milliampers to each sched slice.
--- The power_profile table should be populated with device power profile data
--- before running the metric. It has the following scheme:
--- (device STRING, cpu INT, cluster INT, freq INT, power DOUBLE).
---
--- Metric usage examples:
--- 1) Compute the power cost of every thread in milliamper-seconds:
---     SELECT
---         utid,
---         SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
---     FROM power_per_thread
---     GROUP BY utid;
--- 2) Compute the total power cost of all slices from a table 'my_slice':
---     CREATE VIEW my_slice_utid AS
---     SELECT ts, dur, utid
---     FROM my_slice
---     INNER JOIN thread_track ON track_id = thread_track.id;
---
---     CREATE VIRTUAL TABLE my_slice_power
---     USING SPAN_JOIN(power_per_thread PARTITIONED utid,
---                     my_slice_utid PARTITIONED utid);
---
---     SELECT
---         SUM(dur * COALESCE(power_ma, 0) / 1e9) as power_mas
---     FROM my_slice_power;
-
-SELECT RUN_METRIC('android/android_cpu_agg.sql');
-SELECT RUN_METRIC('android/power_profile_data.sql');
-
-DROP VIEW IF EXISTS device;
-CREATE VIEW device AS
-WITH
-  after_first_slash(str) AS (
-      SELECT SUBSTR(str_value, INSTR(str_value, '/') + 1)
-      FROM metadata
-      WHERE name = 'android_build_fingerprint'
-  ),
-  before_second_slash(str) AS (
-      SELECT SUBSTR(str, 0, INSTR(str, '/'))
-      FROM after_first_slash
-  )
-SELECT str AS name FROM before_second_slash;
-
-DROP VIEW IF EXISTS power_view;
-CREATE VIEW power_view AS
-SELECT
-  cpu_freq_view.cpu AS cpu,
-  ts,
-  dur,
-  power AS power_ma
-FROM cpu_freq_view
-JOIN power_profile ON (
-  power_profile.device = (SELECT name FROM device)
-  AND power_profile.cpu = cpu_freq_view.cpu
-  AND power_profile.freq = cpu_freq_view.freq_khz
-);
-
--- utid = 0 is a reserved value used to mark sched slices where CPU was idle.
--- It doesn't correspond to any real thread.
-DROP VIEW IF EXISTS sched_real_threads;
-CREATE VIEW sched_real_threads AS
-SELECT *
-FROM sched
-WHERE utid != 0;
-
-DROP TABLE IF EXISTS power_per_thread;
-CREATE VIRTUAL TABLE power_per_thread
-USING SPAN_LEFT_JOIN(sched_real_threads PARTITIONED cpu, power_view PARTITIONED cpu);
diff --git a/src/trace_processor/metrics/android/android_startup.sql b/src/trace_processor/metrics/android/android_startup.sql
index b97a2ab..3da0539 100644
--- a/src/trace_processor/metrics/android/android_startup.sql
+++ b/src/trace_processor/metrics/android/android_startup.sql
@@ -16,51 +16,17 @@
 
 -- 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/process_metadata.sql');
 SELECT RUN_METRIC('android/hsc_startups.sql');
 
--- Create the base CPU span join table.
-SELECT RUN_METRIC('android/android_cpu_agg.sql');
-
--- Create a span join safe launches view; since both views
--- being span joined have an "id" column, we need to rename
--- the id column for launches to disambiguate the two.
-DROP VIEW IF EXISTS launches_span_join_safe;
-CREATE VIEW launches_span_join_safe AS
-SELECT ts, dur, id AS launch_id
-FROM launches;
-
--- Span join the CPU table with the launches table to get the
--- breakdown per-cpu.
-DROP TABLE IF EXISTS cpu_freq_sched_per_thread_per_launch;
-CREATE VIRTUAL TABLE cpu_freq_sched_per_thread_per_launch
-USING SPAN_JOIN(
-  launches_span_join_safe,
-  cpu_freq_sched_per_thread PARTITIONED cpu
-);
-
-SELECT RUN_METRIC('android/cpu_info.sql');
-
-DROP VIEW IF EXISTS mcycles_per_core_type_per_launch;
-CREATE VIEW mcycles_per_core_type_per_launch AS
-SELECT
-  launch_id,
-  IFNULL(core_type_per_cpu.core_type, 'unknown') AS core_type,
-  CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) AS mcycles
-FROM cpu_freq_sched_per_thread_per_launch
-LEFT JOIN core_type_per_cpu USING (cpu)
-WHERE utid != 0
-GROUP BY 1, 2;
-
 -- Slices for forked processes. Never present in hot starts.
 -- Prefer this over process start_ts, since the process might have
 -- been preforked.
-DROP VIEW IF EXISTS zygote_fork_slice;
 CREATE VIEW zygote_fork_slice AS
 SELECT slice.ts, slice.dur, STR_SPLIT(slice.name, ": ", 1) AS process_name
 FROM slice WHERE name LIKE 'Start proc: %';
 
-DROP TABLE IF EXISTS zygote_forks_by_id;
 CREATE TABLE zygote_forks_by_id AS
 SELECT
   launches.id,
@@ -73,7 +39,6 @@
     AND zygote_fork_slice.process_name = launches.package
 );
 
-DROP VIEW IF EXISTS launch_main_threads;
 CREATE VIEW launch_main_threads AS
 SELECT
   launches.ts AS ts,
@@ -86,119 +51,42 @@
 JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
 ORDER BY ts;
 
-DROP VIEW IF EXISTS thread_state_extended;
-CREATE VIEW thread_state_extended AS
-SELECT
-  ts,
-  IIF(dur = -1, (SELECT end_ts FROM trace_bounds), dur) AS dur,
-  utid,
-  state
-FROM thread_state;
-
-DROP TABLE IF EXISTS main_thread_state;
 CREATE VIRTUAL TABLE main_thread_state
 USING SPAN_JOIN(
   launch_main_threads PARTITIONED utid,
-  thread_state_extended PARTITIONED utid);
+  task_state PARTITIONED utid);
 
-DROP VIEW IF EXISTS launch_by_thread_state;
 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 main thread process threads.
-DROP VIEW IF EXISTS launch_threads;
-CREATE VIEW launch_threads AS
+-- Tracks all slices for the main process threads
+CREATE TABLE main_process_slice AS
 SELECT
   launches.id AS launch_id,
-  launches.ts AS ts,
-  launches.dur AS dur,
-  thread.utid AS utid,
-  thread.name AS thread_name
+  slice.name AS name,
+  AndroidStartupMetric_Slice(
+    'dur_ns', SUM(slice.dur),
+    'dur_ms', SUM(slice.dur) / 1e6
+  ) AS slice_proto
 FROM launches
 JOIN launch_processes ON (launches.id = launch_processes.launch_id)
-JOIN thread ON (launch_processes.upid = thread.upid);
-
--- Tracks all slices for the main process threads
-DROP VIEW IF EXISTS main_process_slice_unaggregated;
-CREATE VIEW main_process_slice_unaggregated AS
-SELECT
-  launch_threads.launch_id AS launch_id,
-  launch_threads.utid AS utid,
-  launch_threads.thread_name AS thread_name,
-  slice.name AS slice_name,
-  slice.ts AS slice_ts,
-  slice.dur AS slice_dur
-FROM launch_threads
+JOIN thread ON (launch_processes.upid = thread.upid)
 JOIN thread_track USING (utid)
 JOIN slice ON (
   slice.track_id = thread_track.id
-  AND slice.ts BETWEEN launch_threads.ts AND launch_threads.ts + launch_threads.dur)
+  AND slice.ts BETWEEN launches.ts AND launches.ts + launches.dur)
 WHERE slice.name IN (
   'PostFork',
   'ActivityThreadMain',
   'bindApplication',
   'activityStart',
-  'activityRestart',
   'activityResume',
-  'inflate',
-  'ResourcesManager#getResources',
-  'binder transaction')
-  OR slice.name LIKE 'performResume:%'
-  OR slice.name LIKE 'performCreate:%'
-  OR slice.name LIKE 'location=% status=% filter=% reason=%'
-  OR slice.name LIKE 'OpenDexFilesFromOat%'
-  OR slice.name LIKE 'VerifyClass%'
-  OR slice.name LIKE 'Choreographer#doFrame%'
-  OR slice.name LIKE 'JIT compiling%'
-  OR slice.name LIKE '%mark sweep GC'
-  OR slice.name LIKE '%concurrent copying GC'
-  OR slice.name LIKE '%semispace GC';
-
-DROP TABLE IF EXISTS main_process_slice;
-CREATE TABLE main_process_slice AS
-SELECT
-  launch_id,
-  CASE
-    WHEN slice_name LIKE 'OpenDexFilesFromOat%' THEN 'OpenDexFilesFromOat'
-    WHEN slice_name LIKE 'VerifyClass%' THEN 'VerifyClass'
-    WHEN slice_name LIKE 'JIT compiling%' THEN 'JIT compiling'
-    WHEN slice_name LIKE '%mark sweep GC' THEN 'GC'
-    WHEN slice_name LIKE '%concurrent copying GC' THEN 'GC'
-    WHEN slice_name LIKE '%semispace GC' THEN 'GC'
-    ELSE slice_name
-  END AS name,
-  AndroidStartupMetric_Slice(
-    'dur_ns', SUM(slice_dur),
-    'dur_ms', SUM(slice_dur) / 1e6
-  ) AS slice_proto
-FROM main_process_slice_unaggregated
+  'Choreographer#doFrame',
+  'inflate')
 GROUP BY 1, 2;
 
-DROP TABLE IF EXISTS report_fully_drawn_per_launch;
-CREATE TABLE report_fully_drawn_per_launch AS
-WITH report_fully_drawn_launch_slices AS (
-  SELECT
-    launches.id AS launch_id,
-    launches.ts AS launch_ts,
-    min(slice.ts) as report_fully_drawn_ts
-  FROM launches
-  JOIN launch_processes ON (launches.id = launch_processes.launch_id)
-  JOIN thread ON (launch_processes.upid = thread.upid)
-  JOIN thread_track USING (utid)
-  JOIN slice ON (
-    slice.track_id = thread_track.id
-    AND slice.ts >= launches.ts)
-  WHERE slice.name LIKE 'reportFullyDrawn%'
-  GROUP BY launches.id
-)
-SELECT
-  launch_id,
-  report_fully_drawn_ts - launch_ts as report_fully_drawn_dur
-FROM report_fully_drawn_launch_slices;
-
-DROP VIEW IF EXISTS to_event_protos;
 CREATE VIEW to_event_protos AS
 SELECT
   slice.name as slice_name,
@@ -213,116 +101,30 @@
   slice.track_id = thread_track.id
   AND slice.ts BETWEEN l.ts AND l.ts + l.dur);
 
-DROP VIEW IF EXISTS gc_slices;
-CREATE VIEW gc_slices AS
-  SELECT
-    slice_ts AS ts,
-    slice_dur AS dur,
-    utid,
-    launch_id
-  FROM main_process_slice_unaggregated
-  WHERE (
-    slice_name LIKE '%mark sweep GC'
-    OR slice_name LIKE '%concurrent copying GC'
-    OR slice_name LIKE '%semispace GC');
-
-DROP TABLE IF EXISTS gc_slices_by_state;
-CREATE VIRTUAL TABLE gc_slices_by_state
-USING SPAN_JOIN(gc_slices PARTITIONED utid, thread_state_extended PARTITIONED utid);
-
-DROP TABLE IF EXISTS gc_slices_by_state_materialized;
-CREATE TABLE gc_slices_by_state_materialized AS
-SELECT launch_id, SUM(dur) as sum_dur
-FROM gc_slices_by_state
-WHERE state = 'Running'
-GROUP BY launch_id;
-
-DROP TABLE IF EXISTS launch_threads_cpu;
-CREATE VIRTUAL TABLE launch_threads_cpu
-USING SPAN_JOIN(launch_threads PARTITIONED utid, thread_state_extended PARTITIONED utid);
-
-DROP TABLE IF EXISTS launch_threads_cpu_materialized;
-CREATE TABLE launch_threads_cpu_materialized AS
-SELECT launch_id, SUM(dur) as sum_dur
-FROM launch_threads_cpu
-WHERE thread_name = 'Jit thread pool' AND state = 'Running'
-GROUP BY launch_id;
-
-DROP TABLE IF EXISTS activity_names_materialized;
-CREATE TABLE activity_names_materialized AS
-SELECT launch_id, slice_name, slice_ts
-FROM main_process_slice_unaggregated
-WHERE (slice_name LIKE 'performResume:%' OR slice_name LIKE 'performCreate:%');
-
-DROP TABLE IF EXISTS jit_compiled_methods_materialized;
-CREATE TABLE jit_compiled_methods_materialized AS
-SELECT
-  launch_id,
-  COUNT(1) as count
-FROM main_process_slice_unaggregated
-WHERE
-  slice_name LIKE 'JIT compiling%'
-  AND thread_name = 'Jit thread pool'
-GROUP BY launch_id;
-
-DROP TABLE IF EXISTS long_binder_transactions;
-CREATE TABLE long_binder_transactions AS
-SELECT
-  launch_id, slice_dur, thread_name
-FROM
-  main_process_slice_unaggregated
-WHERE
-  slice_name = 'binder transaction'
-  AND slice_dur >= 1e8;
-
-DROP VIEW IF EXISTS startup_view;
 CREATE VIEW startup_view AS
 SELECT
   AndroidStartupMetric_Startup(
     'startup_id', launches.id,
     'package_name', launches.package,
     'process_name', (
-      SELECT p.name
-      FROM launch_processes lp
-      JOIN process p USING (upid)
-      WHERE lp.launch_id = launches.id
-      LIMIT 1
+      SELECT name FROM process
+      WHERE upid IN (
+        SELECT upid FROM launch_processes
+        WHERE launch_id = launches.id
+        LIMIT 1
+      )
     ),
     'process', (
-      SELECT m.metadata
-      FROM process_metadata m
-      JOIN launch_processes p USING (upid)
-      WHERE p.launch_id = launches.id
-      LIMIT 1
-    ),
-    'activities', (
-      SELECT RepeatedField(AndroidStartupMetric_Activity(
-        'name', (SELECT STR_SPLIT(s.slice_name, ':', 1)),
-        'method', (SELECT STR_SPLIT(s.slice_name, ':', 0)),
-        'ts_method_start', s.slice_ts
-      ))
-      FROM activity_names_materialized s
-      WHERE s.launch_id = launches.id
-    ),
-    'long_binder_transactions', (
-      SELECT RepeatedField(AndroidStartupMetric_BinderTransaction(
-        'duration', AndroidStartupMetric_Slice(
-          'dur_ns', lbt.slice_dur,
-          'dur_ms', lbt.slice_dur / 1e6
-        ),
-        'thread', lbt.thread_name
-      ))
-      FROM long_binder_transactions lbt
-      WHERE lbt.launch_id = launches.id
+      SELECT metadata FROM process_metadata
+      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 p
-      WHERE p.launch_id = launches.id
-    ),
-    'event_timestamps', AndroidStartupMetric_EventTimestamps(
-      'intent_received', launches.ts,
-      'first_frame', launches.ts_end
+      SELECT COUNT(1) FROM launch_processes WHERE launch_id = launches.id
     ),
     'to_first_frame', AndroidStartupMetric_ToFirstFrame(
       'dur_ns', launches.dur,
@@ -330,61 +132,39 @@
       'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown(
         'running_dur_ns', IFNULL(
             (
-            SELECT dur FROM launch_by_thread_state l
-            WHERE l.launch_id = launches.id AND state = 'Running'
+            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 l
-            WHERE l.launch_id = launches.id AND state = 'R'
+            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 l
-            WHERE l.launch_id = launches.id AND (state = 'D' or state = 'DK')
+            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 l
-            WHERE l.launch_id = launches.id AND state = 'S'
+            SELECT dur FROM launch_by_thread_state
+            WHERE launch_id = launches.id AND state = 'interruptible'
             ), 0)
       ),
-      'mcycles_by_core_type', AndroidStartupMetric_McyclesByCoreType(
-        'little', (
-          SELECT mcycles
-          FROM mcycles_per_core_type_per_launch m
-          WHERE m.launch_id = launches.id AND m.core_type = 'little'
-        ),
-        'big', (
-          SELECT mcycles
-          FROM mcycles_per_core_type_per_launch m
-          WHERE m.launch_id = launches.id AND m.core_type = 'big'
-        ),
-        'bigger', (
-          SELECT mcycles
-          FROM mcycles_per_core_type_per_launch m
-          WHERE m.launch_id = launches.id AND m.core_type = 'bigger'
-        ),
-        'unknown', (
-          SELECT mcycles
-          FROM mcycles_per_core_type_per_launch m
-          WHERE m.launch_id = launches.id AND m.core_type = 'unknown'
-        )
-      ),
       'to_post_fork', (
         SELECT slice_proto
-        FROM to_event_protos p
-        WHERE p.launch_id = launches.id AND slice_name = 'PostFork'
+        FROM to_event_protos
+        WHERE launch_id = launches.id AND slice_name = 'PostFork'
       ),
       'to_activity_thread_main', (
         SELECT slice_proto
-        FROM to_event_protos p
-        WHERE p.launch_id = launches.id AND slice_name = 'ActivityThreadMain'
+        FROM to_event_protos
+        WHERE launch_id = launches.id AND slice_name = 'ActivityThreadMain'
       ),
       'to_bind_application', (
         SELECT slice_proto
-        FROM to_event_protos p
-        WHERE p.launch_id = launches.id AND slice_name = 'bindApplication'
+        FROM to_event_protos
+        WHERE launch_id = launches.id AND slice_name = 'bindApplication'
       ),
       'other_processes_spawned_count', (
         SELECT COUNT(1) FROM process
@@ -393,148 +173,66 @@
       ),
       'time_activity_manager', (
         SELECT AndroidStartupMetric_Slice(
-          'dur_ns', l.ts - launches.ts,
-          'dur_ms', (l.ts - launches.ts) / 1e6
+          'dur_ns', launching_events.ts - launches.ts,
+          'dur_ms', (launching_events.ts - launches.ts) / 1e6
         )
-        FROM launching_events l
-        WHERE l.ts BETWEEN launches.ts AND launches.ts + launches.dur
+        FROM launching_events
+        WHERE launching_events.ts BETWEEN launches.ts AND launches.ts + launches.dur
       ),
       'time_post_fork', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'PostFork'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'PostFork'
       ),
       'time_activity_thread_main', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'ActivityThreadMain'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'ActivityThreadMain'
       ),
       'time_bind_application', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'bindApplication'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'bindApplication'
       ),
       'time_activity_start', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'activityStart'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'activityStart'
       ),
       'time_activity_resume', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'activityResume'
-      ),
-      'time_activity_restart', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'activityRestart'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'activityResume'
       ),
       'time_choreographer', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name LIKE 'Choreographer#doFrame%'
+        SELECT slice_proto FROM main_process_slice
+        WHERE launch_id = launches.id AND name = 'Choreographer#doFrame'
       ),
       'time_before_start_process', (
         SELECT AndroidStartupMetric_Slice(
           'dur_ns', ts - launches.ts,
           'dur_ms', (ts - launches.ts) / 1e6
         )
-        FROM zygote_forks_by_id z
-        WHERE z.id = launches.id
+        FROM zygote_forks_by_id WHERE id = launches.id
       ),
       'time_during_start_process', (
         SELECT AndroidStartupMetric_Slice(
           'dur_ns', dur,
           'dur_ms', dur / 1e6
         )
-        FROM zygote_forks_by_id z
-        WHERE z.id = launches.id
-      ),
-      'time_inflate', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'inflate'
-      ),
-      'time_get_resources', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id
-        AND name = 'ResourcesManager#getResources'
-      ),
-      'time_dex_open', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'OpenDexFilesFromOat'
-      ),
-      'time_verify_class', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'VerifyClass'
-      ),
-      'jit_compiled_methods', (
-        SELECT count
-        FROM jit_compiled_methods_materialized s
-        WHERE s.launch_id = launches.id
-      ),
-      'time_jit_thread_pool_on_cpu', (
-        SELECT
-          NULL_IF_EMPTY(AndroidStartupMetric_Slice(
-            'dur_ns', sum_dur,
-            'dur_ms', sum_dur / 1e6
-          ))
-        FROM launch_threads_cpu_materialized
-        WHERE launch_id = launches.id
-      ),
-      'time_gc_total', (
-        SELECT slice_proto
-        FROM main_process_slice s
-        WHERE s.launch_id = launches.id AND name = 'GC'
-      ),
-      'time_gc_on_cpu', (
-        SELECT
-          NULL_IF_EMPTY(AndroidStartupMetric_Slice(
-            'dur_ns', sum_dur,
-            'dur_ms', sum_dur / 1e6
-          ))
-        FROM gc_slices_by_state_materialized
-        WHERE launch_id = launches.id
+        FROM zygote_forks_by_id WHERE id = launches.id
       )
     ),
     'hsc', (
-      SELECT NULL_IF_EMPTY(AndroidStartupMetric_HscMetrics(
+      SELECT AndroidStartupMetric_HscMetrics(
         'full_startup', (
           SELECT AndroidStartupMetric_Slice(
-            'dur_ns', h.ts_total,
-            'dur_ms', h.ts_total / 1e6
+            'dur_ns', hsc_based_startup_times.ts_total,
+            'dur_ms', hsc_based_startup_times.ts_total / 1e6
           )
-          FROM hsc_based_startup_times h
-          WHERE h.id = launches.id
+          FROM hsc_based_startup_times WHERE id = launches.id
         )
-      ))
-    ),
-    'report_fully_drawn', (
-      SELECT NULL_IF_EMPTY(AndroidStartupMetric_Slice(
-        'dur_ns', report_fully_drawn_dur,
-        'dur_ms', report_fully_drawn_dur / 1e6
-      ))
-      FROM report_fully_drawn_per_launch r
-      WHERE r.launch_id = launches.id
-    ),
-    'optimization_status',(
-      SELECT RepeatedField(AndroidStartupMetric_OptimizationStatus(
-        'location', SUBSTR(STR_SPLIT(name, ' status=', 0), LENGTH('location=') + 1),
-        'odex_status', STR_SPLIT(STR_SPLIT(name, ' status=', 1), ' filter=', 0),
-        'compilation_filter', STR_SPLIT(STR_SPLIT(name, ' filter=', 1), ' reason=', 0),
-        'compilation_reason', STR_SPLIT(name, ' reason=', 1)
-      ))
-      FROM main_process_slice s
-      WHERE name LIKE 'location=% status=% filter=% reason=%'
+      )
     )
   ) as startup
 FROM launches;
 
-DROP VIEW IF EXISTS android_startup_event;
-CREATE VIEW android_startup_event AS
+CREATE VIEW android_startup_annotations AS
 SELECT
   'slice' as track_type,
   'Android App Startups' as track_name,
@@ -543,7 +241,6 @@
   l.package as slice_name
 FROM launches l;
 
-DROP VIEW IF EXISTS android_startup_output;
 CREATE VIEW android_startup_output AS
 SELECT
   AndroidStartupMetric(
diff --git a/src/trace_processor/metrics/android/android_startup_launches.sql b/src/trace_processor/metrics/android/android_startup_launches.sql
index 2cfb4b9..1fcb059 100644
--- a/src/trace_processor/metrics/android/android_startup_launches.sql
+++ b/src/trace_processor/metrics/android/android_startup_launches.sql
@@ -17,7 +17,6 @@
 -- 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.
-DROP TABLE IF EXISTS launching_events;
 CREATE TABLE launching_events AS
 SELECT
   ts,
@@ -32,14 +31,12 @@
 
 -- Marks the beginning of the trace and is equivalent to when the statsd launch
 -- logging begins.
-DROP VIEW IF EXISTS activity_intent_received;
 CREATE VIEW activity_intent_received AS
 SELECT ts FROM slice
 WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
 
 -- Successful activity launch. The end of the 'launching' event is not related
 -- to whether it actually succeeded or not.
-DROP VIEW IF EXISTS activity_intent_launch_successful;
 CREATE VIEW activity_intent_launch_successful AS
 SELECT ts FROM slice
 WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
@@ -47,7 +44,6 @@
 -- 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.
-DROP TABLE IF EXISTS activity_intent_recv_spans;
 CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
 
 INSERT INTO activity_intent_recv_spans
@@ -61,7 +57,6 @@
 
 -- Filter activity_intent_recv_spans, keeping only the ones that triggered
 -- a launch.
-DROP VIEW IF EXISTS launch_partitions;
 CREATE VIEW launch_partitions AS
 SELECT * FROM activity_intent_recv_spans AS spans
 WHERE 1 = (
@@ -70,7 +65,6 @@
   WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
 
 -- All activity launches in the trace, keyed by ID.
-DROP TABLE IF EXISTS launches;
 CREATE TABLE launches(
   ts BIG INT,
   ts_end BIG INT,
@@ -91,17 +85,13 @@
 JOIN launching_events ON
   (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND
   (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
-WHERE (
-  SELECT COUNT(1)
-  FROM activity_intent_launch_successful AS successful
-  WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
-) > 0;
+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.
-DROP TABLE IF EXISTS launch_processes;
 CREATE TABLE launch_processes(launch_id INT, upid BIG INT);
 
 -- We make the (not always correct) simplification that process == package
diff --git a/src/trace_processor/metrics/android/android_surfaceflinger.sql b/src/trace_processor/metrics/android/android_surfaceflinger.sql
deleted file mode 100644
index b0d761f..0000000
--- a/src/trace_processor/metrics/android/android_surfaceflinger.sql
+++ /dev/null
@@ -1,53 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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/frame_missed.sql',
-  'track_name', 'PrevFrameMissed',
-  'output', 'frame_missed'
-);
-SELECT RUN_METRIC(
-  'android/frame_missed.sql',
-  'track_name', 'PrevHwcFrameMissed',
-  'output', 'hwc_frame_missed'
-);
-SELECT RUN_METRIC(
-  'android/frame_missed.sql',
-  'track_name', 'PrevGpuFrameMissed',
-  'output', 'gpu_frame_missed'
-);
-
-DROP VIEW IF EXISTS android_surfaceflinger_event;
-CREATE VIEW android_surfaceflinger_event AS
-SELECT
-  'slice' AS track_type,
-  'Android Missed Frames' AS track_name,
-  ts,
-  dur,
-  'Frame missed' AS slice_name
-FROM frame_missed
-WHERE value = 1 AND ts IS NOT NULL;
-
-DROP VIEW IF EXISTS android_surfaceflinger_output;
-CREATE VIEW android_surfaceflinger_output AS
-SELECT
-  AndroidSurfaceflingerMetric(
-    'missed_frames', (SELECT COUNT(1) FROM frame_missed WHERE value=1),
-    'missed_hwc_frames', (SELECT COUNT(1) FROM hwc_frame_missed WHERE value=1),
-    'missed_gpu_frames', (SELECT COUNT(1) FROM gpu_frame_missed WHERE value=1),
-    'missed_frame_rate', (SELECT AVG(value) FROM frame_missed),
-    'missed_hwc_frame_rate', (SELECT AVG(value) FROM hwc_frame_missed),
-    'missed_gpu_frame_rate', (SELECT AVG(value) FROM gpu_frame_missed)
-  );
diff --git a/src/trace_processor/metrics/android/android_sysui_cuj.sql b/src/trace_processor/metrics/android/android_sysui_cuj.sql
deleted file mode 100644
index 2a0bba1..0000000
--- a/src/trace_processor/metrics/android/android_sysui_cuj.sql
+++ /dev/null
@@ -1,439 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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_metadata.sql');
-
-DROP TABLE IF EXISTS android_sysui_cuj_last_cuj;
-CREATE TABLE android_sysui_cuj_last_cuj AS
-  SELECT
-    process.name AS name,
-    process.upid AS upid,
-    process_metadata.metadata AS process_metadata,
-    SUBSTR(slice.name, 3, LENGTH(slice.name) - 3) AS cuj_name,
-    ts AS ts_start,
-    ts + dur AS ts_end,
-    dur AS dur
-  FROM slice
-  JOIN process_track ON slice.track_id = process_track.id
-  JOIN process USING (upid)
-  JOIN process_metadata USING (upid)
-  WHERE
-    slice.name LIKE 'J<%>'
-    AND slice.dur > 0
-    AND (
-      process.name LIKE 'com.google.android%'
-      OR process.name = 'com.android.systemui')
-  ORDER BY ts desc
-  LIMIT 1;
-
-SELECT RUN_METRIC(
-  'android/android_hwui_threads.sql',
-  'table_name_prefix', 'android_sysui_cuj',
-  'process_allowlist_table', 'android_sysui_cuj_last_cuj');
-
-DROP VIEW IF EXISTS android_sysui_cuj_thread;
-CREATE VIEW android_sysui_cuj_thread AS
-SELECT
-  process.name as process_name,
-  thread.utid,
-  thread.name
-FROM thread
-JOIN android_sysui_cuj_last_cuj process USING (upid);
-
-DROP VIEW IF EXISTS android_sysui_cuj_slices_in_cuj;
-CREATE VIEW android_sysui_cuj_slices_in_cuj AS
-SELECT
-  process_name,
-  thread.utid,
-  thread.name as thread_name,
-  slice.*,
-  ts + slice.dur AS ts_end
-FROM slice
-JOIN thread_track ON slice.track_id = thread_track.id
-JOIN android_sysui_cuj_thread thread USING (utid)
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end
-WHERE slice.dur > 0;
-
-DROP TABLE IF EXISTS android_sysui_cuj_main_thread_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_main_thread_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_main_thread_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_do_frame_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_do_frame_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_do_frame_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_render_thread_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_render_thread_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_render_thread_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_draw_frame_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_draw_frame_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_draw_frame_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_hwc_release_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_hwc_release_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_hwc_release_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_gpu_completion_slices_in_cuj;
-CREATE TABLE android_sysui_cuj_gpu_completion_slices_in_cuj AS
-SELECT slices.* FROM android_sysui_cuj_gpu_completion_slices slices
-JOIN android_sysui_cuj_last_cuj last_cuj
-ON ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end;
-
-DROP TABLE IF EXISTS android_sysui_cuj_jit_slices;
-CREATE TABLE android_sysui_cuj_jit_slices AS
-SELECT *
-FROM android_sysui_cuj_slices_in_cuj
-WHERE thread_name LIKE 'Jit thread pool%'
-AND name LIKE 'JIT compiling%'
-AND parent_id IS NULL;
-
-DROP TABLE IF EXISTS android_sysui_cuj_frame_timeline_events;
-CREATE TABLE android_sysui_cuj_frame_timeline_events AS
-  SELECT
-    expected.ts as ts_expected,
-    expected.dur as dur_expected,
-    expected.layer_name as layer_name,
-    actual.name as vsync,
-    actual.ts as ts_actual,
-    actual.dur as dur_actual,
-    actual.jank_type LIKE '%App Deadline Missed%' as app_missed,
-    actual.jank_type,
-    actual.on_time_finish
-  FROM expected_frame_timeline_slice expected
-  JOIN android_sysui_cuj_last_cuj cuj
-    ON expected.upid = cuj.upid
-    AND expected.ts + expected.dur > cuj.ts_start
-    AND expected.ts < cuj.ts_end
-  JOIN actual_frame_timeline_slice actual
-    ON expected.surface_frame_token = actual.surface_frame_token
-    AND expected.upid = actual.upid
-    AND expected.layer_name = actual.layer_name;
-
-DROP TABLE IF EXISTS android_sysui_cuj_frames;
-CREATE TABLE android_sysui_cuj_frames AS
-  WITH gcs_to_rt_match AS (
-    -- Match GPU Completion with the last RT slice before it
-    SELECT
-      gcs.ts as gcs_ts,
-      gcs.ts_end as gcs_ts_end,
-      gcs.dur as gcs_dur,
-      gcs.idx as idx,
-      MAX(rts.ts) as rts_ts
-    FROM android_sysui_cuj_gpu_completion_slices_in_cuj gcs
-    JOIN android_sysui_cuj_render_thread_slices_in_cuj rts ON rts.ts < gcs.ts
-    -- dispatchFrameCallbacks might be seen in case of
-    -- drawing that happens on RT only (e.g. ripple effect)
-    WHERE (rts.name LIKE 'DrawFrame%' OR rts.name = 'dispatchFrameCallbacks')
-    GROUP BY gcs.ts, gcs.ts_end, gcs.dur, gcs.idx
-  ),
-  frame_boundaries AS (
-    -- Match main thread doFrame with RT DrawFrame and optional GPU Completion
-    SELECT
-      mts.ts as mts_ts,
-      mts.ts_end as mts_ts_end,
-      mts.dur as mts_dur,
-      mts.vsync as vsync,
-      MAX(gcs_rt.gcs_ts) as gcs_ts_start,
-      MAX(gcs_rt.gcs_ts_end) as gcs_ts_end
-    FROM android_sysui_cuj_do_frame_slices_in_cuj mts
-    JOIN android_sysui_cuj_draw_frame_slices_in_cuj rts
-      ON mts.vsync = rts.vsync
-    LEFT JOIN gcs_to_rt_match gcs_rt ON gcs_rt.rts_ts = rts.ts
-    GROUP BY mts.ts, mts.ts_end, mts.dur
-  )
-  SELECT
-    ROW_NUMBER() OVER (ORDER BY f.mts_ts) AS frame_number,
-    f.vsync as vsync,
-    f.mts_ts as ts_main_thread_start,
-    f.mts_ts_end as ts_main_thread_end,
-    f.mts_dur AS dur_main_thread,
-    MIN(rts.ts) AS ts_render_thread_start,
-    MAX(rts.ts_end) AS ts_render_thread_end,
-    SUM(rts.dur) AS dur_render_thread,
-    MAX(gcs_rt.gcs_ts_end) AS ts_frame_end,
-    MAX(gcs_rt.gcs_ts_end) - f.mts_ts AS dur_frame,
-    SUM(gcs_rt.gcs_ts_end - MAX(COALESCE(hwc.ts_end, 0), gcs_rt.gcs_ts)) as dur_gcs,
-    COUNT(DISTINCT(rts.ts)) as draw_frames,
-    COUNT(DISTINCT(gcs_rt.gcs_ts)) as gpu_completions
-  FROM frame_boundaries f
-  JOIN android_sysui_cuj_draw_frame_slices_in_cuj rts
-    ON f.vsync = rts.vsync
-  LEFT JOIN gcs_to_rt_match gcs_rt
-    ON rts.ts = gcs_rt.rts_ts
-  LEFT JOIN android_sysui_cuj_hwc_release_slices_in_cuj hwc USING (idx)
-  GROUP BY f.mts_ts
-  HAVING gpu_completions >= 1;
-
-DROP TABLE IF EXISTS android_sysui_cuj_missed_frames;
-CREATE TABLE android_sysui_cuj_missed_frames AS
-  SELECT
-    f.*,
-    (SELECT MAX(fte.app_missed)
-     FROM android_sysui_cuj_frame_timeline_events fte
-     WHERE f.vsync = fte.vsync
-     AND fte.on_time_finish = 0) as app_missed
-  FROM android_sysui_cuj_frames f;
-
-DROP VIEW IF EXISTS android_sysui_cuj_frame_main_thread_bounds;
-CREATE VIEW android_sysui_cuj_frame_main_thread_bounds AS
-SELECT frame_number, ts_main_thread_start as ts, dur_main_thread as dur
-FROM android_sysui_cuj_missed_frames
-WHERE app_missed;
-
-DROP VIEW IF EXISTS android_sysui_cuj_main_thread_state_data;
-CREATE VIEW android_sysui_cuj_main_thread_state_data AS
-SELECT * FROM thread_state
-WHERE utid = (SELECT utid FROM android_sysui_cuj_main_thread);
-
-DROP TABLE IF EXISTS android_sysui_cuj_main_thread_state_vt;
-CREATE VIRTUAL TABLE android_sysui_cuj_main_thread_state_vt
-USING span_left_join(android_sysui_cuj_frame_main_thread_bounds, android_sysui_cuj_main_thread_state_data PARTITIONED utid);
-
-DROP TABLE IF EXISTS android_sysui_cuj_main_thread_state;
-CREATE TABLE android_sysui_cuj_main_thread_state AS
-  SELECT
-    frame_number,
-    state,
-    io_wait AS io_wait,
-    SUM(dur) AS dur
-  FROM android_sysui_cuj_main_thread_state_vt
-  GROUP BY frame_number, state, io_wait
-  HAVING dur > 0;
-
-DROP VIEW IF EXISTS android_sysui_cuj_frame_render_thread_bounds;
-CREATE VIEW android_sysui_cuj_frame_render_thread_bounds AS
-SELECT frame_number, ts_render_thread_start as ts, dur_render_thread as dur
-FROM android_sysui_cuj_missed_frames
-WHERE app_missed;
-
-DROP VIEW IF EXISTS android_sysui_cuj_render_thread_state_data;
-CREATE VIEW android_sysui_cuj_render_thread_state_data AS
-SELECT * FROM thread_state
-WHERE utid in (SELECT utid FROM android_sysui_cuj_render_thread);
-
-DROP TABLE IF EXISTS android_sysui_cuj_render_thread_state_vt;
-CREATE VIRTUAL TABLE android_sysui_cuj_render_thread_state_vt
-USING span_left_join(android_sysui_cuj_frame_render_thread_bounds, android_sysui_cuj_render_thread_state_data PARTITIONED utid);
-
-DROP TABLE IF EXISTS android_sysui_cuj_render_thread_state;
-CREATE TABLE android_sysui_cuj_render_thread_state AS
-  SELECT
-    frame_number,
-    state,
-    io_wait AS io_wait,
-    SUM(dur) AS dur
-  FROM android_sysui_cuj_render_thread_state_vt
-  GROUP BY frame_number, state, io_wait
-  HAVING dur > 0;
-
-DROP TABLE IF EXISTS android_sysui_cuj_main_thread_binder;
-CREATE TABLE android_sysui_cuj_main_thread_binder AS
-  SELECT
-    f.frame_number,
-    SUM(mts.dur) AS dur,
-    COUNT(*) AS call_count
-  FROM android_sysui_cuj_missed_frames f
-  JOIN android_sysui_cuj_main_thread_slices_in_cuj mts
-    ON mts.ts >= f.ts_main_thread_start AND mts.ts < f.ts_main_thread_end
-  WHERE mts.name = 'binder transaction'
-  AND f.app_missed
-  GROUP BY f.frame_number;
-
-DROP TABLE IF EXISTS android_sysui_cuj_sf_jank_causes;
-CREATE TABLE android_sysui_cuj_sf_jank_causes AS
-  WITH RECURSIVE split_jank_type(frame_number, jank_cause, remainder) AS (
-    SELECT f.frame_number, "", fte.jank_type || ","
-    FROM android_sysui_cuj_frames f
-    JOIN android_sysui_cuj_frame_timeline_events fte ON f.vsync = fte.vsync
-    UNION ALL SELECT
-    frame_number,
-    STR_SPLIT(remainder, ",", 0) AS jank_cause,
-    TRIM(SUBSTR(remainder, INSTR(remainder, ",") + 1)) AS remainder
-    FROM split_jank_type
-    WHERE remainder <> "")
-  SELECT frame_number, jank_cause
-  FROM split_jank_type
-  WHERE jank_cause NOT IN ('', 'App Deadline Missed', 'None', 'Buffer Stuffing')
-  ORDER BY frame_number ASC;
-
-DROP TABLE IF EXISTS android_sysui_cuj_missed_frames_hwui_times;
-CREATE TABLE android_sysui_cuj_missed_frames_hwui_times AS
-SELECT
-  *,
-  ts_main_thread_start AS ts,
-  ts_render_thread_end - ts_main_thread_start AS dur
-FROM android_sysui_cuj_missed_frames;
-
-DROP TABLE IF EXISTS android_sysui_cuj_jit_slices_join_table;
-CREATE VIRTUAL TABLE android_sysui_cuj_jit_slices_join_table
-USING span_join(android_sysui_cuj_missed_frames_hwui_times partitioned frame_number, android_sysui_cuj_jit_slices);
-
-DROP TABLE IF EXISTS android_sysui_cuj_jank_causes;
-CREATE TABLE android_sysui_cuj_jank_causes AS
-  SELECT
-  frame_number,
-  'RenderThread - long shader_compile' AS jank_cause
-  FROM android_sysui_cuj_missed_frames f
-  JOIN android_sysui_cuj_render_thread_slices_in_cuj rts
-    ON rts.ts >= f.ts_render_thread_start AND rts.ts < f.ts_render_thread_end
-  WHERE rts.name = 'shader_compile'
-  AND f.app_missed
-  AND rts.dur > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'RenderThread - long flush layers' AS jank_cause
-  FROM android_sysui_cuj_missed_frames f
-  JOIN android_sysui_cuj_render_thread_slices_in_cuj rts
-    ON rts.ts >= f.ts_render_thread_start AND rts.ts < f.ts_render_thread_end
-  WHERE rts.name = 'flush layers'
-  AND rts.dur > 8000000
-  AND f.app_missed
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'MainThread - IO wait time' AS jank_cause
-  FROM android_sysui_cuj_main_thread_state
-  WHERE
-    ((state = 'D' OR state = 'DK') AND io_wait)
-    OR (state = 'DK' AND io_wait IS NULL)
-  GROUP BY frame_number
-  HAVING SUM(dur) > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'MainThread - scheduler' AS jank_cause
-  FROM android_sysui_cuj_main_thread_state
-  WHERE (state = 'R' OR state = 'R+')
-  GROUP BY frame_number
-  HAVING SUM(dur) > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'RenderThread - IO wait time' AS jank_cause
-  FROM android_sysui_cuj_render_thread_state
-  WHERE
-    ((state = 'D' OR state = 'DK') AND io_wait)
-    OR (state = 'DK' AND io_wait IS NULL)
-  GROUP BY frame_number
-  HAVING SUM(dur) > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'RenderThread - scheduler' AS jank_cause
-  FROM android_sysui_cuj_render_thread_state
-  WHERE (state = 'R' OR state = 'R+')
-  GROUP BY frame_number
-  HAVING SUM(dur) > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'MainThread - binder transaction time' AS jank_cause
-  FROM android_sysui_cuj_main_thread_binder
-  WHERE dur > 8000000
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'MainThread - binder calls count' AS jank_cause
-  FROM android_sysui_cuj_main_thread_binder
-  WHERE call_count > 8
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'GPU completion - long completion time' AS jank_cause
-  FROM android_sysui_cuj_missed_frames f
-  WHERE dur_gcs > 8000000
-  AND app_missed
-
-  UNION ALL
-  SELECT
-  frame_number,
-  'Long running time' as jank_cause
-  FROM android_sysui_cuj_main_thread_state mts
-  JOIN android_sysui_cuj_render_thread_state rts USING(frame_number)
-  WHERE
-    mts.state = 'Running'
-    AND rts.state = 'Running'
-    AND mts.dur + rts.dur > 15000000
-
-  UNION ALL
-  SELECT
-  f.frame_number,
-  'JIT compiling' as jank_cause
-  FROM android_sysui_cuj_missed_frames f
-  JOIN android_sysui_cuj_jit_slices_join_table jit USING (frame_number)
-  WHERE f.app_missed
-  GROUP BY f.frame_number
-  HAVING SUM(jit.dur) > 8000000
-
-  UNION ALL
-  SELECT frame_number, jank_cause FROM android_sysui_cuj_sf_jank_causes
-  GROUP BY frame_number, jank_cause;
-
--- TODO(b/175098682): Switch to use async slices
-DROP VIEW IF EXISTS android_sysui_cuj_event;
-CREATE VIEW android_sysui_cuj_event AS
- SELECT
-    'slice' as track_type,
-    (SELECT cuj_name FROM android_sysui_cuj_last_cuj)
-        || ' - jank cause' as track_name,
-    f.ts_main_thread_start as ts,
-    f.dur_main_thread as dur,
-    group_concat(jc.jank_cause) as slice_name
-FROM android_sysui_cuj_frames f
-JOIN android_sysui_cuj_jank_causes jc USING (frame_number)
-GROUP BY track_type, track_name, ts, dur;
-
-DROP VIEW IF EXISTS android_sysui_cuj_output;
-CREATE VIEW android_sysui_cuj_output AS
-SELECT
-  AndroidSysUiCujMetrics(
-      'cuj_name', cuj_name,
-      'cuj_start', ts_start,
-      'cuj_dur', dur,
-      'process', process_metadata,
-      'frames',
-       (SELECT RepeatedField(
-         AndroidSysUiCujMetrics_Frame(
-           'number', f.frame_number,
-           'vsync', f.vsync,
-           'ts', f.ts_main_thread_start,
-           'dur', f.dur_frame,
-           'jank_cause',
-              (SELECT RepeatedField(jc.jank_cause)
-              FROM android_sysui_cuj_jank_causes jc WHERE jc.frame_number = f.frame_number)))
-       FROM android_sysui_cuj_frames f
-       ORDER BY frame_number ASC))
-  FROM android_sysui_cuj_last_cuj;
diff --git a/src/trace_processor/metrics/android/android_task_names.sql b/src/trace_processor/metrics/android/android_task_names.sql
index b86186b..be88267 100644
--- a/src/trace_processor/metrics/android/android_task_names.sql
+++ b/src/trace_processor/metrics/android/android_task_names.sql
@@ -16,8 +16,7 @@
 
 SELECT RUN_METRIC('android/process_metadata.sql');
 
-DROP VIEW IF EXISTS android_task_names_output;
-CREATE VIEW android_task_names_output AS
+CREATE VIEW IF NOT EXISTS android_task_names_output AS
 WITH
 -- Process to thread name
 threads_by_upid AS (
diff --git a/src/trace_processor/metrics/android/android_task_state.sql b/src/trace_processor/metrics/android/android_task_state.sql
new file mode 100644
index 0000000..e296390
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_task_state.sql
@@ -0,0 +1,37 @@
+--
+-- 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/android_thread_time_in_state.sql b/src/trace_processor/metrics/android/android_thread_time_in_state.sql
index ace04ed..8fb76a6 100644
--- a/src/trace_processor/metrics/android/android_thread_time_in_state.sql
+++ b/src/trace_processor/metrics/android/android_thread_time_in_state.sql
@@ -17,65 +17,62 @@
 SELECT RUN_METRIC('android/cpu_info.sql');
 SELECT RUN_METRIC('android/process_metadata.sql');
 
-DROP TABLE IF EXISTS android_thread_time_in_state_base;
-CREATE TABLE android_thread_time_in_state_base AS
+CREATE VIEW android_thread_time_in_state_base AS
 SELECT
-  base.*,
-  IFNULL(core_type_per_cpu.core_type, 'unknown') core_type
+  *,
+  (
+    SELECT
+      CASE
+        WHEN layout = 'big_little_bigger' AND cpu < 4 THEN 'little'
+        WHEN layout = 'big_little_bigger' AND cpu < 7 THEN 'big'
+        WHEN layout = 'big_little_bigger' AND cpu = 7 THEN 'bigger'
+        WHEN layout = 'big_little' AND cpu < 4 THEN 'little'
+        WHEN layout = 'big_little' AND cpu < 8 THEN 'big'
+        ELSE 'unknown'
+      END
+    FROM core_layout_type
+  ) AS core_type
 FROM (
   SELECT
-    ts,
+    slice.ts AS ts,
     utid,
-    EXTRACT_ARG(counter.arg_set_id, 'time_in_state_cpu_id') AS
-        time_in_state_cpu,
-    EXTRACT_ARG(counter.arg_set_id, 'freq') AS freq,
-    CAST(value AS INT) AS runtime_ms_counter
-  FROM counter
-  JOIN thread_counter_track ON (counter.track_id = thread_counter_track.id)
-  WHERE thread_counter_track.name = 'time_in_state'
-) base
-LEFT JOIN core_type_per_cpu ON (cpu = time_in_state_cpu);
+    CAST(SUBSTR(slice.name, 18) AS int) AS cpu,
+    CAST(args.key AS int) AS freq,
+    args.int_value as runtime_ms_counter
+  FROM slice
+    JOIN thread_track ON slice.track_id = thread_track.id
+    JOIN args USING (arg_set_id)
+  WHERE slice.name LIKE 'time_in_state.%'
+);
 
-DROP VIEW IF EXISTS android_thread_time_in_state_raw;
 CREATE VIEW android_thread_time_in_state_raw AS
 SELECT
   utid,
-  time_in_state_cpu,
   core_type,
   freq,
   MAX(runtime_ms_counter) - MIN(runtime_ms_counter) runtime_ms_diff
 FROM android_thread_time_in_state_base
-GROUP BY utid, time_in_state_cpu, core_type, freq;
+GROUP BY utid, core_type, freq;
 
-DROP TABLE IF EXISTS android_thread_time_in_state_counters;
 CREATE TABLE android_thread_time_in_state_counters AS
 SELECT
   utid,
-  raw.time_in_state_cpu,
-  raw.core_type,
-  SUM(runtime_ms_diff) AS runtime_ms,
-  SUM(raw.freq * runtime_ms_diff / 1000000) AS mcycles,
-  SUM(power * runtime_ms_diff / 3600000) AS power_profile_mah
-FROM android_thread_time_in_state_raw AS raw
-    LEFT OUTER JOIN cpu_cluster_power AS power USING(core_type, freq)
-GROUP BY utid, raw.time_in_state_cpu, raw.core_type
+  core_type,
+  SUM(runtime_ms_diff) AS runtime_ms
+FROM android_thread_time_in_state_raw
+GROUP BY utid, core_type
 HAVING runtime_ms > 0;
 
-DROP VIEW IF EXISTS android_thread_time_in_state_thread_metrics;
 CREATE VIEW android_thread_time_in_state_thread_metrics AS
 SELECT
   utid,
   RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType(
-    'time_in_state_cpu',  time_in_state_cpu,
     'core_type', core_type,
-    'runtime_ms', runtime_ms,
-    'mcycles', CAST(mcycles AS INT),
-    'power_profile_mah', power_profile_mah
+    'runtime_ms', runtime_ms
   )) metrics
 FROM android_thread_time_in_state_counters
 GROUP BY utid;
 
-DROP VIEW IF EXISTS android_thread_time_in_state_threads;
 CREATE VIEW android_thread_time_in_state_threads AS
 SELECT
   upid,
@@ -91,33 +88,25 @@
 JOIN android_thread_time_in_state_thread_metrics USING (utid)
 GROUP BY upid;
 
-DROP VIEW IF EXISTS android_thread_time_in_state_process_metrics;
 CREATE VIEW android_thread_time_in_state_process_metrics AS
 WITH process_counters AS (
   SELECT
     upid,
-    time_in_state_cpu,
     core_type,
-    SUM(runtime_ms) AS runtime_ms,
-    SUM(mcycles) AS mcycles,
-    SUM(power_profile_mah) AS power_profile_mah
+    SUM(runtime_ms) runtime_ms
   FROM android_thread_time_in_state_counters
   JOIN thread USING (utid)
-  GROUP BY upid, time_in_state_cpu, core_type
+  GROUP BY upid, core_type
 )
 SELECT
   upid,
   RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType(
-    'time_in_state_cpu', time_in_state_cpu,
     'core_type', core_type,
-    'runtime_ms', runtime_ms,
-    'mcycles', CAST(mcycles AS INT),
-    'power_profile_mah', power_profile_mah
- )) metrics
+    'runtime_ms', runtime_ms
+  )) metrics
 FROM process_counters
 GROUP BY upid;
 
-DROP VIEW IF EXISTS android_thread_time_in_state_output;
 CREATE VIEW android_thread_time_in_state_output AS
 SELECT AndroidThreadTimeInStateMetric(
   'processes', (
@@ -136,9 +125,8 @@
 );
 
 -- Ensure we always get the previous clock tick for duration in
--- android_thread_time_in_state_event_raw.
-DROP VIEW IF EXISTS android_thread_time_in_state_event_clock;
-CREATE VIEW android_thread_time_in_state_event_clock AS
+-- android_thread_time_in_state_annotations_raw.
+CREATE VIEW android_thread_time_in_state_annotations_clock AS
 SELECT
   ts,
   LAG(ts) OVER (ORDER BY ts) AS lag_ts
@@ -146,8 +134,7 @@
   SELECT DISTINCT ts from android_thread_time_in_state_base
 );
 
-DROP VIEW IF EXISTS android_thread_time_in_state_event_raw;
-CREATE VIEW android_thread_time_in_state_event_raw AS
+CREATE VIEW android_thread_time_in_state_annotations_raw AS
 SELECT
   ts,
   ts - lag_ts AS dur,
@@ -163,13 +150,10 @@
   runtime_ms_counter - LAG(runtime_ms_counter)
       OVER (PARTITION BY core_type, utid, freq ORDER BY ts) AS runtime_ms
 FROM android_thread_time_in_state_base
-    -- Join to keep only utids which have non-zero runtime in the trace.
-    JOIN android_thread_time_in_state_counters USING (utid, core_type)
-    JOIN android_thread_time_in_state_event_clock USING(ts)
+    JOIN android_thread_time_in_state_annotations_clock USING(ts)
     JOIN thread using (utid);
 
-DROP VIEW IF EXISTS android_thread_time_in_state_event_thread;
-CREATE VIEW android_thread_time_in_state_event_thread AS
+CREATE VIEW android_thread_time_in_state_annotations_thread AS
 SELECT
   'counter' AS track_type,
   thread_track_name || ' (' || core_type || ' core)' as track_name,
@@ -177,13 +161,12 @@
   dur,
   upid,
   sum(runtime_ms * freq) as ms_freq
-FROM android_thread_time_in_state_event_raw
+FROM android_thread_time_in_state_annotations_raw
 WHERE runtime_ms IS NOT NULL
   AND dur != 0
 GROUP BY track_type, track_name, ts, dur, upid;
 
-DROP VIEW IF EXISTS android_thread_time_in_state_event_global;
-CREATE VIEW android_thread_time_in_state_event_global AS
+CREATE VIEW android_thread_time_in_state_annotations_global AS
 SELECT
   'counter' AS track_type,
   'Total ' || core_type || ' core cycles / sec' as track_name,
@@ -191,16 +174,15 @@
   dur,
   0 AS upid,
   SUM(runtime_ms * freq) AS ms_freq
-FROM android_thread_time_in_state_event_raw
+FROM android_thread_time_in_state_annotations_raw
 WHERE runtime_ms IS NOT NULL
 GROUP BY ts, track_name;
 
-DROP TABLE IF EXISTS android_thread_time_in_state_event;
-CREATE TABLE android_thread_time_in_state_event AS
+CREATE VIEW android_thread_time_in_state_annotations AS
 SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
-FROM android_thread_time_in_state_event_thread
-UNION ALL
+FROM android_thread_time_in_state_annotations_thread
+UNION
 SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
-FROM android_thread_time_in_state_event_global
+FROM android_thread_time_in_state_annotations_global
 -- Biggest values at top of list in UI.
 ORDER BY value DESC;
diff --git a/src/trace_processor/metrics/android/composer_execution.sql b/src/trace_processor/metrics/android/composer_execution.sql
deleted file mode 100644
index bec4fdc..0000000
--- a/src/trace_processor/metrics/android/composer_execution.sql
+++ /dev/null
@@ -1,67 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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.
-
-
--- The HWC execution time will be calculated based on the runtime of
--- HwcPresentOrValidateDisplay, HwcValidateDisplay, and/or HwcPresentDisplay
--- which are happened in the same onMessageRefresh.
--- There are 3 possible combinations how those functions will be called in
--- a single onMessageRefresh, i.e.:
--- 1. HwcPresentOrValidateDisplay and then HwcPresentDisplay
--- 2. HwcPresentOrValidateDisplay
--- 3. HwcValidateDisplay and then HwcPresentDisplay
-DROP VIEW IF EXISTS raw_hwc_function_spans;
-CREATE VIEW raw_hwc_function_spans AS
-SELECT
-  id,
-  name,
-  ts AS begin_ts,
-  ts+dur AS end_ts,
-  dur,
-  LEAD(name, 1, '') OVER (PARTITION BY track_id ORDER BY ts) AS next_name,
-  LEAD(ts, 1, 0) OVER (PARTITION BY track_id ORDER BY ts) AS next_ts,
-  LEAD(dur, 1, 0) OVER (PARTITION BY track_id ORDER BY ts) AS next_dur,
-  LEAD(name, 2, '') OVER (PARTITION BY track_id ORDER BY ts) AS second_next_name,
-  LEAD(ts, 2, 0) OVER (PARTITION BY track_id ORDER BY ts) AS second_next_ts,
-  LEAD(dur, 2, 0) OVER (PARTITION BY track_id ORDER BY ts) AS second_next_dur
-FROM slice
-WHERE name = 'HwcPresentOrValidateDisplay' OR name = 'HwcValidateDisplay'
-  OR name = 'HwcPresentDisplay' OR name = 'onMessageRefresh'
-ORDER BY ts;
-
-DROP VIEW IF EXISTS {{output}};
-CREATE VIEW {{output}} AS
-SELECT
-  id,
-  CASE
-    WHEN begin_ts <= next_ts AND next_ts <= end_ts THEN
-      CASE
-        WHEN begin_ts <= second_next_ts AND second_next_ts <= end_ts
-          THEN next_dur + second_next_dur
-        ELSE next_dur
-      END
-    ELSE 0
-  END AS execution_time_ns,
-  CASE
-    WHEN next_name = 'HwcPresentOrValidateDisplay'
-      AND second_next_name = 'HwcPresentDisplay' THEN 'unskipped_validation'
-    WHEN next_name = 'HwcPresentOrValidateDisplay'
-      AND second_next_name != 'HwcPresentDisplay' THEN 'skipped_validation'
-    WHEN next_name = 'HwcValidateDisplay'
-      AND second_next_name = 'HwcPresentDisplay' THEN 'separated_validation'
-    ELSE 'unknown'
-  END AS validation_type
-FROM raw_hwc_function_spans
-WHERE name = 'onMessageRefresh' AND dur > 0;
diff --git a/src/trace_processor/metrics/android/composition_layers.sql b/src/trace_processor/metrics/android/composition_layers.sql
deleted file mode 100644
index 0790296..0000000
--- a/src/trace_processor/metrics/android/composition_layers.sql
+++ /dev/null
@@ -1,30 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 {{output}};
-CREATE VIEW {{output}} AS
-WITH composition_layer_counts AS (
-  SELECT
-    LAG(ts) OVER (ORDER BY ts) AS ts,
-    value
-  FROM counter c
-  JOIN process_counter_track t ON c.track_id = t.id
-  WHERE t.name = '{{track_name}}'
-)
-SELECT
-  ts,
-  value
-FROM composition_layer_counts
-WHERE value >= 0 AND ts IS NOT NULL;
diff --git a/src/trace_processor/metrics/android/counter_span_view.sql b/src/trace_processor/metrics/android/counter_span_view.sql
new file mode 100644
index 0000000..cdd953a
--- /dev/null
+++ b/src/trace_processor/metrics/android/counter_span_view.sql
@@ -0,0 +1,25 @@
+--
+-- Copyright 2020 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     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 IF NOT EXISTS {{table_name}}_span AS
+SELECT
+  ts,
+  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
+      OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
+  value AS {{table_name}}_val
+FROM counter c JOIN counter_track t
+  ON t.id = c.track_id
+WHERE name = '{{counter_name}}';
diff --git a/src/trace_processor/metrics/android/cpu_info.sql b/src/trace_processor/metrics/android/cpu_info.sql
index 1e04a3e..00c887c 100644
--- a/src/trace_processor/metrics/android/cpu_info.sql
+++ b/src/trace_processor/metrics/android/cpu_info.sql
@@ -14,37 +14,31 @@
 -- limitations under the License.
 --
 
-SELECT RUN_METRIC('android/power_profile_data.sql');
-
-DROP TABLE IF EXISTS cluster_core_type;
-CREATE TABLE cluster_core_type AS
-    SELECT 0 as cluster, 'little' as core_type
-    UNION ALL
-    SELECT 1, 'big'
-    UNION ALL
-    SELECT 2, 'bigger';
-
-DROP VIEW IF EXISTS device_power_profile;
-CREATE VIEW device_power_profile AS
-SELECT cpu, cluster, freq, power
-FROM power_profile pp
-WHERE EXISTS (
-  SELECT 1 FROM metadata
-  WHERE name = 'android_build_fingerprint' AND str_value LIKE '%' || pp.device || '%');
-
-DROP VIEW IF EXISTS core_cluster_per_cpu;
-CREATE VIEW core_cluster_per_cpu AS
-SELECT DISTINCT cpu, cluster
-FROM device_power_profile;
-
-DROP VIEW IF EXISTS core_type_per_cpu;
-CREATE VIEW core_type_per_cpu AS
+CREATE VIEW IF NOT EXISTS core_layout_mapping AS
 SELECT
-  cpu,
-  core_type
-FROM core_cluster_per_cpu JOIN cluster_core_type USING(cluster);
+  CASE
+    WHEN (
+      str_value LIKE '%flame%' OR
+      str_value LIKE '%coral%'
+    ) THEN 'big_little_bigger'
+    WHEN (
+      str_value LIKE '%taimen%' OR
+      str_value LIKE '%walleye%' OR
+      str_value LIKE '%bonito%' OR
+      str_value LIKE '%sargo%' OR
+      str_value LIKE '%blueline%' OR
+      str_value LIKE '%crosshatch%'
+    ) THEN 'big_little'
+    ELSE 'unknown'
+  END AS layout
+FROM metadata
+WHERE name = 'android_build_fingerprint';
 
-DROP VIEW IF EXISTS cpu_cluster_power;
-CREATE VIEW cpu_cluster_power AS
-SELECT DISTINCT core_type, freq, power
-FROM device_power_profile pp JOIN cluster_core_type USING(cluster);
+CREATE TABLE IF NOT EXISTS core_layout_type AS
+SELECT *
+FROM (
+  SELECT layout from core_layout_mapping
+  UNION
+  SELECT 'unknown'
+)
+LIMIT 1;
diff --git a/src/trace_processor/metrics/android/display_metrics.sql b/src/trace_processor/metrics/android/display_metrics.sql
index daec213..321ef4d 100644
--- a/src/trace_processor/metrics/android/display_metrics.sql
+++ b/src/trace_processor/metrics/android/display_metrics.sql
@@ -13,76 +13,21 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
-DROP VIEW IF EXISTS same_frame;
 CREATE VIEW same_frame AS
 SELECT COUNT(name) AS total_duplicate_frames
 FROM counters
 WHERE name='SAME_FRAME'
 AND value=1;
 
-DROP VIEW IF EXISTS duplicate_frames_logged;
 CREATE VIEW duplicate_frames_logged AS
 SELECT CASE WHEN COUNT(name) > 0 THEN 1 ELSE 0 END AS logs_found
 FROM counters
 WHERE name='SAME_FRAME' AND value=0;
 
-DROP VIEW IF EXISTS dpu_underrun;
-CREATE VIEW dpu_underrun AS
-SELECT COUNT(name) AS total_dpu_underrun_count
-FROM counters
-WHERE name='DPU_UNDERRUN'
-AND value=1;
-
-DROP VIEW IF EXISTS non_repeated_panel_fps;
-CREATE VIEW non_repeated_panel_fps AS
-SELECT *
-FROM (
-  SELECT
-    ts,
-    value,
-    track_id,
-    LAG(value, 1, 0) OVER (PARTITION BY track_id ORDER BY ts) AS prev_value
-  FROM counter c JOIN track t ON c.track_id = t.id
-  WHERE t.name = 'panel_fps'
-  ORDER BY ts
-)
-WHERE prev_value != value;
-
-DROP VIEW IF EXISTS panel_fps_spans;
-CREATE VIEW panel_fps_spans AS
-SELECT *
-FROM (
-  SELECT
-    ts,
-    value,
-    LEAD(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts AS dur
-  FROM non_repeated_panel_fps
-  ORDER BY ts
-)
-WHERE dur > 0;
-
-DROP VIEW IF EXISTS display_metrics_output;
 CREATE VIEW display_metrics_output AS
 SELECT AndroidDisplayMetrics(
-  'total_duplicate_frames', (SELECT total_duplicate_frames
+    'total_duplicate_frames', (SELECT total_duplicate_frames
                             FROM same_frame),
-  'duplicate_frames_logged', (SELECT logs_found
-                            FROM duplicate_frames_logged),
-  'total_dpu_underrun_count', (SELECT total_dpu_underrun_count
-                              FROM dpu_underrun),
-  'refresh_rate_switches', (SELECT COUNT(*) FROM panel_fps_spans),
-  'refresh_rate_stats', (
-    SELECT RepeatedField(metric)
-    FROM (
-      SELECT AndroidDisplayMetrics_RefreshRateStat(
-        'refresh_rate_fps', CAST(value AS UINT32),
-        'count', COUNT(*),
-        'total_dur_ms', SUM(dur) / 1e6,
-        'avg_dur_ms', AVG(dur) / 1e6
-      ) AS metric
-      FROM panel_fps_spans
-      GROUP BY value
-      ORDER BY value
-    )
-  )
-);
+    'duplicate_frames_logged', (SELECT logs_found
+                            FROM duplicate_frames_logged)
+);
\ No newline at end of file
diff --git a/src/trace_processor/metrics/android/frame_missed.sql b/src/trace_processor/metrics/android/frame_missed.sql
deleted file mode 100644
index 45499fa..0000000
--- a/src/trace_processor/metrics/android/frame_missed.sql
+++ /dev/null
@@ -1,34 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 {{output}};
-CREATE VIEW {{output}} AS
-WITH frame_missed_counters AS (
-  SELECT
-    LAG(ts) OVER (ORDER BY ts) AS ts,
-    -- We intentionally don't partition by track id here as only one
-    -- track should ever exist with this name (the track from
-    -- surfaceflinger).
-    ts - LAG(ts) OVER (ORDER BY ts) AS dur,
-    value
-  FROM counter c
-  JOIN process_counter_track t ON c.track_id = t.id
-  WHERE t.name = '{{track_name}}'
-)
-SELECT
-  ts,
-  dur,
-  value
-FROM frame_missed_counters;
\ No newline at end of file
diff --git a/src/trace_processor/metrics/android/g2d.sql b/src/trace_processor/metrics/android/g2d.sql
deleted file mode 100644
index 5e474b7..0000000
--- a/src/trace_processor/metrics/android/g2d.sql
+++ /dev/null
@@ -1,34 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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/g2d_duration.sql',
-  'g2d_type', 'sw',
-  'output_table', 'g2d_sw_duration_metric'
-);
-
-SELECT RUN_METRIC(
-  'android/g2d_duration.sql',
-  'g2d_type', 'hw',
-  'output_table', 'g2d_hw_duration_metric'
-);
-
-DROP VIEW IF EXISTS g2d_output;
-CREATE VIEW g2d_output AS
-SELECT G2dMetrics(
-  'g2d_hw', (SELECT metric FROM g2d_hw_duration_metric),
-  'g2d_sw', (SELECT metric FROM g2d_sw_duration_metric)
-);
diff --git a/src/trace_processor/metrics/android/g2d_duration.sql b/src/trace_processor/metrics/android/g2d_duration.sql
deleted file mode 100644
index 7d96d06..0000000
--- a/src/trace_processor/metrics/android/g2d_duration.sql
+++ /dev/null
@@ -1,68 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 raw_g2d_{{g2d_type}}_spans;
-CREATE VIEW raw_g2d_{{g2d_type}}_spans AS
-SELECT
-  ts,
-  t.name AS track_name,
-  LEAD(ts, 1, 0) OVER (PARTITION BY name ORDER BY ts) - ts AS dur,
-  LAG(value, 1, -1) OVER (PARTITION BY name ORDER BY ts) AS prev_g2d_value,
-  value AS g2d_value,
-  LEAD(value, 1, -1) OVER (PARTITION BY name ORDER BY ts) AS next_g2d_value
-FROM counter c JOIN thread_counter_track t ON t.id = c.track_id
-WHERE t.name LIKE 'g2d_frame_{{g2d_type}}%';
-
-
-DROP VIEW IF EXISTS g2d_{{g2d_type}}_spans;
-CREATE VIEW g2d_{{g2d_type}}_spans AS
-SELECT ts, track_name, dur
-FROM raw_g2d_{{g2d_type}}_spans
-WHERE g2d_value = 1 AND next_g2d_value = 0;
-
-
-DROP VIEW IF EXISTS g2d_{{g2d_type}}_errors;
-CREATE VIEW g2d_{{g2d_type}}_errors AS
-SELECT ts, track_name, g2d_value
-FROM raw_g2d_{{g2d_type}}_spans
-WHERE (g2d_value = 1 AND next_g2d_value = 1) OR (prev_g2d_value = 0 AND g2d_value = 0);
-
-
-DROP VIEW IF EXISTS g2d_{{g2d_type}}_instances;
-CREATE VIEW g2d_{{g2d_type}}_instances AS
-SELECT
-  G2dMetrics_G2dInstance(
-    'name', g.track_name,
-    'max_dur_ns', CAST(MAX(g.dur) AS INT64),
-    'min_dur_ns', CAST(MIN(g.dur) AS INT64),
-    'avg_dur_ns', CAST(AVG(g.dur) AS INT64),
-    'frame_count', COUNT(*),
-    'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors e WHERE e.track_name = g.track_name)
-  ) AS instance
-FROM g2d_{{g2d_type}}_spans g GROUP BY g.track_name;
-
-
-DROP VIEW IF EXISTS {{output_table}};
-CREATE VIEW {{output_table}} AS
-SELECT
-  G2dMetrics_G2dMetric(
-    'instances', (SELECT RepeatedField(instance) FROM g2d_{{g2d_type}}_instances),
-    'max_dur_ns', CAST(MAX(dur) AS INT64),
-    'min_dur_ns', CAST(MIN(dur) AS INT64),
-    'avg_dur_ns', CAST(AVG(dur) AS INT64),
-    'frame_count', COUNT(*),
-    'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors)
-  ) AS metric
-FROM g2d_{{g2d_type}}_spans;
diff --git a/src/trace_processor/metrics/android/global_counter_span_view.sql b/src/trace_processor/metrics/android/global_counter_span_view.sql
deleted file mode 100644
index 0b531a6..0000000
--- a/src/trace_processor/metrics/android/global_counter_span_view.sql
+++ /dev/null
@@ -1,27 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 end_ts + 1 FROM trace_bounds))
-      OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur,
-  value AS {{table_name}}_val
-FROM counter c JOIN counter_track t
-  ON t.id = c.track_id
-WHERE t.type = 'counter_track'
-  AND name = '{{counter_name}}';
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
new file mode 100644
index 0000000..f84a8ca
--- /dev/null
+++ b/src/trace_processor/metrics/android/heap_profile_callsites.sql
@@ -0,0 +1,236 @@
+--
+-- 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_metadata.sql');
+
+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,
+    'process', process_metadata.metadata,
+    '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)
+JOIN process_metadata 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/hsc_startups.sql b/src/trace_processor/metrics/android/hsc_startups.sql
index 5c0a618..15e62b8 100644
--- a/src/trace_processor/metrics/android/hsc_startups.sql
+++ b/src/trace_processor/metrics/android/hsc_startups.sql
@@ -15,45 +15,29 @@
 --
 
 -- Must be invoked after populating launches table in android_startup.
-DROP VIEW IF EXISTS functions;
+CREATE VIEW frame_times AS
+SELECT
+    slices.ts AS ts,
+    slices.ts + slices.dur AS ts_end,
+    launches.package AS name,
+    launches.id AS launch_id,
+    ROW_NUMBER() OVER(PARTITION BY launches.id ORDER BY slices.ts ASC) as frame_number
+FROM slices
+INNER JOIN thread_track on slices.track_id = thread_track.id
+INNER JOIN thread USING(utid)
+INNER JOIN launches on launches.package LIKE '%' || thread.name || '%'
+WHERE slices.name="Choreographer#doFrame" and slices.ts > launches.ts;
+
 CREATE VIEW functions AS
 SELECT
     slices.ts as ts,
     slices.dur as dur,
-    process.name as process_name,
-    thread.name as thread_name,
+    thread.name as process_name,
     slices.name as function_name
 FROM slices
-INNER JOIN thread_track on slices.track_id = thread_track.id
-INNER JOIN thread USING(utid)
-INNER JOIN process USING(upid);
-
--- Animators don't occur on threads, so add them here.
-DROP VIEW IF EXISTS animators;
-CREATE VIEW animators AS
-SELECT
-    slices.ts AS ts,
-    slices.dur AS dur,
-    thread.name AS process_name,
-    slices.name AS animator_name
-FROM slices
 INNER JOIN process_track on slices.track_id = process_track.id
-INNER JOIN thread USING(upid)
-WHERE slices.name LIKE "animator%";
+INNER JOIN thread USING(upid);
 
-DROP VIEW IF EXISTS frame_times;
-CREATE VIEW frame_times AS
-SELECT
-    functions.ts AS ts,
-    functions.ts + functions.dur AS ts_end,
-    launches.package AS name,
-    launches.id AS launch_id,
-    ROW_NUMBER() OVER(PARTITION BY launches.id ORDER BY functions.ts ASC) as number
-FROM functions
-INNER JOIN launches on launches.package LIKE '%' || functions.process_name || '%'
-WHERE functions.function_name LIKE "Choreographer#doFrame%" AND functions.ts > launches.ts;
-
-DROP TABLE IF EXISTS hsc_based_startup_times;
 CREATE TABLE hsc_based_startup_times(package STRING, id INT, ts_total INT);
 
 -- Calculator
@@ -64,7 +48,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=2 AND frame_times.name LIKE "%roid.calcul%" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=2 AND frame_times.name LIKE "%roid.calcul%" AND frame_times.launch_id = launches.id;
 
 -- Calendar
 INSERT INTO hsc_based_startup_times
@@ -74,8 +58,8 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.name LIKE "%id.calendar%" AND frame_times.launch_id = launches.id
-ORDER BY ABS(frame_times.ts_end - (SELECT ts + dur FROM functions WHERE function_name LIKE "DrawFrame%" AND process_name LIKE "%id.calendar" ORDER BY ts LIMIT 1)) LIMIT 1;
+WHERE frame_times.ts_end > (SELECT ts + dur FROM functions WHERE function_name LIKE "animator:growScale" AND process_name LIKE "%id.calendar" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%id.calendar%" AND frame_times.launch_id = launches.id
+ORDER BY ts_total LIMIT 1;
 
 -- Camera
 INSERT INTO hsc_based_startup_times
@@ -85,7 +69,8 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=2 AND frame_times.name LIKE "%GoogleCamera%" AND frame_times.launch_id = launches.id;
+WHERE frame_times.ts > (SELECT ts + dur FROM functions WHERE function_name="ShutterButtonEnabled" AND process_name LIKE "%id.GoogleCamera%" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%id.GoogleCamera%" AND frame_times.launch_id = launches.id
+ORDER BY ts_total LIMIT 1;
 
 -- Chrome
 INSERT INTO hsc_based_startup_times
@@ -95,7 +80,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=1 AND frame_times.name LIKE "%chrome%" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=1 AND frame_times.name LIKE "%chrome%" AND frame_times.launch_id = launches.id;
 
 -- Clock
 INSERT INTO hsc_based_startup_times
@@ -105,7 +90,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts + dur FROM animators WHERE animator_name="animator:translationZ" AND process_name LIKE "%id.deskclock" ORDER BY (ts+dur) DESC LIMIT 1) AND frame_times.name LIKE "%id.deskclock" AND frame_times.launch_id = launches.id
+WHERE frame_times.ts > (SELECT ts + dur FROM functions WHERE function_name="animator:translationZ" AND process_name LIKE "%id.deskclock" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%id.deskclock" AND frame_times.launch_id = launches.id
 ORDER BY ts_total LIMIT 1;
 
 -- Contacts
@@ -116,7 +101,8 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=3 AND frame_times.name LIKE "%id.contacts" AND frame_times.launch_id=launches.id;
+WHERE frame_times.ts > (SELECT ts + dur FROM functions WHERE function_name="animator:elevation" AND process_name LIKE "%id.contacts" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%id.contacts" AND frame_times.launch_id = launches.id
+ORDER BY ts_total LIMIT 1;
 
 -- Dialer
 INSERT INTO hsc_based_startup_times
@@ -126,29 +112,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=1 AND frame_times.name LIKE "%id.dialer" AND frame_times.launch_id=launches.id;
-
--- Facebook
-INSERT INTO hsc_based_startup_times
-SELECT
-    launches.package as package,
-    launches.id as id,
-    frame_times.ts_end - launches.ts as ts_total
-FROM frame_times
-INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts+dur FROM slices WHERE slices.name LIKE "fb_startup_complete" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%ok.katana" AND frame_times.launch_id = launches.id
-ORDER BY ts_total LIMIT 1;
-
--- Facebook Messenger
-INSERT INTO hsc_based_startup_times
-SELECT
-    launches.package as package,
-    launches.id as id,
-    frame_times.ts_end - launches.ts as ts_total
-FROM frame_times
-INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts+dur FROM slices WHERE slices.name LIKE "msgr_cold_start_to_cached_content" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%book.orca" AND frame_times.launch_id = launches.id
-ORDER BY ts_total LIMIT 1;
+WHERE frame_times.frame_number=2 AND frame_times.name LIKE "%id.dialer" AND frame_times.launch_id = launches.id;
 
 -- Gmail
 INSERT INTO hsc_based_startup_times
@@ -158,19 +122,17 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts + dur FROM animators WHERE animator_name="animator:elevation" AND process_name LIKE "%android.gm" ORDER BY (ts+dur) DESC LIMIT 1) AND frame_times.name LIKE "%android.gm" AND frame_times.launch_id = launches.id
+WHERE frame_times.ts > (SELECT ts + dur FROM functions WHERE function_name="animator:elevation" AND process_name LIKE "%android.gm" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%android.gm" AND frame_times.launch_id = launches.id
 ORDER BY ts_total LIMIT 1;
 
 -- Instagram
 INSERT INTO hsc_based_startup_times
 SELECT
-    launches.package as package,
-    launches.id as id,
-    frame_times.ts_end - launches.ts as ts_total
-FROM frame_times
-INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts+dur FROM slices WHERE slices.name LIKE "ig_cold_start_to_cached_content" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%gram.android" AND frame_times.launch_id = launches.id
-ORDER BY ts_total LIMIT 1;
+    package as package,
+    id as id,
+    (SELECT ts + dur FROM slices WHERE slices.name LIKE "Start proc%mqtt" ORDER BY ts LIMIT 1) - launches.ts as ts_total
+FROM launches
+WHERE launches.package="com.instagram.android";
 
 -- Maps
 INSERT INTO hsc_based_startup_times
@@ -180,7 +142,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=1 AND frame_times.name LIKE "%maps%" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=1 AND frame_times.name LIKE "%maps%" AND frame_times.launch_id = launches.id;
 
 -- Messages
 INSERT INTO hsc_based_startup_times
@@ -190,7 +152,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts_end > (SELECT ts + dur FROM animators WHERE animator_name="animator:translationZ" AND process_name LIKE "%apps.messaging%" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%apps.messaging%" AND frame_times.launch_id = launches.id
+WHERE frame_times.ts_end > (SELECT ts + dur FROM functions WHERE function_name="animator:translationZ" AND process_name LIKE "%apps.messaging%" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%apps.messaging%" AND frame_times.launch_id = launches.id
 ORDER BY ts_total LIMIT 1;
 
 -- Netflix
@@ -201,7 +163,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts < (SELECT ts FROM animators WHERE animator_name LIKE "animator%" AND process_name LIKE "%lix.mediaclient" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%lix.mediaclient%" AND frame_times.launch_id = launches.id
+WHERE frame_times.ts < (SELECT ts FROM functions WHERE function_name LIKE "animator%" AND process_name LIKE "%lix.mediaclient" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%lix.mediaclient%" AND frame_times.launch_id = launches.id
 ORDER BY ts_total DESC LIMIT 1;
 
 -- Photos
@@ -212,9 +174,17 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=1 AND frame_times.name LIKE "%apps.photos%" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=1 AND frame_times.name LIKE "%apps.photos%" AND frame_times.launch_id = launches.id;
 
--- Settings was deprecated in favor of reportFullyDrawn b/169694037.
+-- Settings
+INSERT INTO hsc_based_startup_times
+SELECT
+    launches.package as package,
+    launches.id as id,
+    frame_times.ts_end - launches.ts as ts_total
+FROM frame_times
+INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
+WHERE frame_times.frame_number=4 AND frame_times.name LIKE "%settings%" AND frame_times.launch_id = launches.id;
 
 -- Snapchat
 INSERT INTO hsc_based_startup_times
@@ -224,7 +194,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=1 AND frame_times.name LIKE "%napchat.android" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=1 AND frame_times.name LIKE "%napchat.android" AND frame_times.launch_id = launches.id;
 
 -- Twitter
 INSERT INTO hsc_based_startup_times
@@ -234,18 +204,7 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts_end > (SELECT ts FROM animators WHERE animator_name="animator" AND process_name LIKE "%tter.android" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%tter.android" AND frame_times.launch_id = launches.id
-ORDER BY ts_total LIMIT 1;
-
--- WhatsApp
-INSERT INTO hsc_based_startup_times
-SELECT
-    launches.package as package,
-    launches.id as id,
-    frame_times.ts_end - launches.ts as ts_total
-FROM frame_times
-INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.ts > (SELECT ts+dur FROM slices WHERE slices.name LIKE "wa_startup_complete" ORDER BY ts LIMIT 1) AND frame_times.name LIKE "%om.whatsapp" AND frame_times.launch_id = launches.id
+WHERE frame_times.ts > (SELECT ts + dur FROM functions WHERE function_name="animator:translationZ" AND process_name LIKE "%tter.android" ORDER BY ts DESC LIMIT 1) AND frame_times.name LIKE "%tter.android" AND frame_times.launch_id = launches.id
 ORDER BY ts_total LIMIT 1;
 
 -- Youtube
@@ -256,4 +215,4 @@
     frame_times.ts_end - launches.ts as ts_total
 FROM frame_times
 INNER JOIN launches on launches.package LIKE '%' || frame_times.name || '%'
-WHERE frame_times.number=2 AND frame_times.name LIKE "%id.youtube" AND frame_times.launch_id = launches.id;
+WHERE frame_times.frame_number=1 AND frame_times.name LIKE "%id.youtube" AND frame_times.launch_id = launches.id;
diff --git a/src/trace_processor/metrics/android/java_heap_histogram.sql b/src/trace_processor/metrics/android/java_heap_histogram.sql
index 7fd968c..a8d9b5f 100644
--- a/src/trace_processor/metrics/android/java_heap_histogram.sql
+++ b/src/trace_processor/metrics/android/java_heap_histogram.sql
@@ -16,32 +16,7 @@
 
 SELECT RUN_METRIC('android/process_metadata.sql');
 
-DROP TABLE IF EXISTS android_special_classes;
-CREATE TABLE android_special_classes AS
-WITH RECURSIVE cls_visitor(cls_id, category) AS (
-  SELECT id, name FROM heap_graph_class WHERE name IN (
-    'android.view.View',
-    'android.app.Activity',
-    'android.app.Fragment',
-    'android.app.Service',
-    'android.content.ContentProvider',
-    'android.content.BroadcastReceiver',
-    'android.content.Context',
-    'android.content.Intent',
-    'android.content.res.ApkAssets',
-    'android.os.Handler',
-    'android.os.Parcel',
-    'android.graphics.Bitmap',
-    'android.graphics.BaseCanvas',
-    'com.android.server.am.PendingIntentRecord')
-  UNION ALL
-  SELECT child.id, parent.category
-  FROM heap_graph_class child JOIN cls_visitor parent ON parent.cls_id = child.superclass_id
-)
-SELECT * FROM cls_visitor;
-
-DROP VIEW IF EXISTS java_heap_histogram_output;
-CREATE VIEW java_heap_histogram_output AS
+CREATE VIEW IF NOT EXISTS java_heap_histogram_output AS
 WITH
 -- Base histogram table
 heap_obj_histograms AS (
@@ -49,14 +24,10 @@
     o.upid,
     o.graph_sample_ts,
     IFNULL(c.deobfuscated_name, c.name) AS type_name,
-    special.category,
     COUNT(1) obj_count,
     SUM(CASE o.reachable WHEN TRUE THEN 1 ELSE 0 END) reachable_obj_count
-  FROM heap_graph_object o
-  JOIN heap_graph_class c ON o.type_id = c.id
-  LEFT JOIN android_special_classes special ON special.cls_id = c.id
-  GROUP BY 1, 2, 3, 4
-  ORDER BY 6 DESC
+  FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
+  GROUP BY 1, 2, 3
 ),
 -- Group by to build the repeated field by upid, ts
 heap_obj_histogram_count_protos AS (
@@ -65,7 +36,6 @@
     graph_sample_ts,
     RepeatedField(JavaHeapHistogram_TypeCount(
       'type_name', type_name,
-      'category', category,
       'obj_count', obj_count,
       'reachable_obj_count', reachable_obj_count
     )) AS count_protos
diff --git a/src/trace_processor/metrics/android/java_heap_stats.sql b/src/trace_processor/metrics/android/java_heap_stats.sql
index dfafbbd..bb0b0b2 100644
--- a/src/trace_processor/metrics/android/java_heap_stats.sql
+++ b/src/trace_processor/metrics/android/java_heap_stats.sql
@@ -17,7 +17,6 @@
 SELECT RUN_METRIC('android/process_metadata.sql');
 SELECT RUN_METRIC('android/process_mem.sql');
 
-DROP VIEW IF EXISTS java_heap_stats_output;
 CREATE VIEW java_heap_stats_output AS
 WITH
 -- Base view
diff --git a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql b/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
index 645b8bb..f7ef71b 100644
--- a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
+++ b/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
@@ -15,6 +15,7 @@
 --
 
 DROP TABLE IF EXISTS {{table_name}}_by_priority_stats;
+
 CREATE TABLE {{table_name}}_by_priority_stats (
   process_name TEXT,
   priority TEXT,
@@ -52,6 +53,7 @@
 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,
diff --git a/src/trace_processor/metrics/android/power_drain_in_watts.sql b/src/trace_processor/metrics/android/power_drain_in_watts.sql
deleted file mode 100644
index 1fbfec3..0000000
--- a/src/trace_processor/metrics/android/power_drain_in_watts.sql
+++ /dev/null
@@ -1,91 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
-
--- This is a mapping from counter names on different devices
--- to what subsystems they are measuring.
-DROP TABLE IF EXISTS power_counters;
-CREATE TABLE power_counters (name TEXT UNIQUE, subsystem TEXT);
-
-INSERT INTO power_counters
-VALUES ('power.VPH_PWR_S5C_S6C_uws', 'cpu_big'),
-  ('power.VPH_PWR_S4C_uws', 'cpu_little'),
-  ('power.VPH_PWR_S2C_S3C_uws', 'soc'),
-  ('power.VPH_PWR_OLED_uws', 'display'),
-  ('power.PPVAR_VPH_PWR_S1A_S9A_S10A_uws', 'soc'),
-  ('power.PPVAR_VPH_PWR_S2A_S3A_uws', 'cpu_big'),
-  ('power.PPVAR_VPH_PWR_S1C_uws', 'cpu_little'),
-  ('power.WCN3998_VDD13 [from PP1304_L2C]_uws', 'wifi'),
-  ('power.PPVAR_VPH_PWR_WLAN_uws', 'wifi'),
-  ('power.PPVAR_VPH_PWR_OLED_uws', 'display'),
-  ('power.PPVAR_VPH_PWR_QTM525_uws', 'cellular'),
-  ('power.PPVAR_VPH_PWR_RF_uws', 'cellular'),
-  ('power.rails.aoc.logic', 'aoc'),
-  ('power.rails.aoc.memory', 'aoc'),
-  ('power.rails.cpu.big', 'cpu_big'),
-  ('power.rails.cpu.little', 'cpu_little'),
-  ('power.rails.cpu.mid', 'cpu_mid'),
-  ('power.rails.ddr.a', 'mem'),
-  ('power.rails.ddr.b', 'mem'),
-  ('power.rails.ddr.c', 'mem'),
-  ('power.rails.gpu', 'gpu'),
-  ('power.rails.display', 'display'),
-  ('power.rails.gps', 'gps'),
-  ('power.rails.memory.interface', 'mem'),
-  ('power.rails.modem', 'cellular'),
-  ('power.rails.radio.frontend', 'cellular'),
-  ('power.rails.system.fabric', 'soc'),
-  ('power.rails.wifi.bt', 'wifi');
-
--- Convert power counter data into table of events, where each event has
--- start timestamp, duration and the average power drain during its duration
--- in Watts.
--- Note that power counters wrap around at different values on different
--- devices. When that happens, we ignore the value before overflow, and only
--- take into account the value after it. This underestimates the actual power
--- drain between those counters.
-DROP VIEW IF EXISTS drain_in_watts;
-CREATE VIEW drain_in_watts AS
-SELECT name,
-  ts,
-  LEAD(ts) OVER (
-    PARTITION BY track_id
-    ORDER BY ts
-  ) - ts AS dur,
-  CASE
-    WHEN LEAD(value) OVER (
-      PARTITION BY track_id
-      ORDER BY ts
-    ) >= value THEN (
-      LEAD(value) OVER (
-        PARTITION BY track_id
-        ORDER BY ts
-      ) - value
-    )
-    ELSE LEAD(value) OVER (
-      PARTITION BY track_id
-      ORDER BY ts
-    )
-  END / (
-    LEAD(ts) OVER (
-      PARTITION BY track_id
-      ORDER BY ts
-    ) - ts
-  ) * 1e3 AS drain_w
-FROM counter
-  JOIN counter_track ON (counter.track_id = counter_track.id)
-WHERE counter_track.type = 'counter_track'
-  AND name LIKE "power.%";
-
diff --git a/src/trace_processor/metrics/android/power_profile_data.sql b/src/trace_processor/metrics/android/power_profile_data.sql
deleted file mode 100644
index 5ea96ea..0000000
--- a/src/trace_processor/metrics/android/power_profile_data.sql
+++ /dev/null
@@ -1,1366 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
-INSERT OR REPLACE INTO power_profile VALUES
-("marlin", 0, 0, 307200, 11.272),
-("marlin", 0, 0, 384000, 14.842),
-("marlin", 0, 0, 460800, 18.497),
-("marlin", 0, 0, 537600, 22.518),
-("marlin", 0, 0, 614400, 25.967),
-("marlin", 0, 0, 691200, 31.694),
-("marlin", 0, 0, 768000, 37.673),
-("marlin", 0, 0, 844800, 42.859),
-("marlin", 0, 0, 902600, 46.872),
-("marlin", 0, 0, 979200, 57.92),
-("marlin", 0, 0, 1056000, 67.561),
-("marlin", 0, 0, 1132800, 76.303),
-("marlin", 0, 0, 1209600, 87.613),
-("marlin", 0, 0, 1286400, 97.045),
-("marlin", 0, 0, 1363200, 109.544),
-("marlin", 0, 0, 1440000, 122.054),
-("marlin", 0, 0, 1516800, 136.345),
-("marlin", 0, 0, 1593600, 154.435),
-("marlin", 1, 0, 307200, 11.272),
-("marlin", 1, 0, 384000, 14.842),
-("marlin", 1, 0, 460800, 18.497),
-("marlin", 1, 0, 537600, 22.518),
-("marlin", 1, 0, 614400, 25.967),
-("marlin", 1, 0, 691200, 31.694),
-("marlin", 1, 0, 768000, 37.673),
-("marlin", 1, 0, 844800, 42.859),
-("marlin", 1, 0, 902600, 46.872),
-("marlin", 1, 0, 979200, 57.92),
-("marlin", 1, 0, 1056000, 67.561),
-("marlin", 1, 0, 1132800, 76.303),
-("marlin", 1, 0, 1209600, 87.613),
-("marlin", 1, 0, 1286400, 97.045),
-("marlin", 1, 0, 1363200, 109.544),
-("marlin", 1, 0, 1440000, 122.054),
-("marlin", 1, 0, 1516800, 136.345),
-("marlin", 1, 0, 1593600, 154.435),
-("marlin", 2, 1, 307200, 7.055),
-("marlin", 2, 1, 384000, 11.483),
-("marlin", 2, 1, 460800, 14.979),
-("marlin", 2, 1, 537600, 19.642),
-("marlin", 2, 1, 614400, 23.167),
-("marlin", 2, 1, 691200, 27.479),
-("marlin", 2, 1, 748800, 31.632),
-("marlin", 2, 1, 825600, 39.192),
-("marlin", 2, 1, 902400, 47.817),
-("marlin", 2, 1, 979200, 55.659),
-("marlin", 2, 1, 1056000, 64.908),
-("marlin", 2, 1, 1132800, 73.824),
-("marlin", 2, 1, 1209600, 85.299),
-("marlin", 2, 1, 1286400, 96.036),
-("marlin", 2, 1, 1363200, 109.233),
-("marlin", 2, 1, 1440000, 118.56),
-("marlin", 2, 1, 1516800, 132.959),
-("marlin", 2, 1, 1593600, 143.692),
-("marlin", 2, 1, 1670400, 161.378),
-("marlin", 2, 1, 1747200, 180.616),
-("marlin", 2, 1, 1824000, 193.897),
-("marlin", 2, 1, 1900800, 214.361),
-("marlin", 2, 1, 1977600, 238.338),
-("marlin", 2, 1, 2054400, 265.759),
-("marlin", 2, 1, 2150400, 297.918),
-("marlin", 3, 1, 307200, 7.055),
-("marlin", 3, 1, 384000, 11.483),
-("marlin", 3, 1, 460800, 14.979),
-("marlin", 3, 1, 537600, 19.642),
-("marlin", 3, 1, 614400, 23.167),
-("marlin", 3, 1, 691200, 27.479),
-("marlin", 3, 1, 748800, 31.632),
-("marlin", 3, 1, 825600, 39.192),
-("marlin", 3, 1, 902400, 47.817),
-("marlin", 3, 1, 979200, 55.659),
-("marlin", 3, 1, 1056000, 64.908),
-("marlin", 3, 1, 1132800, 73.824),
-("marlin", 3, 1, 1209600, 85.299),
-("marlin", 3, 1, 1286400, 96.036),
-("marlin", 3, 1, 1363200, 109.233),
-("marlin", 3, 1, 1440000, 118.56),
-("marlin", 3, 1, 1516800, 132.959),
-("marlin", 3, 1, 1593600, 143.692),
-("marlin", 3, 1, 1670400, 161.378),
-("marlin", 3, 1, 1747200, 180.616),
-("marlin", 3, 1, 1824000, 193.897),
-("marlin", 3, 1, 1900800, 214.361),
-("marlin", 3, 1, 1977600, 238.338),
-("marlin", 3, 1, 2054400, 265.759),
-("marlin", 3, 1, 2150400, 297.918),
-("sailfish", 0, 0, 307200, 11.272),
-("sailfish", 0, 0, 384000, 14.842),
-("sailfish", 0, 0, 460800, 18.497),
-("sailfish", 0, 0, 537600, 22.518),
-("sailfish", 0, 0, 614400, 25.967),
-("sailfish", 0, 0, 691200, 31.694),
-("sailfish", 0, 0, 768000, 37.673),
-("sailfish", 0, 0, 844800, 42.859),
-("sailfish", 0, 0, 902600, 46.872),
-("sailfish", 0, 0, 979200, 57.92),
-("sailfish", 0, 0, 1056000, 67.561),
-("sailfish", 0, 0, 1132800, 76.303),
-("sailfish", 0, 0, 1209600, 87.613),
-("sailfish", 0, 0, 1286400, 97.045),
-("sailfish", 0, 0, 1363200, 109.544),
-("sailfish", 0, 0, 1440000, 122.054),
-("sailfish", 0, 0, 1516800, 136.345),
-("sailfish", 0, 0, 1593600, 154.435),
-("sailfish", 1, 0, 307200, 11.272),
-("sailfish", 1, 0, 384000, 14.842),
-("sailfish", 1, 0, 460800, 18.497),
-("sailfish", 1, 0, 537600, 22.518),
-("sailfish", 1, 0, 614400, 25.967),
-("sailfish", 1, 0, 691200, 31.694),
-("sailfish", 1, 0, 768000, 37.673),
-("sailfish", 1, 0, 844800, 42.859),
-("sailfish", 1, 0, 902600, 46.872),
-("sailfish", 1, 0, 979200, 57.92),
-("sailfish", 1, 0, 1056000, 67.561),
-("sailfish", 1, 0, 1132800, 76.303),
-("sailfish", 1, 0, 1209600, 87.613),
-("sailfish", 1, 0, 1286400, 97.045),
-("sailfish", 1, 0, 1363200, 109.544),
-("sailfish", 1, 0, 1440000, 122.054),
-("sailfish", 1, 0, 1516800, 136.345),
-("sailfish", 1, 0, 1593600, 154.435),
-("sailfish", 2, 1, 307200, 7.055),
-("sailfish", 2, 1, 384000, 11.483),
-("sailfish", 2, 1, 460800, 14.979),
-("sailfish", 2, 1, 537600, 19.642),
-("sailfish", 2, 1, 614400, 23.167),
-("sailfish", 2, 1, 691200, 27.479),
-("sailfish", 2, 1, 748800, 31.632),
-("sailfish", 2, 1, 825600, 39.192),
-("sailfish", 2, 1, 902400, 47.817),
-("sailfish", 2, 1, 979200, 55.659),
-("sailfish", 2, 1, 1056000, 64.908),
-("sailfish", 2, 1, 1132800, 73.824),
-("sailfish", 2, 1, 1209600, 85.299),
-("sailfish", 2, 1, 1286400, 96.036),
-("sailfish", 2, 1, 1363200, 109.233),
-("sailfish", 2, 1, 1440000, 118.56),
-("sailfish", 2, 1, 1516800, 132.959),
-("sailfish", 2, 1, 1593600, 143.692),
-("sailfish", 2, 1, 1670400, 161.378),
-("sailfish", 2, 1, 1747200, 180.616),
-("sailfish", 2, 1, 1824000, 193.897),
-("sailfish", 2, 1, 1900800, 214.361),
-("sailfish", 2, 1, 1977600, 238.338),
-("sailfish", 2, 1, 2054400, 265.759),
-("sailfish", 2, 1, 2150400, 297.918),
-("sailfish", 3, 1, 307200, 7.055),
-("sailfish", 3, 1, 384000, 11.483),
-("sailfish", 3, 1, 460800, 14.979),
-("sailfish", 3, 1, 537600, 19.642),
-("sailfish", 3, 1, 614400, 23.167),
-("sailfish", 3, 1, 691200, 27.479),
-("sailfish", 3, 1, 748800, 31.632),
-("sailfish", 3, 1, 825600, 39.192),
-("sailfish", 3, 1, 902400, 47.817),
-("sailfish", 3, 1, 979200, 55.659),
-("sailfish", 3, 1, 1056000, 64.908),
-("sailfish", 3, 1, 1132800, 73.824),
-("sailfish", 3, 1, 1209600, 85.299),
-("sailfish", 3, 1, 1286400, 96.036),
-("sailfish", 3, 1, 1363200, 109.233),
-("sailfish", 3, 1, 1440000, 118.56),
-("sailfish", 3, 1, 1516800, 132.959),
-("sailfish", 3, 1, 1593600, 143.692),
-("sailfish", 3, 1, 1670400, 161.378),
-("sailfish", 3, 1, 1747200, 180.616),
-("sailfish", 3, 1, 1824000, 193.897),
-("sailfish", 3, 1, 1900800, 214.361),
-("sailfish", 3, 1, 1977600, 238.338),
-("sailfish", 3, 1, 2054400, 265.759),
-("sailfish", 3, 1, 2150400, 297.918),
-("walleye", 0, 0, 300000, 3.685),
-("walleye", 0, 0, 364800, 3.598),
-("walleye", 0, 0, 441600, 3.621),
-("walleye", 0, 0, 518400, 4.202),
-("walleye", 0, 0, 595200, 4.935),
-("walleye", 0, 0, 672000, 5.633),
-("walleye", 0, 0, 748800, 6.216),
-("walleye", 0, 0, 825600, 6.71),
-("walleye", 0, 0, 883200, 7.557),
-("walleye", 0, 0, 960000, 8.687),
-("walleye", 0, 0, 1036800, 9.882),
-("walleye", 0, 0, 1094400, 10.95),
-("walleye", 0, 0, 1171200, 12.075),
-("walleye", 0, 0, 1248000, 12.875),
-("walleye", 0, 0, 1324800, 14.424),
-("walleye", 0, 0, 1401600, 15.653),
-("walleye", 0, 0, 1478400, 17.345),
-("walleye", 0, 0, 1555200, 18.71),
-("walleye", 0, 0, 1670400, 21.587),
-("walleye", 0, 0, 1747200, 25.43),
-("walleye", 0, 0, 1824000, 27.165),
-("walleye", 0, 0, 1900800, 31.671),
-("walleye", 1, 0, 300000, 3.685),
-("walleye", 1, 0, 364800, 3.598),
-("walleye", 1, 0, 441600, 3.621),
-("walleye", 1, 0, 518400, 4.202),
-("walleye", 1, 0, 595200, 4.935),
-("walleye", 1, 0, 672000, 5.633),
-("walleye", 1, 0, 748800, 6.216),
-("walleye", 1, 0, 825600, 6.71),
-("walleye", 1, 0, 883200, 7.557),
-("walleye", 1, 0, 960000, 8.687),
-("walleye", 1, 0, 1036800, 9.882),
-("walleye", 1, 0, 1094400, 10.95),
-("walleye", 1, 0, 1171200, 12.075),
-("walleye", 1, 0, 1248000, 12.875),
-("walleye", 1, 0, 1324800, 14.424),
-("walleye", 1, 0, 1401600, 15.653),
-("walleye", 1, 0, 1478400, 17.345),
-("walleye", 1, 0, 1555200, 18.71),
-("walleye", 1, 0, 1670400, 21.587),
-("walleye", 1, 0, 1747200, 25.43),
-("walleye", 1, 0, 1824000, 27.165),
-("walleye", 1, 0, 1900800, 31.671),
-("walleye", 2, 0, 300000, 3.685),
-("walleye", 2, 0, 364800, 3.598),
-("walleye", 2, 0, 441600, 3.621),
-("walleye", 2, 0, 518400, 4.202),
-("walleye", 2, 0, 595200, 4.935),
-("walleye", 2, 0, 672000, 5.633),
-("walleye", 2, 0, 748800, 6.216),
-("walleye", 2, 0, 825600, 6.71),
-("walleye", 2, 0, 883200, 7.557),
-("walleye", 2, 0, 960000, 8.687),
-("walleye", 2, 0, 1036800, 9.882),
-("walleye", 2, 0, 1094400, 10.95),
-("walleye", 2, 0, 1171200, 12.075),
-("walleye", 2, 0, 1248000, 12.875),
-("walleye", 2, 0, 1324800, 14.424),
-("walleye", 2, 0, 1401600, 15.653),
-("walleye", 2, 0, 1478400, 17.345),
-("walleye", 2, 0, 1555200, 18.71),
-("walleye", 2, 0, 1670400, 21.587),
-("walleye", 2, 0, 1747200, 25.43),
-("walleye", 2, 0, 1824000, 27.165),
-("walleye", 2, 0, 1900800, 31.671),
-("walleye", 3, 0, 300000, 3.685),
-("walleye", 3, 0, 364800, 3.598),
-("walleye", 3, 0, 441600, 3.621),
-("walleye", 3, 0, 518400, 4.202),
-("walleye", 3, 0, 595200, 4.935),
-("walleye", 3, 0, 672000, 5.633),
-("walleye", 3, 0, 748800, 6.216),
-("walleye", 3, 0, 825600, 6.71),
-("walleye", 3, 0, 883200, 7.557),
-("walleye", 3, 0, 960000, 8.687),
-("walleye", 3, 0, 1036800, 9.882),
-("walleye", 3, 0, 1094400, 10.95),
-("walleye", 3, 0, 1171200, 12.075),
-("walleye", 3, 0, 1248000, 12.875),
-("walleye", 3, 0, 1324800, 14.424),
-("walleye", 3, 0, 1401600, 15.653),
-("walleye", 3, 0, 1478400, 17.345),
-("walleye", 3, 0, 1555200, 18.71),
-("walleye", 3, 0, 1670400, 21.587),
-("walleye", 3, 0, 1747200, 25.43),
-("walleye", 3, 0, 1824000, 27.165),
-("walleye", 3, 0, 1900800, 31.671),
-("walleye", 4, 1, 300000, 10.722),
-("walleye", 4, 1, 345600, 11.52),
-("walleye", 4, 1, 422400, 14.105),
-("walleye", 4, 1, 499200, 16.68),
-("walleye", 4, 1, 576000, 18.946),
-("walleye", 4, 1, 652800, 21.265),
-("walleye", 4, 1, 729600, 23.432),
-("walleye", 4, 1, 806400, 26.019),
-("walleye", 4, 1, 902400, 28.856),
-("walleye", 4, 1, 979200, 31.085),
-("walleye", 4, 1, 1056000, 33.615),
-("walleye", 4, 1, 1132800, 35.76),
-("walleye", 4, 1, 1190400, 40.608),
-("walleye", 4, 1, 1267200, 43.284),
-("walleye", 4, 1, 1344000, 47.347),
-("walleye", 4, 1, 1420800, 52.231),
-("walleye", 4, 1, 1497600, 57.225),
-("walleye", 4, 1, 1574400, 63.138),
-("walleye", 4, 1, 1651200, 69.251),
-("walleye", 4, 1, 1728000, 76.449),
-("walleye", 4, 1, 1804800, 84.71),
-("walleye", 4, 1, 1881600, 102.551),
-("walleye", 4, 1, 1958400, 107.115),
-("walleye", 4, 1, 2035200, 129.689),
-("walleye", 4, 1, 2112000, 135.832),
-("walleye", 4, 1, 2208000, 164.674),
-("walleye", 4, 1, 2265600, 180.279),
-("walleye", 4, 1, 2323200, 197.024),
-("walleye", 4, 1, 2342400, 204.511),
-("walleye", 4, 1, 2361600, 211.886),
-("walleye", 4, 1, 2457600, 212.147),
-("walleye", 5, 1, 300000, 10.722),
-("walleye", 5, 1, 345600, 11.52),
-("walleye", 5, 1, 422400, 14.105),
-("walleye", 5, 1, 499200, 16.68),
-("walleye", 5, 1, 576000, 18.946),
-("walleye", 5, 1, 652800, 21.265),
-("walleye", 5, 1, 729600, 23.432),
-("walleye", 5, 1, 806400, 26.019),
-("walleye", 5, 1, 902400, 28.856),
-("walleye", 5, 1, 979200, 31.085),
-("walleye", 5, 1, 1056000, 33.615),
-("walleye", 5, 1, 1132800, 35.76),
-("walleye", 5, 1, 1190400, 40.608),
-("walleye", 5, 1, 1267200, 43.284),
-("walleye", 5, 1, 1344000, 47.347),
-("walleye", 5, 1, 1420800, 52.231),
-("walleye", 5, 1, 1497600, 57.225),
-("walleye", 5, 1, 1574400, 63.138),
-("walleye", 5, 1, 1651200, 69.251),
-("walleye", 5, 1, 1728000, 76.449),
-("walleye", 5, 1, 1804800, 84.71),
-("walleye", 5, 1, 1881600, 102.551),
-("walleye", 5, 1, 1958400, 107.115),
-("walleye", 5, 1, 2035200, 129.689),
-("walleye", 5, 1, 2112000, 135.832),
-("walleye", 5, 1, 2208000, 164.674),
-("walleye", 5, 1, 2265600, 180.279),
-("walleye", 5, 1, 2323200, 197.024),
-("walleye", 5, 1, 2342400, 204.511),
-("walleye", 5, 1, 2361600, 211.886),
-("walleye", 5, 1, 2457600, 212.147),
-("walleye", 6, 1, 300000, 10.722),
-("walleye", 6, 1, 345600, 11.52),
-("walleye", 6, 1, 422400, 14.105),
-("walleye", 6, 1, 499200, 16.68),
-("walleye", 6, 1, 576000, 18.946),
-("walleye", 6, 1, 652800, 21.265),
-("walleye", 6, 1, 729600, 23.432),
-("walleye", 6, 1, 806400, 26.019),
-("walleye", 6, 1, 902400, 28.856),
-("walleye", 6, 1, 979200, 31.085),
-("walleye", 6, 1, 1056000, 33.615),
-("walleye", 6, 1, 1132800, 35.76),
-("walleye", 6, 1, 1190400, 40.608),
-("walleye", 6, 1, 1267200, 43.284),
-("walleye", 6, 1, 1344000, 47.347),
-("walleye", 6, 1, 1420800, 52.231),
-("walleye", 6, 1, 1497600, 57.225),
-("walleye", 6, 1, 1574400, 63.138),
-("walleye", 6, 1, 1651200, 69.251),
-("walleye", 6, 1, 1728000, 76.449),
-("walleye", 6, 1, 1804800, 84.71),
-("walleye", 6, 1, 1881600, 102.551),
-("walleye", 6, 1, 1958400, 107.115),
-("walleye", 6, 1, 2035200, 129.689),
-("walleye", 6, 1, 2112000, 135.832),
-("walleye", 6, 1, 2208000, 164.674),
-("walleye", 6, 1, 2265600, 180.279),
-("walleye", 6, 1, 2323200, 197.024),
-("walleye", 6, 1, 2342400, 204.511),
-("walleye", 6, 1, 2361600, 211.886),
-("walleye", 6, 1, 2457600, 212.147),
-("walleye", 7, 1, 300000, 10.722),
-("walleye", 7, 1, 345600, 11.52),
-("walleye", 7, 1, 422400, 14.105),
-("walleye", 7, 1, 499200, 16.68),
-("walleye", 7, 1, 576000, 18.946),
-("walleye", 7, 1, 652800, 21.265),
-("walleye", 7, 1, 729600, 23.432),
-("walleye", 7, 1, 806400, 26.019),
-("walleye", 7, 1, 902400, 28.856),
-("walleye", 7, 1, 979200, 31.085),
-("walleye", 7, 1, 1056000, 33.615),
-("walleye", 7, 1, 1132800, 35.76),
-("walleye", 7, 1, 1190400, 40.608),
-("walleye", 7, 1, 1267200, 43.284),
-("walleye", 7, 1, 1344000, 47.347),
-("walleye", 7, 1, 1420800, 52.231),
-("walleye", 7, 1, 1497600, 57.225),
-("walleye", 7, 1, 1574400, 63.138),
-("walleye", 7, 1, 1651200, 69.251),
-("walleye", 7, 1, 1728000, 76.449),
-("walleye", 7, 1, 1804800, 84.71),
-("walleye", 7, 1, 1881600, 102.551),
-("walleye", 7, 1, 1958400, 107.115),
-("walleye", 7, 1, 2035200, 129.689),
-("walleye", 7, 1, 2112000, 135.832),
-("walleye", 7, 1, 2208000, 164.674),
-("walleye", 7, 1, 2265600, 180.279),
-("walleye", 7, 1, 2323200, 197.024),
-("walleye", 7, 1, 2342400, 204.511),
-("walleye", 7, 1, 2361600, 211.886),
-("walleye", 7, 1, 2457600, 212.147),
-("taimen", 0, 0, 300000, 3.685),
-("taimen", 0, 0, 364800, 3.598),
-("taimen", 0, 0, 441600, 3.621),
-("taimen", 0, 0, 518400, 4.202),
-("taimen", 0, 0, 595200, 4.935),
-("taimen", 0, 0, 672000, 5.633),
-("taimen", 0, 0, 748800, 6.216),
-("taimen", 0, 0, 825600, 6.71),
-("taimen", 0, 0, 883200, 7.557),
-("taimen", 0, 0, 960000, 8.687),
-("taimen", 0, 0, 1036800, 9.882),
-("taimen", 0, 0, 1094400, 10.95),
-("taimen", 0, 0, 1171200, 12.075),
-("taimen", 0, 0, 1248000, 12.875),
-("taimen", 0, 0, 1324800, 14.424),
-("taimen", 0, 0, 1401600, 15.653),
-("taimen", 0, 0, 1478400, 17.345),
-("taimen", 0, 0, 1555200, 18.71),
-("taimen", 0, 0, 1670400, 21.587),
-("taimen", 0, 0, 1747200, 25.43),
-("taimen", 0, 0, 1824000, 27.165),
-("taimen", 0, 0, 1900800, 31.671),
-("taimen", 1, 0, 300000, 3.685),
-("taimen", 1, 0, 364800, 3.598),
-("taimen", 1, 0, 441600, 3.621),
-("taimen", 1, 0, 518400, 4.202),
-("taimen", 1, 0, 595200, 4.935),
-("taimen", 1, 0, 672000, 5.633),
-("taimen", 1, 0, 748800, 6.216),
-("taimen", 1, 0, 825600, 6.71),
-("taimen", 1, 0, 883200, 7.557),
-("taimen", 1, 0, 960000, 8.687),
-("taimen", 1, 0, 1036800, 9.882),
-("taimen", 1, 0, 1094400, 10.95),
-("taimen", 1, 0, 1171200, 12.075),
-("taimen", 1, 0, 1248000, 12.875),
-("taimen", 1, 0, 1324800, 14.424),
-("taimen", 1, 0, 1401600, 15.653),
-("taimen", 1, 0, 1478400, 17.345),
-("taimen", 1, 0, 1555200, 18.71),
-("taimen", 1, 0, 1670400, 21.587),
-("taimen", 1, 0, 1747200, 25.43),
-("taimen", 1, 0, 1824000, 27.165),
-("taimen", 1, 0, 1900800, 31.671),
-("taimen", 2, 0, 300000, 3.685),
-("taimen", 2, 0, 364800, 3.598),
-("taimen", 2, 0, 441600, 3.621),
-("taimen", 2, 0, 518400, 4.202),
-("taimen", 2, 0, 595200, 4.935),
-("taimen", 2, 0, 672000, 5.633),
-("taimen", 2, 0, 748800, 6.216),
-("taimen", 2, 0, 825600, 6.71),
-("taimen", 2, 0, 883200, 7.557),
-("taimen", 2, 0, 960000, 8.687),
-("taimen", 2, 0, 1036800, 9.882),
-("taimen", 2, 0, 1094400, 10.95),
-("taimen", 2, 0, 1171200, 12.075),
-("taimen", 2, 0, 1248000, 12.875),
-("taimen", 2, 0, 1324800, 14.424),
-("taimen", 2, 0, 1401600, 15.653),
-("taimen", 2, 0, 1478400, 17.345),
-("taimen", 2, 0, 1555200, 18.71),
-("taimen", 2, 0, 1670400, 21.587),
-("taimen", 2, 0, 1747200, 25.43),
-("taimen", 2, 0, 1824000, 27.165),
-("taimen", 2, 0, 1900800, 31.671),
-("taimen", 3, 0, 300000, 3.685),
-("taimen", 3, 0, 364800, 3.598),
-("taimen", 3, 0, 441600, 3.621),
-("taimen", 3, 0, 518400, 4.202),
-("taimen", 3, 0, 595200, 4.935),
-("taimen", 3, 0, 672000, 5.633),
-("taimen", 3, 0, 748800, 6.216),
-("taimen", 3, 0, 825600, 6.71),
-("taimen", 3, 0, 883200, 7.557),
-("taimen", 3, 0, 960000, 8.687),
-("taimen", 3, 0, 1036800, 9.882),
-("taimen", 3, 0, 1094400, 10.95),
-("taimen", 3, 0, 1171200, 12.075),
-("taimen", 3, 0, 1248000, 12.875),
-("taimen", 3, 0, 1324800, 14.424),
-("taimen", 3, 0, 1401600, 15.653),
-("taimen", 3, 0, 1478400, 17.345),
-("taimen", 3, 0, 1555200, 18.71),
-("taimen", 3, 0, 1670400, 21.587),
-("taimen", 3, 0, 1747200, 25.43),
-("taimen", 3, 0, 1824000, 27.165),
-("taimen", 3, 0, 1900800, 31.671),
-("taimen", 4, 1, 300000, 10.722),
-("taimen", 4, 1, 345600, 11.52),
-("taimen", 4, 1, 422400, 14.105),
-("taimen", 4, 1, 499200, 16.68),
-("taimen", 4, 1, 576000, 18.946),
-("taimen", 4, 1, 652800, 21.265),
-("taimen", 4, 1, 729600, 23.432),
-("taimen", 4, 1, 806400, 26.019),
-("taimen", 4, 1, 902400, 28.856),
-("taimen", 4, 1, 979200, 31.085),
-("taimen", 4, 1, 1056000, 33.615),
-("taimen", 4, 1, 1132800, 35.76),
-("taimen", 4, 1, 1190400, 40.608),
-("taimen", 4, 1, 1267200, 43.284),
-("taimen", 4, 1, 1344000, 47.347),
-("taimen", 4, 1, 1420800, 52.231),
-("taimen", 4, 1, 1497600, 57.225),
-("taimen", 4, 1, 1574400, 63.138),
-("taimen", 4, 1, 1651200, 69.251),
-("taimen", 4, 1, 1728000, 76.449),
-("taimen", 4, 1, 1804800, 84.71),
-("taimen", 4, 1, 1881600, 102.551),
-("taimen", 4, 1, 1958400, 107.115),
-("taimen", 4, 1, 2035200, 129.689),
-("taimen", 4, 1, 2112000, 135.832),
-("taimen", 4, 1, 2208000, 164.674),
-("taimen", 4, 1, 2265600, 180.279),
-("taimen", 4, 1, 2323200, 197.024),
-("taimen", 4, 1, 2342400, 204.511),
-("taimen", 4, 1, 2361600, 211.886),
-("taimen", 4, 1, 2457600, 212.147),
-("taimen", 5, 1, 300000, 10.722),
-("taimen", 5, 1, 345600, 11.52),
-("taimen", 5, 1, 422400, 14.105),
-("taimen", 5, 1, 499200, 16.68),
-("taimen", 5, 1, 576000, 18.946),
-("taimen", 5, 1, 652800, 21.265),
-("taimen", 5, 1, 729600, 23.432),
-("taimen", 5, 1, 806400, 26.019),
-("taimen", 5, 1, 902400, 28.856),
-("taimen", 5, 1, 979200, 31.085),
-("taimen", 5, 1, 1056000, 33.615),
-("taimen", 5, 1, 1132800, 35.76),
-("taimen", 5, 1, 1190400, 40.608),
-("taimen", 5, 1, 1267200, 43.284),
-("taimen", 5, 1, 1344000, 47.347),
-("taimen", 5, 1, 1420800, 52.231),
-("taimen", 5, 1, 1497600, 57.225),
-("taimen", 5, 1, 1574400, 63.138),
-("taimen", 5, 1, 1651200, 69.251),
-("taimen", 5, 1, 1728000, 76.449),
-("taimen", 5, 1, 1804800, 84.71),
-("taimen", 5, 1, 1881600, 102.551),
-("taimen", 5, 1, 1958400, 107.115),
-("taimen", 5, 1, 2035200, 129.689),
-("taimen", 5, 1, 2112000, 135.832),
-("taimen", 5, 1, 2208000, 164.674),
-("taimen", 5, 1, 2265600, 180.279),
-("taimen", 5, 1, 2323200, 197.024),
-("taimen", 5, 1, 2342400, 204.511),
-("taimen", 5, 1, 2361600, 211.886),
-("taimen", 5, 1, 2457600, 212.147),
-("taimen", 6, 1, 300000, 10.722),
-("taimen", 6, 1, 345600, 11.52),
-("taimen", 6, 1, 422400, 14.105),
-("taimen", 6, 1, 499200, 16.68),
-("taimen", 6, 1, 576000, 18.946),
-("taimen", 6, 1, 652800, 21.265),
-("taimen", 6, 1, 729600, 23.432),
-("taimen", 6, 1, 806400, 26.019),
-("taimen", 6, 1, 902400, 28.856),
-("taimen", 6, 1, 979200, 31.085),
-("taimen", 6, 1, 1056000, 33.615),
-("taimen", 6, 1, 1132800, 35.76),
-("taimen", 6, 1, 1190400, 40.608),
-("taimen", 6, 1, 1267200, 43.284),
-("taimen", 6, 1, 1344000, 47.347),
-("taimen", 6, 1, 1420800, 52.231),
-("taimen", 6, 1, 1497600, 57.225),
-("taimen", 6, 1, 1574400, 63.138),
-("taimen", 6, 1, 1651200, 69.251),
-("taimen", 6, 1, 1728000, 76.449),
-("taimen", 6, 1, 1804800, 84.71),
-("taimen", 6, 1, 1881600, 102.551),
-("taimen", 6, 1, 1958400, 107.115),
-("taimen", 6, 1, 2035200, 129.689),
-("taimen", 6, 1, 2112000, 135.832),
-("taimen", 6, 1, 2208000, 164.674),
-("taimen", 6, 1, 2265600, 180.279),
-("taimen", 6, 1, 2323200, 197.024),
-("taimen", 6, 1, 2342400, 204.511),
-("taimen", 6, 1, 2361600, 211.886),
-("taimen", 6, 1, 2457600, 212.147),
-("taimen", 7, 1, 300000, 10.722),
-("taimen", 7, 1, 345600, 11.52),
-("taimen", 7, 1, 422400, 14.105),
-("taimen", 7, 1, 499200, 16.68),
-("taimen", 7, 1, 576000, 18.946),
-("taimen", 7, 1, 652800, 21.265),
-("taimen", 7, 1, 729600, 23.432),
-("taimen", 7, 1, 806400, 26.019),
-("taimen", 7, 1, 902400, 28.856),
-("taimen", 7, 1, 979200, 31.085),
-("taimen", 7, 1, 1056000, 33.615),
-("taimen", 7, 1, 1132800, 35.76),
-("taimen", 7, 1, 1190400, 40.608),
-("taimen", 7, 1, 1267200, 43.284),
-("taimen", 7, 1, 1344000, 47.347),
-("taimen", 7, 1, 1420800, 52.231),
-("taimen", 7, 1, 1497600, 57.225),
-("taimen", 7, 1, 1574400, 63.138),
-("taimen", 7, 1, 1651200, 69.251),
-("taimen", 7, 1, 1728000, 76.449),
-("taimen", 7, 1, 1804800, 84.71),
-("taimen", 7, 1, 1881600, 102.551),
-("taimen", 7, 1, 1958400, 107.115),
-("taimen", 7, 1, 2035200, 129.689),
-("taimen", 7, 1, 2112000, 135.832),
-("taimen", 7, 1, 2208000, 164.674),
-("taimen", 7, 1, 2265600, 180.279),
-("taimen", 7, 1, 2323200, 197.024),
-("taimen", 7, 1, 2342400, 204.511),
-("taimen", 7, 1, 2361600, 211.886),
-("taimen", 7, 1, 2457600, 212.147),
-("crosshatch", 0, 0, 300000, 2.27),
-("crosshatch", 0, 0, 403200, 3.63),
-("crosshatch", 0, 0, 480000, 4.36),
-("crosshatch", 0, 0, 576000, 5.21),
-("crosshatch", 0, 0, 652800, 5.47),
-("crosshatch", 0, 0, 748800, 6.74),
-("crosshatch", 0, 0, 825600, 7.69),
-("crosshatch", 0, 0, 902400, 8.57),
-("crosshatch", 0, 0, 979200, 9.42),
-("crosshatch", 0, 0, 1056000, 10.41),
-("crosshatch", 0, 0, 1132800, 11.56),
-("crosshatch", 0, 0, 1228800, 12.87),
-("crosshatch", 0, 0, 1324800, 14.61),
-("crosshatch", 0, 0, 1420800, 16.49),
-("crosshatch", 0, 0, 1516800, 18.9),
-("crosshatch", 0, 0, 1612800, 21.62),
-("crosshatch", 0, 0, 1689600, 24.47),
-("crosshatch", 0, 0, 1766400, 26.45),
-("crosshatch", 1, 0, 300000, 2.27),
-("crosshatch", 1, 0, 403200, 3.63),
-("crosshatch", 1, 0, 480000, 4.36),
-("crosshatch", 1, 0, 576000, 5.21),
-("crosshatch", 1, 0, 652800, 5.47),
-("crosshatch", 1, 0, 748800, 6.74),
-("crosshatch", 1, 0, 825600, 7.69),
-("crosshatch", 1, 0, 902400, 8.57),
-("crosshatch", 1, 0, 979200, 9.42),
-("crosshatch", 1, 0, 1056000, 10.41),
-("crosshatch", 1, 0, 1132800, 11.56),
-("crosshatch", 1, 0, 1228800, 12.87),
-("crosshatch", 1, 0, 1324800, 14.61),
-("crosshatch", 1, 0, 1420800, 16.49),
-("crosshatch", 1, 0, 1516800, 18.9),
-("crosshatch", 1, 0, 1612800, 21.62),
-("crosshatch", 1, 0, 1689600, 24.47),
-("crosshatch", 1, 0, 1766400, 26.45),
-("crosshatch", 2, 0, 300000, 2.27),
-("crosshatch", 2, 0, 403200, 3.63),
-("crosshatch", 2, 0, 480000, 4.36),
-("crosshatch", 2, 0, 576000, 5.21),
-("crosshatch", 2, 0, 652800, 5.47),
-("crosshatch", 2, 0, 748800, 6.74),
-("crosshatch", 2, 0, 825600, 7.69),
-("crosshatch", 2, 0, 902400, 8.57),
-("crosshatch", 2, 0, 979200, 9.42),
-("crosshatch", 2, 0, 1056000, 10.41),
-("crosshatch", 2, 0, 1132800, 11.56),
-("crosshatch", 2, 0, 1228800, 12.87),
-("crosshatch", 2, 0, 1324800, 14.61),
-("crosshatch", 2, 0, 1420800, 16.49),
-("crosshatch", 2, 0, 1516800, 18.9),
-("crosshatch", 2, 0, 1612800, 21.62),
-("crosshatch", 2, 0, 1689600, 24.47),
-("crosshatch", 2, 0, 1766400, 26.45),
-("crosshatch", 3, 0, 300000, 2.27),
-("crosshatch", 3, 0, 403200, 3.63),
-("crosshatch", 3, 0, 480000, 4.36),
-("crosshatch", 3, 0, 576000, 5.21),
-("crosshatch", 3, 0, 652800, 5.47),
-("crosshatch", 3, 0, 748800, 6.74),
-("crosshatch", 3, 0, 825600, 7.69),
-("crosshatch", 3, 0, 902400, 8.57),
-("crosshatch", 3, 0, 979200, 9.42),
-("crosshatch", 3, 0, 1056000, 10.41),
-("crosshatch", 3, 0, 1132800, 11.56),
-("crosshatch", 3, 0, 1228800, 12.87),
-("crosshatch", 3, 0, 1324800, 14.61),
-("crosshatch", 3, 0, 1420800, 16.49),
-("crosshatch", 3, 0, 1516800, 18.9),
-("crosshatch", 3, 0, 1612800, 21.62),
-("crosshatch", 3, 0, 1689600, 24.47),
-("crosshatch", 3, 0, 1766400, 26.45),
-("crosshatch", 4, 1, 825600, 28.88),
-("crosshatch", 4, 1, 902400, 32.4),
-("crosshatch", 4, 1, 979200, 36.46),
-("crosshatch", 4, 1, 1056000, 39.99),
-("crosshatch", 4, 1, 1209600, 47.23),
-("crosshatch", 4, 1, 1286400, 51.39),
-("crosshatch", 4, 1, 1363200, 56.9),
-("crosshatch", 4, 1, 1459200, 64.26),
-("crosshatch", 4, 1, 1536000, 69.65),
-("crosshatch", 4, 1, 1612800, 75.14),
-("crosshatch", 4, 1, 1689600, 83.16),
-("crosshatch", 4, 1, 1766400, 91.75),
-("crosshatch", 4, 1, 1843200, 100.66),
-("crosshatch", 4, 1, 1920000, 111.45),
-("crosshatch", 4, 1, 1996800, 122.23),
-("crosshatch", 4, 1, 2092800, 143.54),
-("crosshatch", 4, 1, 2169600, 147.54),
-("crosshatch", 4, 1, 2246400, 153.09),
-("crosshatch", 4, 1, 2323200, 166.44),
-("crosshatch", 4, 1, 2400000, 184.69),
-("crosshatch", 4, 1, 2476800, 204.14),
-("crosshatch", 4, 1, 2553600, 223.37),
-("crosshatch", 4, 1, 2649600, 253.77),
-("crosshatch", 5, 1, 825600, 28.88),
-("crosshatch", 5, 1, 902400, 32.4),
-("crosshatch", 5, 1, 979200, 36.46),
-("crosshatch", 5, 1, 1056000, 39.99),
-("crosshatch", 5, 1, 1209600, 47.23),
-("crosshatch", 5, 1, 1286400, 51.39),
-("crosshatch", 5, 1, 1363200, 56.9),
-("crosshatch", 5, 1, 1459200, 64.26),
-("crosshatch", 5, 1, 1536000, 69.65),
-("crosshatch", 5, 1, 1612800, 75.14),
-("crosshatch", 5, 1, 1689600, 83.16),
-("crosshatch", 5, 1, 1766400, 91.75),
-("crosshatch", 5, 1, 1843200, 100.66),
-("crosshatch", 5, 1, 1920000, 111.45),
-("crosshatch", 5, 1, 1996800, 122.23),
-("crosshatch", 5, 1, 2092800, 143.54),
-("crosshatch", 5, 1, 2169600, 147.54),
-("crosshatch", 5, 1, 2246400, 153.09),
-("crosshatch", 5, 1, 2323200, 166.44),
-("crosshatch", 5, 1, 2400000, 184.69),
-("crosshatch", 5, 1, 2476800, 204.14),
-("crosshatch", 5, 1, 2553600, 223.37),
-("crosshatch", 5, 1, 2649600, 253.77),
-("crosshatch", 6, 1, 825600, 28.88),
-("crosshatch", 6, 1, 902400, 32.4),
-("crosshatch", 6, 1, 979200, 36.46),
-("crosshatch", 6, 1, 1056000, 39.99),
-("crosshatch", 6, 1, 1209600, 47.23),
-("crosshatch", 6, 1, 1286400, 51.39),
-("crosshatch", 6, 1, 1363200, 56.9),
-("crosshatch", 6, 1, 1459200, 64.26),
-("crosshatch", 6, 1, 1536000, 69.65),
-("crosshatch", 6, 1, 1612800, 75.14),
-("crosshatch", 6, 1, 1689600, 83.16),
-("crosshatch", 6, 1, 1766400, 91.75),
-("crosshatch", 6, 1, 1843200, 100.66),
-("crosshatch", 6, 1, 1920000, 111.45),
-("crosshatch", 6, 1, 1996800, 122.23),
-("crosshatch", 6, 1, 2092800, 143.54),
-("crosshatch", 6, 1, 2169600, 147.54),
-("crosshatch", 6, 1, 2246400, 153.09),
-("crosshatch", 6, 1, 2323200, 166.44),
-("crosshatch", 6, 1, 2400000, 184.69),
-("crosshatch", 6, 1, 2476800, 204.14),
-("crosshatch", 6, 1, 2553600, 223.37),
-("crosshatch", 6, 1, 2649600, 253.77),
-("crosshatch", 7, 1, 825600, 28.88),
-("crosshatch", 7, 1, 902400, 32.4),
-("crosshatch", 7, 1, 979200, 36.46),
-("crosshatch", 7, 1, 1056000, 39.99),
-("crosshatch", 7, 1, 1209600, 47.23),
-("crosshatch", 7, 1, 1286400, 51.39),
-("crosshatch", 7, 1, 1363200, 56.9),
-("crosshatch", 7, 1, 1459200, 64.26),
-("crosshatch", 7, 1, 1536000, 69.65),
-("crosshatch", 7, 1, 1612800, 75.14),
-("crosshatch", 7, 1, 1689600, 83.16),
-("crosshatch", 7, 1, 1766400, 91.75),
-("crosshatch", 7, 1, 1843200, 100.66),
-("crosshatch", 7, 1, 1920000, 111.45),
-("crosshatch", 7, 1, 1996800, 122.23),
-("crosshatch", 7, 1, 2092800, 143.54),
-("crosshatch", 7, 1, 2169600, 147.54),
-("crosshatch", 7, 1, 2246400, 153.09),
-("crosshatch", 7, 1, 2323200, 166.44),
-("crosshatch", 7, 1, 2400000, 184.69),
-("crosshatch", 7, 1, 2476800, 204.14),
-("crosshatch", 7, 1, 2553600, 223.37),
-("crosshatch", 7, 1, 2649600, 253.77),
-("blueline", 0, 0, 300000, 2.27),
-("blueline", 0, 0, 403200, 3.63),
-("blueline", 0, 0, 480000, 4.36),
-("blueline", 0, 0, 576000, 5.21),
-("blueline", 0, 0, 652800, 5.47),
-("blueline", 0, 0, 748800, 6.74),
-("blueline", 0, 0, 825600, 7.69),
-("blueline", 0, 0, 902400, 8.57),
-("blueline", 0, 0, 979200, 9.42),
-("blueline", 0, 0, 1056000, 10.41),
-("blueline", 0, 0, 1132800, 11.56),
-("blueline", 0, 0, 1228800, 12.87),
-("blueline", 0, 0, 1324800, 14.61),
-("blueline", 0, 0, 1420800, 16.49),
-("blueline", 0, 0, 1516800, 18.9),
-("blueline", 0, 0, 1612800, 21.62),
-("blueline", 0, 0, 1689600, 24.47),
-("blueline", 0, 0, 1766400, 26.45),
-("blueline", 1, 0, 300000, 2.27),
-("blueline", 1, 0, 403200, 3.63),
-("blueline", 1, 0, 480000, 4.36),
-("blueline", 1, 0, 576000, 5.21),
-("blueline", 1, 0, 652800, 5.47),
-("blueline", 1, 0, 748800, 6.74),
-("blueline", 1, 0, 825600, 7.69),
-("blueline", 1, 0, 902400, 8.57),
-("blueline", 1, 0, 979200, 9.42),
-("blueline", 1, 0, 1056000, 10.41),
-("blueline", 1, 0, 1132800, 11.56),
-("blueline", 1, 0, 1228800, 12.87),
-("blueline", 1, 0, 1324800, 14.61),
-("blueline", 1, 0, 1420800, 16.49),
-("blueline", 1, 0, 1516800, 18.9),
-("blueline", 1, 0, 1612800, 21.62),
-("blueline", 1, 0, 1689600, 24.47),
-("blueline", 1, 0, 1766400, 26.45),
-("blueline", 2, 0, 300000, 2.27),
-("blueline", 2, 0, 403200, 3.63),
-("blueline", 2, 0, 480000, 4.36),
-("blueline", 2, 0, 576000, 5.21),
-("blueline", 2, 0, 652800, 5.47),
-("blueline", 2, 0, 748800, 6.74),
-("blueline", 2, 0, 825600, 7.69),
-("blueline", 2, 0, 902400, 8.57),
-("blueline", 2, 0, 979200, 9.42),
-("blueline", 2, 0, 1056000, 10.41),
-("blueline", 2, 0, 1132800, 11.56),
-("blueline", 2, 0, 1228800, 12.87),
-("blueline", 2, 0, 1324800, 14.61),
-("blueline", 2, 0, 1420800, 16.49),
-("blueline", 2, 0, 1516800, 18.9),
-("blueline", 2, 0, 1612800, 21.62),
-("blueline", 2, 0, 1689600, 24.47),
-("blueline", 2, 0, 1766400, 26.45),
-("blueline", 3, 0, 300000, 2.27),
-("blueline", 3, 0, 403200, 3.63),
-("blueline", 3, 0, 480000, 4.36),
-("blueline", 3, 0, 576000, 5.21),
-("blueline", 3, 0, 652800, 5.47),
-("blueline", 3, 0, 748800, 6.74),
-("blueline", 3, 0, 825600, 7.69),
-("blueline", 3, 0, 902400, 8.57),
-("blueline", 3, 0, 979200, 9.42),
-("blueline", 3, 0, 1056000, 10.41),
-("blueline", 3, 0, 1132800, 11.56),
-("blueline", 3, 0, 1228800, 12.87),
-("blueline", 3, 0, 1324800, 14.61),
-("blueline", 3, 0, 1420800, 16.49),
-("blueline", 3, 0, 1516800, 18.9),
-("blueline", 3, 0, 1612800, 21.62),
-("blueline", 3, 0, 1689600, 24.47),
-("blueline", 3, 0, 1766400, 26.45),
-("blueline", 4, 1, 825600, 28.88),
-("blueline", 4, 1, 902400, 32.4),
-("blueline", 4, 1, 979200, 36.46),
-("blueline", 4, 1, 1056000, 39.99),
-("blueline", 4, 1, 1209600, 47.23),
-("blueline", 4, 1, 1286400, 51.39),
-("blueline", 4, 1, 1363200, 56.9),
-("blueline", 4, 1, 1459200, 64.26),
-("blueline", 4, 1, 1536000, 69.65),
-("blueline", 4, 1, 1612800, 75.14),
-("blueline", 4, 1, 1689600, 83.16),
-("blueline", 4, 1, 1766400, 91.75),
-("blueline", 4, 1, 1843200, 100.66),
-("blueline", 4, 1, 1920000, 111.45),
-("blueline", 4, 1, 1996800, 122.23),
-("blueline", 4, 1, 2092800, 143.54),
-("blueline", 4, 1, 2169600, 147.54),
-("blueline", 4, 1, 2246400, 153.09),
-("blueline", 4, 1, 2323200, 166.44),
-("blueline", 4, 1, 2400000, 184.69),
-("blueline", 4, 1, 2476800, 204.14),
-("blueline", 4, 1, 2553600, 223.37),
-("blueline", 4, 1, 2649600, 253.77),
-("blueline", 5, 1, 825600, 28.88),
-("blueline", 5, 1, 902400, 32.4),
-("blueline", 5, 1, 979200, 36.46),
-("blueline", 5, 1, 1056000, 39.99),
-("blueline", 5, 1, 1209600, 47.23),
-("blueline", 5, 1, 1286400, 51.39),
-("blueline", 5, 1, 1363200, 56.9),
-("blueline", 5, 1, 1459200, 64.26),
-("blueline", 5, 1, 1536000, 69.65),
-("blueline", 5, 1, 1612800, 75.14),
-("blueline", 5, 1, 1689600, 83.16),
-("blueline", 5, 1, 1766400, 91.75),
-("blueline", 5, 1, 1843200, 100.66),
-("blueline", 5, 1, 1920000, 111.45),
-("blueline", 5, 1, 1996800, 122.23),
-("blueline", 5, 1, 2092800, 143.54),
-("blueline", 5, 1, 2169600, 147.54),
-("blueline", 5, 1, 2246400, 153.09),
-("blueline", 5, 1, 2323200, 166.44),
-("blueline", 5, 1, 2400000, 184.69),
-("blueline", 5, 1, 2476800, 204.14),
-("blueline", 5, 1, 2553600, 223.37),
-("blueline", 5, 1, 2649600, 253.77),
-("blueline", 6, 1, 825600, 28.88),
-("blueline", 6, 1, 902400, 32.4),
-("blueline", 6, 1, 979200, 36.46),
-("blueline", 6, 1, 1056000, 39.99),
-("blueline", 6, 1, 1209600, 47.23),
-("blueline", 6, 1, 1286400, 51.39),
-("blueline", 6, 1, 1363200, 56.9),
-("blueline", 6, 1, 1459200, 64.26),
-("blueline", 6, 1, 1536000, 69.65),
-("blueline", 6, 1, 1612800, 75.14),
-("blueline", 6, 1, 1689600, 83.16),
-("blueline", 6, 1, 1766400, 91.75),
-("blueline", 6, 1, 1843200, 100.66),
-("blueline", 6, 1, 1920000, 111.45),
-("blueline", 6, 1, 1996800, 122.23),
-("blueline", 6, 1, 2092800, 143.54),
-("blueline", 6, 1, 2169600, 147.54),
-("blueline", 6, 1, 2246400, 153.09),
-("blueline", 6, 1, 2323200, 166.44),
-("blueline", 6, 1, 2400000, 184.69),
-("blueline", 6, 1, 2476800, 204.14),
-("blueline", 6, 1, 2553600, 223.37),
-("blueline", 6, 1, 2649600, 253.77),
-("blueline", 7, 1, 825600, 28.88),
-("blueline", 7, 1, 902400, 32.4),
-("blueline", 7, 1, 979200, 36.46),
-("blueline", 7, 1, 1056000, 39.99),
-("blueline", 7, 1, 1209600, 47.23),
-("blueline", 7, 1, 1286400, 51.39),
-("blueline", 7, 1, 1363200, 56.9),
-("blueline", 7, 1, 1459200, 64.26),
-("blueline", 7, 1, 1536000, 69.65),
-("blueline", 7, 1, 1612800, 75.14),
-("blueline", 7, 1, 1689600, 83.16),
-("blueline", 7, 1, 1766400, 91.75),
-("blueline", 7, 1, 1843200, 100.66),
-("blueline", 7, 1, 1920000, 111.45),
-("blueline", 7, 1, 1996800, 122.23),
-("blueline", 7, 1, 2092800, 143.54),
-("blueline", 7, 1, 2169600, 147.54),
-("blueline", 7, 1, 2246400, 153.09),
-("blueline", 7, 1, 2323200, 166.44),
-("blueline", 7, 1, 2400000, 184.69),
-("blueline", 7, 1, 2476800, 204.14),
-("blueline", 7, 1, 2553600, 223.37),
-("blueline", 7, 1, 2649600, 253.77),
-("bonito", 0, 0, 300000, 15.2466666667),
-("bonito", 0, 0, 576000, 18.2166666667),
-("bonito", 0, 0, 748800, 20.1866666667),
-("bonito", 0, 0, 998400, 23.29),
-("bonito", 0, 0, 1209600, 25.0116666667),
-("bonito", 0, 0, 1324800, 28.485),
-("bonito", 0, 0, 1516800, 31.6866666667),
-("bonito", 0, 0, 1708800, 35.79),
-("bonito", 1, 0, 300000, 15.2466666667),
-("bonito", 1, 0, 576000, 18.2166666667),
-("bonito", 1, 0, 748800, 20.1866666667),
-("bonito", 1, 0, 998400, 23.29),
-("bonito", 1, 0, 1209600, 25.0116666667),
-("bonito", 1, 0, 1324800, 28.485),
-("bonito", 1, 0, 1516800, 31.6866666667),
-("bonito", 1, 0, 1708800, 35.79),
-("bonito", 2, 0, 300000, 15.2466666667),
-("bonito", 2, 0, 576000, 18.2166666667),
-("bonito", 2, 0, 748800, 20.1866666667),
-("bonito", 2, 0, 998400, 23.29),
-("bonito", 2, 0, 1209600, 25.0116666667),
-("bonito", 2, 0, 1324800, 28.485),
-("bonito", 2, 0, 1516800, 31.6866666667),
-("bonito", 2, 0, 1708800, 35.79),
-("bonito", 3, 0, 300000, 15.2466666667),
-("bonito", 3, 0, 576000, 18.2166666667),
-("bonito", 3, 0, 748800, 20.1866666667),
-("bonito", 3, 0, 998400, 23.29),
-("bonito", 3, 0, 1209600, 25.0116666667),
-("bonito", 3, 0, 1324800, 28.485),
-("bonito", 3, 0, 1516800, 31.6866666667),
-("bonito", 3, 0, 1708800, 35.79),
-("bonito", 4, 0, 300000, 15.2466666667),
-("bonito", 4, 0, 576000, 18.2166666667),
-("bonito", 4, 0, 748800, 20.1866666667),
-("bonito", 4, 0, 998400, 23.29),
-("bonito", 4, 0, 1209600, 25.0116666667),
-("bonito", 4, 0, 1324800, 28.485),
-("bonito", 4, 0, 1516800, 31.6866666667),
-("bonito", 4, 0, 1708800, 35.79),
-("bonito", 5, 0, 300000, 15.2466666667),
-("bonito", 5, 0, 576000, 18.2166666667),
-("bonito", 5, 0, 748800, 20.1866666667),
-("bonito", 5, 0, 998400, 23.29),
-("bonito", 5, 0, 1209600, 25.0116666667),
-("bonito", 5, 0, 1324800, 28.485),
-("bonito", 5, 0, 1516800, 31.6866666667),
-("bonito", 5, 0, 1708800, 35.79),
-("bonito", 6, 1, 300000, 24.06),
-("bonito", 6, 1, 652800, 27.56),
-("bonito", 6, 1, 825600, 29.0),
-("bonito", 6, 1, 979200, 31.675),
-("bonito", 6, 1, 1132800, 34.53),
-("bonito", 6, 1, 1363200, 38.885),
-("bonito", 6, 1, 1536000, 43.075),
-("bonito", 6, 1, 1747200, 48.705),
-("bonito", 6, 1, 1843200, 64.57),
-("bonito", 6, 1, 1996800, 69.805),
-("bonito", 6, 1, 2016000, 76.545),
-("bonito", 7, 1, 300000, 24.06),
-("bonito", 7, 1, 652800, 27.56),
-("bonito", 7, 1, 825600, 29.0),
-("bonito", 7, 1, 979200, 31.675),
-("bonito", 7, 1, 1132800, 34.53),
-("bonito", 7, 1, 1363200, 38.885),
-("bonito", 7, 1, 1536000, 43.075),
-("bonito", 7, 1, 1747200, 48.705),
-("bonito", 7, 1, 1843200, 64.57),
-("bonito", 7, 1, 1996800, 69.805),
-("bonito", 7, 1, 2016000, 76.545),
-("sargo", 0, 0, 300000, 15.2466666667),
-("sargo", 0, 0, 576000, 18.2166666667),
-("sargo", 0, 0, 748800, 20.1866666667),
-("sargo", 0, 0, 998400, 23.29),
-("sargo", 0, 0, 1209600, 25.0116666667),
-("sargo", 0, 0, 1324800, 28.485),
-("sargo", 0, 0, 1516800, 31.6866666667),
-("sargo", 0, 0, 1708800, 35.79),
-("sargo", 1, 0, 300000, 15.2466666667),
-("sargo", 1, 0, 576000, 18.2166666667),
-("sargo", 1, 0, 748800, 20.1866666667),
-("sargo", 1, 0, 998400, 23.29),
-("sargo", 1, 0, 1209600, 25.0116666667),
-("sargo", 1, 0, 1324800, 28.485),
-("sargo", 1, 0, 1516800, 31.6866666667),
-("sargo", 1, 0, 1708800, 35.79),
-("sargo", 2, 0, 300000, 15.2466666667),
-("sargo", 2, 0, 576000, 18.2166666667),
-("sargo", 2, 0, 748800, 20.1866666667),
-("sargo", 2, 0, 998400, 23.29),
-("sargo", 2, 0, 1209600, 25.0116666667),
-("sargo", 2, 0, 1324800, 28.485),
-("sargo", 2, 0, 1516800, 31.6866666667),
-("sargo", 2, 0, 1708800, 35.79),
-("sargo", 3, 0, 300000, 15.2466666667),
-("sargo", 3, 0, 576000, 18.2166666667),
-("sargo", 3, 0, 748800, 20.1866666667),
-("sargo", 3, 0, 998400, 23.29),
-("sargo", 3, 0, 1209600, 25.0116666667),
-("sargo", 3, 0, 1324800, 28.485),
-("sargo", 3, 0, 1516800, 31.6866666667),
-("sargo", 3, 0, 1708800, 35.79),
-("sargo", 4, 0, 300000, 15.2466666667),
-("sargo", 4, 0, 576000, 18.2166666667),
-("sargo", 4, 0, 748800, 20.1866666667),
-("sargo", 4, 0, 998400, 23.29),
-("sargo", 4, 0, 1209600, 25.0116666667),
-("sargo", 4, 0, 1324800, 28.485),
-("sargo", 4, 0, 1516800, 31.6866666667),
-("sargo", 4, 0, 1708800, 35.79),
-("sargo", 5, 0, 300000, 15.2466666667),
-("sargo", 5, 0, 576000, 18.2166666667),
-("sargo", 5, 0, 748800, 20.1866666667),
-("sargo", 5, 0, 998400, 23.29),
-("sargo", 5, 0, 1209600, 25.0116666667),
-("sargo", 5, 0, 1324800, 28.485),
-("sargo", 5, 0, 1516800, 31.6866666667),
-("sargo", 5, 0, 1708800, 35.79),
-("sargo", 6, 1, 300000, 24.06),
-("sargo", 6, 1, 652800, 27.56),
-("sargo", 6, 1, 825600, 29.0),
-("sargo", 6, 1, 979200, 31.675),
-("sargo", 6, 1, 1132800, 34.53),
-("sargo", 6, 1, 1363200, 38.885),
-("sargo", 6, 1, 1536000, 43.075),
-("sargo", 6, 1, 1747200, 48.705),
-("sargo", 6, 1, 1843200, 64.57),
-("sargo", 6, 1, 1996800, 69.805),
-("sargo", 6, 1, 2016000, 76.545),
-("sargo", 7, 1, 300000, 24.06),
-("sargo", 7, 1, 652800, 27.56),
-("sargo", 7, 1, 825600, 29.0),
-("sargo", 7, 1, 979200, 31.675),
-("sargo", 7, 1, 1132800, 34.53),
-("sargo", 7, 1, 1363200, 38.885),
-("sargo", 7, 1, 1536000, 43.075),
-("sargo", 7, 1, 1747200, 48.705),
-("sargo", 7, 1, 1843200, 64.57),
-("sargo", 7, 1, 1996800, 69.805),
-("sargo", 7, 1, 2016000, 76.545),
-("coral", 0, 0, 300000, 9.86),
-("coral", 0, 0, 403200, 10.335),
-("coral", 0, 0, 499200, 10.8925),
-("coral", 0, 0, 576000, 11.37),
-("coral", 0, 0, 672000, 11.8),
-("coral", 0, 0, 768000, 12.41),
-("coral", 0, 0, 844800, 12.97),
-("coral", 0, 0, 940800, 13.335),
-("coral", 0, 0, 1036800, 14.1725),
-("coral", 0, 0, 1113600, 14.695),
-("coral", 0, 0, 1209600, 15.3525),
-("coral", 0, 0, 1305600, 16.2775),
-("coral", 0, 0, 1382400, 16.8725),
-("coral", 0, 0, 1478400, 17.6525),
-("coral", 0, 0, 1555200, 18.0975),
-("coral", 0, 0, 1632000, 18.8575),
-("coral", 0, 0, 1708800, 20.0525),
-("coral", 0, 0, 1785600, 21.2625),
-("coral", 1, 0, 300000, 9.86),
-("coral", 1, 0, 403200, 10.335),
-("coral", 1, 0, 499200, 10.8925),
-("coral", 1, 0, 576000, 11.37),
-("coral", 1, 0, 672000, 11.8),
-("coral", 1, 0, 768000, 12.41),
-("coral", 1, 0, 844800, 12.97),
-("coral", 1, 0, 940800, 13.335),
-("coral", 1, 0, 1036800, 14.1725),
-("coral", 1, 0, 1113600, 14.695),
-("coral", 1, 0, 1209600, 15.3525),
-("coral", 1, 0, 1305600, 16.2775),
-("coral", 1, 0, 1382400, 16.8725),
-("coral", 1, 0, 1478400, 17.6525),
-("coral", 1, 0, 1555200, 18.0975),
-("coral", 1, 0, 1632000, 18.8575),
-("coral", 1, 0, 1708800, 20.0525),
-("coral", 1, 0, 1785600, 21.2625),
-("coral", 2, 0, 300000, 9.86),
-("coral", 2, 0, 403200, 10.335),
-("coral", 2, 0, 499200, 10.8925),
-("coral", 2, 0, 576000, 11.37),
-("coral", 2, 0, 672000, 11.8),
-("coral", 2, 0, 768000, 12.41),
-("coral", 2, 0, 844800, 12.97),
-("coral", 2, 0, 940800, 13.335),
-("coral", 2, 0, 1036800, 14.1725),
-("coral", 2, 0, 1113600, 14.695),
-("coral", 2, 0, 1209600, 15.3525),
-("coral", 2, 0, 1305600, 16.2775),
-("coral", 2, 0, 1382400, 16.8725),
-("coral", 2, 0, 1478400, 17.6525),
-("coral", 2, 0, 1555200, 18.0975),
-("coral", 2, 0, 1632000, 18.8575),
-("coral", 2, 0, 1708800, 20.0525),
-("coral", 2, 0, 1785600, 21.2625),
-("coral", 3, 0, 300000, 9.86),
-("coral", 3, 0, 403200, 10.335),
-("coral", 3, 0, 499200, 10.8925),
-("coral", 3, 0, 576000, 11.37),
-("coral", 3, 0, 672000, 11.8),
-("coral", 3, 0, 768000, 12.41),
-("coral", 3, 0, 844800, 12.97),
-("coral", 3, 0, 940800, 13.335),
-("coral", 3, 0, 1036800, 14.1725),
-("coral", 3, 0, 1113600, 14.695),
-("coral", 3, 0, 1209600, 15.3525),
-("coral", 3, 0, 1305600, 16.2775),
-("coral", 3, 0, 1382400, 16.8725),
-("coral", 3, 0, 1478400, 17.6525),
-("coral", 3, 0, 1555200, 18.0975),
-("coral", 3, 0, 1632000, 18.8575),
-("coral", 3, 0, 1708800, 20.0525),
-("coral", 3, 0, 1785600, 21.2625),
-("coral", 4, 1, 710400, 16.7833333333),
-("coral", 4, 1, 825600, 18.3733333333),
-("coral", 4, 1, 940800, 20.4833333333),
-("coral", 4, 1, 1056000, 23.3066666667),
-("coral", 4, 1, 1171200, 25.8266666667),
-("coral", 4, 1, 1286400, 28.45),
-("coral", 4, 1, 1401600, 31.7233333333),
-("coral", 4, 1, 1497600, 34.42),
-("coral", 4, 1, 1612800, 39.3966666667),
-("coral", 4, 1, 1708800, 44.24),
-("coral", 4, 1, 1804800, 47.9433333333),
-("coral", 4, 1, 1920000, 51.97),
-("coral", 4, 1, 2016000, 63.3866666667),
-("coral", 4, 1, 2131200, 71.0366666667),
-("coral", 4, 1, 2227200, 79.32),
-("coral", 4, 1, 2323200, 88.99),
-("coral", 4, 1, 2419200, 100.68),
-("coral", 5, 1, 710400, 16.7833333333),
-("coral", 5, 1, 825600, 18.3733333333),
-("coral", 5, 1, 940800, 20.4833333333),
-("coral", 5, 1, 1056000, 23.3066666667),
-("coral", 5, 1, 1171200, 25.8266666667),
-("coral", 5, 1, 1286400, 28.45),
-("coral", 5, 1, 1401600, 31.7233333333),
-("coral", 5, 1, 1497600, 34.42),
-("coral", 5, 1, 1612800, 39.3966666667),
-("coral", 5, 1, 1708800, 44.24),
-("coral", 5, 1, 1804800, 47.9433333333),
-("coral", 5, 1, 1920000, 51.97),
-("coral", 5, 1, 2016000, 63.3866666667),
-("coral", 5, 1, 2131200, 71.0366666667),
-("coral", 5, 1, 2227200, 79.32),
-("coral", 5, 1, 2323200, 88.99),
-("coral", 5, 1, 2419200, 100.68),
-("coral", 6, 1, 710400, 16.7833333333),
-("coral", 6, 1, 825600, 18.3733333333),
-("coral", 6, 1, 940800, 20.4833333333),
-("coral", 6, 1, 1056000, 23.3066666667),
-("coral", 6, 1, 1171200, 25.8266666667),
-("coral", 6, 1, 1286400, 28.45),
-("coral", 6, 1, 1401600, 31.7233333333),
-("coral", 6, 1, 1497600, 34.42),
-("coral", 6, 1, 1612800, 39.3966666667),
-("coral", 6, 1, 1708800, 44.24),
-("coral", 6, 1, 1804800, 47.9433333333),
-("coral", 6, 1, 1920000, 51.97),
-("coral", 6, 1, 2016000, 63.3866666667),
-("coral", 6, 1, 2131200, 71.0366666667),
-("coral", 6, 1, 2227200, 79.32),
-("coral", 6, 1, 2323200, 88.99),
-("coral", 6, 1, 2419200, 100.68),
-("coral", 7, 2, 825600, 52.7),
-("coral", 7, 2, 940800, 55.9),
-("coral", 7, 2, 1056000, 59.73),
-("coral", 7, 2, 1171200, 63.66),
-("coral", 7, 2, 1286400, 67.28),
-("coral", 7, 2, 1401600, 71.66),
-("coral", 7, 2, 1497600, 76.47),
-("coral", 7, 2, 1612800, 80.92),
-("coral", 7, 2, 1708800, 85.81),
-("coral", 7, 2, 1804800, 93.19),
-("coral", 7, 2, 1920000, 98.06),
-("coral", 7, 2, 2016000, 119.08),
-("coral", 7, 2, 2131200, 127.88),
-("coral", 7, 2, 2227200, 129.85),
-("coral", 7, 2, 2323200, 140.37),
-("coral", 7, 2, 2419200, 151.22),
-("coral", 7, 2, 2534400, 160.73),
-("coral", 7, 2, 2649600, 175.5),
-("coral", 7, 2, 2745600, 186.29),
-("coral", 7, 2, 2841600, 223.89),
-("flame", 0, 0, 300000, 9.86),
-("flame", 0, 0, 403200, 10.335),
-("flame", 0, 0, 499200, 10.8925),
-("flame", 0, 0, 576000, 11.37),
-("flame", 0, 0, 672000, 11.8),
-("flame", 0, 0, 768000, 12.41),
-("flame", 0, 0, 844800, 12.97),
-("flame", 0, 0, 940800, 13.335),
-("flame", 0, 0, 1036800, 14.1725),
-("flame", 0, 0, 1113600, 14.695),
-("flame", 0, 0, 1209600, 15.3525),
-("flame", 0, 0, 1305600, 16.2775),
-("flame", 0, 0, 1382400, 16.8725),
-("flame", 0, 0, 1478400, 17.6525),
-("flame", 0, 0, 1555200, 18.0975),
-("flame", 0, 0, 1632000, 18.8575),
-("flame", 0, 0, 1708800, 20.0525),
-("flame", 0, 0, 1785600, 21.2625),
-("flame", 1, 0, 300000, 9.86),
-("flame", 1, 0, 403200, 10.335),
-("flame", 1, 0, 499200, 10.8925),
-("flame", 1, 0, 576000, 11.37),
-("flame", 1, 0, 672000, 11.8),
-("flame", 1, 0, 768000, 12.41),
-("flame", 1, 0, 844800, 12.97),
-("flame", 1, 0, 940800, 13.335),
-("flame", 1, 0, 1036800, 14.1725),
-("flame", 1, 0, 1113600, 14.695),
-("flame", 1, 0, 1209600, 15.3525),
-("flame", 1, 0, 1305600, 16.2775),
-("flame", 1, 0, 1382400, 16.8725),
-("flame", 1, 0, 1478400, 17.6525),
-("flame", 1, 0, 1555200, 18.0975),
-("flame", 1, 0, 1632000, 18.8575),
-("flame", 1, 0, 1708800, 20.0525),
-("flame", 1, 0, 1785600, 21.2625),
-("flame", 2, 0, 300000, 9.86),
-("flame", 2, 0, 403200, 10.335),
-("flame", 2, 0, 499200, 10.8925),
-("flame", 2, 0, 576000, 11.37),
-("flame", 2, 0, 672000, 11.8),
-("flame", 2, 0, 768000, 12.41),
-("flame", 2, 0, 844800, 12.97),
-("flame", 2, 0, 940800, 13.335),
-("flame", 2, 0, 1036800, 14.1725),
-("flame", 2, 0, 1113600, 14.695),
-("flame", 2, 0, 1209600, 15.3525),
-("flame", 2, 0, 1305600, 16.2775),
-("flame", 2, 0, 1382400, 16.8725),
-("flame", 2, 0, 1478400, 17.6525),
-("flame", 2, 0, 1555200, 18.0975),
-("flame", 2, 0, 1632000, 18.8575),
-("flame", 2, 0, 1708800, 20.0525),
-("flame", 2, 0, 1785600, 21.2625),
-("flame", 3, 0, 300000, 9.86),
-("flame", 3, 0, 403200, 10.335),
-("flame", 3, 0, 499200, 10.8925),
-("flame", 3, 0, 576000, 11.37),
-("flame", 3, 0, 672000, 11.8),
-("flame", 3, 0, 768000, 12.41),
-("flame", 3, 0, 844800, 12.97),
-("flame", 3, 0, 940800, 13.335),
-("flame", 3, 0, 1036800, 14.1725),
-("flame", 3, 0, 1113600, 14.695),
-("flame", 3, 0, 1209600, 15.3525),
-("flame", 3, 0, 1305600, 16.2775),
-("flame", 3, 0, 1382400, 16.8725),
-("flame", 3, 0, 1478400, 17.6525),
-("flame", 3, 0, 1555200, 18.0975),
-("flame", 3, 0, 1632000, 18.8575),
-("flame", 3, 0, 1708800, 20.0525),
-("flame", 3, 0, 1785600, 21.2625),
-("flame", 4, 1, 710400, 16.7833333333),
-("flame", 4, 1, 825600, 18.3733333333),
-("flame", 4, 1, 940800, 20.4833333333),
-("flame", 4, 1, 1056000, 23.3066666667),
-("flame", 4, 1, 1171200, 25.8266666667),
-("flame", 4, 1, 1286400, 28.45),
-("flame", 4, 1, 1401600, 31.7233333333),
-("flame", 4, 1, 1497600, 34.42),
-("flame", 4, 1, 1612800, 39.3966666667),
-("flame", 4, 1, 1708800, 44.24),
-("flame", 4, 1, 1804800, 47.9433333333),
-("flame", 4, 1, 1920000, 51.97),
-("flame", 4, 1, 2016000, 63.3866666667),
-("flame", 4, 1, 2131200, 71.0366666667),
-("flame", 4, 1, 2227200, 79.32),
-("flame", 4, 1, 2323200, 88.99),
-("flame", 4, 1, 2419200, 100.68),
-("flame", 5, 1, 710400, 16.7833333333),
-("flame", 5, 1, 825600, 18.3733333333),
-("flame", 5, 1, 940800, 20.4833333333),
-("flame", 5, 1, 1056000, 23.3066666667),
-("flame", 5, 1, 1171200, 25.8266666667),
-("flame", 5, 1, 1286400, 28.45),
-("flame", 5, 1, 1401600, 31.7233333333),
-("flame", 5, 1, 1497600, 34.42),
-("flame", 5, 1, 1612800, 39.3966666667),
-("flame", 5, 1, 1708800, 44.24),
-("flame", 5, 1, 1804800, 47.9433333333),
-("flame", 5, 1, 1920000, 51.97),
-("flame", 5, 1, 2016000, 63.3866666667),
-("flame", 5, 1, 2131200, 71.0366666667),
-("flame", 5, 1, 2227200, 79.32),
-("flame", 5, 1, 2323200, 88.99),
-("flame", 5, 1, 2419200, 100.68),
-("flame", 6, 1, 710400, 16.7833333333),
-("flame", 6, 1, 825600, 18.3733333333),
-("flame", 6, 1, 940800, 20.4833333333),
-("flame", 6, 1, 1056000, 23.3066666667),
-("flame", 6, 1, 1171200, 25.8266666667),
-("flame", 6, 1, 1286400, 28.45),
-("flame", 6, 1, 1401600, 31.7233333333),
-("flame", 6, 1, 1497600, 34.42),
-("flame", 6, 1, 1612800, 39.3966666667),
-("flame", 6, 1, 1708800, 44.24),
-("flame", 6, 1, 1804800, 47.9433333333),
-("flame", 6, 1, 1920000, 51.97),
-("flame", 6, 1, 2016000, 63.3866666667),
-("flame", 6, 1, 2131200, 71.0366666667),
-("flame", 6, 1, 2227200, 79.32),
-("flame", 6, 1, 2323200, 88.99),
-("flame", 6, 1, 2419200, 100.68),
-("flame", 7, 2, 825600, 52.7),
-("flame", 7, 2, 940800, 55.9),
-("flame", 7, 2, 1056000, 59.73),
-("flame", 7, 2, 1171200, 63.66),
-("flame", 7, 2, 1286400, 67.28),
-("flame", 7, 2, 1401600, 71.66),
-("flame", 7, 2, 1497600, 76.47),
-("flame", 7, 2, 1612800, 80.92),
-("flame", 7, 2, 1708800, 85.81),
-("flame", 7, 2, 1804800, 93.19),
-("flame", 7, 2, 1920000, 98.06),
-("flame", 7, 2, 2016000, 119.08),
-("flame", 7, 2, 2131200, 127.88),
-("flame", 7, 2, 2227200, 129.85),
-("flame", 7, 2, 2323200, 140.37),
-("flame", 7, 2, 2419200, 151.22),
-("flame", 7, 2, 2534400, 160.73),
-("flame", 7, 2, 2649600, 175.5),
-("flame", 7, 2, 2745600, 186.29),
-("flame", 7, 2, 2841600, 223.89);
diff --git a/src/trace_processor/metrics/android/process_counter_span_view.sql b/src/trace_processor/metrics/android/process_counter_span_view.sql
index f1f8493..2853f62 100644
--- a/src/trace_processor/metrics/android/process_counter_span_view.sql
+++ b/src/trace_processor/metrics/android/process_counter_span_view.sql
@@ -14,8 +14,7 @@
 -- limitations under the License.
 --
 
-DROP VIEW IF EXISTS {{table_name}}_span;
-CREATE VIEW {{table_name}}_span AS
+CREATE VIEW IF NOT EXISTS {{table_name}}_span AS
 SELECT
   ts,
   LEAD(ts, 1, (
diff --git a/src/trace_processor/metrics/android/process_mem.sql b/src/trace_processor/metrics/android/process_mem.sql
index af2d726..ab0c50b 100644
--- a/src/trace_processor/metrics/android/process_mem.sql
+++ b/src/trace_processor/metrics/android/process_mem.sql
@@ -39,10 +39,12 @@
 
 -- 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,
@@ -51,6 +53,7 @@
 
 -- Anon RSS + file RSS + Swap
 DROP TABLE IF EXISTS anon_and_file_and_swap_join;
+
 CREATE VIRTUAL TABLE anon_and_file_and_swap_join
 USING SPAN_OUTER_JOIN(
   anon_and_swap_join PARTITIONED upid,
@@ -58,7 +61,9 @@
 );
 
 -- RSS + Swap
+
 DROP TABLE IF EXISTS rss_and_swap_join;
+
 CREATE VIRTUAL TABLE rss_and_swap_join
 USING SPAN_OUTER_JOIN(
   anon_and_file_and_swap_join PARTITIONED upid,
@@ -66,6 +71,7 @@
 );
 
 DROP VIEW IF EXISTS rss_and_swap_span;
+
 CREATE VIEW rss_and_swap_span AS
 SELECT
 ts, dur, upid,
@@ -86,26 +92,32 @@
   '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;
 
 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_metadata.sql b/src/trace_processor/metrics/android/process_metadata.sql
index 6e0e6d3..401948d 100644
--- a/src/trace_processor/metrics/android/process_metadata.sql
+++ b/src/trace_processor/metrics/android/process_metadata.sql
@@ -26,16 +26,7 @@
 CREATE TABLE process_metadata_table AS
 SELECT
   process.upid,
-  -- TODO(b/169226092) remove this workaround
-  CASE
-      -- cmdline gets rewritten after fork, if these are still there we must
-      -- have seen a racy capture.
-    WHEN length(process.name) = 15 AND (
-      process.cmdline in ('zygote', 'zygote64', '<pre-initialized>')
-      OR process.cmdline like '%' || process.name)
-    THEN process.cmdline
-    ELSE process.name
-  END AS process_name,
+  process.name AS process_name,
   process.android_appid AS uid,
   CASE WHEN uid_package_count.cnt > 1 THEN TRUE ELSE NULL END AS shared_uid,
   plist.package_name,
@@ -54,9 +45,7 @@
     OR process.name LIKE plist.package_name || '%')
   );
 
-DROP VIEW IF EXISTS process_metadata;
-
-CREATE VIEW process_metadata AS
+CREATE VIEW IF NOT EXISTS process_metadata AS
 WITH upid_packages AS (
   SELECT
   upid,
@@ -71,15 +60,15 @@
 )
 SELECT
   upid,
-  NULL_IF_EMPTY(AndroidProcessMetadata(
+  AndroidProcessMetadata(
     'name', process_name,
     'uid', uid,
-    'package', NULL_IF_EMPTY(AndroidProcessMetadata_Package(
+    'package', AndroidProcessMetadata_Package(
       'package_name', package_name,
       'apk_version_code', version_code,
       'debuggable', debuggable
-    )),
+    ),
     'packages_for_uid', packages_for_uid
-  )) AS metadata
+  ) AS metadata
 FROM process_metadata_table
 LEFT JOIN upid_packages USING (upid);
diff --git a/src/trace_processor/metrics/android/process_oom_score.sql b/src/trace_processor/metrics/android/process_oom_score.sql
index 3a53688..00812d4 100644
--- a/src/trace_processor/metrics/android/process_oom_score.sql
+++ b/src/trace_processor/metrics/android/process_oom_score.sql
@@ -15,8 +15,7 @@
 --
 
 -- Create a track for process OOM scores.
-DROP VIEW IF EXISTS oom_score_span;
-CREATE VIEW oom_score_span AS
+CREATE VIEW IF NOT EXISTS oom_score_span AS
 SELECT
   ts,
   LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
diff --git a/src/trace_processor/metrics/android/span_view_stats.sql b/src/trace_processor/metrics/android/span_view_stats.sql
index 5b83047..ff85408 100644
--- a/src/trace_processor/metrics/android/span_view_stats.sql
+++ b/src/trace_processor/metrics/android/span_view_stats.sql
@@ -15,6 +15,7 @@
 --
 
 DROP TABLE IF EXISTS {{table_name}}_stats;
+
 CREATE TABLE {{table_name}}_stats (
   process_name TEXT PRIMARY KEY,
   min_value REAL,
@@ -34,6 +35,7 @@
 ORDER BY 1;
 
 DROP VIEW IF EXISTS {{table_name}}_stats_proto;
+
 CREATE VIEW {{table_name}}_stats_proto AS
 SELECT
   process_name,
diff --git a/src/trace_processor/metrics/android/unmapped_java_symbols.sql b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
new file mode 100644
index 0000000..1b7f829
--- /dev/null
+++ b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
@@ -0,0 +1,81 @@
+--
+-- Copyright 2020 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     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_metadata.sql');
+
+CREATE TABLE IF NOT EXISTS types_per_upid AS
+WITH distinct_unmapped_type_names AS (
+  SELECT DISTINCT upid, type_name
+  FROM (
+    SELECT
+      upid,
+      RTRIM(REPLACE(c.name, 'java.lang.Class<', ''), '[]>') AS type_name
+    FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
+    WHERE c.deobfuscated_name IS NULL
+  )
+  WHERE type_name NOT IN ('byte', 'char', 'short', 'int', 'long', 'boolean', 'float', 'double')
+  AND type_name NOT LIKE '$Proxy%'
+  AND type_name NOT LIKE 'java.%'
+  AND type_name NOT LIKE 'javax.%'
+  AND type_name NOT LIKE 'j$.%'
+  AND type_name NOT LIKE 'android.%'
+  AND type_name NOT LIKE 'com.android.%'
+  AND type_name NOT LIKE 'sun.%'
+  AND type_name NOT LIKE 'dalvik.%'
+  AND type_name NOT LIKE 'libcore.%'
+  AND LENGTH(type_name) > 0
+)
+SELECT upid, RepeatedField(type_name) AS types
+FROM distinct_unmapped_type_names GROUP BY 1;
+
+CREATE TABLE IF NOT EXISTS fields_per_upid AS
+WITH distinct_unmapped_field_names AS (
+  SELECT DISTINCT o.upid, field_type_name, field_name
+    FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
+           JOIN heap_graph_reference USING (reference_set_id)
+  WHERE c.deobfuscated_name IS NULL
+  AND field_name NOT LIKE '$Proxy%'
+  AND field_name NOT LIKE 'java.%'
+  AND field_name NOT LIKE 'javax.%'
+  AND field_name NOT LIKE 'j$.%'
+  AND field_name NOT LIKE 'android.%'
+  AND field_name NOT LIKE 'com.android.%'
+  AND field_name NOT LIKE 'sun.%'
+  AND field_name NOT LIKE 'dalvik.%'
+  AND field_name NOT LIKE 'libcore.%'
+  AND LENGTH(field_name) > 0
+)
+SELECT upid, RepeatedField(
+  UnmappedJavaSymbols_Field(
+    'field_name', field_name,
+    'field_type_name', field_type_name)) AS fields
+FROM distinct_unmapped_field_names GROUP BY 1;
+
+CREATE VIEW IF NOT EXISTS java_symbols_per_process AS
+SELECT UnmappedJavaSymbols_ProcessSymbols(
+  'process_metadata', metadata,
+  'type_name', types,
+  'field', fields
+) types
+FROM types_per_upid
+JOIN process_metadata USING (upid)
+LEFT JOIN fields_per_upid USING (upid);
+
+CREATE VIEW unmapped_java_symbols_output AS
+SELECT UnmappedJavaSymbols(
+  'process_symbols',
+  (SELECT RepeatedField(types) FROM java_symbols_per_process)
+);
diff --git a/src/trace_processor/metrics/android/unsymbolized_frames.sql b/src/trace_processor/metrics/android/unsymbolized_frames.sql
index ed6046c..426beb7 100644
--- a/src/trace_processor/metrics/android/unsymbolized_frames.sql
+++ b/src/trace_processor/metrics/android/unsymbolized_frames.sql
@@ -14,7 +14,6 @@
 -- limitations under the License.
 --
 
-DROP VIEW IF EXISTS unsymbolized_frames_view;
 CREATE VIEW unsymbolized_frames_view AS
 SELECT UnsymbolizedFrames_Frame(
     'module', spm.name,
@@ -27,7 +26,6 @@
 WHERE spm.build_id != ''
 AND (spf.symbol_set_id == 0 OR spf.symbol_set_id IS NULL);
 
-DROP VIEW IF EXISTS unsymbolized_frames_output;
 CREATE VIEW unsymbolized_frames_output AS
 SELECT UnsymbolizedFrames(
   'frames',
diff --git a/src/trace_processor/metrics/chrome/actual_power_by_category.sql b/src/trace_processor/metrics/chrome/actual_power_by_category.sql
deleted file mode 100644
index 27b632e..0000000
--- a/src/trace_processor/metrics/chrome/actual_power_by_category.sql
+++ /dev/null
@@ -1,79 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
-
--- This is a templated metric that takes 3 parameters:
--- input: name of a table/view which must have columns: id, ts, dur and a
---   "category" column
--- output: name of the view that will be created
--- category: name of the category column in the input table, which will be
---   preserved in the output
-
-SELECT RUN_METRIC('chrome/chrome_processes.sql');
-SELECT RUN_METRIC('android/power_drain_in_watts.sql');
-
--- SPAN_JOIN does not yet support non-integer partitions so add an integer
--- column that corresponds to the power rail name.
-DROP TABLE IF EXISTS power_rail_name_mapping;
-CREATE TABLE power_rail_name_mapping AS
-SELECT DISTINCT name,
-  ROW_NUMBER() OVER() AS idx
-FROM drain_in_watts;
-
-DROP VIEW IF EXISTS mapped_drain_in_watts;
-CREATE VIEW mapped_drain_in_watts AS
-SELECT d.name, ts, dur, drain_w, idx
-FROM drain_in_watts d
-  JOIN power_rail_name_mapping p ON d.name = p.name;
-
-DROP TABLE IF EXISTS real_{{input}}_power;
-CREATE VIRTUAL TABLE real_{{input}}_power USING SPAN_JOIN(
-    {{input}},
-    mapped_drain_in_watts PARTITIONED idx
-);
-
--- Actual power usage for chrome across the categorised slices contained in the
--- input table broken down by subsystem.
-DROP VIEW IF EXISTS {{output}};
-CREATE VIEW {{output}} AS
-SELECT s.id,
-  ts,
-  dur,
-  {{category}},
-  subsystem,
-  joules,
-  joules / dur * 1e9 AS drain_w
-FROM (
-    SELECT id,
-      subsystem,
-      SUM(drain_w * dur / 1e9) AS joules
-    FROM real_{{input}}_power
-      JOIN power_counters
-    WHERE real_{{input}}_power.name = power_counters.name
-    GROUP BY id,
-      subsystem
-  ) p
-  JOIN {{input}} s
-WHERE s.id = p.id
-ORDER BY s.id;
-
-SELECT id,
-      subsystem,
-      SUM(drain_w * dur / 1e9) AS joules
-    FROM real_{{input}}_power
-      JOIN power_counters
-    WHERE real_{{input}}_power.name = power_counters.name
-    GROUP BY id,
-      subsystem
diff --git a/src/trace_processor/metrics/chrome/actual_power_by_rail_mode.sql b/src/trace_processor/metrics/chrome/actual_power_by_rail_mode.sql
deleted file mode 100644
index 901a07b..0000000
--- a/src/trace_processor/metrics/chrome/actual_power_by_rail_mode.sql
+++ /dev/null
@@ -1,26 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql');
-
--- Creates a view called real_power_by_rail_mode, containing the actual power
--- usage for chrome broken down by RAIL Mode (subdivided by subsystem).
-SELECT RUN_METRIC(
-    'chrome/actual_power_by_category.sql',
-    'input', 'combined_overall_rail_slices',
-    'output', 'real_power_by_rail_mode',
-    'category', 'rail_mode'
-  );
diff --git a/src/trace_processor/metrics/chrome/chrome_event_metadata.sql b/src/trace_processor/metrics/chrome/chrome_event_metadata.sql
deleted file mode 100644
index cc23004..0000000
--- a/src/trace_processor/metrics/chrome/chrome_event_metadata.sql
+++ /dev/null
@@ -1,39 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
-
--- Creates a view containing name-value pairs extracted from
--- chrome_event.metadata. Some names can have multiple values:
--- e.g. trace-category
-DROP VIEW IF EXISTS chrome_event_metadata;
-CREATE VIEW chrome_event_metadata AS
-WITH metadata (arg_set_id) AS (
-  SELECT arg_set_id
-  FROM raw
-  WHERE name = "chrome_event.metadata"
-)
--- TODO(b/173201788): Once this is fixed, extract all the fields.
-SELECT 'os-name' AS name,
-  EXTRACT_ARG(metadata.arg_set_id, 'os-name') AS value
-FROM metadata
-UNION
-SELECT "trace-category" AS name,
-  value AS category
-FROM metadata, json_each(
-    json_extract(
-      EXTRACT_ARG(metadata.arg_set_id, "trace-config"),
-      '$.included_categories'
-    )
-  );
diff --git a/src/trace_processor/metrics/chrome/chrome_processes.sql b/src/trace_processor/metrics/chrome/chrome_processes.sql
index dd3be51..9287082 100644
--- a/src/trace_processor/metrics/chrome/chrome_processes.sql
+++ b/src/trace_processor/metrics/chrome/chrome_processes.sql
@@ -14,115 +14,35 @@
 -- limitations under the License.
 --
 
--- Table to map any of the various chrome process names to a type (e.g. Browser,
--- Renderer, GPU Process, etc).
-DROP TABLE IF EXISTS chrome_process_name_type_mapping;
-CREATE TABLE chrome_process_name_type_mapping (
-  original_name_pattern TEXT UNIQUE,
-  type TEXT
-);
+-- A view of all Chrome processes.
+-- TODO(skyostil): Create this table in the trace processor internally so we
+-- can expose the process type.
+DROP VIEW IF EXISTS chrome_process;
 
-WITH prefix (value) AS (
+CREATE VIEW chrome_process AS
   SELECT *
-  FROM (
-      VALUES ("org.chromium.chrome"),
-        ("com.google.android.apps.chrome"),
-        ("com.android.chrome"),
-        ("com.chrome.beta"),
-        ("com.chrome.canary"),
-        ("com.chrome.dev")
-    )
-),
-suffix (value, TYPE) AS (
-  SELECT *
-  FROM (
-      VALUES ("", "Browser"),
-        (
-          ":sandboxed_process*:org.chromium.content.app.SandboxedProcessService*",
-          "Sandboxed"
-        ),
-        (":privileged_process*", "Privileged"),
-        ("_zygote", "Zygote")
-    )
-)
--- Insert the Chrome process names for a normal chrome trace
-INSERT INTO chrome_process_name_type_mapping
-VALUES ('Browser', 'Browser'),
-  ('Renderer', 'Renderer'),
-  ('GPU Process', 'Gpu'),
-  ('Gpu', 'Gpu'),
-  ('Zygote', 'Zygote'),
-  ('Utility', 'Utility'),
-  ('SandboxHelper', 'SandboxHelper'),
-  ('PpapiPlugin', 'PpapiPlugin'),
-  ('PpapiBroker', 'PpapiBroker')
-UNION ALL
--- Construct all the possible Chrome process names for an Android system chrome
--- trace.
-SELECT prefix.value || suffix.value AS name,
-  suffix.type AS type
-FROM prefix,
-  suffix;
-
--- Use GLOB here instead of LIKE as it's case-sensitive which means we don't
--- match the Android system zygote.
-DROP VIEW IF EXISTS all_chrome_processes;
-CREATE VIEW all_chrome_processes AS
-SELECT upid, m.type AS process_type
-FROM process JOIN chrome_process_name_type_mapping m
-ON name GLOB original_name_pattern;
+  FROM process WHERE (
+    -- Chrome package names.
+    name like 'com.android.chrome%' OR
+    name like 'com.chrome.beta%' OR
+    name like 'com.chrome.dev%' OR
+    name like 'com.chrome.canary%' OR
+    name like 'com.google.android.apps.chrome%' OR
+    name like 'org.chromium.chrome%' OR
+    -- Chrome process descriptor names.
+    name = 'Browser' OR
+    name = 'Renderer' OR
+    name = 'Utility' OR
+    name = 'Zygote' OR
+    name = 'SandboxHelper' OR
+    name = 'Gpu' OR
+    name = 'PpapiPlugin' OR
+    name = 'PpapiBroker');
 
 -- A view of all Chrome threads.
-DROP VIEW IF EXISTS all_chrome_threads;
-CREATE VIEW all_chrome_threads AS
-  SELECT utid, thread.upid, thread.name
-  FROM thread, all_chrome_processes
-  WHERE thread.upid = all_chrome_processes.upid;
-
--- For sandboxed and privileged processes (found in Android system traces), use
--- the main thread name to type of process.
-DROP VIEW IF EXISTS chrome_subprocess_types;
-CREATE VIEW chrome_subprocess_types AS
--- Sometimes you can get multiple threads in a trace marked main_thread, but
--- they appear to have the same name so just use one of them.
-SELECT DISTINCT p.upid,
-  SUBSTR(t.name, 3, LENGTH(t.name) - 6) AS sandbox_type
-FROM all_chrome_processes p
-  JOIN all_chrome_threads t ON p.upid = t.upid
-WHERE process_type IN ("Sandboxed", "Privileged")
-  AND t.name GLOB "Cr*Main";
-
--- Contains all the chrome processes from process with an extra column,
--- process_type.
-DROP VIEW IF EXISTS chrome_process;
-CREATE VIEW chrome_process AS
-SELECT PROCESS.*,
-  IIF(sandbox_type IS NULL, process_type, sandbox_type) AS process_type
-FROM PROCESS
-  JOIN (
-    SELECT a.upid,
-      sandbox_type,
-      process_type
-    FROM all_chrome_processes a
-      LEFT JOIN chrome_subprocess_types s ON a.upid = s.upid
-  ) c ON PROCESS.upid = c.upid;
-
--- Contains all the chrome threads from thread with an extra column,
--- canonical_name, that should contain a thread that's the same in both chrome
--- and system traces.
 DROP VIEW IF EXISTS chrome_thread;
 
 CREATE VIEW chrome_thread AS
-SELECT thread.*,
-  CASE
-    WHEN thread.name GLOB "Cr*Main" THEN "CrProcessMain"
-    WHEN thread.name IS NULL THEN "Unknown"
-    ELSE thread.name
-  END AS canonical_name
-FROM (
-    SELECT t.utid,
-      p.*
-    FROM all_chrome_threads t
-      JOIN chrome_process p ON t.upid = p.upid
-  ) c
-  JOIN thread ON thread.utid = c.utid;
+  SELECT thread.*
+  FROM thread, chrome_process
+  WHERE thread.upid = chrome_process.upid;
diff --git a/src/trace_processor/metrics/chrome/chrome_thread_slice_with_cpu_time.sql b/src/trace_processor/metrics/chrome/chrome_thread_slice_with_cpu_time.sql
deleted file mode 100644
index 4af0d45..0000000
--- a/src/trace_processor/metrics/chrome/chrome_thread_slice_with_cpu_time.sql
+++ /dev/null
@@ -1,98 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_processes.sql');
-
--- Grab all the thread tracks which are found in chrome threads.
-DROP VIEW IF EXISTS chrome_track;
-CREATE VIEW chrome_track AS
-  SELECT
-    *
-  FROM thread_track
-  WHERE utid IN (SELECT utid FROM chrome_thread);
-
--- From all the chrome thread tracks select all the slice details as well as
--- the utid of the track so we can join with counter table later.
-DROP VIEW IF EXISTS chrome_slice;
-CREATE VIEW chrome_slice AS
-  SELECT
-    slice.*,
-    chrome_track.utid
-  FROM
-    slice JOIN
-    chrome_track ON
-        chrome_track.id = slice.track_id
-  WHERE
-    track_id in (SELECT id FROM chrome_track);
-
--- Using utid join the thread_counter_track to chrome thread slices. This allows
--- the filtering of the counter table to only counters associated to these
--- threads.
-DROP VIEW IF EXISTS chrome_slice_and_counter_track;
-CREATE VIEW chrome_slice_and_counter_track AS
-  SELECT
-    s.*,
-    thread_counter_track.id as counter_track_id,
-    thread_counter_track.name as counter_name
-  FROM
-    chrome_slice s JOIN
-    thread_counter_track ON
-        thread_counter_track.utid = s.utid AND
-        thread_counter_track.name = "thread_time";
-
--- Join each slice with the recorded value at the beginning and the end, as
--- well as computing the total CPU time each slice took.
---
--- We use MIN and MAX inside because sometimes nested slices will have the exact
--- same timestamp and we need to select one, there is nothing tying a particular
--- counter value to which slice generated it so we always choose the minimum for
--- the start on ties and the maximum for ties on the end of the slice. This
--- means this is always an overestimate, but events being emitted at exactly the
--- same timestamp is relatively rare so shouldn't cause to much inflation.
-DROP VIEW IF EXISTS chrome_thread_slice_with_cpu_time;
-CREATE VIEW chrome_thread_slice_with_cpu_time AS
-  SELECT
-    end_cpu_time - start_cpu_time AS slice_cpu_time,
-    *
-  FROM (
-    SELECT
-      s.*,
-      min_counter.start_cpu_time
-    FROM
-      chrome_slice_and_counter_track s LEFT JOIN (
-        SELECT
-          ts,
-          track_id,
-          MIN(value) AS start_cpu_time
-        FROM counter
-        GROUP BY 1, 2
-      ) min_counter ON
-          min_counter.ts = s.ts AND min_counter.track_id = s.counter_track_id
-  ) min_and_slice LEFT JOIN (
-    SELECT
-      ts,
-      track_id,
-      MAX(value) AS end_cpu_time
-    FROM counter
-    GROUP BY 1, 2
-  ) max_counter ON
-      max_counter.ts =
-          CASE WHEN min_and_slice.dur >= 0 THEN
-            min_and_slice.ts + min_and_slice.dur
-          ELSE
-            min_and_slice.ts
-          END AND
-      max_counter.track_id = min_and_slice.counter_track_id;
diff --git a/src/trace_processor/metrics/chrome/cpu_time_by_category.sql b/src/trace_processor/metrics/chrome/cpu_time_by_category.sql
deleted file mode 100644
index 2981ebd..0000000
--- a/src/trace_processor/metrics/chrome/cpu_time_by_category.sql
+++ /dev/null
@@ -1,71 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
-
--- This is a templated metric that takes 3 parameters:
--- input: name of a table/view which must have columns: id, ts, dur and a
---   "category" column
--- output: name of the view that will be created
--- category: name of the category column in the input table, which will be
---   preserved in the output
-
-SELECT RUN_METRIC('chrome/chrome_processes.sql') ;
-
--- CPU time slices for Chrome threads.
-DROP VIEW IF EXISTS chrome_cpu_slices;
-CREATE VIEW chrome_cpu_slices AS
-SELECT counters.id AS counter_id,
-  track_id,
-  ts,
-  lead(ts) OVER (
-    PARTITION BY track_id
-    ORDER BY ts
-  ) - ts AS dur,
-  CAST(
-    lead(value) OVER (
-      PARTITION BY track_id
-      ORDER BY ts
-    ) - value AS "INT64"
-  ) AS cpu_dur
-FROM counters,
-  (
-    SELECT thread_counter_track.id
-    FROM chrome_thread
-      JOIN thread_counter_track ON chrome_thread.utid = thread_counter_track.utid
-  ) AS t
-WHERE t.id = track_id;
-
-DROP TABLE IF EXISTS {{input}}_cpu_time;
-CREATE VIRTUAL TABLE {{input}}_cpu_time USING SPAN_JOIN(
-  {{input}},
-  chrome_cpu_slices PARTITIONED track_id
-);
-
--- View containing the CPU time used (across all cores) for each category slice
--- from input.
--- This will slightly overestimate the CPU time for some category slices as the
--- cpu time slices don't always line up with the category slices. However the
--- CPU slices are small enough this makes very little difference.
-DROP VIEW IF EXISTS {{output}};
-CREATE VIEW {{output}} AS
-SELECT s.id,
-  s.ts,
-  s.dur,
-  s.{{category}},
-  SUM(cpu_dur) AS cpu_dur
-FROM {{input}}_cpu_time r
-  JOIN {{input}} s
-WHERE r.id = s.id
-GROUP BY r.id;
diff --git a/src/trace_processor/metrics/chrome/cpu_time_by_rail_mode.sql b/src/trace_processor/metrics/chrome/cpu_time_by_rail_mode.sql
deleted file mode 100644
index 426bd25..0000000
--- a/src/trace_processor/metrics/chrome/cpu_time_by_rail_mode.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql') AS suppress_query_output;
-
--- Creates a view cpu_time_by_rail_mode containing the CPU time used (across all
--- cores) for each RAIL Mode slice in combined_overall_rail_slices.
-SELECT RUN_METRIC('chrome/cpu_time_by_category.sql',
-    'input', 'combined_overall_rail_slices',
-    'output', 'cpu_time_by_rail_mode',
-    'category', 'rail_mode'
-  );
diff --git a/src/trace_processor/metrics/chrome/estimated_power_by_category.sql b/src/trace_processor/metrics/chrome/estimated_power_by_category.sql
deleted file mode 100644
index 506d2a1..0000000
--- a/src/trace_processor/metrics/chrome/estimated_power_by_category.sql
+++ /dev/null
@@ -1,71 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
-
--- This is a templated metric that takes 3 parameters:
--- input: name of a table/view which must have columns: id, ts, dur and a
---   "category" column
--- output: name of the view that will be created
--- category: name of the category column in the input table, which will be
---   preserved in the output
-
-SELECT RUN_METRIC('chrome/chrome_processes.sql');
-SELECT RUN_METRIC('android/android_proxy_power.sql');
-
--- View containing estimated power slices broken down by cpu.
-DROP VIEW IF EXISTS power_per_chrome_thread;
-CREATE VIEW power_per_chrome_thread AS
-SELECT ts,
-  dur,
-  cpu,
-  power_per_thread.utid,
-  end_state,
-  priority,
-  power_ma,
-  power_per_thread.type,
-  name AS thread_name,
-  upid,
-  is_main_thread
-FROM power_per_thread
-  JOIN chrome_thread
-WHERE power_per_thread.utid = chrome_thread.utid;
-
-DROP TABLE IF EXISTS {{input}}_power;
-CREATE VIRTUAL TABLE {{input}}_power USING SPAN_JOIN(
-  {{input}},
-  power_per_chrome_thread PARTITIONED utid
-);
-
--- Estimated power usage for chrome across the categroy slices contained in
--- input.
-DROP VIEW IF EXISTS {{output}};
-CREATE VIEW {{output}} AS
-SELECT id,
-  ts,
-  dur,
-  {{category}},
-  mas,
-  mas / dur * 1e9 AS ma
-FROM (
-    SELECT s.id,
-      s.ts,
-      s.dur,
-      s.{{category}},
-      SUM(r.power_ma * r.dur) / 1e9 AS mas
-    FROM {{input}}_power r
-      JOIN {{input}} s
-    WHERE r.id == s.id
-    GROUP BY s.id
-  );
diff --git a/src/trace_processor/metrics/chrome/estimated_power_by_rail_mode.sql b/src/trace_processor/metrics/chrome/estimated_power_by_rail_mode.sql
deleted file mode 100644
index a0b9b22..0000000
--- a/src/trace_processor/metrics/chrome/estimated_power_by_rail_mode.sql
+++ /dev/null
@@ -1,26 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql');
-
--- Creates a view called power_by_rail_mode, containing the estimated CPU power
--- usage for chrome broken down by RAIL Mode.
-SELECT RUN_METRIC(
-    'chrome/estimated_power_by_category.sql',
-    'input', 'combined_overall_rail_slices',
-    'output', 'power_by_rail_mode',
-    'category', 'rail_mode'
-  );
diff --git a/src/trace_processor/metrics/chrome/rail_modes.sql b/src/trace_processor/metrics/chrome/rail_modes.sql
deleted file mode 100644
index d86c25f..0000000
--- a/src/trace_processor/metrics/chrome/rail_modes.sql
+++ /dev/null
@@ -1,562 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_processes.sql') AS suppress_query_output;
-SELECT RUN_METRIC('chrome/chrome_event_metadata.sql') AS suppress_query_output;
-
--- Priority order for RAIL modes where response has the highest priority and
--- idle has the lowest.
-DROP TABLE IF EXISTS rail_modes;
-CREATE TABLE rail_modes (
-  mode TEXT UNIQUE,
-  ordering INT,
-  short_name TEXT
-);
-
--- RAIL_MODE_IDLE is used when no frames are visible in the renderer and so this
--- interprets that as background.
--- RAIL_MODE_LOAD is for the time from a navigation until the first meaningful
--- paint (assuming there are no user interactions).
--- RAIL_MODE_RESPONSE is used when the main thread is dealing with a
--- user-interaction (but not for instance for scrolls which may be handled by
--- the compositor).
--- RAIL_MODE_ANIMATION is used when none of the above apply.
--- The enum in chrome is defined in:
--- https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/scheduler/public/rail_mode_observer.h
-INSERT INTO rail_modes
-VALUES ('RAIL_MODE_IDLE', 0, 'background'),
-  ('RAIL_MODE_ANIMATION', 1, "animation"),
-  ('RAIL_MODE_LOAD', 2, "load"),
-  ('RAIL_MODE_RESPONSE', 3, "response");
-
-
--- Find the max ts + dur for every process
-DROP TABLE IF EXISTS max_ts_per_process;
-CREATE TABLE max_ts_per_process AS
- -- MAX(dur, 0) means unclosed slices just contribute their start time.
-SELECT upid,
-  MAX(ts + MAX(dur, 0)) AS ts
-FROM (
-    SELECT upid,
-      ts,
-      dur
-    FROM process_track t
-      JOIN slice s
-    WHERE s.track_id = t.id
-    UNION ALL
-    SELECT upid,
-      ts,
-      dur
-    FROM thread_track t
-      JOIN thread
-      JOIN slice
-    WHERE slice.track_id = t.id
-      AND thread.utid = t.utid
-  )
-GROUP BY upid;
-
--- View containing all Scheduler.RAILMode slices across all Chrome renderer
--- processes.
-DROP VIEW IF EXISTS original_rail_mode_slices;
-CREATE VIEW original_rail_mode_slices AS
-SELECT slice.id,
-  slice.ts,
-  CASE
-    -- Add 1 to the duration to ensure you cannot get a zero-sized RAIL mode
-    -- slice, which can throw off the later queries.
-    WHEN dur == -1 THEN max_ts_per_process.ts - slice.ts + 1
-    ELSE dur
-  END AS dur,
-  track_id,
-  EXTRACT_ARG(
-    slice.arg_set_id,
-    "chrome_renderer_scheduler_state.rail_mode"
-  ) AS rail_mode
-FROM max_ts_per_process,
-  slice,
-  process_track
-WHERE slice.name = "Scheduler.RAILMode"
-  AND slice.track_id = process_track.id
-  AND process_track.upid = max_ts_per_process.upid;
-
--- Detect if the trace has an unrealistic length (10 minutes) that probably
--- means some trace events have faulty timestamps and which could throw off any
--- metrics that use the trace.
-DROP VIEW IF EXISTS trace_has_realistic_length;
-CREATE VIEW trace_has_realistic_length AS
-SELECT (end_ts - start_ts) < 1e9 * 60 * 10 AS value
-FROM trace_bounds;
-
--- RAIL_MODE_LOAD seems to get stuck which makes it not very useful so remap it
--- to RAIL_MODE_ANIMATION so it doesn't dominate the overall RAIL mode.
-DROP VIEW IF EXISTS rail_mode_slices;
-CREATE VIEW rail_mode_slices AS
-SELECT ts, dur, track_id,
-    CASE
-      WHEN rail_mode == "RAIL_MODE_LOAD" THEN "RAIL_MODE_ANIMATION"
-      ELSE rail_mode
-    END AS rail_mode
-FROM original_rail_mode_slices;
-
--- View containing a collapsed view of rail_mode_slices where there is only one
--- RAIL mode active at a given time. The mode is derived using the priority
--- order in rail_modes.
-DROP VIEW IF EXISTS overall_rail_mode_slices;
-CREATE VIEW overall_rail_mode_slices AS
-SELECT s.ts,
-  s.end_ts,
-  rail_modes.short_name AS rail_mode,
-  MAX(rail_modes.ordering)
-FROM (
-    SELECT ts,
-      LEAD(ts, 1, (SELECT MAX(ts + dur) FROM rail_mode_slices)) OVER (
-        ORDER BY ts
-      ) AS end_ts
-    FROM (
-        SELECT DISTINCT ts
-        FROM rail_mode_slices
-      ) start_times
-  ) s,
-  rail_mode_slices r,
-  rail_modes,
-  trace_has_realistic_length
-WHERE (
-    (
-      s.ts >= r.ts AND s.ts < r.ts + r.dur
-    )
-    OR (
-      s.end_ts > r.ts AND s.end_ts <= r.ts + r.dur
-    )
-  )
-  AND r.rail_mode == rail_modes.mode
-  AND trace_has_realistic_length.value
-GROUP BY s.ts;
-
--- Contains the same data as overall_rail_mode_slices except adjacent slices
--- with the same RAIL mode are combined.
-DROP TABLE IF EXISTS combined_overall_rail_slices;
-CREATE TABLE combined_overall_rail_slices AS
-SELECT ROW_NUMBER() OVER () AS id,
-  ts,
-  end_ts - ts AS dur,
-  rail_mode
-FROM (
-    SELECT lag(l.end_ts, 1, FIRST) OVER (
-        ORDER BY l.ts
-      ) AS ts,
-      l.end_ts,
-      l.rail_mode
-    FROM (
-        SELECT ts,
-          end_ts,
-          rail_mode
-        FROM overall_rail_mode_slices s
-        WHERE NOT EXISTS (
-            SELECT NULL
-            FROM overall_rail_mode_slices s2
-            WHERE s.rail_mode = s2.rail_mode
-              AND s.end_ts = s2.ts
-          )
-      ) AS l,
-      (
-        SELECT min(ts) AS FIRST
-        FROM overall_rail_mode_slices
-      )
-  );
-
--- Now we have the RAIL Mode, use other trace events to create a modified RAIL
--- mode that more accurately reflects what the browser/user are doing.
-
--- First create slices for when there's no animation as indicated by a large gap
--- between vsync events (since it's easier to find gaps than runs of adjacent
--- vsyncs).
-
--- Mark any large gaps between vsyncs.
--- The value in "not_animating" is always 1. It's just there to be a non-NULL
--- value so the later SPAN_JOIN can find the set-difference.
-DROP VIEW IF EXISTS not_animating_slices;
-CREATE VIEW not_animating_slices AS
-WITH const (vsync_padding, large_gap) AS (
-  SELECT
-    -- Pad 50ms either side of a vsync
-    50000000,
-    -- A gap of >200ms between the adjacent vsyncs is treated as a gap in
-    -- animation.
-    200000000
-)
-SELECT ts + const.vsync_padding AS ts,
-  gap_to_next_vsync - const.vsync_padding * 2 AS dur, 1 AS not_animating
-FROM const, (SELECT name,
-    ts,
-    lead(ts) OVER () - ts AS gap_to_next_vsync,
-    dur
-  FROM slice
-  WHERE name = "VSync")
-WHERE gap_to_next_vsync > const.large_gap
-UNION
--- Insert a slice between start_ts and the first vsync (or the end of the trace
--- if there are none).
-SELECT
-  ts,
-  dur,
-  1
-FROM (SELECT start_ts AS ts,
-          COALESCE((
-              SELECT MIN(ts)
-              FROM slice
-              WHERE name = "VSync"
-            ) - start_ts - const.vsync_padding,
-            end_ts - start_ts
-          ) AS dur
-FROM trace_bounds, const)
-WHERE dur > 0
-UNION
--- Insert a slice between the last vsync and end_ts
-SELECT last_vsync AS ts,
-  end_ts - last_vsync AS dur,
-  1
-FROM (
-    SELECT MAX(ts) + const.vsync_padding AS last_vsync
-    FROM slice, const
-    WHERE name = "VSync"
-  ),
-  trace_bounds
-WHERE last_vsync < end_ts;
-
--- There are two types of InputLatency:: events:
--- 1) Simple ones that begin at ts and end at ts+dur
--- 2) Paired ones that begin with a "begin" slice and end at an "end" slice.
---
--- Paired events are even trickier because we can't guarantee that the "begin"
--- slice will even be in the trace and because it's possible for multiple begin
--- slices to appear without an intervening end slice.
-
--- Table of begin and end events along with the increment/decrement to be
--- applied to the appropriate counter (one for each type of paired event). Final
--- column dur_multiplier is used to find the timestamp to mark the event at in
--- the equation event_ts = ts + dur * dur_multiplier. End events have
--- dur_multiplier of 1, which makes their ts the end of the slice rather than
--- the start.
-DROP TABLE IF EXISTS input_latency_begin_end_names;
-CREATE TABLE input_latency_begin_end_names
-(
-  full_name TEXT UNIQUE,
-  prefix TEXT,
-  scroll_increment INT,
-  pinch_increment INT,
-  touch_increment INT,
-  fling_increment INT,
-  pointer_increment INT,
-  dur_multiplier INT
-);
-
-INSERT
-  OR IGNORE INTO input_latency_begin_end_names
-VALUES
-  ("InputLatency::GestureScrollBegin",
-     "InputLatency::GestureScroll", 1, 0, 0, 0, 0, 0),
-  ("InputLatency::GestureScrollEnd",
-     "InputLatency::GestureScroll", -1, 0, 0, 0, 0, 1),
-  ("InputLatency::GesturePinchBegin",
-     "InputLatency::GesturePinch", 0, 1, 0, 0, 0, 0),
-  ("InputLatency::GesturePinchEnd",
-     "InputLatency::GesturePinch", 0, -1, 0, 0, 0, 1),
-  ("InputLatency::TouchStart",
-     "InputLatency::Touch", 0, 0, 1, 0, 0, 0),
-  ("InputLatency::TouchEnd",
-     "InputLatency::Touch", 0, 0, -1, 0, 0, 1),
-  ("InputLatency::GestureFlingStart",
-     "InputLatency::GestureFling", 0, 0, 0, 1, 0, 0),
-  ("InputLatency::GestureFlingCancel",
-     "InputLatency::GestureFling", 0, 0, 0, -1, 0, 1),
-  ("InputLatency::PointerDown",
-     "InputLatency::Pointer", 0, 0, 0, 0, 1, 0),
-  ("InputLatency::PointerUp",
-     "InputLatency::Pointer", 0, 0, 0, 0, -1, 1),
-  ("InputLatency::PointerCancel",
-     "InputLatency::Pointer", 0, 0, 0, 0, -1, 1);
-
--- Find all the slices that have split "begin" and "end" slices and maintain a
--- running total for each type, where >0 means that type of input event is
--- ongoing.
-DROP VIEW IF EXISTS input_begin_end_slices;
-CREATE VIEW input_begin_end_slices AS
-SELECT prefix,
-  -- Mark the change at the start of "start" slices and the end of "end" slices.
-  ts + dur * dur_multiplier AS ts,
-  scroll_increment,
-  pinch_increment,
-  touch_increment,
-  fling_increment,
-  pointer_increment
-FROM slice
-JOIN input_latency_begin_end_names ON name = full_name
-ORDER BY ts;
-
--- Combine all the paired input events to get an indication of when any paired
--- input event is ongoing.
-DROP VIEW IF EXISTS unified_input_pair_increments;
-CREATE VIEW unified_input_pair_increments AS
-SELECT ts,
-  scroll_increment +
-  pinch_increment +
-  touch_increment +
-  fling_increment +
-  pointer_increment AS increment
-FROM input_begin_end_slices;
-
--- It's possible there's an end slice without a start slice (as it occurred
--- before the trace started) which would result in (starts - ends) going
--- negative at some point. So find an offset that shifts up all counts so the
--- lowest values becomes zero. It's possible this could still do the wrong thing
--- if there were start AND end slices that are outside the trace bounds, in
--- which case it should count as covering the entire trace, but it's impossible
--- to compensate for that without augmenting the trace events themselves.
-DROP VIEW IF EXISTS initial_paired_increment;
-CREATE VIEW initial_paired_increment AS
-SELECT ts,
-  MIN(0, MIN(scroll_total)) +
-  MIN(0, MIN(pinch_total))  +
-  MIN(0, MIN(touch_total))  +
-  MIN(0, MIN(fling_total))  +
-  MIN(0, MIN(pointer_total)) AS offset
-FROM (
-    SELECT ts,
-      SUM(scroll_increment) OVER(ROWS UNBOUNDED PRECEDING) AS scroll_total,
-      SUM(pinch_increment)  OVER(ROWS UNBOUNDED PRECEDING) AS pinch_total,
-      SUM(touch_increment)  OVER(ROWS UNBOUNDED PRECEDING) AS touch_total,
-      SUM(fling_increment)  OVER(ROWS UNBOUNDED PRECEDING) AS fling_total,
-      SUM(pointer_increment)  OVER(ROWS UNBOUNDED PRECEDING) AS pointer_total
-    FROM input_begin_end_slices
-  );
-
--- Now find all the simple input slices that fully enclose the input they're
--- marking (i.e. not the start or end of a pair).
-DROP VIEW IF EXISTS simple_input_slices;
-CREATE VIEW simple_input_slices AS
-SELECT id,
-  name,
-  ts,
-  dur
-FROM slice s
-WHERE name LIKE "InputLatency::%"
-  AND NOT EXISTS (
-    SELECT 1
-    FROM slice
-      JOIN input_latency_begin_end_names
-    WHERE s.name == full_name
-  );
-
--- Turn the simple input slices into +1s and -1s at the start and end of each
--- slice.
-DROP VIEW IF EXISTS simple_input_increments;
-CREATE VIEW simple_input_increments AS
-SELECT ts,
-  1 AS increment
-FROM simple_input_slices
-UNION ALL
-SELECT ts + dur,
-  -1
-FROM simple_input_slices
-ORDER BY ts;
-
--- Combine simple and paired inputs into one, summing all the increments at a
--- given ts.
-DROP VIEW IF EXISTS all_input_increments;
-CREATE VIEW all_input_increments AS
-SELECT ts,
-  SUM(increment) AS increment
-FROM (
-    SELECT *
-    FROM simple_input_increments
-    UNION ALL
-    SELECT *
-    FROM unified_input_pair_increments
-    ORDER BY ts
-  )
-GROUP BY ts;
-
--- Now calculate the cumulative sum of the increments as each ts, giving the
--- total number of outstanding input events at a given time.
-DROP VIEW IF EXISTS all_input_totals;
-CREATE VIEW all_input_totals AS
-SELECT ts,
-  SUM(increment) OVER(ROWS UNBOUNDED PRECEDING) > 0 AS input_total
-FROM all_input_increments;
-
--- Now find the transitions from and to 0 and use that to create slices where
--- input events were occurring. The input_active column always contains 1, but
--- is there so that the SPAN_JOIN_LEFT can put NULL in it for RAIL Mode slices
--- that do not have corresponding input events.
-DROP VIEW IF EXISTS all_input_slices;
-CREATE VIEW all_input_slices AS
-SELECT ts,
-  dur,
-  input_active
-FROM (
-    SELECT ts,
-      lead(ts, 1, end_ts) OVER() - ts AS dur,
-      input_active
-    FROM trace_bounds,
-      (
-        SELECT ts,
-          input_total > 0 AS input_active
-        FROM (
-            SELECT ts,
-              input_total,
-              lag(input_total) OVER() AS prev_input_total
-            FROM all_input_totals
-          )
-        WHERE (input_total > 0 <> prev_input_total > 0)
-          OR prev_input_total IS NULL
-      )
-  )
-WHERE input_active > 0;
-
--- Since the scheduler defaults to animation when none of the other RAIL modes
--- apply, animation overestimates the amount of time that actual animation is
--- occurring.
--- So instead we try to divide up animation in other buckets based on other
--- trace events.
-DROP VIEW IF EXISTS rail_mode_animation_slices;
-CREATE VIEW rail_mode_animation_slices AS
-SELECT * FROM combined_overall_rail_slices WHERE rail_mode = "animation";
-
--- Left-join rail mode animation slices with all_input_slices to find all
--- "animation" slices that should actually be labelled "response".
-DROP TABLE IF EXISTS rail_mode_join_inputs;
-CREATE VIRTUAL TABLE rail_mode_join_inputs
-USING SPAN_LEFT_JOIN(rail_mode_animation_slices, all_input_slices);
-
--- Left-join rail mode animation slices with not_animating_slices which is
--- based on the gaps between vsync events.
-DROP TABLE IF EXISTS rail_mode_join_inputs_join_animation;
-CREATE VIRTUAL TABLE rail_mode_join_inputs_join_animation
-USING SPAN_LEFT_JOIN(rail_mode_join_inputs, not_animating_slices);
-
-DROP VIEW IF EXISTS has_modified_rail_slices;
-CREATE VIEW has_modified_rail_slices AS
-SELECT (
-    SELECT value
-    FROM chrome_event_metadata
-    WHERE name == "os-name"
-  ) == "Android" AS value;
-
--- Mapping to allow CamelCased names to be produced from the modified rail
--- modes.
-DROP TABLE IF EXISTS modified_rail_mode_prettier;
-CREATE TABLE modified_rail_mode_prettier (
-  orig_name TEXT UNIQUE,
-  pretty_name TEXT
-);
-INSERT INTO modified_rail_mode_prettier
-VALUES ("background", "Background"),
-  ("foreground_idle", "ForegroundIdle"),
-  ("animation", "Animation"),
-  ("load", "Load"),
-  ("response", "Response");
-
--- When the RAIL mode is animation, use input/vsync data to conditionally change
--- the mode to response or foreground_idle.
-DROP VIEW IF EXISTS unmerged_modified_rail_slices;
-CREATE VIEW unmerged_modified_rail_slices AS
-SELECT ROW_NUMBER() OVER () AS id,
-  ts,
-  dur,
-  mode
-FROM (
-    SELECT ts,
-      dur,
-      CASE
-        WHEN input_active IS NOT NULL THEN "response"
-        WHEN not_animating IS NULL THEN "animation"
-        ELSE "foreground_idle"
-      END AS mode
-    FROM rail_mode_join_inputs_join_animation
-    UNION
-    SELECT ts,
-      dur,
-      rail_mode AS mode
-    FROM combined_overall_rail_slices
-    WHERE rail_mode <> "animation"
-  )
-  -- Since VSync events are only emitted on Android (and the concept of a
-  -- unified RAIL mode only makes sense if there's just a single Chrome window),
-  -- don't output anything on other platforms. This will result in all the power
-  -- and cpu time tables being empty rather than containing bogus results.
-WHERE (
-    SELECT value
-    FROM has_modified_rail_slices
-  );
-
--- The previous query creating unmerged_modified_rail_slices, can create
--- adjacent slices with the same mode. This merges them together as well as
--- adding a unique id to each slice. Rather than directly merging slices
--- together, this instead looks for all the transitions and uses this to
--- reconstruct the slices that should occur between them.
-DROP TABLE IF EXISTS modified_rail_slices;
-CREATE TABLE modified_rail_slices AS
-WITH const (end_ts) AS (SELECT ts + dur
-              FROM unmerged_modified_rail_slices
-              ORDER BY ts DESC
-              LIMIT 1)
-SELECT ROW_NUMBER() OVER () AS id, lag(next_ts) OVER() AS ts,
-  ts + dur - lag(next_ts) OVER() AS dur,
-  mode AS mode
-FROM (
-    -- For each row in the original table, create a new row with the information
-    -- from the following row, since you can't use lag/lead in WHERE clause.
-    --
-    -- Transition row at the beginning. "mode" is invalid, so a transition will
-    -- always be recorded.
-    SELECT *
-    FROM (SELECT
-          0 AS ts,
-          ts AS dur,
-          "" AS mode,
-          ts AS next_ts,
-          dur AS next_dur,
-          mode AS next_mode
-        FROM unmerged_modified_rail_slices
-        LIMIT 1
-      )
-    UNION ALL
-    SELECT ts,
-      dur,
-      mode,
-      lead(ts, 1, end_ts) OVER() AS next_ts,
-      lead(dur) OVER() AS next_dur,
-      lead(mode) OVER() AS next_mode
-    FROM unmerged_modified_rail_slices, const
-    UNION ALL
-    -- Transition row at the end. "next_mode" is invalid, so a transition will
-    -- always be recorded.
-    SELECT *
-    FROM (SELECT
-          ts + dur AS ts,
-          0 AS dur,
-          mode,
-          ts + dur AS next_ts,
-          0,
-          "" AS next_mode
-        FROM unmerged_modified_rail_slices
-        ORDER BY ts DESC
-        LIMIT 1
-      )
-  )
-WHERE mode <> next_mode
--- Retrieve all but the first row.
-LIMIT -1 OFFSET 1;
diff --git a/src/trace_processor/metrics/chrome/scroll_flow_event.sql b/src/trace_processor/metrics/chrome/scroll_flow_event.sql
deleted file mode 100644
index 05699f4..0000000
--- a/src/trace_processor/metrics/chrome/scroll_flow_event.sql
+++ /dev/null
@@ -1,258 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
--- While handling a InputLatency::GestureScrollUpdate event a sequence of Flows
--- define the critical path from Beginning to End. This metric breaks down the
--- flows for the same InputLatency::GestureScrollUpdate event.
---
--- WARNING: This metric should not be used as a source of truth. It is under
---          active development and the values & meaning might change without
---          notice.
-
--- Provides the scroll_jank table which gives us all the GestureScrollUpdate
--- events we care about and labels them janky or not.
-SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
--- We get all latency_info that have valid trace_ids, And we make a synthetic
--- one for the beginning of each GestureScrollUpdate event so we can track the
--- time between receiving the input and being converted into a scroll.
---
--- flows with a trace_id of -1 are incomplete and are difficult to reason about
--- (especially if GestureScrollUpdate flows end up getting -1). so ignore them
--- for this table.
-DROP VIEW IF EXISTS latency_info_flow_step_and_ancestors;
-CREATE VIEW latency_info_flow_step_and_ancestors AS
-  SELECT
-    *
-  FROM (
-    SELECT
-      slice.name,
-      slice.id,
-      slice.ts,
-      slice.dur,
-      slice.track_id,
-      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
-      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.step') AS step,
-      COALESCE(ancestor_zero.name, slice.name) AS ancestor_name_zero,
-      COALESCE(ancestor_zero.id, slice.id) AS ancestor_id_zero,
-      COALESCE(ancestor_zero.ts, slice.ts) AS ancestor_ts_zero,
-      COALESCE(ancestor_zero.dur, slice.dur) AS ancestor_dur_zero,
-      COALESCE(ancestor_one.name, slice.name) AS ancestor_name_one,
-      COALESCE(ancestor_one.id, slice.id) AS ancestor_id_one,
-      COALESCE(ancestor_one.ts, slice.ts) AS ancestor_ts_one,
-      COALESCE(ancestor_one.dur, slice.dur) AS ancestor_dur_one
-    FROM
-      slice LEFT JOIN
-      ancestor_slice(slice.id) AS ancestor_zero
-          ON ancestor_zero.depth = 0 LEFT JOIN
-      ancestor_slice(slice.id) AS ancestor_one ON ancestor_one.depth = 1
-    WHERE
-      slice.name = 'LatencyInfo.Flow' AND
-      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.trace_id') != -1
-  ) flow JOIN (
-      SELECT
-        id AS scroll_slice_id,
-        ts AS scroll_ts,
-        dur AS scroll_dur,
-        track_id AS scroll_track_id,
-        trace_id AS scroll_trace_id,
-        jank,
-        gesture_scroll_id
-      FROM scroll_jank
-  ) scroll ON
-    flow.trace_id = scroll.scroll_trace_id
-  UNION ALL
-  SELECT
-    'InputLatency::GestureScrollUpdate' AS name,
-    id,
-    ts,
-    dur,
-    track_id,
-    trace_id,
-    'AsyncBegin' AS step,
-    'InputLatency::GestureScrollUpdate' AS ancestor_name_zero,
-    id AS ancestor_id_zero,
-    ts AS ancestor_ts_zero,
-    0 AS ancestor_dur_zero,
-    'InputLatency::GestureScrollUpdate' AS ancestor_name_one,
-    id AS ancestor_id_one,
-    ts AS ancestor_ts_one,
-    0 AS ancestor_dur_one,
-    id AS scroll_slice_id,
-    ts AS scroll_ts,
-    dur AS scroll_dur,
-    track_id AS scroll_track_id,
-    trace_id AS scroll_trace_id,
-    jank,
-    gesture_scroll_id
-  FROM scroll_jank
-  ORDER BY gesture_scroll_id ASC, trace_id ASC, ts ASC;
-
--- See b/184134310, but "ThreadController active" spans multiple tasks and when
--- the top level parent is this event we should use the second event instead.
-DROP VIEW IF EXISTS latency_info_flow_step;
-CREATE VIEW latency_info_flow_step AS
-  SELECT
-    *,
-    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
-      ancestor_name_zero ELSE ancestor_name_one END AS ancestor_name,
-    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
-      ancestor_id_zero ELSE ancestor_id_one END AS ancestor_id,
-    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
-      ancestor_ts_zero ELSE ancestor_ts_one END AS ancestor_ts,
-    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
-      ancestor_dur_zero ELSE ancestor_dur_one END AS ancestor_dur
-  FROM latency_info_flow_step_and_ancestors;
-
--- This is a heuristic to figure out which flow event properly joins this
--- GestureScrollUpdate. This heuristic is only needed in traces before we added
--- gesture_scroll_id.
---
--- We select the first |ts| from a flow event after its corresponding
--- GestureScrollUpdate has ended. This allows us to use this |ts| to contain all
--- flow events from the start of a particular scroll_slice_id (the slice id of
--- the async event) to that |ts|.
---
--- The reason for this is if these flow events share the same trace_id which can
--- occur if multiple chrome browsers are in the trace (webview & chrome for
--- example). We would normally add flow events from different scrolls, but by
--- limiting by the GestureScrollUpdate end we can prevent incorrect duplication.
--- This breaks of course if the same trace_id happens at the exact same time in
--- both browsers but this is hopefully unlikely.
-DROP VIEW IF EXISTS max_latency_info_ts_per_trace_id;
-CREATE VIEW max_latency_info_ts_per_trace_id AS
-  SELECT
-    scroll_slice_id,
-    MIN(ts) AS max_flow_ts
-  FROM latency_info_flow_step
-  WHERE
-    trace_id = scroll_trace_id AND
-    ts > scroll_ts + scroll_dur
-  GROUP BY scroll_slice_id;
-
--- As described by the comments about this uses the heuristic to remove any flow
--- events that aren't contained within the |max_flow_ts| and the beginning of
--- the GestureScrollUpdate. This prevents other processes that share the same
--- trace_id from inserting events in the middle.
---
--- Note: Must be a TABLE because it uses a window function which can behave
---       strangely in views.
-DROP TABLE IF EXISTS latency_info_flow_step_filtered;
-CREATE TABLE latency_info_flow_step_filtered AS
-  SELECT
-    ROW_NUMBER() OVER (ORDER BY
-      flow.gesture_scroll_id ASC, trace_id ASC, ts ASC) AS row_number,
-    *
-  FROM
-    latency_info_flow_step flow JOIN
-    max_latency_info_ts_per_trace_id max_flow on
-    max_flow.scroll_slice_id = flow.scroll_slice_id
-  WHERE
-    ts >= scroll_ts AND
-    ts <= max_flow_ts
-  ORDER BY flow.gesture_scroll_id ASC, flow.trace_id ASC, flow.ts ASC;
-
--- Take all the LatencyInfo.Flow events and within a |trace_id| join it with the
--- previous and nextflows. Some events are 'Unknown' when they don't have a step
--- but occur in the middle of the critical path. Most of these are errors though
--- and we've weeded I think all of them out (citation needed).
---
--- Note: Must be a TABLE because it uses a window function which can behave
---       strangely in views.
-DROP TABLE IF EXISTS latency_info_flow_null_step_removed;
-CREATE TABLE latency_info_flow_null_step_removed AS
-  SELECT
-    ROW_NUMBER() OVER (ORDER BY
-      curr.gesture_scroll_id ASC, curr.trace_id ASC, curr.ts ASC
-    ) AS row_number,
-    curr.id,
-    curr.ts,
-    curr.dur,
-    curr.track_id,
-    curr.trace_id,
-    curr.gesture_scroll_id,
-    curr.scroll_slice_id,
-    curr.scroll_ts,
-    curr.scroll_dur,
-    curr.scroll_track_id,
-    curr.jank,
-    curr.ancestor_id,
-    curr.ancestor_ts,
-    curr.ancestor_dur,
-    curr.ancestor_ts + curr.ancestor_dur AS ancestor_end,
-    CASE WHEN curr.step IS NULL THEN
-      CASE WHEN
-          prev.gesture_scroll_id != curr.gesture_scroll_id OR
-          prev.trace_id != curr.trace_id OR
-          prev.trace_id IS NULL OR
-          prev.step = 'AsyncBegin' THEN
-        'Begin'
-      ELSE
-        CASE WHEN
-            next.gesture_scroll_id != curr.gesture_scroll_id OR
-            next.trace_id != curr.trace_id OR
-            next.trace_id IS NULL THEN
-          'End'
-        ELSE
-         'Unknown'
-        END
-      END
-    ELSE curr.step END AS step
-  FROM
-    latency_info_flow_step_filtered curr LEFT JOIN
-    latency_info_flow_step_filtered prev ON
-      curr.row_number - 1 = prev.row_number LEFT JOIN
-    latency_info_flow_step_filtered next ON
-      curr.row_number + 1 = next.row_number
-  ORDER BY curr.gesture_scroll_id ASC, curr.trace_id ASC, curr.ts ASC;
-
--- Now that we've got the steps all named properly we want to join them with the
--- next step so we can compute the difference between the end of the current
--- step and the beginning of the next step.
-DROP VIEW IF EXISTS scroll_flow_event;
-CREATE VIEW scroll_flow_event AS
-  SELECT
-    curr.trace_id,
-    curr.id,
-    curr.ts,
-    curr.dur,
-    curr.track_id,
-    curr.gesture_scroll_id,
-    curr.scroll_slice_id,
-    curr.scroll_ts,
-    curr.scroll_dur,
-    curr.scroll_track_id,
-    curr.jank,
-    curr.step,
-    curr.ancestor_id,
-    curr.ancestor_ts,
-    curr.ancestor_dur,
-    curr.ancestor_end,
-    next.id as next_id,
-    next.ts AS next_ts,
-    next.dur AS next_dur,
-    next.track_id AS next_track_id,
-    next.trace_id AS next_trace_id,
-    next.step AS next_step,
-    CASE WHEN next.trace_id = curr.trace_id THEN
-      next.ancestor_ts
-    ELSE
-      NULL
-    END AS maybe_next_ancestor_ts
-  FROM
-    latency_info_flow_null_step_removed curr LEFT JOIN
-    latency_info_flow_null_step_removed next ON
-    curr.row_number + 1 = next.row_number
-  ORDER BY curr.gesture_scroll_id, curr.trace_id, curr.ts;
diff --git a/src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql b/src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql
deleted file mode 100644
index 81eba40..0000000
--- a/src/trace_processor/metrics/chrome/scroll_flow_event_queuing_delay.sql
+++ /dev/null
@@ -1,75 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
--- This metric takes each flow event in a InputLatency::GestureScrollUpdate and
--- and computes the time from the ancestor_end of the current flow to the
--- ancestor_ts of the next flow event. This is a reasonable approximation of the
--- time we waited for the next step in the critical flow to start.
-
--- Provides the scroll_flow_event table which gives us all the flow events with
--- associated GestureScrollUpdate events we care about and labels them janky or
--- not.
-SELECT RUN_METRIC('chrome/scroll_flow_event.sql');
-
--- Take each flow and next flow (from scroll_flow_event table) and generate the
--- metric name as well as compute the time between.
-DROP VIEW IF EXISTS scroll_flow_event_queuing_delay;
-
-CREATE VIEW scroll_flow_event_queuing_delay AS
-  SELECT
-    trace_id,
-    id,
-    ts,
-    dur,
-    track_id,
-    gesture_scroll_id,
-    scroll_slice_id,
-    scroll_ts,
-    scroll_dur,
-    scroll_track_id,
-    jank,
-    step,
-    ancestor_id,
-    ancestor_ts,
-    ancestor_end,
-    next_id,
-    next_step,
-    maybe_next_ancestor_ts,
-    next_track_id,
-      CASE WHEN trace_id = next_trace_id THEN
-      'InputLatency.LatencyInfo.Flow.QueuingDelay.' ||
-      CASE WHEN
-        jank IS NOT NULL AND
-        jank = 1
-      THEN
-          'Jank.'
-      ELSE
-          'NoJank.'
-      END
-      || step || '-to-' || next_step
-    ELSE
-      step
-    END AS description,
-    CASE WHEN maybe_next_ancestor_ts IS NULL THEN
-      NULL
-    ELSE
-      CASE WHEN maybe_next_ancestor_ts > ancestor_end THEN
-        (maybe_next_ancestor_ts - ancestor_end)
-      ELSE
-        0
-      END
-    END AS queuing_time_ns
-  FROM scroll_flow_event
-  ORDER BY gesture_scroll_id, trace_id, ts;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank.sql b/src/trace_processor/metrics/chrome/scroll_jank.sql
deleted file mode 100644
index 0564bd5..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank.sql
+++ /dev/null
@@ -1,303 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
---
--- A collection of metrics related to GestureScrollUpdate events.
---
--- We define a GestureScrollUpdate to be janky if comparing forwards or
--- backwards (ignoring coalesced updates) a given GestureScrollUpdate exceeds
--- the duration of its predecessor or successor by 50% of a vsync interval
--- (defaulted to 60 FPS).
---
--- WARNING: This metric should not be used as a source of truth. It is under
---          active development and the values & meaning might change without
---          notice.
-
--- Get all chrome processes and threads tables set up.
-SELECT RUN_METRIC('chrome/chrome_processes.sql');
-
--- When working on GestureScrollUpdate events we need to ensure we have all the
--- events from the browser, renderer, and GPU processes. This query isn't quite
--- perfect. In system tracing we could have 3 browser processes all in the
--- background and this would match, but for now its the best we can do (renderer
--- and GPU names on android are quite complicated, but this should filter 99% (
--- citation needed) of what we want.
---
--- See b/151077536 for historical context.
-DROP VIEW IF EXISTS sufficient_chrome_processes;
-CREATE VIEW sufficient_chrome_processes AS
-  SELECT
-    CASE WHEN (
-      SELECT COUNT(*) FROM chrome_process) = 0
-    THEN
-      FALSE
-    ELSE (
-      SELECT COUNT(*) >= 3 FROM (
-        SELECT name FROM chrome_process
-        WHERE
-          name LIKE "Browser" OR
-          name LIKE "Renderer" OR
-          name LIKE "Gpu" OR
-          name LIKE 'com.android.chrome%' OR
-          name LIKE 'com.chrome.beta%' OR
-          name LIKE 'com.chrome.dev%' OR
-          name LIKE 'com.chrome.canary%' OR
-          name LIKE 'com.google.android.apps.chrome%' OR
-          name LIKE 'org.chromium.chrome%'
-        GROUP BY name
-    )) END AS have_enough_chrome_processes;
-
--- A simple table that checks the time between VSync (this can be used to
--- determine if we're scrolling at 90 FPS or 60 FPS.
---
--- Note: In traces without the "Java" category there will be no VSync
---       TraceEvents and this table will be empty.
---
--- Note: Must be a TABLE because it uses a window function which can behave
---       strangely in views.
-DROP TABLE IF EXISTS vsync_intervals;
-CREATE TABLE vsync_intervals AS
-  SELECT
-    slice_id,
-    ts,
-    dur,
-    track_id,
-    LEAD(ts) OVER(PARTITION BY track_id ORDER BY ts) - ts AS time_to_next_vsync
-  FROM slice
-  WHERE name = "VSync"
-  ORDER BY track_id, ts;
-
--- Get all the GestureScrollBegin and GestureScrollEnd events. We take their
--- IDs to group them together into scrolls later and the timestamp and duration
--- to compute the duration of the scroll.
-DROP VIEW IF EXISTS scroll_begin_and_end;
-CREATE VIEW scroll_begin_and_end AS
-  SELECT
-    slice.name,
-    slice.id,
-    slice.ts,
-    slice.dur,
-    slice.track_id,
-    EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id')
-        AS gesture_scroll_id,
-    EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id
-  FROM
-    slice
-  WHERE
-    slice.name IN (
-      'InputLatency::GestureScrollBegin',
-      'InputLatency::GestureScrollEnd'
-    )
-  ORDER BY ts;
-
--- Now we take the GestureScrollBegin and the GestureScrollEnd events and join
--- the information into a single row per scroll. We also compute the average
--- Vysnc interval of the scroll (hopefully this would be either 60 FPS for the
--- whole scroll or 90 FPS but that isn't always the case). If the trace doesn't
--- contain the VSync TraceEvent we just fall back on assuming its 60 FPS (this
--- is the 1.6e+7 in the COALESCE which corresponds to 16 ms or 60 FPS).
-DROP VIEW IF EXISTS joined_scroll_begin_and_end;
-CREATE VIEW joined_scroll_begin_and_end AS
-  SELECT
-    begin.id AS begin_id,
-    begin.ts AS begin_ts,
-    begin.dur AS begin_dur,
-    begin.track_id AS begin_track_id,
-    begin.trace_id AS begin_trace_id,
-    COALESCE(begin.gesture_scroll_id, begin.trace_id)
-        AS begin_gesture_scroll_id,
-    end.ts AS end_ts,
-    end.ts + end.dur AS end_ts_and_dur,
-    end.trace_id AS end_trace_id,
-    COALESCE((
-      SELECT
-        CAST(AVG(time_to_next_vsync) AS FLOAT)
-      FROM vsync_intervals in_query
-      WHERE
-        time_to_next_vsync IS NOT NULL AND
-        in_query.ts > begin.ts AND
-        in_query.ts < end.ts
-    ), 1.6e+7) AS avg_vsync_interval
-  FROM scroll_begin_and_end begin JOIN scroll_begin_and_end end ON
-    begin.trace_id < end.trace_id AND
-    begin.name = 'InputLatency::GestureScrollBegin' AND
-    end.name = 'InputLatency::GestureScrollEnd' AND (
-      (
-        begin.gesture_scroll_id IS NULL AND
-        end.trace_id = (
-          SELECT MIN(trace_id)
-          FROM scroll_begin_and_end in_query
-          WHERE
-            name = 'InputLatency::GestureScrollEnd' AND
-          in_query.trace_id > begin.trace_id
-        )
-      ) OR
-      end.gesture_scroll_id = begin.gesture_scroll_id
-    )
-  ORDER BY begin.ts;
-
--- Get the GestureScrollUpdate events by name ordered by the
--- |gesture_scroll_id|, and timestamp. Then compute the number of frames (
--- relative to vsync interval) that each event took. 1.6e+7 is 16 ms in
--- nanoseconds and is used in case there are no VSync events to default to 60
--- fps. We join each GestureScrollUpdate event to the information about it'
--- begin and end events for easy computation later.
---
--- We remove updates with |dur| == -1 because this means we have no end event
--- and can't reasonably determine what it should be. We have separate tracking
--- to ensure this only happens at the end of the trace where its expected.
---
--- Note: Must be a TABLE because it uses a window function which can behave
---       strangely in views.
-DROP TABLE IF EXISTS gesture_scroll_update;
-CREATE TABLE gesture_scroll_update AS
-  SELECT
-    ROW_NUMBER() OVER (
-      ORDER BY gesture_scroll_id ASC, ts ASC) AS row_number,
-    begin_id,
-    begin_ts,
-    begin_dur,
-    begin_track_id,
-    begin_trace_id,
-    COALESCE(gesture_scroll_id, begin_trace_id) AS gesture_scroll_id,
-    CASE WHEN
-      end_ts_and_dur > ts + dur THEN
-        end_ts_and_dur
-      ELSE
-        ts + dur
-      END AS maybe_scroll_end,
-    id,
-    ts,
-    dur,
-    track_id,
-    trace_id,
-    dur/avg_vsync_interval AS scroll_frames_exact
-  FROM joined_scroll_begin_and_end begin_and_end JOIN (
-    SELECT
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-      EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id')
-          AS gesture_scroll_id,
-      *
-    FROM
-      slice JOIN track ON slice.track_id = track.id
-    WHERE
-      slice.name = 'InputLatency::GestureScrollUpdate' AND
-      slice.dur != -1 AND
-      NOT COALESCE(
-              EXTRACT_ARG(arg_set_id, "chrome_latency_info.is_coalesced"),
-              TRUE)
-  ) scroll_update ON
-  scroll_update.ts <= begin_and_end.end_ts AND
-  scroll_update.ts >= begin_and_end.begin_ts AND
-  scroll_update.trace_id > begin_and_end.begin_trace_id AND
-  scroll_update.trace_id < begin_and_end.end_trace_id AND (
-    scroll_update.gesture_scroll_id IS NULL OR
-    scroll_update.gesture_scroll_id = begin_and_end.begin_gesture_scroll_id
-  );
-
--- This takes the GestureScrollUpdate events and joins it to the previous
--- GestureScrollUpdate event (previous row and NULL if there isn't one) and the
--- next GestureScrollUpdate event (next row and again NULL if there isn't one).
--- Then we compute the duration of the event (relative to fps) and see if it
--- increased by more then 0.5 (which is 1/2 of 16 ms at 60 fps, and so on).
---
--- We only compare a GestureScrollUpdate event to another event within the same
--- scroll (gesture_scroll_id == prev/next gesture_scroll_id). This controls
--- somewhat for variability of scrolls.
---
--- Note: Must be a TABLE because it uses a window function which can behave
---       strangely in views.
-DROP TABLE IF EXISTS scroll_jank_maybe_null_prev_and_next;
-CREATE TABLE scroll_jank_maybe_null_prev_and_next AS
-  SELECT
-    currprev.*,
-    CASE WHEN
-      currprev.gesture_scroll_id != prev_gesture_scroll_id OR
-      prev_ts IS NULL OR
-      prev_ts < currprev.begin_ts OR
-      prev_ts > currprev.maybe_scroll_end
-    THEN
-      FALSE
-    ELSE
-      currprev.scroll_frames_exact > prev_scroll_frames_exact + 0.5
-    END AS prev_jank,
-    CASE WHEN
-      currprev.gesture_scroll_id != next.gesture_scroll_id OR
-      next.ts IS NULL OR
-      next.ts < currprev.begin_ts OR
-      next.ts > currprev.maybe_scroll_end
-    THEN
-      FALSE
-    ELSE
-      currprev.scroll_frames_exact > next.scroll_frames_exact + 0.5
-    END AS next_jank,
-    next.scroll_frames_exact AS next_scroll_frames_exact
-  FROM (
-    SELECT
-      curr.*,
-      curr.maybe_scroll_end - curr.begin_ts AS scroll_dur,
-      prev.ts AS prev_ts,
-      prev.gesture_scroll_id AS prev_gesture_scroll_id,
-      prev.scroll_frames_exact AS prev_scroll_frames_exact
-    FROM
-      gesture_scroll_update curr LEFT JOIN
-      gesture_scroll_update prev ON prev.row_number + 1 = curr.row_number
-  ) currprev LEFT JOIN
-  gesture_scroll_update next ON currprev.row_number + 1 = next.row_number
-  ORDER BY currprev.gesture_scroll_id ASC, currprev.ts ASC;
-
--- This just uses prev_jank and next_jank to see if each GestureScrollUpdate
--- event is a jank.
-DROP VIEW IF EXISTS scroll_jank;
-CREATE VIEW scroll_jank AS
-  SELECT
-    id AS slice_id,
-    (next_jank IS NOT NULL AND next_jank) OR
-    (prev_jank IS NOT NULL AND prev_jank)
-    AS jank,
-    *
-  FROM scroll_jank_maybe_null_prev_and_next
-  ORDER BY gesture_scroll_id ASC, ts ASC;
-
-DROP VIEW IF EXISTS scroll_jank_ms;
-
-DROP VIEW IF EXISTS scroll_jank_output;
-CREATE VIEW scroll_jank_output AS
-  SELECT
-    ScrollJank(
-      'scroll_jank_percentage', (
-        SELECT
-          (
-            SUM(CASE WHEN jank THEN dur ELSE 0 END)/CAST(SUM(dur) AS REAL)
-          ) * 100.0
-        FROM scroll_jank
-      ),
-      'scroll_ms', (
-        SELECT
-          CAST(SUM(scroll_dur)/1e6 AS REAL)
-        FROM (
-          SELECT
-            MAX(scroll_dur) AS scroll_dur
-          FROM scroll_jank
-          GROUP BY gesture_scroll_id
-        )
-      ),
-      'scroll_processing_ms', CAST(SUM(dur)/1e6 AS REAL),
-      'scroll_jank_processing_ms', (
-        SELECT CAST(SUM(dur)/1e6 AS REAL) FROM scroll_jank WHERE jank
-      ),
-      'num_scroll_update_count', COUNT(*),
-      'num_scroll_update_jank_count', SUM(jank)
-    )
-  FROM scroll_jank;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank_cause.sql b/src/trace_processor/metrics/chrome/scroll_jank_cause.sql
deleted file mode 100644
index 030ab32..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank_cause.sql
+++ /dev/null
@@ -1,84 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
--- Needed for the scroll_jank table to tell which updates were janky.
-SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
--- Causes of jank which we will join together. The process to add new causes
--- should be pretty straight forward.
---
--- 1) Determine a query (or sequence of queries) which identifies a
---    InputLatency::GestureScrollUpdate (which can be found in the scroll_jank
---    table) that was effected by the cause you are investigating.
--- 2) output the InputLatency::GestureScrollUpdate id from the slice table (or
---    scroll_jank table), along with a "true" ish value if that
---    InputLatency::GestureScrollUpdate was affected by your cause
--- 3) Add your new metric file in the SELECT RUN_METRIC lines below.
--- 4) Add a LEFT JOIN on your output table joining on the
---    InputLatency::GestureScrollUpdate id with scroll_jank_cause_joined.
--- 5) modify the scroll_jank_cause_explained_jank to include your cause.
-SELECT RUN_METRIC('chrome/scroll_jank_cause_blocking_touch_move.sql');
-SELECT RUN_METRIC('chrome/scroll_jank_cause_blocking_task.sql');
-SELECT RUN_METRIC('chrome/scroll_jank_cause_get_bitmap.sql');
-
-DROP VIEW IF EXISTS scroll_jank_cause_joined;
-CREATE VIEW scroll_jank_cause_joined AS
-  SELECT
-    COALESCE(move.blocking_touch_move, 0) AS blocking_touch_move,
-    COALESCE(task.blocked_by_language_detection, 0)
-        AS blocked_by_language_detection,
-    COALESCE(task.blocked_by_copy_request, 0) AS blocked_by_copy_request,
-    COALESCE(bitmap.blocked_by_bitmap, 0) AS blocked_by_bitmap,
-    COALESCE(bitmap.blocked_by_toolbar, 0) AS blocked_by_toolbar,
-    COALESCE(bitmap.blocked_by_bitmap_no_toolbar, 0)
-        AS blocked_by_bitmap_no_toolbar,
-    jank.*
-  FROM
-    scroll_jank jank LEFT JOIN
-    scroll_jank_cause_blocking_touch_move move
-        ON jank.id = move.scroll_id LEFT JOIN
-    scroll_jank_cause_blocking_task task
-        ON jank.id = task.scroll_id LEFT JOIN
-    scroll_jank_cause_get_bitmap bitmap
-        ON jank.id = bitmap.scroll_id;
-
-DROP VIEW IF EXISTS scroll_jank_cause_explained_jank;
-CREATE VIEW scroll_jank_cause_explained_jank AS
-  SELECT
-    CASE WHEN
-      NOT jank
-    THEN
-      FALSE
-    ELSE
-      CASE WHEN
-        blocking_touch_move OR
-        blocked_by_language_detection OR
-        blocked_by_copy_request OR
-        blocked_by_bitmap
-      THEN
-        TRUE
-      ELSE
-        FALSE
-      END
-    END AS explained_jank,
-    jank.*
-  FROM scroll_jank_cause_joined jank;
-
-DROP VIEW IF EXISTS scroll_jank_cause;
-CREATE VIEW scroll_jank_cause AS
-  SELECT
-    jank AND NOT explained_jank AS unexplained_jank,
-    jank.*
-  FROM scroll_jank_cause_explained_jank jank;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_task.sql b/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_task.sql
deleted file mode 100644
index d061413..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_task.sql
+++ /dev/null
@@ -1,294 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
--- Needed for the scroll_jank table to tell which updates were janky.
-SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
---------------------------------------------------------------------------------
--- Get all the track ids relevant to the critical path.
---------------------------------------------------------------------------------
-
--- Grab the track of the browser. sendTouchEvent is a Java category event which
--- only occurs on the browser. This saves us the trouble of dealing with all the
--- different possible names of the browser (when including system tracing).
-DROP VIEW IF EXISTS browser_main_track_id;
-CREATE VIEW browser_main_track_id AS
-SELECT
-  track_id AS id
-FROM slice
-WHERE
-  name = "sendTouchEvent"
-LIMIT 1;
-
-DROP VIEW IF EXISTS viz_compositor_track_id;
-CREATE VIEW viz_compositor_track_id AS
-SELECT
-  id
-FROM thread_track
-WHERE
-  utid = (
-    SELECT
-      utid
-    FROM thread
-    WHERE
-      name = "VizCompositorThread"
-  )
-LIMIT 1;
-
--- Grab the track of the GPU. gpu/command_buffer is a toplevel category event
--- which only occurs on the gpu main. This saves us the trouble of dealing with
--- all the different possible names of the GPU process (when including system
--- tracing).
-DROP VIEW IF EXISTS gpu_main_track_id;
-CREATE VIEW gpu_main_track_id AS
-SELECT
-  track_id AS id
-FROM slice
-WHERE
-  EXTRACT_ARG(arg_set_id, "task.posted_from.file_name") LIKE
-      "%gpu/command_buffer/service/scheduler.cc"
-LIMIT 1;
-
--- TODO(nuskos): Determine a good way to get all the renderer track_ids (each
---               scroll will have a single renderer main and a single renderer
---               compositor however different scroll updates could have
---               DIFFERENT renderers so bit tricky). Ignore this complexity for
---               now until we have a single task we want to blame jank on.
-
---------------------------------------------------------------------------------
--- Grab the last LatencyInfo.Flow for each trace_id on the browser main.
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS browser_flows;
-CREATE VIEW browser_flows AS
-SELECT
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
-  track_id,
-  max(ts) AS ts
-FROM slice
-WHERE
-  track_id = (
-    SELECT id FROM browser_main_track_id
-  ) AND
-  name = "LatencyInfo.Flow"
-  GROUP BY trace_id;
-
--- Grab the last LatencyInfo.Flow for each trace_id on the VizCompositor.
-DROP VIEW IF EXISTS viz_flows;
-CREATE VIEW viz_flows AS
-SELECT
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
-  track_id,
-  max(ts) AS ts
-FROM slice
-WHERE
-  track_id = (
-    SELECT id FROM viz_compositor_track_id
-  ) AND
-  name = "LatencyInfo.Flow"
-  GROUP BY trace_id;
-
--- Grab the last LatencyInfo.Flow for each trace_id on the GPU main.
-DROP VIEW IF EXISTS gpu_flows;
-CREATE VIEW gpu_flows AS
-SELECT
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
-  track_id,
-  max(ts) AS ts
-FROM slice
-WHERE
-  track_id = (
-    SELECT id FROM gpu_main_track_id
-  ) AND
-  name = "LatencyInfo.Flow"
-  GROUP BY trace_id;
-
---------------------------------------------------------------------------------
--- Finally join the relevant tracks/flows to the individual scrolls.
---------------------------------------------------------------------------------
-
--- Keeping only the GestureScrollUpdates join the maximum flows with their
--- associated scrolls. We only keep non-coalesced scrolls.
-DROP VIEW IF EXISTS scroll_with_browser_gpu_and_viz_flows;
-CREATE VIEW scroll_with_browser_gpu_and_viz_flows AS
-SELECT
-  scroll.trace_id,
-  scroll.scroll_id,
-  scroll.ts,
-  scroll.dur,
-  scroll.track_id,
-  browser_flows.ts AS browser_flow_ts,
-  browser_flows.flow_step AS browser_flow_step,
-  browser_flows.track_id AS browser_track_id,
-  viz_flows.ts AS viz_flow_ts,
-  viz_flows.flow_step AS viz_flow_step,
-  viz_flows.track_id AS viz_track_id,
-  gpu_flows.ts AS gpu_flow_ts,
-  gpu_flows.flow_step AS gpu_flow_step,
-  gpu_flows.track_id AS gpu_track_id
-FROM (
-  SELECT
-    trace_id,
-    id AS scroll_id,
-    ts,
-    dur,
-    track_id
-  FROM scroll_jank
-) scroll JOIN browser_flows ON
-    scroll.trace_id = browser_flows.trace_id
-  JOIN viz_flows ON viz_flows.trace_id = scroll.trace_id
-  JOIN gpu_flows ON gpu_flows.trace_id = scroll.trace_id;
-
---------------------------------------------------------------------------------
--- Below we determine individual causes of blocking tasks.
---------------------------------------------------------------------------------
-
---------------------------------------------------------------------------------
--- Determine if a CopyOutputRequest blocked any important threads.
---------------------------------------------------------------------------------
-
--- These are the events that block the Browser Main or the VizCompositor thread.
-DROP VIEW IF EXISTS blocking_browser_gpu_and_viz_copies;
-CREATE VIEW blocking_browser_gpu_and_viz_copies AS
-SELECT
-  id,
-  ts,
-  dur,
-  track_id
-FROM slice
-WHERE
-  (
-    (
-      name = "viz.mojom.CopyOutputResultSender" OR
-      name = "GLRenderer::CopyDrawnRenderPass"
-    ) AND
-    track_id = (SELECT id FROM browser_main_track_id)
-  ) OR (
-    EXTRACT_ARG(arg_set_id, "task.posted_from.file_name") LIKE
-        "%components/viz/common/frame_sinks/copy_output_request.cc" AND
-    track_id = (SELECT id FROM viz_compositor_track_id)
-  ) OR (
-    name = "SkiaOutputSurfaceImplOnGpu::CopyOutput" AND
-    track_id = (SELECT id FROM gpu_main_track_id)
-  );
-
--- Determine based on the LatencyInfo.Flow timestamp and the copy task overlap
--- if this scroll might have been delayed because of the copy.
-DROP VIEW IF EXISTS blocking_copy_tasks;
-CREATE VIEW blocking_copy_tasks AS
-SELECT
-  scroll.scroll_id,
-  scroll.trace_id,
-  copy.id,
-  copy.ts,
-  copy.dur,
-  copy.track_id,
-  CASE WHEN copy.track_id = scroll.browser_track_id THEN
-    CASE WHEN copy.ts < scroll.browser_flow_ts THEN
-      TRUE
-    ELSE
-      FALSE
-    END
-  WHEN copy.track_id = scroll.viz_track_id THEN
-    CASE WHEN copy.ts < scroll.viz_flow_ts THEN
-      TRUE
-    ELSE
-      FALSE
-    END
-  WHEN copy.track_id = scroll.gpu_track_id THEN
-    CASE WHEN copy.ts < scroll.gpu_flow_ts THEN
-      TRUE
-    ELSE
-      FALSE
-    END
-  ELSE
-    FALSE
-  END AS blocked_by_copy
-FROM
-  scroll_with_browser_gpu_and_viz_flows scroll JOIN
-  blocking_browser_gpu_and_viz_copies copy ON
-  scroll.ts + scroll.dur >= copy.ts AND
-  copy.ts + copy.dur >= scroll.ts;
-
--- Group by scroll so we can equally join one reply to the ScrollJankAndCauses
--- view.
-DROP VIEW IF EXISTS screenshot_overlapping_scrolls;
-CREATE VIEW screenshot_overlapping_scrolls AS
-SELECT
-  scroll_id, trace_id, SUM(blocked_by_copy) > 0 AS blocked_by_copy_request
-FROM blocking_copy_tasks
-GROUP BY 1, 2;
-
---------------------------------------------------------------------------------
--- Check for blocking language_detection on the browser thread
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS blocking_browser_language_detection;
-CREATE VIEW blocking_browser_language_detection AS
-SELECT
-  id,
-  ts,
-  dur,
-  track_id
-FROM slice
-WHERE
-  (
-    name = "language_detection.mojom.LanguageDetectionService" AND
-    track_id = (SELECT id FROM browser_main_track_id)
-  );
-
-DROP VIEW IF EXISTS blocking_language_detection_tasks;
-CREATE VIEW blocking_language_detection_tasks AS
-SELECT
-  scroll.scroll_id,
-  scroll.trace_id,
-  lang.id,
-  lang.ts,
-  lang.dur,
-  lang.track_id,
-  CASE WHEN lang.track_id = scroll.browser_track_id THEN
-    CASE WHEN lang.ts < scroll.browser_flow_ts THEN
-      TRUE
-    ELSE
-      FALSE
-    END
-  END AS blocked_by_language_detection
-FROM
-  scroll_with_browser_gpu_and_viz_flows scroll JOIN
-  blocking_browser_language_detection lang ON
-  scroll.ts + scroll.dur >= lang.ts AND
-  lang.ts + lang.dur >= scroll.ts;
-
-DROP VIEW IF EXISTS language_detection_overlapping_scrolls;
-CREATE VIEW language_detection_overlapping_scrolls AS
-SELECT
-  scroll_id, trace_id,
-  SUM(blocked_by_language_detection) > 0 AS blocked_by_language_detection
-FROM blocking_language_detection_tasks
-GROUP BY 1, 2;
-
---------------------------------------------------------------------------------
--- Finally join the causes together for easy grouping.
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS scroll_jank_cause_blocking_task;
-CREATE VIEW scroll_jank_cause_blocking_task AS
-  SELECT
-    lang.scroll_id,
-    lang.blocked_by_language_detection,
-    copy.blocked_by_copy_request
-  FROM
-    language_detection_overlapping_scrolls lang JOIN
-    screenshot_overlapping_scrolls copy ON copy.scroll_id = lang.scroll_id;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_touch_move.sql b/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_touch_move.sql
deleted file mode 100644
index e07bb32..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank_cause_blocking_touch_move.sql
+++ /dev/null
@@ -1,162 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank.sql');
-
--- Below we want to collect TouchMoves and figure out if they blocked any
--- GestureScrollUpdates. This table gets the TouchMove slice and joins it with
--- the data from the first flow event for that TouchMove.
-DROP TABLE IF EXISTS touch_move_and_begin_flow;
-CREATE TABLE touch_move_and_begin_flow AS
-  SELECT
-    flow.begin_flow_id,
-    flow.begin_flow_ts,
-    flow.begin_flow_track_id,
-    move.*
-  FROM (
-    SELECT
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-      *
-    FROM slice move
-    WHERE name = "InputLatency::TouchMove"
-  ) move JOIN (
-    SELECT
-      MIN(id) AS begin_flow_id,
-      track_id AS begin_flow_track_id,
-      ts AS begin_flow_ts,
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id")
-          AS begin_flow_trace_id
-    FROM slice
-    WHERE
-      name = "LatencyInfo.Flow" AND
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") IS NULL
-    GROUP BY begin_flow_trace_id
-  ) flow ON flow.begin_flow_trace_id = move.trace_id;
-
--- Now we take the TouchMove and beginning flow event and figure out if there
--- is an end flow event on the same browser track_id. This will allow us to see
--- if it was blocking because if they share the same parent stack then they
--- weren't blocking.
-DROP TABLE IF EXISTS touch_move_begin_and_end_flow;
-CREATE TABLE touch_move_begin_and_end_flow AS
-  SELECT
-    flow.end_flow_id,
-    flow.end_flow_ts,
-    flow.end_flow_track_id,
-    move.*
-  FROM touch_move_and_begin_flow move LEFT JOIN (
-    SELECT
-      MAX(id) AS end_flow_id,
-      ts AS end_flow_ts,
-      track_id AS end_flow_track_id,
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id")
-          AS end_flow_trace_id
-    FROM slice
-    WHERE
-      name = "LatencyInfo.Flow" AND
-      EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") IS NULL
-    GROUP BY end_flow_trace_id
-  ) flow ON
-      flow.end_flow_trace_id = move.trace_id AND
-      move.begin_flow_track_id = flow.end_flow_track_id AND
-      flow.end_flow_id != move.begin_flow_id
-  WHERE flow.end_flow_id IS NOT NULL;
-
--- Now that we have the begin and the end we need to find the parent stack of
--- both. If the end didn't happen on the browser (end is NULL), then we can
--- ignore it because it couldn't have generated a GestureScrollUpdate.
-DROP TABLE IF EXISTS touch_move_with_ancestor;
-CREATE TABLE touch_move_with_ancestor AS
-  SELECT
-    begin.id AS begin_ancestor_id,
-    end.id AS end_ancestor_id,
-    end.ts AS end_ancestor_ts,
-    end.dur AS end_ancestor_dur,
-    end.track_id AS end_ancestor_track_id,
-    move.*
-  FROM
-    touch_move_begin_and_end_flow move JOIN
-    ancestor_slice(begin_flow_id) begin ON begin.depth = 0 LEFT JOIN
-    ancestor_slice(end_flow_id) end ON end.depth = 0;
-
--- Now take the parent stack for the end and find if a GestureScrollUpdate was
--- launched that share the same parent as the end flow event for the TouchMove.
--- This is the GestureScrollUpdate that the TouchMove blocked (or didn't block)
--- depending on if the begin flow event is in the same stack.
-DROP TABLE IF EXISTS blocking_touch_move_with_scroll_update;
-CREATE TABLE blocking_touch_move_with_scroll_update AS
-  SELECT
-      move.begin_ancestor_id != move.end_ancestor_id AS blocking_touch_move,
-      scroll.scroll_begin_flow_id,
-      scroll.scroll_begin_flow_trace_id,
-      scroll.scroll_id,
-      move.*
-    FROM touch_move_with_ancestor move LEFT JOIN (
-      SELECT in_flow.*, in_scroll.scroll_id FROM (
-        SELECT
-          MIN(slice.id) AS scroll_begin_flow_id,
-          slice.ts AS scroll_begin_flow_ts,
-          slice.track_id AS scroll_begin_flow_track_id,
-          EXTRACT_ARG(slice.arg_set_id, "chrome_latency_info.trace_id")
-              AS scroll_begin_flow_trace_id,
-          ancestor.id AS scroll_begin_flow_ancestor_id
-        FROM
-          slice LEFT JOIN
-          ancestor_slice(slice.id) AS ancestor ON ancestor.depth = 0
-        WHERE
-          slice.name = "LatencyInfo.Flow" AND
-          EXTRACT_ARG(slice.arg_set_id, "chrome_latency_info.step") IS NULL
-        GROUP BY scroll_begin_flow_trace_id
-      ) in_flow JOIN (
-        SELECT
-          id AS scroll_id,
-          EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id")
-              AS scroll_trace_id
-        FROM slice in_scroll
-        WHERE
-          name = "InputLatency::GestureScrollUpdate" AND
-          dur != -1 AND
-          NOT EXTRACT_ARG(arg_set_id, "chrome_latency_info.is_coalesced")
-      ) in_scroll ON
-          in_scroll.scroll_trace_id = in_flow.scroll_begin_flow_trace_id
-    ) scroll ON
-      scroll.scroll_begin_flow_track_id = move.end_ancestor_track_id AND
-      scroll.scroll_begin_flow_ancestor_id = move.end_ancestor_id AND
-      scroll.scroll_begin_flow_ts > move.end_ancestor_ts AND
-      scroll.scroll_begin_flow_ts < move.end_ancestor_ts + move.end_ancestor_dur AND
-      scroll.scroll_begin_flow_id > move.end_ancestor_id
-    WHERE scroll.scroll_id IS NOT NULL;
-
--- Now filter out any TouchMoves that weren't during a complete scroll. Most of
--- the other ones will be null anyway since they won't have
--- GestureScrollUpdates.
-DROP VIEW IF EXISTS scroll_jank_cause_blocking_touch_move;
-CREATE VIEW scroll_jank_cause_blocking_touch_move AS
-   SELECT
-      id,
-      ts,
-      dur,
-      track_id,
-      blocking_touch_move,
-      scroll_id
-  FROM joined_scroll_begin_and_end begin_and_end JOIN (
-    SELECT
-      *
-    FROM blocking_touch_move_with_scroll_update
-  ) touch ON
-    touch.ts <= begin_and_end.end_ts AND
-    touch.ts > begin_and_end.begin_ts + begin_and_end.begin_dur AND
-    touch.trace_id > begin_and_end.begin_trace_id AND
-    touch.trace_id < begin_and_end.end_trace_id;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql b/src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql
deleted file mode 100644
index e0a67e0..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql
+++ /dev/null
@@ -1,187 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
--- Needed for the scroll_jank table to tell which updates were janky.
-SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
---------------------------------------------------------------------------------
--- Get all the track ids relevant to the critical path.
---------------------------------------------------------------------------------
-
--- Grab the track of the browser. sendTouchEvent is a Java category event which
--- only occurs on the browser. This saves us the trouble of dealing with all the
--- different possible names of the browser (when including system tracing).
-DROP VIEW IF EXISTS browser_main_track_id;
-CREATE VIEW browser_main_track_id AS
-SELECT
-  track_id AS id
-FROM slice
-WHERE
-  name = "sendTouchEvent"
-LIMIT 1;
-
---------------------------------------------------------------------------------
--- Grab the last LatencyInfo.Flow for each trace_id on the browser main.
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS browser_flows;
-CREATE VIEW browser_flows AS
-SELECT
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
-  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
-  track_id,
-  max(ts) AS ts
-FROM slice
-WHERE
-  track_id = (
-    SELECT id FROM browser_main_track_id
-  ) AND
-  name = "LatencyInfo.Flow"
-  GROUP BY trace_id;
-
---------------------------------------------------------------------------------
--- Join the relevant tracks/flows to the individual scrolls.
---------------------------------------------------------------------------------
-
--- Keeping only the GestureScrollUpdates join the maximum flows on the browser
--- thread. 
-DROP VIEW IF EXISTS scroll_with_browser_flows;
-CREATE VIEW scroll_with_browser_flows AS
-SELECT
-  scroll.trace_id,
-  scroll.scroll_id,
-  scroll.ts,
-  scroll.dur,
-  scroll.track_id,
-  browser_flows.ts AS browser_flow_ts,
-  browser_flows.flow_step AS browser_flow_step,
-  browser_flows.track_id AS browser_track_id
-FROM (
-  SELECT
-    trace_id,
-    id AS scroll_id,
-    ts,
-    dur,
-    track_id
-  FROM scroll_jank
-) scroll JOIN browser_flows ON
-    scroll.trace_id = browser_flows.trace_id;
-
---------------------------------------------------------------------------------
--- Below we determine if there was any bitmaps taken on the browser main.
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS get_bitmap_calls;
-CREATE VIEW get_bitmap_calls AS
-  SELECT
-    id,
-    ts,
-    dur,
-    track_id
-  FROM slice
-  WHERE
-    slice.name = "ViewResourceAdapter:getBitmap" AND
-    track_id = (SELECT id FROM browser_main_track_id);
-
-DROP VIEW IF EXISTS toolbar_bitmaps;
-CREATE VIEW toolbar_bitmaps AS
-  SELECT
-    slice.id,
-    slice.ts,
-    slice.dur,
-    slice.track_id,
-    ancestor.id AS ancestor_id
-  FROM
-    slice JOIN
-    ancestor_slice(slice.id) AS ancestor ON
-      ancestor.depth = slice.depth - 1
-  WHERE
-    slice.name = "ToolbarLayout.draw" AND
-    ancestor.name = "ViewResourceAdapter:getBitmap" AND
-    slice.track_id = (SELECT id FROM browser_main_track_id);
-
-DROP VIEW IF EXISTS get_bitmaps_and_toolbar;
-CREATE VIEW get_bitmaps_and_toolbar AS
-  SELECT
-    bitmap.id AS id,
-    bitmap.ts AS ts,
-    bitmap.dur AS dur,
-    bitmap.track_id AS track_id,
-    toolbar.id AS toolbar_id,
-    toolbar.ts AS toolbar_ts,
-    toolbar.dur AS toolbar_dur,
-    toolbar.track_id AS toolbar_track_id
-  FROM
-    get_bitmap_calls bitmap LEFT JOIN
-    toolbar_bitmaps toolbar ON
-      toolbar.ancestor_id = bitmap.id;
-
---------------------------------------------------------------------------------
--- Take bitmaps and determine if it could have been blocked by a scroll. I.E. if
--- the bitmap occurred after the start of the GestureScrollUpdate but before the
--- last flow on the browser thread (the GestureScrollUpdate can't be blocked
--- by a browser thread slice once its done on the browser thread).
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS blocking_bitmap_tasks;
-CREATE VIEW blocking_bitmap_tasks AS
-SELECT
-  scroll.scroll_id,
-  scroll.trace_id,
-  bitmap.id,
-  bitmap.ts,
-  bitmap.dur,
-  bitmap.track_id,
-  CASE WHEN
-      bitmap.track_id = scroll.browser_track_id AND
-      bitmap.ts < scroll.browser_flow_ts THEN
-    TRUE
-  ELSE
-    FALSE
-  END AS blocked_by_bitmap,
-  CASE WHEN
-      bitmap.track_id = scroll.browser_track_id AND
-      bitmap.toolbar_id IS NOT NULL AND
-      bitmap.ts < scroll.browser_flow_ts THEN
-    TRUE
-  ELSE
-    FALSE
-  END AS blocked_by_toolbar,
-  CASE WHEN
-      bitmap.track_id = scroll.browser_track_id AND
-      bitmap.toolbar_id IS NULL AND
-      bitmap.ts < scroll.browser_flow_ts THEN
-    TRUE
-  ELSE
-    FALSE
-  END AS blocked_by_bitmap_no_toolbar
-FROM
-  scroll_with_browser_flows scroll JOIN
-  get_bitmaps_and_toolbar bitmap ON
-  scroll.ts + scroll.dur >= bitmap.ts AND
-  bitmap.ts + bitmap.dur >= scroll.ts;
-
-
---------------------------------------------------------------------------------
--- Remove duplicate tasks blocking so that there is only a boolean per
--- scroll_id.
---------------------------------------------------------------------------------
-DROP VIEW IF EXISTS scroll_jank_cause_get_bitmap;
-CREATE VIEW scroll_jank_cause_get_bitmap AS
-SELECT
-  scroll_id,
-  trace_id,
-  SUM(blocked_by_bitmap) > 0 AS blocked_by_bitmap,
-  SUM(blocked_by_toolbar) > 0 AS blocked_by_toolbar,
-  SUM(blocked_by_bitmap_no_toolbar) > 0 AS blocked_by_bitmap_no_toolbar
-FROM blocking_bitmap_tasks
-GROUP BY 1, 2;
diff --git a/src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql b/src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql
deleted file mode 100644
index a57fe70..0000000
--- a/src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql
+++ /dev/null
@@ -1,306 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_thread_slice_with_cpu_time.sql');
-SELECT RUN_METRIC('chrome/scroll_flow_event_queuing_delay.sql');
-
--- See b/184134310 why we remove ThreadController active.
-DROP VIEW IF EXISTS blocking_tasks_no_threadcontroller_active;
-CREATE VIEW blocking_tasks_no_threadcontroller_active AS
- SELECT
-    slice.*,
-    ancestor.id AS task_ancestor_id,
-    ancestor.name AS task_ancestor_name
-  FROM
-    chrome_thread_slice_with_cpu_time AS slice LEFT JOIN
-    ancestor_slice(slice.id) as ancestor ON ancestor.id = slice.parent_id
-  WHERE
-    slice.name != "ThreadController active" AND
-    (slice.depth = 0 OR ancestor.name = "ThreadController active");
-
--- This view grabs any slice that could have prevented any GestureScrollUpdate
--- flow event from being run (queuing delays). For RunTask we know that its
--- generic (and thus hard to figure out whats the cause) so we grab the src
--- location to make it more meaningful.
---
--- See b/166441398 & crbug/1094361 for why we remove the -to-End step. In
--- essence -to-End is often reported on the ThreadPool after the fact with
--- explicit timestamps so it being blocked isn't noteworthy.
---
--- See b/184134310 for why we allow depth == 1 and ancestor.id is null (which
--- implies its a "ThreadController active" slice because we removed it
--- previously).
-DROP TABLE IF EXISTS blocking_tasks_queuing_delay;
-CREATE TABLE blocking_tasks_queuing_delay AS
-  SELECT
-    EXTRACT_ARG(slice.arg_set_id, "task.posted_from.file_name") as file,
-    EXTRACT_ARG(slice.arg_set_id, "task.posted_from.function_name") as function,
-    trace_id,
-    queuing_time_ns,
-    next_track_id,
-    CASE WHEN queuing.ancestor_end <= slice.ts THEN
-      CASE WHEN slice.ts + slice.dur <= queuing.maybe_next_ancestor_ts THEN
-        slice.dur
-      ELSE
-        queuing.maybe_next_ancestor_ts - slice.ts
-      END
-    ELSE
-      CASE WHEN slice.ts + slice.dur <= queuing.maybe_next_ancestor_ts THEN
-        slice.ts + slice.dur - queuing.ancestor_end
-      ELSE
-        queuing.maybe_next_ancestor_ts - queuing.ancestor_end
-      END
-    END AS dur_overlapping_ns,
-    description,
-    scroll_slice_id,
-    scroll_ts,
-    scroll_dur,
-    scroll_track_id,
-    jank,
-    slice.*
-  FROM
-    scroll_flow_event_queuing_delay queuing JOIN
-    blocking_tasks_no_threadcontroller_active AS slice ON
-        slice.ts + slice.dur > queuing.ancestor_end AND
-        queuing.maybe_next_ancestor_ts > slice.ts AND
-        slice.track_id = queuing.next_track_id AND
-        queuing.description NOT LIKE
-            "InputLatency.LatencyInfo.%ank.STEP_DRAW_AND_SWAP-to-End" AND
-        queuing.description NOT LIKE
-            "InputLatency.LatencyInfo.%ank.STEP_FINISHED_SWAP_BUFFERS-to-End"
-  WHERE
-    queuing_time_ns IS NOT NULL AND
-    queuing_time_ns > 0;
-
--- Now for each toplevel task (depth = 0 from above) we want to grab all their
--- children slices. This is done by joining on descendant_slice which is a
--- trace processor defined operator. This will results in 1 row for every
--- descendant slice. So all fields in base.* will be repeated ONCE for each
--- child, but if it has no slice it will occur only once but all the
--- |descendant_.*| fields will be NULL because of the LEFT JOIN.
--- Additionally for mojo events, append "(interface_name)" to the end of the
--- descendant name.
-DROP VIEW IF EXISTS all_descendant_blocking_tasks_queuing_delay;
-CREATE VIEW all_descendant_blocking_tasks_queuing_delay AS
-  SELECT
-    descendant.id AS descendant_id,
-    descendant.ts AS descendant_ts,
-    descendant.dur AS descendant_dur,
-    COALESCE(descendant.name || "(" ||
-      IIF(descendant.arg_set_id IS NOT NULL,
-          EXTRACT_ARG(descendant.arg_set_id,
-              "chrome_mojo_event_info.watcher_notify_interface_tag"),
-          NULL) || ")",
-      descendant.name) AS descendant_name,
-    descendant.parent_id As descendant_parent_id,
-    descendant.depth AS descendant_depth,
-    base.*
-  FROM
-    blocking_tasks_queuing_delay base LEFT JOIN
-    descendant_slice(base.id) AS descendant;
-
-DROP TABLE IF EXISTS all_descendant_blocking_tasks_queuing_delay_with_cpu_time;
-CREATE TABLE all_descendant_blocking_tasks_queuing_delay_with_cpu_time AS
-  SELECT
-    cpu.slice_cpu_time AS descendant_slice_cpu_time,
-    cpu.slice_cpu_time / descendant.slice_cpu_time AS descendant_cpu_percentage,
-    cpu.slice_cpu_time /
-        (descendant.slice_cpu_time /
-          (1 << (descendant.descendant_depth - 1))) > 0.5
-            AS descendant_cpu_time_above_relative_threshold,
-    descendant_dur / descendant.dur AS descendant_dur_percentage,
-    descendant_dur /
-        (descendant.dur / (1 << (descendant.descendant_depth - 1))) > 0.5
-        AS descendant_dur_above_relative_threshold,
-    descendant.*
-  FROM
-    all_descendant_blocking_tasks_queuing_delay descendant LEFT JOIN (
-      SELECT
-        id, slice_cpu_time
-      FROM chrome_thread_slice_with_cpu_time
-    ) AS cpu ON
-        cpu.id = descendant.descendant_id;
-
--- Now that we've generated the descendant count how many siblings each row
--- has. Recall that all the top level tasks are repeated but each row represents
--- a descendant slice. This means since we LEFT JOIN we will say a slice has 0
--- siblings if it has no descendants (which is true), and otherwise we will
--- compute the siblings as the count of all slices with the same parent minus
--- the current slice.
-DROP VIEW IF EXISTS counted_descendant_blocking_tasks_queuing_delay;
-CREATE VIEW counted_descendant_blocking_tasks_queuing_delay AS
-  SELECT
-    base.*,
-    COALESCE(single_descendant.number_of_siblings, 0) AS number_of_siblings
-  FROM
-    all_descendant_blocking_tasks_queuing_delay_with_cpu_time base LEFT JOIN (
-      SELECT
-        descendant_parent_id,
-        COUNT(*) - 1 AS number_of_siblings
-      FROM all_descendant_blocking_tasks_queuing_delay_with_cpu_time
-      WHERE descendant_parent_id IS NOT NULL
-      GROUP BY 1
-  ) single_descendant ON
-      single_descendant.descendant_parent_id = base.descendant_parent_id;
-
--- Now we group by the |id| which is the top level task id and find the first
--- descendant_depth where we have a sibling. We need this because we only want
--- to include single descendant slices in our metric name to keep it easy to
--- reason about what that code is doing.
-DROP VIEW IF EXISTS blocking_tasks_queuing_delay_with_invalid_depth;
-CREATE VIEW blocking_tasks_queuing_delay_with_invalid_depth AS
-  SELECT
-    base.*,
-    (
-      descendant_cpu_time_above_relative_threshold AND
-      descendant_cpu_percentage > 0.05
-    ) OR (
-      descendant_dur_above_relative_threshold AND
-      descendant_dur_percentage > 0.05
-    ) AS descendant_major_slice,
-    COALESCE(depth.invalid_depth, 10) AS invalid_depth
-  FROM
-    counted_descendant_blocking_tasks_queuing_delay base LEFT JOIN (
-      SELECT
-        id,
-        MIN(descendant_depth) AS invalid_depth
-      FROM counted_descendant_blocking_tasks_queuing_delay
-      WHERE number_of_siblings >= 1
-      GROUP BY 1
-    ) AS depth ON base.id = depth.id
-  ORDER BY
-    descendant_depth ASC,
-    descendant_cpu_percentage DESC,
-    descendant_dur_percentage DESC;
-
--- Now to get back to a single output per top level task we group by all the
--- toplevel fields and aggregate the descendant fields. We only include the
--- descendant if their depth is less than the first depth with siblings (the
--- |invalid_depth|).
-DROP VIEW IF EXISTS descendant_blocking_tasks_queuing_delay;
-CREATE VIEW descendant_blocking_tasks_queuing_delay AS
-  SELECT
-    id,
-    ts,
-    dur,
-    track_id,
-    trace_id,
-    name,
-    scroll_slice_id AS scroll_id,
-    scroll_ts,
-    scroll_dur,
-    scroll_track_id,
-    jank,
-    queuing_time_ns,
-    dur_overlapping_ns,
-    description,
-    replace(file, rtrim(file, replace(file, '/', '')), '') AS file,
-    function,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_id
-      ELSE
-        NULL
-      END
-    , "-") AS descendant_id,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_ts
-      ELSE
-        NULL
-      END
-    , "-") AS descendant_ts,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_dur
-      ELSE
-        NULL
-      END
-    , "-") AS descendant_dur,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_name
-      ELSE
-        NULL
-      END, "-") AS descendant_name,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_slice_cpu_time
-      ELSE
-        NULL
-      END
-    , "-") AS descendant_slice_cpu_time,
-    GROUP_CONCAT(
-      CASE WHEN descendant_depth < invalid_depth OR descendant_major_slice THEN
-        descendant_cpu_percentage
-      ELSE
-        NULL
-      END
-    , "-") AS descendant_cpu_time
-  FROM
-    blocking_tasks_queuing_delay_with_invalid_depth
-  GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-  ORDER BY descendant_cpu_percentage DESC;
-
--- Create a common name for each "cause" based on the slice stack we found.
-DROP VIEW IF EXISTS scroll_jank_cause_queuing_delay_temp;
-CREATE VIEW scroll_jank_cause_queuing_delay_temp AS
-  SELECT
-    CASE WHEN name = "ThreadControllerImpl::RunTask" THEN
-      'posted-from-' || function || '()-in-' || file
-    ELSE
-      name
-    END || COALESCE("-" || descendant_name, "") AS location,
-
-    base.*
-  FROM descendant_blocking_tasks_queuing_delay base;
-
--- Figure out the average time taken during non-janky scrolls updates for each
--- TraceEvent (metric_name) stack.
-DROP VIEW IF EXISTS scroll_jank_cause_queuing_delay_average_no_jank_time;
-CREATE VIEW scroll_jank_cause_queuing_delay_average_no_jank_time AS
-  SELECT
-    location,
-    AVG(dur_overlapping_ns) as avg_dur_overlapping_ns
-  FROM scroll_jank_cause_queuing_delay_temp
-  WHERE NOT jank
-  GROUP BY 1;
-
--- Join every row (jank and non-jank with the average non-jank time for the
--- given metric_name).
-DROP VIEW IF EXISTS scroll_jank_cause_queuing_delay_unannotated;
-CREATE VIEW scroll_jank_cause_queuing_delay_unannotated AS
-  SELECT
-    base.*,
-    'InputLatency.LatencyInfo.Flow.QueuingDelay.' ||
-    CASE WHEN jank THEN 'Jank' ELSE 'NoJank' END || '.BlockingTasksUs.' ||
-      base.location as metric_name,
-    COALESCE(avg_no_jank.avg_dur_overlapping_ns, 0)
-        AS avg_no_jank_dur_overlapping_ns
-  FROM
-    scroll_jank_cause_queuing_delay_temp base LEFT JOIN
-    scroll_jank_cause_queuing_delay_average_no_jank_time avg_no_jank ON
-        base.location = avg_no_jank.location;
-
--- Annotate with process and thread names.
-DROP VIEW IF EXISTS scroll_jank_cause_queuing_delay;
-CREATE VIEW scroll_jank_cause_queuing_delay AS
-SELECT p.process_type AS process_name, ct.canonical_name AS thread_name, s.*
-FROM scroll_jank_cause_queuing_delay_unannotated s,
-  thread_track tt, chrome_thread ct,
-  chrome_process p
-WHERE s.track_id = tt.id
-  AND tt.utid = ct.utid
-  AND ct.upid = p.upid;
diff --git a/src/trace_processor/metrics/chrome/test_chrome_metric.sql b/src/trace_processor/metrics/chrome/test_chrome_metric.sql
deleted file mode 100644
index 2e9ee32..0000000
--- a/src/trace_processor/metrics/chrome/test_chrome_metric.sql
+++ /dev/null
@@ -1,18 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 test_chrome_metric_output;
-CREATE VIEW test_chrome_metric_output AS
-SELECT TestChromeMetric('test_value', 1)
diff --git a/src/trace_processor/metrics/custom_options.descriptor.h b/src/trace_processor/metrics/custom_options.descriptor.h
new file mode 100644
index 0000000..c7edf8d
--- /dev/null
+++ b/src/trace_processor/metrics/custom_options.descriptor.h
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CUSTOM_OPTIONS_DESCRIPTOR_H_
+#define SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_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)
+// 3df80477da2ea38cc659967487b37051a154bb69
+// SHA1(protos/perfetto/metrics/custom_options.proto)
+// 074c971d85f72345988fb3279345cd6b3dabde9c
+
+// This is the proto CustomOptions encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 7803> kCustomOptionsDescriptor{
+    {0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
+     0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
+     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
+     0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+     0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
+     0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+     0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
+     0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
+     0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
+     0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
+     0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
+     0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
+     0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
+     0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
+     0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
+     0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
+     0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+     0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
+     0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
+     0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
+     0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+     0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+     0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
+     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
+     0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
+     0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+     0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+     0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+     0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
+     0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
+     0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
+     0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+     0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
+     0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
+     0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
+     0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+     0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
+     0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
+     0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
+     0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
+     0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+     0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
+     0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
+     0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
+     0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
+     0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
+     0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+     0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
+     0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+     0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+     0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+     0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+     0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
+     0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
+     0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+     0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
+     0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
+     0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
+     0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
+     0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+     0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+     0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
+     0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
+     0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
+     0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
+     0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
+     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
+     0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
+     0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+     0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
+     0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
+     0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+     0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
+     0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
+     0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
+     0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
+     0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
+     0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
+     0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
+     0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
+     0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
+     0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
+     0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
+     0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
+     0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
+     0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
+     0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
+     0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
+     0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
+     0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
+     0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
+     0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
+     0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
+     0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
+     0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
+     0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
+     0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
+     0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
+     0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
+     0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
+     0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
+     0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
+     0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
+     0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
+     0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
+     0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+     0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+     0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+     0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
+     0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
+     0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
+     0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+     0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+     0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+     0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+     0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+     0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+     0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
+     0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
+     0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
+     0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
+     0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
+     0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
+     0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
+     0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
+     0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
+     0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+     0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
+     0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
+     0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
+     0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
+     0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+     0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
+     0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
+     0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
+     0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
+     0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
+     0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
+     0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
+     0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
+     0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
+     0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
+     0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
+     0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
+     0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
+     0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
+     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
+     0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
+     0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
+     0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
+     0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
+     0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
+     0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
+     0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
+     0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
+     0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+     0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
+     0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
+     0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
+     0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+     0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
+     0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
+     0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
+     0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+     0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
+     0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+     0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+     0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
+     0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
+     0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
+     0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
+     0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
+     0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
+     0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
+     0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
+     0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
+     0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
+     0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+     0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
+     0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
+     0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
+     0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+     0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
+     0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
+     0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
+     0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+     0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
+     0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
+     0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
+     0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
+     0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+     0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
+     0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
+     0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
+     0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+     0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+     0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
+     0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
+     0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+     0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
+     0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
+     0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
+     0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
+     0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
+     0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+     0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
+     0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
+     0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
+     0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
+     0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
+     0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
+     0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
+     0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
+     0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+     0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
+     0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
+     0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
+     0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
+     0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
+     0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
+     0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
+     0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
+     0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
+     0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
+     0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
+     0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
+     0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
+     0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+     0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
+     0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
+     0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
+     0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+     0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+     0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+     0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
+     0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
+     0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
+     0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
+     0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
+     0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
+     0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
+     0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
+     0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
+     0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+     0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
+     0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
+     0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+     0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+     0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
+     0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
+     0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
+     0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
+     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+     0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
+     0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+     0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
+     0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
+     0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+     0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
+     0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
+     0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
+     0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+     0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
+     0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+     0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
+     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+     0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
+     0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
+     0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
+     0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+     0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
+     0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
+     0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
+     0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
+     0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
+     0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
+     0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
+     0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
+     0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
+     0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+     0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
+     0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
+     0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
+     0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
+     0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
+     0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
+     0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
+     0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
+     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
+     0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
+     0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+     0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
+     0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
+     0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
+     0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
+     0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
+     0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
+     0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+     0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
+     0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
+     0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+     0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
+     0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
+     0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
+     0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
+     0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
+     0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
+     0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
+     0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
+     0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+     0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
+     0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+     0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
+     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
+     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
+     0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+     0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
+     0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+     0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
+     0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
+     0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
+     0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
+     0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
+     0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
+     0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
+     0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
+     0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
+     0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
+     0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+     0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
+     0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
+     0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
+     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
+     0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
+     0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
+     0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
+     0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+     0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
+     0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
+     0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0xda,
+     0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x73, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+     0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x33, 0x0a,
+     0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x18, 0xd1, 0x86, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e,
+     0x69, 0x74, 0x3a, 0x53, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76,
+     0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+     0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
+     0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd2, 0x86,
+     0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f,
+     0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
+     0x69, 0x6f, 0x6e}};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
diff --git a/src/trace_processor/metrics/experimental/blink_gc_metric.sql b/src/trace_processor/metrics/experimental/blink_gc_metric.sql
deleted file mode 100644
index 096d9c3..0000000
--- a/src/trace_processor/metrics/experimental/blink_gc_metric.sql
+++ /dev/null
@@ -1,581 +0,0 @@
--- Maps non-aggregated Blink GC events in timeline to telemetry friendly
--- names.
---
--- This includes the old style or the new naming scheme one which only occur on
--- the main thread.
-DROP VIEW IF EXISTS blink_non_aggregated_gc_event_name;
-CREATE VIEW blink_non_aggregated_gc_event_name AS
-SELECT
-  'BlinkGC.AtomicPauseMarkEpilogue' AS name,
-  'blink-gc-atomic-pause-mark-epilogue' AS old_event_name,
-  'blink:gc:main_thread:cycle:full:atomic:mark:epilogue' AS new_event_name
-UNION ALL
-SELECT
-  'BlinkGC.AtomicPauseMarkPrologue',
-  'blink-gc-atomic-pause-mark-prologue',
-  'blink:gc:main_thread:cycle:full:atomic:mark:prologue'
-UNION ALL
-SELECT
-  'BlinkGC.AtomicPauseMarkRoots',
-  'blink-gc-atomic-pause-mark-roots',
-  'blink:gc:main_thread:cycle:full:atomic:mark:roots'
-UNION ALL
-SELECT
-  'BlinkGC.IncrementalMarkingStartMarking',
-  'blink-gc-incremental-start',
-  'blink:gc:main_thread:cycle:full:incremental:mark:start'
-UNION ALL
-SELECT
-  'BlinkGC.IncrementalMarkingStep',
-  'blink-gc-incremental-step',
-  'blink:gc:main_thread:cycle:full:incremental:mark:step'
-UNION ALL
-SELECT
-  'BlinkGC.UnifiedMarkingStep',
-  'blink-gc-unified-marking-by-v8',
-  'unified:gc:main_thread:cycle:full:mark:step'
-UNION ALL
-SELECT
-  'BlinkGC.CompleteSweep',
-  'blink-gc-complete-sweep',
-  'blink:gc:main_thread:cycle:full:sweep:complete'
-UNION ALL
-SELECT
-  'BlinkGC.LazySweepInIdle',
-  'blink-gc-sweep-task-foreground',
-  'blink:gc:main_thread:cycle:full:sweep:idle'
-UNION ALL
-SELECT
-  'BlinkGC.LazySweepOnAllocation',
-  'blink-gc-sweep-allocation',
-  'blink:gc:main_thread:cycle:full:sweep:on_allocation'
-UNION ALL
-SELECT
-  'BlinkGC.AtomicPauseSweepAndCompact' AS name,
-  'blink-gc-atomic-pause-sweep-and-compact' AS old_event_name,
-  'blink:gc:main_thread:cycle:full:atomic:sweep:compact' AS new_event_name;
-
--- Get all the slices we care about. These are ones that start with V8.GC or
--- BlinkGC. If you need more you need to modify the where clause for
--- blink_gc_cpu_slice.
-DROP TABLE IF EXISTS blink_gc_cpu_slice;
-CREATE TABLE blink_gc_cpu_slice AS
-SELECT
-  CASE WHEN dur != 0 THEN cpuDurNs/1e6 ELSE 0.0 END AS cpuDurMs,
-  *
-FROM (
-  SELECT
-    COALESCE(EXTRACT_ARG(arg_set_id, 'debug.forced'), FALSE) OR
-    -- This subquery replaces
-    -- metrics.v8.utils.isForcedGarbageCollectionEvent(event)
-    (
-      SELECT
-        id
-      FROM ANCESTOR_SLICE(slice.id) AS ancestor
-      WHERE ancestor.name = 'V8.GCLowMemoryNotification' LIMIT 1
-    ) IS NOT NULL AS forced,
-    -- upid replaces pid, because its more fool proof ensuring uniqueness.
-    thread.upid || ':' || EXTRACT_ARG(arg_set_id, 'debug.epoch') AS epoch,
-    slice.thread_dur AS cpuDurNs,
-    slice.*
-  FROM thread_slice as slice
-  INNER JOIN thread_track ON slice.track_id = thread_track.id
-  INNER JOIN thread ON thread_track.utid = thread.id
-  WHERE
-    slice.dur >= 0 AND (
-    slice.name LIKE "V8.GC%" OR (slice.name LIKE "BlinkGC%" AND NOT forced)
-  )
-);
-
--- This grabs all the single events for "BlinkGC.*", and restricts to only
--- forced events.
-DROP TABLE IF EXISTS blink_slice;
-CREATE TABLE blink_slice AS
-SELECT
-  event_name.old_event_name AS blink_non_aggregated_gc_event_name,
-  event_name.new_event_name AS blink_non_aggregated_gc_events_new_name,
-  blink_gc_cpu_slice.*
-FROM
-  blink_gc_cpu_slice LEFT JOIN
-  blink_non_aggregated_gc_event_name AS event_name ON
-      event_name.name = blink_gc_cpu_slice.name
-WHERE
-  blink_gc_cpu_slice.name LIKE "BlinkGC%" AND NOT forced;
-
--- This groups all the events by name and epoch for from "blink_slice" for easy
--- access.
-DROP TABLE IF EXISTS blink_per_epoch_slice;
-CREATE TABLE blink_per_epoch_slice AS
-SELECT
-  name,
-  epoch,
-  blink_non_aggregated_gc_event_name,
-  blink_non_aggregated_gc_events_new_name,
-  SUM(cpuDurMs) AS cpuDurPerEpochMs
-FROM blink_slice
-GROUP BY 1, 2, 3, 4;
-
--- All events that should be summed up to 'blink-gc-mark-roots'.
-DROP VIEW IF EXISTS blink_top_gc_roots_marking_event;
-CREATE VIEW blink_top_gc_roots_marking_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.VisitRoots'
-);
-
--- All events that should be summed up to
--- 'blink-gc-atomic-pause-mark-transitive-closure'.
-DROP VIEW IF EXISTS blink_gc_atomic_pause_transitive_closure_event;
-CREATE VIEW blink_gc_atomic_pause_transitive_closure_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.AtomicPauseMarkTransitiveClosure'
-);
-
--- All events that should be summed up to 'blink-gc-mark-transitive-closure'.
-DROP VIEW IF EXISTS blink_gc_foreground_marking_transitive_closure_event;
-CREATE VIEW
-      blink_gc_foreground_marking_transitive_closure_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.AtomicPauseMarkTransitiveClosure',
-  'BlinkGC.IncrementalMarkingStep',
-  'BlinkGC.UnifiedMarkingStep'
-);
-
--- Names of Blink GC foreground marking events in timeline.
-DROP VIEW IF EXISTS blink_top_gc_foreground_marking_event;
-CREATE VIEW blink_top_gc_foreground_marking_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.AtomicPauseMarkEpilogue',
-  'BlinkGC.AtomicPauseMarkPrologue',
-  'BlinkGC.AtomicPauseMarkRoots',
-  'BlinkGC.IncrementalMarkingStartMarking'
-)
-UNION ALL
-SELECT * FROM blink_gc_foreground_marking_transitive_closure_event;
-
--- Names of Blink GC foreground marking events in timeline.
-DROP VIEW IF EXISTS blink_gc_forced_foreground_marking_event;
-CREATE VIEW blink_gc_forced_foreground_marking_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.AtomicPauseMarkEpilogue',
-  'BlinkGC.AtomicPauseMarkPrologue',
-  'BlinkGC.AtomicPauseMarkRoots',
-  'BlinkGC.IncrementalMarkingStartMarking',
-  'BlinkGC.MarkBailOutObjects',
-  'BlinkGC.MarkFlushV8References',
-  'BlinkGC.MarkFlushEphemeronPairs'
-);
-
--- Names of Blink GC background marking events in timeline.
-DROP VIEW IF EXISTS blink_top_gc_background_marking_event;
-CREATE VIEW blink_top_gc_background_marking_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.ConcurrentMarkingStep'
-);
-
--- Names of Blink GC foreground sweeping events in timeline.
-DROP VIEW IF EXISTS blink_top_gc_foreground_sweeping_event;
-CREATE VIEW blink_top_gc_foreground_sweeping_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.CompleteSweep',
-  'BlinkGC.LazySweepInIdle',
-  'BlinkGC.LazySweepOnAllocation'
-);
-
--- Names of Blink GC background sweeping events in timeline.
-DROP VIEW IF EXISTS blink_top_gc_background_sweeping_event;
-CREATE VIEW blink_top_gc_background_sweeping_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.ConcurrentSweepingStep'
-);
-
--- Names of all Blink Unified GC events in timeline.
-DROP VIEW IF EXISTS blink_top_gc_event;
-CREATE VIEW blink_top_gc_event AS
-SELECT * FROM blink_slice WHERE name in (
-  SELECT name FROM blink_non_aggregated_gc_event_name
-) OR name in (
-  SELECT name FROM blink_gc_atomic_pause_transitive_closure_event
-);
-
--- All events that should be summed up to 'blink-gc-atomic-pause'. Note that
--- this events need to have an epoch counter in args.epoch.
-DROP VIEW IF EXISTS atomic_pause_event;
-CREATE VIEW atomic_pause_event AS
-SELECT * FROM blink_slice WHERE name in (
-  'BlinkGC.AtomicPauseMarkEpilogue',
-  'BlinkGC.AtomicPauseMarkPrologue',
-  'BlinkGC.AtomicPauseMarkRoots',
-  'BlinkGC.AtomicPauseMarkTransitiveClosure',
-  'BlinkGC.AtomicPauseSweepAndCompact'
-);
-
--- This is a more complex variable so benefits from additional comments so we
--- pull it out of the proto filling.
-DROP VIEW IF EXISTS unified_gc_total;
-CREATE VIEW unified_gc_total AS
-SELECT
-  *
-FROM blink_gc_cpu_slice
-WHERE (
-  -- This subclause replaces
-  -- metrics.v8.utils.isNotForcedTopGarbageCollectionEvent()
-
-  -- These names are found in isTopGarbageCollectionEvent().
-  name in (
-    'V8.GCCompactor',
-    'V8.GCFinalizeMC',
-    'V8.GCFinalizeMCReduceMemory',
-    'V8.GCIncrementalMarking',
-    'V8.GCIncrementalMarkingFinalize',
-    'V8.GCIncrementalMarkingStart',
-    'V8.GCPhantomHandleProcessingCallback',
-    'V8.GCScavenger'
-  ) AND (
-    -- This replaces isForcedGarbageCollectionEvent.
-    SELECT name FROM ANCESTOR_SLICE(blink_gc_cpu_slice.id) AS ancestor
-    WHERE ancestor.name == 'V8.GCLowMemoryNotification'
-    LIMIT 1
-  ) IS NULL
-) OR (
-  -- This subclause replaces isNonNestedNonForcedBlinkGarbageCollectionEvent().
-  name IN (
-    -- This subquery replaces isNonForcedBlinkGarbageCollectionEvent().
-    SELECT name FROM blink_top_gc_event
-  ) AND (
-    -- This subquery replaces metrics.v8.utils.isGarbageCollectionEvent().
-    SELECT name FROM ANCESTOR_SLICE(blink_gc_cpu_slice.id) AS ancestor
-    WHERE
-      ancestor.name LIKE "V8.GC%" AND
-      ancestor.name != 'V8.GCLowMemoryNotification'
-    LIMIT 1
-  ) IS NULL
-);
-
--- This table name is just "file_name" + "_output" used by TBMv3 to know which
--- view to extract the proto BlinkGcMetric out of.
-DROP VIEW IF EXISTS blink_gc_metric_output;
-CREATE VIEW blink_gc_metric_output AS
-SELECT BlinkGcMetric(
-  'blink_gc_atomic_pause_mark_epilogue',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE
-      blink_non_aggregated_gc_event_name = 'blink-gc-atomic-pause-mark-epilogue'
-  ),
-  'blink_gc_main_thread_cycle_full_atomic_mark_epilogue',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:atomic:mark:epilogue'
-  ),
-  'blink_gc_atomic_pause_mark_prologue',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE
-      blink_non_aggregated_gc_event_name =
-          'blink-gc-atomic-pause-mark-prologue'
-  ),
-  'blink_gc_main_thread_cycle_full_atomic_mark_prologue',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:atomic:mark:prologue'
-  ),
-  'blink_gc_atomic_pause_mark_roots',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE
-      blink_non_aggregated_gc_event_name = 'blink-gc-atomic-pause-mark-roots'
-  ),
-  'blink_gc_main_thread_cycle_full_atomic_mark_roots',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:atomic:mark:roots'
-  ),
-  'blink_gc_atomic_pause_sweep_and_compact',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE
-      blink_non_aggregated_gc_event_name =
-          'blink-gc-atomic-pause-sweep-and-compact'
-  ),
-  'blink_gc_main_thread_cycle_full_atomic_sweep_compact',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:atomic:sweep:compact'
-  ),
-  'blink_gc_complete_sweep',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-complete-sweep'
-  ),
-  'blink_gc_main_thread_cycle_full_sweep_complete',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:sweep:complete'
-  ),
-  'blink_gc_incremental_start',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-incremental-start'
-  ),
-  'blink_gc_main_thread_cycle_full_incremental_mark_start',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:incremental:mark:start'
-  ),
-  'blink_gc_incremental_step',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-incremental-step'
-  ),
-  'blink_gc_main_thread_cycle_full_incremental_mark_step',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:incremental:mark:step'
-  ),
-  'blink_gc_sweep_allocation',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-sweep-allocation'
-  ),
-  'blink_gc_main_thread_cycle_full_sweep_on_allocation',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:sweep:on_allocation'
-  ),
-  'blink_gc_sweep_task_foreground',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-sweep-task-foreground'
-  ),
-  'blink_gc_main_thread_cycle_full_sweep_idle',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'blink:gc:main_thread:cycle:full:sweep:idle'
-  ),
-  'blink_gc_unified_marking_by_v8',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_slice
-    WHERE blink_non_aggregated_gc_event_name = 'blink-gc-unified-marking-by-v8'
-  ),
-  'unified_gc_main_thread_cycle_full_mark_step',
-  (
-    SELECT
-      RepeatedField(cpuDurPerEpochMs)
-    FROM blink_per_epoch_slice
-    WHERE
-      blink_non_aggregated_gc_events_new_name =
-          'unified:gc:main_thread:cycle:full:mark:step'
-  ),
-  'blink_gc_atomic_pause',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM atomic_pause_event
-  ),
-  'blink_gc_main_thread_cycle_full_atomic',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM atomic_pause_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_atomic_pause_mark_transitive_closure',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_gc_atomic_pause_transitive_closure_event
-  ),
-  'blink_gc_main_thread_cycle_full_atomic_mark_transitive_closure',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_gc_atomic_pause_transitive_closure_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_total',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_event
-  ),
-  'blink_gc_main_thread_cycle_full',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_mark_roots',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_roots_marking_event
-  ),
-  'blink_gc_main_thread_cycle_full_mark_roots',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_roots_marking_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_mark_transitive_closure',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_gc_foreground_marking_transitive_closure_event
-  ),
-  'blink_gc_main_thread_cycle_full_mark_transitive_closure',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_gc_foreground_marking_transitive_closure_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_mark_foreground',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_foreground_marking_event
-  ),
-  'blink_gc_main_thread_cycle_full_mark',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_foreground_marking_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_mark_foreground_forced',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_gc_forced_foreground_marking_event
-  ),
-  'blink_gc_main_thread_cycle_full_mark_forced',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_gc_forced_foreground_marking_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_mark_background',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_background_marking_event
-  ),
-  'blink_gc_concurrent_thread_cycle_full_mark',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_background_marking_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_sweep_foreground',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_foreground_sweeping_event
-  ),
-  'blink_gc_main_thread_cycle_full_sweep',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_foreground_sweeping_event
-      GROUP BY epoch
-    )
-  ),
-  'blink_gc_sweep_background',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM blink_top_gc_background_sweeping_event
-  ),
-  'blink_gc_concurrent_thread_cycle_full_sweep',
-  (
-    SELECT RepeatedField(val) FROM (
-      SELECT
-        SUM(cpuDurMs) as val
-      FROM blink_top_gc_background_sweeping_event
-      GROUP BY epoch
-    )
-  ),
-  'unified_gc_total',
-  (
-    SELECT
-      RepeatedField(cpuDurMs)
-    FROM unified_gc_total
-  )
-);
diff --git a/src/trace_processor/metrics/experimental/frame_times.sql b/src/trace_processor/metrics/experimental/frame_times.sql
deleted file mode 100644
index 4e0ccdb..0000000
--- a/src/trace_processor/metrics/experimental/frame_times.sql
+++ /dev/null
@@ -1,184 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 InteractionEvents;
-CREATE VIEW InteractionEvents AS
-SELECT
-  ts, dur, ts AS ts_ir, dur AS dur_ir
-FROM slice WHERE name LIKE 'Interaction.%';
-
-DROP VIEW IF EXISTS GestureLegacyEvents;
-CREATE VIEW GestureLegacyEvents AS
-SELECT
-  ts,
-  EXTRACT_ARG(arg_set_id, 'legacy_event.phase') AS phase
-FROM raw
-WHERE EXTRACT_ARG(arg_set_id, 'legacy_event.name') = 'SyntheticGestureController::running';
-
--- Convert pairs of 'S' and 'F' events into slices with ts and dur.
-DROP VIEW IF EXISTS GestureEvents;
-CREATE VIEW GestureEvents AS
-SELECT
-  ts, dur, ts AS ts_ge, dur AS dur_ge
-FROM (
-  SELECT
-    ts,
-    phase,
-    LEAD(ts) OVER (ORDER BY ts) - ts as dur
-  FROM GestureLegacyEvents
-)
-WHERE phase = 'S';
-
-DROP TABLE IF EXISTS InteractionEventsJoinGestureEvents;
-CREATE VIRTUAL TABLE InteractionEventsJoinGestureEvents
-USING SPAN_LEFT_JOIN(InteractionEvents, GestureEvents);
-
---------------------------------------------------------------------------------
--- Interesting segments are:
--- 1) If there's a gesture overlapping with interaction, then gesture's range.
--- 2) Else, interaction's range.
-
-DROP VIEW IF EXISTS InterestingSegments;
-CREATE VIEW InterestingSegments AS
-SELECT  -- 1) Gestures overlapping interactions.
-  ts_ge AS ts,
-  dur_ge AS dur
-FROM InteractionEventsJoinGestureEvents
-WHERE ts_ge IS NOT NULL
-GROUP BY ts_ge
-UNION ALL
-SELECT  -- 2) Interactions without gestures.
-  ts_ir AS ts,
-  dur_ir AS dur
-FROM InteractionEventsJoinGestureEvents
-WHERE ts_ge IS NULL
-GROUP BY ts_ir
-HAVING COUNT(*) = 1;
-
---------------------------------------------------------------------------------
--- On ChromeOS, DRM events, if they exist, are the source of truth. Otherwise,
--- look for display rendering stats.
--- On Android, the TBMv2 version relied on Surface Flinger events that are
--- currently unavailable in proto traces. So results may be different from
--- the TBMv2 version on this platform.
-
-DROP TABLE IF EXISTS DisplayCompositorPresentationEvents;
-CREATE TABLE DisplayCompositorPresentationEvents AS
-SELECT ts, FALSE AS exp
-FROM slice
-WHERE name = 'DrmEventFlipComplete'
-GROUP BY ts;
-
-INSERT INTO DisplayCompositorPresentationEvents
-SELECT ts, FALSE AS exp
-FROM slice
-WHERE
-  name = 'vsync_before'
-  AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
-GROUP BY ts;
-
-INSERT INTO DisplayCompositorPresentationEvents
-SELECT ts, FALSE AS exp
-FROM slice
-WHERE
-  name = 'BenchmarkInstrumentation::DisplayRenderingStats'
-  AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
-GROUP BY ts;
-
-INSERT INTO DisplayCompositorPresentationEvents
-SELECT ts, TRUE AS exp
-FROM slice
-WHERE name = 'Display::FrameDisplayed'
-GROUP BY ts;
-
-DROP VIEW IF EXISTS FrameSegments;
-CREATE VIEW FrameSegments AS
-SELECT
-  ts,
-  LEAD(ts) OVER wnd - ts as dur,
-  ts as ts_fs,
-  LEAD(ts) OVER wnd - ts as dur_fs,
-  exp
-FROM DisplayCompositorPresentationEvents
-WINDOW wnd AS (PARTITION BY exp ORDER BY ts);
-
-DROP TABLE IF EXISTS FrameSegmentsJoinInterestingSegments;
-CREATE VIRTUAL TABLE FrameSegmentsJoinInterestingSegments USING
-SPAN_JOIN(FrameSegments, InterestingSegments);
-
-DROP VIEW IF EXISTS FrameTimes;
-CREATE VIEW FrameTimes AS
-SELECT dur / 1e6 AS dur_ms, exp
-FROM FrameSegmentsJoinInterestingSegments
-WHERE ts = ts_fs AND dur = dur_fs;
-
---------------------------------------------------------------------------------
--- Determine frame rate
-
-DROP VIEW IF EXISTS RefreshPeriodAndroid;
-CREATE VIEW RefreshPeriodAndroid AS
--- Not implemented yet.
-SELECT NULL AS interval_ms
-;
-
-DROP VIEW IF EXISTS RefreshPeriodNonAndroid;
-CREATE VIEW RefreshPeriodNonAndroid AS
-SELECT EXTRACT_ARG(arg_set_id, 'debug.args.interval_us') / 1e3 AS interval_ms
-FROM slice
-JOIN thread_track ON (slice.track_id = thread_track.id)
-JOIN thread ON (thread_track.utid = thread.utid)
-WHERE thread.name = 'Compositor' AND slice.name = 'Scheduler::BeginFrame'
-LIMIT 1;
-
-DROP VIEW IF EXISTS RefreshPeriodDefault;
-CREATE VIEW RefreshPeriodDefault AS
-SELECT 1000.0 / 60 AS interval_ms;
-
-DROP TABLE IF EXISTS RefreshPeriod;
-CREATE TABLE RefreshPeriod AS
-SELECT COALESCE(
-  (SELECT interval_ms FROM RefreshPeriodAndroid),
-  (SELECT interval_ms FROM RefreshPeriodNonAndroid),
-  (SELECT interval_ms FROM RefreshPeriodDefault)
-) AS interval_ms;
-
---------------------------------------------------------------------------------
--- Compute average FPS
-
-DROP VIEW IF EXISTS ValidFrameTimes;
-CREATE VIEW ValidFrameTimes AS
-SELECT
-  dur_ms / (SELECT interval_ms FROM RefreshPeriod) AS length,
-  exp
-FROM FrameTimes
-WHERE dur_ms / (SELECT interval_ms FROM RefreshPeriod) >= 0.5;
-
-DROP VIEW IF EXISTS AvgSurfaceFps;
-CREATE VIEW AvgSurfaceFps AS
-SELECT
-  exp,
-  1e3 * COUNT(*) / (SELECT SUM(dur_ms) FROM FrameTimes WHERE exp = valid.exp) AS fps
-FROM ValidFrameTimes valid
-GROUP BY exp;
-
-DROP VIEW IF EXISTS frame_times_output;
-CREATE VIEW frame_times_output AS
-SELECT FrameTimes(
-  'frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE NOT exp),
-  'exp_frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE exp),
-  'avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE NOT exp),
-  'exp_avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE exp)
-);
-
diff --git a/src/trace_processor/metrics/experimental/media_metric.sql b/src/trace_processor/metrics/experimental/media_metric.sql
deleted file mode 100644
index eb2351f..0000000
--- a/src/trace_processor/metrics/experimental/media_metric.sql
+++ /dev/null
@@ -1,290 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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('chrome/chrome_processes.sql');
-
--- Helper for thread slices
-DROP VIEW IF EXISTS thread_slice;
-CREATE VIEW thread_slice AS
-SELECT s.*, thread.utid, thread.upid
-FROM slice s
-INNER JOIN thread_track ON s.track_id = thread_track.id
-INNER JOIN thread USING(utid);
-
---------------------------------------------------------------------------------
--- Find all playbacks on renderer main threads.
-
-DROP VIEW IF EXISTS PlaybackStart;
-CREATE VIEW PlaybackStart AS
-SELECT
-  EXTRACT_ARG(s.arg_set_id, 'debug.id') AS playback_id,
-  s.ts AS playback_start,
-  upid
-FROM slice s
-INNER JOIN thread_track ON s.track_id = thread_track.id
-INNER JOIN thread USING(utid)
-WHERE
-  s.name = 'WebMediaPlayerImpl::DoLoad'
-  AND thread.name = 'CrRendererMain';
-
---------------------------------------------------------------------------------
--- Find the first video render time after the playback to compute
--- time_to_video_play.
-
-DROP VIEW IF EXISTS VideoStart;
-CREATE VIEW VideoStart AS
-SELECT
-  playback_id,
-  playback_start,
-  PlaybackStart.upid,
-  MIN(s.ts) AS video_start
-FROM PlaybackStart, thread_slice s
-WHERE
-  s.name = 'VideoRendererImpl::Render'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = PlaybackStart.upid
-GROUP BY playback_id, playback_start, PlaybackStart.upid;
-
---------------------------------------------------------------------------------
--- Find the first audio render time after the playback to compute
--- time_to_audio_play.
-
-DROP VIEW IF EXISTS AudioStart;
-CREATE VIEW AudioStart AS
-SELECT
-  playback_id,
-  playback_start,
-  PlaybackStart.upid,
-  MIN(s.ts) AS audio_start
-FROM PlaybackStart, thread_slice s
-WHERE
-  s.name = 'AudioRendererImpl::Render'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = PlaybackStart.upid
-GROUP BY playback_id, playback_start, PlaybackStart.upid;
-
---------------------------------------------------------------------------------
--- Sum up the dropped frame count from all such events for each playback to
--- compute dropped_frame_count.
-
-DROP VIEW IF EXISTS DroppedFrameCount;
-CREATE VIEW DroppedFrameCount AS
-SELECT
-  playback_id,
-  vs.upid,
-  SUM(
-    CASE
-    WHEN s.arg_set_id IS NULL THEN 0
-    ELSE EXTRACT_ARG(s.arg_set_id, 'debug.count') END
-  ) AS dropped_frame_count
-FROM VideoStart vs
-LEFT JOIN thread_slice s ON
-  s.name = 'VideoFramesDropped'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = vs.upid
-GROUP BY playback_id, vs.upid;
-
---------------------------------------------------------------------------------
--- Compute seek times.
-
--- Find the seeks.
-DROP VIEW IF EXISTS SeekStart;
-CREATE VIEW SeekStart AS
-SELECT
-  playback_id,
-  PlaybackStart.upid,
-  s.ts AS seek_start,
-  EXTRACT_ARG(s.arg_set_id, 'debug.target') AS seek_target
-FROM PlaybackStart
-LEFT JOIN thread_slice s
-WHERE
-  s.name = 'WebMediaPlayerImpl::DoSeek'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = PlaybackStart.upid;
-
--- Partition by the next seek's ts, so that we can filter for events occurring
--- within each seek's window below.
-DROP VIEW IF EXISTS SeekPartitioned;
-CREATE VIEW SeekPartitioned AS
-SELECT
-  *,
-  LEAD(seek_start) OVER (
-    PARTITION BY playback_id, upid
-    ORDER BY seek_start ASC
-  ) AS seek_end
-FROM SeekStart;
-
--- Find the subsequent matching pipeline seeks that occur before the next seek.
-DROP VIEW IF EXISTS PipelineSeek;
-CREATE VIEW PipelineSeek AS
-SELECT
-  seek.*,
-  (
-    SELECT MIN(s.ts)
-    FROM thread_slice s
-    WHERE
-      s.name = 'WebMediaPlayerImpl::OnPipelineSeeked'
-      AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = seek.playback_id
-      AND EXTRACT_ARG(s.arg_set_id, 'debug.target') = seek.seek_target
-      AND s.upid = seek.upid
-      AND s.ts >= seek.seek_start
-      AND (seek.seek_end IS NULL OR s.ts < seek.seek_end)
-  ) AS pipeline_seek
-FROM SeekPartitioned seek;
-
--- Find the subsequent buffering events that occur before the next seek.
-DROP VIEW IF EXISTS SeekComplete;
-CREATE VIEW SeekComplete AS
-SELECT
-  seek.*,
-  (
-    SELECT MIN(s.ts)
-    FROM thread_slice s
-    WHERE
-      s.name = 'WebMediaPlayerImpl::BufferingHaveEnough'
-      AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = seek.playback_id
-      AND s.upid = seek.upid
-      AND s.ts >= seek.pipeline_seek
-      AND (seek.seek_end IS NULL OR s.ts < seek.seek_end)
-  ) AS seek_complete
-FROM PipelineSeek seek;
-
--- Find the subsequent buffering events that occur before the next seek.
-DROP VIEW IF EXISTS ValidSeek;
-CREATE VIEW ValidSeek AS
-SELECT
-  s.*
-FROM SeekComplete s
-WHERE
-  s.pipeline_seek IS NOT NULL
-  AND s.seek_complete IS NOT NULL;
-
---------------------------------------------------------------------------------
--- Find playback end timestamps and their duration for playbacks without seeks
--- to compute buffering_time.
-
--- Helper view that shows either video or audio start for each playback
-DROP VIEW IF EXISTS AVStart;
-CREATE VIEW AVStart AS
-SELECT
-  v.playback_id,
-  v.playback_start,
-  v.upid,
-  v.video_start AS av_start
-FROM VideoStart v
-UNION
-SELECT
-  a.playback_id,
-  a.playback_start,
-  a.upid,
-  a.audio_start AS av_start
-FROM AudioStart a
-WHERE a.playback_id NOT IN (SELECT playback_id FROM VideoStart);
-
--- Find the corresponding media end events and their reported duration.
-DROP VIEW IF EXISTS PlaybackEnd;
-CREATE VIEW PlaybackEnd AS
-SELECT
-  AVStart.*,
-  slice.ts AS playback_end,
-  EXTRACT_ARG(slice.arg_set_id, 'debug.duration') * 1e9 AS duration
-FROM AVStart
-INNER JOIN slice ON slice.id = (
-  SELECT s.id
-  FROM thread_slice s
-  WHERE
-    s.name = 'WebMediaPlayerImpl::OnEnded'
-    AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = AVStart.playback_id
-    AND s.upid = AVStart.upid
-  ORDER BY s.ts ASC
-  LIMIT 1
-)
-WHERE NOT EXISTS (
-  SELECT 1 FROM SeekStart
-  WHERE SeekStart.playback_id = AVStart.playback_id
-);
-
---------------------------------------------------------------------------------
--- Find maximum video roughness and freezing events per playback.
-
-DROP VIEW IF EXISTS VideoRoughness;
-CREATE VIEW VideoRoughness AS
-SELECT
-  playback_id,
-  playback_start,
-  PlaybackStart.upid,
-  MAX(EXTRACT_ARG(s.arg_set_id, 'debug.roughness')) AS roughness
-FROM PlaybackStart
-INNER JOIN thread_slice s
-WHERE
-  s.name = 'VideoPlaybackRoughness'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = PlaybackStart.upid
-GROUP BY playback_id, playback_start, PlaybackStart.upid;
-
-DROP VIEW IF EXISTS VideoFreezing;
-CREATE VIEW VideoFreezing AS
-SELECT
-  playback_id,
-  playback_start,
-  PlaybackStart.upid,
-  MAX(EXTRACT_ARG(s.arg_set_id, 'debug.freezing')) AS freezing
-FROM PlaybackStart
-INNER JOIN thread_slice s
-WHERE
-  s.name = 'VideoPlaybackFreezing'
-  AND EXTRACT_ARG(s.arg_set_id, 'debug.id') = playback_id
-  AND s.upid = PlaybackStart.upid
-GROUP BY playback_id, playback_start, PlaybackStart.upid;
-
---------------------------------------------------------------------------------
--- Output to proto
-
-DROP VIEW IF EXISTS media_metric_output;
-CREATE VIEW media_metric_output AS
-SELECT MediaMetric(
-  'time_to_video_play', (
-    SELECT RepeatedField((video_start - playback_start) / 1e6)
-    FROM VideoStart
-  ),
-  'time_to_audio_play', (
-    SELECT RepeatedField((audio_start - playback_start) / 1e6)
-    FROM AudioStart
-  ),
-  'dropped_frame_count', (
-    SELECT RepeatedField(CAST(dropped_frame_count AS INTEGER))
-    FROM DroppedFrameCount
-  ),
-  'buffering_time', (
-    SELECT RepeatedField((playback_end - duration - av_start) / 1e6)
-    FROM PlaybackEnd
-  ),
-  'roughness', (
-    SELECT RepeatedField(roughness / 1e0)
-    FROM VideoRoughness
-  ),
-  'freezing', (
-    SELECT RepeatedField(freezing / 1e0)
-    FROM VideoFreezing
-  ),
-  'seek_time', (
-    SELECT RepeatedField((seek_complete - seek_start) / 1e6)
-    FROM ValidSeek
-  ),
-  'pipeline_seek_time', (
-    SELECT RepeatedField((pipeline_seek - seek_start) / 1e6)
-    FROM ValidSeek
-  )
-);
diff --git a/src/trace_processor/metrics/experimental/reported_by_page.sql b/src/trace_processor/metrics/experimental/reported_by_page.sql
deleted file mode 100644
index 2685433..0000000
--- a/src/trace_processor/metrics/experimental/reported_by_page.sql
+++ /dev/null
@@ -1,66 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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.
-
---------------------------------------------------------------------------------
--- Collect page-reported events for each renderer. Note that we don't need to
--- match up process ids, because the unique nav_id ensures we're only comparing
--- corresponding events.
-
-DROP VIEW IF EXISTS page_reported_events;
-CREATE VIEW page_reported_events AS
-SELECT ts, name, EXTRACT_ARG(arg_set_id, "debug.data.navigationId") as nav_id
-FROM slice
-WHERE category = 'blink.user_timing' AND
-    (name = 'navigationStart' OR name LIKE 'telemetry:reported_by_page:%')
-ORDER BY nav_id, ts ASC;
-
---------------------------------------------------------------------------------
--- Compute the duration from the corresponding navigation start for each
--- reported event.
-
-DROP VIEW IF EXISTS page_reported_durations;
-CREATE VIEW page_reported_durations AS
-SELECT p.name, (p.ts - (
-    SELECT MAX(ts) FROM page_reported_events
-    WHERE
-      nav_id = p.nav_id AND
-      ts < p.ts AND (
-        -- Viewable/interactive markers measure time from nav start.
-        (p.name LIKE 'telemetry:reported_by_page:%' AND
-         p.name NOT LIKE 'telemetry:reported_by_page:benchmark%' AND
-         name = 'navigationStart') OR
-        -- Benchmark end markers measure time from the most recent begin marker.
-        (p.name = 'telemetry:reported_by_page:benchmark_end' AND
-         name = 'telemetry:reported_by_page:benchmark_begin')
-      ))
-    ) / 1e6 as dur_ms
-FROM page_reported_events p;
-
---------------------------------------------------------------------------------
--- Combine results into the output table.
-
-DROP VIEW IF EXISTS reported_by_page_output;
-CREATE VIEW reported_by_page_output AS
-SELECT ReportedByPage(
-  'time_to_viewable', (
-      SELECT RepeatedField(dur_ms) FROM page_reported_durations
-      WHERE name = 'telemetry:reported_by_page:viewable'),
-  'time_to_interactive', (
-      SELECT RepeatedField(dur_ms) FROM page_reported_durations
-      WHERE name = 'telemetry:reported_by_page:interactive'),
-  'benchmark_time', (
-      SELECT RepeatedField(dur_ms) FROM page_reported_durations
-      WHERE name = 'telemetry:reported_by_page:benchmark_end')
-);
diff --git a/src/trace_processor/metrics/metrics.cc b/src/trace_processor/metrics/metrics.cc
index c58fb1f..f4d1030 100644
--- a/src/trace_processor/metrics/metrics.cc
+++ b/src/trace_processor/metrics/metrics.cc
@@ -25,7 +25,6 @@
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/trace_processor/metrics/sql_metrics.h"
 #include "src/trace_processor/tp_metatrace.h"
-#include "src/trace_processor/util/status_macros.h"
 
 #include "protos/perfetto/common/descriptor.pbzero.h"
 #include "protos/perfetto/trace_processor/metrics_impl.pbzero.h"
@@ -98,44 +97,43 @@
 util::Status ProtoBuilder::AppendLong(const std::string& field_name,
                                       int64_t value,
                                       bool is_inside_repeated) {
-  auto field = descriptor_->FindFieldByName(field_name);
-  if (!field) {
+  auto field_idx = descriptor_->FindFieldIdxByName(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;
-  if (field->is_repeated() && !is_inside_repeated) {
+  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()) {
+  switch (field.type()) {
     case FieldDescriptorProto::TYPE_INT32:
     case FieldDescriptorProto::TYPE_INT64:
     case FieldDescriptorProto::TYPE_UINT32:
     case FieldDescriptorProto::TYPE_BOOL:
-    case FieldDescriptorProto::TYPE_ENUM:
-      message_->AppendVarInt(field->number(), value);
+      message_->AppendVarInt(field.number(), value);
       break;
     case FieldDescriptorProto::TYPE_SINT32:
     case FieldDescriptorProto::TYPE_SINT64:
-      message_->AppendSignedVarInt(field->number(), value);
+      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);
+      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());
+          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
     }
   }
   return util::OkStatus();
@@ -144,27 +142,28 @@
 util::Status ProtoBuilder::AppendDouble(const std::string& field_name,
                                         double value,
                                         bool is_inside_repeated) {
-  auto field = descriptor_->FindFieldByName(field_name);
-  if (!field) {
+  auto field_idx = descriptor_->FindFieldIdxByName(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;
-  if (field->is_repeated() && !is_inside_repeated) {
+  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()) {
+  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));
+      if (field.type() == FieldDescriptorProto::TYPE_FLOAT) {
+        message_->AppendFixed(field.number(), static_cast<float>(value));
       } else {
-        message_->AppendFixed(field->number(), value);
+        message_->AppendFixed(field.number(), value);
       }
       break;
     }
@@ -172,8 +171,7 @@
       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());
+          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
     }
   }
   return util::OkStatus();
@@ -182,31 +180,31 @@
 util::Status ProtoBuilder::AppendString(const std::string& field_name,
                                         base::StringView data,
                                         bool is_inside_repeated) {
-  const FieldDescriptor* field = descriptor_->FindFieldByName(field_name);
-  if (!field) {
+  auto field_idx = descriptor_->FindFieldIdxByName(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;
-  if (field->is_repeated() && !is_inside_repeated) {
+  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()) {
+  switch (field.type()) {
     case FieldDescriptorProto::TYPE_STRING: {
-      message_->AppendBytes(field->number(), data.data(), data.size());
+      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());
+          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
     }
   }
   return util::OkStatus();
@@ -216,45 +214,44 @@
                                        const uint8_t* ptr,
                                        size_t size,
                                        bool is_inside_repeated) {
-  const FieldDescriptor* field = descriptor_->FindFieldByName(field_name);
-  if (!field) {
+  auto field_idx = descriptor_->FindFieldIdxByName(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;
-  if (field->is_repeated() && !is_inside_repeated)
-    return AppendRepeated(*field, ptr, size);
+  const auto& field = descriptor_->fields()[field_idx.value()];
+  if (field.is_repeated() && !is_inside_repeated)
+    return AppendRepeated(field, ptr, size);
 
-  if (field->type() == FieldDescriptorProto::TYPE_MESSAGE)
-    return AppendSingleMessage(*field, ptr, size);
+  if (field.type() == FieldDescriptorProto::TYPE_MESSAGE)
+    return AppendSingleMessage(field, ptr, size);
 
   if (size == 0) {
     return util::ErrStatus(
-        "Tried to write zero-sized value into field %s (in proto type "
-        "%s). Nulls are only supported for message protos; all other types "
-        "should ensure that nulls are not passed to proto builder functions by "
-        "using the SQLite IFNULL/COALESCE functions.",
-        field->name().c_str(), descriptor_->full_name().c_str());
+        "Tried to write null value into field %s (in proto type %s). "
+        "Nulls are only supported for message protos; all other types should"
+        "ensure that nulls are not passed to proto builder functions by using"
+        "the SQLite IFNULL/COALESCE functions.",
+        field.name().c_str(), descriptor_->full_name().c_str());
   }
 
   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());
+      field.name().c_str(), descriptor_->full_name().c_str(), field.type());
 }
 
 util::Status ProtoBuilder::AppendSingleMessage(const FieldDescriptor& field,
                                                const uint8_t* ptr,
                                                size_t size) {
-  // If we have an zero sized bytes, we still want to propogate that the field
-  // message was set but empty.
   if (size == 0) {
-    // ptr can be null and passing nullptr to AppendBytes feels dangerous so
-    // just pass an empty string (which will have a valid pointer always) and
-    // zero as the size.
-    message_->AppendBytes(field.number(), "", 0);
+    // If we have an zero sized bytes, we still want to propogate that it the
+    // message was set but empty. Just set the field with that id to an
+    // empty bytes.
+    message_->AppendBytes(field.number(), ptr, size);
     return util::OkStatus();
   }
 
@@ -432,24 +429,6 @@
   return 0;
 }
 
-void NullIfEmpty(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
-  // SQLite should enforce this for us.
-  PERFETTO_CHECK(argc == 1);
-
-  if (sqlite3_value_type(argv[0]) != SQLITE_BLOB) {
-    sqlite3_result_error(
-        ctx, "NULL_IF_EMPTY: should only be called with bytes argument", -1);
-    return;
-  }
-
-  if (sqlite3_value_bytes(argv[0]) == 0) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-
-  sqlite3_result_value(ctx, argv[0]);
-}
-
 void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
   if (argc != 1) {
     sqlite3_result_error(ctx, "RepeatedField: only expected one arg", -1);
@@ -540,13 +519,9 @@
     }
   }
 
-  // Even if the message is empty, we don't return null here as we want the
-  // existence of the message to be respected.
   std::vector<uint8_t> raw = builder.SerializeToProtoBuilderResult();
   if (raw.empty()) {
-    // Passing nullptr to SQLite feels dangerous so just pass an empty string
-    // and zero as the size so we don't deref nullptr accidentially somewhere.
-    sqlite3_result_blob(ctx, "", 0, nullptr);
+    sqlite3_result_null(ctx);
     return;
   }
 
@@ -589,9 +564,8 @@
     std::string buffer;
     int ret = TemplateReplace(query, substitutions, &buffer);
     if (ret) {
-      char* error = sqlite3_mprintf(
-          "RUN_METRIC: Error when performing substitutions: %s", query.c_str());
-      sqlite3_result_error(ctx, error, -1);
+      sqlite3_result_error(
+          ctx, "RUN_METRIC: Error when performing substitution", -1);
       return;
     }
 
@@ -609,7 +583,6 @@
       return;
     }
   }
-  sqlite3_result_null(ctx);
 }
 
 util::Status ComputeMetrics(TraceProcessor* tp,
@@ -634,7 +607,10 @@
       PERFETTO_DLOG("Executing query: %s", query.c_str());
       auto prep_it = tp->ExecuteQuery(query);
       prep_it.Next();
-      RETURN_IF_ERROR(prep_it.Status());
+
+      util::Status status = prep_it.Status();
+      if (!status.ok())
+        return status;
     }
 
     auto output_query =
@@ -646,35 +622,36 @@
 
     auto it = tp->ExecuteQuery(output_query.c_str());
     auto has_next = it.Next();
-    RETURN_IF_ERROR(it.Status());
-
-    // Allow the query to return no rows. This has the same semantic as an
-    // empty proto being returned.
-    const auto& field_name = sql_metric.proto_field_name.value();
-    if (!has_next) {
-      metric_builder.AppendBytes(field_name, nullptr, 0);
-      continue;
-    }
-
-    if (it.ColumnCount() != 1) {
+    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());
     }
 
-    SqlValue col = it.Get(0);
-    if (col.type != SqlValue::kBytes) {
+    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());
     }
-    RETURN_IF_ERROR(metric_builder.AppendSqlValue(field_name, col));
 
     has_next = it.Next();
-    if (has_next) {
-      return util::ErrStatus("Output table %s should have at most one row",
+    if (has_next)
+      return util::ErrStatus("Output table %s should only have one row",
                              sql_metric.output_table_name.value().c_str());
-    }
 
-    RETURN_IF_ERROR(it.Status());
+    status = it.Status();
+    if (!status.ok())
+      return status;
   }
   *metrics_proto = metric_builder.SerializeRaw();
   return util::OkStatus();
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
new file mode 100644
index 0000000..c8b2a06
--- /dev/null
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -0,0 +1,1583 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_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)
+// 3df80477da2ea38cc659967487b37051a154bb69
+// SHA1(protos/perfetto/metrics/metrics.proto)
+// 0056b8cbc15eefe5e829a61c68395aff65742da7
+
+// 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, 18493> kMetricsDescriptor{
+    {0x0a, 0xcb, 0x05, 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,
+     0x84, 0x05, 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, 0x12, 0x66, 0x0a, 0x12, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
+     0x79, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 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, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+     0x74, 0x65, 0x73, 0x52, 0x11, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79,
+     0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 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, 0x1a, 0xcc, 0x01, 0x0a, 0x11,
+     0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x41, 0x67, 0x67, 0x72, 0x65,
+     0x67, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x74, 0x6f, 0x74,
+     0x61, 0x6c, 0x5f, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x6f, 0x66,
+     0x66, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10,
+     0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x4f,
+     0x66, 0x66, 0x4e, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x74, 0x6f, 0x74, 0x61,
+     0x6c, 0x5f, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x6f, 0x6e, 0x5f,
+     0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x6f,
+     0x74, 0x61, 0x6c, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x4f, 0x6e, 0x4e,
+     0x73, 0x12, 0x2f, 0x0a, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73,
+     0x63, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x64, 0x6f, 0x7a, 0x65, 0x5f, 0x6e,
+     0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x74, 0x6f, 0x74,
+     0x61, 0x6c, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x44, 0x6f, 0x7a, 0x65,
+     0x4e, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+     0x77, 0x61, 0x6b, 0x65, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x73, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+     0x57, 0x61, 0x6b, 0x65, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x73, 0x0a, 0xd4,
+     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, 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, 0x8e, 0x08, 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,
+     0xa8, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
+     0x18, 0x0a, 0x07, 0x6d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x63, 0x79, 0x63, 0x6c, 0x65,
+     0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65,
+     0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72,
+     0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4e, 0x73, 0x12, 0x20, 0x0a, 0x0c,
+     0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68, 0x7a,
+     0x18, 0x03, 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, 0x04,
+     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, 0x05, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0a, 0x61, 0x76, 0x67, 0x46, 0x72, 0x65, 0x71, 0x4b,
+     0x68, 0x7a, 0x1a, 0x65, 0x0a, 0x08, 0x43, 0x6f, 0x72, 0x65, 0x44, 0x61,
+     0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 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, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x06, 0x1a, 0x67, 0x0a,
+     0x0c, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61, 0x74,
+     0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a,
+     0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01,
+     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, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0xf4, 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, 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x18, 0x04, 0x20, 0x01, 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, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x3e,
+     0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x2a, 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, 0x6f, 0x72, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x63, 0x6f,
+     0x72, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x74,
+     0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 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, 0x6f, 0x72,
+     0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x63,
+     0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10,
+     0x04, 0x1a, 0xb9, 0x02, 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, 0x43, 0x0a,
+     0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01,
+     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, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x07, 0x74, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x06, 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, 0x3e, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x07,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 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, 0x6f, 0x72, 0x65, 0x44, 0x61, 0x74, 0x61,
+     0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x63, 0x6f,
+     0x72, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x2e, 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, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61, 0x74,
+     0x61, 0x52, 0x08, 0x63, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4a,
+     0x04, 0x08, 0x03, 0x10, 0x04, 0x0a, 0x8f, 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, 0x0a, 0xa0, 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, 0x0a, 0xe0, 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, 0x9a, 0x02, 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, 0xc3, 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, 0x12, 0x33, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61,
+     0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01,
+     0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
+     0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x0a, 0xbb, 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, 0xf5, 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, 0x12, 0x28, 0x0a,
+     0x10, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6d, 0x5f,
+     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x0e, 0x6f, 0x6f, 0x6d, 0x56, 0x69, 0x63, 0x74, 0x69, 0x6d, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 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, 0x0a, 0xc0, 0x03, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xf4, 0x02, 0x0a, 0x16,
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12,
+     0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69,
+     0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64,
+     0x12, 0x49, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x12, 0x59, 0x0a, 0x10, 0x70, 0x61, 0x63, 0x6b, 0x61,
+     0x67, 0x65, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x69, 0x64, 0x18,
+     0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x73, 0x46, 0x6f, 0x72, 0x55, 0x69, 0x64, 0x1a, 0x76,
+     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, 0x28, 0x0a, 0x10,
+     0x61, 0x70, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
+     0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e,
+     0x61, 0x70, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
+     0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67,
+     0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
+     0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x04,
+     0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04,
+     0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x0a, 0xcc,
+     0x05, 0x0a, 0x37, 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, 0x72, 0x65, 0x61, 0x73, 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, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74,
+     0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+     0xc7, 0x04, 0x0a, 0x16, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
+     0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x12, 0x3f, 0x0a, 0x04, 0x6c, 0x6d, 0x6b, 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, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61,
+     0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4c, 0x6d,
+     0x6b, 0x52, 0x04, 0x6c, 0x6d, 0x6b, 0x73, 0x1a, 0x97, 0x02, 0x0a, 0x07,
+     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x07, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x27, 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, 0x4d, 0x65, 0x74,
+     0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63,
+     0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41,
+     0x64, 0x6a, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x24,
+     0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x62,
+     0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c,
+     0x66, 0x69, 0x6c, 0x65, 0x52, 0x73, 0x73, 0x42, 0x79, 0x74, 0x65, 0x73,
+     0x12, 0x24, 0x0a, 0x0e, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x73, 0x73,
+     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0c, 0x61, 0x6e, 0x6f, 0x6e, 0x52, 0x73, 0x73, 0x42, 0x79, 0x74,
+     0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x5f,
+     0x72, 0x73, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0d, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x52, 0x73,
+     0x73, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x77,
+     0x61, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x09, 0x73, 0x77, 0x61, 0x70, 0x42, 0x79, 0x74, 0x65,
+     0x73, 0x1a, 0xd1, 0x01, 0x0a, 0x03, 0x4c, 0x6d, 0x6b, 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, 0x26, 0x0a,
+     0x0f, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x73, 0x5f, 0x62,
+     0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
+     0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x70, 0x73, 0x42, 0x79, 0x74, 0x65,
+     0x73, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
+     0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a,
+     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x79, 0x73,
+     0x74, 0x65, 0x6d, 0x49, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69,
+     0x7a, 0x65, 0x12, 0x4d, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x09,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0xf0, 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, 0x0a, 0xa1, 0x13, 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, 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, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x12, 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, 0x35, 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, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6d,
+     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x64, 0x75, 0x72,
+     0x4d, 0x73, 0x1a, 0x80, 0x0b, 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, 0x15, 0x0a, 0x06, 0x64, 0x75,
+     0x72, 0x5f, 0x6d, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05,
+     0x64, 0x75, 0x72, 0x4d, 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, 0x4d, 0x0a, 0x0c, 0x74, 0x6f, 0x5f, 0x70, 0x6f, 0x73,
+     0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x12, 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, 0x0a, 0x74,
+     0x6f, 0x50, 0x6f, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x62, 0x0a,
+     0x17, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
+     0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+     0x18, 0x13, 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, 0x14, 0x74, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76,
+     0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x61, 0x69,
+     0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x6f, 0x5f, 0x62, 0x69, 0x6e, 0x64,
+     0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x18, 0x14, 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, 0x6f, 0x42, 0x69, 0x6e, 0x64, 0x41,
+     0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51,
+     0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x5f,
+     0x66, 0x6f, 0x72, 0x6b, 0x18, 0x10, 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, 0x0c, 0x74, 0x69, 0x6d,
+     0x65, 0x50, 0x6f, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6b, 0x4a, 0x04, 0x08,
+     0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08,
+     0x0e, 0x10, 0x0f, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x1a, 0x5c, 0x0a,
+     0x0a, 0x48, 0x73, 0x63, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
+     0x4e, 0x0a, 0x0c, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x18, 0x01, 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, 0x0b, 0x66, 0x75, 0x6c, 0x6c,
+     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xc2, 0x03, 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, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
+     0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x42, 0x0a, 0x03,
+     0x68, 0x73, 0x63, 0x18, 0x08, 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, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x48, 0x73, 0x63, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
+     0x03, 0x68, 0x73, 0x63, 0x0a, 0xae, 0x08, 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, 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,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+     0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa4,
+     0x07, 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, 0xb5, 0x02,
+     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, 0x41, 0x0a, 0x07,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 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, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65,
+     0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 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, 0x0a, 0x86, 0x0f,
+     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, 0x68, 0x77,
+     0x75, 0x69, 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, 0xe3, 0x0d, 0x0a,
+     0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e, 0x64,
+     0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 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, 0x23, 0x0a, 0x0e, 0x72, 0x74, 0x5f,
+     0x63, 0x70, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x74, 0x43, 0x70, 0x75,
+     0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x72,
+     0x61, 0x77, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x72,
+     0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4d,
+     0x61, 0x78, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x4d, 0x69, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x06,
+     0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x41, 0x76, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6c,
+     0x75, 0x73, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20,
+     0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73, 0x68,
+     0x5f, 0x6d, 0x61, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
+     0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09,
+     0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x08, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d, 0x69,
+     0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x61,
+     0x76, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x66, 0x6c,
+     0x75, 0x73, 0x68, 0x41, 0x76, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72,
+     0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x63,
+     0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10,
+     0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x70,
+     0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6d, 0x61, 0x78,
+     0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x70,
+     0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x61, 0x78, 0x12, 0x28,
+     0x0a, 0x10, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72,
+     0x65, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0e, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65,
+     0x65, 0x4d, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x70,
+     0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x61, 0x76, 0x67,
+     0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x70,
+     0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x41, 0x76, 0x67, 0x12, 0x30,
+     0x0a, 0x14, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+     0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d,
+     0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x12, 0x2c, 0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
+     0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x10,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d,
+     0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x12, 0x2c,
+     0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+     0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x11, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70, 0x6c,
+     0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x12,
+     0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69,
+     0x6f, 0x6e, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28, 0x01,
+     0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+     0x69, 0x6f, 0x6e, 0x41, 0x76, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69,
+     0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+     0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x75, 0x69, 0x52,
+     0x65, 0x63, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22,
+     0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f,
+     0x6d, 0x61, 0x78, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75,
+     0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x61, 0x78, 0x12, 0x22,
+     0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f,
+     0x6d, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75,
+     0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x69, 0x6e, 0x12, 0x22,
+     0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f,
+     0x61, 0x76, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x75,
+     0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x41, 0x76, 0x67, 0x12, 0x30,
+     0x0a, 0x14, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d,
+     0x70, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x17,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72,
+     0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x12, 0x2e, 0x0a, 0x13, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x63,
+     0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
+     0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x68, 0x61, 0x64, 0x65,
+     0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65,
+     0x12, 0x2c, 0x0a, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x63,
+     0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x19,
+     0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72,
+     0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x41, 0x76, 0x67, 0x12, 0x26,
+     0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x68, 0x69, 0x74, 0x5f,
+     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69, 0x74, 0x43, 0x6f, 0x75,
+     0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f,
+     0x68, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69, 0x74,
+     0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x63, 0x68,
+     0x65, 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1c, 0x20,
+     0x01, 0x28, 0x01, 0x52, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69,
+     0x74, 0x41, 0x76, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x61, 0x63, 0x68,
+     0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x61, 0x63, 0x68,
+     0x65, 0x4d, 0x69, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26,
+     0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73,
+     0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x54, 0x69,
+     0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f,
+     0x6d, 0x69, 0x73, 0x73, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1f, 0x20, 0x01,
+     0x28, 0x01, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69, 0x73,
+     0x73, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72, 0x61, 0x70,
+     0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x6d,
+     0x5f, 0x6d, 0x61, 0x78, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11,
+     0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70, 0x75, 0x4d,
+     0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72, 0x61,
+     0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65,
+     0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70, 0x75,
+     0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72,
+     0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d,
+     0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x22, 0x20, 0x01, 0x28, 0x01,
+     0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70,
+     0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14, 0x67,
+     0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70, 0x75, 0x5f,
+     0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x23, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x47,
+     0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a, 0x14,
+     0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70, 0x75,
+     0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x24, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
+     0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f, 0x0a,
+     0x14, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70,
+     0x75, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x25, 0x20,
+     0x01, 0x28, 0x01, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
+     0x73, 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12, 0x26,
+     0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65,
+     0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x26, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d, 0x4d,
+     0x61, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+     0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x27, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+     0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x65,
+     0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76,
+     0x67, 0x18, 0x28, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x74, 0x65, 0x78,
+     0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12, 0x1e,
+     0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x61,
+     0x78, 0x18, 0x29, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c, 0x6c,
+     0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6c,
+     0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x2a, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d, 0x4d,
+     0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65,
+     0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x01, 0x52,
+     0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x22, 0x5a,
+     0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48, 0x77, 0x75,
+     0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x45, 0x0a, 0x0c, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
+     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e, 0x64, 0x65,
+     0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x0a, 0x88, 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, 0x0a, 0x98, 0x04,
+     0x0a, 0x3b, 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,
+     0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a, 0x61, 0x76, 0x61, 0x5f,
+     0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 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, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x22, 0x8f, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x6d, 0x61, 0x70,
+     0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f,
+     0x6c, 0x73, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 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, 0x55, 0x6e,
+     0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79,
+     0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x52, 0x0e, 0x70, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
+     0x1a, 0x4e, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1d, 0x0a,
+     0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0xc9, 0x01, 0x0a,
+     0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62,
+     0x6f, 0x6c, 0x73, 0x12, 0x52, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64,
+     0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08,
+     0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x05,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70,
+     0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+     0x73, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x0a, 0xfc, 0x01, 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, 0x0a,
+     0xff, 0x04, 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,
+     0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x68, 0x69,
+     0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x22, 0xf8, 0x03, 0x0a, 0x11, 0x4a, 0x61, 0x76, 0x61, 0x48,
+     0x65, 0x61, 0x70, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     0x12, 0x57, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x30, 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, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     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, 0x75, 0x0a, 0x09, 0x54, 0x79, 0x70,
+     0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
+     0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+     0x1b, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x61, 0x63,
+     0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x5f, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x72,
+     0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 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, 0x4b, 0x0a, 0x0a, 0x74, 0x79,
+     0x70, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 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, 0x4a, 0x61, 0x76,
+     0x61, 0x48, 0x65, 0x61, 0x70, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72,
+     0x61, 0x6d, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x52, 0x09, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x1a,
+     0xab, 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, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
+     0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43, 0x0a, 0x07,
+     0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x29, 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, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+     0x6d, 0x2e, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61,
+     0x6d, 0x70, 0x6c, 0x65, 0x73, 0x0a, 0x9e, 0x06, 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, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9b, 0x05, 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,
+     0x62, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x70, 0x52, 0x6f, 0x6f, 0x74, 0x73,
+     0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x79, 0x70,
+     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x6f,
+     0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70,
+     0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b,
+     0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x1a, 0xa6, 0x02, 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,
+     0x1b, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 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, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x61, 0x63,
+     0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x5f, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72,
+     0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x16, 0x61, 0x6e, 0x6f, 0x6e,
+     0x5f, 0x72, 0x73, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61,
+     0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x12, 0x61, 0x6e, 0x6f, 0x6e, 0x52, 0x73, 0x73, 0x41, 0x6e, 0x64,
+     0x53, 0x77, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x3e, 0x0a, 0x05,
+     0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x28, 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, 0x48, 0x65, 0x61, 0x70,
+     0x52, 0x6f, 0x6f, 0x74, 0x73, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73,
+     0x1a, 0xa7, 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, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+     0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 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, 0x0a, 0xd0, 0x01, 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, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 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, 0x22, 0x85, 0x01, 0x0a, 0x15, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x74,
+     0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
+     0x74, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x0d, 0x52, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x75,
+     0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x73, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
+     0x74, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x6c, 0x6f,
+     0x67, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15,
+     0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x73, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x0a, 0xbb, 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, 0x74, 0x61,
+     0x73, 0x6b, 0x5f, 0x6e, 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, 0xf5, 0x01, 0x0a, 0x10,
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54, 0x61, 0x73, 0x6b, 0x4e,
+     0x61, 0x6d, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 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, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54,
+     0x61, 0x73, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x50, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x1a, 0x9b, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x03, 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, 0x1f, 0x0a, 0x0b, 0x74, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
+     0x03, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e,
+     0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x28, 0x0a,
+     0x10, 0x75, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
+     0x0e, 0x75, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e,
+     0x61, 0x6d, 0x65, 0x0a, 0xa2, 0x06, 0x0a, 0x41, 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, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74,
+     0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+     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, 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, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x22, 0x93, 0x05, 0x0a, 0x1e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65,
+     0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x12, 0x55, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x65, 0x73, 0x1a, 0x4f, 0x0a, 0x11, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x79,
+     0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f,
+     0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x75,
+     0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4d,
+     0x73, 0x1a, 0xb1, 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, 0x1f, 0x0a, 0x0b,
+     0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x54,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x72, 0x0a, 0x14, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x63, 0x6f, 0x72, 0x65,
+     0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x41, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49,
+     0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x79, 0x43, 0x6f,
+     0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x11, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70,
+     0x65, 0x1a, 0x94, 0x02, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x12, 0x43, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+     0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+     0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x72,
+     0x0a, 0x14, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x62, 0x79,
+     0x5f, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x54, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x42, 0x79, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
+     0x11, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x79, 0x43, 0x6f,
+     0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x50, 0x0a, 0x07, 0x74, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x73, 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, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49,
+     0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x52, 0x07, 0x74, 0x68, 0x72,
+     0x65, 0x61, 0x64, 0x73, 0x0a, 0xde, 0x19, 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, 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, 0x37,
+     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,
+     0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 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, 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, 0x68, 0x77, 0x75, 0x69,
+     0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 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, 0x3b, 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, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f,
+     0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
+     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, 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, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70,
+     0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 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, 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, 0x64, 0x69, 0x73,
+     0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     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, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x6e, 0x61, 0x6d,
+     0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x41, 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, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x22, 0xf7, 0x03, 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, 0x12, 0x3a,
+     0x0a, 0x19, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x75,
+     0x69, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72,
+     0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x46,
+     0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x49,
+     0x0a, 0x21, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, 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,
+     0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1e, 0x73, 0x74, 0x61, 0x74, 0x73,
+     0x64, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53,
+     0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49,
+     0x64, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73,
+     0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x69,
+     0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74,
+     0x72, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
+     0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x13,
+     0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69,
+     0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x11, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x53, 0x65, 0x73,
+     0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 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, 0x95, 0x0d, 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, 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, 0x12, 0x52, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65,
+     0x61, 0x70, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 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, 0x48, 0x69, 0x73,
+     0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61,
+     0x48, 0x65, 0x61, 0x70, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+     0x6d, 0x12, 0x55, 0x0a, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x5f, 0x6c, 0x6d, 0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
+     0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 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, 0x52, 0x65,
+     0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x10,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65,
+     0x61, 0x73, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x15, 0x75, 0x6e, 0x6d, 0x61,
+     0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x79,
+     0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70,
+     0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+     0x73, 0x52, 0x13, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a,
+     0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x52,
+     0x0a, 0x13, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x68, 0x77,
+     0x75, 0x69, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x14, 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, 0x48, 0x77, 0x75, 0x69, 0x4d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x52, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x48, 0x77, 0x75, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x4f,
+     0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x4f, 0x0a, 0x12, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x17, 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, 0x54, 0x61, 0x73, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x10,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54, 0x61, 0x73, 0x6b, 0x4e,
+     0x61, 0x6d, 0x65, 0x73, 0x12, 0x6f, 0x0a, 0x1c, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74,
+     0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+     0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x54, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x18, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69,
+     0x6d, 0x65, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x0a, 0x10,
+     0x0b, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10,
+     0x0f}};
+
+}  // 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 dea62f7..8568c15 100644
--- a/src/trace_processor/metrics/metrics.h
+++ b/src/trace_processor/metrics/metrics.h
@@ -147,9 +147,6 @@
     const std::unordered_map<std::string, std::string>& substitutions,
     std::string* out);
 
-// Implements the NULL_IF_EMPTY SQL function.
-void NullIfEmpty(sqlite3_context* ctx, int argc, sqlite3_value** argv);
-
 // These functions implement the RepeatedField SQL aggregate functions.
 void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv);
 void RepeatedFieldFinal(sqlite3_context* ctx);
diff --git a/src/trace_processor/metrics/metrics_unittest.cc b/src/trace_processor/metrics/metrics_unittest.cc
index 661df33..abbb57a 100644
--- a/src/trace_processor/metrics/metrics_unittest.cc
+++ b/src/trace_processor/metrics/metrics_unittest.cc
@@ -74,8 +74,7 @@
   // message TestProto {
   //   optional int64 int_value = 1;
   // }
-  ProtoDescriptor descriptor("file.proto", ".perfetto.protos",
-                             ".perfetto.protos.TestProto",
+  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
                              ProtoDescriptor::Type::kMessage, base::nullopt);
   descriptor.AddField(FieldDescriptor(
       "int_value", 1, FieldDescriptorProto::TYPE_INT64, "", false));
@@ -96,8 +95,7 @@
   // message TestProto {
   //   optional double double_value = 1;
   // }
-  ProtoDescriptor descriptor("file.proto", ".perfetto.protos",
-                             ".perfetto.protos.TestProto",
+  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
                              ProtoDescriptor::Type::kMessage, base::nullopt);
   descriptor.AddField(FieldDescriptor(
       "double_value", 1, FieldDescriptorProto::TYPE_DOUBLE, "", false));
@@ -118,8 +116,7 @@
   // message TestProto {
   //   optional string string_value = 1;
   // }
-  ProtoDescriptor descriptor("file.proto", ".perfetto.protos",
-                             ".perfetto.protos.TestProto",
+  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
                              ProtoDescriptor::Type::kMessage, base::nullopt);
   descriptor.AddField(FieldDescriptor(
       "string_value", 1, FieldDescriptorProto::TYPE_STRING, "", false));
@@ -143,14 +140,13 @@
   //   }
   //   optional NestedProto nested_value = 1;
   // }
-  ProtoDescriptor nested("file.proto", ".perfetto.protos",
+  ProtoDescriptor nested(".perfetto.protos",
                          ".perfetto.protos.TestProto.NestedProto",
                          ProtoDescriptor::Type::kMessage, base::nullopt);
   nested.AddField(FieldDescriptor("nested_int_value", 1,
                                   FieldDescriptorProto::TYPE_INT64, "", false));
 
-  ProtoDescriptor descriptor("file.proto", ".perfetto.protos",
-                             ".perfetto.protos.TestProto",
+  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
                              ProtoDescriptor::Type::kMessage, base::nullopt);
   auto field =
       FieldDescriptor("nested_value", 1, FieldDescriptorProto::TYPE_MESSAGE,
@@ -190,8 +186,7 @@
   // message TestProto {
   //   repeated int64 int_value = 1;
   // }
-  ProtoDescriptor descriptor("file.proto", ".perfetto.protos",
-                             ".perfetto.protos.TestProto",
+  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
                              ProtoDescriptor::Type::kMessage, base::nullopt);
   descriptor.AddField(FieldDescriptor(
       "rep_int_value", 1, FieldDescriptorProto::TYPE_INT64, "", true));
diff --git a/src/trace_processor/metrics/trace_metadata.sql b/src/trace_processor/metrics/trace_metadata.sql
index 838116b..50dd9ed 100644
--- a/src/trace_processor/metrics/trace_metadata.sql
+++ b/src/trace_processor/metrics/trace_metadata.sql
@@ -14,10 +14,19 @@
 -- limitations under the License.
 --
 
-DROP VIEW IF EXISTS trace_metadata_output;
-CREATE VIEW trace_metadata_output AS
+CREATE VIEW IF NOT EXISTS 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 IF NOT EXISTS trace_metadata_output AS
 SELECT TraceMetadata(
-  'trace_duration_ns', CAST((SELECT end_ts - start_ts FROM trace_bounds) AS INT),
+  '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'),
   'android_build_fingerprint', (
     SELECT str_value FROM metadata WHERE name = 'android_build_fingerprint'
@@ -38,12 +47,5 @@
     SELECT RepeatedField(slice.name)
     FROM track JOIN slice ON track.id = slice.track_id
     WHERE track.name = 'Trace Triggers'
-  ),
-  'trace_config_pbtxt', (
-    SELECT str_value FROM metadata
-    WHERE name = 'trace_config_pbtxt'
-  ),
-  'sched_duration_ns', (
-    SELECT MAX(ts) - MIN(ts) from sched
   )
 );
diff --git a/src/trace_processor/metrics/trace_stats.sql b/src/trace_processor/metrics/trace_stats.sql
deleted file mode 100644
index f647442..0000000
--- a/src/trace_processor/metrics/trace_stats.sql
+++ /dev/null
@@ -1,39 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 trace_stats_output;
-CREATE VIEW trace_stats_output AS
-SELECT TraceAnalysisStats(
-  'stat', (
-    SELECT RepeatedField(TraceAnalysisStats_Stat(
-      'name', name,
-      'idx', idx,
-      'count', value,
-      -- TraceAnalysisStats.Source enum:
-      'source', CASE source
-        WHEN 'trace' THEN 1
-        WHEN 'analysis' THEN 2
-      END,
-      -- TraceAnalysisStats.Severity enum:
-      'severity', CASE severity
-        WHEN 'info' THEN 1
-        WHEN 'data_loss' THEN 2
-        WHEN 'error' THEN 3
-      END
-    ))
-    FROM stats ORDER BY name ASC
-  )
-);
diff --git a/src/trace_processor/metrics/webview/webview_power_usage.sql b/src/trace_processor/metrics/webview/webview_power_usage.sql
deleted file mode 100644
index 7ac8efc..0000000
--- a/src/trace_processor/metrics/webview/webview_power_usage.sql
+++ /dev/null
@@ -1,278 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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.
-
--- WebView is embedded in the hosting app's main process, which means it shares some threads
--- with the host app's work. We approximate WebView-related power usage
--- by selecting user slices that belong to WebView and estimating their power use
--- through the CPU time they consume at different core frequencies.
--- This file populates a summary table that can be used to produce metrics in different formats.
-
-SELECT RUN_METRIC('android/android_proxy_power.sql');
-SELECT RUN_METRIC('android/cpu_info.sql');
-
-DROP VIEW IF EXISTS top_level_slice;
-
--- Select topmost slices from the 'toplevel' and 'Java' categories.
--- Filter out Looper events since they are likely to belong to the host app.
--- Slices are only used to calculate the contribution of the browser process,
--- renderer contribution will be calculated as the sum of all renderer processes' usage.
-CREATE VIEW top_level_slice AS
-  SELECT *
-  FROM slice WHERE
-  depth = 0 AND
-  ((category like '%toplevel%' OR category = 'Java') AND
-  name NOT LIKE '%looper%');
-
-DROP VIEW IF EXISTS webview_browser_slices;
-
--- Match top-level slices to threads and hosting apps.
--- This excludes any renderer slices because renderer processes are counted
--- as a whole separately.
--- Slices from Chrome browser processes are also excluded.
-CREATE VIEW webview_browser_slices AS
-  SELECT
-    top_level_slice.ts,
-    top_level_slice.dur,
-    thread_track.utid,
-    process.upid AS upid,
-    extract_arg(process.arg_set_id, 'chrome.host_app_package_name') AS app_name
-  FROM top_level_slice
-  INNER JOIN thread_track
-  ON top_level_slice.track_id = thread_track.id
-  INNER JOIN process
-  ON thread.upid = process.upid
-  INNER JOIN thread
-  ON thread_track.utid = thread.utid
-  WHERE process.name NOT LIKE '%SandboxedProcessService%'
-  AND process.name NOT LIKE '%chrome%'
-  AND app_name IS NOT NULL;
-
-DROP TABLE IF EXISTS webview_browser_slices_power;
-
--- Assign power usage to WebView browser slices.
-CREATE VIRTUAL TABLE webview_browser_slices_power
-USING SPAN_JOIN(power_per_thread PARTITIONED utid,
-                webview_browser_slices PARTITIONED utid);
-
-DROP VIEW IF EXISTS webview_browser_slices_power_summary;
-
--- Calculate the power usage of all WebView browser slices for each app
--- in milliampere-seconds.
-CREATE VIEW webview_browser_slices_power_summary AS
-SELECT
-  app_name,
-  SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-  FROM webview_browser_slices_power
-  GROUP BY app_name;
-
-DROP VIEW IF EXISTS webview_renderer_threads;
-
--- All threads of all WebView renderer processes.
-CREATE VIEW webview_renderer_threads AS
-SELECT
-  thread.utid AS utid,
-  extract_arg(process.arg_set_id, 'chrome.host_app_package_name') as app_name
-  FROM process
-  INNER JOIN thread
-  ON thread.upid = process.upid
-  WHERE process.name LIKE '%webview%SandboxedProcessService%'
-  AND app_name IS NOT NULL;
-
-DROP VIEW IF EXISTS webview_renderer_power_summary;
-
--- Calculate the power usage of all WebView renderer processes for each app
--- in milliampere-seconds.
-CREATE VIEW webview_renderer_power_summary AS
-  SELECT
-    app_name,
-    SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-  FROM power_per_thread
-  INNER JOIN webview_renderer_threads
-  ON power_per_thread.utid = webview_renderer_threads.utid
-  GROUP BY app_name;
-
-DROP VIEW IF EXISTS webview_renderer_power_per_core_type;
-
--- Calculate the power usage of all WebView renderer processes for each app
--- in milliampere-seconds grouped by core type.
-CREATE VIEW webview_renderer_power_per_core_type AS
-SELECT
-  app_name,
-  core_type_per_cpu.core_type AS core_type,
-  SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-FROM power_per_thread
-INNER JOIN webview_renderer_threads
-  ON power_per_thread.utid = webview_renderer_threads.utid
-INNER JOIN core_type_per_cpu
-  ON power_per_thread.cpu = core_type_per_cpu.cpu
-GROUP BY app_name, core_type_per_cpu.core_type;
-
-DROP VIEW IF EXISTS host_app_threads;
-
--- All threads of hosting apps (this is a superset of webview_browser_slices).
--- 1) select all threads that had any WebView browser slices associated with them;
--- 2) get all threads for processes matching threads from 1).
--- For example, only some of app's threads wrote any slices, but we are selecting
--- all threads for this app's process.
--- Excludes all renderer processes and Chrome browser processes.
-CREATE VIEW host_app_threads AS
-SELECT
-    thread.utid AS utid,
-    thread.name AS name,
-    extract_arg(process.arg_set_id, 'chrome.host_app_package_name') as app_name
-  FROM thread
-  JOIN process ON thread.upid = process.upid
-  WHERE thread.upid IN
-    (SELECT DISTINCT(webview_browser_slices.upid) FROM webview_browser_slices)
-  AND process.name NOT LIKE '%SandboxedProcessService%'
-  AND process.name NOT LIKE '%chrome%'
-  AND app_name IS NOT NULL;
-
-DROP VIEW IF EXISTS host_app_power_summary;
-
--- Calculate the power usage of all WebView (host app+browser) processes for each app
--- in milliampere-seconds.
-CREATE VIEW host_app_power_summary AS
-  SELECT
-    app_name,
-    SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-  FROM power_per_thread
-  INNER JOIN host_app_threads
-  ON power_per_thread.utid = host_app_threads.utid
-  GROUP BY app_name;
-
-DROP VIEW IF EXISTS host_app_power_per_core_type;
-
--- Calculate the power usage of all WebView (host app+browser) processes for each app
--- in milliampere-seconds grouped by core type.
-CREATE VIEW host_app_power_per_core_type AS
-SELECT
-  app_name,
-  core_type_per_cpu.core_type AS core_type,
-  SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-FROM power_per_thread
-INNER JOIN host_app_threads
-  ON power_per_thread.utid = host_app_threads.utid
-INNER JOIN core_type_per_cpu
-  ON power_per_thread.cpu = core_type_per_cpu.cpu
-GROUP BY app_name, core_type_per_cpu.core_type;
-
-DROP VIEW IF EXISTS webview_only_threads;
-
--- A subset of the host app threads that are WebView-specific.
-CREATE VIEW webview_only_threads AS
-SELECT *
-FROM host_app_threads
-  WHERE name LIKE 'Chrome%' OR name LIKE 'CookieMonster%'
-  OR name LIKE 'CompositorTileWorker%' OR name LIKE 'ThreadPool%ground%'
-  OR NAME LIKE 'ThreadPoolService%' OR  name like 'VizCompositorThread%'
-  OR name IN ('AudioThread', 'DedicatedWorker thread', 'GpuMemoryThread',
-  'JavaBridge', 'LevelDBEnv.IDB', 'MemoryInfra', 'NetworkService', 'VizWebView');
-
-DROP VIEW IF EXISTS webview_only_power_summary;
-
--- Calculate the power usage of all WebView-specific host app threads
--- (browser + in-process renderers) for each app in milliampere-seconds.
-CREATE VIEW webview_only_power_summary AS
-  SELECT
-    app_name,
-    SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-  FROM power_per_thread
-  INNER JOIN webview_only_threads
-  ON power_per_thread.utid = webview_only_threads.utid
-  GROUP BY app_name;
-
-DROP VIEW IF EXISTS webview_only_power_per_core_type;
-
--- Calculate the power usage of all WebView-specific host app threads
--- for each app in milliampere-seconds grouped by core type.
-CREATE VIEW webview_only_power_per_core_type AS
-  SELECT app_name,
-  core_type_per_cpu.core_type AS core_type,
-  SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-FROM power_per_thread
-INNER JOIN webview_only_threads
-  ON power_per_thread.utid = webview_only_threads.utid
-INNER JOIN core_type_per_cpu
-  ON power_per_thread.cpu = core_type_per_cpu.cpu
-GROUP BY app_name, core_type_per_cpu.core_type;
-
--- Create views for output.
-
-DROP VIEW IF EXISTS total_app_power_output;
-
-CREATE VIEW total_app_power_output AS
-  SELECT
-    host_app_power_summary.app_name as app_name,
-    host_app_power_summary.power_mas AS total_mas,
-    host_app_power_little_cores_mas.power_mas AS little_cores_mas,
-    host_app_power_big_cores_mas.power_mas AS big_cores_mas,
-    host_app_power_bigger_cores_mas.power_mas AS bigger_cores_mas
-  FROM host_app_power_summary LEFT JOIN host_app_power_per_core_type AS host_app_power_little_cores_mas
-  ON host_app_power_summary.app_name = host_app_power_little_cores_mas.app_name
-  AND host_app_power_little_cores_mas.core_type = 'little'
-  LEFT JOIN host_app_power_per_core_type AS host_app_power_big_cores_mas
-  ON host_app_power_summary.app_name = host_app_power_big_cores_mas.app_name
-  AND host_app_power_big_cores_mas.core_type = 'big'
-  LEFT JOIN host_app_power_per_core_type AS host_app_power_bigger_cores_mas
-  ON host_app_power_summary.app_name = host_app_power_bigger_cores_mas.app_name
-  AND host_app_power_bigger_cores_mas.core_type = 'bigger';
-
-DROP VIEW IF EXISTS webview_renderer_power_output;
-
-CREATE VIEW webview_renderer_power_output AS
-  SELECT
-    webview_renderer_power_summary.app_name AS app_name,
-    webview_renderer_power_summary.power_mas AS total_mas,
-    webview_renderer_little_power.power_mas AS little_cores_mas,
-    webview_renderer_big_power.power_mas AS big_cores_mas,
-    webview_renderer_bigger_power.power_mas AS bigger_cores_mas
-  FROM webview_renderer_power_summary LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_little_power
-  ON webview_renderer_power_summary.app_name = webview_renderer_little_power.app_name
-  AND webview_renderer_little_power.core_type = 'little'
-  LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_big_power
-  ON webview_renderer_power_summary.app_name = webview_renderer_big_power.app_name
-  AND webview_renderer_big_power.core_type = 'big'
-  LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_bigger_power
-  ON webview_renderer_power_summary.app_name = webview_renderer_bigger_power.app_name
-  AND webview_renderer_bigger_power.core_type = 'bigger';
-
-DROP VIEW IF EXISTS webview_only_power_output;
-
-CREATE VIEW webview_only_power_output AS
-  SELECT
-    webview_only_power_summary.app_name AS app_name,
-    webview_only_power_summary.power_mas AS total_mas,
-    webview_only_power_little_cores_mas.power_mas AS little_cores_mas,
-    webview_only_power_big_cores_mas.power_mas AS big_cores_mas,
-    webview_only_power_bigger_cores_mas.power_mas AS bigger_cores_mas
-  FROM webview_only_power_summary LEFT JOIN webview_only_power_per_core_type AS webview_only_power_little_cores_mas
-  ON webview_only_power_summary.app_name = webview_only_power_little_cores_mas.app_name
-  AND webview_only_power_little_cores_mas.core_type = 'little'
-  LEFT JOIN webview_only_power_per_core_type AS webview_only_power_big_cores_mas
-  ON webview_only_power_summary.app_name = webview_only_power_big_cores_mas.app_name
-  AND webview_only_power_big_cores_mas.core_type = 'big'
-  LEFT JOIN webview_only_power_per_core_type AS webview_only_power_bigger_cores_mas
-  ON webview_only_power_summary.app_name = webview_only_power_bigger_cores_mas.app_name
-  AND webview_only_power_bigger_cores_mas.core_type = 'bigger';
-
-DROP VIEW IF EXISTS total_device_power;
-
--- Calculate the power usage of the device in milliampere-seconds.
-CREATE VIEW total_device_power AS
-  SELECT SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-  FROM power_per_thread;
-
-DROP VIEW IF EXISTS webview_power_summary;
diff --git a/src/trace_processor/python/LICENSE b/src/trace_processor/python/LICENSE
deleted file mode 100644
index ab4c4a2..0000000
--- a/src/trace_processor/python/LICENSE
+++ /dev/null
@@ -1,189 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   Copyright (c) 2020, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
diff --git a/src/trace_processor/python/README.md b/src/trace_processor/python/README.md
deleted file mode 100644
index 3ef3430..0000000
--- a/src/trace_processor/python/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Perfetto - System profiling, app tracing and trace analysis
-
-Perfetto is a production-grade open-source stack for performance
-instrumentation and trace analysis. It offers services and libraries and for
-recording system-level and app-level traces, native + java heap profiling, a
-library for analyzing traces using SQL and a web-based UI to visualize and
-explore multi-GB traces.
-
-See https://perfetto.dev/docs or the /docs/ directory for documentation.
diff --git a/src/trace_processor/python/example.py b/src/trace_processor/python/example.py
deleted file mode 100644
index b3925a4..0000000
--- a/src/trace_processor/python/example.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import argparse
-
-from perfetto.trace_processor import TraceProcessor
-
-
-def main():
-  # Parse arguments passed from command line
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      "-a",
-      "--address",
-      help="Address at which trace_processor is being run, e.g. localhost:9001",
-      type=str)
-  parser.add_argument(
-      "-b",
-      "--binary",
-      help="Absolute path to a trace processor binary",
-      type=str)
-  parser.add_argument("-f", "--file", help="Absolute path to trace", type=str)
-  args = parser.parse_args()
-
-  # Pass arguments into api to construct the trace processor and load the trace
-  if args.address is None and args.file is None:
-    raise Exception("You must specify an address or a file path to trace")
-  elif args.address is None:
-    tp = TraceProcessor(file_path=args.file, bin_path=args.binary)
-  elif args.file is None:
-    tp = TraceProcessor(addr=args.address)
-  else:
-    tp = TraceProcessor(
-        addr=args.address, file_path=args.file, bin_path=args.binary)
-
-  # Iterate through QueryResultIterator
-  res_it = tp.query('select * from slice limit 10')
-  for row in res_it:
-    print(row.name)
-
-  # Convert QueryResultIterator into a pandas dataframe + iterate. This yields
-  # the same results as the function above.
-  try:
-    res_df = tp.query('select * from slice limit 10').as_pandas_dataframe()
-    for index, row in res_df.iterrows():
-      print(row['name'])
-  except Exception:
-    pass
-
-  # Call another function on the loaded trace
-  am_metrics = tp.metric(['android_mem'])
-  tp.close()
-
-
-if __name__ == "__main__":
-  main()
diff --git a/src/trace_processor/python/perfetto/__init__.py b/src/trace_processor/python/perfetto/__init__.py
deleted file mode 100644
index c569069..0000000
--- a/src/trace_processor/python/perfetto/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-try:
-  __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
-  __path__ = __import__('pkgutil').extend_path(__path__, __name__)
\ No newline at end of file
diff --git a/src/trace_processor/python/perfetto/trace_processor/__init__.py b/src/trace_processor/python/perfetto/trace_processor/__init__.py
deleted file mode 100644
index fbbffcd..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from .api import TraceProcessor
-from .http import TraceProcessorHttp
\ No newline at end of file
diff --git a/src/trace_processor/python/perfetto/trace_processor/api.py b/src/trace_processor/python/perfetto/trace_processor/api.py
deleted file mode 100644
index 9cabf07..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/api.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from urllib.parse import urlparse
-
-from .http import TraceProcessorHttp
-from .loader import get_loader
-from .protos import ProtoFactory
-from .shell import load_shell
-
-
-# Custom exception raised if any trace_processor functions return a
-# response with an error defined
-class TraceProcessorException(Exception):
-
-  def __init__(self, message):
-    super().__init__(message)
-
-
-class TraceProcessor:
-
-  # Values of these constants correspond to the QueryResponse message at
-  # protos/perfetto/trace_processor/trace_processor.proto
-  # Value 0 corresponds to CELL_INVALID, which is represented as None in
-  # this class
-  QUERY_CELL_NULL_FIELD_ID = 1
-  QUERY_CELL_VARINT_FIELD_ID = 2
-  QUERY_CELL_FLOAT64_FIELD_ID = 3
-  QUERY_CELL_STRING_FIELD_ID = 4
-  QUERY_CELL_BLOB_FIELD_ID = 5
-
-  # This is the class returned to the user and contains one row of the
-  # resultant query. Each column name is stored as an attribute of this
-  # class, with the value corresponding to the column name and row in
-  # the query results table.
-  class Row(object):
-
-    def __str__(self):
-      return str(self.__dict__)
-
-    def __repr__(self):
-      return self.__dict__
-
-  class QueryResultIterator:
-
-    def __init__(self, column_names, batches):
-      self.__batches = batches
-      self.__column_names = column_names
-      self.__batch_index = 0
-      self.__next_index = 0
-      # TODO(lalitm): Look into changing string_cells to bytes in the protobuf
-      self.__string_cells = memoryview(bytes(batches[0].string_cells, 'utf-8'))
-      self.__string_index = 0
-
-    def get_cell_list(self, proto_index):
-      if proto_index == TraceProcessor.QUERY_CELL_NULL_FIELD_ID:
-        return None
-      elif proto_index == TraceProcessor.QUERY_CELL_VARINT_FIELD_ID:
-        return self.__batches[self.__batch_index].varint_cells
-      elif proto_index == TraceProcessor.QUERY_CELL_FLOAT64_FIELD_ID:
-        return self.__batches[self.__batch_index].float64_cells
-      elif proto_index == TraceProcessor.QUERY_CELL_BLOB_FIELD_ID:
-        return self.__batches[self.__batch_index].blob_cells
-      else:
-        raise TraceProcessorException('Invalid cell type')
-
-    def cells(self):
-      return self.__batches[self.__batch_index].cells
-
-    # To use the query result as a populated Pandas dataframe, this
-    # function must be called directly after calling query inside
-    # TraceProcesor.
-    def as_pandas_dataframe(self):
-      try:
-        import numpy as np
-        import pandas as pd
-
-        df = pd.DataFrame(columns=self.__column_names)
-
-        # Populate the dataframe with the query results
-        while True:
-          # If all cells are read, then check if last batch before
-          # returning the populated dataframe
-          if self.__next_index >= len(self.__batches[self.__batch_index].cells):
-            if self.__batches[self.__batch_index].is_last_batch:
-              ordered_df = df.reset_index(drop=True)
-              return ordered_df
-            self.__batch_index += 1
-            self.__next_index = 0
-            self.__string_cells = memoryview(
-                bytes(self.__batches[self.__batch_index].string_cells, 'utf-8'))
-            self.__string_index = 0
-
-          row = []
-          for num, column_name in enumerate(self.__column_names):
-            cell_type = self.__batches[self.__batch_index].cells[
-                self.__next_index + num]
-            if cell_type == TraceProcessor.QUERY_CELL_STRING_FIELD_ID:
-              start_index = self.__string_index
-              while self.__string_cells[self.__string_index] != 0:
-                self.__string_index += 1
-              row.append(
-                  str(self.__string_cells[start_index:self.__string_index],
-                      'utf-8'))
-              self.__string_index += 1
-            else:
-              cell_list = self.get_cell_list(cell_type)
-              if cell_list is None:
-                row.append(np.NAN)
-              else:
-                row.append(cell_list.pop(0))
-          df.loc[-1] = row
-          df.index = df.index + 1
-          self.__next_index = self.__next_index + len(self.__column_names)
-
-      except ModuleNotFoundError:
-        raise TraceProcessorException(
-            'The sufficient libraries are not installed')
-
-    def __iter__(self):
-      return self
-
-    def __next__(self):
-      # If all cells are read, then check if last batch before raising
-      # StopIteration
-      if self.__next_index >= len(self.cells()):
-        if self.__batches[self.__batch_index].is_last_batch:
-          raise StopIteration
-        self.__batch_index += 1
-        self.__next_index = 0
-        self.__string_cells = memoryview(
-            bytes(self.__batches[self.__batch_index].string_cells, 'utf-8'))
-        self.__string_index = 0
-
-      row = TraceProcessor.Row()
-      for num, column_name in enumerate(self.__column_names):
-        cell_type = self.__batches[self.__batch_index].cells[self.__next_index +
-                                                             num]
-        if cell_type == TraceProcessor.QUERY_CELL_STRING_FIELD_ID:
-          start_index = self.__string_index
-          while self.__string_cells[self.__string_index] != 0:
-            self.__string_index += 1
-          setattr(
-              row, column_name,
-              str(self.__string_cells[start_index:self.__string_index],
-                  'utf-8'))
-          self.__string_index += 1
-        else:
-          cell_list = self.get_cell_list(cell_type)
-          if cell_list is None:
-            setattr(row, column_name, None)
-          else:
-            setattr(row, column_name, cell_list.pop(0))
-      self.__next_index = self.__next_index + len(self.__column_names)
-      return row
-
-  def __init__(self, addr=None, file_path=None, bin_path=None,
-               unique_port=True):
-    # Load trace_processor_shell or access via given address
-    if addr:
-      p = urlparse(addr)
-      tp = TraceProcessorHttp(p.netloc if p.netloc else p.path)
-    else:
-      url, self.subprocess = load_shell(
-          bin_path=bin_path, unique_port=unique_port)
-      tp = TraceProcessorHttp(url)
-    self.http = tp
-    self.protos = ProtoFactory()
-
-    # Parse trace by its file_path into the loaded instance of trace_processor
-    if file_path:
-      get_loader().parse_file(self.http, file_path)
-
-  def query(self, sql):
-    """Executes passed in SQL query using class defined HTTP API, and returns
-    the response as a QueryResultIterator. Raises TraceProcessorException if
-    the response returns with an error.
-
-    Args:
-      sql: SQL query written as a String
-
-    Returns:
-      A class which can iterate through each row of the results table. This
-      can also be converted to a pandas dataframe by calling the
-      as_pandas_dataframe() function after calling query.
-    """
-    response = self.http.execute_query(sql)
-    if response.error:
-      raise TraceProcessorException(response.error)
-
-    return TraceProcessor.QueryResultIterator(response.column_names,
-                                              response.batch)
-
-  def metric(self, metrics):
-    """Returns the metrics data corresponding to the passed in trace metric.
-    Raises TraceProcessorException if the response returns with an error.
-
-    Args:
-      metrics: A list of valid metrics as defined in TraceMetrics
-
-    Returns:
-      The metrics data as a proto message
-    """
-    response = self.http.compute_metric(metrics)
-    if response.error:
-      raise TraceProcessorException(response.error)
-
-    metrics = self.protos.TraceMetrics()
-    metrics.ParseFromString(response.metrics)
-    return metrics
-
-  def enable_metatrace(self):
-    """Enable metatrace for the currently running trace_processor.
-    """
-    return self.http.enable_metatrace()
-
-  def disable_and_read_metatrace(self):
-    """Disable and return the metatrace formed from the currently running
-    trace_processor. This must be enabled before attempting to disable. This
-    returns the serialized bytes of the metatrace data directly. Raises
-    TraceProcessorException if the response returns with an error.
-    """
-    response = self.http.disable_and_read_metatrace()
-    if response.error:
-      raise TraceProcessorException(response.error)
-
-    return response.metatrace
-
-  # TODO(@aninditaghosh): Investigate context managers for
-  # cleaner usage
-  def close(self):
-    if hasattr(self, 'subprocess'):
-      self.subprocess.kill()
-    self.http.conn.close()
diff --git a/src/trace_processor/python/perfetto/trace_processor/http.py b/src/trace_processor/python/perfetto/trace_processor/http.py
deleted file mode 100644
index bf751f9..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/http.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import http.client
-
-from .protos import ProtoFactory
-
-
-class TraceProcessorHttp:
-
-  def __init__(self, url):
-    self.protos = ProtoFactory()
-    self.conn = http.client.HTTPConnection(url)
-
-  def execute_query(self, query):
-    args = self.protos.RawQueryArgs()
-    args.sql_query = query
-    byte_data = args.SerializeToString()
-    self.conn.request('POST', '/query', body=byte_data)
-    with self.conn.getresponse() as f:
-      result = self.protos.QueryResult()
-      result.ParseFromString(f.read())
-      return result
-
-  def compute_metric(self, metrics):
-    args = self.protos.ComputeMetricArgs()
-    args.metric_names.extend(metrics)
-    byte_data = args.SerializeToString()
-    self.conn.request('POST', '/compute_metric', body=byte_data)
-    with self.conn.getresponse() as f:
-      result = self.protos.ComputeMetricResult()
-      result.ParseFromString(f.read())
-      return result
-
-  def parse(self, chunk):
-    self.conn.request('POST', '/parse', body=chunk)
-    with self.conn.getresponse() as f:
-      return f.read()
-
-  def notify_eof(self):
-    self.conn.request('GET', '/notify_eof')
-    with self.conn.getresponse() as f:
-      return f.read()
-
-  def status(self):
-    self.conn.request('GET', '/status')
-    with self.conn.getresponse() as f:
-      result = self.protos.StatusResult()
-      result.ParseFromString(f.read())
-      return result
-
-  def enable_metatrace(self):
-    self.conn.request('GET', '/enable_metatrace')
-    with self.conn.getresponse() as f:
-      return f.read()
-
-  def disable_and_read_metatrace(self):
-    self.conn.request('GET', '/disable_and_read_metatrace')
-    with self.conn.getresponse() as f:
-      result = self.protos.DisableAndReadMetatraceResult()
-      result.ParseFromString(f.read())
-      return result
diff --git a/src/trace_processor/python/perfetto/trace_processor/loader.py b/src/trace_processor/python/perfetto/trace_processor/loader.py
deleted file mode 100644
index e57145f..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/loader.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import socket
-import subprocess
-import tempfile
-from urllib import request
-
-
-# This class contains all functions that first try to use a vendor to fulfil
-# their function
-class LoaderStandalone:
-  # Limit parsing file to 32MB to maintain parity with the UI
-  MAX_BYTES_LOADED = 32 * 1024 * 1024
-
-  # URL to download script to run trace_processor
-  SHELL_URL = 'http://get.perfetto.dev/trace_processor'
-
-  # Default port that trace_processor_shell runs on
-  TP_PORT = '9001'
-
-  def read_tp_descriptor():
-    ws = os.path.dirname(__file__)
-    with open(os.path.join(ws, 'trace_processor.descriptor'), 'rb') as x:
-      return x.read()
-
-  def read_metrics_descriptor():
-    ws = os.path.dirname(__file__)
-    with open(os.path.join(ws, 'metrics.descriptor'), 'rb') as x:
-      return x.read()
-
-  def parse_file(tp_http, file_path):
-    with open(file_path, 'rb') as f:
-      f_size = os.path.getsize(file_path)
-      bytes_read = 0
-      while (bytes_read < f_size):
-        chunk = f.read(LoaderStandalone.MAX_BYTES_LOADED)
-        tp_http.parse(chunk)
-        bytes_read += len(chunk)
-    tp_http.notify_eof()
-    return tp_http
-
-  def get_shell_path(bin_path=None):
-    # Try to use preexisting binary before attempting to download
-    # trace_processor
-    if bin_path is None:
-      with tempfile.NamedTemporaryFile(delete=False) as file:
-        req = request.Request(LoaderStandalone.SHELL_URL)
-        with request.urlopen(req) as req:
-          file.write(req.read())
-      subprocess.check_output(['chmod', '+x', file.name])
-      return file.name
-    else:
-      if not os.path.isfile(bin_path):
-        raise Exception('Path to binary is not valid')
-      return bin_path
-
-  def get_free_port(unique_port=False):
-    if not unique_port:
-      return LoaderStandalone.TP_PORT, f'localhost:{LoaderStandalone.TP_PORT}'
-    free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    free_socket.bind(('', 0))
-    free_socket.listen(5)
-    port = free_socket.getsockname()[1]
-    free_socket.close()
-    return str(port), f"localhost:{str(port)}"
-
-
-# Return vendor class if it exists before falling back on LoaderStandalone
-def get_loader():
-  try:
-    from .loader_vendor import LoaderVendor
-    return LoaderVendor
-  except ModuleNotFoundError:
-    return LoaderStandalone
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
deleted file mode 100644
index b5e2561..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
+++ /dev/null
Binary files differ
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1 b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
deleted file mode 100644
index a876fff..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
+++ /dev/null
@@ -1,6 +0,0 @@
-
-// SHA1(tools/gen_binary_descriptors)
-// 30f9a74885dae344b1a42f7ba94d8909c9d07ad0
-// SHA1(protos/perfetto/metrics/metrics.proto)
-// 64a90d4e7177aa7a8ba57919313037430848325c
-  
\ No newline at end of file
diff --git a/src/trace_processor/python/perfetto/trace_processor/protos.py b/src/trace_processor/python/perfetto/trace_processor/protos.py
deleted file mode 100644
index b5e3700..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/protos.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from google.protobuf import descriptor_pb2
-from google.protobuf import message_factory
-from google.protobuf.descriptor_pool import DescriptorPool
-
-from .loader import get_loader
-
-
-class ProtoFactory:
-
-  def __init__(self):
-    # Declare descriptor pool
-    self.descriptor_pool = DescriptorPool()
-
-    # Load trace processor descriptor and add to descriptor pool
-    tp_descriptor_bytes = get_loader().read_tp_descriptor()
-    tp_file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
-    tp_file_desc_set_pb2.MergeFromString(tp_descriptor_bytes)
-
-    for f_desc_pb2 in tp_file_desc_set_pb2.file:
-      self.descriptor_pool.Add(f_desc_pb2)
-
-    # Load metrics descriptor and add to descriptor pool
-    metrics_descriptor_bytes = get_loader().read_metrics_descriptor()
-    metrics_file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
-    metrics_file_desc_set_pb2.MergeFromString(metrics_descriptor_bytes)
-
-    for f_desc_pb2 in metrics_file_desc_set_pb2.file:
-      self.descriptor_pool.Add(f_desc_pb2)
-
-    def create_message_factory(message_type):
-      message_desc = self.descriptor_pool.FindMessageTypeByName(message_type)
-      return message_factory.MessageFactory().GetPrototype(message_desc)
-
-    # Create proto messages to correctly communicate with the RPC API by sending
-    # and receiving data as protos
-    self.StatusResult = create_message_factory('perfetto.protos.StatusResult')
-    self.ComputeMetricArgs = create_message_factory(
-        'perfetto.protos.ComputeMetricArgs')
-    self.ComputeMetricResult = create_message_factory(
-        'perfetto.protos.ComputeMetricResult')
-    self.RawQueryArgs = create_message_factory('perfetto.protos.RawQueryArgs')
-    self.QueryResult = create_message_factory('perfetto.protos.QueryResult')
-    self.TraceMetrics = create_message_factory('perfetto.protos.TraceMetrics')
-    self.DisableAndReadMetatraceResult = create_message_factory(
-        'perfetto.protos.DisableAndReadMetatraceResult')
-    self.CellsBatch = create_message_factory(
-        'perfetto.protos.QueryResult.CellsBatch')
diff --git a/src/trace_processor/python/perfetto/trace_processor/shell.py b/src/trace_processor/python/perfetto/trace_processor/shell.py
deleted file mode 100644
index 44da342..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/shell.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import subprocess
-import time
-from urllib import request, error
-
-from .loader import get_loader
-
-
-def load_shell(bin_path=None, unique_port=False):
-  shell_path = get_loader().get_shell_path(bin_path=bin_path)
-  port, url = get_loader().get_free_port(unique_port=unique_port)
-  p = subprocess.Popen([shell_path, '-D', '--http-port', port],
-                       stdout=subprocess.DEVNULL)
-
-  while True:
-    try:
-      if p.poll() != None:
-        if unique_port:
-          raise Exception(
-              "Random port allocation failed, please file a bug at https://goto.google.com/perfetto-bug"
-          )
-        raise Exception(
-            "Trace processor failed to start, please file a bug at https://goto.google.com/perfetto-bug"
-        )
-      req = request.urlretrieve(f'http://{url}/status')
-      time.sleep(1)
-      break
-    except error.URLError:
-      pass
-
-  return url, p
diff --git a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor b/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor
deleted file mode 100644
index 3d2bf28..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor
+++ /dev/null
Binary files differ
diff --git a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor.sha1 b/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor.sha1
deleted file mode 100644
index 5ac17dd..0000000
--- a/src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor.sha1
+++ /dev/null
@@ -1,6 +0,0 @@
-
-// SHA1(tools/gen_binary_descriptors)
-// 30f9a74885dae344b1a42f7ba94d8909c9d07ad0
-// SHA1(protos/perfetto/trace_processor/trace_processor.proto)
-// 8320f306d6d5bbcb5ef6ba8cd62cc70a0994d102
-  
\ No newline at end of file
diff --git a/src/trace_processor/python/setup.py b/src/trace_processor/python/setup.py
deleted file mode 100644
index c826824..0000000
--- a/src/trace_processor/python/setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from distutils.core import setup
-
-setup(
-    name='perfetto',
-    packages=['perfetto', 'perfetto.trace_processor'],
-    package_data={'perfetto.trace_processor': ['*.descriptor']},
-    include_package_data=True,
-    version='0.2.9',
-    license='apache-2.0',
-    description='Python API for Perfetto\'s Trace Processor',
-    author='Perfetto',
-    author_email='perfetto-pypi@google.com',
-    url='https://perfetto.dev/',
-    download_url='https://github.com/google/perfetto/archive/v6.0.tar.gz',
-    keywords=['trace processor', 'tracing', 'perfetto'],
-    install_requires=[
-        'protobuf',
-    ],
-    classifiers=[
-        'Development Status :: 3 - Alpha',
-        'License :: OSI Approved :: Apache Software License',
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.5",
-        "Programming Language :: Python :: 3.6",
-        "Programming Language :: Python :: 3.7",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
-    ],
-)
diff --git a/src/trace_processor/read_trace.cc b/src/trace_processor/read_trace.cc
index 8f5b6f0..3a655c6 100644
--- a/src/trace_processor/read_trace.cc
+++ b/src/trace_processor/read_trace.cc
@@ -16,24 +16,17 @@
 
 #include "perfetto/trace_processor/read_trace.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/protozero/proto_utils.h"
 #include "perfetto/trace_processor/trace_processor.h"
 
-#include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
 #include "src/trace_processor/importers/gzip/gzip_utils.h"
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-#include "src/trace_processor/util/status_macros.h"
 
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #define PERFETTO_HAS_AIO_H() 1
 #else
 #define PERFETTO_HAS_AIO_H() 0
@@ -45,70 +38,6 @@
 
 namespace perfetto {
 namespace trace_processor {
-namespace {
-
-// 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
-constexpr size_t kChunkSize = 1024 * 1024;
-
-util::Status ReadTraceUsingRead(
-    TraceProcessor* tp,
-    int fd,
-    uint64_t* file_size,
-    const std::function<void(uint64_t parsed_size)>& progress_callback) {
-  // Load the trace in chunks using ordinary read().
-  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 = base::Read(fd, buf.get(), kChunkSize);
-    if (rsize == 0)
-      break;
-
-    if (rsize < 0) {
-      return util::ErrStatus("Reading trace file failed (errno: %d, %s)", errno,
-                             strerror(errno));
-    }
-
-    *file_size += static_cast<uint64_t>(rsize);
-
-    RETURN_IF_ERROR(tp->Parse(std::move(buf), static_cast<size_t>(rsize)));
-  }
-  return util::OkStatus();
-}
-
-class SerializingProtoTraceReader : public ChunkedTraceReader {
- public:
-  SerializingProtoTraceReader(std::vector<uint8_t>* output) : output_(output) {}
-
-  util::Status Parse(std::unique_ptr<uint8_t[]> data, size_t size) override {
-    return tokenizer_.Tokenize(
-        std::move(data), size, [this](TraceBlobView packet) {
-          uint8_t buffer[protozero::proto_utils::kMaxSimpleFieldEncodedSize];
-
-          uint8_t* pos = buffer;
-          pos = protozero::proto_utils::WriteVarInt(kTracePacketTag, pos);
-          pos = protozero::proto_utils::WriteVarInt(packet.length(), pos);
-          output_->insert(output_->end(), buffer, pos);
-
-          output_->insert(output_->end(), packet.data(),
-                          packet.data() + packet.length());
-          return util::OkStatus();
-        });
-  }
-
-  void NotifyEndOfFile() override {}
-
- private:
-  static constexpr uint8_t kTracePacketTag =
-      protozero::proto_utils::MakeTagLengthDelimited(
-          protos::pbzero::Trace::kPacketFieldNumber);
-
-  ProtoTraceTokenizer tokenizer_;
-  std::vector<uint8_t>* output_;
-};
-
-}  // namespace
 
 util::Status ReadTrace(
     TraceProcessor* tp,
@@ -118,6 +47,8 @@
   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()
@@ -164,17 +95,27 @@
     PERFETTO_CHECK(aio_read(&cb) == 0);
 
     // Parse the completed buffer while the async read is in-flight.
-    RETURN_IF_ERROR(tp->Parse(std::move(buf), static_cast<size_t>(rsize)));
-  }
-
-  if (file_size == 0) {
-    PERFETTO_ILOG(
-        "Failed to read any data using AIO. This is expected and not an error "
-        "on WSL. Falling back to read()");
-    RETURN_IF_ERROR(ReadTraceUsingRead(tp, *fd, &file_size, progress_callback));
+    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()
-  RETURN_IF_ERROR(ReadTraceUsingRead(tp, *fd, &file_size, progress_callback));
+  // 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();
@@ -188,32 +129,13 @@
 util::Status DecompressTrace(const uint8_t* data,
                              size_t size,
                              std::vector<uint8_t>* output) {
-  TraceType type = GuessTraceType(data, size);
-  if (type != TraceType::kGzipTraceType && type != TraceType::kProtoTraceType) {
+  if (!gzip::IsGzipSupported()) {
     return util::ErrStatus(
-        "Only GZIP and proto trace types are supported by DecompressTrace");
+        "Cannot decompress trace in build where zlib is disabled");
   }
 
-  if (type == TraceType::kGzipTraceType) {
-    std::unique_ptr<ChunkedTraceReader> reader(
-        new SerializingProtoTraceReader(output));
-    GzipTraceParser parser(std::move(reader));
-
-    RETURN_IF_ERROR(parser.ParseUnowned(data, size));
-    if (parser.needs_more_input())
-      return util::ErrStatus("Cannot decompress partial trace file");
-
-    parser.NotifyEndOfFile();
-    return util::OkStatus();
-  }
-
-  PERFETTO_CHECK(type == TraceType::kProtoTraceType);
-
   protos::pbzero::Trace::Decoder decoder(data, size);
   GzipDecompressor decompressor;
-  if (size > 0 && !decoder.packet()) {
-    return util::ErrStatus("Trace does not contain valid packets");
-  }
   for (auto it = decoder.packet(); it; ++it) {
     protos::pbzero::TracePacket::Decoder packet(*it);
     if (!packet.has_compressed_packets()) {
diff --git a/src/trace_processor/read_trace_integrationtest.cc b/src/trace_processor/read_trace_integrationtest.cc
index 390a7ef..5070e35 100644
--- a/src/trace_processor/read_trace_integrationtest.cc
+++ b/src/trace_processor/read_trace_integrationtest.cc
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/trace_processor/read_trace.h"
@@ -29,13 +28,10 @@
 namespace trace_processor {
 namespace {
 
-base::ScopedFstream OpenTestTrace(const std::string& path) {
-  std::string full_path = base::GetTestDataPath(path);
-  EXPECT_TRUE(base::FileExists(full_path)) << full_path;
-  return base::ScopedFstream(fopen(full_path.c_str(), "rb"));
-}
-
-std::vector<uint8_t> ReadAllData(const base::ScopedFstream& f) {
+TEST(ReadTraceIntegrationTest, CompressedTrace) {
+  base::ScopedFstream f(fopen(
+      base::GetTestDataPath(std::string("test/data/compressed.pb")).c_str(),
+      "rb"));
   std::vector<uint8_t> raw_trace;
   while (!feof(*f)) {
     uint8_t buf[4096];
@@ -43,12 +39,6 @@
         fread(reinterpret_cast<char*>(buf), 1, base::ArraySize(buf), *f);
     raw_trace.insert(raw_trace.end(), buf, buf + rsize);
   }
-  return raw_trace;
-}
-
-TEST(ReadTraceIntegrationTest, CompressedTrace) {
-  base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb");
-  std::vector<uint8_t> raw_trace = ReadAllData(f);
 
   std::vector<uint8_t> decompressed;
   decompressed.reserve(raw_trace.size());
@@ -68,54 +58,6 @@
   ASSERT_EQ(packet_count, 2412u);
 }
 
-TEST(ReadTraceIntegrationTest, NonProtobufShouldNotDecompress) {
-  base::ScopedFstream f = OpenTestTrace("test/data/unsorted_trace.json");
-  std::vector<uint8_t> raw_trace = ReadAllData(f);
-
-  std::vector<uint8_t> decompressed;
-  util::Status status = trace_processor::DecompressTrace(
-      raw_trace.data(), raw_trace.size(), &decompressed);
-  ASSERT_FALSE(status.ok());
-}
-
-TEST(ReadTraceIntegrationTest, OuterGzipDecompressTrace) {
-  base::ScopedFstream f =
-      OpenTestTrace("test/data/example_android_trace_30s.pb.gz");
-  std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);
-
-  std::vector<uint8_t> decompressed;
-  util::Status status = trace_processor::DecompressTrace(
-      raw_compressed_trace.data(), raw_compressed_trace.size(), &decompressed);
-  ASSERT_TRUE(status.ok());
-
-  base::ScopedFstream u =
-      OpenTestTrace("test/data/example_android_trace_30s.pb");
-  std::vector<uint8_t> raw_trace = ReadAllData(u);
-
-  ASSERT_EQ(decompressed.size(), raw_trace.size());
-  ASSERT_EQ(decompressed, raw_trace);
-}
-
-TEST(ReadTraceIntegrationTest, DoubleGzipDecompressTrace) {
-  base::ScopedFstream f = OpenTestTrace("test/data/compressed.pb.gz");
-  std::vector<uint8_t> raw_compressed_trace = ReadAllData(f);
-
-  std::vector<uint8_t> decompressed;
-  util::Status status = trace_processor::DecompressTrace(
-      raw_compressed_trace.data(), raw_compressed_trace.size(), &decompressed);
-  ASSERT_TRUE(status.ok());
-
-  protos::pbzero::Trace::Decoder decoder(decompressed.data(),
-                                         decompressed.size());
-  uint32_t packet_count = 0;
-  for (auto it = decoder.packet(); it; ++it) {
-    protos::pbzero::TracePacket::Decoder packet(*it);
-    ASSERT_FALSE(packet.has_compressed_packets());
-    ++packet_count;
-  }
-  ASSERT_EQ(packet_count, 2412u);
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/rpc/BUILD.gn b/src/trace_processor/rpc/BUILD.gn
index 63cc752..dcc814c 100644
--- a/src/trace_processor/rpc/BUILD.gn
+++ b/src/trace_processor/rpc/BUILD.gn
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("../../../gn/perfetto.gni")
-import("../../../gn/test.gni")
 import("../../../gn/wasm.gni")
 
 # Prevent that this file is accidentally included in embedder builds.
@@ -23,15 +22,10 @@
 # interface) and by the :httpd module for the HTTP interface.
 source_set("rpc") {
   sources = [
-    "proto_ring_buffer.cc",
-    "proto_ring_buffer.h",
-    "query_result_serializer.cc",
-    "query_result_serializer.h",
     "rpc.cc",
     "rpc.h",
   ]
   deps = [
-    "..:lib",
     "..:metatrace",
     "../../../gn:default_deps",
     "../../../include/perfetto/trace_processor",
@@ -41,23 +35,6 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  sources = [
-    "proto_ring_buffer_unittest.cc",
-    "query_result_serializer_unittest.cc",
-  ]
-  deps = [
-    ":rpc",
-    "..:lib",
-    "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-    "../../../protos/perfetto/trace_processor:zero",
-    "../../base",
-    "../../protozero",
-  ]
-}
-
 if (enable_perfetto_trace_processor_httpd) {
   source_set("httpd") {
     sources = [
@@ -68,6 +45,7 @@
       ":rpc",
       "../../../gn:default_deps",
       "../../../include/perfetto/trace_processor",
+      "../../../protos/perfetto/metrics:zero",
       "../../../protos/perfetto/trace_processor:zero",
       "../../base",
       "../../base:unix_socket",
@@ -87,18 +65,3 @@
     ]
   }
 }
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":rpc",
-      "..:lib",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
-      "../../../gn:sqlite",
-      "../../base",
-    ]
-    sources = [ "query_result_serializer_benchmark.cc" ]
-  }
-}
diff --git a/src/trace_processor/rpc/httpd.cc b/src/trace_processor/rpc/httpd.cc
index 1a061aa..0c18624 100644
--- a/src/trace_processor/rpc/httpd.cc
+++ b/src/trace_processor/rpc/httpd.cc
@@ -39,8 +39,7 @@
 
 namespace {
 
-constexpr char kBindPort[] = "9001";
-constexpr size_t kOmitContentLength = static_cast<size_t>(-1);
+constexpr char kBindAddr[] = "127.0.0.1:9001";
 
 // 32 MiB payload + 128K for HTTP headers.
 constexpr size_t kMaxRequestSize = (32 * 1024 + 128) * 1024;
@@ -69,7 +68,7 @@
  public:
   explicit HttpServer(std::unique_ptr<TraceProcessor>);
   ~HttpServer() override;
-  void Run(const char*, const char*);
+  void Run();
 
  private:
   size_t ParseOneHttpRequest(Client* client);
@@ -83,8 +82,7 @@
 
   Rpc trace_processor_rpc_;
   base::UnixTaskRunner task_runner_;
-  std::unique_ptr<base::UnixSocket> sock4_;
-  std::unique_ptr<base::UnixSocket> sock6_;
+  std::unique_ptr<base::UnixSocket> sock_;
   std::vector<Client> clients_;
 };
 
@@ -99,8 +97,8 @@
 void HttpReply(base::UnixSocket* sock,
                const char* http_code,
                std::initializer_list<const char*> headers = {},
-               const uint8_t* content = nullptr,
-               size_t content_length = 0) {
+               const uint8_t* body = nullptr,
+               size_t body_len = 0) {
   std::vector<char> response;
   response.reserve(4096);
   Append(response, "HTTP/1.1 ");
@@ -110,15 +108,12 @@
     Append(response, hdr);
     Append(response, "\r\n");
   }
-  if (content_length != kOmitContentLength) {
-    Append(response, "Content-Length: ");
-    Append(response, std::to_string(content_length));
-    Append(response, "\r\n");
-  }
-  Append(response, "\r\n");                      // End-of-headers marker.
-  sock->Send(response.data(), response.size());  // Send response headers.
-  if (content_length > 0 && content_length != kOmitContentLength)
-    sock->Send(content, content_length);  // Send response payload.
+  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());
+  if (body_len)
+    sock->Send(body, body_len);
 }
 
 void ShutdownBadRequest(base::UnixSocket* sock, const char* reason) {
@@ -131,28 +126,11 @@
     : trace_processor_rpc_(std::move(preloaded_instance)) {}
 HttpServer::~HttpServer() = default;
 
-void HttpServer::Run(const char* kBindAddr4, const char* kBindAddr6) {
-  PERFETTO_ILOG("[HTTP] Starting RPC server on %s and %s", kBindAddr4,
-                kBindAddr6);
-
-  sock4_ = base::UnixSocket::Listen(kBindAddr4, this, &task_runner_,
-                                    base::SockFamily::kInet,
-                                    base::SockType::kStream);
-  bool ipv4_listening = sock4_ && sock4_->is_listening();
-  if (!ipv4_listening) {
-    PERFETTO_ILOG("Failed to listen on IPv4 socket");
-  }
-
-  sock6_ = base::UnixSocket::Listen(kBindAddr6, this, &task_runner_,
-                                    base::SockFamily::kInet6,
-                                    base::SockType::kStream);
-  bool ipv6_listening = sock6_ && sock6_->is_listening();
-  if (!ipv6_listening) {
-    PERFETTO_ILOG("Failed to listen on IPv6 socket");
-  }
-
-  PERFETTO_CHECK(ipv4_listening || ipv6_listening);
-
+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();
 }
 
@@ -278,15 +256,11 @@
                req.body.size());
   std::string allow_origin_hdr =
       "Access-Control-Allow-Origin: " + req.origin.ToStdString();
-
-  // This is the default. Overridden by the /query handler for chunked replies.
-  char transfer_encoding_hdr[255] = "Transfer-Encoding: identity";
   std::initializer_list<const char*> headers = {
       "Connection: Keep-Alive",                //
       "Cache-Control: no-cache",               //
       "Keep-Alive: timeout=5, max=1000",       //
       "Content-Type: application/x-protobuf",  //
-      transfer_encoding_hdr,                   //
       allow_origin_hdr.c_str()};
 
   if (req.method == "OPTIONS") {
@@ -316,43 +290,8 @@
     return HttpReply(client->sock.get(), "200 OK", headers);
   }
 
-  // New endpoint, returns data in batches using chunked transfer encoding.
-  // The batch size is determined by |cells_per_batch_| and
-  // |batch_split_threshold_| in query_result_serializer.h.
-  // This is temporary, it will be switched to WebSockets soon.
-  if (req.uri == "/query") {
-    std::vector<uint8_t> response;
-
-    // Start the chunked reply.
-    strncpy(transfer_encoding_hdr, "Transfer-Encoding: chunked",
-            sizeof(transfer_encoding_hdr));
-    base::UnixSocket* cli_sock = client->sock.get();
-    HttpReply(cli_sock, "200 OK", headers, nullptr, kOmitContentLength);
-
-    // |on_result_chunk| will be called nested within the same callstack of the
-    // rpc.Query() call. No further calls will be made once Query() returns.
-    auto on_result_chunk = [&](const uint8_t* buf, size_t len, bool has_more) {
-      PERFETTO_DLOG("Sending response chunk, len=%zu eof=%d", len, !has_more);
-      char chunk_hdr[32];
-      auto hdr_len = static_cast<size_t>(sprintf(chunk_hdr, "%zx\r\n", len));
-      cli_sock->Send(chunk_hdr, hdr_len);
-      cli_sock->Send(buf, len);
-      cli_sock->Send("\r\n", 2);
-      if (!has_more) {
-        hdr_len = static_cast<size_t>(sprintf(chunk_hdr, "0\r\n\r\n"));
-        cli_sock->Send(chunk_hdr, hdr_len);
-      }
-    };
-    trace_processor_rpc_.Query(
-        reinterpret_cast<const uint8_t*>(req.body.data()), req.body.size(),
-        on_result_chunk);
-    return;
-  }
-
-  // Legacy endpoint.
-  // Returns a columnar-oriented one-shot result. Very inefficient for large
-  // result sets. Very inefficient in general too.
   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(),
@@ -375,13 +314,6 @@
                      res.size());
   }
 
-  if (req.uri == "/get_metric_descriptors") {
-    std::vector<uint8_t> res = trace_processor_rpc_.GetMetricDescriptors(
-        reinterpret_cast<const uint8_t*>(req.body.data()), req.body.size());
-    return HttpReply(client->sock.get(), "200 OK", headers, res.data(),
-                     res.size());
-  }
-
   if (req.uri == "/enable_metatrace") {
     trace_processor_rpc_.EnableMetatrace();
     return HttpReply(client->sock.get(), "200 OK", headers);
@@ -398,13 +330,9 @@
 
 }  // namespace
 
-void RunHttpRPCServer(std::unique_ptr<TraceProcessor> preloaded_instance,
-                      std::string port_number) {
+void RunHttpRPCServer(std::unique_ptr<TraceProcessor> preloaded_instance) {
   HttpServer srv(std::move(preloaded_instance));
-  std::string port = port_number.empty() ? kBindPort : port_number;
-  std::string ipv4_addr = "127.0.0.1:" + port;
-  std::string ipv6_addr = "[::1]:" + port;
-  srv.Run(ipv4_addr.c_str(), ipv6_addr.c_str());
+  srv.Run();
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/rpc/httpd.h b/src/trace_processor/rpc/httpd.h
index 57e7ddb..b145da8 100644
--- a/src/trace_processor/rpc/httpd.h
+++ b/src/trace_processor/rpc/httpd.h
@@ -18,7 +18,6 @@
 #define SRC_TRACE_PROCESSOR_RPC_HTTPD_H_
 
 #include <memory>
-#include <string>
 
 namespace perfetto {
 namespace trace_processor {
@@ -30,7 +29,7 @@
 // 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>, std::string);
+void RunHttpRPCServer(std::unique_ptr<TraceProcessor>);
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/rpc/proto_ring_buffer.cc b/src/trace_processor/rpc/proto_ring_buffer.cc
deleted file mode 100644
index 3354efe..0000000
--- a/src/trace_processor/rpc/proto_ring_buffer.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/proto_ring_buffer.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-constexpr size_t kGrowBytes = 128 * 1024;
-
-inline ProtoRingBuffer::Message FramingError() {
-  ProtoRingBuffer::Message msg{};
-  msg.fatal_framing_error = true;
-  return msg;
-}
-
-// Tries to decode a length-delimited proto field from |start|.
-// Returns a valid boundary if the preamble is valid and the length is within
-// |end|, or an invalid message otherwise.
-ProtoRingBuffer::Message TryReadMessage(const uint8_t* start,
-                                        const uint8_t* end) {
-  namespace proto_utils = protozero::proto_utils;
-  uint64_t field_tag = 0;
-  auto* start_of_len = proto_utils::ParseVarInt(start, end, &field_tag);
-  if (start_of_len == start)
-    return ProtoRingBuffer::Message{};  // Not enough data.
-
-  const uint32_t tag = field_tag & 0x07;
-  if (tag !=
-      static_cast<uint32_t>(proto_utils::ProtoWireType::kLengthDelimited)) {
-    PERFETTO_ELOG("RPC framing error, unexpected msg tag 0x%xu", tag);
-    return FramingError();
-  }
-
-  uint64_t msg_len = 0;
-  auto* start_of_msg = proto_utils::ParseVarInt(start_of_len, end, &msg_len);
-  if (start_of_msg == start_of_len)
-    return ProtoRingBuffer::Message{};  // Not enough data.
-
-  if (msg_len > ProtoRingBuffer::kMaxMsgSize) {
-    PERFETTO_ELOG("RPC framing error, message too large (%" PRIu64 " > %zu)",
-                  msg_len, ProtoRingBuffer::kMaxMsgSize);
-    return FramingError();
-  }
-
-  if (start_of_msg + msg_len > end)
-    return ProtoRingBuffer::Message{};  // Not enough data.
-
-  ProtoRingBuffer::Message msg{};
-  msg.start = start_of_msg;
-  msg.len = static_cast<uint32_t>(msg_len);
-  msg.field_id = static_cast<uint32_t>(field_tag >> 3);
-  return msg;
-}
-
-}  // namespace
-
-ProtoRingBuffer::ProtoRingBuffer()
-    : buf_(base::PagedMemory::Allocate(kGrowBytes)) {}
-ProtoRingBuffer::~ProtoRingBuffer() = default;
-
-void ProtoRingBuffer::Append(const void* data_void, size_t data_len) {
-  if (failed_)
-    return;
-  const uint8_t* data = static_cast<const uint8_t*>(data_void);
-  PERFETTO_DCHECK(wr_ <= buf_.size());
-  PERFETTO_DCHECK(wr_ >= rd_);
-
-  // If the last call to ReadMessage() consumed all the data in the buffer and
-  // there are no incomplete messages pending, restart from the beginning rather
-  // than keep ringing. This is the most common case.
-  if (rd_ == wr_)
-    rd_ = wr_ = 0;
-
-  // The caller is expected to always issue a ReadMessage() after each Append().
-  PERFETTO_CHECK(!fastpath_.valid());
-  if (rd_ == wr_) {
-    auto msg = TryReadMessage(data, data + data_len);
-    if (msg.valid() && msg.end() == (data + data_len)) {
-      // Fastpath: in many cases, the underlying stream will effectively
-      // preserve the atomicity of messages for most small messages.
-      // In this case we can avoid the extra buf_ roundtrip and just pass a
-      // pointer to |data| + (proto preamble len).
-      // The next call to ReadMessage)= will return |fastpath_|.
-      fastpath_ = std::move(msg);
-      return;
-    }
-  }
-
-  size_t avail = buf_.size() - wr_;
-  if (data_len > avail) {
-    // This whole section should be hit extremely rare.
-
-    // Try first just recompacting the buffer by moving everything to the left.
-    // This can happen if we received "a message and a bit" on each Append call
-    // so we ended pup in a situation like:
-    // buf_: [unused space] [msg1 incomplete]
-    //                      ^rd_             ^wr_
-    //
-    // After recompaction:
-    // buf_: [msg1 incomplete]
-    //       ^rd_             ^wr_
-    uint8_t* buf = static_cast<uint8_t*>(buf_.Get());
-    memmove(&buf[0], &buf[rd_], wr_ - rd_);
-    avail += rd_;
-    wr_ -= rd_;
-    rd_ = 0;
-    if (data_len > avail) {
-      // The compaction didn't free up enough space and we need to expand the
-      // ring buffer. Yes, we could have detected this earlier and split the
-      // code paths, rather than first compacting and then realizing it wasn't
-      // sufficient. However, that would make the code harder to reason about,
-      // creating code paths that are nearly never hit, hence making it more
-      // likely to accumulate bugs in future. All this is very rare.
-      size_t new_size = buf_.size();
-      while (data_len > new_size - wr_)
-        new_size += kGrowBytes;
-      if (new_size > kMaxMsgSize * 2) {
-        failed_ = true;
-        return;
-      }
-      auto new_buf = base::PagedMemory::Allocate(new_size);
-      memcpy(new_buf.Get(), buf_.Get(), buf_.size());
-      buf_ = std::move(new_buf);
-      avail = new_size - wr_;
-      // No need to touch rd_ / wr_ cursors.
-    }
-  }
-
-  // Append the received data at the end of the ring buffer.
-  uint8_t* buf = static_cast<uint8_t*>(buf_.Get());
-  memcpy(&buf[wr_], data, data_len);
-  wr_ += data_len;
-}
-
-ProtoRingBuffer::Message ProtoRingBuffer::ReadMessage() {
-  if (failed_)
-    return FramingError();
-
-  if (fastpath_.valid()) {
-    // The fastpath can only be hit when the buffer is empty.
-    PERFETTO_CHECK(rd_ == wr_);
-    auto msg = std::move(fastpath_);
-    fastpath_ = Message{};
-    return msg;
-  }
-
-  uint8_t* buf = static_cast<uint8_t*>(buf_.Get());
-
-  PERFETTO_DCHECK(rd_ <= wr_);
-  if (rd_ >= wr_)
-    return Message{};  // Completely empty.
-
-  auto msg = TryReadMessage(&buf[rd_], &buf[wr_]);
-  if (!msg.valid()) {
-    failed_ = failed_ || msg.fatal_framing_error;
-    return msg;  // Return |msg| because it could be a framing error.
-  }
-
-  // Note: msg.start is > buf[rd_], because it skips the proto preamble.
-  PERFETTO_DCHECK(msg.start > &buf[rd_]);
-  const uint8_t* msg_end = msg.start + msg.len;
-  PERFETTO_CHECK(msg_end > &buf[rd_] && msg_end <= &buf[wr_]);
-  auto msg_outer_len = static_cast<size_t>(msg_end - &buf[rd_]);
-  rd_ += msg_outer_len;
-  return msg;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/rpc/proto_ring_buffer.h b/src/trace_processor/rpc/proto_ring_buffer.h
deleted file mode 100644
index 62934ca..0000000
--- a/src/trace_processor/rpc/proto_ring_buffer.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_PROTO_RING_BUFFER_H_
-#define SRC_TRACE_PROCESSOR_RPC_PROTO_RING_BUFFER_H_
-
-#include <stdint.h>
-
-#include "perfetto/ext/base/paged_memory.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// This class buffers and tokenizes proto messages used for the TraceProcessor
-// RPC interface (See comments in trace_processor.proto).
-// From a logical level, the RPC is a sequence of protos like this.
-// [ header 1 ] [ payload 1   ]
-// [ header 2 ] [ payload 2  ]
-// [ header 3 ] [ payload 3     ]
-// Where [ header ] is a variable-length sequence of:
-// [ Field ID = 1, type = length-delimited] [ length (varint) ].
-// The RPC pipe is byte-oriented, not message-oriented (like a TCP stream).
-// The pipe is not required to respect the boundaries of each message, it only
-// guarantees that data is not lost or duplicated. The following sequence of
-// inbound events is possible:
-// 1. [ hdr 1 (incomplete) ... ]
-// 2. [ ... hdr 1 ] [ payload 1 ] [ hdr 2 ] [ payoad 2 ] [ hdr 3 ] [ pay... ]
-// 3. [ ...load 3 ]
-//
-// This class maintains inbound requests in a ring buffer.
-// The expected usage is:
-// ring_buf.Append(data, len);
-// for (;;) {
-//   auto msg = ring_buf.ReadMessage();
-//   if (!msg.valid())
-//     break;
-//   Decode(msg);
-// }
-//
-// After each call to Append, the caller is expected to call ReadMessage() until
-// it returns an invalid message (signalling no more messages could be decoded).
-// Note that a single Append can "unblock" > 1 messages, which is why the caller
-// needs to keep calling ReadMessage in a loop.
-//
-// Internal architecture
-// ---------------------
-// Internally this is similar to a ring-buffer, with the caveat that it never
-// wraps, it only expands. Expansions are rare. The deal is that in most cases
-// the read cursor follows very closely the write cursor. For instance, if the
-// uderlying behaves as a dgram socket, after each Append, the read cursor will
-// chase completely the write cursor. Even if the underyling stream is not
-// always atomic, the expectation is that the read cursor will eventually reach
-// the write one within few messages.
-// A visual example, imagine we have four messages: 2it 4will 2be 4fine
-// Visually:
-//
-// Append("2it4wi"): A message and a bit:
-// [ 2it 4wi                     ]
-// ^R       ^W
-//
-// After the ReadMessage(), the 1st message will be read, but not the 2nd.
-// [ 2it 4wi                     ]
-//      ^R ^W
-//
-// Append("ll2be4f")
-// [ 2it 4will 2be 4f            ]
-//      ^R           ^W
-//
-// After the ReadMessage() loop:
-// [ 2it 4will 2be 4f            ]
-//                ^R ^W
-// Append("ine")
-// [ 2it 4will 2be 4fine         ]
-//                ^R    ^W
-//
-// In the next ReadMessage() the R cursor will chase the W cursor. When this
-// happens (very frequent) we can just reset both cursors to 0 and restart.
-// If we are unlucky and get to the end of the buffer, two things happen:
-// 1. We try first to recompact the buffer, moving everything left by R.
-// 2. If still there isn't enough space, we expand the buffer.
-// Given that each message is expected to be at most kMaxMsgSize (64 MB), the
-// expansion is bound at 2 * kMaxMsgSize.
-class ProtoRingBuffer {
- public:
-  static constexpr size_t kMaxMsgSize = 64 * 1024 * 1024;
-  struct Message {
-    const uint8_t* start = nullptr;
-    uint32_t len = 0;
-    uint32_t field_id = 0;
-    bool fatal_framing_error = false;
-    const uint8_t* end() const { return start + len; }
-    inline bool valid() const { return !!start; }
-  };
-
-  ProtoRingBuffer();
-  ~ProtoRingBuffer();
-  ProtoRingBuffer(const ProtoRingBuffer&) = delete;
-  ProtoRingBuffer& operator=(const ProtoRingBuffer&) = delete;
-
-  // Appends data into the ring buffer, recompacting or resizing it if needed.
-  // Will invaildate the pointers previously handed out.
-  void Append(const void* data, size_t len);
-
-  // If a protobuf message can be read, it returns the boundaries of the message
-  // (without including the preamble) and advances the read cursor.
-  // If no message is avaiable, returns a null range.
-  // The returned pointer is only valid until the next call to Append(), as
-  // that can recompact or resize the underlying buffer.
-  Message ReadMessage();
-
-  // Exposed for testing.
-  size_t capacity() const { return buf_.size(); }
-  size_t avail() const { return buf_.size() - (wr_ - rd_); }
-
- private:
-  base::PagedMemory buf_;
-  Message fastpath_{};
-  bool failed_ = false;  // Set in case of an unrecoverable framing faiulre.
-  size_t rd_ = 0;        // Offset of the read cursor in |buf_|.
-  size_t wr_ = 0;        // Offset of the write cursor in |buf_|.
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_RPC_PROTO_RING_BUFFER_H_
diff --git a/src/trace_processor/rpc/proto_ring_buffer_unittest.cc b/src/trace_processor/rpc/proto_ring_buffer_unittest.cc
deleted file mode 100644
index 0e3944c..0000000
--- a/src/trace_processor/rpc/proto_ring_buffer_unittest.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/proto_ring_buffer.h"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <list>
-#include <ostream>
-#include <random>
-#include <vector>
-
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "test/gtest_and_gmock.h"
-
-using testing::ElementsAre;
-
-namespace perfetto {
-namespace trace_processor {
-
-// For ASSERT_EQ()
-inline bool operator==(const ProtoRingBuffer::Message& a,
-                       const ProtoRingBuffer::Message& b) {
-  if (a.field_id != b.field_id || a.len != b.len || a.valid() != b.valid())
-    return false;
-  if (!a.valid())
-    return true;
-  return memcmp(a.start, b.start, a.len) == 0;
-}
-
-inline std::ostream& operator<<(std::ostream& stream,
-                                const ProtoRingBuffer::Message& msg) {
-  stream << "Message{field_id:" << msg.field_id << ", len:" << msg.len;
-  stream << ", payload: \"";
-  static constexpr uint32_t kTruncLen = 16;
-  for (uint32_t i = 0; i < std::min(msg.len, kTruncLen); i++)
-    stream << static_cast<char>(msg.start[i]);
-  if (msg.len > kTruncLen)
-    stream << "...";
-  stream << "\"}";
-  return stream;
-}
-
-namespace {
-
-constexpr uint32_t kMaxMsgSize = ProtoRingBuffer::kMaxMsgSize;
-
-class ProtoRingBufferTest : public ::testing::Test {
- public:
-  ProtoRingBuffer::Message MakeProtoMessage(uint32_t field_id,
-                                            uint32_t len,
-                                            bool append = false) {
-    ProtoRingBuffer::Message msg{};
-    namespace proto_utils = protozero::proto_utils;
-    const uint8_t* initial_ptr = last_msg_.data();
-    if (!append)
-      last_msg_.clear();
-    size_t initial_size = last_msg_.size();
-
-    // 20 is an over-estimation of the preamble (fixed by the 2nd resize below).
-    last_msg_.resize(initial_size + len + 20);
-    uint8_t* wptr = &last_msg_[initial_size];
-    auto tag = proto_utils::MakeTagLengthDelimited(field_id);
-    wptr = proto_utils::WriteVarInt(tag, wptr);
-    wptr = proto_utils::WriteVarInt(len, wptr);
-    msg.start = wptr;
-    msg.len = len;
-    msg.field_id = field_id;
-    for (uint32_t i = 0; i < len; i++)
-      *(wptr++) = '0' + ((len + i) % 73);  // 73 prime for more unique patterns.
-
-    PERFETTO_CHECK(wptr <= &last_msg_.back());
-    last_msg_.resize(static_cast<size_t>(wptr - &last_msg_[0]));
-
-    // Vector must not expand, because the returned Mesdage relies on pointer
-    // stability. The TEST_F must reserve enough capacity.
-    if (append)
-      PERFETTO_CHECK(last_msg_.data() == initial_ptr);
-    return msg;
-  }
-
-  std::vector<uint8_t> last_msg_;
-};
-
-// Test that when appending buffers that contain whole messages the ring buffer
-// is skipped.
-TEST_F(ProtoRingBufferTest, Fastpath) {
-  ProtoRingBuffer buf;
-  for (uint32_t i = 0; i < 10; i++) {
-    // Write a whole message that hits the fastpath.
-    auto expected = MakeProtoMessage(/*field_id=*/i + 1, /*len=*/i * 7);
-    buf.Append(last_msg_.data(), last_msg_.size());
-    // Shouln't take any space the buffer because it hits the fastpath.
-    EXPECT_EQ(buf.avail(), buf.capacity());
-    auto actual = buf.ReadMessage();
-    ASSERT_TRUE(actual.valid());
-    EXPECT_EQ(actual.start, expected.start);  // Should point to the same buf.
-    EXPECT_EQ(actual, expected);
-
-    // Now write a message in two fragments. It won't hit the fastpath
-    expected = MakeProtoMessage(/*field_id*/ 1, /*len=*/32);
-    buf.Append(last_msg_.data(), 13);
-    EXPECT_LT(buf.avail(), buf.capacity());
-    EXPECT_FALSE(buf.ReadMessage().valid());
-
-    // Append 2nd fragment.
-    buf.Append(last_msg_.data() + 13, last_msg_.size() - 13);
-    actual = buf.ReadMessage();
-    ASSERT_TRUE(actual.valid());
-    EXPECT_EQ(actual, expected);
-  }
-}
-
-TEST_F(ProtoRingBufferTest, CoalescingStream) {
-  ProtoRingBuffer buf;
-  last_msg_.reserve(1024);
-  std::list<ProtoRingBuffer::Message> expected;
-
-  // Build 6 messages of 100 bytes each (100 does not include preambles).
-  for (uint32_t i = 1; i <= 6; i++)
-    expected.emplace_back(MakeProtoMessage(i, 100, /*append=*/true));
-
-  uint32_t frag_lens[] = {120, 20, 471, 1};
-  uint32_t frag_sum = 0;
-  for (uint32_t i = 0; i < base::ArraySize(frag_lens); i++)
-    frag_sum += frag_lens[i];
-  ASSERT_EQ(frag_sum, last_msg_.size());
-
-  // Append the messages in such a way that each appen either passes a portion
-  // of a message (the 20 ones) or more than a message.
-  uint32_t written = 0;
-  for (uint32_t i = 0; i < base::ArraySize(frag_lens); i++) {
-    buf.Append(&last_msg_[written], frag_lens[i]);
-    written += frag_lens[i];
-    for (;;) {
-      auto msg = buf.ReadMessage();
-      if (!msg.valid())
-        break;
-      ASSERT_FALSE(expected.empty());
-      ASSERT_EQ(expected.front(), msg);
-      expected.pop_front();
-    }
-  }
-  EXPECT_TRUE(expected.empty());
-}
-
-TEST_F(ProtoRingBufferTest, RandomSizes) {
-  ProtoRingBuffer buf;
-  std::minstd_rand0 rnd(0);
-
-  last_msg_.reserve(1024 * 1024 * 64);
-  std::list<ProtoRingBuffer::Message> expected;
-
-  const uint32_t kNumMsg = 100;
-  for (uint32_t i = 0; i < kNumMsg; i++) {
-    uint32_t field_id = static_cast<uint32_t>(1 + (rnd() % 1024u));
-    uint32_t rndval = static_cast<uint32_t>(rnd());
-    uint32_t len = 1 + (rndval % 1024);
-    if ((rndval % 100) < 2) {
-      len *= 10 * 1024;  // 2% of messages will get close to kMaxMsgSize
-    } else if ((rndval % 100) < 20) {
-      len *= 512;  // 18% will be around 500K;
-    }
-    len = std::max(std::min(len, kMaxMsgSize), 1u);
-    expected.push_back(MakeProtoMessage(field_id, len, /*append=*/true));
-  }
-
-  uint32_t total = static_cast<uint32_t>(last_msg_.size());
-  for (uint32_t frag_sum = 0; frag_sum < total;) {
-    uint32_t frag_len = static_cast<uint32_t>(1 + (rnd() % 32768));
-    frag_len = std::min(frag_len, total - frag_sum);
-    buf.Append(&last_msg_[frag_sum], frag_len);
-    frag_sum += frag_len;
-    for (;;) {
-      auto msg = buf.ReadMessage();
-      if (!msg.valid())
-        break;
-      ASSERT_FALSE(expected.empty());
-      ASSERT_EQ(expected.front(), msg);
-      expected.pop_front();
-    }
-  }
-  EXPECT_TRUE(expected.empty());
-}
-
-TEST_F(ProtoRingBufferTest, HandleProtoErrorsGracefully) {
-  ProtoRingBuffer buf;
-
-  // Apppend a partial valid 32 byte message, followed by some invalild
-  // data.
-  auto expected = MakeProtoMessage(1, 32);
-  buf.Append(last_msg_.data(), last_msg_.size() - 1);
-  auto msg = buf.ReadMessage();
-  EXPECT_FALSE(msg.valid());
-  EXPECT_FALSE(msg.fatal_framing_error);
-
-  uint8_t invalid[] = {0x7f, 0x7f, 0x7f, 0x7f};
-  invalid[0] = last_msg_.back();
-  buf.Append(invalid, sizeof(invalid));
-
-  // The first message shoudl be valild
-  msg = buf.ReadMessage();
-  EXPECT_EQ(msg, expected);
-
-  // All the rest should be a framing error.
-  for (int i = 0; i < 3; i++) {
-    msg = buf.ReadMessage();
-    EXPECT_FALSE(msg.valid());
-    EXPECT_TRUE(msg.fatal_framing_error);
-
-    buf.Append(invalid, sizeof(invalid));
-  }
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/rpc/query_result_serializer.cc b/src/trace_processor/rpc/query_result_serializer.cc
deleted file mode 100644
index f6042fd..0000000
--- a/src/trace_processor/rpc/query_result_serializer.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/rpc/query_result_serializer.h"
-
-#include <vector>
-
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/trace_processor/iterator_impl.h"
-
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-namespace pu = ::protozero::proto_utils;
-using BatchProto = protos::pbzero::QueryResult::CellsBatch;
-using ResultProto = protos::pbzero::QueryResult;
-
-// The reserved field in trace_processor.proto.
-static constexpr uint32_t kPaddingFieldId = 7;
-
-uint8_t MakeLenDelimTag(uint32_t field_num) {
-  uint32_t tag = pu::MakeTagLengthDelimited(field_num);
-  PERFETTO_DCHECK(tag <= 127);  // Must fit in one byte.
-  return static_cast<uint8_t>(tag);
-}
-
-}  // namespace
-
-QueryResultSerializer::QueryResultSerializer(Iterator iter)
-    : iter_(iter.take_impl()), num_cols_(iter_->ColumnCount()) {}
-
-QueryResultSerializer::~QueryResultSerializer() = default;
-
-bool QueryResultSerializer::Serialize(std::vector<uint8_t>* buf) {
-  const size_t slice = batch_split_threshold_ + 4096;
-  protozero::HeapBuffered<protos::pbzero::QueryResult> result(slice, slice);
-  bool has_more = Serialize(result.get());
-  auto arr = result.SerializeAsArray();
-  buf->insert(buf->end(), arr.begin(), arr.end());
-  return has_more;
-}
-
-bool QueryResultSerializer::Serialize(protos::pbzero::QueryResult* res) {
-  PERFETTO_CHECK(!eof_reached_);
-
-  if (!did_write_column_names_) {
-    SerializeColumnNames(res);
-    did_write_column_names_ = true;
-  }
-
-  // In case of an error we still want to go through SerializeBatch(). That will
-  // write an empty batch with the EOF marker. Errors can happen also in the
-  // middle of a query, not just before starting it.
-
-  SerializeBatch(res);
-  MaybeSerializeError(res);
-  return !eof_reached_;
-}
-
-void QueryResultSerializer::SerializeBatch(protos::pbzero::QueryResult* res) {
-  // The buffer is filled in this way:
-  // - Append all the strings as we iterate through the results. The rationale
-  //   is that strings are typically the largest part of the result and we want
-  //   to avoid copying these.
-  // - While iterating, buffer all other types of cells. They will be appended
-  //   at the end of the batch, after the string payload is known.
-
-  // Note: this function uses uint32_t instead of size_t because Wasm doesn't
-  // have yet native 64-bit integers and this is perf-sensitive.
-
-  const auto& writer = *res->stream_writer();
-  auto* batch = res->add_batch();
-
-  // Start the |string_cells|.
-  auto* strings = batch->BeginNestedMessage<protozero::Message>(
-      BatchProto::kStringCellsFieldNumber);
-
-  // This keeps track of the overall size of the batch. It is used to decide if
-  // we need to prematurely end the batch, even if the batch_split_threshold_ is
-  // not reached. This is to guard against the degenerate case of appending a
-  // lot of very large strings and ending up with an enormous batch.
-  uint32_t approx_batch_size = 16;
-
-  std::vector<uint8_t> cell_types(cells_per_batch_);
-
-  // Varints and doubles are written on stack-based storage and appended later.
-  protozero::PackedVarInt varints;
-  protozero::PackedFixedSizeInt<double> doubles;
-
-  // We write blobs on a temporary heap buffer and append it at the end. Blobs
-  // are extremely rare, trying to avoid copies is not worth the complexity.
-  std::vector<uint8_t> blobs;
-
-  uint32_t cell_idx = 0;
-  bool batch_full = false;
-
-  for (;; ++cell_idx, ++col_) {
-    // This branch is hit before starting each row. Note that iter_->Next() must
-    // be called before iterating on a row. col_ is initialized at MAX_INT in
-    // the constructor.
-    if (col_ >= num_cols_) {
-      col_ = 0;
-      // If num_cols_ == 0 and the query didn't return any result (e.g. CREATE
-      // TABLE) we should exit at this point. We still need to advance the
-      // iterator via Next() otherwise the statement will have no effect.
-      if (!iter_->Next())
-        break;  // EOF or error.
-
-      PERFETTO_DCHECK(num_cols_ > 0);
-      // We need to guarantee that a batch contains whole rows. Before moving to
-      // the next row, make sure that: (i) there is space for all the columns;
-      // (ii) the batch didn't grow too much.
-      if (cell_idx + num_cols_ > cells_per_batch_ ||
-          approx_batch_size > batch_split_threshold_) {
-        batch_full = true;
-        break;
-      }
-    }
-
-    auto value = iter_->Get(col_);
-    uint8_t cell_type = BatchProto::CELL_INVALID;
-    switch (value.type) {
-      case SqlValue::Type::kNull: {
-        cell_type = BatchProto::CELL_NULL;
-        break;
-      }
-      case SqlValue::Type::kLong: {
-        cell_type = BatchProto::CELL_VARINT;
-        varints.Append(value.long_value);
-        approx_batch_size += 4;  // Just a guess, doesn't need to be accurate.
-        break;
-      }
-      case SqlValue::Type::kDouble: {
-        cell_type = BatchProto::CELL_FLOAT64;
-        approx_batch_size += sizeof(double);
-        doubles.Append(value.double_value);
-        break;
-      }
-      case SqlValue::Type::kString: {
-        // Append the string to the one |string_cells| proto field, just use
-        // \0 to separate each string. We are deliberately NOT emitting one
-        // proto repeated field for each string. Doing so significantly slows
-        // down parsing on the JS side (go/postmessage-benchmark).
-        cell_type = BatchProto::CELL_STRING;
-        uint32_t len_with_nul =
-            static_cast<uint32_t>(strlen(value.string_value)) + 1;
-        const char* str_begin = value.string_value;
-        strings->AppendRawProtoBytes(str_begin, len_with_nul);
-        approx_batch_size += len_with_nul + 4;  // 4 is a guess on the preamble.
-        break;
-      }
-      case SqlValue::Type::kBytes: {
-        // Each blob is stored as its own repeated proto field, unlike strings.
-        // Blobs don't incur in text-decoding overhead (and are also rare).
-        cell_type = BatchProto::CELL_BLOB;
-        auto* src = static_cast<const uint8_t*>(value.bytes_value);
-        uint32_t len = static_cast<uint32_t>(value.bytes_count);
-        uint8_t preamble[16];
-        uint8_t* preamble_end = &preamble[0];
-        *(preamble_end++) = MakeLenDelimTag(BatchProto::kBlobCellsFieldNumber);
-        preamble_end = pu::WriteVarInt(len, preamble_end);
-        blobs.insert(blobs.end(), preamble, preamble_end);
-        blobs.insert(blobs.end(), src, src + len);
-        approx_batch_size += len + 4;  // 4 is a guess on the preamble size.
-        break;
-      }
-    }
-
-    PERFETTO_DCHECK(cell_type != BatchProto::CELL_INVALID);
-    cell_types[cell_idx] = cell_type;
-  }  // for (cell)
-
-  // Backfill the string size.
-  strings->Finalize();
-  strings = nullptr;
-
-  // Write the cells headers (1 byte per cell).
-  batch->AppendBytes(BatchProto::kCellsFieldNumber, cell_types.data(),
-                     cell_idx);
-
-  // Append the |varint_cells|, copying over the packed varint buffer.
-  if (varints.size())
-    batch->set_varint_cells(varints);
-
-  // Append the |float64_cells|, copying over the packed fixed64 buffer. This is
-  // appended at a 64-bit aligned offset, so that JS can access these by overlay
-  // a TypedArray, without extra copies.
-  const uint32_t doubles_size = static_cast<uint32_t>(doubles.size());
-  if (doubles_size > 0) {
-    uint8_t preamble[16];
-    uint8_t* preamble_end = &preamble[0];
-    *(preamble_end++) = MakeLenDelimTag(BatchProto::kFloat64CellsFieldNumber);
-    preamble_end = pu::WriteVarInt(doubles_size, preamble_end);
-    uint32_t preamble_size = static_cast<uint32_t>(preamble_end - &preamble[0]);
-
-    // The byte after the preamble must start at a 64bit-aligned offset.
-    // The padding needs to be > 1 Byte because of proto encoding.
-    const uint32_t off =
-        static_cast<uint32_t>(writer.written() + preamble_size);
-    const uint32_t aligned_off = (off + 7) & ~7u;
-    uint32_t padding = aligned_off - off;
-    padding = padding == 1 ? 9 : padding;
-    if (padding > 0) {
-      uint8_t pad_buf[10];
-      uint8_t* pad = pad_buf;
-      *(pad++) = pu::MakeTagVarInt(kPaddingFieldId);
-      for (uint32_t i = 0; i < padding - 2; i++)
-        *(pad++) = 0x80;
-      *(pad++) = 0;
-      batch->AppendRawProtoBytes(pad_buf, static_cast<size_t>(pad - pad_buf));
-    }
-    batch->AppendRawProtoBytes(preamble, preamble_size);
-    PERFETTO_CHECK(writer.written() % 8 == 0);
-    batch->AppendRawProtoBytes(doubles.data(), doubles_size);
-  }  // if (doubles_size > 0)
-
-  // Append the blobs.
-  batch->AppendRawProtoBytes(blobs.data(), blobs.size());
-
-  // If this is the last batch, write the EOF field.
-  if (!batch_full) {
-    eof_reached_ = true;
-    batch->set_is_last_batch(true);
-  }
-
-  // Finally backfill the size of the whole |batch| sub-message.
-  batch->Finalize();
-}
-
-void QueryResultSerializer::MaybeSerializeError(
-    protos::pbzero::QueryResult* res) {
-  if (iter_->Status().ok())
-    return;
-  std::string err = iter_->Status().message();
-  // Make sure the |error| field is always non-zero if the query failed, so
-  // the client can tell some error happened.
-  if (err.empty())
-    err = "Unknown error";
-  res->set_error(err);
-}
-
-void QueryResultSerializer::SerializeColumnNames(
-    protos::pbzero::QueryResult* res) {
-  PERFETTO_DCHECK(!did_write_column_names_);
-  for (uint32_t c = 0; c < num_cols_; c++)
-    res->add_column_names(iter_->GetColumnName(c));
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/rpc/query_result_serializer.h b/src/trace_processor/rpc/query_result_serializer.h
deleted file mode 100644
index 9c05e0b..0000000
--- a/src/trace_processor/rpc/query_result_serializer.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
-#define SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
-
-#include <memory>
-#include <vector>
-
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class QueryResult;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class Iterator;
-class IteratorImpl;
-
-// This class serializes a TraceProcessor query result (i.e. an Iterator)
-// into batches of QueryResult (trace_processor.proto). This class
-// returns results in batches, allowing to deal with O(M) results without
-// full memory buffering. It works as follows:
-// - The iterator is passed in the constructor.
-// - The client is expected to call Serialize(out_buf) until EOF is reached.
-// - For each Serialize() call, this class will serialize a batch of cells,
-//   stopping when either when a number of cells (|cells_per_batch_|) is reached
-//   or when the batch size exceeds (batch_split_threshold_).
-//   A batch is guaranteed to contain a number of cells that is an integer
-//   multiple of the column count (i.e. a batch is not truncated in the middle
-//   of a row).
-// The intended use case is streaaming these batches onto through a
-// chunked-encoded HTTP response, or through a repetition of Wasm calls.
-class QueryResultSerializer {
- public:
-  explicit QueryResultSerializer(Iterator);
-  ~QueryResultSerializer();
-
-  // No copy or move.
-  QueryResultSerializer(const QueryResultSerializer&) = delete;
-  QueryResultSerializer& operator=(const QueryResultSerializer&) = delete;
-
-  // Appends the data to the passed protozero message. It returns true if more
-  // chunks are available (i.e. it returns NOT(|eof_reached_||)). The caller is
-  // supposed to keep calling this function until it returns false.
-  bool Serialize(protos::pbzero::QueryResult*);
-
-  // Like the above but stitches everything together in a vector. Incurs in
-  // extra copies.
-  bool Serialize(std::vector<uint8_t>*);
-
-  void set_batch_size_for_testing(uint32_t cells_per_batch, uint32_t thres) {
-    cells_per_batch_ = cells_per_batch;
-    batch_split_threshold_ = thres;
-  }
-
- private:
-  void SerializeColumnNames(protos::pbzero::QueryResult*);
-  void SerializeBatch(protos::pbzero::QueryResult*);
-  void MaybeSerializeError(protos::pbzero::QueryResult*);
-
-  std::unique_ptr<IteratorImpl> iter_;
-  const uint32_t num_cols_;
-  bool did_write_column_names_ = false;
-  bool eof_reached_ = false;
-  uint32_t col_ = UINT32_MAX;
-
-  // These params specify the thresholds for splitting the results in batches,
-  // in terms of: (1) max cells (row x cols); (2) serialized batch size in
-  // bytes, whichever is reached first. Note also that the byte limit is not
-  // 100% accurate and can occasionally yield to batches slighly larger than
-  // the limit (it splits on the next row *after* the limit is hit).
-  // Overridable for testing only.
-  uint32_t cells_per_batch_ = 50000;
-  uint32_t batch_split_threshold_ = 1024 * 128;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
diff --git a/src/trace_processor/rpc/query_result_serializer_benchmark.cc b/src/trace_processor/rpc/query_result_serializer_benchmark.cc
deleted file mode 100644
index 339d6ea..0000000
--- a/src/trace_processor/rpc/query_result_serializer_benchmark.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/rpc/query_result_serializer.h"
-
-#include <benchmark/benchmark.h>
-
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/trace_processor.h"
-
-using perfetto::trace_processor::Config;
-using perfetto::trace_processor::QueryResultSerializer;
-using perfetto::trace_processor::TraceProcessor;
-using VectorType = std::vector<uint8_t>;
-
-namespace {
-
-bool IsBenchmarkFunctionalOnly() {
-  return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
-}
-
-void BenchmarkArgs(benchmark::internal::Benchmark* b) {
-  if (IsBenchmarkFunctionalOnly()) {
-    b->Ranges({{1024, 1024}, {4096, 4096}});
-  } else {
-    b->RangeMultiplier(8)->Ranges({{128, 8192}, {4096, 1024 * 512}});
-  }
-}
-
-void RunQueryChecked(TraceProcessor* tp, const std::string& query) {
-  auto iter = tp->ExecuteQuery(query);
-  iter.Next();
-  PERFETTO_CHECK(iter.Status().ok());
-}
-
-}  // namespace
-
-static void BM_QueryResultSerializer_Mixed(benchmark::State& state) {
-  auto tp = TraceProcessor::CreateInstance(Config());
-  RunQueryChecked(tp.get(), "create virtual table win using window;");
-  RunQueryChecked(tp.get(),
-                  "update win set window_start=0, window_dur=50000, quantum=1 "
-                  "where rowid = 0");
-  VectorType buf;
-  for (auto _ : state) {
-    auto iter = tp->ExecuteQuery(
-        "select dur || dur as x, ts, dur * 1.0 as dur, quantum_ts from win");
-    QueryResultSerializer serializer(std::move(iter));
-    serializer.set_batch_size_for_testing(
-        static_cast<uint32_t>(state.range(0)),
-        static_cast<uint32_t>(state.range(1)));
-    while (serializer.Serialize(&buf)) {
-    }
-    benchmark::DoNotOptimize(buf.data());
-    buf.clear();
-  }
-  benchmark::ClobberMemory();
-}
-
-static void BM_QueryResultSerializer_Strings(benchmark::State& state) {
-  auto tp = TraceProcessor::CreateInstance(Config());
-  RunQueryChecked(tp.get(), "create virtual table win using window;");
-  RunQueryChecked(tp.get(),
-                  "update win set window_start=0, window_dur=100000, quantum=1 "
-                  "where rowid = 0");
-  VectorType buf;
-  for (auto _ : state) {
-    auto iter = tp->ExecuteQuery(
-        "select  ts || '-' || ts , (dur * 1.0) || dur from win");
-    QueryResultSerializer serializer(std::move(iter));
-    serializer.set_batch_size_for_testing(
-        static_cast<uint32_t>(state.range(0)),
-        static_cast<uint32_t>(state.range(1)));
-    while (serializer.Serialize(&buf)) {
-    }
-    benchmark::DoNotOptimize(buf.data());
-    buf.clear();
-  }
-  benchmark::ClobberMemory();
-}
-
-BENCHMARK(BM_QueryResultSerializer_Mixed)->Apply(BenchmarkArgs);
-BENCHMARK(BM_QueryResultSerializer_Strings)->Apply(BenchmarkArgs);
diff --git a/src/trace_processor/rpc/query_result_serializer_unittest.cc b/src/trace_processor/rpc/query_result_serializer_unittest.cc
deleted file mode 100644
index a655410..0000000
--- a/src/trace_processor/rpc/query_result_serializer_unittest.cc
+++ /dev/null
@@ -1,455 +0,0 @@
-
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/rpc/query_result_serializer.h"
-
-#include <deque>
-#include <ostream>
-#include <random>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// For ASSERT_THAT(ElementsAre(...))
-inline bool operator==(const SqlValue& a, const SqlValue& b) {
-  if (a.type != b.type)
-    return false;
-  if (a.type == SqlValue::kString)
-    return strcmp(a.string_value, b.string_value) == 0;
-  if (a.type == SqlValue::kBytes) {
-    if (a.bytes_count != b.bytes_count)
-      return false;
-    return memcmp(a.bytes_value, b.bytes_value, a.bytes_count) == 0;
-  }
-  return a.long_value == b.long_value;
-}
-
-inline std::ostream& operator<<(std::ostream& stream, const SqlValue& v) {
-  stream << "SqlValue{";
-  switch (v.type) {
-    case SqlValue::kString:
-      return stream << "\"" << v.string_value << "\"}";
-    case SqlValue::kBytes:
-      return stream << "Bytes[" << v.bytes_count << "]:"
-                    << base::ToHex(reinterpret_cast<const char*>(v.bytes_value),
-                                   v.bytes_count)
-                    << "}";
-    case SqlValue::kLong:
-      return stream << "Long " << v.long_value << "}";
-    case SqlValue::kDouble:
-      return stream << "Double " << v.double_value << "}";
-    case SqlValue::kNull:
-      return stream << "NULL}";
-  }
-  return stream;
-}
-
-namespace {
-
-using ::testing::ElementsAre;
-using BatchProto = protos::pbzero::QueryResult::CellsBatch;
-using ResultProto = protos::pbzero::QueryResult;
-
-void RunQueryChecked(TraceProcessor* tp, const std::string& query) {
-  auto iter = tp->ExecuteQuery(query);
-  iter.Next();
-  ASSERT_TRUE(iter.Status().ok()) << iter.Status().message();
-}
-
-// Implements a minimal deserializer for QueryResultSerializer.
-class TestDeserializer {
- public:
-  void SerializeAndDeserialize(QueryResultSerializer*);
-  void DeserializeBuffer(const uint8_t* start, size_t size);
-
-  std::vector<std::string> columns;
-  std::vector<SqlValue> cells;
-  std::string error;
-  bool eof_reached = false;
-
- private:
-  std::vector<std::unique_ptr<char[]>> copied_buf_;
-};
-
-void TestDeserializer::SerializeAndDeserialize(
-    QueryResultSerializer* serializer) {
-  std::vector<uint8_t> buf;
-  error.clear();
-  for (eof_reached = false; !eof_reached;) {
-    serializer->Serialize(&buf);
-    DeserializeBuffer(buf.data(), buf.size());
-    buf.clear();
-  }
-}
-
-void TestDeserializer::DeserializeBuffer(const uint8_t* start, size_t size) {
-  ResultProto::Decoder result(start, size);
-  error += result.error().ToStdString();
-  for (auto it = result.column_names(); it; ++it)
-    columns.push_back(it->as_std_string());
-
-  for (auto batch_it = result.batch(); batch_it; ++batch_it) {
-    ASSERT_FALSE(eof_reached);
-    auto batch_bytes = batch_it->as_bytes();
-
-    ResultProto::CellsBatch::Decoder batch(batch_bytes.data, batch_bytes.size);
-    eof_reached = batch.is_last_batch();
-    std::deque<int64_t> varints;
-    std::deque<double> doubles;
-    std::deque<std::string> blobs;
-
-    bool parse_error = false;
-    for (auto it = batch.varint_cells(&parse_error); it; ++it)
-      varints.emplace_back(*it);
-
-    for (auto it = batch.float64_cells(&parse_error); it; ++it)
-      doubles.emplace_back(*it);
-
-    for (auto it = batch.blob_cells(); it; ++it)
-      blobs.emplace_back((*it).ToStdString());
-
-    std::string merged_strings = batch.string_cells().ToStdString();
-    std::deque<std::string> strings;
-    for (size_t pos = 0; pos < merged_strings.size();) {
-      // Will return npos for the last string, but it's fine
-      size_t next_sep = merged_strings.find('\0', pos);
-      strings.emplace_back(merged_strings.substr(pos, next_sep - pos));
-      pos = next_sep == std::string::npos ? next_sep : next_sep + 1;
-    }
-
-    uint32_t num_cells = 0;
-    for (auto it = batch.cells(&parse_error); it; ++it, ++num_cells) {
-      uint8_t cell_type = static_cast<uint8_t>(*it);
-      switch (cell_type) {
-        case BatchProto::CELL_INVALID:
-          break;
-        case BatchProto::CELL_NULL:
-          cells.emplace_back(SqlValue());
-          break;
-        case BatchProto::CELL_VARINT:
-          ASSERT_GT(varints.size(), 0u);
-          cells.emplace_back(SqlValue::Long(varints.front()));
-          varints.pop_front();
-          break;
-        case BatchProto::CELL_FLOAT64:
-          ASSERT_GT(doubles.size(), 0u);
-          cells.emplace_back(SqlValue::Double(doubles.front()));
-          doubles.pop_front();
-          break;
-        case BatchProto::CELL_STRING: {
-          ASSERT_GT(strings.size(), 0u);
-          const std::string& str = strings.front();
-          copied_buf_.emplace_back(new char[str.size() + 1]);
-          char* new_buf = copied_buf_.back().get();
-          memcpy(new_buf, str.c_str(), str.size() + 1);
-          cells.emplace_back(SqlValue::String(new_buf));
-          strings.pop_front();
-          break;
-        }
-        case BatchProto::CELL_BLOB: {
-          ASSERT_GT(blobs.size(), 0u);
-          auto bytes = blobs.front();
-          copied_buf_.emplace_back(new char[bytes.size()]);
-          memcpy(copied_buf_.back().get(), bytes.data(), bytes.size());
-          cells.emplace_back(
-              SqlValue::Bytes(copied_buf_.back().get(), bytes.size()));
-          blobs.pop_front();
-          break;
-        }
-        default:
-          FAIL() << "Unknown cell type " << cell_type;
-      }
-
-      EXPECT_FALSE(parse_error);
-    }
-    if (columns.empty()) {
-      EXPECT_EQ(num_cells, 0u);
-    } else {
-      EXPECT_EQ(num_cells % columns.size(), 0u);
-    }
-  }
-}
-
-TEST(QueryResultSerializerTest, ShortBatch) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-
-  auto iter = tp->ExecuteQuery(
-      "select 1 as i8, 128 as i16, 100000 as i32, 42001001001 as i64, 1e9 as "
-      "f64, 'a_string' as str, cast('a_blob' as blob) as blb");
-  QueryResultSerializer ser(std::move(iter));
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-
-  EXPECT_THAT(deser.columns,
-              ElementsAre("i8", "i16", "i32", "i64", "f64", "str", "blb"));
-  EXPECT_THAT(deser.cells,
-              ElementsAre(SqlValue::Long(1), SqlValue::Long(128),
-                          SqlValue::Long(100000), SqlValue::Long(42001001001),
-                          SqlValue::Double(1e9), SqlValue::String("a_string"),
-                          SqlValue::Bytes("a_blob", 6)));
-}
-
-TEST(QueryResultSerializerTest, LongBatch) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-
-  RunQueryChecked(tp.get(), "create virtual table win using window;");
-  RunQueryChecked(tp.get(),
-                  "update win set window_start=0, window_dur=8192, quantum=1 "
-                  "where rowid = 0");
-
-  auto iter = tp->ExecuteQuery(
-      "select 'x' as x, ts, dur * 1.0 as dur, quantum_ts from win");
-  QueryResultSerializer ser(std::move(iter));
-
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-
-  ASSERT_THAT(deser.columns, ElementsAre("x", "ts", "dur", "quantum_ts"));
-  ASSERT_EQ(deser.cells.size(), 4 * 8192u);
-  for (uint32_t row = 0; row < 1024; row++) {
-    uint32_t cell = row * 4;
-    ASSERT_EQ(deser.cells[cell].type, SqlValue::kString);
-    ASSERT_STREQ(deser.cells[cell].string_value, "x");
-
-    ASSERT_EQ(deser.cells[cell + 1].type, SqlValue::kLong);
-    ASSERT_EQ(deser.cells[cell + 1].long_value, row);
-
-    ASSERT_EQ(deser.cells[cell + 2].type, SqlValue::kDouble);
-    ASSERT_EQ(deser.cells[cell + 2].double_value, 1.0);
-
-    ASSERT_EQ(deser.cells[cell + 3].type, SqlValue::kLong);
-    ASSERT_EQ(deser.cells[cell + 3].long_value, row);
-  }
-}
-
-TEST(QueryResultSerializerTest, BatchSaturatingBinaryPayload) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-
-  RunQueryChecked(tp.get(), "create virtual table win using window;");
-  RunQueryChecked(tp.get(),
-                  "update win set window_start=0, window_dur=1024, quantum=1 "
-                  "where rowid = 0");
-  auto iter = tp->ExecuteQuery(
-      "select 'x' as x, ts, dur * 1.0 as dur, quantum_ts from win");
-  QueryResultSerializer ser(std::move(iter));
-  ser.set_batch_size_for_testing(1024, 32);
-
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-
-  ASSERT_THAT(deser.columns, ElementsAre("x", "ts", "dur", "quantum_ts"));
-  ASSERT_EQ(deser.cells.size(), 1024 * 4u);
-}
-
-TEST(QueryResultSerializerTest, BatchSaturatingNumCells) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-
-  RunQueryChecked(tp.get(), "create virtual table win using window;");
-  RunQueryChecked(tp.get(),
-                  "update win set window_start=0, window_dur=4, quantum=1 "
-                  "where rowid = 0");
-  auto iter = tp->ExecuteQuery(
-      "select 'x' as x, ts, dur * 1.0 as dur, quantum_ts from win");
-  QueryResultSerializer ser(std::move(iter));
-  ser.set_batch_size_for_testing(16, 4096);
-
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-
-  ASSERT_THAT(deser.columns, ElementsAre("x", "ts", "dur", "quantum_ts"));
-  ASSERT_EQ(deser.cells.size(), 16u);
-}
-
-TEST(QueryResultSerializerTest, LargeStringAndBlobs) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-  RunQueryChecked(tp.get(), "create table tab (colz);");
-
-  std::minstd_rand0 rnd_engine(0);
-  std::vector<SqlValue> expected;
-  std::string sql_values;
-  std::deque<std::string> string_buf;  // Needs stable pointers
-  for (size_t n = 0; n < 32; n++) {
-    std::string very_long_str;
-    size_t len = (rnd_engine() % 4) * 32 * 1024;
-    very_long_str.resize(len);
-    for (size_t i = 0; i < very_long_str.size(); i++)
-      very_long_str[i] = 'A' + ((n * 11 + i) % 25);
-
-    if (n % 4 == 0) {
-      sql_values += "(NULL),";
-      expected.emplace_back(SqlValue());  // NULL.
-    } else if (n % 4 == 1) {
-      // Blob
-      sql_values += "(X'" + base::ToHex(very_long_str) + "'),";
-      string_buf.emplace_back(std::move(very_long_str));
-      expected.emplace_back(
-          SqlValue::Bytes(string_buf.back().data(), string_buf.back().size()));
-    } else {
-      sql_values += "('" + very_long_str + "'),";
-      string_buf.emplace_back(std::move(very_long_str));
-      expected.emplace_back(SqlValue::String(string_buf.back().c_str()));
-    }
-  }
-  sql_values.resize(sql_values.size() - 1);  // Remove trailing comma.
-  RunQueryChecked(tp.get(), "insert into tab (colz) values " + sql_values);
-
-  auto iter = tp->ExecuteQuery("select colz from tab");
-  QueryResultSerializer ser(std::move(iter));
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-  ASSERT_EQ(deser.cells.size(), expected.size());
-  for (size_t i = 0; i < expected.size(); i++) {
-    EXPECT_EQ(deser.cells[i], expected[i]) << "Cell " << i;
-  }
-}
-
-TEST(QueryResultSerializerTest, RandomSizes) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-  static constexpr uint32_t kNumCells = 3 * 1000;
-
-  RunQueryChecked(tp.get(), "create table tab (a, b, c);");
-  std::vector<SqlValue> expected;
-  expected.reserve(kNumCells);
-  std::deque<std::string> string_buf;  // Needs stable pointers
-  std::minstd_rand0 rnd_engine(0);
-  std::string insert_values;
-
-  for (uint32_t i = 0; i < kNumCells; i++) {
-    const uint32_t col = i % 3;
-    if (col == 0)
-      insert_values += "(";
-    int type = rnd_engine() % 5;
-    if (type == 0) {
-      expected.emplace_back(SqlValue());  // NULL
-      insert_values += "NULL";
-    } else if (type == 1) {
-      expected.emplace_back(SqlValue::Long(static_cast<long>(rnd_engine())));
-      insert_values += std::to_string(expected.back().long_value);
-    } else if (type == 2) {
-      expected.emplace_back(
-          SqlValue::Double(static_cast<double>(rnd_engine())));
-      insert_values += std::to_string(expected.back().double_value);
-    } else if (type == 3 || type == 4) {
-      size_t len = (rnd_engine() % 5) * 32;
-      std::string rndstr;
-      rndstr.resize(len);
-      for (size_t n = 0; n < len; n++)
-        rndstr[n] = static_cast<char>(rnd_engine() % 256);
-      auto rndstr_hex = base::ToHex(rndstr);
-      if (type == 3) {
-        insert_values += "\"" + rndstr_hex + "\"";
-        string_buf.emplace_back(std::move(rndstr_hex));
-        expected.emplace_back(SqlValue::String(string_buf.back().c_str()));
-
-      } else {
-        insert_values += "X'" + rndstr_hex + "'";
-        string_buf.emplace_back(std::move(rndstr));
-        expected.emplace_back(SqlValue::Bytes(string_buf.back().data(),
-                                              string_buf.back().size()));
-      }
-    }
-
-    if (col < 2) {
-      insert_values += ",";
-    } else {
-      insert_values += "),";
-      if (insert_values.size() > 1024 * 1024 || i == kNumCells - 1) {
-        insert_values[insert_values.size() - 1] = ';';
-        auto query = "insert into tab (a,b,c) values " + insert_values;
-        insert_values = "";
-        RunQueryChecked(tp.get(), query);
-      }
-    }
-  }
-
-  // Serialize and de-serialize with different batch and payload sizes.
-  for (int rep = 0; rep < 10; rep++) {
-    auto iter = tp->ExecuteQuery("select * from tab");
-    QueryResultSerializer ser(std::move(iter));
-    uint32_t cells_per_batch = 1 << (rnd_engine() % 8 + 2);
-    uint32_t binary_payload_size = 1 << (rnd_engine() % 8 + 8);
-    ser.set_batch_size_for_testing(cells_per_batch, binary_payload_size);
-    TestDeserializer deser;
-    deser.SerializeAndDeserialize(&ser);
-    ASSERT_EQ(deser.cells.size(), expected.size());
-    for (size_t i = 0; i < expected.size(); i++) {
-      EXPECT_EQ(deser.cells[i], expected[i]) << "Cell " << i;
-    }
-  }
-}
-
-TEST(QueryResultSerializerTest, ErrorBeforeStartingQuery) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-  auto iter = tp->ExecuteQuery("insert into incomplete_input");
-  QueryResultSerializer ser(std::move(iter));
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-  EXPECT_EQ(deser.cells.size(), 0u);
-  EXPECT_EQ(deser.error, "incomplete input");
-  EXPECT_TRUE(deser.eof_reached);
-}
-
-TEST(QueryResultSerializerTest, ErrorAfterSomeResults) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-  RunQueryChecked(tp.get(), "create table tab (x)");
-  RunQueryChecked(tp.get(), "insert into tab (x) values (0), (1), ('error')");
-  auto iter = tp->ExecuteQuery("select str_split('a;b', ';', x) as s from tab");
-  QueryResultSerializer ser(std::move(iter));
-  TestDeserializer deser;
-  deser.SerializeAndDeserialize(&ser);
-  EXPECT_NE(deser.error, "");
-  EXPECT_THAT(deser.cells,
-              ElementsAre(SqlValue::String("a"), SqlValue::String("b")));
-  EXPECT_TRUE(deser.eof_reached);
-}
-
-TEST(QueryResultSerializerTest, NoResultQuery) {
-  auto tp = TraceProcessor::CreateInstance(trace_processor::Config());
-  {
-    auto iter = tp->ExecuteQuery("create table tab (x)");
-    QueryResultSerializer ser(std::move(iter));
-    TestDeserializer deser;
-    deser.SerializeAndDeserialize(&ser);
-    EXPECT_EQ(deser.error, "");
-    EXPECT_EQ(deser.cells.size(), 0u);
-    EXPECT_TRUE(deser.eof_reached);
-  }
-
-  // Check that the table has been created for real.
-  {
-    auto iter = tp->ExecuteQuery("select count(*) from tab");
-    QueryResultSerializer ser(std::move(iter));
-    TestDeserializer deser;
-    deser.SerializeAndDeserialize(&ser);
-    EXPECT_EQ(deser.error, "");
-    EXPECT_EQ(deser.cells.size(), 1u);
-    EXPECT_TRUE(deser.eof_reached);
-  }
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/rpc/rpc.cc b/src/trace_processor/rpc/rpc.cc
index 7a9a595..b96df5e 100644
--- a/src/trace_processor/rpc/rpc.cc
+++ b/src/trace_processor/rpc/rpc.cc
@@ -22,7 +22,6 @@
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/trace_processor/trace_processor.h"
 #include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-#include "src/trace_processor/rpc/query_result_serializer.h"
 #include "src/trace_processor/tp_metatrace.h"
 
 namespace perfetto {
@@ -74,47 +73,14 @@
 void Rpc::MaybePrintProgress() {
   if (eof_ || bytes_parsed_ - bytes_last_progress_ > kProgressUpdateBytes) {
     bytes_last_progress_ = bytes_parsed_;
-    auto t_load_s =
-        static_cast<double>(base::GetWallTimeNs().count() - t_parse_started_) /
-        1e9;
+    auto t_load_s = (base::GetWallTimeNs().count() - t_parse_started_) / 1e9;
     fprintf(stderr, "\rLoading trace %.2f MB (%.1f MB/s)%s",
-            static_cast<double>(bytes_parsed_) / 1e6,
-            static_cast<double>(bytes_parsed_) / 1e6 / t_load_s,
+            bytes_parsed_ / 1e6, bytes_parsed_ / 1e6 / t_load_s,
             (eof_ ? "\n" : ""));
     fflush(stderr);
   }
 }
 
-void Rpc::Query(const uint8_t* args,
-                size_t len,
-                QueryResultBatchCallback result_callback) {
-  protos::pbzero::RawQueryArgs::Decoder query(args, len);
-  std::string sql = query.sql_query().ToStdString();
-  PERFETTO_DLOG("[RPC] Query < %s", sql.c_str());
-  PERFETTO_TP_TRACE("RPC_QUERY",
-                    [&](metatrace::Record* r) { r->AddArg("SQL", sql); });
-
-  if (!trace_processor_) {
-    static const char kErr[] = "Query() called before Parse()";
-    PERFETTO_ELOG("[RPC] %s", kErr);
-    protozero::HeapBuffered<protos::pbzero::QueryResult> result;
-    result->set_error(kErr);
-    auto vec = result.SerializeAsArray();
-    result_callback(vec.data(), vec.size(), /*has_more=*/false);
-    return;
-  }
-
-  auto it = trace_processor_->ExecuteQuery(sql.c_str());
-  QueryResultSerializer serializer(std::move(it));
-
-  std::vector<uint8_t> res;
-  for (bool has_more = true; has_more;) {
-    has_more = serializer.Serialize(&res);
-    result_callback(res.data(), res.size(), has_more);
-    res.clear();
-  }
-}
-
 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);
@@ -275,55 +241,22 @@
   PERFETTO_TP_TRACE("RPC_COMPUTE_METRIC", [&](metatrace::Record* r) {
     for (const auto& metric : metric_names) {
       r->AddArg("Metric", metric);
-      r->AddArg("Format", std::to_string(args.format()));
     }
   });
 
-  switch (args.format()) {
-    case protos::pbzero::ComputeMetricArgs::BINARY_PROTOBUF: {
-      std::vector<uint8_t> metrics_proto;
-      util::Status status =
-          trace_processor_->ComputeMetric(metric_names, &metrics_proto);
-      if (status.ok()) {
-        result->AppendBytes(
-            protos::pbzero::ComputeMetricResult::kMetricsFieldNumber,
-            metrics_proto.data(), metrics_proto.size());
-      } else {
-        result->set_error(status.message());
-      }
-      break;
-    }
-    case protos::pbzero::ComputeMetricArgs::TEXTPROTO: {
-      std::string metrics_string;
-      util::Status status = trace_processor_->ComputeMetricText(
-          metric_names, TraceProcessor::MetricResultFormat::kProtoText,
-          &metrics_string);
-      if (status.ok()) {
-        result->AppendString(
-            protos::pbzero::ComputeMetricResult::kMetricsAsPrototextFieldNumber,
-            metrics_string);
-      } else {
-        result->set_error(status.message());
-      }
-      break;
-    }
+  std::vector<uint8_t> metrics_proto;
+  util::Status status =
+      trace_processor_->ComputeMetric(metric_names, &metrics_proto);
+  if (status.ok()) {
+    result->AppendBytes(
+        protos::pbzero::ComputeMetricResult::kMetricsFieldNumber,
+        metrics_proto.data(), metrics_proto.size());
+  } else {
+    result->set_error(status.message());
   }
   return result.SerializeAsArray();
 }
 
-std::vector<uint8_t> Rpc::GetMetricDescriptors(const uint8_t*, size_t) {
-  protozero::HeapBuffered<protos::pbzero::GetMetricDescriptorsResult> result;
-  if (!trace_processor_) {
-    return result.SerializeAsArray();
-  }
-  std::vector<uint8_t> descriptor_set =
-      trace_processor_->GetMetricDescriptors();
-  result->AppendBytes(
-      protos::pbzero::GetMetricDescriptorsResult::kDescriptorSetFieldNumber,
-      descriptor_set.data(), descriptor_set.size());
-  return result.SerializeAsArray();
-}
-
 void Rpc::EnableMetatrace() {
   if (!trace_processor_)
     return;
@@ -344,7 +277,7 @@
   } else {
     result->set_error(status.message());
   }
-  return result.SerializeAsArray();
+  return trace_proto;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/rpc/rpc.h b/src/trace_processor/rpc/rpc.h
index bddc1aa..1670063 100644
--- a/src/trace_processor/rpc/rpc.h
+++ b/src/trace_processor/rpc/rpc.h
@@ -17,7 +17,6 @@
 #ifndef SRC_TRACE_PROCESSOR_RPC_RPC_H_
 #define SRC_TRACE_PROCESSOR_RPC_RPC_H_
 
-#include <functional>
 #include <memory>
 #include <vector>
 
@@ -59,33 +58,13 @@
 
   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();
   std::vector<uint8_t> ComputeMetric(const uint8_t* data, size_t len);
-  std::vector<uint8_t> GetMetricDescriptors(const uint8_t* data, size_t len);
   void EnableMetatrace();
   std::vector<uint8_t> DisableAndReadMetatrace();
 
-  // Runs a query and returns results in batch. Each batch is a proto-encoded
-  // TraceProcessor.QueryResult message and contains a variable number of rows.
-  // The callbacks are called inline, so the whole callstack looks as follows:
-  // Query(..., callback)
-  //   callback(..., has_more=true)
-  //   ...
-  //   callback(..., has_more=false)
-  //   (Query() returns at this point).
-  // TODO(primiano): long-term this API should change and be turned into a
-  // bidirectional streaming api (see go/imperative-metrics). The problem with
-  // the current design is that it holds the callstack until the query is done
-  // and makes nested query hard as they cause re-entrancy. It's okay for now
-  // but will change soon.
-  using QueryResultBatchCallback = std::function<
-      void(const uint8_t* /*buf*/, size_t /*len*/, bool /*has_more*/)>;
-  void Query(const uint8_t* args, size_t len, QueryResultBatchCallback);
-
-  // DEPRECATED, only for legacy clients. Use |Query()| above.
-  std::vector<uint8_t> RawQuery(const uint8_t* args, size_t len);
-
  private:
   void MaybePrintProgress();
 
diff --git a/src/trace_processor/rpc/wasm_bridge.cc b/src/trace_processor/rpc/wasm_bridge.cc
index 79e5dae..80beff1 100644
--- a/src/trace_processor/rpc/wasm_bridge.cc
+++ b/src/trace_processor/rpc/wasm_bridge.cc
@@ -61,7 +61,7 @@
 
 // Ingests trace data.
 void EMSCRIPTEN_KEEPALIVE trace_processor_parse(uint32_t);
-void trace_processor_parse(uint32_t size) {
+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.
@@ -97,14 +97,6 @@
           static_cast<uint32_t>(res.size()));
 }
 
-void EMSCRIPTEN_KEEPALIVE trace_processor_get_metric_descriptors(uint32_t);
-void trace_processor_get_metric_descriptors(uint32_t size) {
-  std::vector<uint8_t> res =
-      g_trace_processor_rpc->GetMetricDescriptors(g_req_buf, size);
-  g_reply(reinterpret_cast<const char*>(res.data()),
-          static_cast<uint32_t>(res.size()));
-}
-
 void EMSCRIPTEN_KEEPALIVE trace_processor_enable_metatrace(uint32_t);
 void trace_processor_enable_metatrace(uint32_t) {
   g_trace_processor_rpc->EnableMetatrace();
@@ -119,19 +111,6 @@
 }
 
 }  // extern "C"
+
 }  // namespace trace_processor
 }  // namespace perfetto
-
-int main(int, char**) {
-  // This is unused but is needed for the following series of reason:
-  // - We need the callMain() Emscripten JS helper function for traceconv (but
-  //   not for trace_processor).
-  // - Newer versions of emscripten require that callMain is explicitly exported
-  //   via EXTRA_EXPORTED_RUNTIME_METHODS = ['callMain'].
-  // - We have one set of EXTRA_EXPORTED_RUNTIME_METHODS for both
-  //   trace_processor.wasm (which does not need a main) and traceconv (which
-  //   does).
-  // - Without this main(), the Wasm bootstrap code will cause a JS error at
-  //   runtime when trying to load trace_processor.js.
-  return 0;
-}
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
index 71b6918..ba2c13f 100644
--- a/src/trace_processor/sqlite/BUILD.gn
+++ b/src/trace_processor/sqlite/BUILD.gn
@@ -47,8 +47,8 @@
       "../../../include/perfetto/trace_processor",
       "../../../protos/perfetto/trace/ftrace:zero",
       "../../base",
-      "../db",
-      "../importers/common",
+      "../db:lib",
+      "../importers:common",
       "../storage",
       "../types",
     ]
@@ -61,7 +61,6 @@
       "query_constraints_unittest.cc",
       "span_join_operator_table_unittest.cc",
       "sqlite3_str_split_unittest.cc",
-      "sqlite_utils_unittest.cc",
     ]
     deps = [
       ":sqlite",
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 8dc57f9..03b0d70 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -310,8 +310,7 @@
   // by |qc.order_by().size()| * log(row count). This should act as a crude
   // estimation of the cost.
   double sort_cost =
-      static_cast<double>(qc.order_by().size() * current_row_count) *
-      log2(current_row_count);
+      qc.order_by().size() * current_row_count * log2(current_row_count);
 
   // The cost of iterating rows is more expensive than filtering the rows
   // so multiply by an appropriate factor.
diff --git a/src/trace_processor/sqlite/span_join_operator_table.cc b/src/trace_processor/sqlite/span_join_operator_table.cc
index c6c3b78..1ab7eb7 100644
--- a/src/trace_processor/sqlite/span_join_operator_table.cc
+++ b/src/trace_processor/sqlite/span_join_operator_table.cc
@@ -53,53 +53,6 @@
   return base::nullopt;
 }
 
-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";
-    case SQLITE_INDEX_CONSTRAINT_ISNULL:
-      // The "null" will be added below in EscapedSqliteValueAsString.
-      return " is ";
-    case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
-      // The "null" will be added below in EscapedSqliteValueAsString.
-      return " is not";
-    default:
-      PERFETTO_FATAL("Operator to string conversion not impemented for %d", op);
-  }
-}
-
-std::string EscapedSqliteValueAsString(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: {
-      // If str itself contains a single quote, we need to escape it with
-      // another single quote.
-      const char* str =
-          reinterpret_cast<const char*>(sqlite3_value_text(value));
-      return "'" + base::ReplaceAll(str, "'", "''") + "'";
-    }
-    case SQLITE_NULL:
-      return " null";
-    default:
-      PERFETTO_FATAL("Unknown value type %d", sqlite3_value_type(value));
-  }
-}
-
 }  // namespace
 
 SpanJoinOperatorTable::SpanJoinOperatorTable(sqlite3* db, const TraceStorage*)
@@ -272,29 +225,9 @@
         (ob.size() == 1 && is_first_ob_partition) ||
         (ob.size() == 2 && is_first_ob_partition && is_second_ob_ts);
   }
-
-  const auto& cs = qc.constraints();
-  for (uint32_t i = 0; i < cs.size(); ++i) {
-    if (cs[i].op == kSourceGeqOpCode) {
-      info->sqlite_omit_constraint[i] = true;
-    }
-  }
-
   return SQLITE_OK;
 }
 
-int SpanJoinOperatorTable::FindFunction(const char* name,
-                                        FindFunctionFn* fn,
-                                        void**) {
-  if (base::CaseInsensitiveEqual(name, "source_geq")) {
-    *fn = [](sqlite3_context* ctx, int, sqlite3_value**) {
-      sqlite3_result_error(ctx, "Should not be called.", -1);
-    };
-    return kSourceGeqOpCode;
-  }
-  return 0;
-}
-
 std::vector<std::string>
 SpanJoinOperatorTable::ComputeSqlConstraintsForDefinition(
     const TableDefinition& defn,
@@ -304,30 +237,15 @@
   for (size_t i = 0; i < qc.constraints().size(); i++) {
     const auto& cs = qc.constraints()[i];
     auto col_name = GetNameForGlobalColumnIndex(defn, cs.column);
-    if (col_name.empty())
+    if (col_name == "")
       continue;
 
-    // Le constraints can be passed straight to the child tables as they won't
-    // affect the span join computation. Similarily, source_geq constraints
-    // explicitly request that they are passed as geq constraints to the source
-    // tables.
-    if (col_name == kTsColumnName && !sqlite_utils::IsOpLe(cs.op) &&
-        cs.op != kSourceGeqOpCode)
+    if (col_name == kTsColumnName || col_name == kDurColumnName) {
+      // Allow SQLite handle any constraints on ts or duration.
       continue;
-
-    // Allow SQLite handle any constraints on duration apart from source_geq
-    // constraints.
-    if (col_name == kDurColumnName && cs.op != kSourceGeqOpCode)
-      continue;
-
-    // If we're emitting shadow slices, don't propogate any constraints
-    // on this table as this will break the shadow slice computation.
-    if (defn.ShouldEmitPresentPartitionShadow())
-      continue;
-
-    auto op = OpToString(cs.op == kSourceGeqOpCode ? SQLITE_INDEX_CONSTRAINT_GE
-                                                   : cs.op);
-    auto value = EscapedSqliteValueAsString(argv[i]);
+    }
+    auto op = sqlite_utils::OpToString(cs.op);
+    auto value = sqlite_utils::SqliteValueAsString(argv[i]);
 
     constraints.emplace_back("`" + col_name + "`" + op + value);
   }
@@ -345,11 +263,7 @@
         desc.name.c_str());
   }
 
-  std::vector<SqliteTable::Column> cols;
-  auto status = sqlite_utils::GetColumnsForTable(db_, desc.name, cols);
-  if (!status.ok()) {
-    return status;
-  }
+  auto cols = sqlite_utils::GetColumnsForTable(db_, desc.name);
 
   uint32_t required_columns_found = 0;
   uint32_t ts_idx = std::numeric_limits<uint32_t>::max();
@@ -421,16 +335,11 @@
                                           FilterHistory) {
   PERFETTO_TP_TRACE("SPAN_JOIN_XFILTER");
 
-  util::Status status =
-      t1_.Initialize(qc, argv, Query::InitialEofBehavior::kTreatAsEof);
+  util::Status status = t1_.Initialize(qc, argv);
   if (!status.ok())
     return SQLITE_ERROR;
 
-  status = t2_.Initialize(
-      qc, argv,
-      table_->IsLeftJoin()
-          ? Query::InitialEofBehavior::kTreatAsMissingPartitionShadow
-          : Query::InitialEofBehavior::kTreatAsEof);
+  status = t2_.Initialize(qc, argv);
   if (!status.ok())
     return SQLITE_ERROR;
 
@@ -508,7 +417,7 @@
     // Find which slice finishes first.
     next_query_ = FindEarliestFinishQuery();
 
-    // If the current span is overlapping, just finish there to emit the current
+    // If the current span is overlapping, just finsh there to emit the current
     // slice.
     if (IsOverlappingSpan())
       break;
@@ -620,19 +529,11 @@
 
 util::Status SpanJoinOperatorTable::Query::Initialize(
     const QueryConstraints& qc,
-    sqlite3_value** argv,
-    InitialEofBehavior eof_behavior) {
+    sqlite3_value** argv) {
   *this = Query(table_, definition(), db_);
   sql_query_ = CreateSqlQuery(
       table_->ComputeSqlConstraintsForDefinition(*defn_, qc, argv));
-  util::Status status = Rewind();
-  if (!status.ok())
-    return status;
-  if (eof_behavior == InitialEofBehavior::kTreatAsMissingPartitionShadow &&
-      IsEof()) {
-    state_ = State::kMissingPartitionShadow;
-  }
-  return status;
+  return Rewind();
 }
 
 util::Status SpanJoinOperatorTable::Query::Next() {
diff --git a/src/trace_processor/sqlite/span_join_operator_table.h b/src/trace_processor/sqlite/span_join_operator_table.h
index ebfb867..290b3d9 100644
--- a/src/trace_processor/sqlite/span_join_operator_table.h
+++ b/src/trace_processor/sqlite/span_join_operator_table.h
@@ -70,8 +70,6 @@
 // are passed through unchanged.
 class SpanJoinOperatorTable : public SqliteTable {
  public:
-  static constexpr int kSourceGeqOpCode = SQLITE_INDEX_CONSTRAINT_FUNCTION + 1;
-
   // Enum indicating whether the queries on the two inner tables should
   // emit shadows.
   enum class EmitShadowType {
@@ -165,16 +163,8 @@
     Query(Query&&) noexcept = default;
     Query& operator=(Query&&) = default;
 
-    enum class InitialEofBehavior {
-      kTreatAsEof,
-      kTreatAsMissingPartitionShadow
-    };
-
     // Initializes the query with the given constraints and query parameters.
-    util::Status Initialize(
-        const QueryConstraints& qc,
-        sqlite3_value** argv,
-        InitialEofBehavior eof_behavior = InitialEofBehavior::kTreatAsEof);
+    util::Status Initialize(const QueryConstraints& qc, sqlite3_value** argv);
 
     // Forwards the query to the next valid slice.
     util::Status Next();
@@ -361,7 +351,6 @@
   util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
   std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) override;
-  int FindFunction(const char* name, FindFunctionFn* fn, void** args) override;
 
  private:
   // Columns of the span operator table.
diff --git a/src/trace_processor/sqlite/span_join_operator_table_unittest.cc b/src/trace_processor/sqlite/span_join_operator_table_unittest.cc
index 4c28397..87bb645 100644
--- a/src/trace_processor/sqlite/span_join_operator_table_unittest.cc
+++ b/src/trace_processor/sqlite/span_join_operator_table_unittest.cc
@@ -254,92 +254,6 @@
   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
 }
 
-TEST_F(SpanJoinOperatorTableTest, LeftJoinTwoSpanTables) {
-  RunStatement(
-      "CREATE TEMP TABLE f("
-      "ts BIG INT PRIMARY KEY, "
-      "dur BIG INT, "
-      "cpu UNSIGNED INT"
-      ");");
-  RunStatement(
-      "CREATE TEMP TABLE s("
-      "ts BIG INT PRIMARY KEY, "
-      "dur BIG INT, "
-      "tid UNSIGNED INT"
-      ");");
-  RunStatement("CREATE VIRTUAL TABLE sp USING span_left_join(f, s);");
-
-  RunStatement("INSERT INTO f VALUES(100, 10, 0);");
-  RunStatement("INSERT INTO f VALUES(110, 50, 1);");
-
-  RunStatement("INSERT INTO s VALUES(100, 5, 1);");
-  RunStatement("INSERT INTO s VALUES(110, 40, 2);");
-  RunStatement("INSERT INTO s VALUES(150, 50, 3);");
-
-  PrepareValidStatement("SELECT * FROM sp");
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 1);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 105);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
-  ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 40);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 2);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 150);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 3);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
-}
-
-TEST_F(SpanJoinOperatorTableTest, LeftJoinTwoSpanTables_EmptyRight) {
-  RunStatement(
-      "CREATE TEMP TABLE f("
-      "ts BIG INT PRIMARY KEY, "
-      "dur BIG INT, "
-      "cpu UNSIGNED INT"
-      ");");
-  RunStatement(
-      "CREATE TEMP TABLE s("
-      "ts BIG INT PRIMARY KEY, "
-      "dur BIG INT, "
-      "tid UNSIGNED INT"
-      ");");
-  RunStatement("CREATE VIRTUAL TABLE sp USING span_left_join(f, s);");
-
-  RunStatement("INSERT INTO f VALUES(100, 10, 0);");
-  RunStatement("INSERT INTO f VALUES(110, 50, 1);");
-
-  PrepareValidStatement("SELECT * FROM sp");
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
-  ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 50);
-  ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
-  ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
-
-  ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/sqlite/sql_stats_table.cc b/src/trace_processor/sqlite/sql_stats_table.cc
index 372dc1e..b9fb2db 100644
--- a/src/trace_processor/sqlite/sql_stats_table.cc
+++ b/src/trace_processor/sqlite/sql_stats_table.cc
@@ -56,7 +56,8 @@
   return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
 }
 
-int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
+int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
+  info->sqlite_omit_order_by = true;
   return SQLITE_OK;
 }
 
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.cc b/src/trace_processor/sqlite/sqlite_raw_table.cc
index b02abf4..e13c3af 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.cc
+++ b/src/trace_processor/sqlite/sqlite_raw_table.cc
@@ -24,18 +24,14 @@
 #include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
 #include "src/trace_processor/sqlite/sqlite_utils.h"
 #include "src/trace_processor/types/gfp_flags.h"
-#include "src/trace_processor/types/softirq_action.h"
 #include "src/trace_processor/types/task_state.h"
 #include "src/trace_processor/types/variadic.h"
 
 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
 #include "protos/perfetto/trace/ftrace/clk.pbzero.h"
-#include "protos/perfetto/trace/ftrace/dpu.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/g2d.pbzero.h"
-#include "protos/perfetto/trace/ftrace/irq.pbzero.h"
 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
@@ -65,19 +61,12 @@
 
  private:
   using ValueWriter = std::function<void(const Variadic&)>;
-  using SerializerValueWriter = void (ArgsSerializer::*)(const Variadic&);
 
   void WriteArgForField(uint32_t field_id) {
     WriteArgForField(field_id,
                      [this](const Variadic& v) { return WriteValue(v); });
   }
 
-  void WriteArgForField(uint32_t field_id, SerializerValueWriter writer) {
-    WriteArgForField(field_id, [this, writer](const Variadic& variadic) {
-      (this->*writer)(variadic);
-    });
-  }
-
   void WriteArgForField(uint32_t field_id, ValueWriter writer) {
     WriteArgAtRow(FieldIdToRow(field_id), writer);
   }
@@ -87,12 +76,6 @@
                        [this](const Variadic& v) { return WriteValue(v); });
   }
 
-  void WriteValueForField(uint32_t field_id, SerializerValueWriter writer) {
-    WriteValueForField(field_id, [this, writer](const Variadic& variadic) {
-      (this->*writer)(variadic);
-    });
-  }
-
   void WriteValueForField(uint32_t field_id, ValueWriter writer) {
     writer(storage_->GetArgValue(FieldIdToRow(field_id)));
   }
@@ -104,16 +87,6 @@
 
   void WriteArgAtRow(uint32_t arg_index, ValueWriter writer);
 
-  void WriteKernelFnValue(const Variadic& value) {
-    if (value.type == Variadic::Type::kUint) {
-      writer_->AppendHexInt(value.uint_value);
-    } else if (value.type == Variadic::Type::kString) {
-      WriteValue(value);
-    } else {
-      PERFETTO_DFATAL("Invalid field type %d", static_cast<int>(value.type));
-    }
-  }
-
   void WriteValue(const Variadic& variadic);
 
   uint32_t FieldIdToRow(uint32_t field_id) {
@@ -223,8 +196,10 @@
     return;
   } else if (event_name_ == "clock_set_rate") {
     using CSR = protos::pbzero::ClockSetRateFtraceEvent;
-    writer_->AppendLiteral(" ");
-    WriteValueForField(CSR::kNameFieldNumber);
+
+    // We use the string "todo" as the name to stay consistent with old
+    // trace_to_text print code.
+    writer_->AppendString(" todo");
     WriteArgForField(CSR::kStateFieldNumber);
     WriteArgForField(CSR::kCpuIdFieldNumber);
     return;
@@ -347,8 +322,10 @@
     using SBR = protos::pbzero::SchedBlockedReasonFtraceEvent;
     WriteArgForField(SBR::kPidFieldNumber);
     WriteArgForField(SBR::kIoWaitFieldNumber);
-    WriteArgForField(SBR::kCallerFieldNumber,
-                     &ArgsSerializer::WriteKernelFnValue);
+    WriteArgForField(SBR::kCallerFieldNumber, [this](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;
@@ -367,7 +344,10 @@
     });
     writer_->AppendString(": function ");
     WriteValueForField(WES::kFunctionFieldNumber,
-                       &ArgsSerializer::WriteKernelFnValue);
+                       [this](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;
@@ -384,8 +364,10 @@
       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
       writer_->AppendHexInt(value.uint_value);
     });
-    WriteArgForField(WQW::kFunctionFieldNumber,
-                     &ArgsSerializer::WriteKernelFnValue);
+    WriteArgForField(WQW::kFunctionFieldNumber, [this](const Variadic& value) {
+      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
+      writer_->AppendHexInt(value.uint_value);
+    });
     WriteArgForField(WQW::kWorkqueueFieldNumber, [this](const Variadic& value) {
       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
       writer_->AppendHexInt(value.uint_value);
@@ -393,67 +375,8 @@
     WriteValueForField(WQW::kReqCpuFieldNumber);
     WriteValueForField(WQW::kCpuFieldNumber);
     return;
-  } else if (event_name_ == "irq_handler_entry") {
-    using IEN = protos::pbzero::IrqHandlerEntryFtraceEvent;
-    WriteArgForField(IEN::kIrqFieldNumber);
-    WriteArgForField(IEN::kNameFieldNumber);
-    return;
-  } else if (event_name_ == "irq_handler_exit") {
-    using IEX = protos::pbzero::IrqHandlerExitFtraceEvent;
-    WriteArgForField(IEX::kIrqFieldNumber);
-    writer_->AppendString(" ret=");
-    WriteValueForField(IEX::kRetFieldNumber, [this](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer_->AppendString(value.uint_value ? "handled" : "unhandled");
-    });
-    return;
-  } else if (event_name_ == "softirq_entry") {
-    using SIE = protos::pbzero::SoftirqEntryFtraceEvent;
-    WriteArgForField(SIE::kVecFieldNumber);
-    writer_->AppendString(" [action=");
-    WriteValueForField(SIE::kVecFieldNumber, [this](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer_->AppendString(kActionNames[value.uint_value]);
-    });
-    writer_->AppendString("]");
-    return;
-  } else if (event_name_ == "softirq_exit") {
-    using SIX = protos::pbzero::SoftirqExitFtraceEvent;
-    WriteArgForField(SIX::kVecFieldNumber);
-    writer_->AppendString(" [action=");
-    WriteValueForField(SIX::kVecFieldNumber, [this](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer_->AppendString(kActionNames[value.uint_value]);
-    });
-    writer_->AppendString("]");
-    return;
-  } else if (event_name_ == "dpu_tracing_mark_write") {
-    using TMW = protos::pbzero::DpuTracingMarkWriteFtraceEvent;
-    WriteValueForField(TMW::kTypeFieldNumber, [this](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer_->AppendChar(static_cast<char>(value.uint_value));
-    });
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kPidFieldNumber);
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kNameFieldNumber);
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kValueFieldNumber);
-    return;
-  } else if (event_name_ == "g2d_tracing_mark_write") {
-    using TMW = protos::pbzero::G2dTracingMarkWriteFtraceEvent;
-    WriteValueForField(TMW::kTypeFieldNumber, [this](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer_->AppendChar(static_cast<char>(value.uint_value));
-    });
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kPidFieldNumber);
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kNameFieldNumber);
-    writer_->AppendString("|");
-    WriteValueForField(TMW::kValueFieldNumber);
-    return;
   }
+
   for (auto it = row_map_.IterateRows(); it; it.Next()) {
     WriteArgAtRow(it.row());
   }
@@ -563,8 +486,7 @@
   StringId event_name_id = raw.name()[raw_row];
   NullTermStringView event_name = storage_->GetString(event_name_id);
   writer.AppendChar(' ');
-  if (event_name == "print" || event_name == "g2d_tracing_mark_write" ||
-      event_name == "dpu_tracing_mark_write") {
+  if (event_name == "print") {
     writer.AppendString("tracing_mark_write");
   } else {
     writer.AppendString(event_name.c_str(), event_name.size());
@@ -599,8 +521,12 @@
   FtraceTime ftrace_time(ts);
   if (tid == 0) {
     name = "<idle>";
-  } else if (name.empty()) {
+  } 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());
diff --git a/src/trace_processor/sqlite/sqlite_raw_table.h b/src/trace_processor/sqlite/sqlite_raw_table.h
index 3722d9b..2e6d774 100644
--- a/src/trace_processor/sqlite/sqlite_raw_table.h
+++ b/src/trace_processor/sqlite/sqlite_raw_table.h
@@ -53,7 +53,7 @@
   };
 
   SqliteRawTable(sqlite3*, Context);
-  ~SqliteRawTable() override;
+  virtual ~SqliteRawTable();
 
   static void RegisterTable(sqlite3* db, QueryCache*, TraceProcessorContext*);
 
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index 2540a75..a2ed4c5 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -32,7 +32,7 @@
 std::string TypeToString(SqlValue::Type type) {
   switch (type) {
     case SqlValue::Type::kString:
-      return "TEXT";
+      return "STRING";
     case SqlValue::Type::kLong:
       return "BIG INT";
     case SqlValue::Type::kDouble:
@@ -140,7 +140,7 @@
   return SQLITE_OK;
 }
 
-int SqliteTable::FindFunction(const char*, FindFunctionFn*, void**) {
+int SqliteTable::FindFunction(const char*, FindFunctionFn, void**) {
   return 0;
 }
 
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index cfb7d43..99d9e29 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -325,9 +325,9 @@
   virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
 
   // Optional metods to implement.
-  using FindFunctionFn = void (*)(sqlite3_context*, int, sqlite3_value**);
+  using FindFunctionFn = void (**)(sqlite3_context*, int, sqlite3_value**);
   virtual int ModifyConstraints(QueryConstraints* qc);
-  virtual int FindFunction(const char* name, FindFunctionFn* fn, void** args);
+  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*);
diff --git a/src/trace_processor/sqlite/sqlite_utils.h b/src/trace_processor/sqlite/sqlite_utils.h
index 889ad95..8e97c03 100644
--- a/src/trace_processor/sqlite/sqlite_utils.h
+++ b/src/trace_processor/sqlite/sqlite_utils.h
@@ -26,7 +26,6 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "src/trace_processor/sqlite/scoped_db.h"
 #include "src/trace_processor/sqlite/sqlite_table.h"
 
@@ -68,6 +67,27 @@
   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;
 }
@@ -360,11 +380,25 @@
   sqlite3_result_double(ctx, value);
 }
 
-inline util::Status GetColumnsForTable(
+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,
-    std::vector<SqliteTable::Column>& columns) {
-  PERFETTO_DCHECK(columns.empty());
+    const std::string& raw_table_name) {
   char sql[1024];
   const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
 
@@ -376,18 +410,21 @@
   sqlite3_stmt* raw_stmt = nullptr;
   int err = sqlite3_prepare_v2(db, sql, n, &raw_stmt, nullptr);
   if (err != SQLITE_OK) {
-    return util::ErrStatus("Preparing database failed");
+    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) {
-      return util::ErrStatus("Querying schema of table %s failed",
-                             raw_table_name.c_str());
+      PERFETTO_ELOG("Querying schema of table %s failed",
+                    raw_table_name.c_str());
+      return {};
     }
 
     const char* name =
@@ -395,32 +432,31 @@
     const char* raw_type =
         reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
     if (!name || !raw_type || !*name) {
-      return util::ErrStatus("Schema for %s has invalid column values",
-                             raw_table_name.c_str());
+      PERFETTO_FATAL("Schema for %s has invalid column values",
+                     raw_table_name.c_str());
     }
 
     SqlValue::Type type;
-    if (base::CaseInsensitiveEqual(raw_type, "STRING") ||
-        base::CaseInsensitiveEqual(raw_type, "TEXT")) {
+    if (strcmp(raw_type, "STRING") == 0) {
       type = SqlValue::Type::kString;
-    } else if (base::CaseInsensitiveEqual(raw_type, "DOUBLE")) {
+    } else if (strcmp(raw_type, "DOUBLE") == 0) {
       type = SqlValue::Type::kDouble;
-    } else if (base::CaseInsensitiveEqual(raw_type, "BIG INT") ||
-               base::CaseInsensitiveEqual(raw_type, "UNSIGNED INT") ||
-               base::CaseInsensitiveEqual(raw_type, "INT") ||
-               base::CaseInsensitiveEqual(raw_type, "BOOLEAN")) {
+    } 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 {
-      return util::ErrStatus("Unknown column type '%s' on table %s", raw_type,
-                             raw_table_name.c_str());
+      PERFETTO_FATAL("Unknown column type '%s' on table %s", raw_type,
+                     raw_table_name.c_str());
     }
     columns.emplace_back(columns.size(), name, type);
   }
-  return util::OkStatus();
+  return columns;
 }
 
 template <typename T>
diff --git a/src/trace_processor/sqlite/sqlite_utils_unittest.cc b/src/trace_processor/sqlite/sqlite_utils_unittest.cc
deleted file mode 100644
index 1d1de13..0000000
--- a/src/trace_processor/sqlite/sqlite_utils_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class GetColumnsForTableTest : public ::testing::Test {
- public:
-  GetColumnsForTableTest() {
-    sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
-    PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
-    db_.reset(db);
-  }
-
-  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);
-  }
-
-  void RunStatement(const std::string& sql) {
-    PrepareValidStatement(sql);
-    ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
-  }
-
- protected:
-  ScopedDb db_;
-  ScopedStmt stmt_;
-};
-
-TEST_F(GetColumnsForTableTest, ValidInput) {
-  RunStatement("CREATE TABLE foo (name STRING, ts INT, dur INT);");
-  std::vector<SqliteTable::Column> columns;
-  auto status = sqlite_utils::GetColumnsForTable(*db_, "foo", columns);
-  ASSERT_TRUE(status.ok());
-}
-
-TEST_F(GetColumnsForTableTest, UnknownType) {
-  // Currently GetColumnsForTable does not work with tables containing types it
-  // doesn't recognise. This just ensures that the query fails rather than
-  // crashing.
-  RunStatement("CREATE TABLE foo (name NUM, ts INT, dur INT);");
-  std::vector<SqliteTable::Column> columns;
-  auto status = sqlite_utils::GetColumnsForTable(*db_, "foo", columns);
-  ASSERT_FALSE(status.ok());
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_vtable_benchmark.cc b/src/trace_processor/sqlite/sqlite_vtable_benchmark.cc
index 510f776..830d28a 100644
--- a/src/trace_processor/sqlite/sqlite_vtable_benchmark.cc
+++ b/src/trace_processor/sqlite/sqlite_vtable_benchmark.cc
@@ -194,8 +194,8 @@
     PERFETTO_CHECK(value != 42);
   }
 
-  state.counters["rows"] = Counter(static_cast<double>(batch_size),
-                                   Counter::kIsIterationInvariantRate);
+  state.counters["rows"] =
+      Counter(batch_size, Counter::kIsIterationInvariantRate);
 }
 
 BENCHMARK(BM_SqliteStepAndResult)->Apply(BenchmarkArgs);
diff --git a/src/trace_processor/sqlite/stats_table.cc b/src/trace_processor/sqlite/stats_table.cc
index e4b7787..de536a5 100644
--- a/src/trace_processor/sqlite/stats_table.cc
+++ b/src/trace_processor/sqlite/stats_table.cc
@@ -39,8 +39,6 @@
           SqliteTable::Column(Column::kSource, "source",
                               SqlValue::Type::kString),
           SqliteTable::Column(Column::kValue, "value", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kDescription, "description",
-                              SqlValue::Type::kString),
       },
       {Column::kName});
   return util::OkStatus();
@@ -107,9 +105,6 @@
         sqlite3_result_int64(ctx, storage_->stats()[key_].value);
       }
       break;
-    case Column::kDescription:
-      sqlite3_result_text(ctx, stats::kDescriptions[key_], -1, kSqliteStatic);
-      break;
     default:
       PERFETTO_FATAL("Unknown column %d", N);
       break;
diff --git a/src/trace_processor/sqlite/stats_table.h b/src/trace_processor/sqlite/stats_table.h
index 3213a2a..6ef8c20 100644
--- a/src/trace_processor/sqlite/stats_table.h
+++ b/src/trace_processor/sqlite/stats_table.h
@@ -32,7 +32,7 @@
 // - Generated at parsing time (e.g., clock events out-of-order).
 class StatsTable : public SqliteTable {
  public:
-  enum Column { kName = 0, kIndex, kSeverity, kSource, kValue, kDescription };
+  enum Column { kName = 0, kIndex, kSeverity, kSource, kValue };
   class Cursor : public SqliteTable::Cursor {
    public:
     Cursor(StatsTable*);
diff --git a/src/trace_processor/storage/BUILD.gn b/src/trace_processor/storage/BUILD.gn
index 844d228..47e1195 100644
--- a/src/trace_processor/storage/BUILD.gn
+++ b/src/trace_processor/storage/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (C) 2021 The Android Open Source Project
+# Copyright (C) 20 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/src/trace_processor/storage/metadata.h b/src/trace_processor/storage/metadata.h
index ba68793..dd8aa89 100644
--- a/src/trace_processor/storage/metadata.h
+++ b/src/trace_processor/storage/metadata.h
@@ -46,12 +46,8 @@
   F(system_release,                    KeyType::kSingle,  Variadic::kString), \
   F(system_machine,                    KeyType::kSingle,  Variadic::kString), \
   F(android_build_fingerprint,         KeyType::kSingle,  Variadic::kString), \
-  F(trace_size_bytes,                  KeyType::kSingle,  Variadic::kInt),    \
-  F(all_data_source_started_ns,        KeyType::kSingle,  Variadic::kInt),    \
-  F(tracing_started_ns,                KeyType::kSingle,  Variadic::kInt),    \
-  F(tracing_disabled_ns,               KeyType::kSingle,  Variadic::kInt),    \
-  F(trace_config_pbtxt,                KeyType::kSingle,  Variadic::kString), \
-  F(ui_state,                          KeyType::kSingle,  Variadic::kString)
+  F(trace_size_bytes,                  KeyType::kSingle,  Variadic::kInt), \
+  F(all_data_source_started_ns,        KeyType::kSingle,  Variadic::kInt)
 // clang-format on
 
 // Compile time list of metadata items.
@@ -62,9 +58,7 @@
 // clang-format
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
 
 #define PERFETTO_TP_META_TYPE_ENUM(varname, ...) varname
 enum class KeyType : size_t {
@@ -80,7 +74,7 @@
 // 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 KeyId : size_t {
+enum KeyIDs : size_t {
   PERFETTO_TP_METADATA(PERFETTO_TP_META_ENUM),
   kNumKeys
 };
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index bc44fef..09854e0 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -25,163 +25,130 @@
 
 // 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,  kInfo,     kTrace,    ""),   \
-  F(android_log_num_total,              kSingle,  kInfo,     kTrace,    ""),   \
-  F(counter_events_out_of_order,        kSingle,  kError,    kAnalysis, ""),   \
-  F(deobfuscate_location_parse_error,   kSingle,  kError,    kTrace,    ""),   \
-  F(frame_timeline_event_parser_errors, kSingle,  kInfo,     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,           \
+#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(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,     \
       "The kernel ftrace buffer cannot keep up with the rate of events "       \
       "produced. Indexed by CPU. This is likely a misconfiguration."),         \
-  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(gpu_render_stage_parser_errors,     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(rss_stat_unknown_thread_for_mm_id,  kSingle,  kInfo,     kAnalysis, ""),   \
-  F(sched_switch_out_of_order,          kSingle,  kError,    kAnalysis, ""),   \
-  F(slice_out_of_order,                 kSingle,  kError,    kAnalysis, ""),   \
-  F(flow_duplicate_id,                  kSingle,  kError,    kTrace,    ""),   \
-  F(flow_no_enclosing_slice,            kSingle,  kError,    kTrace,    ""),   \
-  F(flow_step_without_start,            kSingle,  kInfo,     kTrace,    ""),   \
-  F(flow_end_without_start,             kSingle,  kInfo,     kTrace,    ""),   \
-  F(flow_invalid_id,                    kSingle,  kError,    kTrace,    ""),   \
-  F(flow_without_direction,             kSingle,  kError,    kTrace,    ""),   \
-  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, 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, kDataLoss, 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, kDataLoss, 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(clock_sync_cache_miss,              kSingle,  kInfo,     kAnalysis, ""),   \
-  F(process_tracker_errors,             kSingle,  kError,    kAnalysis, ""),   \
-  F(json_tokenizer_failure,             kSingle,  kError,    kTrace,    ""),   \
-  F(json_parser_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, kError,    kTrace,    ""),   \
-  F(heapprofd_buffer_corrupted,         kIndexed, kError,    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(gpu_render_stage_parser_errors,           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(rss_stat_unknown_thread_for_mm_id,        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, 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_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(clock_sync_cache_miss,                    kSingle,  kInfo,     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, kError,    kTrace),    \
+  F(heap_graph_location_parse_error,          kSingle,  kError,    kTrace),    \
+  F(heapprofd_buffer_corrupted,               kIndexed, kError,    kTrace,     \
       "Shared memory buffer corrupted. This is a bug or memory corruption "    \
       "in the target. Indexed by target upid."),                               \
-  F(heapprofd_hit_guardrail,            kIndexed, kError,    kTrace,           \
+  F(heapprofd_hit_guardrail,                  kIndexed, kError,    kTrace,     \
       "HeapprofdConfig specified a CPU or Memory Guardrail that was hit. "     \
       "Indexed by target upid."),                                              \
-  F(heapprofd_buffer_overran,           kIndexed, kDataLoss, kTrace,           \
+  F(heapprofd_buffer_overran,                 kIndexed, kDataLoss, kTrace,     \
       "The shared memory buffer between the target and heapprofd overran. "    \
       "The profile was truncated early. Indexed by target upid."),             \
-  F(heapprofd_client_error,             kIndexed, kError,    kTrace,           \
-      "The heapprofd client ran into a problem and disconnected. "             \
-      "See profile_packet.proto  for error codes."),                           \
-  F(heapprofd_client_disconnected,      kIndexed, kInfo,     kTrace,    ""),   \
-  F(heapprofd_malformed_packet,         kIndexed, kError,    kTrace,    ""),   \
-  F(heapprofd_missing_packet,           kSingle,  kError,    kTrace,    ""),   \
-  F(heapprofd_rejected_concurrent,      kIndexed, kError,    kTrace,           \
+  F(heapprofd_client_disconnected,            kIndexed, kInfo,     kTrace),    \
+  F(heapprofd_malformed_packet,               kIndexed, kError,    kTrace),    \
+  F(heapprofd_missing_packet,                 kSingle,  kError,    kTrace),    \
+  F(heapprofd_rejected_concurrent,            kIndexed, kError,    kTrace,     \
       "The target was already profiled by another tracing session, so the "    \
-      "profile was not taken. Indexed by target upid."),                       \
-  F(heapprofd_non_finalized_profile,    kSingle,  kError,    kTrace,    ""),   \
-  F(heapprofd_sampling_interval_adjusted,                                      \
-      kIndexed, kInfo,    kTrace,                                              \
-      "By how many byes the interval for PID was increased "                   \
-      "by adaptive sampling."),                                                \
-  F(heapprofd_unwind_time_us,           kIndexed, kInfo,     kTrace,           \
-      "Time spent unwinding callstacks."),                                     \
-  F(heapprofd_unwind_samples,           kIndexed, kInfo,     kTrace,           \
-      "Number of samples unwound."),                                           \
-  F(heapprofd_client_spinlock_blocked,  kIndexed, kInfo,     kTrace,           \
-       "Time (us) the heapprofd client was blocked on the spinlock."),         \
-  F(heapprofd_last_profile_timestamp,   kIndexed, kInfo,     kTrace,           \
-       "The timestamp (in trace time) for the last dump for a process"),       \
-  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, ""),   \
-  F(empty_chrome_metadata,              kSingle,  kError,    kTrace,    ""),   \
-  F(perf_cpu_lost_records,              kIndexed, kDataLoss, kTrace,    ""),   \
-  F(ninja_parse_errors,                 kSingle,  kError,    kTrace,    ""),   \
-  F(perf_samples_skipped,               kSingle,  kInfo,     kTrace,    ""),   \
-  F(perf_samples_skipped_dataloss,      kSingle,  kDataLoss, kTrace,    ""),   \
-  F(memory_snapshot_parser_failure,     kSingle,  kError,    kAnalysis, ""),   \
-  F(thread_time_in_state_out_of_order,  kSingle,  kError,    kAnalysis, ""),   \
-  F(thread_time_in_state_unknown_cpu_freq,                                     \
-                                        kSingle,  kError,    kAnalysis, ""),   \
-  F(ftrace_packet_before_tracing_start, kSingle,  kInfo,     kAnalysis,        \
-      "An ftrace packet was seen before the tracing start timestamp from "     \
-      "the tracing service. This happens if the ftrace buffers were not "      \
-      "cleared properly. These packets are silently dropped by trace "         \
-      "processor."),                                                           \
-  F(perf_guardrail_stop_ts,             kIndexed, kDataLoss, kTrace,    "")
+      "profile was not taken. Indexed by target upid."),    \
+  F(heapprofd_non_finalized_profile,          kSingle,  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), \
+  F(empty_chrome_metadata,                    kSingle,  kError,    kTrace),    \
+  F(perf_cpu_lost_records,                    kIndexed, kDataLoss, kTrace),    \
+  F(ninja_parse_errors,                       kSingle,  kError,    kTrace),    \
+  F(perf_samples_skipped,                     kSingle,  kInfo,     kTrace),    \
+  F(perf_samples_skipped_dataloss,            kSingle,  kDataLoss, kTrace),    \
+  F(thread_time_in_state_out_of_order,        kSingle,  kError,    kAnalysis), \
+  F(thread_time_in_state_unknown_cpu_freq,    kSingle,  kError,    kAnalysis)
 // clang-format on
 
 enum Type {
@@ -208,9 +175,7 @@
 };
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
 
 // Declares an enum of literals (one for each stat). The enum values of each
 // literal corresponds to the string index in the arrays below.
@@ -232,10 +197,6 @@
 #define PERFETTO_TP_STATS_SOURCE(_, __, ___, source, ...) source
 constexpr Source kSources[] = {PERFETTO_TP_STATS(PERFETTO_TP_STATS_SOURCE)};
 
-#define PERFETTO_TP_STATS_DESCRIPTION(_, __, ___, ____, descr, ...) descr
-constexpr char const* kDescriptions[] = {
-    PERFETTO_TP_STATS(PERFETTO_TP_STATS_DESCRIPTION)};
-
 }  // namespace stats
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/storage/trace_storage.cc b/src/trace_processor/storage/trace_storage.cc
index 20fdd51..b66ce82 100644
--- a/src/trace_processor/storage/trace_storage.cc
+++ b/src/trace_processor/storage/trace_storage.cc
@@ -72,6 +72,18 @@
 }
 
 TraceStorage::TraceStorage(const Config&) {
+  // Reserve utid/upid 0. These are special as embedders (e.g. Perfetto UI)
+  // exclude them by filtering them out. If the parsed trace contains ftrace
+  // data, ProcessTracker::SetPidZeroIgnoredForIdleProcess will create a mapping
+  // to these rows for tid/pid 0.
+  tables::ThreadTable::Row thread_row;
+  thread_row.tid = 0;
+  thread_table_.Insert(thread_row);
+
+  tables::ProcessTable::Row process_row;
+  process_row.pid = 0;
+  process_table_.Insert(process_row);
+
   for (uint32_t i = 0; i < variadic_type_ids_.size(); ++i) {
     variadic_type_ids_[i] = InternString(Variadic::kTypeNames[i]);
   }
@@ -135,7 +147,6 @@
   DbTableMaybeUpdateMinMax(android_log_table_.ts(), &start_ns, &end_ns);
   DbTableMaybeUpdateMinMax(heap_graph_object_table_.graph_sample_ts(),
                            &start_ns, &end_ns);
-  DbTableMaybeUpdateMinMax(perf_sample_table_.ts(), &start_ns, &end_ns);
 
   if (start_ns == std::numeric_limits<int64_t>::max()) {
     return std::make_pair(0, 0);
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index e2af2ce..290de0d 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -32,14 +32,11 @@
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/containers/string_pool.h"
 #include "src/trace_processor/storage/metadata.h"
 #include "src/trace_processor/storage/stats.h"
 #include "src/trace_processor/tables/android_tables.h"
 #include "src/trace_processor/tables/counter_tables.h"
-#include "src/trace_processor/tables/flow_tables.h"
-#include "src/trace_processor/tables/memory_tables.h"
 #include "src/trace_processor/tables/metadata_tables.h"
 #include "src/trace_processor/tables/profiler_tables.h"
 #include "src/trace_processor/tables/slice_tables.h"
@@ -91,10 +88,6 @@
 
 using VulkanAllocId = tables::VulkanMemoryAllocationsTable::Id;
 
-using ProcessMemorySnapshotId = tables::ProcessMemorySnapshotTable::Id;
-
-using SnapshotNodeId = tables::MemorySnapshotNodeTable::Id;
-
 // 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 =
@@ -123,9 +116,70 @@
 
   virtual ~TraceStorage();
 
+  class ThreadSlices {
+   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;
+    }
+
+    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_;
+  };
+
   class VirtualTrackSlices {
    public:
-    inline uint32_t AddVirtualTrackSlice(SliceId slice_id,
+    inline uint32_t AddVirtualTrackSlice(uint32_t slice_id,
                                          int64_t thread_timestamp_ns,
                                          int64_t thread_duration_ns,
                                          int64_t thread_instruction_count,
@@ -142,7 +196,7 @@
       return static_cast<uint32_t>(slice_ids_.size());
     }
 
-    const std::deque<SliceId>& slice_ids() const { return slice_ids_; }
+    const std::deque<uint32_t>& slice_ids() const { return slice_ids_; }
     const std::deque<int64_t>& thread_timestamp_ns() const {
       return thread_timestamp_ns_;
     }
@@ -156,7 +210,7 @@
       return thread_instruction_deltas_;
     }
 
-    base::Optional<uint32_t> FindRowForSliceId(SliceId slice_id) const {
+    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) {
@@ -165,13 +219,10 @@
       return base::nullopt;
     }
 
-    void UpdateThreadDeltasForSliceId(SliceId slice_id,
+    void UpdateThreadDeltasForSliceId(uint32_t slice_id,
                                       int64_t end_thread_timestamp_ns,
                                       int64_t end_thread_instruction_count) {
-      auto opt_row = FindRowForSliceId(slice_id);
-      if (!opt_row)
-        return;
-      uint32_t row = *opt_row;
+      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];
@@ -180,7 +231,7 @@
     }
 
    private:
-    std::deque<SliceId> slice_ids_;
+    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_;
@@ -380,13 +431,6 @@
     return &gpu_counter_group_table_;
   }
 
-  const tables::PerfCounterTrackTable& perf_counter_track_table() const {
-    return perf_counter_track_table_;
-  }
-  tables::PerfCounterTrackTable* mutable_perf_counter_track_table() {
-    return &perf_counter_track_table_;
-  }
-
   const tables::SchedSliceTable& sched_slice_table() const {
     return sched_slice_table_;
   }
@@ -397,15 +441,8 @@
   const tables::SliceTable& slice_table() const { return slice_table_; }
   tables::SliceTable* mutable_slice_table() { return &slice_table_; }
 
-  const tables::FlowTable& flow_table() const { return flow_table_; }
-  tables::FlowTable* mutable_flow_table() { return &flow_table_; }
-
-  const tables::ThreadSliceTable& thread_slice_table() const {
-    return thread_slice_table_;
-  }
-  tables::ThreadSliceTable* mutable_thread_slice_table() {
-    return &thread_slice_table_;
-  }
+  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_;
@@ -442,13 +479,6 @@
   }
   tables::MetadataTable* mutable_metadata_table() { return &metadata_table_; }
 
-  const tables::ClockSnapshotTable& clock_snapshot_table() const {
-    return clock_snapshot_table_;
-  }
-  tables::ClockSnapshotTable* mutable_clock_snapshot_table() {
-    return &clock_snapshot_table_;
-  }
-
   const tables::ArgTable& arg_table() const { return arg_table_; }
   tables::ArgTable* mutable_arg_table() { return &arg_table_; }
 
@@ -505,13 +535,6 @@
     return &profiler_smaps_table_;
   }
 
-  const tables::StackSampleTable& stack_sample_table() const {
-    return stack_sample_table_;
-  }
-  tables::StackSampleTable* mutable_stack_sample_table() {
-    return &stack_sample_table_;
-  }
-
   const tables::CpuProfileStackSampleTable& cpu_profile_stack_sample_table()
       const {
     return cpu_profile_stack_sample_table_;
@@ -520,13 +543,6 @@
     return &cpu_profile_stack_sample_table_;
   }
 
-  const tables::PerfSampleTable& perf_sample_table() const {
-    return perf_sample_table_;
-  }
-  tables::PerfSampleTable* mutable_perf_sample_table() {
-    return &perf_sample_table_;
-  }
-
   const tables::SymbolTable& symbol_table() const { return symbol_table_; }
 
   tables::SymbolTable* mutable_symbol_table() { return &symbol_table_; }
@@ -577,55 +593,6 @@
     return &graphics_frame_slice_table_;
   }
 
-  const tables::MemorySnapshotTable& memory_snapshot_table() const {
-    return memory_snapshot_table_;
-  }
-  tables::MemorySnapshotTable* mutable_memory_snapshot_table() {
-    return &memory_snapshot_table_;
-  }
-
-  const tables::ProcessMemorySnapshotTable& process_memory_snapshot_table()
-      const {
-    return process_memory_snapshot_table_;
-  }
-  tables::ProcessMemorySnapshotTable* mutable_process_memory_snapshot_table() {
-    return &process_memory_snapshot_table_;
-  }
-
-  const tables::MemorySnapshotNodeTable& memory_snapshot_node_table() const {
-    return memory_snapshot_node_table_;
-  }
-  tables::MemorySnapshotNodeTable* mutable_memory_snapshot_node_table() {
-    return &memory_snapshot_node_table_;
-  }
-
-  const tables::MemorySnapshotEdgeTable& memory_snapshot_edge_table() const {
-    return memory_snapshot_edge_table_;
-  }
-  tables::MemorySnapshotEdgeTable* mutable_memory_snapshot_edge_table() {
-    return &memory_snapshot_edge_table_;
-  }
-
-  const tables::ExpectedFrameTimelineSliceTable&
-  expected_frame_timeline_slice_table() const {
-    return expected_frame_timeline_slice_table_;
-  }
-
-  tables::ExpectedFrameTimelineSliceTable*
-  mutable_expected_frame_timeline_slice_table() {
-    return &expected_frame_timeline_slice_table_;
-  }
-
-  const tables::ActualFrameTimelineSliceTable&
-  actual_frame_timeline_slice_table() const {
-    return actual_frame_timeline_slice_table_;
-  }
-
-  tables::ActualFrameTimelineSliceTable*
-  mutable_actual_frame_timeline_slice_table() {
-    return &actual_frame_timeline_slice_table_;
-  }
-
   const StringPool& string_pool() const { return string_pool_; }
   StringPool* mutable_string_pool() { return &string_pool_; }
 
@@ -636,23 +603,35 @@
   // Returns (0, 0) if the trace is empty.
   std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs() const;
 
-  util::Status ExtractArg(uint32_t arg_set_id,
-                          const char* key,
-                          base::Optional<Variadic>* result) {
-    const auto& args = arg_table();
-    RowMap filtered = args.FilterToRowMap(
-        {args.arg_set_id().eq(arg_set_id), args.key().eq(key)});
-    if (filtered.empty()) {
-      *result = base::nullopt;
-      return util::OkStatus();
-    }
-    if (filtered.size() > 1) {
-      return util::ErrStatus(
-          "EXTRACT_ARG: received multiple args matching arg set id and key");
-    }
-    uint32_t idx = filtered.Get(0);
-    *result = GetArgValue(idx);
-    return util::OkStatus();
+  // TODO(lalitm): remove this when we have a better home.
+  std::vector<MappingId> FindMappingRow(StringId name,
+                                        StringId build_id) const {
+    auto it = stack_profile_mapping_index_.find(std::make_pair(name, build_id));
+    if (it == stack_profile_mapping_index_.end())
+      return {};
+    return it->second;
+  }
+
+  // TODO(lalitm): remove this when we have a better home.
+  void InsertMappingId(StringId name, StringId build_id, MappingId row) {
+    auto pair = std::make_pair(name, build_id);
+    stack_profile_mapping_index_[pair].emplace_back(row);
+  }
+
+  // TODO(lalitm): remove this when we have a better home.
+  std::vector<FrameId> FindFrameIds(MappingId mapping_row,
+                                    uint64_t rel_pc) const {
+    auto it =
+        stack_profile_frame_index_.find(std::make_pair(mapping_row, rel_pc));
+    if (it == stack_profile_frame_index_.end())
+      return {};
+    return it->second;
+  }
+
+  // TODO(lalitm): remove this when we have a better home.
+  void InsertFrameRow(MappingId mapping_row, uint64_t rel_pc, FrameId row) {
+    auto pair = std::make_pair(mapping_row, rel_pc);
+    stack_profile_frame_index_[pair].emplace_back(row);
   }
 
   Variadic GetArgValue(uint32_t row) const {
@@ -715,6 +694,14 @@
   TraceStorage(TraceStorage&&) = delete;
   TraceStorage& operator=(TraceStorage&&) = delete;
 
+  // TODO(lalitm): remove this when we find a better home for this.
+  using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
+  std::map<MappingKey, std::vector<MappingId>> stack_profile_mapping_index_;
+
+  // TODO(lalitm): remove this when we find a better home for this.
+  using FrameKey = std::pair<MappingId, uint64_t /* rel_pc */>;
+  std::map<FrameKey, std::vector<FrameId>> stack_profile_frame_index_;
+
   // One entry for each unique string in the trace.
   StringPool string_pool_;
 
@@ -726,9 +713,6 @@
   // * descriptions of android packages
   tables::MetadataTable metadata_table_{&string_pool_, nullptr};
 
-  // Contains data from all the clock snapshots in the trace.
-  tables::ClockSnapshotTable clock_snapshot_table_{&string_pool_, nullptr};
-
   // Metadata for tracks.
   tables::TrackTable track_table_{&string_pool_, nullptr};
   tables::GpuTrackTable gpu_track_table_{&string_pool_, &track_table_};
@@ -750,8 +734,6 @@
   tables::GpuCounterTrackTable gpu_counter_track_table_{&string_pool_,
                                                         &counter_track_table_};
   tables::GpuCounterGroupTable gpu_counter_group_table_{&string_pool_, nullptr};
-  tables::PerfCounterTrackTable perf_counter_track_table_{
-      &string_pool_, &counter_track_table_};
 
   // Args for all other tables.
   tables::ArgTable arg_table_{&string_pool_, nullptr};
@@ -763,14 +745,11 @@
   // Slices coming from userspace events (e.g. Chromium TRACE_EVENT macros).
   tables::SliceTable slice_table_{&string_pool_, nullptr};
 
-  // Flow events from userspace events (e.g. Chromium TRACE_EVENT macros).
-  tables::FlowTable flow_table_{&string_pool_, nullptr};
-
   // Slices from CPU scheduling data.
   tables::SchedSliceTable sched_slice_table_{&string_pool_, nullptr};
 
   // Additional attributes for threads slices (sub-type of NestableSlices).
-  tables::ThreadSliceTable thread_slice_table_{&string_pool_, &slice_table_};
+  ThreadSlices thread_slices_;
 
   // Additional attributes for virtual track slices (sub-type of
   // NestableSlices).
@@ -809,12 +788,10 @@
                                                             nullptr};
   tables::StackProfileCallsiteTable stack_profile_callsite_table_{&string_pool_,
                                                                   nullptr};
-  tables::StackSampleTable stack_sample_table_{&string_pool_, nullptr};
   tables::HeapProfileAllocationTable heap_profile_allocation_table_{
       &string_pool_, nullptr};
   tables::CpuProfileStackSampleTable cpu_profile_stack_sample_table_{
-      &string_pool_, &stack_sample_table_};
-  tables::PerfSampleTable perf_sample_table_{&string_pool_, nullptr};
+      &string_pool_, nullptr};
   tables::PackageListTable package_list_table_{&string_pool_, nullptr};
   tables::ProfilerSmapsTable profiler_smaps_table_{&string_pool_, nullptr};
 
@@ -831,21 +808,6 @@
   tables::GraphicsFrameSliceTable graphics_frame_slice_table_{&string_pool_,
                                                               &slice_table_};
 
-  // Metadata for memory snapshot.
-  tables::MemorySnapshotTable memory_snapshot_table_{&string_pool_, nullptr};
-  tables::ProcessMemorySnapshotTable process_memory_snapshot_table_{
-      &string_pool_, nullptr};
-  tables::MemorySnapshotNodeTable memory_snapshot_node_table_{&string_pool_,
-                                                              nullptr};
-  tables::MemorySnapshotEdgeTable memory_snapshot_edge_table_{&string_pool_,
-                                                              nullptr};
-
-  // FrameTimeline tables
-  tables::ExpectedFrameTimelineSliceTable expected_frame_timeline_slice_table_{
-      &string_pool_, &slice_table_};
-  tables::ActualFrameTimelineSliceTable actual_frame_timeline_slice_table_{
-      &string_pool_, &slice_table_};
-
   // The below array allow us to map between enums and their string
   // representations.
   std::array<StringId, Variadic::kMaxType + 1> variadic_type_ids_;
@@ -854,8 +816,10 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
+namespace std {
+
 template <>
-struct std::hash<::perfetto::trace_processor::BaseId> {
+struct hash<::perfetto::trace_processor::BaseId> {
   using argument_type = ::perfetto::trace_processor::BaseId;
   using result_type = size_t;
 
@@ -865,21 +829,20 @@
 };
 
 template <>
-struct std::hash<::perfetto::trace_processor::TrackId>
-    : std::hash<::perfetto::trace_processor::BaseId> {};
+struct hash<::perfetto::trace_processor::TrackId>
+    : hash<::perfetto::trace_processor::BaseId> {};
 template <>
-struct std::hash<::perfetto::trace_processor::MappingId>
-    : std::hash<::perfetto::trace_processor::BaseId> {};
+struct hash<::perfetto::trace_processor::MappingId>
+    : hash<::perfetto::trace_processor::BaseId> {};
 template <>
-struct std::hash<::perfetto::trace_processor::CallsiteId>
-    : std::hash<::perfetto::trace_processor::BaseId> {};
+struct hash<::perfetto::trace_processor::CallsiteId>
+    : hash<::perfetto::trace_processor::BaseId> {};
 template <>
-struct std::hash<::perfetto::trace_processor::FrameId>
-    : std::hash<::perfetto::trace_processor::BaseId> {};
+struct hash<::perfetto::trace_processor::FrameId>
+    : hash<::perfetto::trace_processor::BaseId> {};
 
 template <>
-struct std::hash<
-    ::perfetto::trace_processor::tables::StackProfileFrameTable::Row> {
+struct hash<::perfetto::trace_processor::tables::StackProfileFrameTable::Row> {
   using argument_type =
       ::perfetto::trace_processor::tables::StackProfileFrameTable::Row;
   using result_type = size_t;
@@ -893,7 +856,7 @@
 };
 
 template <>
-struct std::hash<
+struct hash<
     ::perfetto::trace_processor::tables::StackProfileCallsiteTable::Row> {
   using argument_type =
       ::perfetto::trace_processor::tables::StackProfileCallsiteTable::Row;
@@ -908,7 +871,7 @@
 };
 
 template <>
-struct std::hash<
+struct hash<
     ::perfetto::trace_processor::tables::StackProfileMappingTable::Row> {
   using argument_type =
       ::perfetto::trace_processor::tables::StackProfileMappingTable::Row;
@@ -924,4 +887,6 @@
   }
 };
 
+}  // namespace std
+
 #endif  // SRC_TRACE_PROCESSOR_STORAGE_TRACE_STORAGE_H_
diff --git a/src/trace_processor/storage_minimal_smoke_test.cc b/src/trace_processor/storage_minimal_smoke_test.cc
index 650f1f2..dcf8aba 100644
--- a/src/trace_processor/storage_minimal_smoke_test.cc
+++ b/src/trace_processor/storage_minimal_smoke_test.cc
@@ -59,16 +59,11 @@
 
   JsonStringOutputWriter output_writer;
   json::ExportJson(storage_.get(), &output_writer);
-  Json::CharReaderBuilder b;
-  auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
-
+  Json::Reader reader;
   Json::Value result;
-  std::string& o = output_writer.buffer;
-  ASSERT_TRUE(reader->parse(o.data(), o.data() + o.length(), &result, nullptr));
+  reader.parse(output_writer.buffer, result);
 
-  // We should only see a single event (the mapping of the idle thread to have
-  // name "swapper").
-  ASSERT_EQ(result["traceEvents"].size(), 1u);
+  ASSERT_EQ(result["traceEvents"].size(), 0u);
 }
 
 TEST_F(StorageMinimalSmokeTest, SystraceReturnsError) {
@@ -84,7 +79,7 @@
 
 TEST_F(StorageMinimalSmokeTest, TrackEventsImported) {
   const size_t MAX_SIZE = 1 << 20;
-  auto f = fopen("test/data/track_event_typed_args.pb", "rb");
+  auto f = fopen("test/trace_processor/track_event_typed_args.pb", "rb");
   std::unique_ptr<uint8_t[]> buf(new uint8_t[MAX_SIZE]);
   auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, MAX_SIZE, f);
   util::Status status = storage_->Parse(std::move(buf), rsize);
@@ -93,16 +88,11 @@
 
   JsonStringOutputWriter output_writer;
   json::ExportJson(storage_.get(), &output_writer);
-  Json::CharReaderBuilder b;
-  auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
-
+  Json::Reader reader;
   Json::Value result;
-  std::string& o = output_writer.buffer;
-  ASSERT_TRUE(reader->parse(o.data(), o.data() + o.length(), &result, nullptr));
+  reader.parse(output_writer.buffer, result);
 
-  // We have an "extra" event from the mapping of the idle thread to have name
-  // "swapper".
-  ASSERT_EQ(result["traceEvents"].size(), 5u);
+  ASSERT_EQ(result["traceEvents"].size(), 4u);
 }
 
 }  // namespace
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 66f0cfa..7f6ac2b 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -18,10 +18,8 @@
   sources = [
     "android_tables.h",
     "counter_tables.h",
-    "flow_tables.h",
     "macros.h",
     "macros_internal.h",
-    "memory_tables.h",
     "metadata_tables.h",
     "profiler_tables.h",
     "slice_tables.h",
@@ -30,7 +28,7 @@
   ]
   deps = [
     "../../../gn:default_deps",
-    "../db",
+    "../db:lib",
   ]
 }
 
diff --git a/src/trace_processor/tables/flow_tables.h b/src/trace_processor/tables/flow_tables.h
deleted file mode 100644
index 6eeff36..0000000
--- a/src/trace_processor/tables/flow_tables.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_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-#include "src/trace_processor/tables/slice_tables.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// @param arg_set_id {@joinable args.arg_set_id}
-#define PERFETTO_TP_FLOW_DEF(NAME, PARENT, C) \
-  NAME(FlowTable, "flow")                     \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)           \
-  C(SliceTable::Id, slice_out)                \
-  C(SliceTable::Id, slice_in)                 \
-  C(uint32_t, arg_set_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_FLOW_DEF);
-
-}  // namespace tables
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index a7b8325..6710c69 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -140,9 +140,7 @@
 }  // namespace macros_internal
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
-#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC system_header
-#endif
 
 // Basic helper macros.
 #define PERFETTO_TP_NOOP(...)
@@ -225,15 +223,11 @@
 
 #define PERFETTO_TP_COLUMN_FLAG_CHOOSER(type, name, maybe_flags, fn, ...) fn
 
-// MSVC has slightly different rules about __VA_ARGS__ expansion. This makes it
-// behave similarly to GCC/Clang.
-// See https://stackoverflow.com/q/5134523/14028266 .
-#define PERFETTO_TP_EXPAND_VA_ARGS(x) x
-
-#define PERFETTO_TP_COLUMN_FLAG(...)                          \
-  PERFETTO_TP_EXPAND_VA_ARGS(PERFETTO_TP_COLUMN_FLAG_CHOOSER( \
-      __VA_ARGS__, PERFETTO_TP_COLUMN_FLAG_HAS_FLAG_COL,      \
-      PERFETTO_TP_COLUMN_FLAG_NO_FLAG_COL)(__VA_ARGS__))
+#define PERFETTO_TP_COLUMN_FLAG(...)                                    \
+  PERFETTO_TP_COLUMN_FLAG_CHOOSER(__VA_ARGS__,                          \
+                                  PERFETTO_TP_COLUMN_FLAG_HAS_FLAG_COL, \
+                                  PERFETTO_TP_COLUMN_FLAG_NO_FLAG_COL)  \
+  (__VA_ARGS__)
 
 // Creates the sparse vector with the given flags.
 #define PERFETTO_TP_TABLE_CONSTRUCTOR_SV(type, name, ...)               \
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
index c9dd4b4..b6b0269 100644
--- a/src/trace_processor/tables/macros_unittest.cc
+++ b/src/trace_processor/tables/macros_unittest.cc
@@ -67,9 +67,9 @@
 };
 
 TEST_F(TableMacrosUnittest, Name) {
-  ASSERT_STREQ(event_.table_name(), "event");
-  ASSERT_STREQ(slice_.table_name(), "slice");
-  ASSERT_STREQ(cpu_slice_.table_name(), "cpu_slice");
+  ASSERT_EQ(event_.table_name(), "event");
+  ASSERT_EQ(slice_.table_name(), "slice");
+  ASSERT_EQ(cpu_slice_.table_name(), "cpu_slice");
 }
 
 TEST_F(TableMacrosUnittest, InsertParent) {
@@ -326,7 +326,7 @@
   row.value = 99.9999;
   counter_.Insert(row);
 
-  row.value = static_cast<double>(std::numeric_limits<int64_t>::min());
+  row.value = std::numeric_limits<int64_t>::min();
   counter_.Insert(row);
 
   Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))});
diff --git a/src/trace_processor/tables/memory_tables.h b/src/trace_processor/tables/memory_tables.h
deleted file mode 100644
index 3758318..0000000
--- a/src/trace_processor/tables/memory_tables.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TABLES_MEMORY_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_MEMORY_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-#include "src/trace_processor/tables/track_tables.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// @tablegroup Memory Snapshots
-#define PERFETTO_TP_MEMORY_SNAPSHOT_DEF(NAME, PARENT, C) \
-  NAME(MemorySnapshotTable, "memory_snapshot")           \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                      \
-  C(int64_t, timestamp)                                  \
-  C(TrackTable::Id, track_id)                            \
-  C(StringPool::Id, detail_level)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_MEMORY_SNAPSHOT_DEF);
-
-// @tablegroup Memory Snapshots
-#define PERFETTO_TP_PROCESS_MEMORY_SNAPSHOT_DEF(NAME, PARENT, C) \
-  NAME(ProcessMemorySnapshotTable, "process_memory_snapshot")    \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                              \
-  C(MemorySnapshotTable::Id, snapshot_id)                        \
-  C(uint32_t, upid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_MEMORY_SNAPSHOT_DEF);
-
-// @tablegroup Memory Snapshots
-#define PERFETTO_TP_MEMORY_SNAPSHOT_NODE_DEF(NAME, PARENT, C)    \
-  NAME(MemorySnapshotNodeTable, "memory_snapshot_node")          \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                              \
-  C(ProcessMemorySnapshotTable::Id, process_snapshot_id)         \
-  C(base::Optional<MemorySnapshotNodeTable::Id>, parent_node_id) \
-  C(StringPool::Id, path)                                        \
-  C(int64_t, size)                                               \
-  C(int64_t, effective_size)                                     \
-  C(base::Optional<uint32_t>, arg_set_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_MEMORY_SNAPSHOT_NODE_DEF);
-
-// @tablegroup Memory Snapshots
-#define PERFETTO_TP_MEMORY_SNAPSHOT_EDGE_DEF(NAME, PARENT, C) \
-  NAME(MemorySnapshotEdgeTable, "memory_snapshot_edge")       \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                           \
-  C(MemorySnapshotNodeTable::Id, source_node_id)              \
-  C(MemorySnapshotNodeTable::Id, target_node_id)              \
-  C(uint32_t, importance)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_MEMORY_SNAPSHOT_EDGE_DEF);
-
-}  // namespace tables
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_MEMORY_TABLES_H_
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index 3f1bb90..3bde1ea 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -91,9 +91,7 @@
   C(base::Optional<int64_t>, end_ts)                   \
   C(base::Optional<uint32_t>, parent_upid)             \
   C(base::Optional<uint32_t>, uid)                     \
-  C(base::Optional<uint32_t>, android_appid)           \
-  C(base::Optional<StringPool::Id>, cmdline)           \
-  C(uint32_t, arg_set_id)
+  C(base::Optional<uint32_t>, android_appid)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_TABLE_DEF);
 
@@ -113,28 +111,6 @@
 
 PERFETTO_TP_TABLE(PERFETTO_TP_CPU_FREQ_TABLE_DEF);
 
-// Contains all the mapping between clock snapshots and trace time.
-//
-// NOTE: this table is not sorted by timestamp; this is why we omit the
-// sorted flag on the ts column.
-//
-// @param ts            timestamp of the snapshot in trace time.
-// @param clock_id      id of the clock (corresponds to the id in the trace).
-// @param clock_name    the name of the clock for builtin clocks or null
-//                      otherwise.
-// @param clock_value   timestamp of the snapshot in clock time.
-// @param snapshot_id   the index of this snapshot (only useful for debugging)
-#define PERFETTO_TP_CLOCK_SNAPSHOT_TABLE_DEF(NAME, PARENT, C) \
-  NAME(ClockSnapshotTable, "clock_snapshot")                  \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                           \
-  C(int64_t, ts)                                              \
-  C(int64_t, clock_id)                                        \
-  C(base::Optional<StringPool::Id>, clock_name)               \
-  C(int64_t, clock_value)                                     \
-  C(uint32_t, snapshot_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_CLOCK_SNAPSHOT_TABLE_DEF);
-
 }  // namespace tables
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index 419d852..4ce7ed9 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -33,19 +33,6 @@
 // @param size_kb Total size of the mapping.
 // @param private_dirty_kb KB of this mapping that are private dirty  RSS.
 // @param swap_kb KB of this mapping that are in swap.
-// @param file_name
-// @param file_name_iid
-// @param path_iid
-// @param start_address
-// @param module_timestamp
-// @param module_debugid
-// @param module_debug_path
-// @param protection_flags
-// @param private_clean_resident_kb
-// @param shared_dirty_resident_kb
-// @param shared_clean_resident_kb
-// @param locked_kb
-// @param proportional_resident_kb
 // @tablegroup Callstack profilers
 #define PERFETTO_TP_PROFILER_SMAPS_DEF(NAME, PARENT, C) \
   NAME(ProfilerSmapsTable, "profiler_smaps")            \
@@ -55,18 +42,7 @@
   C(StringPool::Id, path)                               \
   C(int64_t, size_kb)                                   \
   C(int64_t, private_dirty_kb)                          \
-  C(int64_t, swap_kb)                                   \
-  C(StringPool::Id, file_name)                          \
-  C(int64_t, start_address)                             \
-  C(int64_t, module_timestamp)                          \
-  C(StringPool::Id, module_debugid)                     \
-  C(StringPool::Id, module_debug_path)                  \
-  C(int64_t, protection_flags)                          \
-  C(int64_t, private_clean_resident_kb)                 \
-  C(int64_t, shared_dirty_resident_kb)                  \
-  C(int64_t, shared_clean_resident_kb)                  \
-  C(int64_t, locked_kb)                                 \
-  C(int64_t, proportional_resident_kb)
+  C(int64_t, swap_kb)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_PROFILER_SMAPS_DEF);
 
@@ -123,8 +99,7 @@
   C(StringPool::Id, name)                                    \
   C(StackProfileMappingTable::Id, mapping)                   \
   C(int64_t, rel_pc)                                         \
-  C(base::Optional<uint32_t>, symbol_set_id)                 \
-  C(base::Optional<StringPool::Id>, deobfuscated_name)
+  C(base::Optional<uint32_t>, symbol_set_id)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_STACK_PROFILE_FRAME_DEF);
 
@@ -143,67 +118,23 @@
 
 PERFETTO_TP_TABLE(PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF);
 
-// TODO(rsavitski): rethink what to do with the root table now that only chrome
-// callstacks use it.
-
-// Root table for timestamped stack samples.
-// @param ts timestamp of the sample.
-// @param callsite_id unwound callstack.
-// @tablegroup Callstack profilers
-#define PERFETTO_TP_STACK_SAMPLE_DEF(NAME, PARENT, C) \
-  NAME(StackSampleTable, "stack_sample")              \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                   \
-  C(int64_t, ts, Column::Flag::kSorted)               \
-  C(StackProfileCallsiteTable::Id, callsite_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_STACK_SAMPLE_DEF);
-
-// Samples from the Chromium stack sampler.
+// This is generated by traced_perf.
 // @param ts timestamp this sample was taken at.
 // @param utid thread that was active when the sample was taken.
 // @param callsite_id callstack in active thread at time of sample.
 // @tablegroup Callstack profilers
 #define PERFETTO_TP_CPU_PROFILE_STACK_SAMPLE_DEF(NAME, PARENT, C) \
   NAME(CpuProfileStackSampleTable, "cpu_profile_stack_sample")    \
-  PARENT(PERFETTO_TP_STACK_SAMPLE_DEF, C)                         \
+  PERFETTO_TP_ROOT_TABLE(PARENT, C)                               \
+  C(int64_t, ts, Column::Flag::kSorted)                           \
+  C(StackProfileCallsiteTable::Id, callsite_id)                   \
   C(uint32_t, utid)                                               \
   C(int32_t, process_priority)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_CPU_PROFILE_STACK_SAMPLE_DEF);
 
-// Samples from the traced_perf perf sampler.
-//
-// The table currently provides no means of discriminating between multiple data
-// sources producing samples within a single trace.
-// @param ts timestamp of the sample.
-// @param utid sampled thread. {@joinable thread.utid}.
-// @param cpu the core the sampled thread was running on.
-// @param cpu_mode execution state (userspace/kernelspace) of the sampled
-//        thread.
-// @param callsite_id if set, unwound callstack of the sampled thread.
-// @param unwind_error if set, indicates that the unwinding for this sample
-//        encountered an error. Such samples still reference the best-effort
-//        result via the callsite_id (with a synthetic error frame at the point
-//        where unwinding stopped).
-// @param perf_session_id distinguishes samples from different profiling
-//        streams (i.e. multiple data sources).
-//        {@joinable perf_counter_track.perf_session_id}
-// @tablegroup Callstack profilers
-#define PERFETTO_TP_PERF_SAMPLE_DEF(NAME, PARENT, C)            \
-  NAME(PerfSampleTable, "perf_sample")                          \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                             \
-  C(int64_t, ts, Column::Flag::kSorted)                         \
-  C(uint32_t, utid)                                             \
-  C(uint32_t, cpu)                                              \
-  C(StringPool::Id, cpu_mode)                                   \
-  C(base::Optional<StackProfileCallsiteTable::Id>, callsite_id) \
-  C(base::Optional<StringPool::Id>, unwind_error)               \
-  C(uint32_t, perf_session_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_PERF_SAMPLE_DEF);
-
-// Symbolization data for a frame. Rows with the same symbol_set_id describe
-// one callframe, with the most-inlined symbol having id == symbol_set_id.
+// Symbolization data for a frame. Rows with them same symbol_set_id describe
+// one frame, with the bottom-most inlined frame having id == symbol_set_id.
 //
 // For instance, if the function foo has an inlined call to the function bar,
 // which has an inlined call to baz, the stack_profile_symbol table would look
@@ -212,9 +143,9 @@
 // ```
 // |id|symbol_set_id|name         |source_file|line_number|
 // |--|-------------|-------------|-----------|-----------|
-// |1 |      1      |baz          |foo.cc     | 36        |
+// |1 |      1      |foo          |foo.cc     | 60        |
 // |2 |      1      |bar          |foo.cc     | 30        |
-// |3 |      1      |foo          |foo.cc     | 60        |
+// |3 |      1      |baz          |foo.cc     | 36        |
 // ```
 // @param name name of the function.
 // @param source_file name of the source file containing the function.
@@ -252,7 +183,6 @@
   PERFETTO_TP_ROOT_TABLE(PARENT, C)                              \
   C(int64_t, ts, Column::Flag::kSorted)                          \
   C(uint32_t, upid)                                              \
-  C(StringPool::Id, heap_name)                                   \
   C(StackProfileCallsiteTable::Id, callsite_id)                  \
   C(int64_t, count)                                              \
   C(int64_t, size)
@@ -290,20 +220,13 @@
 // @param deobfuscated_name if class name was obfuscated and deobfuscation map
 // for it provided, the deobfuscated name.
 // @param location the APK / Dex / JAR file the class is contained in.
-// @tablegroup ART Heap Graphs
-//
-// classloader_id should really be HeapGraphObject::id, but that would
-// create a loop, which is currently not possible.
-// TODO(lalitm): resolve this
-#define PERFETTO_TP_HEAP_GRAPH_CLASS_DEF(NAME, PARENT, C)   \
-  NAME(HeapGraphClassTable, "heap_graph_class")             \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                         \
-  C(StringPool::Id, name)                                   \
-  C(base::Optional<StringPool::Id>, deobfuscated_name)      \
-  C(base::Optional<StringPool::Id>, location)               \
-  C(base::Optional<HeapGraphClassTable::Id>, superclass_id) \
-  C(base::Optional<uint32_t>, classloader_id)               \
-  C(StringPool::Id, kind)
+// @tablegroup ART Heap Profiler
+#define PERFETTO_TP_HEAP_GRAPH_CLASS_DEF(NAME, PARENT, C) \
+  NAME(HeapGraphClassTable, "heap_graph_class")           \
+  PERFETTO_TP_ROOT_TABLE(PARENT, C)                       \
+  C(StringPool::Id, name)                                 \
+  C(base::Optional<StringPool::Id>, deobfuscated_name)    \
+  C(base::Optional<StringPool::Id>, location)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_CLASS_DEF);
 
@@ -320,7 +243,7 @@
 // false, this object is uncollected garbage.
 // @param type_id class this object is an instance of.
 // @param root_type if not NULL, this object is a GC root.
-// @tablegroup ART Heap Graphs
+// @tablegroup ART Heap Profiler
 #define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C)            \
   NAME(HeapGraphObjectTable, "heap_graph_object")                     \
   PERFETTO_TP_ROOT_TABLE(PARENT, C)                                   \
@@ -346,13 +269,13 @@
 // @param field_type_name the static type of the field. E.g. java.lang.String.
 // @param deobfuscated_field_name if field_name was obfuscated and a
 // deobfuscation mapping was provided for it, the deobfuscated name.
-// @tablegroup ART Heap Graphs
+// @tablegroup ART Heap Profiler
 #define PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF(NAME, PARENT, C) \
   NAME(HeapGraphReferenceTable, "heap_graph_reference")       \
   PERFETTO_TP_ROOT_TABLE(PARENT, C)                           \
   C(uint32_t, reference_set_id, Column::Flag::kSorted)        \
   C(HeapGraphObjectTable::Id, owner_id)                       \
-  C(base::Optional<HeapGraphObjectTable::Id>, owned_id)       \
+  C(HeapGraphObjectTable::Id, owned_id)                       \
   C(StringPool::Id, field_name)                               \
   C(StringPool::Id, field_type_name)                          \
   C(base::Optional<StringPool::Id>, deobfuscated_field_name)
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index 54272d8..c347dcb 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -71,21 +71,6 @@
 PERFETTO_TP_TABLE(PERFETTO_TP_SCHED_SLICE_TABLE_DEF);
 
 // @tablegroup Events
-// @param utid {@joinable thread.utid}
-#define PERFETTO_TP_THREAD_STATE_TABLE_DEF(NAME, PARENT, C) \
-  NAME(ThreadStateTable, "thread_state")                    \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                         \
-  C(int64_t, ts)                                            \
-  C(int64_t, dur)                                           \
-  C(base::Optional<uint32_t>, cpu)                          \
-  C(uint32_t, utid)                                         \
-  C(StringPool::Id, state)                                  \
-  C(base::Optional<uint32_t>, io_wait)                      \
-  C(base::Optional<StringPool::Id>, blocked_function)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_STATE_TABLE_DEF);
-
-// @tablegroup Events
 #define PERFETTO_TP_GPU_SLICES_DEF(NAME, PARENT, C) \
   NAME(GpuSliceTable, "gpu_slice")                  \
   PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C)            \
@@ -98,8 +83,7 @@
   C(StringPool::Id, command_buffer_name)            \
   C(base::Optional<uint32_t>, frame_id)             \
   C(base::Optional<uint32_t>, submission_id)        \
-  C(base::Optional<int64_t>, hw_queue_id)           \
-  C(StringPool::Id, render_subpasses)
+  C(base::Optional<uint32_t>, hw_queue_id)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_GPU_SLICES_DEF);
 
@@ -124,46 +108,6 @@
 
 PERFETTO_TP_TABLE(PERFETTO_TP_DESCRIBE_SLICE_TABLE);
 
-#define PERFETTO_TP_EXPECTED_FRAME_TIMELINE_SLICES_DEF(NAME, PARENT, C)  \
-  NAME(ExpectedFrameTimelineSliceTable, "expected_frame_timeline_slice") \
-  PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C)                                 \
-  C(int64_t, display_frame_token)                                        \
-  C(int64_t, surface_frame_token)                                        \
-  C(uint32_t, upid)                                                      \
-  C(StringPool::Id, layer_name)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_EXPECTED_FRAME_TIMELINE_SLICES_DEF);
-
-#define PERFETTO_TP_ACTUAL_FRAME_TIMELINE_SLICES_DEF(NAME, PARENT, C) \
-  NAME(ActualFrameTimelineSliceTable, "actual_frame_timeline_slice")  \
-  PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C)                              \
-  C(int64_t, display_frame_token)                                     \
-  C(int64_t, surface_frame_token)                                     \
-  C(uint32_t, upid)                                                   \
-  C(StringPool::Id, layer_name)                                       \
-  C(StringPool::Id, present_type)                                     \
-  C(int32_t, on_time_finish)                                          \
-  C(int32_t, gpu_composition)                                         \
-  C(StringPool::Id, jank_type)                                        \
-  C(StringPool::Id, prediction_type)                                  \
-  C(StringPool::Id, jank_tag)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ACTUAL_FRAME_TIMELINE_SLICES_DEF);
-
-// @param thread_instruction_count The value of the CPU instruction counter at
-// the start of the slice.
-// @param thread_instruction_delta The change in value from
-// @param thread_instruction_count to the end of the slice.
-#define PERFETTO_TP_THREAD_SLICE_DEF(NAME, PARENT, C)  \
-  NAME(ThreadSliceTable, "thread_slice")               \
-  PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C)               \
-  C(base::Optional<int64_t>, thread_ts)                \
-  C(base::Optional<int64_t>, thread_dur)               \
-  C(base::Optional<int64_t>, thread_instruction_count) \
-  C(base::Optional<int64_t>, thread_instruction_delta)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_SLICE_DEF);
-
 }  // namespace tables
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index 34206b9..859be5d 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -16,8 +16,6 @@
 
 #include "src/trace_processor/tables/android_tables.h"
 #include "src/trace_processor/tables/counter_tables.h"
-#include "src/trace_processor/tables/flow_tables.h"
-#include "src/trace_processor/tables/memory_tables.h"
 #include "src/trace_processor/tables/metadata_tables.h"
 #include "src/trace_processor/tables/profiler_tables.h"
 #include "src/trace_processor/tables/slice_tables.h"
@@ -45,15 +43,12 @@
 CpuFreqTable::~CpuFreqTable() = default;
 ThreadTable::~ThreadTable() = default;
 ProcessTable::~ProcessTable() = default;
-ClockSnapshotTable::~ClockSnapshotTable() = default;
 
 // profiler_tables.h
 StackProfileMappingTable::~StackProfileMappingTable() = default;
 StackProfileFrameTable::~StackProfileFrameTable() = default;
 StackProfileCallsiteTable::~StackProfileCallsiteTable() = default;
-StackSampleTable::~StackSampleTable() = default;
 CpuProfileStackSampleTable::~CpuProfileStackSampleTable() = default;
-PerfSampleTable::~PerfSampleTable() = default;
 SymbolTable::~SymbolTable() = default;
 HeapProfileAllocationTable::~HeapProfileAllocationTable() = default;
 ExperimentalFlamegraphNodesTable::~ExperimentalFlamegraphNodesTable() = default;
@@ -67,16 +62,11 @@
 
 // slice_tables.h
 SliceTable::~SliceTable() = default;
-FlowTable::~FlowTable() = default;
-ThreadSliceTable::~ThreadSliceTable() = default;
 InstantTable::~InstantTable() = default;
 SchedSliceTable::~SchedSliceTable() = default;
 GpuSliceTable::~GpuSliceTable() = default;
 GraphicsFrameSliceTable::~GraphicsFrameSliceTable() = default;
 DescribeSliceTable::~DescribeSliceTable() = default;
-ThreadStateTable::~ThreadStateTable() = default;
-ExpectedFrameTimelineSliceTable::~ExpectedFrameTimelineSliceTable() = default;
-ActualFrameTimelineSliceTable::~ActualFrameTimelineSliceTable() = default;
 
 // track_tables.h
 TrackTable::~TrackTable() = default;
@@ -90,14 +80,6 @@
 IrqCounterTrackTable::~IrqCounterTrackTable() = default;
 SoftirqCounterTrackTable::~SoftirqCounterTrackTable() = default;
 GpuCounterTrackTable::~GpuCounterTrackTable() = default;
-PerfCounterTrackTable::~PerfCounterTrackTable() = default;
-
-// memory_tables.h
-MemorySnapshotTable::~MemorySnapshotTable() = default;
-ProcessMemorySnapshotTable::~ProcessMemorySnapshotTable() = default;
-MemorySnapshotNodeTable::~MemorySnapshotNodeTable() = default;
-MemorySnapshotEdgeTable::~MemorySnapshotEdgeTable() = default;
-
 }  // namespace tables
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
index afcd708..f9012d8 100644
--- a/src/trace_processor/tables/track_tables.h
+++ b/src/trace_processor/tables/track_tables.h
@@ -116,23 +116,6 @@
 
 PERFETTO_TP_TABLE(PERFETTO_TP_GPU_COUNTER_TRACK_DEF);
 
-// Sampled counters' values for samples in the perf_sample table.
-//
-// @param perf_session_id id of a distict profiling stream.
-//        {@joinable perf_sample.perf_session_id}
-// @param cpu the core the sample was taken on.
-// @is_timebase if true, this counter was the sampling timebase for this
-//              perf_session_id.
-// @tablegroup Tracks
-#define PERFETTO_TP_PERF_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(PerfCounterTrackTable, "perf_counter_track")         \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                  \
-  C(uint32_t, perf_session_id)                              \
-  C(uint32_t, cpu)                                          \
-  C(uint32_t, is_timebase)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_PERF_COUNTER_TRACK_DEF);
-
 }  // namespace tables
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/timestamped_trace_piece.h b/src/trace_processor/timestamped_trace_piece.h
index f775443..74b484f 100644
--- a/src/trace_processor/timestamped_trace_piece.h
+++ b/src/trace_processor/timestamped_trace_piece.h
@@ -19,12 +19,12 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/fuchsia/fuchsia_record.h"
 #include "src/trace_processor/importers/json/json_utils.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
 #include "src/trace_processor/importers/systrace/systrace_line.h"
 #include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
 // GCC can't figure out the relationship between TimestampedTracePiece's type
@@ -55,25 +55,20 @@
 
 struct TracePacketData {
   TraceBlobView packet;
-  std::shared_ptr<PacketSequenceStateGeneration> sequence_state;
-};
 
-struct FtraceEventData {
-  TraceBlobView event;
-  std::shared_ptr<PacketSequenceStateGeneration> sequence_state;
+  PacketSequenceStateGeneration* sequence_state;
 };
 
 struct TrackEventData : public TracePacketData {
-  TrackEventData(TraceBlobView pv,
-                 std::shared_ptr<PacketSequenceStateGeneration> generation)
-      : TracePacketData{std::move(pv), std::move(generation)} {}
+  TrackEventData(TraceBlobView pv, PacketSequenceStateGeneration* generation)
+      : TracePacketData{std::move(pv), generation} {}
 
   static constexpr size_t kMaxNumExtraCounters = 8;
 
-  base::Optional<int64_t> thread_timestamp;
-  base::Optional<int64_t> thread_instruction_count;
-  double counter_value = 0;
-  std::array<double, kMaxNumExtraCounters> extra_counter_values = {};
+  int64_t thread_timestamp = 0;
+  int64_t thread_instruction_count = 0;
+  int64_t counter_value = 0;
+  std::array<int64_t, kMaxNumExtraCounters> extra_counter_values = {};
 };
 
 // A TimestampedTracePiece is (usually a reference to) a piece of a trace that
@@ -91,23 +86,24 @@
     kSystraceLine,
   };
 
-  TimestampedTracePiece(
-      int64_t ts,
-      uint64_t idx,
-      TraceBlobView tbv,
-      std::shared_ptr<PacketSequenceStateGeneration> sequence_state)
-      : packet_data{std::move(tbv), std::move(sequence_state)},
+  TimestampedTracePiece(int64_t ts,
+                        uint64_t idx,
+                        TraceBlobView tbv,
+                        PacketSequenceStateGeneration* sequence_state)
+      : packet_data{std::move(tbv), sequence_state},
         timestamp(ts),
         packet_idx(idx),
         type(Type::kTracePacket) {}
 
-  TimestampedTracePiece(int64_t ts, uint64_t idx, FtraceEventData fed)
-      : ftrace_event(std::move(fed)),
+  TimestampedTracePiece(int64_t ts, uint64_t idx, TraceBlobView tbv)
+      : ftrace_event(std::move(tbv)),
         timestamp(ts),
         packet_idx(idx),
         type(Type::kFtraceEvent) {}
 
-  TimestampedTracePiece(int64_t ts, uint64_t idx, std::string value)
+  TimestampedTracePiece(int64_t ts,
+                        uint64_t idx,
+                        std::unique_ptr<Json::Value> value)
       : json_value(std::move(value)),
         timestamp(ts),
         packet_idx(idx),
@@ -157,7 +153,7 @@
       case Type::kInvalid:
         break;
       case Type::kFtraceEvent:
-        new (&ftrace_event) FtraceEventData(std::move(ttp.ftrace_event));
+        new (&ftrace_event) TraceBlobView(std::move(ttp.ftrace_event));
         break;
       case Type::kTracePacket:
         new (&packet_data) TracePacketData(std::move(ttp.packet_data));
@@ -169,7 +165,8 @@
         new (&sched_waking) InlineSchedWaking(std::move(ttp.sched_waking));
         break;
       case Type::kJsonValue:
-        new (&json_value) std::string(std::move(ttp.json_value));
+        new (&json_value)
+            std::unique_ptr<Json::Value>(std::move(ttp.json_value));
         break;
       case Type::kFuchsiaRecord:
         new (&fuchsia_record)
@@ -211,13 +208,13 @@
       case Type::kInlineSchedWaking:
         break;
       case Type::kFtraceEvent:
-        ftrace_event.~FtraceEventData();
+        ftrace_event.~TraceBlobView();
         break;
       case Type::kTracePacket:
         packet_data.~TracePacketData();
         break;
       case Type::kJsonValue:
-        json_value.~basic_string();
+        json_value.~unique_ptr();
         break;
       case Type::kFuchsiaRecord:
         fuchsia_record.~unique_ptr();
@@ -246,11 +243,11 @@
 
   // Data for different types of TimestampedTracePiece.
   union {
-    FtraceEventData ftrace_event;
+    TraceBlobView ftrace_event;
     TracePacketData packet_data;
     InlineSchedSwitch sched_switch;
     InlineSchedWaking sched_waking;
-    std::string json_value;
+    std::unique_ptr<Json::Value> json_value;
     std::unique_ptr<FuchsiaRecord> fuchsia_record;
     std::unique_ptr<TrackEventData> track_event_data;
     std::unique_ptr<SystraceLine> systrace_line;
diff --git a/src/trace_processor/trace_blob_view.h b/src/trace_processor/trace_blob_view.h
new file mode 100644
index 0000000..7a7889b
--- /dev/null
+++ b/src/trace_processor/trace_blob_view.h
@@ -0,0 +1,148 @@
+/*
+ * 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_TRACE_BLOB_VIEW_H_
+#define SRC_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <memory>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// This class is an equivalent of std::string_view for trace binary data.
+// The main difference is that this class has also shared ownership of a portion
+// of the raw trace.
+// The underlying buffer will be freed once all the TraceBlobViews that refer
+// to the same buffer have passed through the pipeline and been parsed.
+class TraceBlobView {
+ public:
+  TraceBlobView(std::unique_ptr<uint8_t[]> buffer, size_t offset, size_t length)
+      : shbuf_(SharedBuf(std::move(buffer))),
+        offset_(static_cast<uint32_t>(offset)),
+        length_(static_cast<uint32_t>(length)) {
+    PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max());
+    PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max());
+  }
+
+  // Allow std::move().
+  TraceBlobView(TraceBlobView&&) noexcept = default;
+  TraceBlobView& operator=(TraceBlobView&&) = default;
+
+  // Disable implicit copy.
+  TraceBlobView(const TraceBlobView&) = delete;
+  TraceBlobView& operator=(const TraceBlobView&) = delete;
+
+  TraceBlobView slice(size_t offset, size_t length) const {
+    PERFETTO_DCHECK(offset + length <= offset_ + length_);
+    return TraceBlobView(shbuf_, offset, length);
+  }
+
+  bool operator==(const TraceBlobView& rhs) const {
+    return (shbuf_ == rhs.shbuf_) && (offset_ == rhs.offset_) &&
+           (length_ == rhs.length_);
+  }
+  bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); }
+
+  inline const uint8_t* data() const { return start() + offset_; }
+
+  size_t offset_of(const uint8_t* data) const {
+    // When a field is size 0, data can be equal to start() + offset_ + length_.
+    PERFETTO_DCHECK(data >= start() && data <= (start() + offset_ + length_));
+    return static_cast<size_t>(data - start());
+  }
+
+  size_t length() const { return length_; }
+  size_t offset() const { return offset_; }
+
+ private:
+  // An equivalent to std::shared_ptr<uint8_t>, with the differnce that:
+  // - Supports array types, available for shared_ptr only in C++17.
+  // - Is not thread safe, which is not needed for our purposes.
+  class SharedBuf {
+   public:
+    explicit SharedBuf(std::unique_ptr<uint8_t[]> mem) {
+      rcbuf_ = new RefCountedBuf(std::move(mem));
+    }
+
+    SharedBuf(const SharedBuf& copy) : rcbuf_(copy.rcbuf_) {
+      PERFETTO_DCHECK(rcbuf_->refcount > 0);
+      rcbuf_->refcount++;
+    }
+
+    ~SharedBuf() {
+      if (!rcbuf_)
+        return;
+      PERFETTO_DCHECK(rcbuf_->refcount > 0);
+      if (--rcbuf_->refcount == 0) {
+        RefCountedBuf* rcbuf = rcbuf_;
+        rcbuf_ = nullptr;
+        delete rcbuf;
+      }
+    }
+
+    SharedBuf(SharedBuf&& other) noexcept {
+      rcbuf_ = other.rcbuf_;
+      other.rcbuf_ = nullptr;
+    }
+
+    SharedBuf& operator=(SharedBuf&& other) {
+      if (this != &other) {
+        // A bit of a ugly but pragmatic pattern to implement move assignment.
+        // First invoke the distructor and then invoke the move constructor
+        // inline via placement-new.
+        this->~SharedBuf();
+        new (this) SharedBuf(std::move(other));
+      }
+      return *this;
+    }
+
+    bool operator==(const SharedBuf& x) const { return x.rcbuf_ == rcbuf_; }
+    bool operator!=(const SharedBuf& x) const { return !(x == *this); }
+    const uint8_t* data() const { return rcbuf_->mem.get(); }
+
+   private:
+    struct RefCountedBuf {
+      explicit RefCountedBuf(std::unique_ptr<uint8_t[]> buf)
+          : refcount(1), mem(std::move(buf)) {}
+      int refcount;
+      std::unique_ptr<uint8_t[]> mem;
+    };
+
+    RefCountedBuf* rcbuf_ = nullptr;
+  };
+
+  inline const uint8_t* start() const { return shbuf_.data(); }
+
+  TraceBlobView(SharedBuf b, size_t o, size_t l)
+      : shbuf_(b),
+        offset_(static_cast<uint32_t>(o)),
+        length_(static_cast<uint32_t>(l)) {}
+
+  SharedBuf shbuf_;
+  uint32_t offset_;
+  uint32_t length_;  // Measured from |offset_|, not from |data()|.
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index e963b54..0255ed5 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -20,12 +20,8 @@
 #include <string>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "protos/perfetto/common/descriptor.pbzero.h"
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-
 #include "src/base/test/utils.h"
 #include "test/gtest_and_gmock.h"
 
@@ -59,12 +55,10 @@
     return util::OkStatus();
   }
 
-  Iterator Query(const std::string& query) {
+  TraceProcessor::Iterator Query(const std::string& query) {
     return processor_->ExecuteQuery(query.c_str());
   }
 
-  TraceProcessor* Processor() { return processor_.get(); }
-
   size_t RestoreInitialTables() { return processor_->RestoreInitialTables(); }
 
  private:
@@ -176,38 +170,6 @@
   ASSERT_FALSE(it.Next());
 }
 
-TEST_F(TraceProcessorIntegrationTest, SerializeMetricDescriptors) {
-  std::vector<uint8_t> desc_set_bytes = Processor()->GetMetricDescriptors();
-  protos::pbzero::DescriptorSet::Decoder desc_set(desc_set_bytes.data(),
-                                                  desc_set_bytes.size());
-
-  ASSERT_TRUE(desc_set.has_descriptors());
-  int trace_metrics_count = 0;
-  for (auto desc = desc_set.descriptors(); desc; ++desc) {
-    protos::pbzero::DescriptorProto::Decoder proto_desc(*desc);
-    if (proto_desc.name().ToStdString() == ".perfetto.protos.TraceMetrics") {
-      ASSERT_TRUE(proto_desc.has_field());
-      trace_metrics_count++;
-    }
-  }
-
-  // There should be exactly one definition of TraceMetrics. This can be not
-  // true if we're not deduping descriptors properly.
-  ASSERT_EQ(trace_metrics_count, 1);
-}
-
-TEST_F(TraceProcessorIntegrationTest, ComputeMetricsFormatted) {
-  std::string metric_output;
-  util::Status status = Processor()->ComputeMetricText(
-      std::vector<std::string>{"test_chrome_metric"},
-      TraceProcessor::MetricResultFormat::kProtoText, &metric_output);
-  ASSERT_TRUE(status.ok());
-  ASSERT_EQ(metric_output,
-            "test_chrome_metric: {\n"
-            "  test_value: 1\n"
-            "}");
-}
-
 // TODO(hjd): Add trace to test_data.
 TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
   ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")).ok());
@@ -252,10 +214,9 @@
 }
 
 TEST_F(TraceProcessorIntegrationTest, Clusterfuzz17805) {
-  // This trace is garbage but is detected as a systrace. However, it should
-  // still parse successfully as we try to be graceful with encountering random
-  // data in systrace as they can have arbitrary print events from the kernel.
-  ASSERT_TRUE(LoadTrace("clusterfuzz_17805", 4096).ok());
+  // This trace fails to load as it's detected as a systrace but is full of
+  // garbage data.
+  ASSERT_TRUE(!LoadTrace("clusterfuzz_17805", 4096).ok());
 }
 
 // Failing on DCHECKs during import because the traces aren't really valid.
@@ -265,16 +226,12 @@
 #define MAYBE_Clusterfuzz21178 DISABLED_Clusterfuzz21178
 #define MAYBE_Clusterfuzz21890 DISABLED_Clusterfuzz21890
 #define MAYBE_Clusterfuzz23053 DISABLED_Clusterfuzz23053
-#define MAYBE_Clusterfuzz28338 DISABLED_Clusterfuzz28338
-#define MAYBE_Clusterfuzz28766 DISABLED_Clusterfuzz28766
 #else  // PERFETTO_DCHECK_IS_ON()
 #define MAYBE_Clusterfuzz20215 Clusterfuzz20215
 #define MAYBE_Clusterfuzz20292 Clusterfuzz20292
 #define MAYBE_Clusterfuzz21178 Clusterfuzz21178
 #define MAYBE_Clusterfuzz21890 Clusterfuzz21890
 #define MAYBE_Clusterfuzz23053 Clusterfuzz23053
-#define MAYBE_Clusterfuzz28338 Clusterfuzz28338
-#define MAYBE_Clusterfuzz28766 Clusterfuzz28766
 #endif  // PERFETTO_DCHECK_IS_ON()
 
 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20215) {
@@ -282,7 +239,7 @@
 }
 
 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz20292) {
-  ASSERT_FALSE(LoadTrace("clusterfuzz_20292", 4096).ok());
+  ASSERT_TRUE(LoadTrace("clusterfuzz_20292", 4096).ok());
 }
 
 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21178) {
@@ -290,19 +247,11 @@
 }
 
 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz21890) {
-  ASSERT_FALSE(LoadTrace("clusterfuzz_21890", 4096).ok());
+  ASSERT_TRUE(LoadTrace("clusterfuzz_21890", 4096).ok());
 }
 
 TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz23053) {
-  ASSERT_FALSE(LoadTrace("clusterfuzz_23053", 4096).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28338) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_28338", 4096).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, MAYBE_Clusterfuzz28766) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_28766", 4096).ok());
+  ASSERT_TRUE(LoadTrace("clusterfuzz_23053", 4096).ok());
 }
 
 TEST_F(TraceProcessorIntegrationTest, RestoreInitialTables) {
diff --git a/src/trace_processor/trace_parser.h b/src/trace_processor/trace_parser.h
new file mode 100644
index 0000000..fa3b4ef
--- /dev/null
+++ b/src/trace_processor/trace_parser.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 SRC_TRACE_PROCESSOR_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_TRACE_PARSER_H_
+
+#include <stdint.h>
+
+#include "src/trace_processor/timestamped_trace_piece.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceParser {
+ public:
+  virtual ~TraceParser();
+
+  virtual void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) = 0;
+  virtual void ParseFtracePacket(uint32_t cpu,
+                                 int64_t timestamp,
+                                 TimestampedTracePiece) = 0;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_TRACE_PARSER_H_
diff --git a/src/trace_processor/trace_processor.cc b/src/trace_processor/trace_processor.cc
index 72b0b1d..9be89e5 100644
--- a/src/trace_processor/trace_processor.cc
+++ b/src/trace_processor/trace_processor.cc
@@ -30,6 +30,35 @@
 
 TraceProcessor::~TraceProcessor() = default;
 
+TraceProcessor::Iterator::Iterator(std::unique_ptr<IteratorImpl> iterator)
+    : iterator_(std::move(iterator)) {}
+TraceProcessor::Iterator::~Iterator() = default;
+
+TraceProcessor::Iterator::Iterator(TraceProcessor::Iterator&&) noexcept =
+    default;
+TraceProcessor::Iterator& TraceProcessor::Iterator::operator=(
+    TraceProcessor::Iterator&&) = default;
+
+bool TraceProcessor::Iterator::Next() {
+  return iterator_->Next();
+}
+
+SqlValue TraceProcessor::Iterator::Get(uint32_t col) {
+  return iterator_->Get(col);
+}
+
+std::string TraceProcessor::Iterator::GetColumnName(uint32_t col) {
+  return iterator_->GetColumnName(col);
+}
+
+uint32_t TraceProcessor::Iterator::ColumnCount() {
+  return iterator_->ColumnCount();
+}
+
+util::Status TraceProcessor::Iterator::Status() {
+  return iterator_->Status();
+}
+
 // static
 void EnableSQLiteVtableDebugging() {
   // This level of indirection is required to avoid clients to depend on table.h
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 412b63a..337a4d6 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -16,18 +16,16 @@
 
 #include "src/trace_processor/types/trace_processor_context.h"
 
+#include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/global_args_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
 #include "src/trace_processor/importers/proto/heap_profile_tracker.h"
 #include "src/trace_processor/importers/proto/metadata_tracker.h"
 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 0ca05ea..a7faa22 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -23,16 +23,10 @@
 #include "perfetto/base/time.h"
 #include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/dynamic/ancestor_generator.h"
-#include "src/trace_processor/dynamic/connected_flow_generator.h"
-#include "src/trace_processor/dynamic/descendant_slice_generator.h"
 #include "src/trace_processor/dynamic/describe_slice_generator.h"
-#include "src/trace_processor/dynamic/experimental_annotated_stack_generator.h"
 #include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
 #include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
-#include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
 #include "src/trace_processor/dynamic/experimental_slice_layout_generator.h"
-#include "src/trace_processor/dynamic/thread_state_generator.h"
 #include "src/trace_processor/export_json.h"
 #include "src/trace_processor/importers/additional_modules.h"
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
@@ -43,7 +37,6 @@
 #include "src/trace_processor/importers/json/json_trace_tokenizer.h"
 #include "src/trace_processor/importers/proto/metadata_tracker.h"
 #include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
-#include "src/trace_processor/iterator_impl.h"
 #include "src/trace_processor/sqlite/span_join_operator_table.h"
 #include "src/trace_processor/sqlite/sql_stats_table.h"
 #include "src/trace_processor/sqlite/sqlite3_str_split.h"
@@ -54,13 +47,11 @@
 #include "src/trace_processor/sqlite/window_operator_table.h"
 #include "src/trace_processor/tp_metatrace.h"
 #include "src/trace_processor/types/variadic.h"
-#include "src/trace_processor/util/protozero_to_text.h"
 
 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
-#include "src/trace_processor/metrics/chrome/all_chrome_metrics.descriptor.h"
 #include "src/trace_processor/metrics/metrics.descriptor.h"
 #include "src/trace_processor/metrics/metrics.h"
 #include "src/trace_processor/metrics/sql_metrics.h"
@@ -139,33 +130,6 @@
     PERFETTO_ELOG("Error initializing: %s", error);
     sqlite3_free(error);
   }
-  // Ensure that the entries in power_profile are unique to prevent duplicates
-  // when the power_profile is augmented with additional profiles.
-  sqlite3_exec(db,
-               "CREATE TABLE power_profile("
-               "device STRING, cpu INT, cluster INT, freq INT, power DOUBLE,"
-               "UNIQUE(device, cpu, cluster, freq));",
-               0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
-  sqlite3_exec(db, "CREATE TABLE trace_metrics(name STRING)", 0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
-  // This is a table intended to be used for metric debugging/developing. Data
-  // in the table is shown specially in the UI, and users can insert rows into
-  // this table to draw more things.
-  sqlite3_exec(db,
-               "CREATE TABLE debug_slices (id BIG INT, name STRING, ts BIG INT,"
-               "dur BIG INT, depth BIG INT)",
-               0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
 
   // Initialize the bounds table with some data so even before parsing any data,
   // we still have a valid table.
@@ -351,10 +315,6 @@
     return;
   }
   sqlite3_value* value = argv[0];
-  if (sqlite3_value_type(value) == SQLITE_NULL) {
-    sqlite3_result_null(ctx);
-    return;
-  }
   if (sqlite3_value_type(value) != SQLITE_TEXT) {
     sqlite3_result_error(ctx, "Unsupported type of arg passed to DEMANGLE", -1);
     return;
@@ -450,104 +410,11 @@
   }
 }
 
-struct ValueAtMaxTsContext {
-  bool initialized;
-  int value_type;
-
-  int64_t max_ts;
-  int64_t int_value_at_max_ts;
-  double double_value_at_max_ts;
-};
-
-void ValueAtMaxTsStep(sqlite3_context* ctx, int, sqlite3_value** argv) {
-  sqlite3_value* ts = argv[0];
-  sqlite3_value* value = argv[1];
-
-  // Note that sqlite3_aggregate_context zeros the memory for us so all the
-  // variables of the struct should be zero.
-  ValueAtMaxTsContext* fn_ctx = reinterpret_cast<ValueAtMaxTsContext*>(
-      sqlite3_aggregate_context(ctx, sizeof(ValueAtMaxTsContext)));
-
-  // For performance reasons, we only do the check for the type of ts and value
-  // on the first call of the function.
-  if (PERFETTO_UNLIKELY(!fn_ctx->initialized)) {
-    if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
-      sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: ts passed was not an integer",
-                           -1);
-      return;
-    }
-
-    fn_ctx->value_type = sqlite3_value_type(value);
-    if (fn_ctx->value_type != SQLITE_INTEGER &&
-        fn_ctx->value_type != SQLITE_FLOAT) {
-      sqlite3_result_error(
-          ctx, "VALUE_AT_MAX_TS: value passed was not an integer or float", -1);
-      return;
-    }
-
-    fn_ctx->initialized = true;
-  }
-
-  // On dcheck builds however, we check every passed ts and value.
-#if PERFETTO_DCHECK_IS_ON()
-  if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
-    sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: ts passed was not an integer",
-                         -1);
-    return;
-  }
-  if (sqlite3_value_type(value) != fn_ctx->value_type) {
-    sqlite3_result_error(ctx, "VALUE_AT_MAX_TS: value type is inconsistent",
-                         -1);
-    return;
-  }
-#endif
-
-  int64_t ts_int = sqlite3_value_int64(ts);
-  if (PERFETTO_LIKELY(fn_ctx->max_ts < ts_int)) {
-    fn_ctx->max_ts = ts_int;
-
-    if (fn_ctx->value_type == SQLITE_INTEGER) {
-      fn_ctx->int_value_at_max_ts = sqlite3_value_int64(value);
-    } else {
-      fn_ctx->double_value_at_max_ts = sqlite3_value_double(value);
-    }
-  }
-}
-
-void ValueAtMaxTsFinal(sqlite3_context* ctx) {
-  ValueAtMaxTsContext* fn_ctx =
-      reinterpret_cast<ValueAtMaxTsContext*>(sqlite3_aggregate_context(ctx, 0));
-  if (!fn_ctx) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-  if (fn_ctx->value_type == SQLITE_INTEGER) {
-    sqlite3_result_int64(ctx, fn_ctx->int_value_at_max_ts);
-  } else {
-    sqlite3_result_double(ctx, fn_ctx->double_value_at_max_ts);
-  }
-}
-
-void CreateValueAtMaxTsFunction(sqlite3* db) {
-  auto ret = sqlite3_create_function_v2(
-      db, "VALUE_AT_MAX_TS", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
-      nullptr, &ValueAtMaxTsStep, &ValueAtMaxTsFinal, nullptr);
-  if (ret) {
-    PERFETTO_ELOG("Error initializing VALUE_AT_MAX_TS");
-  }
-}
-
 void ExtractArg(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
   if (argc != 2) {
     sqlite3_result_error(ctx, "EXTRACT_ARG: 2 args required", -1);
     return;
   }
-
-  // If the arg set id is null, just return null as the result.
-  if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
-    sqlite3_result_null(ctx);
-    return;
-  }
   if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
     sqlite3_result_error(ctx, "EXTRACT_ARG: 1st argument should be arg set id",
                          -1);
@@ -562,41 +429,35 @@
   uint32_t arg_set_id = static_cast<uint32_t>(sqlite3_value_int(argv[0]));
   const char* key = reinterpret_cast<const char*>(sqlite3_value_text(argv[1]));
 
-  base::Optional<Variadic> opt_value;
-  util::Status status = storage->ExtractArg(arg_set_id, key, &opt_value);
-  if (!status.ok()) {
-    sqlite3_result_error(ctx, status.c_message(), -1);
-    return;
-  }
-
-  if (!opt_value) {
+  const auto& args = storage->arg_table();
+  RowMap filtered = args.FilterToRowMap(
+      {args.arg_set_id().eq(arg_set_id), args.key().eq(key)});
+  if (filtered.size() == 0) {
     sqlite3_result_null(ctx);
     return;
   }
+  if (filtered.size() > 1) {
+    sqlite3_result_error(
+        ctx, "EXTRACT_ARG: received multiple args matching arg set id and key",
+        -1);
+  }
 
-  switch (opt_value->type) {
-    case Variadic::kInt:
-      sqlite3_result_int64(ctx, opt_value->int_value);
-      break;
+  uint32_t idx = filtered.Get(0);
+  Variadic::Type type = *storage->GetVariadicTypeForId(args.value_type()[idx]);
+  switch (type) {
     case Variadic::kBool:
-      sqlite3_result_int64(ctx, opt_value->bool_value);
-      break;
+    case Variadic::kInt:
     case Variadic::kUint:
-      sqlite3_result_int64(ctx, static_cast<int64_t>(opt_value->uint_value));
-      break;
     case Variadic::kPointer:
-      sqlite3_result_int64(ctx, static_cast<int64_t>(opt_value->pointer_value));
+      sqlite3_result_int64(ctx, *args.int_value()[idx]);
       break;
     case Variadic::kJson:
-      sqlite3_result_text(ctx, storage->GetString(opt_value->json_value).data(),
-                          -1, nullptr);
-      break;
     case Variadic::kString:
-      sqlite3_result_text(
-          ctx, storage->GetString(opt_value->string_value).data(), -1, nullptr);
+      sqlite3_result_text(ctx, args.string_value().GetString(idx).data(), -1,
+                          nullptr);
       break;
     case Variadic::kReal:
-      sqlite3_result_double(ctx, opt_value->real_value);
+      sqlite3_result_double(ctx, *args.real_value()[idx]);
       break;
   }
 }
@@ -610,25 +471,10 @@
   }
 }
 
-void CreateSourceGeqFunction(sqlite3* db) {
-  auto fn = [](sqlite3_context* ctx, int, sqlite3_value**) {
-    sqlite3_result_error(
-        ctx, "SOURCE_GEQ should not be called from the global scope", -1);
-  };
-  auto ret = sqlite3_create_function_v2(db, "SOURCE_GEQ", -1,
-                                        SQLITE_UTF8 | SQLITE_DETERMINISTIC,
-                                        nullptr, fn, nullptr, nullptr, nullptr);
-  if (ret != SQLITE_OK) {
-    PERFETTO_FATAL("Error initializing SOURCE_GEQ: %s", sqlite3_errmsg(db));
-  }
-}
-
 void SetupMetrics(TraceProcessor* tp,
                   sqlite3* db,
                   std::vector<metrics::SqlMetricFile>* sql_metrics) {
   tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
-  tp->ExtendMetricsProto(kAllChromeMetricsDescriptor.data(),
-                         kAllChromeMetricsDescriptor.size());
 
   for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
     tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
@@ -644,7 +490,7 @@
         nullptr, nullptr,
         [](void* ptr) { delete static_cast<metrics::RunMetricContext*>(ptr); });
     if (ret)
-      PERFETTO_FATAL("Error initializing RUN_METRIC");
+      PERFETTO_ELOG("Error initializing RUN_METRIC");
   }
 
   {
@@ -652,15 +498,7 @@
         db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
         metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
     if (ret)
-      PERFETTO_FATAL("Error initializing RepeatedField");
-  }
-
-  {
-    auto ret = sqlite3_create_function_v2(db, "NULL_IF_EMPTY", 1, SQLITE_UTF8,
-                                          nullptr, metrics::NullIfEmpty,
-                                          nullptr, nullptr, nullptr);
-    if (ret)
-      PERFETTO_FATAL("Error initializing NULL_IF_EMPTY");
+      PERFETTO_ELOG("Error initializing RepeatedField");
   }
 }
 
@@ -672,18 +510,6 @@
   PERFETTO_CHECK(init_once);
 }
 
-void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) {
-  char* insert_sql = sqlite3_mprintf(
-      "INSERT INTO trace_metrics(name) VALUES('%q')", metric_name.c_str());
-  char* insert_error = nullptr;
-  sqlite3_exec(db, insert_sql, nullptr, nullptr, &insert_error);
-  sqlite3_free(insert_sql);
-  if (insert_error) {
-    PERFETTO_ELOG("Error registering table: %s", insert_error);
-    sqlite3_free(insert_error);
-  }
-}
-
 }  // namespace
 
 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
@@ -716,8 +542,6 @@
   CreateDemangledNameFunction(db);
   CreateLastNonNullFunction(db);
   CreateExtractArgFunction(context_.storage.get(), db);
-  CreateSourceGeqFunction(db);
-  CreateValueAtMaxTsFunction(db);
 
   SetupMetrics(this, *db_, &sql_metrics_);
 
@@ -747,28 +571,6 @@
       new ExperimentalSliceLayoutGenerator(
           context_.storage.get()->mutable_string_pool(),
           &storage->slice_table())));
-  RegisterDynamicTable(std::unique_ptr<AncestorGenerator>(
-      new AncestorGenerator(AncestorGenerator::Ancestor::kSlice, &context_)));
-  RegisterDynamicTable(std::unique_ptr<AncestorGenerator>(new AncestorGenerator(
-      AncestorGenerator::Ancestor::kStackProfileCallsite, &context_)));
-  RegisterDynamicTable(std::unique_ptr<DescendantSliceGenerator>(
-      new DescendantSliceGenerator(&context_)));
-  RegisterDynamicTable(
-      std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
-          ConnectedFlowGenerator::Mode::kDirectlyConnectedFlow, &context_)));
-  RegisterDynamicTable(
-      std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
-          ConnectedFlowGenerator::Mode::kPrecedingFlow, &context_)));
-  RegisterDynamicTable(
-      std::unique_ptr<ConnectedFlowGenerator>(new ConnectedFlowGenerator(
-          ConnectedFlowGenerator::Mode::kFollowingFlow, &context_)));
-  RegisterDynamicTable(std::unique_ptr<ExperimentalSchedUpidGenerator>(
-      new ExperimentalSchedUpidGenerator(storage->sched_slice_table(),
-                                         storage->thread_table())));
-  RegisterDynamicTable(std::unique_ptr<ThreadStateGenerator>(
-      new ThreadStateGenerator(&context_)));
-  RegisterDynamicTable(std::unique_ptr<ExperimentalAnnotatedStackGenerator>(
-      new ExperimentalAnnotatedStackGenerator(&context_)));
 
   // New style db-backed tables.
   RegisterDbTable(storage->arg_table());
@@ -776,8 +578,6 @@
   RegisterDbTable(storage->process_table());
 
   RegisterDbTable(storage->slice_table());
-  RegisterDbTable(storage->flow_table());
-  RegisterDbTable(storage->thread_slice_table());
   RegisterDbTable(storage->sched_slice_table());
   RegisterDbTable(storage->instant_table());
   RegisterDbTable(storage->gpu_slice_table());
@@ -797,7 +597,6 @@
   RegisterDbTable(storage->softirq_counter_track_table());
   RegisterDbTable(storage->gpu_counter_track_table());
   RegisterDbTable(storage->gpu_counter_group_table());
-  RegisterDbTable(storage->perf_counter_track_table());
 
   RegisterDbTable(storage->heap_graph_object_table());
   RegisterDbTable(storage->heap_graph_reference_table());
@@ -806,7 +605,6 @@
   RegisterDbTable(storage->symbol_table());
   RegisterDbTable(storage->heap_profile_allocation_table());
   RegisterDbTable(storage->cpu_profile_stack_sample_table());
-  RegisterDbTable(storage->perf_sample_table());
   RegisterDbTable(storage->stack_profile_callsite_table());
   RegisterDbTable(storage->stack_profile_mapping_table());
   RegisterDbTable(storage->stack_profile_frame_table());
@@ -819,21 +617,15 @@
 
   RegisterDbTable(storage->graphics_frame_slice_table());
 
-  RegisterDbTable(storage->expected_frame_timeline_slice_table());
-  RegisterDbTable(storage->actual_frame_timeline_slice_table());
-
   RegisterDbTable(storage->metadata_table());
   RegisterDbTable(storage->cpu_table());
   RegisterDbTable(storage->cpu_freq_table());
-  RegisterDbTable(storage->clock_snapshot_table());
-
-  RegisterDbTable(storage->memory_snapshot_table());
-  RegisterDbTable(storage->process_memory_snapshot_table());
-  RegisterDbTable(storage->memory_snapshot_node_table());
-  RegisterDbTable(storage->memory_snapshot_edge_table());
 }
 
-TraceProcessorImpl::~TraceProcessorImpl() = default;
+TraceProcessorImpl::~TraceProcessorImpl() {
+  for (auto* it : iterators_)
+    it->Reset();
+}
 
 util::Status TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data,
                                        size_t size) {
@@ -905,8 +697,9 @@
   return deletion_list.size();
 }
 
-Iterator TraceProcessorImpl::ExecuteQuery(const std::string& sql,
-                                          int64_t time_queued) {
+TraceProcessor::Iterator TraceProcessorImpl::ExecuteQuery(
+    const std::string& sql,
+    int64_t time_queued) {
   sqlite3_stmt* raw_stmt;
   int err;
   {
@@ -930,7 +723,8 @@
 
   std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
       this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
-  return Iterator(std::move(impl));
+  iterators_.emplace_back(impl.get());
+  return TraceProcessor::Iterator(std::move(impl));
 }
 
 void TraceProcessorImpl::InterruptQuery() {
@@ -940,15 +734,6 @@
   sqlite3_interrupt(db_.get());
 }
 
-bool TraceProcessorImpl::IsRootMetricField(const std::string& metric_name) {
-  base::Optional<uint32_t> desc_idx =
-      pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
-  if (!desc_idx.has_value())
-    return false;
-  auto field_idx = pool_.descriptors()[*desc_idx].FindFieldByName(metric_name);
-  return field_idx != nullptr;
-}
-
 util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
                                                 const std::string& sql) {
   std::string stripped_sql;
@@ -969,7 +754,7 @@
     return util::OkStatus();
   }
 
-  auto sep_idx = path.rfind('/');
+  auto sep_idx = path.rfind("/");
   std::string basename =
       sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
 
@@ -981,14 +766,9 @@
 
   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;
-
-  if (IsRootMetricField(no_ext_name)) {
-    metric.proto_field_name = no_ext_name;
-    metric.output_table_name = no_ext_name + "_output";
-    InsertIntoTraceMetricsTable(*db_, no_ext_name);
-  }
-
   sql_metrics_.emplace_back(metric);
   return util::OkStatus();
 }
@@ -1034,33 +814,6 @@
                                  root_descriptor, metrics_proto);
 }
 
-util::Status TraceProcessorImpl::ComputeMetricText(
-    const std::vector<std::string>& metric_names,
-    TraceProcessor::MetricResultFormat format,
-    std::string* metrics_string) {
-  std::vector<uint8_t> metrics_proto;
-  util::Status status = ComputeMetric(metric_names, &metrics_proto);
-  if (!status.ok())
-    return status;
-  switch (format) {
-    case TraceProcessor::MetricResultFormat::kProtoText:
-      *metrics_string = protozero_to_text::ProtozeroToText(
-          pool_, ".perfetto.protos.TraceMetrics",
-          protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
-          protozero_to_text::kIncludeNewLines);
-      break;
-    case TraceProcessor::MetricResultFormat::kJson:
-      // TODO(dproy): Implement this.
-      PERFETTO_FATAL("Json formatted metrics not supported yet.");
-      break;
-  }
-  return status;
-}
-
-std::vector<uint8_t> TraceProcessorImpl::GetMetricDescriptors() {
-  return pool_.SerializeAsDescriptorSet();
-}
-
 void TraceProcessorImpl::EnableMetatrace() {
   metatrace::Enable();
 }
@@ -1093,5 +846,42 @@
   return util::OkStatus();
 }
 
+TraceProcessor::IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
+                                           sqlite3* db,
+                                           ScopedStmt stmt,
+                                           uint32_t column_count,
+                                           util::Status status,
+                                           uint32_t sql_stats_row)
+    : trace_processor_(trace_processor),
+      db_(db),
+      stmt_(std::move(stmt)),
+      column_count_(column_count),
+      status_(status),
+      sql_stats_row_(sql_stats_row) {}
+
+TraceProcessor::IteratorImpl::~IteratorImpl() {
+  if (trace_processor_) {
+    auto* its = &trace_processor_->iterators_;
+    auto it = std::find(its->begin(), its->end(), this);
+    PERFETTO_CHECK(it != its->end());
+    its->erase(it);
+
+    base::TimeNanos t_end = base::GetWallTimeNs();
+    auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
+    sql_stats->RecordQueryEnd(sql_stats_row_, t_end.count());
+  }
+}
+
+void TraceProcessor::IteratorImpl::Reset() {
+  *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0,
+                       util::ErrStatus("Trace processor was deleted"), 0);
+}
+
+void TraceProcessor::IteratorImpl::RecordFirstNextInSqlStats() {
+  base::TimeNanos t_first_next = base::GetWallTimeNs();
+  auto* sql_stats = trace_processor_->context_.storage->mutable_sql_stats();
+  sql_stats->RecordQueryFirstNext(sql_stats_row_, t_first_next.count());
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index cb9ef9f..c2523a2 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -64,12 +64,6 @@
   util::Status ComputeMetric(const std::vector<std::string>& metric_names,
                              std::vector<uint8_t>* metrics) override;
 
-  util::Status ComputeMetricText(const std::vector<std::string>& metric_names,
-                                 TraceProcessor::MetricResultFormat format,
-                                 std::string* metrics_string) override;
-
-  std::vector<uint8_t> GetMetricDescriptors() override;
-
   void InterruptQuery() override;
 
   size_t RestoreInitialTables() override;
@@ -83,7 +77,7 @@
       std::vector<uint8_t>* trace_proto) override;
 
  private:
-  // Needed for iterators to be able to access the context.
+  // Needed for iterators to be able to delete themselves from the vector.
   friend class IteratorImpl;
 
   template <typename Table>
@@ -98,13 +92,14 @@
                                  std::move(generator));
   }
 
-  bool IsRootMetricField(const std::string& metric_name);
   ScopedDb db_;
   std::unique_ptr<QueryCache> query_cache_;
 
   DescriptorPool pool_;
   std::vector<metrics::SqlMetricFile> sql_metrics_;
 
+  std::vector<IteratorImpl*> iterators_;
+
   // This is atomic because it is set by the CTRL-C signal handler and we need
   // to prevent single-flow compiler optimizations in ExecuteQuery().
   std::atomic<bool> query_interrupted_{false};
@@ -118,6 +113,96 @@
   uint64_t bytes_parsed_ = 0;
 };
 
+// The pointer implementation of TraceProcessor::Iterator.
+class TraceProcessor::IteratorImpl {
+ public:
+  IteratorImpl(TraceProcessorImpl* impl,
+               sqlite3* db,
+               ScopedStmt,
+               uint32_t column_count,
+               util::Status,
+               uint32_t sql_stats_row);
+  ~IteratorImpl();
+
+  IteratorImpl(IteratorImpl&) noexcept = delete;
+  IteratorImpl& operator=(IteratorImpl&) = delete;
+
+  IteratorImpl(IteratorImpl&&) noexcept = default;
+  IteratorImpl& operator=(IteratorImpl&&) = default;
+
+  // Methods called by TraceProcessor::Iterator.
+  bool Next() {
+    // Delegate to the cc file to prevent trace_storage.h include in this file.
+    if (!called_next_) {
+      RecordFirstNextInSqlStats();
+      called_next_ = true;
+    }
+
+    if (!status_.ok())
+      return false;
+
+    int ret = sqlite3_step(*stmt_);
+    if (PERFETTO_UNLIKELY(ret != SQLITE_ROW && ret != SQLITE_DONE)) {
+      status_ = util::ErrStatus("%s", sqlite3_errmsg(db_));
+      return false;
+    }
+    return ret == SQLITE_ROW;
+  }
+
+  SqlValue Get(uint32_t col) {
+    auto column = static_cast<int>(col);
+    auto col_type = sqlite3_column_type(*stmt_, column);
+    SqlValue value;
+    switch (col_type) {
+      case SQLITE_INTEGER:
+        value.type = SqlValue::kLong;
+        value.long_value = sqlite3_column_int64(*stmt_, column);
+        break;
+      case SQLITE_TEXT:
+        value.type = SqlValue::kString;
+        value.string_value =
+            reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, column));
+        break;
+      case SQLITE_FLOAT:
+        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;
+    }
+    return value;
+  }
+
+  std::string GetColumnName(uint32_t col) {
+    return sqlite3_column_name(stmt_.get(), static_cast<int>(col));
+  }
+
+  uint32_t ColumnCount() { return column_count_; }
+
+  util::Status Status() { return status_; }
+
+  // Methods called by TraceProcessorImpl.
+  void Reset();
+
+ private:
+  void RecordFirstNextInSqlStats();
+
+  TraceProcessorImpl* trace_processor_;
+  sqlite3* db_ = nullptr;
+  ScopedStmt stmt_;
+  uint32_t column_count_ = 0;
+  util::Status status_;
+
+  uint32_t sql_stats_row_ = 0;
+  bool called_next_ = false;
+};
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index e4fac8b..88c39af 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -32,15 +32,12 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
 #include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/version.h"
-
 #include "perfetto/trace_processor/read_trace.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/metrics/chrome/all_chrome_metrics.descriptor.h"
+#include "src/trace_processor/metrics/custom_options.descriptor.h"
 #include "src/trace_processor/metrics/metrics.descriptor.h"
 #include "src/trace_processor/util/proto_to_json.h"
 #include "src/trace_processor/util/status_macros.h"
@@ -48,14 +45,17 @@
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
 #include "src/trace_processor/rpc/httpd.h"
 #endif
-#include "src/profiling/deobfuscator.h"
-#include "src/profiling/symbolizer/local_symbolizer.h"
+
 #include "src/profiling/symbolizer/symbolize_database.h"
 #include "src/profiling/symbolizer/symbolizer.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+#include "src/profiling/symbolizer/local_symbolizer.h"
+#endif
+
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #define PERFETTO_HAS_SIGNAL_H() 1
 #else
 #define PERFETTO_HAS_SIGNAL_H() 0
@@ -67,20 +67,21 @@
 #include <sys/types.h>
 #endif
 
+#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
+#include "perfetto_version.gen.h"
+#else
+#define PERFETTO_GET_GIT_REVISION() "unknown"
+#endif
+
 #if PERFETTO_HAS_SIGNAL_H()
 #include <signal.h>
 #endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <io.h>
 #define ftruncate _chsize
 #else
 #include <dirent.h>
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_LINENOISE) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <unistd.h>  // For getuid() in GetConfigPath().
+#include <getopt.h>
 #endif
 
 namespace perfetto {
@@ -92,7 +93,7 @@
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_LINENOISE)
 
 bool EnsureDir(const std::string& path) {
-  return base::Mkdir(path) || errno == EEXIST;
+  return mkdir(path.c_str(), 0755) != -1 || errno == EEXIST;
 }
 
 bool EnsureFile(const std::string& path) {
@@ -101,15 +102,8 @@
 
 std::string GetConfigPath() {
   const char* homedir = getenv("HOME");
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
   if (homedir == nullptr)
     homedir = getpwuid(getuid())->pw_dir;
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  if (homedir == nullptr)
-    homedir = getenv("USERPROFILE");
-#endif
   if (homedir == nullptr)
     return "";
   return std::string(homedir) + "/.config";
@@ -117,14 +111,14 @@
 
 std::string GetPerfettoPath() {
   std::string config = GetConfigPath();
-  if (config.empty())
+  if (config == "")
     return "";
   return config + "/perfetto";
 }
 
 std::string GetHistoryPath() {
   std::string perfetto = GetPerfettoPath();
-  if (perfetto.empty())
+  if (perfetto == "")
     return "";
   return perfetto + "/.trace_processor_shell_history";
 }
@@ -133,7 +127,7 @@
   linenoiseSetMultiLine(true);
   linenoiseHistorySetMaxLen(1000);
 
-  bool success = !GetHistoryPath().empty();
+  bool success = GetHistoryPath() != "";
   success = success && EnsureDir(GetConfigPath());
   success = success && EnsureDir(GetPerfettoPath());
   success = success && EnsureFile(GetHistoryPath());
@@ -240,7 +234,7 @@
 }
 
 util::Status ExportTraceToDatabase(const std::string& output_name) {
-  PERFETTO_CHECK(output_name.find('\'') == std::string::npos);
+  PERFETTO_CHECK(output_name.find("'") == std::string::npos);
   {
     base::ScopedFile fd(base::OpenFile(output_name, O_CREAT | O_RDWR, 0600));
     if (!fd)
@@ -265,7 +259,7 @@
       "SELECT name FROM sqlite_master WHERE type='table'");
   for (uint32_t rows = 0; tables_it.Next(); rows++) {
     std::string table_name = tables_it.Get(0).string_value;
-    PERFETTO_CHECK(!base::Contains(table_name, '\''));
+    PERFETTO_CHECK(table_name.find("'") == std::string::npos);
     std::string export_sql = "CREATE TABLE perfetto_export." + table_name +
                              " AS SELECT * FROM " + table_name;
 
@@ -359,11 +353,28 @@
   google::protobuf::compiler::Parser parser;
   parser.Parse(&tokenizer, file_desc);
 
+  // Go through all the imports (dependencies) and make the import
+  // paths relative to the Perfetto root. This allows trace processor embedders
+  // to have paths relative to their own root for imports when using metric
+  // proto extensions.
+  for (int i = 0; i < file_desc->dependency_size(); ++i) {
+    static constexpr char kPrefix[] = "protos/perfetto/metrics/";
+    auto* dep = file_desc->mutable_dependency(i);
+
+    // If the file being imported contains kPrefix, it is probably an import of
+    // a Perfetto metrics proto. Strip anything before kPrefix to ensure that
+    // we resolve the paths correctly.
+    size_t idx = dep->find(kPrefix);
+    if (idx != std::string::npos) {
+      *dep = dep->substr(idx);
+    }
+  }
+
   file_desc->set_name(BaseName(extend_metrics_proto));
   pool->BuildFile(*file_desc);
 
   std::vector<uint8_t> metric_proto;
-  metric_proto.resize(desc_set.ByteSizeLong());
+  metric_proto.resize(static_cast<size_t>(desc_set.ByteSize()));
   desc_set.SerializeToArray(metric_proto.data(),
                             static_cast<int>(metric_proto.size()));
 
@@ -426,7 +437,7 @@
   return util::OkStatus();
 }
 
-void PrintQueryResultInteractively(Iterator* it,
+void PrintQueryResultInteractively(TraceProcessor::Iterator* it,
                                    base::TimeNanos t_start,
                                    uint32_t column_width) {
   base::TimeNanos t_end = t_start;
@@ -483,11 +494,56 @@
   if (!status.ok()) {
     PERFETTO_ELOG("SQLite error: %s", status.c_message());
   }
-  printf("\nQuery executed in %.3f ms\n\n",
-         static_cast<double>((t_end - t_start).count()) / 1E6);
+  printf("\nQuery executed in %.3f ms\n\n", (t_end - t_start).count() / 1E6);
 }
 
-util::Status PrintQueryResultAsCsv(Iterator* it, FILE* output) {
+void PrintShellUsage() {
+  PERFETTO_ELOG(
+      "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");
+}
+
+util::Status StartInteractiveShell(uint32_t column_width) {
+  SetupLineEditor();
+
+  for (;;) {
+    ScopedLine line = GetLine("> ");
+    if (!line)
+      break;
+    if (strcmp(line.get(), "") == 0) {
+      printf("If you want to quit either type .q or press CTRL-D (EOF)\n");
+      continue;
+    }
+    if (line.get()[0] == '.') {
+      char command[32] = {};
+      char arg[1024] = {};
+      sscanf(line.get() + 1, "%31s %1023s", command, arg);
+      if (strcmp(command, "quit") == 0 || strcmp(command, "q") == 0) {
+        break;
+      } else if (strcmp(command, "help") == 0) {
+        PrintShellUsage();
+      } else if (strcmp(command, "dump") == 0 && strlen(arg)) {
+        if (!ExportTraceToDatabase(arg).ok())
+          PERFETTO_ELOG("Database export failed");
+      } else if (strcmp(command, "reset") == 0) {
+        g_tp->RestoreInitialTables();
+      } else {
+        PrintShellUsage();
+      }
+      continue;
+    }
+
+    base::TimeNanos t_start = base::GetWallTimeNs();
+    auto it = g_tp->ExecuteQuery(line.get());
+    PrintQueryResultInteractively(&it, t_start, column_width);
+  }
+  return util::OkStatus();
+}
+
+util::Status PrintQueryResultAsCsv(TraceProcessor::Iterator* it, FILE* output) {
   for (uint32_t c = 0; c < it->ColumnCount(); c++) {
     if (c > 0)
       fprintf(output, ",");
@@ -542,7 +598,7 @@
   while (!feof(input) && !ferror(input)) {
     std::string sql_query;
     while (fgets(buffer, sizeof(buffer), input)) {
-      std::string line = base::TrimLeading(buffer);
+      std::string line = buffer;
       if (IsBlankLine(line))
         break;
 
@@ -571,22 +627,10 @@
   return util::OkStatus();
 }
 
-util::Status RunQueriesWithoutOutput(const std::vector<std::string>& queries) {
-  for (const auto& sql_query : queries) {
-    PERFETTO_DLOG("Executing query: %s", sql_query.c_str());
-
-    auto it = g_tp->ExecuteQuery(sql_query);
-    RETURN_IF_ERROR(it.Status());
-    if (it.Next()) {
-      return util::ErrStatus("Unexpected result from a query.");
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status RunQueriesAndPrintResult(const std::vector<std::string>& queries,
-                                      FILE* output) {
+util::Status RunQueryAndPrintResult(const std::vector<std::string>& queries,
+                                    FILE* output) {
   bool is_first_query = true;
+  bool is_query_error = false;
   bool has_output = false;
   for (const auto& sql_query : queries) {
     // Add an extra newline separator between query results.
@@ -597,40 +641,36 @@
     PERFETTO_ILOG("Executing query: %s", sql_query.c_str());
 
     auto it = g_tp->ExecuteQuery(sql_query);
-    RETURN_IF_ERROR(it.Status());
+    util::Status status = it.Status();
+    if (!status.ok()) {
+      PERFETTO_ELOG("SQLite error: %s", status.c_message());
+      is_query_error = true;
+      break;
+    }
     if (it.ColumnCount() == 0) {
       bool it_has_more = it.Next();
       PERFETTO_DCHECK(!it_has_more);
       continue;
     }
 
-    // If we have a single column with the name |suppress_query_output| that's
-    // a hint to shell that it should not treat the query as having real
-    // meaning.
-    if (it.ColumnCount() == 1 &&
-        it.GetColumnName(0) == "suppress_query_output") {
-      // We should only see a single null value as this feature is usually used
-      // as SELECT RUN_METRIC(<metric file>) as suppress_query_output and
-      // RUN_METRIC returns a single null.
-      bool has_next = it.Next();
-      RETURN_IF_ERROR(it.Status());
-      PERFETTO_DCHECK(has_next);
-      PERFETTO_DCHECK(it.Get(0).is_null());
-
-      has_next = it.Next();
-      RETURN_IF_ERROR(it.Status());
-      PERFETTO_DCHECK(!has_next);
-      continue;
-    }
-
     if (has_output) {
-      return util::ErrStatus(
-          "More than one query generated result rows. This is unsupported.");
+      PERFETTO_ELOG(
+          "More than one query generated result rows. This is "
+          "unsupported.");
+      is_query_error = true;
+      break;
     }
+    status = PrintQueryResultAsCsv(&it, output);
     has_output = true;
-    RETURN_IF_ERROR(PrintQueryResultAsCsv(&it, output));
+
+    if (!status.ok()) {
+      PERFETTO_ELOG("SQLite error: %s", status.c_message());
+      is_query_error = true;
+    }
   }
-  return util::OkStatus();
+  return is_query_error
+             ? util::ErrStatus("Encountered errors while running queries")
+             : util::OkStatus();
 }
 
 util::Status PrintPerfFile(const std::string& perf_file_path,
@@ -655,12 +695,10 @@
 struct CommandLineOptions {
   std::string perf_file_path;
   std::string query_file_path;
-  std::string pre_metrics_path;
   std::string sqlite_file_path;
   std::string metric_names;
   std::string metric_output;
   std::string trace_file_path;
-  std::string port_number;
   bool launch_shell = false;
   bool enable_httpd = false;
   bool wide = false;
@@ -668,6 +706,58 @@
   std::string metatrace_path;
 };
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+void PrintUsage(char** argv) {
+  PERFETTO_ELOG(R"(
+Interactive trace processor shell.
+Usage: %s [OPTIONS] trace_file.pb
+
+Options:
+ -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.
+ --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).)",
+                argv[0]);
+}
+
+CommandLineOptions ParseCommandLineOptions(int argc, char** argv) {
+  CommandLineOptions command_line_options;
+
+  if (argc < 2 || argc % 2 == 1) {
+    PrintUsage(argv);
+    exit(1);
+  }
+
+  for (int i = 1; i < argc - 1; i += 2) {
+    if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--query-file") == 0) {
+      command_line_options.query_file_path = argv[i + 1];
+    } else if (strcmp(argv[i], "--run-metrics") == 0) {
+      command_line_options.metric_names = argv[i + 1];
+    } else if (strcmp(argv[i], "--metrics-output") == 0) {
+      command_line_options.metric_output = argv[i + 1];
+    } else {
+      PrintUsage(argv);
+      exit(1);
+    }
+  }
+  command_line_options.trace_file_path = argv[argc - 1];
+  command_line_options.launch_shell =
+      command_line_options.metric_names.empty() &&
+      command_line_options.query_file_path.empty();
+  return command_line_options;
+}
+
+#else  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
 void PrintUsage(char** argv) {
   PERFETTO_ELOG(R"(
 Interactive trace processor shell.
@@ -688,11 +778,7 @@
                                       If used with --run-metrics, the query is
                                       executed after the selected metrics and
                                       the metrics output is suppressed.
- --pre-metrics FILE                   Read and execute an SQL query from a file.
-                                      This query is executed before the selected
-                                      metrics and can't output any results.
  -D, --httpd                          Enables the HTTP RPC server.
- --http-port PORT                     Specify what port to run HTTP RPC server.
  -i, --interactive                    Starts interactive mode even after a query
                                       file is specified with -q or
                                       --run-metrics.
@@ -720,13 +806,11 @@
   CommandLineOptions command_line_options;
   enum LongOption {
     OPT_RUN_METRICS = 1000,
-    OPT_PRE_METRICS,
     OPT_METRICS_OUTPUT,
     OPT_FORCE_FULL_SORT,
-    OPT_HTTP_PORT,
   };
 
-  static const option long_options[] = {
+  static const struct option long_options[] = {
       {"help", no_argument, nullptr, 'h'},
       {"version", no_argument, nullptr, 'v'},
       {"wide", no_argument, nullptr, 'W'},
@@ -738,22 +822,21 @@
       {"export", required_argument, nullptr, 'e'},
       {"metatrace", required_argument, nullptr, 'm'},
       {"run-metrics", required_argument, nullptr, OPT_RUN_METRICS},
-      {"pre-metrics", required_argument, nullptr, OPT_PRE_METRICS},
       {"metrics-output", required_argument, nullptr, OPT_METRICS_OUTPUT},
       {"full-sort", no_argument, nullptr, OPT_FORCE_FULL_SORT},
-      {"http-port", required_argument, nullptr, OPT_HTTP_PORT},
       {nullptr, 0, nullptr, 0}};
 
   bool explicit_interactive = false;
+  int option_index = 0;
   for (;;) {
     int option =
-        getopt_long(argc, argv, "hvWiDdm:p:q:e:", long_options, nullptr);
+        getopt_long(argc, argv, "hvWiDdm:p:q:e:", long_options, &option_index);
 
     if (option == -1)
       break;  // EOF.
 
     if (option == 'v') {
-      printf("%s\n", base::GetVersionString());
+      printf("%s\n", PERFETTO_GET_GIT_REVISION());
       exit(0);
     }
 
@@ -801,11 +884,6 @@
       continue;
     }
 
-    if (option == OPT_PRE_METRICS) {
-      command_line_options.pre_metrics_path = optarg;
-      continue;
-    }
-
     if (option == OPT_RUN_METRICS) {
       command_line_options.metric_names = optarg;
       continue;
@@ -821,18 +899,12 @@
       continue;
     }
 
-    if (option == OPT_HTTP_PORT) {
-      command_line_options.port_number = optarg;
-      continue;
-    }
-
     PrintUsage(argv);
     exit(option == 'h' ? 0 : 1);
   }
 
   command_line_options.launch_shell =
-      explicit_interactive || (command_line_options.pre_metrics_path.empty() &&
-                               command_line_options.metric_names.empty() &&
+      explicit_interactive || (command_line_options.metric_names.empty() &&
                                command_line_options.query_file_path.empty() &&
                                command_line_options.sqlite_file_path.empty());
 
@@ -855,6 +927,8 @@
   return command_line_options;
 }
 
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
 void ExtendPoolWithBinaryDescriptor(google::protobuf::DescriptorPool& pool,
                                     const void* data,
                                     int size) {
@@ -868,7 +942,7 @@
 util::Status LoadTrace(const std::string& trace_file_path, double* size_mb) {
   util::Status read_status =
       ReadTrace(g_tp, trace_file_path.c_str(), [&size_mb](size_t parsed_size) {
-        *size_mb = static_cast<double>(parsed_size) / 1E6;
+        *size_mb = parsed_size / 1E6;
         fprintf(stderr, "\rLoading trace: %.2f MB\r", *size_mb);
       });
   if (!read_status.ok()) {
@@ -876,9 +950,15 @@
                            trace_file_path.c_str(), read_status.c_message());
   }
 
-  std::unique_ptr<profiling::Symbolizer> symbolizer =
-      profiling::LocalSymbolizerOrDie(profiling::GetPerfettoBinaryPath(),
-                                      getenv("PERFETTO_SYMBOLIZER_MODE"));
+  std::unique_ptr<profiling::Symbolizer> symbolizer;
+  auto binary_path = profiling::GetPerfettoBinaryPath();
+  if (!binary_path.empty()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+      symbolizer.reset(new profiling::LocalSymbolizer(std::move(binary_path)));
+#else
+      PERFETTO_FATAL("This build does not support local symbolization.");
+#endif
+  }
 
   if (symbolizer) {
     profiling::SymbolizeDatabase(
@@ -894,45 +974,18 @@
         });
     g_tp->NotifyEndOfFile();
   }
-
-  auto maybe_map = profiling::GetPerfettoProguardMapPath();
-  if (!maybe_map.empty()) {
-    profiling::ReadProguardMapsToDeobfuscationPackets(
-        maybe_map, [](const std::string& trace_proto) {
-          std::unique_ptr<uint8_t[]> buf(new uint8_t[trace_proto.size()]);
-          memcpy(buf.get(), trace_proto.data(), trace_proto.size());
-          auto status = g_tp->Parse(std::move(buf), trace_proto.size());
-          if (!status.ok()) {
-            PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
-                                    status.message().c_str());
-            return;
-          }
-        });
-  }
   return util::OkStatus();
 }
 
-util::Status RunQueries(const std::string& query_file_path,
-                        bool expect_output) {
+util::Status RunQueries(const CommandLineOptions& options) {
   std::vector<std::string> queries;
-  base::ScopedFstream file(fopen(query_file_path.c_str(), "r"));
+  base::ScopedFstream file(fopen(options.query_file_path.c_str(), "r"));
   if (!file) {
     return util::ErrStatus("Could not open query file (path: %s)",
-                           query_file_path.c_str());
+                           options.query_file_path.c_str());
   }
   RETURN_IF_ERROR(LoadQueries(file.get(), &queries));
-
-  util::Status status;
-  if (expect_output) {
-    status = RunQueriesAndPrintResult(queries, stdout);
-  } else {
-    status = RunQueriesWithoutOutput(queries);
-  }
-  if (!status.ok()) {
-    return util::ErrStatus("Encountered error while running queries: %s",
-                           status.c_message());
-  }
-  return util::OkStatus();
+  return RunQueryAndPrintResult(queries, stdout);
 }
 
 util::Status RunMetrics(const CommandLineOptions& options) {
@@ -943,8 +996,8 @@
       google::protobuf::DescriptorPool::generated_pool());
   ExtendPoolWithBinaryDescriptor(pool, kMetricsDescriptor.data(),
                                  kMetricsDescriptor.size());
-  ExtendPoolWithBinaryDescriptor(pool, kAllChromeMetricsDescriptor.data(),
-                                 kAllChromeMetricsDescriptor.size());
+  ExtendPoolWithBinaryDescriptor(pool, kCustomOptionsDescriptor.data(),
+                                 kCustomOptionsDescriptor.size());
 
   std::vector<std::string> metrics;
   for (base::StringSplitter ss(options.metric_names, ','); ss.Next();) {
@@ -957,22 +1010,20 @@
     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('.');
+    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);
-
-    // The proto must be extended before registering the metric.
-    util::Status status = ExtendMetricsProto(no_ext_name + ".proto", &pool);
+    util::Status status = RegisterMetric(no_ext_name + ".sql");
     if (!status.ok()) {
-      return util::ErrStatus("Unable to extend metrics proto %s: %s",
+      return util::ErrStatus("Unable to register metric %s: %s",
                              metric_or_path.c_str(), status.c_message());
     }
 
-    status = RegisterMetric(no_ext_name + ".sql");
+    status = ExtendMetricsProto(no_ext_name + ".proto", &pool);
     if (!status.ok()) {
-      return util::ErrStatus("Unable to register metric %s: %s",
+      return util::ErrStatus("Unable to extend metrics proto %s: %s",
                              metric_or_path.c_str(), status.c_message());
     }
 
@@ -992,65 +1043,11 @@
   return RunMetrics(std::move(metrics), format, pool);
 }
 
-void PrintShellUsage() {
-  PERFETTO_ELOG(
-      "Available commands:\n"
-      ".quit, .q    Exit the shell.\n"
-      ".help        This text.\n"
-      ".dump FILE   Export the trace as a sqlite database.\n"
-      ".read FILE   Executes the queries in the FILE.\n"
-      ".reset       Destroys all tables/view created by the user.\n");
-}
-
-util::Status StartInteractiveShell(uint32_t column_width) {
-  SetupLineEditor();
-
-  for (;;) {
-    ScopedLine line = GetLine("> ");
-    if (!line)
-      break;
-    if (strcmp(line.get(), "") == 0) {
-      printf("If you want to quit either type .q or press CTRL-D (EOF)\n");
-      continue;
-    }
-    if (line.get()[0] == '.') {
-      char command[32] = {};
-      char arg[1024] = {};
-      sscanf(line.get() + 1, "%31s %1023s", command, arg);
-      if (strcmp(command, "quit") == 0 || strcmp(command, "q") == 0) {
-        break;
-      } else if (strcmp(command, "help") == 0) {
-        PrintShellUsage();
-      } else if (strcmp(command, "dump") == 0 && strlen(arg)) {
-        if (!ExportTraceToDatabase(arg).ok())
-          PERFETTO_ELOG("Database export failed");
-      } else if (strcmp(command, "reset") == 0) {
-        g_tp->RestoreInitialTables();
-      } else if (strcmp(command, "read") == 0 && strlen(arg)) {
-        util::Status status = RunQueries(arg, true);
-        if (!status.ok()) {
-          PERFETTO_ELOG("%s", status.c_message());
-        }
-      } else {
-        PrintShellUsage();
-      }
-      continue;
-    }
-
-    base::TimeNanos t_start = base::GetWallTimeNs();
-    auto it = g_tp->ExecuteQuery(line.get());
-    PrintQueryResultInteractively(&it, t_start, column_width);
-  }
-  return util::OkStatus();
-}
-
 util::Status TraceProcessorMain(int argc, char** argv) {
   CommandLineOptions options = ParseCommandLineOptions(argc, argv);
 
   Config config;
-  config.sorting_mode = options.force_full_sort
-                            ? SortingMode::kForceFullSort
-                            : SortingMode::kDefaultHeuristics;
+  config.force_full_sort = options.force_full_sort;
 
   std::unique_ptr<TraceProcessor> tp = TraceProcessor::CreateInstance(config);
   g_tp = tp.get();
@@ -1067,7 +1064,7 @@
     RETURN_IF_ERROR(LoadTrace(options.trace_file_path, &size_mb));
     t_load = base::GetWallTimeNs() - t_load_start;
 
-    double t_load_s = static_cast<double>(t_load.count()) / 1E9;
+    double t_load_s = t_load.count() / 1E9;
     PERFETTO_ILOG("Trace loaded: %.2f MB (%.1f MB/s)", size_mb,
                   size_mb / t_load_s);
 
@@ -1076,7 +1073,7 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
   if (options.enable_httpd) {
-    RunHttpRPCServer(std::move(tp), options.port_number);
+    RunHttpRPCServer(std::move(tp));
     PERFETTO_FATAL("Should never return");
   }
 #endif
@@ -1086,16 +1083,12 @@
 #endif
 
   base::TimeNanos t_query_start = base::GetWallTimeNs();
-  if (!options.pre_metrics_path.empty()) {
-    RETURN_IF_ERROR(RunQueries(options.pre_metrics_path, false));
-  }
-
   if (!options.metric_names.empty()) {
     RETURN_IF_ERROR(RunMetrics(options));
   }
 
   if (!options.query_file_path.empty()) {
-    RETURN_IF_ERROR(RunQueries(options.query_file_path, true));
+    RETURN_IF_ERROR(RunQueries(options));
   }
   base::TimeNanos t_query = base::GetWallTimeNs() - t_query_start;
 
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index cca6947..5276196 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -18,64 +18,38 @@
 
 #include "perfetto/base/logging.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/importers/chrome_track_event.descriptor.h"
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/default_modules.h"
-#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
 #include "src/trace_processor/importers/proto/heap_profile_tracker.h"
 #include "src/trace_processor/importers/proto/metadata_tracker.h"
 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/importers/proto/proto_trace_reader.h"
+#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
-#include "src/trace_processor/importers/track_event.descriptor.h"
+#include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/util/descriptors.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) {
   context_.config = cfg;
-
   context_.storage.reset(new TraceStorage(context_.config));
   context_.track_tracker.reset(new TrackTracker(&context_));
-  context_.async_track_set_tracker.reset(new AsyncTrackSetTracker(&context_));
   context_.args_tracker.reset(new ArgsTracker(&context_));
   context_.slice_tracker.reset(new SliceTracker(&context_));
-  context_.flow_tracker.reset(new FlowTracker(&context_));
   context_.event_tracker.reset(new EventTracker(&context_));
   context_.process_tracker.reset(new ProcessTracker(&context_));
   context_.clock_tracker.reset(new ClockTracker(&context_));
   context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
-  context_.perf_sample_tracker.reset(new PerfSampleTracker(&context_));
-  context_.global_stack_profile_tracker.reset(new GlobalStackProfileTracker());
   context_.metadata_tracker.reset(new MetadataTracker(&context_));
   context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
-  {
-    context_.descriptor_pool_.reset(new DescriptorPool());
-    auto status = context_.descriptor_pool_->AddFromFileDescriptorSet(
-        kTrackEventDescriptor.data(), kTrackEventDescriptor.size());
-
-    PERFETTO_DCHECK(status.ok());
-
-    status = context_.descriptor_pool_->AddFromFileDescriptorSet(
-        kChromeTrackEventDescriptor.data(), kChromeTrackEventDescriptor.size());
-
-    PERFETTO_DCHECK(status.ok());
-  }
-
-  context_.slice_tracker->SetOnSliceBeginCallback(
-      [this](TrackId track_id, SliceId slice_id) {
-        context_.flow_tracker->ClosePendingEventsOnTrack(track_id, slice_id);
-      });
+  context_.perf_sample_tracker.reset(new PerfSampleTracker(&context_));
 
   RegisterDefaultModules(&context_);
 }
@@ -109,11 +83,9 @@
   context_.event_tracker->FlushPendingEvents();
   context_.slice_tracker->FlushPendingSlices();
   context_.heap_profile_tracker->NotifyEndOfFile();
-  context_.process_tracker->NotifyEndOfFile();
   for (std::unique_ptr<ProtoImporterModule>& module : context_.modules) {
     module->NotifyEndOfFile();
   }
-  context_.args_tracker->Flush();
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/trace_sorter.h b/src/trace_processor/trace_sorter.h
index 614d627..a42e9b0 100644
--- a/src/trace_processor/trace_sorter.h
+++ b/src/trace_processor/trace_sorter.h
@@ -21,9 +21,9 @@
 
 #include "perfetto/ext/base/circular_queue.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_blob_view.h"
 
 namespace Json {
 class Value;
@@ -78,7 +78,8 @@
     MaybeExtractEvents(queue);
   }
 
-  inline void PushJsonValue(int64_t timestamp, std::string json_value) {
+  inline void PushJsonValue(int64_t timestamp,
+                            std::unique_ptr<Json::Value> json_value) {
     auto* queue = GetQueue(0);
     queue->Append(
         TimestampedTracePiece(timestamp, packet_idx_++, std::move(json_value)));
@@ -105,12 +106,10 @@
 
   inline void PushFtraceEvent(uint32_t cpu,
                               int64_t timestamp,
-                              TraceBlobView event,
-                              PacketSequenceState* state) {
+                              TraceBlobView event) {
     set_ftrace_batch_cpu_for_DCHECK(cpu);
-    GetQueue(cpu + 1)->Append(TimestampedTracePiece(
-        timestamp, packet_idx_++,
-        FtraceEventData{std::move(event), state->current_generation()}));
+    GetQueue(cpu + 1)->Append(
+        TimestampedTracePiece(timestamp, packet_idx_++, std::move(event)));
 
     // The caller must call FinalizeFtraceEventBatch() after having pushed a
     // batch of ftrace events. This is to amortize the overhead of handling
diff --git a/src/trace_processor/trace_sorter_unittest.cc b/src/trace_processor/trace_sorter_unittest.cc
index b49f515..a7b2fc7 100644
--- a/src/trace_processor/trace_sorter_unittest.cc
+++ b/src/trace_processor/trace_sorter_unittest.cc
@@ -49,9 +49,9 @@
                          int64_t timestamp,
                          TimestampedTracePiece ttp) override {
     bool isNonCompact = ttp.type == TimestampedTracePiece::Type::kFtraceEvent;
-    MOCK_ParseFtracePacket(
-        cpu, timestamp, isNonCompact ? ttp.ftrace_event.event.data() : nullptr,
-        isNonCompact ? ttp.ftrace_event.event.length() : 0);
+    MOCK_ParseFtracePacket(cpu, timestamp,
+                           isNonCompact ? ttp.ftrace_event.data() : nullptr,
+                           isNonCompact ? ttp.ftrace_event.length() : 0);
   }
 
   MOCK_METHOD3(MOCK_ParseTracePacket,
@@ -93,11 +93,10 @@
 };
 
 TEST_F(TraceSorterTest, TestFtrace) {
-  PacketSequenceState state(&context_);
   TraceBlobView view = test_buffer_.slice(0, 1);
   EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(0, 1000, view.data(), 1));
   context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
-                                   std::move(view), &state);
+                                   std::move(view));
   context_.sorter->FinalizeFtraceEventBatch(0);
   context_.sorter->ExtractEventsForced();
 }
@@ -127,12 +126,12 @@
 
   context_.sorter->SetWindowSizeNs(200);
   context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
-                                   std::move(view_4), &state);
+                                   std::move(view_4));
   context_.sorter->FinalizeFtraceEventBatch(2);
   context_.sorter->PushTracePacket(1001, &state, std::move(view_2));
   context_.sorter->PushTracePacket(1100, &state, std::move(view_3));
   context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
-                                   std::move(view_1), &state);
+                                   std::move(view_1));
 
   context_.sorter->FinalizeFtraceEventBatch(0);
   context_.sorter->ExtractEventsForced();
@@ -160,13 +159,13 @@
 
   context_.sorter->SetWindowSizeNs(200);
   context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
-                                   std::move(view_4), &state);
+                                   std::move(view_4));
   context_.sorter->FinalizeFtraceEventBatch(2);
   context_.sorter->PushTracePacket(1001, &state, std::move(view_2));
   context_.sorter->PushTracePacket(1100, &state, std::move(view_3));
 
   context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
-                                   std::move(view_1), &state);
+                                   std::move(view_1));
   context_.sorter->FinalizeFtraceEventBatch(0);
 
   // At this point, we should just flush the 1000 and 1001 packets.
@@ -189,7 +188,6 @@
 // Tests that the output of the TraceSorter matches the timestamp order
 // (% events happening at the same time on different CPUs).
 TEST_F(TraceSorterTest, MultiQueueSorting) {
-  PacketSequenceState state(&context_);
   std::minstd_rand0 rnd_engine(0);
   std::map<int64_t /*ts*/, std::vector<uint32_t /*cpu*/>> expectations;
 
@@ -217,8 +215,7 @@
     for (int j = 0; j < num_cpus; j++) {
       uint32_t cpu = static_cast<uint32_t>(rnd_engine() % 32);
       expectations[ts].push_back(cpu);
-      context_.sorter->PushFtraceEvent(cpu, ts, TraceBlobView(nullptr, 0, 0),
-                                       &state);
+      context_.sorter->PushFtraceEvent(cpu, ts, TraceBlobView(nullptr, 0, 0));
       context_.sorter->FinalizeFtraceEventBatch(cpu);
     }
   }
diff --git a/src/trace_processor/types/BUILD.gn b/src/trace_processor/types/BUILD.gn
index 46d16b9..a2a3a97 100644
--- a/src/trace_processor/types/BUILD.gn
+++ b/src/trace_processor/types/BUILD.gn
@@ -18,7 +18,6 @@
     "destructible.h",
     "gfp_flags.cc",
     "gfp_flags.h",
-    "softirq_action.h",
     "task_state.cc",
     "task_state.h",
     "trace_processor_context.h",
diff --git a/src/trace_processor/types/gfp_flags.cc b/src/trace_processor/types/gfp_flags.cc
index acb52fb..30a5932 100644
--- a/src/trace_processor/types/gfp_flags.cc
+++ b/src/trace_processor/types/gfp_flags.cc
@@ -208,7 +208,7 @@
   } else if (version >= VersionNumber{4, 4} && version < VersionNumber{4, 14}) {
     return &v4_4;
   } else {  // version >= 4.14
-    // TODO(hjd): Add newer kernel versions once we have access to them.
+    // TODO(taylori): Add newer kernel versions once we have access to them.
     return &v4_14;
   }
 }
diff --git a/src/trace_processor/types/softirq_action.h b/src/trace_processor/types/softirq_action.h
deleted file mode 100644
index 0e500e1..0000000
--- a/src/trace_processor/types/softirq_action.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TYPES_SOFTIRQ_ACTION_H_
-#define SRC_TRACE_PROCESSOR_TYPES_SOFTIRQ_ACTION_H_
-
-namespace perfetto {
-namespace trace_processor {
-
-static constexpr const char* const kActionNames[] = {
-    "HI",           "TIMER",   "NET_TX", "NET_RX",  "BLOCK",
-    "BLOCK_IOPOLL", "TASKLET", "SCHED",  "HRTIMER", "RCU"};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TYPES_SOFTIRQ_ACTION_H_
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index b2c63ba..2f188ad 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -27,7 +27,6 @@
 namespace trace_processor {
 
 class ArgsTracker;
-class AsyncTrackSetTracker;
 class AndroidProbesTracker;
 class ChunkedTraceReader;
 class ClockTracker;
@@ -35,21 +34,18 @@
 class ForwardingTraceParser;
 class FtraceModule;
 class GlobalArgsTracker;
-class GlobalStackProfileTracker;
 class HeapGraphTracker;
 class HeapProfileTracker;
-class PerfSampleTracker;
 class MetadataTracker;
+class PerfSampleTracker;
 class ProtoImporterModule;
 class ProcessTracker;
 class SliceTracker;
-class FlowTracker;
 class TraceParser;
 class TraceSorter;
 class TraceStorage;
 class TrackTracker;
 class JsonTracker;
-class DescriptorPool;
 
 class TraceProcessorContext {
  public:
@@ -70,16 +66,13 @@
   std::unique_ptr<ArgsTracker> args_tracker;
 
   std::unique_ptr<TrackTracker> track_tracker;
-  std::unique_ptr<AsyncTrackSetTracker> async_track_set_tracker;
   std::unique_ptr<SliceTracker> slice_tracker;
-  std::unique_ptr<FlowTracker> flow_tracker;
   std::unique_ptr<ProcessTracker> process_tracker;
   std::unique_ptr<EventTracker> event_tracker;
   std::unique_ptr<ClockTracker> clock_tracker;
   std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
-  std::unique_ptr<PerfSampleTracker> perf_sample_tracker;
-  std::unique_ptr<GlobalStackProfileTracker> global_stack_profile_tracker;
   std::unique_ptr<MetadataTracker> metadata_tracker;
+  std::unique_ptr<PerfSampleTracker> perf_sample_tracker;
 
   // These fields are stored as pointers to Destructible objects rather than
   // their actual type (a subclass of Destructible), as the concrete subclass
@@ -109,13 +102,9 @@
   std::unique_ptr<TraceParser> json_trace_parser;
   std::unique_ptr<TraceParser> fuchsia_trace_parser;
 
-  // This field contains the list of proto descriptors that can be used by
-  // reflection-based parsers.
-  std::unique_ptr<DescriptorPool> descriptor_pool_;
-
   // The module at the index N is registered to handle field id N in
   // TracePacket.
-  std::vector<std::vector<ProtoImporterModule*>> modules_by_field;
+  std::vector<ProtoImporterModule*> modules_by_field;
   std::vector<std::unique_ptr<ProtoImporterModule>> modules;
   FtraceModule* ftrace_module = nullptr;
 };
diff --git a/src/trace_processor/util/BUILD.gn b/src/trace_processor/util/BUILD.gn
index 02887ac..28f1781 100644
--- a/src/trace_processor/util/BUILD.gn
+++ b/src/trace_processor/util/BUILD.gn
@@ -14,13 +14,6 @@
 
 import("../../../gn/perfetto.gni")
 
-# Track event args parsing logic here is tentatitively planned to eventually
-# move to src/util and will be used to implement writing typed args in console
-# interceptor.
-# Do not add new dependencies to trace_processor code outside of this directory.
-#
-# TODO(altimin): Move it to src/util and use it in console interceptor.
-
 source_set("util") {
   sources = [ "status_macros.h" ]
   deps = [
@@ -36,12 +29,12 @@
   ]
   deps = [
     ":descriptors",
+    "..:track_event_descriptor",
     "../../../gn:default_deps",
     "../../../protos/perfetto/common:zero",
     "../../../protos/perfetto/trace/track_event:zero",
     "../../base",
     "../../protozero",
-    "../importers:gen_cc_track_event_descriptor",
   ]
 }
 
@@ -51,62 +44,24 @@
     "descriptors.h",
   ]
   deps = [
-    ":util",
+    "..:track_event_descriptor",
     "../../../gn:default_deps",
+    "../../../include/perfetto/trace_processor",
     "../../../protos/perfetto/common:zero",
-    "../../../protos/perfetto/trace_processor:zero",
-    "../../protozero",
-    "../importers:gen_cc_track_event_descriptor",
-  ]
-  public_deps = [ "../../base" ]
-}
-
-source_set("proto_to_args_parser") {
-  sources = [
-    "proto_to_args_parser.cc",
-    "proto_to_args_parser.h",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../protos/perfetto/common:zero",
-    "../../../protos/perfetto/trace/interned_data:zero",
-    "../../../protos/perfetto/trace_processor:zero",
-    "../../protozero",
-    "../importers:gen_cc_track_event_descriptor",
-  ]
-
-  public_deps = [
-    ":descriptors",
-    ":util",
     "../../base",
-
-    # TODO(altimin): Move InternedMessageView and TraceBlobView here and remove
-    # this dependency.
-    "../importers/common",
+    "../../protozero",
   ]
 }
 
 source_set("unittests") {
-  sources = [
-    "proto_to_args_parser_unittest.cc",
-    "protozero_to_text_unittests.cc",
-  ]
+  sources = [ "protozero_to_text_unittests.cc" ]
   testonly = true
   deps = [
-    ":descriptors",
-    ":proto_to_args_parser",
     ":protozero_to_text",
-    "..:gen_cc_test_messages_descriptor",
+    "..:track_event_descriptor",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
-    "../../../protos/perfetto/common:zero",
     "../../../protos/perfetto/trace/track_event:zero",
     "../../protozero",
-    "../../protozero:testing_messages_zero",
-    "../importers:gen_cc_track_event_descriptor",
-
-    # TODO(altimin): Move InternedMessageView and TraceBlobView here and remove
-    # this dependency.
-    "..:storage_minimal",
   ]
 }
diff --git a/src/trace_processor/util/descriptors.cc b/src/trace_processor/util/descriptors.cc
index b5b00e1..e75a77b 100644
--- a/src/trace_processor/util/descriptors.cc
+++ b/src/trace_processor/util/descriptors.cc
@@ -17,17 +17,16 @@
 #include "src/trace_processor/util/descriptors.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/protozero/field.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
+
 #include "protos/perfetto/common/descriptor.pbzero.h"
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-#include "src/trace_processor/util/status_macros.h"
 
 namespace perfetto {
 namespace trace_processor {
 
+namespace {
+
 FieldDescriptor CreateFieldFromDecoder(
-    const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder,
-    bool is_extension) {
+    const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder) {
   using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
   std::string type_name =
       f_decoder.has_type_name()
@@ -41,9 +40,11 @@
   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, is_extension);
+      f_decoder.label() == FieldDescriptorProto::LABEL_REPEATED);
 }
 
+}  // namespace
+
 base::Optional<uint32_t> DescriptorPool::ResolveShortType(
     const std::string& parent_path,
     const std::string& short_type) {
@@ -71,13 +72,10 @@
     protozero::ConstBytes field_desc_proto) {
   using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
   FieldDescriptorProto::Decoder f_decoder(field_desc_proto);
-  auto field = CreateFieldFromDecoder(f_decoder, true);
+  auto field = CreateFieldFromDecoder(f_decoder);
 
   auto extendee_name = base::StringView(f_decoder.extendee()).ToStdString();
-  if (extendee_name.empty()) {
-    return util::ErrStatus("Extendee name is empty");
-  }
-
+  PERFETTO_CHECK(!extendee_name.empty());
   if (extendee_name[0] != '.') {
     // Only prepend if the extendee is not fully qualified
     extendee_name = package_name + "." + extendee_name;
@@ -90,13 +88,10 @@
   return util::OkStatus();
 }
 
-util::Status DescriptorPool::AddNestedProtoDescriptors(
-    const std::string& file_name,
+void DescriptorPool::AddNestedProtoDescriptors(
     const std::string& package_name,
     base::Optional<uint32_t> parent_idx,
-    protozero::ConstBytes descriptor_proto,
-    std::vector<ExtensionInfo>* extensions,
-    bool merge_existing_messages) {
+    protozero::ConstBytes descriptor_proto) {
   protos::pbzero::DescriptorProto::Decoder decoder(descriptor_proto);
 
   auto parent_name =
@@ -104,70 +99,28 @@
   auto full_name =
       parent_name + "." + base::StringView(decoder.name()).ToStdString();
 
-  auto prev_idx = FindDescriptorIdx(full_name);
-  if (prev_idx.has_value() && !merge_existing_messages) {
-    const auto& existing_descriptor = descriptors_[*prev_idx];
-    return util::ErrStatus("%s: %s was already defined in file %s",
-                           file_name.c_str(), full_name.c_str(),
-                           existing_descriptor.file_name().c_str());
-  }
-  if (!prev_idx.has_value()) {
-    prev_idx = static_cast<unsigned int>(descriptors_.size());
-    ProtoDescriptor proto_descriptor(file_name, package_name, full_name,
-                                     ProtoDescriptor::Type::kMessage,
-                                     parent_idx);
-    descriptors_.emplace_back(std::move(proto_descriptor));
-  }
-  ProtoDescriptor& proto_descriptor = descriptors_[*prev_idx];
-  if (proto_descriptor.type() != ProtoDescriptor::Type::kMessage) {
-    return util::ErrStatus("%s was enum, redefined as message",
-                           full_name.c_str());
-  }
-
   using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
+  ProtoDescriptor proto_descriptor(package_name, full_name,
+                                   ProtoDescriptor::Type::kMessage, parent_idx);
   for (auto it = decoder.field(); it; ++it) {
     FieldDescriptorProto::Decoder f_decoder(*it);
-    auto field = CreateFieldFromDecoder(f_decoder, /*is_extension=*/false);
-    auto existing_field = proto_descriptor.FindFieldByTag(field.number());
-    if (!existing_field) {
-      proto_descriptor.AddField(std::move(field));
-    } else {
-      if (field.type() != existing_field->type()) {
-        return util::ErrStatus("Field %s is re-introduced with different type",
-                               field.name().c_str());
-      }
-      if (field.type() == FieldDescriptorProto::TYPE_MESSAGE &&
-          field.resolved_type_name() != existing_field->resolved_type_name()) {
-        return util::ErrStatus(
-            "Field %s is re-introduced with different type %s (was %s)",
-            field.name().c_str(), field.resolved_type_name().c_str(),
-            existing_field->resolved_type_name().c_str());
-      }
-    }
+    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.enum_type(); it; ++it) {
-    AddEnumProtoDescriptors(file_name, package_name, idx, *it,
-                            merge_existing_messages);
+    AddEnumProtoDescriptors(package_name, idx, *it);
   }
   for (auto it = decoder.nested_type(); it; ++it) {
-    RETURN_IF_ERROR(AddNestedProtoDescriptors(file_name, package_name, idx, *it,
-                                              extensions,
-                                              merge_existing_messages));
+    AddNestedProtoDescriptors(package_name, idx, *it);
   }
-  for (auto ext_it = decoder.extension(); ext_it; ++ext_it) {
-    extensions->emplace_back(package_name, *ext_it);
-  }
-  return util::OkStatus();
 }
 
-util::Status DescriptorPool::AddEnumProtoDescriptors(
-    const std::string& file_name,
+void DescriptorPool::AddEnumProtoDescriptors(
     const std::string& package_name,
     base::Optional<uint32_t> parent_idx,
-    protozero::ConstBytes descriptor_proto,
-    bool merge_existing_messages) {
+    protozero::ConstBytes descriptor_proto) {
   protos::pbzero::EnumDescriptorProto::Decoder decoder(descriptor_proto);
 
   auto parent_name =
@@ -175,80 +128,57 @@
   auto full_name =
       parent_name + "." + base::StringView(decoder.name()).ToStdString();
 
-  auto prev_idx = FindDescriptorIdx(full_name);
-  if (prev_idx.has_value() && !merge_existing_messages) {
-    const auto& existing_descriptor = descriptors_[*prev_idx];
-    return util::ErrStatus("%s: %s was already defined in file %s",
-                           file_name.c_str(), full_name.c_str(),
-                           existing_descriptor.file_name().c_str());
-  }
-  if (!prev_idx.has_value()) {
-    prev_idx = static_cast<unsigned int>(descriptors_.size());
-    ProtoDescriptor proto_descriptor(file_name, package_name, full_name,
-                                     ProtoDescriptor::Type::kEnum,
-                                     base::nullopt);
-    descriptors_.emplace_back(std::move(proto_descriptor));
-  }
-  ProtoDescriptor& proto_descriptor = descriptors_[*prev_idx];
-  if (proto_descriptor.type() != ProtoDescriptor::Type::kEnum) {
-    return util::ErrStatus("%s was message, redefined as enum",
-                           full_name.c_str());
-  }
-
+  ProtoDescriptor proto_descriptor(package_name, full_name,
+                                   ProtoDescriptor::Type::kEnum, base::nullopt);
   for (auto it = decoder.value(); it; ++it) {
     protos::pbzero::EnumValueDescriptorProto::Decoder enum_value(it->data(),
                                                                  it->size());
     proto_descriptor.AddEnumValue(enum_value.number(),
                                   enum_value.name().ToStdString());
   }
-
-  return util::OkStatus();
+  descriptors_.emplace_back(std::move(proto_descriptor));
 }
 
 util::Status DescriptorPool::AddFromFileDescriptorSet(
     const uint8_t* file_descriptor_set_proto,
-    size_t size,
-    bool merge_existing_messages) {
+    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);
-  std::vector<ExtensionInfo> extensions;
   for (auto it = proto.file(); it; ++it) {
     protos::pbzero::FileDescriptorProto::Decoder file(*it);
-    std::string file_name = file.name().ToStdString();
-    if (processed_files_.find(file_name) != processed_files_.end()) {
-      // This file has been loaded once already. Skip.
-      continue;
-    }
-    processed_files_.insert(file_name);
     std::string package = "." + base::StringView(file.package()).ToStdString();
     for (auto message_it = file.message_type(); message_it; ++message_it) {
-      RETURN_IF_ERROR(AddNestedProtoDescriptors(
-          file_name, package, base::nullopt, *message_it, &extensions,
-          merge_existing_messages));
+      AddNestedProtoDescriptors(package, base::nullopt, *message_it);
     }
     for (auto enum_it = file.enum_type(); enum_it; ++enum_it) {
-      AddEnumProtoDescriptors(file_name, package, base::nullopt, *enum_it,
-                              merge_existing_messages);
-    }
-    for (auto ext_it = file.extension(); ext_it; ++ext_it) {
-      extensions.emplace_back(package, *ext_it);
+      AddEnumProtoDescriptors(package, base::nullopt, *enum_it);
     }
   }
 
-  // Second pass: Add extension fields to the real protos.
-  for (const auto& extension : extensions) {
-    auto status = AddExtensionField(extension.first, extension.second);
-    if (!status.ok())
-      return status;
+  // 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& entry : *descriptor.mutable_fields()) {
-      auto& field = entry.second;
+    for (auto& field : *descriptor.mutable_fields()) {
       if (!field.resolved_type_name().empty())
         continue;
 
@@ -280,39 +210,11 @@
                                    : base::nullopt;
 }
 
-std::vector<uint8_t> DescriptorPool::SerializeAsDescriptorSet() {
-  protozero::HeapBuffered<protos::pbzero::DescriptorSet> descs;
-  for (auto& desc : descriptors()) {
-    protos::pbzero::DescriptorProto* proto_descriptor =
-        descs->add_descriptors();
-    proto_descriptor->set_name(desc.full_name());
-    for (auto& entry : desc.fields()) {
-      auto& field = entry.second;
-      protos::pbzero::FieldDescriptorProto* field_descriptor =
-          proto_descriptor->add_field();
-      field_descriptor->set_name(field.name());
-      field_descriptor->set_number(static_cast<int32_t>(field.number()));
-      // We do not support required fields. They will show up as optional
-      // after serialization.
-      field_descriptor->set_label(
-          field.is_repeated()
-              ? protos::pbzero::FieldDescriptorProto::LABEL_REPEATED
-              : protos::pbzero::FieldDescriptorProto::LABEL_OPTIONAL);
-      field_descriptor->set_type_name(field.resolved_type_name());
-      field_descriptor->set_type(
-          static_cast<protos::pbzero::FieldDescriptorProto_Type>(field.type()));
-    }
-  }
-  return descs.SerializeAsArray();
-}
-
-ProtoDescriptor::ProtoDescriptor(std::string file_name,
-                                 std::string package_name,
+ProtoDescriptor::ProtoDescriptor(std::string package_name,
                                  std::string full_name,
                                  Type type,
                                  base::Optional<uint32_t> parent_id)
-    : file_name_(std::move(file_name)),
-      package_name_(std::move(package_name)),
+    : package_name_(std::move(package_name)),
       full_name_(std::move(full_name)),
       type_(type),
       parent_id_(parent_id) {}
@@ -321,14 +223,12 @@
                                  uint32_t number,
                                  uint32_t type,
                                  std::string raw_type_name,
-                                 bool is_repeated,
-                                 bool is_extension)
+                                 bool is_repeated)
     : name_(std::move(name)),
       number_(number),
       type_(type),
       raw_type_name_(std::move(raw_type_name)),
-      is_repeated_(is_repeated),
-      is_extension_(is_extension) {}
+      is_repeated_(is_repeated) {}
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/util/descriptors.h b/src/trace_processor/util/descriptors.h
index 7108781..59ea48d 100644
--- a/src/trace_processor/util/descriptors.h
+++ b/src/trace_processor/util/descriptors.h
@@ -18,14 +18,12 @@
 #define SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_
 
 #include <algorithm>
-#include <set>
 #include <string>
-#include <unordered_map>
 #include <vector>
 
-#include "perfetto/base/status.h"
 #include "perfetto/ext/base/optional.h"
-#include "protos/perfetto/common/descriptor.pbzero.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "perfetto/trace_processor/status.h"
 
 namespace protozero {
 struct ConstBytes;
@@ -40,8 +38,7 @@
                   uint32_t number,
                   uint32_t type,
                   std::string raw_type_name,
-                  bool is_repeated,
-                  bool is_extension = false);
+                  bool is_repeated);
 
   const std::string& name() const { return name_; }
   uint32_t number() const { return number_; }
@@ -49,7 +46,6 @@
   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_; }
-  bool is_extension() const { return is_extension_; }
 
   void set_resolved_type_name(const std::string& resolved_type_name) {
     resolved_type_name_ = resolved_type_name;
@@ -62,96 +58,80 @@
   std::string raw_type_name_;
   std::string resolved_type_name_;
   bool is_repeated_;
-  bool is_extension_;
 };
 
-FieldDescriptor CreateFieldFromDecoder(
-    const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder,
-    bool is_extension);
-
 class ProtoDescriptor {
  public:
   enum class Type { kEnum = 0, kMessage = 1 };
 
-  ProtoDescriptor(std::string file_name,
-                  std::string package_name,
+  ProtoDescriptor(std::string package_name,
                   std::string full_name,
                   Type type,
                   base::Optional<uint32_t> parent_id);
 
   void AddField(FieldDescriptor descriptor) {
     PERFETTO_DCHECK(type_ == Type::kMessage);
-    fields_.emplace(descriptor.number(), std::move(descriptor));
+    fields_.emplace_back(std::move(descriptor));
   }
 
   void AddEnumValue(int32_t integer_representation,
                     std::string string_representation) {
     PERFETTO_DCHECK(type_ == Type::kEnum);
-    enum_values_[integer_representation] = std::move(string_representation);
+    enum_values_.emplace_back(integer_representation,
+                              std::move(string_representation));
   }
 
-  const FieldDescriptor* FindFieldByName(const std::string& name) const {
+  base::Optional<uint32_t> FindFieldIdxByName(const std::string& name) const {
     PERFETTO_DCHECK(type_ == Type::kMessage);
-    auto it =
-        std::find_if(fields_.begin(), fields_.end(),
-                     [name](std::pair<int32_t, const FieldDescriptor&> p) {
-                       return p.second.name() == name;
-                     });
-    if (it == fields_.end()) {
-      return nullptr;
-    }
-    return &it->second;
+    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 FieldDescriptor* FindFieldByTag(const uint32_t tag_number) const {
+  base::Optional<uint32_t> FindFieldIdxByTag(const uint16_t tag_number) const {
     PERFETTO_DCHECK(type_ == Type::kMessage);
-    auto it = fields_.find(tag_number);
-    if (it == fields_.end()) {
-      return nullptr;
-    }
-    return &it->second;
+    auto it = std::find_if(fields_.begin(), fields_.end(),
+                           [tag_number](const FieldDescriptor& desc) {
+                             return desc.number() == tag_number;
+                           });
+    auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it));
+    return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt;
   }
 
   base::Optional<std::string> FindEnumString(const int32_t value) const {
     PERFETTO_DCHECK(type_ == Type::kEnum);
-    auto it = enum_values_.find(value);
+    auto it =
+        std::find_if(enum_values_.begin(), enum_values_.end(),
+                     [value](const std::pair<int32_t, std::string>& enum_val) {
+                       return enum_val.first == value;
+                     });
     return it == enum_values_.end() ? base::nullopt
                                     : base::Optional<std::string>(it->second);
   }
 
-  const std::string& file_name() const { return file_name_; }
-
   const std::string& package_name() const { return package_name_; }
 
   const std::string& full_name() const { return full_name_; }
 
-  Type type() const { return type_; }
-
-  const std::unordered_map<uint32_t, FieldDescriptor>& fields() const {
-    return fields_;
-  }
-  std::unordered_map<uint32_t, FieldDescriptor>* mutable_fields() {
-    return &fields_;
-  }
+  const std::vector<FieldDescriptor>& fields() const { return fields_; }
+  std::vector<FieldDescriptor>* mutable_fields() { return &fields_; }
 
  private:
-  std::string file_name_;  // File in which descriptor was originally defined.
   std::string package_name_;
   std::string full_name_;
   const Type type_;
   base::Optional<uint32_t> parent_id_;
-  std::unordered_map<uint32_t, FieldDescriptor> fields_;
-  std::unordered_map<int32_t, std::string> enum_values_;
+  std::vector<FieldDescriptor> fields_;
+  std::vector<std::pair<int32_t, std::string>> enum_values_;
 };
 
-using ExtensionInfo = std::pair<std::string, protozero::ConstBytes>;
-
 class DescriptorPool {
  public:
-  base::Status AddFromFileDescriptorSet(
+  util::Status AddFromFileDescriptorSet(
       const uint8_t* file_descriptor_set_proto,
-      size_t size,
-      bool merge_existing_messages = false);
+      size_t size);
 
   base::Optional<uint32_t> FindDescriptorIdx(
       const std::string& full_name) const;
@@ -160,22 +140,15 @@
     return descriptors_;
   }
 
-  std::vector<uint8_t> SerializeAsDescriptorSet();
-
  private:
-  base::Status AddNestedProtoDescriptors(const std::string& file_name,
-                                         const std::string& package_name,
-                                         base::Optional<uint32_t> parent_idx,
-                                         protozero::ConstBytes descriptor_proto,
-                                         std::vector<ExtensionInfo>* extensions,
-                                         bool merge_existing_messages);
-  base::Status AddEnumProtoDescriptors(const std::string& file_name,
-                                       const std::string& package_name,
-                                       base::Optional<uint32_t> parent_idx,
-                                       protozero::ConstBytes descriptor_proto,
-                                       bool merge_existing_messages);
+  void AddNestedProtoDescriptors(const std::string& package_name,
+                                 base::Optional<uint32_t> parent_idx,
+                                 protozero::ConstBytes descriptor_proto);
+  void AddEnumProtoDescriptors(const std::string& package_name,
+                               base::Optional<uint32_t> parent_idx,
+                               protozero::ConstBytes descriptor_proto);
 
-  base::Status AddExtensionField(const std::string& package_name,
+  util::Status AddExtensionField(const std::string& package_name,
                                  protozero::ConstBytes field_desc_proto);
 
   // Recursively searches for the given short type in all parent messages
@@ -184,7 +157,6 @@
                                             const std::string& short_type);
 
   std::vector<ProtoDescriptor> descriptors_;
-  std::set<std::string> processed_files_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/util/proto_to_args_parser.cc b/src/trace_processor/util/proto_to_args_parser.cc
deleted file mode 100644
index 6fec35e..0000000
--- a/src/trace_processor/util/proto_to_args_parser.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/util/proto_to_args_parser.h"
-
-#include "protos/perfetto/common/descriptor.pbzero.h"
-#include "src/trace_processor/util/descriptors.h"
-#include "src/trace_processor/util/status_macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace util {
-
-namespace {
-
-// ScopedStringAppender will add |append| to |dest| when constructed and
-// erases the appended suffix from |dest| when it goes out of scope. Thus
-// |dest| must be valid for the entire lifetime of ScopedStringAppender.
-//
-// This is useful as we descend into a proto since the column names just
-// appended with ".field_name" as we go lower.
-//
-// I.E. message1.message2.field_name1 is a column, but we'll then need to
-// append message1.message2.field_name2 afterwards so we only need to append
-// "field_name1" within some scope.
-class ScopedStringAppender {
- public:
-  ScopedStringAppender(const std::string& append, std::string* dest)
-      : old_size_(dest->size()), dest_(dest) {
-    if (dest->empty()) {
-      dest_->reserve(append.size());
-    } else {
-      dest_->reserve(old_size_ + 1 + append.size());
-      dest_->append(".");
-    }
-    dest_->append(append);
-  }
-  ~ScopedStringAppender() { dest_->erase(old_size_); }
-
- private:
-  size_t old_size_;
-  std::string* dest_;
-};
-
-}  // namespace
-
-ProtoToArgsParser::Key::Key() = default;
-ProtoToArgsParser::Key::Key(const std::string& k) : flat_key(k), key(k) {}
-ProtoToArgsParser::Key::Key(const std::string& fk, const std::string& k)
-    : flat_key(fk), key(k) {}
-ProtoToArgsParser::Key::~Key() = default;
-
-ProtoToArgsParser::Delegate::~Delegate() = default;
-
-ProtoToArgsParser::ProtoToArgsParser(const DescriptorPool& pool) : pool_(pool) {
-  constexpr int kDefaultSize = 64;
-  key_prefix_.key.reserve(kDefaultSize);
-  key_prefix_.flat_key.reserve(kDefaultSize);
-}
-
-base::Status ProtoToArgsParser::ParseMessage(
-    const protozero::ConstBytes& cb,
-    const std::string& type,
-    const std::vector<uint16_t>* allowed_fields,
-    Delegate& delegate) {
-  auto idx = pool_.FindDescriptorIdx(type);
-  if (!idx) {
-    return base::Status("Failed to find proto descriptor");
-  }
-
-  auto& descriptor = pool_.descriptors()[*idx];
-
-  std::unordered_map<size_t, int> repeated_field_index;
-
-  protozero::ProtoDecoder decoder(cb);
-  for (protozero::Field f = decoder.ReadField(); f.valid();
-       f = decoder.ReadField()) {
-    auto field = descriptor.FindFieldByTag(f.id());
-    if (!field) {
-      // Unknown field, possibly an unknown extension.
-      continue;
-    }
-
-    // If allowlist is not provided, reflect all fields. Otherwise, check if the
-    // current field either an extension or is in allowlist.
-    bool is_allowed = field->is_extension() || !allowed_fields ||
-                      std::find(allowed_fields->begin(), allowed_fields->end(),
-                                f.id()) != allowed_fields->end();
-
-    if (!is_allowed) {
-      // Field is neither an extension, nor is allowed to be
-      // reflected.
-      continue;
-    }
-    RETURN_IF_ERROR(
-        ParseField(*field, repeated_field_index[f.id()], f, delegate));
-    if (field->is_repeated()) {
-      repeated_field_index[f.id()]++;
-    }
-  }
-
-  return base::OkStatus();
-}
-
-base::Status ProtoToArgsParser::ParseField(
-    const FieldDescriptor& field_descriptor,
-    int repeated_field_number,
-    protozero::Field field,
-    Delegate& delegate) {
-  std::string prefix_part = field_descriptor.name();
-  if (field_descriptor.is_repeated()) {
-    std::string number = std::to_string(repeated_field_number);
-    prefix_part.reserve(prefix_part.length() + number.length() + 2);
-    prefix_part.append("[");
-    prefix_part.append(number);
-    prefix_part.append("]");
-  }
-
-  // In the args table we build up message1.message2.field1 as the column
-  // name. This will append the ".field1" suffix to |key_prefix| and then
-  // remove it when it goes out of scope.
-  ScopedStringAppender scoped_prefix(prefix_part, &key_prefix_.key);
-  ScopedStringAppender scoped_flat_key_prefix(field_descriptor.name(),
-                                              &key_prefix_.flat_key);
-
-  // If we have an override parser then use that instead and move onto the
-  // next loop.
-  if (base::Optional<base::Status> status =
-          MaybeApplyOverride(field, delegate)) {
-    return *status;
-  }
-
-  // If this is not a message we can just immediately add the column name and
-  // get the value out of |field|. However if it is a message we need to
-  // recurse into it.
-  if (field_descriptor.type() ==
-      protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
-    return ParseMessage(field.as_bytes(), field_descriptor.resolved_type_name(),
-                        nullptr, delegate);
-  }
-
-  return ParseSimpleField(field_descriptor, field, delegate);
-}
-
-void ProtoToArgsParser::AddParsingOverride(std::string field,
-                                           ParsingOverride func) {
-  overrides_[std::move(field)] = std::move(func);
-}
-
-base::Optional<base::Status> ProtoToArgsParser::MaybeApplyOverride(
-    const protozero::Field& field,
-    Delegate& delegate) {
-  auto it = overrides_.find(key_prefix_.flat_key);
-  if (it == overrides_.end())
-    return base::nullopt;
-  return it->second(field, delegate);
-}
-
-base::Status ProtoToArgsParser::ParseSimpleField(
-    const FieldDescriptor& descriptor,
-    const protozero::Field& field,
-    Delegate& delegate) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  switch (descriptor.type()) {
-    case FieldDescriptorProto::TYPE_INT32:
-    case FieldDescriptorProto::TYPE_SFIXED32:
-    case FieldDescriptorProto::TYPE_FIXED32:
-      delegate.AddInteger(key_prefix_, field.as_int32());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_SINT32:
-      delegate.AddInteger(key_prefix_, field.as_sint32());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_INT64:
-    case FieldDescriptorProto::TYPE_SFIXED64:
-    case FieldDescriptorProto::TYPE_FIXED64:
-      delegate.AddInteger(key_prefix_, field.as_int64());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_SINT64:
-      delegate.AddInteger(key_prefix_, field.as_sint64());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_UINT32:
-      delegate.AddUnsignedInteger(key_prefix_, field.as_uint32());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_UINT64:
-      delegate.AddUnsignedInteger(key_prefix_, field.as_uint64());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_BOOL:
-      delegate.AddBoolean(key_prefix_, field.as_bool());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_DOUBLE:
-      delegate.AddDouble(key_prefix_, field.as_double());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_FLOAT:
-      delegate.AddDouble(key_prefix_, static_cast<double>(field.as_float()));
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_STRING:
-      delegate.AddString(key_prefix_, field.as_string());
-      return base::OkStatus();
-    case FieldDescriptorProto::TYPE_ENUM: {
-      auto opt_enum_descriptor_idx =
-          pool_.FindDescriptorIdx(descriptor.resolved_type_name());
-      if (!opt_enum_descriptor_idx) {
-        delegate.AddInteger(key_prefix_, field.as_int32());
-        return base::OkStatus();
-      }
-      auto opt_enum_string =
-          pool_.descriptors()[*opt_enum_descriptor_idx].FindEnumString(
-              field.as_int32());
-      if (!opt_enum_string) {
-        // Fall back to the integer representation of the field.
-        delegate.AddInteger(key_prefix_, field.as_int32());
-        return base::OkStatus();
-      }
-      delegate.AddString(key_prefix_,
-                         protozero::ConstChars{opt_enum_string->data(),
-                                               opt_enum_string->size()});
-      return base::OkStatus();
-    }
-    default:
-      return base::ErrStatus(
-          "Tried to write value of type field %s (in proto type "
-          "%s) which has type enum %d",
-          descriptor.name().c_str(), descriptor.resolved_type_name().c_str(),
-          descriptor.type());
-  }
-}
-
-}  // namespace util
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/util/proto_to_args_parser.h b/src/trace_processor/util/proto_to_args_parser.h
deleted file mode 100644
index f99179c..0000000
--- a/src/trace_processor/util/proto_to_args_parser.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_UTIL_PROTO_TO_ARGS_PARSER_H_
-#define SRC_TRACE_PROCESSOR_UTIL_PROTO_TO_ARGS_PARSER_H_
-
-#include "perfetto/base/status.h"
-#include "perfetto/protozero/field.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "src/trace_processor/util/descriptors.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// TODO(altimin): Move InternedMessageView into trace_processor/util.
-class InternedMessageView;
-
-namespace util {
-
-// ProtoToArgsParser encapsulates the process of taking an arbitrary proto and
-// parsing it into key-value arg pairs. This is done by traversing
-// the proto using reflection (with descriptors from |descriptor_pool|)
-// and passing the parsed data to |Delegate| callbacks.
-//
-// E.g. given a proto like
-//
-// package perfetto.protos;
-// message SubMessage {
-//   optional int32 field = 1;
-// }
-// message MainMessage {
-//   optional int32 field1 = 1;
-//   optional string field2 = 2;
-//   optional SubMessage field3 = 3;
-// }
-//
-// We will get the args set columns "field1", "field2", "field3.field" and will
-// store the values found inside as the result.
-//
-// Usage of this is as follows:
-//
-// DescriptorPool pool;
-// ProtoToArgsParser parser(&pool);
-// pool.AddProtoFileDescriptor(
-//     /* provide descriptor generated by tools/gen_binary_descriptors */);
-// parser.ParseMessage(const_bytes, ".perfetto.protos.MainMessage",
-//     /* fields */, /* delegate */);
-class ProtoToArgsParser {
- public:
-  explicit ProtoToArgsParser(const DescriptorPool& descriptor_pool);
-
-  struct Key {
-    Key(const std::string& flat_key, const std::string& key);
-    Key(const std::string& key);
-    Key();
-    ~Key();
-
-    std::string flat_key;
-    std::string key;
-  };
-
-  class Delegate {
-   public:
-    virtual ~Delegate();
-
-    virtual void AddInteger(const Key& key, int64_t value) = 0;
-    virtual void AddUnsignedInteger(const Key& key, uint64_t value) = 0;
-    virtual void AddString(const Key& key,
-                           const protozero::ConstChars& value) = 0;
-    virtual void AddDouble(const Key& key, double value) = 0;
-    virtual void AddPointer(const Key& key, const void* value) = 0;
-    virtual void AddBoolean(const Key& key, bool value) = 0;
-    virtual void AddJson(const Key& key,
-                         const protozero::ConstChars& value) = 0;
-
-    template <typename FieldMetadata>
-    typename FieldMetadata::cpp_field_type::Decoder* GetInternedMessage(
-        protozero::proto_utils::internal::FieldMetadataHelper<FieldMetadata>,
-        uint64_t iid) {
-      static_assert(std::is_base_of<protozero::proto_utils::FieldMetadataBase,
-                                    FieldMetadata>::value,
-                    "Field metadata should be a subclass of FieldMetadataBase");
-      static_assert(std::is_same<typename FieldMetadata::message_type,
-                                 protos::pbzero::InternedData>::value,
-                    "Field should belong to InternedData proto");
-      return GetInternedMessageView(FieldMetadata::kFieldId, iid)
-          ->template GetOrCreateDecoder<
-              typename FieldMetadata::cpp_field_type>();
-    }
-
-   protected:
-    virtual InternedMessageView* GetInternedMessageView(uint32_t field_id,
-                                                        uint64_t iid) = 0;
-  };
-
-  using ParsingOverride =
-      std::function<base::Optional<base::Status>(const protozero::Field&,
-                                                 Delegate& delegate)>;
-
-  // Installs an override for the field at the specified path. We will invoke
-  // |parsing_override| when the field is encountered.
-  //
-  // The return value of |parsing_override| indicates whether the override
-  // parsed the sub-message and ProtoToArgsParser should skip it (base::nullopt)
-  // or the sub-message should continue to be parsed by ProtoToArgsParser using
-  // the descriptor (base::Status).
-  //
-  // Note |field_path| must be the full path separated by periods. I.E. in the
-  // proto
-  //
-  // message SubMessage {
-  //   optional int32 field = 1;
-  // }
-  // message MainMessage {
-  //   optional SubMessage field1 = 1;
-  //   optional SubMessage field2 = 2;
-  // }
-  //
-  // To override the handling of both SubMessage fields you must add two parsing
-  // overrides. One with a |field_path| == "field1.field" and another with
-  // "field2.field".
-  void AddParsingOverride(std::string field_path,
-                          ParsingOverride parsing_override);
-
-  // Given a view of bytes that represent a serialized protozero message of
-  // |type| we will parse each field.
-  //
-  // Returns on any error with a status describing the problem. However any
-  // added values before encountering the error will be parsed and forwarded to
-  // the delegate.
-  //
-  // Fields with ids given in |fields| are parsed using reflection, as well
-  // as known (previously registered) extension fields. If |allowed_fields| is a
-  // nullptr, all fields are going to be parsed.
-  //
-  // Note:
-  // |type| must be the fully qualified name, but with a '.' added to the
-  // beginning. I.E. ".perfetto.protos.TrackEvent". And must match one of the
-  // descriptors already added through |AddProtoFileDescriptor|.
-  //
-  // IMPORTANT: currently bytes fields are not supported.
-  //
-  // TODO(b/145578432): Add support for byte fields.
-  base::Status ParseMessage(const protozero::ConstBytes& cb,
-                            const std::string& type,
-                            const std::vector<uint16_t>* allowed_fields,
-                            Delegate& delegate);
-
- private:
-  base::Status ParseField(const FieldDescriptor& field_descriptor,
-                          int repeated_field_number,
-                          protozero::Field field,
-                          Delegate& delegate);
-
-  base::Optional<base::Status> MaybeApplyOverride(const protozero::Field&,
-                                                  Delegate& delegate);
-
-  base::Status ParseSimpleField(const FieldDescriptor& desciptor,
-                                const protozero::Field& field,
-                                Delegate& delegate);
-
-  std::unordered_map<std::string, ParsingOverride> overrides_;
-  const DescriptorPool& pool_;
-  Key key_prefix_;
-};
-
-}  // namespace util
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_UTIL_PROTO_TO_ARGS_PARSER_H_
diff --git a/src/trace_processor/util/proto_to_args_parser_unittest.cc b/src/trace_processor/util/proto_to_args_parser_unittest.cc
deleted file mode 100644
index 89ee945..0000000
--- a/src/trace_processor/util/proto_to_args_parser_unittest.cc
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/util/proto_to_args_parser.h"
-
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/common/descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
-#include "src/protozero/test/example_proto/test_messages.pbzero.h"
-#include "src/trace_processor/importers/common/trace_blob_view.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/test_messages.descriptor.h"
-#include "test/gtest_and_gmock.h"
-
-#include <sstream>
-
-namespace perfetto {
-namespace trace_processor {
-namespace util {
-namespace {
-
-constexpr size_t kChunkSize = 42;
-
-using ::testing::_;
-using ::testing::Eq;
-using ::testing::Invoke;
-using ::testing::NiceMock;
-
-class ProtoToArgsParserTest : public ::testing::Test,
-                              public ProtoToArgsParser::Delegate {
- protected:
-  ProtoToArgsParserTest() {}
-
-  const std::vector<std::string>& args() const { return args_; }
-
-  void AddInternedSourceLocation(uint64_t iid, TraceBlobView data) {
-    interned_source_locations_[iid] = std::unique_ptr<InternedMessageView>(
-        new InternedMessageView(std::move(data)));
-  }
-
- private:
-  using Key = ProtoToArgsParser::Key;
-
-  void AddInteger(const Key& key, int64_t value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << value;
-    args_.push_back(ss.str());
-  }
-
-  void AddUnsignedInteger(const Key& key, uint64_t value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << value;
-    args_.push_back(ss.str());
-  }
-
-  void AddString(const Key& key, const protozero::ConstChars& value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << value.ToStdString();
-    args_.push_back(ss.str());
-  }
-
-  void AddDouble(const Key& key, double value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << value;
-    args_.push_back(ss.str());
-  }
-
-  void AddPointer(const Key& key, const void* value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << std::hex
-       << reinterpret_cast<uintptr_t>(value) << std::dec;
-    args_.push_back(ss.str());
-  }
-
-  void AddBoolean(const Key& key, bool value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << (value ? "true" : "false");
-    args_.push_back(ss.str());
-  }
-
-  void AddJson(const Key& key, const protozero::ConstChars& value) override {
-    std::stringstream ss;
-    ss << key.flat_key << " " << key.key << " " << std::hex
-       << value.ToStdString() << std::dec;
-    args_.push_back(ss.str());
-  }
-
-  InternedMessageView* GetInternedMessageView(uint32_t field_id,
-                                              uint64_t iid) override {
-    if (field_id != protos::pbzero::InternedData::kSourceLocationsFieldNumber)
-      return nullptr;
-    return interned_source_locations_.at(iid).get();
-  }
-
-  std::vector<std::string> args_;
-  std::map<uint64_t, std::unique_ptr<InternedMessageView>>
-      interned_source_locations_;
-};
-
-TEST_F(ProtoToArgsParserTest, EnsureTestMessageProtoParses) {
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-}
-
-TEST_F(ProtoToArgsParserTest, BasicSingleLayerProto) {
-  using namespace protozero::test::protos::pbzero;
-  protozero::HeapBuffered<EveryField> msg{kChunkSize, kChunkSize};
-  msg->set_field_int32(-1);
-  msg->set_field_int64(-333123456789ll);
-  msg->set_field_uint32(600);
-  msg->set_field_uint64(333123456789ll);
-  msg->set_field_sint32(-5);
-  msg->set_field_sint64(-9000);
-  msg->set_field_fixed32(12345);
-  msg->set_field_fixed64(444123450000ll);
-  msg->set_field_sfixed32(-69999);
-  msg->set_field_sfixed64(-200);
-  msg->set_field_double(0.5555);
-  msg->set_field_bool(true);
-  msg->set_small_enum(SmallEnum::TO_BE);
-  msg->set_signed_enum(SignedEnum::NEGATIVE);
-  msg->set_big_enum(BigEnum::BEGIN);
-  msg->set_nested_enum(EveryField::PONG);
-  msg->set_field_float(3.14f);
-  msg->set_field_string("FizzBuzz");
-  msg->add_repeated_int32(1);
-  msg->add_repeated_int32(-1);
-  msg->add_repeated_int32(100);
-  msg->add_repeated_int32(2000000);
-
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.EveryField", nullptr, *this);
-
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-
-  EXPECT_THAT(
-      args(),
-      testing::ElementsAre(
-          "field_int32 field_int32 -1", "field_int64 field_int64 -333123456789",
-          "field_uint32 field_uint32 600",
-          "field_uint64 field_uint64 333123456789",
-          "field_sint32 field_sint32 -5", "field_sint64 field_sint64 -9000",
-          "field_fixed32 field_fixed32 12345",
-          "field_fixed64 field_fixed64 444123450000",
-          "field_sfixed32 field_sfixed32 -69999",
-          "field_sfixed64 field_sfixed64 -200",
-          "field_double field_double 0.5555", "field_bool field_bool true",
-          "small_enum small_enum TO_BE", "signed_enum signed_enum NEGATIVE",
-          "big_enum big_enum BEGIN", "nested_enum nested_enum PONG",
-          "field_float field_float 3.14", "field_string field_string FizzBuzz",
-          "repeated_int32 repeated_int32[0] 1",
-          "repeated_int32 repeated_int32[1] -1",
-          "repeated_int32 repeated_int32[2] 100",
-          "repeated_int32 repeated_int32[3] 2000000"));
-}
-
-TEST_F(ProtoToArgsParserTest, NestedProto) {
-  using namespace protozero::test::protos::pbzero;
-  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
-  msg->set_super_nested()->set_value_c(3);
-
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.NestedA", nullptr, *this);
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-  EXPECT_THAT(args(), testing::ElementsAre(
-                          "super_nested.value_c super_nested.value_c 3"));
-}
-
-TEST_F(ProtoToArgsParserTest, CamelCaseFieldsProto) {
-  using namespace protozero::test::protos::pbzero;
-  protozero::HeapBuffered<CamelCaseFields> msg{kChunkSize, kChunkSize};
-  msg->set_barbaz(true);
-  msg->set_moomoo(true);
-  msg->set___bigbang(true);
-
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.CamelCaseFields", nullptr, *this);
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-  EXPECT_THAT(args(),
-              testing::ElementsAre("barBaz barBaz true", "MooMoo MooMoo true",
-                                   "__bigBang __bigBang true"));
-}
-
-TEST_F(ProtoToArgsParserTest, NestedProtoParsingOverrideHandled) {
-  using namespace protozero::test::protos::pbzero;
-  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
-  msg->set_super_nested()->set_value_c(3);
-
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  parser.AddParsingOverride(
-      "super_nested.value_c",
-      [](const protozero::Field& field, ProtoToArgsParser::Delegate& writer) {
-        EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
-        std::string key = "super_nested.value_b.replaced";
-        writer.AddInteger({key, key}, field.as_int32());
-        // We've handled this field by adding the desired args.
-        return base::OkStatus();
-      });
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.NestedA", nullptr, *this);
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-  EXPECT_THAT(
-      args(),
-      testing::ElementsAre(
-          "super_nested.value_b.replaced super_nested.value_b.replaced 3"));
-}
-
-TEST_F(ProtoToArgsParserTest, NestedProtoParsingOverrideSkipped) {
-  using namespace protozero::test::protos::pbzero;
-  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
-  msg->set_super_nested()->set_value_c(3);
-
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ProtoToArgsParser parser(pool);
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  parser.AddParsingOverride(
-      "super_nested.value_c",
-      [](const protozero::Field& field, ProtoToArgsParser::Delegate&) {
-        static int val = 0;
-        ++val;
-        EXPECT_EQ(1, val);
-        EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
-        return base::nullopt;
-      });
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.NestedA", nullptr, *this);
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-  EXPECT_THAT(args(), testing::ElementsAre(
-                          "super_nested.value_c super_nested.value_c 3"));
-}
-
-TEST_F(ProtoToArgsParserTest, LookingUpInternedStateParsingOverride) {
-  using namespace protozero::test::protos::pbzero;
-  // The test proto, we will use |value_c| as the source_location iid.
-  protozero::HeapBuffered<NestedA> msg{kChunkSize, kChunkSize};
-  msg->set_super_nested()->set_value_c(3);
-  auto binary_proto = msg.SerializeAsArray();
-
-  // The interned source location.
-  protozero::HeapBuffered<protos::pbzero::SourceLocation> src_loc{kChunkSize,
-                                                                  kChunkSize};
-  const uint64_t kIid = 3;
-  src_loc->set_iid(kIid);
-  src_loc->set_file_name("test_file_name");
-  // We need to update sequence_state to point to it.
-  auto binary_data = src_loc.SerializeAsArray();
-  std::unique_ptr<uint8_t[]> buffer(new uint8_t[binary_data.size()]);
-  for (size_t i = 0; i < binary_data.size(); ++i) {
-    buffer.get()[i] = binary_data[i];
-  }
-  TraceBlobView blob(std::move(buffer), 0, binary_data.size());
-  AddInternedSourceLocation(kIid, std::move(blob));
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTestMessagesDescriptor.data(),
-                                              kTestMessagesDescriptor.size());
-  ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
-                           << status.message();
-
-  ProtoToArgsParser parser(pool);
-  // Now we override the behaviour of |value_c| so we can expand the iid into
-  // multiple args rows.
-  parser.AddParsingOverride(
-      "super_nested.value_c",
-      [](const protozero::Field& field, ProtoToArgsParser::Delegate& delegate)
-          -> base::Optional<base::Status> {
-        auto* decoder = delegate.GetInternedMessage(
-            protos::pbzero::InternedData::kSourceLocations, field.as_uint64());
-        if (!decoder) {
-          // Lookup failed fall back on default behaviour.
-          return base::nullopt;
-        }
-        delegate.AddString(ProtoToArgsParser::Key("file_name"),
-                           protozero::ConstChars{"file", 4});
-        delegate.AddInteger(ProtoToArgsParser::Key("line_number"), 2);
-        return base::OkStatus();
-      });
-
-  status = parser.ParseMessage(
-      protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
-      ".protozero.test.protos.NestedA", nullptr, *this);
-  EXPECT_TRUE(status.ok())
-      << "InternProtoFieldsIntoArgsTable failed with error: "
-      << status.message();
-  EXPECT_THAT(args(), testing::ElementsAre("file_name file_name file",
-                                           "line_number line_number 2"));
-}
-
-}  // namespace
-}  // namespace util
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/util/proto_to_json.cc b/src/trace_processor/util/proto_to_json.cc
index ff430c7..6befd5e 100644
--- a/src/trace_processor/util/proto_to_json.cc
+++ b/src/trace_processor/util/proto_to_json.cc
@@ -30,6 +30,42 @@
 
 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,
@@ -44,7 +80,7 @@
                                 ? ref->GetRepeatedBool(message, field_desc, idx)
                                 : ref->GetBool(message, field_desc));
     case FieldDescriptor::CppType::CPPTYPE_ENUM:
-      return base::QuoteAndEscapeControlCodes(
+      return EscapeJsonString(
           is_repeated ? ref->GetRepeatedEnum(message, field_desc, idx)->name()
                       : ref->GetEnum(message, field_desc)->name());
     case FieldDescriptor::CppType::CPPTYPE_FLOAT:
@@ -66,7 +102,7 @@
           is_repeated ? ref->GetRepeatedDouble(message, field_desc, idx)
                       : ref->GetDouble(message, field_desc));
     case FieldDescriptor::CppType::CPPTYPE_STRING:
-      return base::QuoteAndEscapeControlCodes(
+      return EscapeJsonString(
           is_repeated ? ref->GetRepeatedString(message, field_desc, idx)
                       : ref->GetString(message, field_desc));
     case FieldDescriptor::CppType::CPPTYPE_UINT32:
@@ -193,12 +229,12 @@
       }
       std::string nested_fields =
           NestedMessageFieldOptionsToJson(message, field_desc, indent + 2);
-      if (!nested_fields.empty()) {
+      if (nested_fields != "") {
         field_entries.push_back(std::move(nested_fields));
       }
       // We don't output annotations for a field if that field and all its
       // descendants have no field options.
-      if (!field_entries.empty()) {
+      if (field_entries.size() > 0) {
         if (field_desc->is_repeated()) {
           field_entries.push_back(std::string(indent, ' ') +
                                   R"("__repeated": true)");
@@ -273,13 +309,13 @@
   ret = "{" + MessageFieldsToJson(message, indent + 2);
   std::string annotation_fields =
       options_converter.MessageFieldOptionsToJson(message, indent + 4);
-  if (annotation_fields.empty()) {
-    ret += "\n";
-  } else {
+  if (annotation_fields != "") {
     ret += ",\n";
     ret += std::string(indent + 2, ' ') + "\"__annotations\": {\n";
     ret += annotation_fields + "\n";
     ret += std::string(indent + 2, ' ') + "}\n";
+  } else {
+    ret += "\n";
   }
   ret += std::string(indent, ' ') + "}\n";
   return ret;
diff --git a/src/trace_processor/util/protozero_to_text.cc b/src/trace_processor/util/protozero_to_text.cc
index 43cf9b5..cc0f659 100644
--- a/src/trace_processor/util/protozero_to_text.cc
+++ b/src/trace_processor/util/protozero_to_text.cc
@@ -1,6 +1,5 @@
 #include "src/trace_processor/util/protozero_to_text.h"
 
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "perfetto/protozero/proto_utils.h"
@@ -8,28 +7,12 @@
 #include "src/trace_processor/util/descriptors.h"
 
 // This is the highest level that this protozero to text supports.
-#include "src/trace_processor/importers/track_event.descriptor.h"
+#include "src/trace_processor/importers/proto/track_event.descriptor.h"
 
 namespace perfetto {
 namespace trace_processor {
-namespace protozero_to_text {
-
 namespace {
 
-std::string BytesToHexEncodedString(const std::string& bytes) {
-  // Each byte becomes four chars 'A' -> "\x41" + 1 for trailing null.
-  std::string value(4 * bytes.size() + 1, 'Z');
-  for (size_t i = 0; i < bytes.size(); ++i) {
-    // snprintf prints 5 characters: '\x', then two hex digits, and finally a
-    // null byte. As we write left to right, we keep overwriting the null
-    // byte, except for the last call to snprintf.
-    snprintf(&(value[4 * i]), 5, "\\x%02hhx", bytes[i]);
-  }
-  // Trim trailing null.
-  value.resize(4 * bytes.size());
-  return value;
-}
-
 // Recursively determine the size of all the string like things passed in the
 // parameter pack |rest|.
 size_t SizeOfStr() {
@@ -70,7 +53,7 @@
                                            const protozero::Field& field,
                                            const std::string& separator,
                                            const std::string& indent,
-                                           const DescriptorPool& pool,
+                                           DescriptorPool* pool,
                                            std::string* out) {
   using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
   switch (fd.type()) {
@@ -114,22 +97,15 @@
       StrAppend(out, separator, indent, fd.name(), ": ",
                 std::to_string(field.as_float()));
       return;
-    case FieldDescriptorProto::TYPE_STRING: {
-      auto s = base::QuoteAndEscapeControlCodes(field.as_std_string());
-      StrAppend(out, separator, indent, fd.name(), ": ", s);
+    case FieldDescriptorProto::TYPE_STRING:
+      StrAppend(out, separator, indent, fd.name(), ": ", field.as_std_string());
       return;
-    }
-    case FieldDescriptorProto::TYPE_BYTES: {
-      std::string value = BytesToHexEncodedString(field.as_std_string());
-      StrAppend(out, separator, indent, fd.name(), ": \"", value, "\"");
-      return;
-    }
     case FieldDescriptorProto::TYPE_ENUM: {
       auto opt_enum_descriptor_idx =
-          pool.FindDescriptorIdx(fd.resolved_type_name());
+          pool->FindDescriptorIdx(fd.resolved_type_name());
       PERFETTO_DCHECK(opt_enum_descriptor_idx);
       auto opt_enum_string =
-          pool.descriptors()[*opt_enum_descriptor_idx].FindEnumString(
+          pool->descriptors()[*opt_enum_descriptor_idx].FindEnumString(
               field.as_int32());
       PERFETTO_DCHECK(opt_enum_string);
       StrAppend(out, separator, indent, fd.name(), ": ", *opt_enum_string);
@@ -142,6 +118,7 @@
           fd.name().c_str(), fd.resolved_type_name().c_str(), fd.type());
     }
   }
+  return;
 }
 
 void IncreaseIndents(std::string* out) {
@@ -157,28 +134,26 @@
 // |type| and will use |pool| to look up the |type|. All output will be placed
 // in |output| and between fields |separator| will be placed. When called for
 // |indents| will be increased by 2 spaces to improve readability.
-void ProtozeroToTextInternal(const std::string& type,
-                             protozero::ConstBytes protobytes,
-                             NewLinesMode new_lines_mode,
-                             const DescriptorPool& pool,
-                             std::string* indents,
-                             std::string* output) {
-  auto opt_proto_descriptor_idx = pool.FindDescriptorIdx(type);
+void ProtozeroToText(const std::string& type,
+                     protozero::ConstBytes protobytes,
+                     bool include_new_lines,
+                     DescriptorPool* pool,
+                     std::string* indents,
+                     std::string* output) {
+  auto opt_proto_descriptor_idx = pool->FindDescriptorIdx(type);
   PERFETTO_DCHECK(opt_proto_descriptor_idx);
-  auto& proto_descriptor = pool.descriptors()[*opt_proto_descriptor_idx];
-  bool include_new_lines = new_lines_mode == kIncludeNewLines;
+  auto& proto_descriptor = pool->descriptors()[*opt_proto_descriptor_idx];
 
   protozero::ProtoDecoder decoder(protobytes.data, protobytes.size);
   for (auto field = decoder.ReadField(); field.valid();
        field = decoder.ReadField()) {
-    auto opt_field_descriptor = proto_descriptor.FindFieldByTag(field.id());
-    if (!opt_field_descriptor) {
-      StrAppend(
-          output, output->empty() ? "" : "\n", *indents,
-          "# Ignoring unknown field with id: ", std::to_string(field.id()));
-      continue;
-    }
-    const auto& field_descriptor = *opt_field_descriptor;
+    // Since this is only used in debugging or tests we should always have a
+    // valid compiled in binary descriptor.
+    auto opt_field_descriptor_idx =
+        proto_descriptor.FindFieldIdxByTag(field.id());
+    PERFETTO_DCHECK(opt_field_descriptor_idx);
+    const auto& field_descriptor =
+        proto_descriptor.fields()[*opt_field_descriptor_idx];
 
     if (field_descriptor.type() ==
         protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
@@ -190,9 +165,8 @@
         StrAppend(output, output->empty() ? "" : " ", field_descriptor.name(),
                   ": {");
       }
-      ProtozeroToTextInternal(field_descriptor.resolved_type_name(),
-                              field.as_bytes(), new_lines_mode, pool, indents,
-                              output);
+      ProtozeroToText(field_descriptor.resolved_type_name(), field.as_bytes(),
+                      include_new_lines, pool, indents, output);
       if (include_new_lines) {
         DecreaseIndents(indents);
         StrAppend(output, "\n", *indents, "}");
@@ -209,36 +183,28 @@
   PERFETTO_DCHECK(decoder.bytes_left() == 0);
 }
 
-}  // namespace
-
-std::string ProtozeroToText(const DescriptorPool& pool,
-                            const std::string& type,
+std::string ProtozeroToText(const std::string& type,
                             protozero::ConstBytes protobytes,
-                            NewLinesMode new_lines_mode) {
+                            bool include_new_lines) {
   std::string indent = "";
   std::string final_result;
-  ProtozeroToTextInternal(type, protobytes, new_lines_mode, pool, &indent,
-                          &final_result);
+  DescriptorPool pool;
+  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
+                                              kTrackEventDescriptor.size());
+  PERFETTO_DCHECK(status.ok());
+  ProtozeroToText(type, protobytes, include_new_lines, &pool, &indent,
+                  &final_result);
   return final_result;
 }
+}  // namespace
 
-std::string DebugTrackEventProtozeroToText(const std::string& type,
-                                           protozero::ConstBytes protobytes) {
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  PERFETTO_DCHECK(status.ok());
-  return ProtozeroToText(pool, type, protobytes, kIncludeNewLines);
+std::string DebugProtozeroToText(const std::string& type,
+                                 protozero::ConstBytes protobytes) {
+  return ProtozeroToText(type, protobytes, /* include_new_lines = */ true);
 }
-
-std::string ShortDebugTrackEventProtozeroToText(
-    const std::string& type,
-    protozero::ConstBytes protobytes) {
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  PERFETTO_DCHECK(status.ok());
-  return ProtozeroToText(pool, type, protobytes, kSkipNewLines);
+std::string ShortDebugProtozeroToText(const std::string& type,
+                                      protozero::ConstBytes protobytes) {
+  return ProtozeroToText(type, protobytes, /* include_new_lines = */ false);
 }
 
 std::string ProtozeroEnumToText(const std::string& type, int32_t enum_value) {
@@ -260,19 +226,5 @@
   return *opt_enum_string;
 }
 
-std::string ProtozeroToText(const DescriptorPool& pool,
-                            const std::string& type,
-                            const std::vector<uint8_t>& protobytes,
-                            NewLinesMode new_lines_mode) {
-  return ProtozeroToText(
-      pool, type, protozero::ConstBytes{protobytes.data(), protobytes.size()},
-      new_lines_mode);
-}
-
-std::string BytesToHexEncodedStringForTesting(const std::string& s) {
-  return BytesToHexEncodedString(s);
-}
-
-}  // namespace protozero_to_text
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/util/protozero_to_text.h b/src/trace_processor/util/protozero_to_text.h
index c2082f9..e418926 100644
--- a/src/trace_processor/util/protozero_to_text.h
+++ b/src/trace_processor/util/protozero_to_text.h
@@ -24,41 +24,15 @@
 namespace perfetto {
 namespace trace_processor {
 
-class DescriptorPool;
-
-namespace protozero_to_text {
-
-enum NewLinesMode {
-  kIncludeNewLines = 0,
-  kSkipNewLines,
-};
-
 // Given a protozero message |protobytes| which is of fully qualified name
-// |type| within TrackEvent proto messages, we will convert this into a text
-// proto format string.
+// |type|. We will convert this into a text proto format string.
 //
-// DebugTrackEventProtozeroToText will use new lines between fields, and
-// ShortDebugTrackEventProtozeroToText will use only a single space.
-std::string DebugTrackEventProtozeroToText(const std::string& type,
-                                           protozero::ConstBytes protobytes);
-std::string ShortDebugTrackEventProtozeroToText(
-    const std::string& type,
-    protozero::ConstBytes protobytes);
-
-// Given a protozero message |protobytes| which is of fully qualified name
-// |type|, convert this into a text proto format string. All types used in
-// message definition of |type| must be available in |pool|. If
-// |new_lines_modes| == kIncludeNewLines, new lines will be used between fields,
-// otherwise only a space will be used.
-std::string ProtozeroToText(const DescriptorPool& pool,
-                            const std::string& type,
-                            protozero::ConstBytes protobytes,
-                            NewLinesMode new_lines_mode);
-
-std::string ProtozeroToText(const DescriptorPool& pool,
-                            const std::string& type,
-                            const std::vector<uint8_t>& protobytes,
-                            NewLinesMode new_lines_mode);
+// DebugProtozeroToText will use new lines between fields, and
+// ShortDebugProtozeroToText will use only a single space.
+std::string DebugProtozeroToText(const std::string& type,
+                                 protozero::ConstBytes protobytes);
+std::string ShortDebugProtozeroToText(const std::string& type,
+                                      protozero::ConstBytes protobytes);
 
 // Allow the conversion from a protozero enum to a string. The template is just
 // to allow easy enum passing since we will do the explicit cast to a int32_t
@@ -69,9 +43,6 @@
   return ProtozeroEnumToText(type, static_cast<int32_t>(enum_value));
 }
 
-std::string BytesToHexEncodedStringForTesting(const std::string&);
-
-}  // namespace protozero_to_text
 }  // namespace trace_processor
 }  // namespace perfetto
 
diff --git a/src/trace_processor/util/protozero_to_text_unittests.cc b/src/trace_processor/util/protozero_to_text_unittests.cc
index d6390af..e172dd6 100644
--- a/src/trace_processor/util/protozero_to_text_unittests.cc
+++ b/src/trace_processor/util/protozero_to_text_unittests.cc
@@ -19,14 +19,10 @@
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-#include "src/trace_processor/importers/track_event.descriptor.h"
-#include "src/trace_processor/util/descriptors.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace trace_processor {
-namespace protozero_to_text {
-
 namespace {
 
 constexpr size_t kChunkSize = 42;
@@ -40,14 +36,13 @@
   msg->set_track_uuid(4);
   msg->set_timestamp_delta_us(3);
   auto binary_proto = msg.SerializeAsArray();
-  EXPECT_EQ(
-      "track_uuid: 4\ntimestamp_delta_us: 3",
-      DebugTrackEventProtozeroToText(
-          ".perfetto.protos.TrackEvent",
-          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
+  EXPECT_EQ("track_uuid: 4\ntimestamp_delta_us: 3",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
   EXPECT_EQ(
       "track_uuid: 4 timestamp_delta_us: 3",
-      ShortDebugTrackEventProtozeroToText(
+      ShortDebugProtozeroToText(
           ".perfetto.protos.TrackEvent",
           protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
 }
@@ -65,8 +60,7 @@
   msg->set_timestamp_delta_us(3);
   auto binary_proto = msg.SerializeAsArray();
 
-  EXPECT_EQ(
-      R"(track_uuid: 4
+  EXPECT_EQ(R"(track_uuid: 4
 cc_scheduler_state: {
   deadline_us: 7
   state_machine: {
@@ -77,15 +71,15 @@
   observing_begin_frame_source: true
 }
 timestamp_delta_us: 3)",
-      DebugTrackEventProtozeroToText(
-          ".perfetto.protos.TrackEvent",
-          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
 
   EXPECT_EQ(
       "track_uuid: 4 cc_scheduler_state: { deadline_us: 7 state_machine: { "
       "minor_state: { commit_count: 8 } } observing_begin_frame_source: true } "
       "timestamp_delta_us: 3",
-      ShortDebugTrackEventProtozeroToText(
+      ShortDebugProtozeroToText(
           ".perfetto.protos.TrackEvent",
           protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
 }
@@ -95,75 +89,14 @@
   protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
   msg->set_type(TrackEvent::TYPE_SLICE_BEGIN);
   auto binary_proto = msg.SerializeAsArray();
-  EXPECT_EQ(
-      "type: TYPE_SLICE_BEGIN",
-      DebugTrackEventProtozeroToText(
-          ".perfetto.protos.TrackEvent",
-          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
-  EXPECT_EQ(
-      "type: TYPE_SLICE_BEGIN",
-      DebugTrackEventProtozeroToText(
-          ".perfetto.protos.TrackEvent",
-          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
-}
-
-TEST(ProtozeroToTextTest, CustomDescriptorPoolBasic) {
-  using perfetto::protos::pbzero::TrackEvent;
-  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
-  msg->set_track_uuid(4);
-  msg->set_timestamp_delta_us(3);
-  auto binary_proto = msg.SerializeAsArray();
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  ASSERT_TRUE(status.ok());
-  EXPECT_EQ("track_uuid: 4\ntimestamp_delta_us: 3",
-            ProtozeroToText(pool, ".perfetto.protos.TrackEvent", binary_proto,
-                            kIncludeNewLines));
-  EXPECT_EQ("track_uuid: 4 timestamp_delta_us: 3",
-            ProtozeroToText(pool, ".perfetto.protos.TrackEvent", binary_proto,
-                            kSkipNewLines));
-}
-
-TEST(ProtozeroToTextTest, CustomDescriptorPoolNestedMsg) {
-  using perfetto::protos::pbzero::TrackEvent;
-  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
-  msg->set_track_uuid(4);
-  auto* state = msg->set_cc_scheduler_state();
-  state->set_deadline_us(7);
-  auto* machine = state->set_state_machine();
-  auto* minor_state = machine->set_minor_state();
-  minor_state->set_commit_count(8);
-  state->set_observing_begin_frame_source(true);
-  msg->set_timestamp_delta_us(3);
-  auto binary_proto = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  ASSERT_TRUE(status.ok());
-
-  EXPECT_EQ(
-      R"(track_uuid: 4
-cc_scheduler_state: {
-  deadline_us: 7
-  state_machine: {
-    minor_state: {
-      commit_count: 8
-    }
-  }
-  observing_begin_frame_source: true
-}
-timestamp_delta_us: 3)",
-      ProtozeroToText(pool, ".perfetto.protos.TrackEvent", binary_proto,
-                      kIncludeNewLines));
-
-  EXPECT_EQ(
-      "track_uuid: 4 cc_scheduler_state: { deadline_us: 7 state_machine: { "
-      "minor_state: { commit_count: 8 } } observing_begin_frame_source: true } "
-      "timestamp_delta_us: 3",
-      ProtozeroToText(pool, ".perfetto.protos.TrackEvent", binary_proto,
-                      kSkipNewLines));
+  EXPECT_EQ("type: TYPE_SLICE_BEGIN",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
+  EXPECT_EQ("type: TYPE_SLICE_BEGIN",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
 }
 
 TEST(ProtozeroToTextTest, EnumToString) {
@@ -172,48 +105,6 @@
             ProtozeroEnumToText(".perfetto.protos.TrackEvent.Type",
                                 TrackEvent::TYPE_SLICE_END));
 }
-
-TEST(ProtozeroToTextTest, UnknownField) {
-  using perfetto::protos::pbzero::TrackEvent;
-  // Wrong type to force unknown field:
-  const auto type = ".perfetto.protos.ChromeCompositorSchedulerState";
-  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
-  auto* state = msg->set_cc_scheduler_state();
-  state->set_deadline_us(7);
-  auto* machine = state->set_state_machine();
-  auto* minor_state = machine->set_minor_state();
-  minor_state->set_commit_count(8);
-  auto bytes = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  ASSERT_TRUE(status.ok());
-  ASSERT_EQ(ProtozeroToText(pool, type, bytes, kIncludeNewLines),
-            "# Ignoring unknown field with id: 24");
-}
-
-TEST(ProtozeroToTextTest, StringField) {
-  using perfetto::protos::pbzero::TrackEvent;
-  // Wrong type to force unknown field:
-  const auto type = ".perfetto.protos.TrackEvent";
-  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
-  msg->add_categories(R"(Hello, "World")");
-  auto bytes = msg.SerializeAsArray();
-
-  DescriptorPool pool;
-  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
-                                              kTrackEventDescriptor.size());
-  ASSERT_TRUE(status.ok());
-  ASSERT_EQ(ProtozeroToText(pool, type, bytes, kIncludeNewLines),
-            "categories: \"Hello, \\\"World\\\"\"");
-}
-
-TEST(ProtozeroToTextTest, BytesField) {
-  EXPECT_EQ(BytesToHexEncodedStringForTesting("abc"), R"(\x61\x62\x63)");
-}
-
 }  // namespace
-}  // namespace protozero_to_text
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/virtual_destructors.cc b/src/trace_processor/virtual_destructors.cc
index db5225b..40cc0cd 100644
--- a/src/trace_processor/virtual_destructors.cc
+++ b/src/trace_processor/virtual_destructors.cc
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/importers/common/trace_parser.h"
+#include "src/trace_processor/chunked_trace_reader.h"
+#include "src/trace_processor/trace_parser.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/traced/probes/BUILD.gn b/src/traced/probes/BUILD.gn
index db547fc..7eec236 100644
--- a/src/traced/probes/BUILD.gn
+++ b/src/traced/probes/BUILD.gn
@@ -12,11 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/perfetto.gni")
 import("../../../gn/test.gni")
 
-assert(enable_perfetto_traced_probes)
-
 # The unprivileged daemon that is allowed to access tracefs (for ftrace).
 # Registers as a Producer on the traced daemon.
 executable("traced_probes") {
@@ -38,14 +35,14 @@
     "../../../gn:default_deps",
     "../../tracing/ipc/producer",
   ]
+  if (enable_perfetto_version_gen) {
+    deps += [ "//gn/standalone:gen_git_revision" ]
+  }
   sources = [ "probes.cc" ]
 }
 
 source_set("probes_src") {
-  public_deps = [
-    "ftrace",
-    "ftrace:ftrace_procfs",
-  ]
+  public_deps = [ "ftrace" ]
   deps = [
     ":data_source",
     "../../../gn:default_deps",
@@ -53,7 +50,6 @@
     "../../../protos/perfetto/config/ftrace:cpp",
     "../../../protos/perfetto/trace:zero",
     "../../../protos/perfetto/trace/ps:zero",
-    "../../android_stats",
     "../../base",
     "../../tracing/core",
     "../../tracing/ipc/producer",
@@ -69,8 +65,6 @@
     "system_info",
   ]
   sources = [
-    "kmem_activity_trigger.cc",
-    "kmem_activity_trigger.h",
     "probes_producer.cc",
     "probes_producer.h",
   ]
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 286d138..f63ca51 100644
--- a/src/traced/probes/android_log/android_log_data_source.cc
+++ b/src/traced/probes/android_log/android_log_data_source.cc
@@ -41,7 +41,7 @@
 using protos::pbzero::AndroidLogConfig;
 using protos::pbzero::AndroidLogId;
 
-constexpr size_t kBufSize = 4096;
+constexpr size_t kBufSize = base::kPageSize;
 const char kLogTagsPath[] = "/system/etc/event-log-tags";
 const char kLogdrSocket[] = "/dev/socket/logdr";
 
@@ -208,7 +208,7 @@
   // modulo is to increase the chance that the wakeup is packed together with
   // some other wakeup task of traced_probes.
   const uint32_t kBatchMs = 100;
-  uint32_t delay_ms = kBatchMs - static_cast<uint32_t>(now_ms % kBatchMs);
+  uint32_t delay_ms = kBatchMs - (now_ms % kBatchMs);
   auto weak_this = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
       [weak_this] {
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 d012707..c7753f1 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
@@ -63,7 +63,7 @@
     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::CreatePairPosix(
+    std::tie(send_sock, recv_sock) = base::UnixSocketRaw::CreatePair(
         base::SockFamily::kUnix, base::SockType::kDgram);
     ASSERT_TRUE(send_sock);
     ASSERT_TRUE(recv_sock);
diff --git a/src/traced/probes/common/cpu_freq_info_for_testing.cc b/src/traced/probes/common/cpu_freq_info_for_testing.cc
index 132f75a..d1e2b76 100644
--- a/src/traced/probes/common/cpu_freq_info_for_testing.cc
+++ b/src/traced/probes/common/cpu_freq_info_for_testing.cc
@@ -16,6 +16,9 @@
 
 #include "src/traced/probes/common/cpu_freq_info_for_testing.h"
 
+#include <dirent.h>
+#include <sys/stat.h>
+
 #include <algorithm>
 #include <memory>
 
@@ -62,10 +65,10 @@
 
 CpuFreqInfoForTesting::~CpuFreqInfoForTesting() {
   for (auto path : files_to_remove_)
-    PERFETTO_CHECK(remove(AbsolutePath(path).c_str()) == 0);
+    RmFile(path);
   std::reverse(dirs_to_remove_.begin(), dirs_to_remove_.end());
   for (auto path : dirs_to_remove_)
-    base::Rmdir(AbsolutePath(path));
+    RmDir(path);
 }
 
 std::unique_ptr<CpuFreqInfo> CpuFreqInfoForTesting::GetInstance() {
@@ -74,7 +77,7 @@
 
 void CpuFreqInfoForTesting::AddDir(std::string path) {
   dirs_to_remove_.push_back(path);
-  base::Mkdir(AbsolutePath(path).c_str());
+  mkdir(AbsolutePath(path).c_str(), 0755);
 }
 
 void CpuFreqInfoForTesting::AddFile(std::string path, std::string content) {
@@ -85,6 +88,14 @@
                  static_cast<ssize_t>(content.size()));
 }
 
+void CpuFreqInfoForTesting::RmDir(std::string path) {
+  PERFETTO_CHECK(rmdir(AbsolutePath(path).c_str()) == 0);
+}
+
+void CpuFreqInfoForTesting::RmFile(std::string path) {
+  PERFETTO_CHECK(remove(AbsolutePath(path).c_str()) == 0);
+}
+
 std::string CpuFreqInfoForTesting::AbsolutePath(std::string path) {
   return fake_cpu_dir_.path() + "/" + path;
 }
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index 5362f2c..bbe38e0 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -60,20 +60,20 @@
   StaticMapDelegate(
       std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>* map)
       : map_(map) {}
-  ~StaticMapDelegate() override {}
+  ~StaticMapDelegate() {}
 
  private:
   bool OnInodeFound(BlockDeviceID block_device_id,
                     Inode inode_number,
                     const std::string& path,
-                    InodeFileMap_Entry_Type type) override {
+                    InodeFileMap_Entry_Type type) {
     std::unordered_map<Inode, InodeMapValue>& inode_map =
         (*map_)[block_device_id];
     inode_map[inode_number].SetType(type);
     inode_map[inode_number].AddPath(path);
     return true;
   }
-  void OnInodeScanDone() override {}
+  void OnInodeScanDone() {}
   std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>* map_;
 };
 
@@ -257,7 +257,7 @@
                 PERFETTO_DLOG("Giving up filesystem scan.");
                 return;
               }
-              weak_this->FindMissingInodes();
+              weak_this.get()->FindMissingInodes();
             },
             scan_delay_ms_);
       }
diff --git a/src/traced/probes/filesystem/prefix_finder.cc b/src/traced/probes/filesystem/prefix_finder.cc
index 4dca5c8..b22532e 100644
--- a/src/traced/probes/filesystem/prefix_finder.cc
+++ b/src/traced/probes/filesystem/prefix_finder.cc
@@ -27,21 +27,11 @@
 }
 
 PrefixFinder::Node* PrefixFinder::Node::AddChild(std::string name) {
-  auto it = children_.emplace(std::move(name), this);
-  return const_cast<Node*>(&(*it.first));
+  return children_.Emplace(std::move(name), this);
 }
 
 PrefixFinder::Node* PrefixFinder::Node::MaybeChild(const std::string& name) {
-  // 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 Node from the key.
-  Node node(name);
-  auto it = children_.find(node);
-  if (it == children_.end())
-    return nullptr;
-  return const_cast<Node*>(&(*it));
+  return children_.Get(name);
 }
 
 PrefixFinder::PrefixFinder(size_t limit) : limit_(limit) {}
diff --git a/src/traced/probes/filesystem/prefix_finder.h b/src/traced/probes/filesystem/prefix_finder.h
index d2b8385..3d84ed1 100644
--- a/src/traced/probes/filesystem/prefix_finder.h
+++ b/src/traced/probes/filesystem/prefix_finder.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/ext/base/lookup_set.h"
 
 namespace perfetto {
 
@@ -69,17 +70,10 @@
 
     const std::string name_;
     const Node* parent_;
-    class NodeComparator {
-     public:
-      bool operator()(const Node& one, const Node& other) const {
-        return one.name_ < other.name_;
-      }
-    };
-
-    std::set<Node, NodeComparator> children_;
+    base::LookupSet<Node, const std::string, &Node::name_> children_;
   };
 
-  explicit PrefixFinder(size_t limit);
+  PrefixFinder(size_t limit);
 
   // Add path to prefix mapping.
   // Must be called in DFS order.
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index dcc8ca1..0ffd645 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -17,8 +17,6 @@
 import("../../../../gn/proto_library.gni")
 import("../../../../gn/test.gni")
 
-assert(target_os != "win")
-
 # For use_libfuzzer.
 if (perfetto_root_path == "//") {
   import("//gn/standalone/sanitizers/vars.gni")
@@ -30,7 +28,6 @@
   testonly = true
   deps = [
     ":ftrace",
-    ":ftrace_procfs",
     "../../../../gn:default_deps",
     "../../../base:test_support",
     "../../../protozero",
@@ -46,8 +43,8 @@
 perfetto_unittest_source_set("unittests") {
   testonly = true
   deps = [
+    ":format_parser",
     ":ftrace",
-    ":ftrace_procfs",
     ":test_messages_cpp",
     ":test_messages_lite",
     ":test_messages_zero",
@@ -59,19 +56,17 @@
     "../../../../protos/perfetto/trace/ftrace:zero",
     "../../../base:test_support",
     "../../../tracing/test:test_support",
-    "format_parser",
-    "format_parser:unittests",
   ]
   sources = [
     "cpu_reader_unittest.cc",
     "cpu_stats_parser_unittest.cc",
     "discover_vendor_tracepoints_unittest.cc",
     "event_info_unittest.cc",
+    "format_parser_unittest.cc",
     "ftrace_config_muxer_unittest.cc",
     "ftrace_config_unittest.cc",
     "ftrace_controller_unittest.cc",
     "ftrace_procfs_unittest.cc",
-    "printk_formats_parser_unittest.cc",
     "proto_translation_table_unittest.cc",
   ]
 }
@@ -92,7 +87,6 @@
   testonly = true
   deps = [
     ":ftrace",
-    ":ftrace_procfs",
     ":test_support",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
@@ -109,18 +103,14 @@
     "../../../tracing/core",
   ]
   deps = [
-    ":ftrace_procfs",
+    ":format_parser",
     "..:data_source",
     "../../../../gn:default_deps",
     "../../../../include/perfetto/ext/traced",
     "../../../../protos/perfetto/trace:zero",
-    "../../../../protos/perfetto/trace/interned_data:zero",
-    "../../../../protos/perfetto/trace/profiling:zero",
     "../../../android_internal:lazy_library_loader",
     "../../../base",
-    "../../../kallsyms",
     "../../../protozero",
-    "format_parser",
   ]
   sources = [
     "atrace_hal_wrapper.cc",
@@ -148,23 +138,23 @@
     "ftrace_data_source.cc",
     "ftrace_data_source.h",
     "ftrace_metadata.h",
+    "ftrace_procfs.cc",
+    "ftrace_procfs.h",
     "ftrace_stats.cc",
     "ftrace_stats.h",
-    "printk_formats_parser.cc",
-    "printk_formats_parser.h",
     "proto_translation_table.cc",
     "proto_translation_table.h",
   ]
 }
 
-source_set("ftrace_procfs") {
+source_set("format_parser") {
   deps = [
     "../../../../gn:default_deps",
     "../../../base",
   ]
   sources = [
-    "ftrace_procfs.cc",
-    "ftrace_procfs.h",
+    "format_parser.cc",
+    "format_parser.h",
   ]
 }
 
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.cc b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
index 361c00a..78f4114 100644
--- a/src/traced/probes/ftrace/atrace_hal_wrapper.cc
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
@@ -57,7 +57,6 @@
     if (!enable_categories_)
       return false;
     std::vector<const char*> args;
-    args.reserve(categories.size());
     for (const std::string& category : categories) {
       args.push_back(category.c_str());
     }
diff --git a/src/traced/probes/ftrace/compact_sched.cc b/src/traced/probes/ftrace/compact_sched.cc
index cd2d117..35309d8 100644
--- a/src/traced/probes/ftrace/compact_sched.cc
+++ b/src/traced/probes/ftrace/compact_sched.cc
@@ -208,7 +208,7 @@
   return CompactSchedConfig{/*enabled=*/false};
 }
 
-// Check size of stack-allocated bundle state.
+// Sanity check size of stack-allocated bundle state.
 static_assert(sizeof(CompactSchedBuffer) <= 1 << 18,
               "CompactSchedBuffer's on-stack size excessively large.");
 
diff --git a/src/traced/probes/ftrace/cpu_reader.cc b/src/traced/probes/ftrace/cpu_reader.cc
index 9b1d4f8..6010e90 100644
--- a/src/traced/probes/ftrace/cpu_reader.cc
+++ b/src/traced/probes/ftrace/cpu_reader.cc
@@ -17,10 +17,8 @@
 #include "src/traced/probes/ftrace/cpu_reader.h"
 
 #include <dirent.h>
-#include <fcntl.h>
 #include <signal.h>
 
-#include <algorithm>
 #include <utility>
 
 #include "perfetto/base/build_config.h"
@@ -29,20 +27,15 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
-#include "src/kallsyms/kernel_symbol_map.h"
-#include "src/kallsyms/lazy_kernel_symbolizer.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 "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_data_source.h"
 #include "src/traced/probes/ftrace/proto_translation_table.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/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
 namespace perfetto {
 namespace {
 
@@ -147,12 +140,8 @@
 
 CpuReader::CpuReader(size_t cpu,
                      const ProtoTranslationTable* table,
-                     LazyKernelSymbolizer* symbolizer,
                      base::ScopedFile trace_fd)
-    : cpu_(cpu),
-      table_(table),
-      symbolizer_(symbolizer),
-      trace_fd_(std::move(trace_fd)) {
+    : cpu_(cpu), table_(table), trace_fd_(std::move(trace_fd)) {
   PERFETTO_CHECK(trace_fd_);
   PERFETTO_CHECK(SetBlocking(*trace_fd_, false));
 }
@@ -212,11 +201,8 @@
         // Expected errors:
         // EAGAIN: no data (since we're in non-blocking mode).
         // ENONMEM, EBUSY: temporary ftrace failures (they happen).
-        // ENODEV: the cpu is offline (b/145583318).
-        if (errno != EAGAIN && errno != ENOMEM && errno != EBUSY &&
-            errno != ENODEV) {
+        if (errno != EAGAIN && errno != ENOMEM && errno != EBUSY)
           PERFETTO_PLOG("Unexpected error on raw ftrace read");
-        }
         break;  // stop reading regardless of errno
       }
 
@@ -275,8 +261,7 @@
   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_,
-        symbolizer_);
+        data_source->parsing_config(), parsing_buf, pages_read, table_);
     PERFETTO_CHECK(success);
   }
 
@@ -291,98 +276,20 @@
     const FtraceDataSourceConfig* ds_config,
     const uint8_t* parsing_buf,
     const size_t pages_read,
-    const ProtoTranslationTable* table,
-    LazyKernelSymbolizer* symbolizer) {
-  // Allocate the buffer for compact scheduler events (which will be unused if
-  // the compact option isn't enabled).
+    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;
 
-  TraceWriter::TracePacketHandle packet;
-  protos::pbzero::FtraceEventBundle* bundle = nullptr;
+  // 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));
 
-  // This function is called after the contents of a FtraceBundle are written.
-  auto finalize_cur_packet = [&] {
-    PERFETTO_DCHECK(packet);
-    if (compact_sched_enabled)
-      compact_sched.WriteAndReset(bundle);
-
-    bundle->Finalize();
-    bundle = nullptr;
-
-    // Write the kernel symbol index (mangled address) -> name table.
-    // |metadata| is shared across all cpus, is distinct per |data_source| (i.e.
-    // tracing session) and is cleared after each FtraceController::ReadTick().
-    // const size_t kaddrs_size = metadata->kernel_addrs.size();
-    if (ds_config->symbolize_ksyms) {
-      // Symbol indexes are assigned mononically as |kernel_addrs.size()|,
-      // starting from index 1 (no symbol has index 0). Here we remember the
-      // size() (which is also == the highest value in |kernel_addrs|) at the
-      // beginning and only write newer indexes bigger than that.
-      uint32_t max_index_at_start = metadata->last_kernel_addr_index_written;
-      PERFETTO_DCHECK(max_index_at_start <= metadata->kernel_addrs.size());
-      protos::pbzero::InternedData* interned_data = nullptr;
-      auto* ksyms_map = symbolizer->GetOrCreateKernelSymbolMap();
-      bool wrote_at_least_one_symbol = false;
-      for (const FtraceMetadata::KernelAddr& kaddr : metadata->kernel_addrs) {
-        if (kaddr.index <= max_index_at_start)
-          continue;
-        std::string sym_name = ksyms_map->Lookup(kaddr.addr);
-        if (sym_name.empty()) {
-          // Lookup failed. This can genuinely happen in many occasions. E.g.,
-          // workqueue_execute_start has two pointers: one is a pointer to a
-          // function (which we expect to be symbolized), the other (|work|) is
-          // a pointer to a heap struct, which is unsymbolizable, even when
-          // using the textual ftrace endpoint.
-          continue;
-        }
-
-        if (!interned_data) {
-          // If this is the very first write, clear the start of the sequence
-          // so the trace processor knows that all previous indexes can be
-          // discarded and that the mapping is restarting.
-          // In most cases this occurs with cpu==0. But if cpu0 is idle, this
-          // will happen with the first CPU that has any ftrace data.
-          if (max_index_at_start == 0) {
-            packet->set_sequence_flags(
-                protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
-          }
-          interned_data = packet->set_interned_data();
-        }
-        auto* interned_sym = interned_data->add_kernel_symbols();
-        interned_sym->set_iid(kaddr.index);
-        interned_sym->set_str(sym_name);
-        wrote_at_least_one_symbol = true;
-      }
-
-      auto max_it_at_end = static_cast<uint32_t>(metadata->kernel_addrs.size());
-
-      // Rationale for the if (wrote_at_least_one_symbol) check: in rare cases,
-      // all symbols seen in a ProcessPagesForDataSource() call can fail the
-      // ksyms_map->Lookup(). If that happens we don't want to bump the
-      // last_kernel_addr_index_written watermark, as that would cause the next
-      // call to NOT emit the SEQ_INCREMENTAL_STATE_CLEARED.
-      if (wrote_at_least_one_symbol)
-        metadata->last_kernel_addr_index_written = max_it_at_end;
-    }
-
-    packet->Finalize();
-  };  // finalize_cur_packet().
-
-  auto start_new_packet = [&](bool lost_events) {
-    if (packet)
-      finalize_cur_packet();
-    packet = trace_writer->NewTracePacket();
-    bundle = packet->set_ftrace_events();
-    // 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));
-    if (lost_events)
-      bundle->set_lost_events(true);
-  };
-
-  start_new_packet(/*lost_events=*/false);
   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;
@@ -408,9 +315,17 @@
         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();
 
-    if (page_header->lost_events || interner_past_threshold)
-      start_new_packet(page_header->lost_events);
+      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,
@@ -420,7 +335,9 @@
     // (FtraceMetadata -> FtraceStats in trace).
     PERFETTO_DCHECK(evt_size == page_header->size);
   }
-  finalize_cur_packet();
+
+  if (compact_sched_enabled)
+    compact_sched.WriteAndReset(bundle);
 
   return true;
 }
@@ -509,7 +426,7 @@
           PERFETTO_DFATAL("Empty padding event.");
           return 0;
         }
-        uint32_t length = 0;
+        uint32_t length;
         if (!ReadAndAdvance<uint32_t>(&ptr, end, &length))
           return 0;
         // length includes itself (4 bytes)
@@ -520,23 +437,20 @@
       }
       case kTypeTimeExtend: {
         // Extend the time delta.
-        uint32_t time_delta_ext = 0;
+        uint32_t time_delta_ext;
         if (!ReadAndAdvance<uint32_t>(&ptr, end, &time_delta_ext))
           return 0;
+        // See https://goo.gl/CFBu5x
         timestamp += (static_cast<uint64_t>(time_delta_ext)) << 27;
         break;
       }
       case kTypeTimeStamp: {
-        // Absolute timestamp. This was historically partially implemented, but
-        // not written. Kernels 4.17+ reimplemented this record, changing its
-        // size in the process. We assume the newer layout. Parsed the same as
-        // kTypeTimeExtend, except that the timestamp is interpreted as an
-        // absolute, instead of a delta on top of the previous state.
-        timestamp = event_header.time_delta;
-        uint32_t time_delta_ext = 0;
-        if (!ReadAndAdvance<uint32_t>(&ptr, end, &time_delta_ext))
+        // Sync time stamp with external clock.
+        TimeStamp time_stamp;
+        if (!ReadAndAdvance<TimeStamp>(&ptr, end, &time_stamp))
           return 0;
-        timestamp += (static_cast<uint64_t>(time_delta_ext)) << 27;
+        // Not implemented in the kernel, nothing should generate this.
+        PERFETTO_DFATAL("Unimplemented in kernel. Should be unreachable.");
         break;
       }
       // Data record:
@@ -546,7 +460,7 @@
         // record. if == 0, this is an extended record and the size of the
         // record is stored in the first uint32_t word in the payload. See
         // Kernel's include/linux/ring_buffer.h
-        uint32_t event_size = 0;
+        uint32_t event_size;
         if (event_header.type_or_length == 0) {
           if (!ReadAndAdvance<uint32_t>(&ptr, end, &event_size))
             return 0;
@@ -635,7 +549,7 @@
 
   bool success = true;
   for (const Field& field : table->common_fields())
-    success &= ParseField(field, start, end, table, message, metadata);
+    success &= ParseField(field, start, end, message, metadata);
 
   protozero::Message* nested =
       message->BeginNestedMessage<protozero::Message>(info.proto_field_id);
@@ -647,14 +561,14 @@
     for (const Field& field : info.fields) {
       auto generic_field = nested->BeginNestedMessage<protozero::Message>(
           GenericFtraceEvent::kFieldFieldNumber);
-      // TODO(hjd): Avoid outputting field names every time.
+      // TODO(taylori): Avoid outputting field names every time.
       generic_field->AppendString(GenericFtraceEvent::Field::kNameFieldNumber,
                                   field.ftrace_name);
-      success &= ParseField(field, start, end, table, generic_field, metadata);
+      success &= ParseField(field, start, end, generic_field, metadata);
     }
   } else {  // Parse all other events.
     for (const Field& field : info.fields) {
-      success &= ParseField(field, start, end, table, nested, metadata);
+      success &= ParseField(field, start, end, nested, metadata);
     }
   }
 
@@ -681,7 +595,6 @@
 bool CpuReader::ParseField(const Field& field,
                            const uint8_t* start,
                            const uint8_t* end,
-                           const ProtoTranslationTable* table,
                            protozero::Message* message,
                            FtraceMetadata* metadata) {
   PERFETTO_DCHECK(start + field.ftrace_offset + field.ftrace_size <= end);
@@ -725,22 +638,10 @@
                             field_id, message);
     case kCStringToString:
       // TODO(hjd): Kernel-dive to check this how size:0 char fields work.
-      return ReadIntoString(field_start, end, field_id, message);
-    case kStringPtrToString: {
-      uint64_t n = 0;
-      // The ftrace field may be 8 or 4 bytes and we need to copy it into the
-      // bottom of n. In the unlikely case where the field is >8 bytes we
-      // should avoid making things worse by corrupting the stack but we
-      // don't need to handle it correctly.
-      size_t size = std::min<size_t>(field.ftrace_size, sizeof(n));
-      memcpy(base::AssumeLittleEndian(&n),
-             reinterpret_cast<const void*>(field_start), size);
-      // Look up the adddress in the printk format map and write it into the
-      // proto.
-      base::StringView name = table->LookupTraceString(n);
-      message->AppendBytes(field_id, name.begin(), name.size());
+      return ReadIntoString(field_start, end, field.proto_field_id, message);
+    case kStringPtrToString:
+      // TODO(hjd): Figure out how to read these.
       return true;
-    }
     case kDataLocToString:
       return ReadDataLoc(start, field_start, end, field, message);
     case kBoolToUint32:
@@ -767,9 +668,6 @@
     case kDevId64ToUint64:
       ReadDevId<uint64_t>(field_start, field_id, message, metadata);
       return true;
-    case kFtraceSymAddr64ToUint64:
-      ReadSymbolAddr<uint64_t>(field_start, field_id, message, metadata);
-      return true;
     case kInvalidTranslationStrategy:
       break;
   }
diff --git a/src/traced/probes/ftrace/cpu_reader.h b/src/traced/probes/ftrace/cpu_reader.h
index ba0f9fd..f329044 100644
--- a/src/traced/probes/ftrace/cpu_reader.h
+++ b/src/traced/probes/ftrace/cpu_reader.h
@@ -42,7 +42,6 @@
 namespace perfetto {
 
 class FtraceDataSource;
-class LazyKernelSymbolizer;
 class ProtoTranslationTable;
 struct FtraceDataSourceConfig;
 
@@ -66,7 +65,6 @@
 
   CpuReader(size_t cpu,
             const ProtoTranslationTable* table,
-            LazyKernelSymbolizer* symbolizer,
             base::ScopedFile trace_fd);
   ~CpuReader();
 
@@ -121,22 +119,6 @@
     metadata->AddDevice(dev_id);
   }
 
-  template <typename T>
-  static void ReadSymbolAddr(const uint8_t* start,
-                             uint32_t field_id,
-                             protozero::Message* out,
-                             FtraceMetadata* metadata) {
-    // ReadSymbolAddr is a bit special. In order to not disclose KASLR layout
-    // via traces, we put in the trace only a mangled address (which really is
-    // the insertion order into metadata.kernel_addrs). We don't care about the
-    // actual symbol addesses. We just need to match that against the symbol
-    // name in the names in the FtraceEventBundle.KernelSymbols.
-    T full_addr;
-    memcpy(&full_addr, reinterpret_cast<const void*>(start), sizeof(T));
-    uint32_t interned_index = metadata->AddSymbolAddr(full_addr);
-    out->AppendVarInt(field_id, interned_index);
-  }
-
   static void ReadPid(const uint8_t* start,
                       uint32_t field_id,
                       protozero::Message* out,
@@ -208,7 +190,6 @@
   static bool ParseField(const Field& field,
                          const uint8_t* start,
                          const uint8_t* end,
-                         const ProtoTranslationTable* table,
                          protozero::Message* message,
                          FtraceMetadata* metadata);
 
@@ -238,8 +219,7 @@
                                         const FtraceDataSourceConfig* ds_config,
                                         const uint8_t* parsing_buf,
                                         const size_t pages_read,
-                                        const ProtoTranslationTable* table,
-                                        LazyKernelSymbolizer* symbolizer);
+                                        const ProtoTranslationTable* table);
 
  private:
   CpuReader(const CpuReader&) = delete;
@@ -257,7 +237,6 @@
 
   const size_t cpu_;
   const ProtoTranslationTable* const table_;
-  LazyKernelSymbolizer* const symbolizer_;
   base::ScopedFile trace_fd_;
 };
 
diff --git a/src/traced/probes/ftrace/cpu_reader_benchmark.cc b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
index 6a647a9..ee6d246 100644
--- a/src/traced/probes/ftrace/cpu_reader_benchmark.cc
+++ b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
@@ -15,7 +15,6 @@
 #include <benchmark/benchmark.h>
 
 #include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/root_message.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"
@@ -311,16 +310,13 @@
 
   ScatteredStreamWriterNullDelegate delegate(perfetto::base::kPageSize);
   ScatteredStreamWriter stream(&delegate);
-  protozero::RootMessage<FtraceEventBundle> writer;
+  FtraceEventBundle writer;
 
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting(),
-                                   {},
-                                   {},
-                                   false /*symbolize_ksyms*/};
+  FtraceDataSourceConfig ds_config{
+      EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
   ds_config.event_filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
diff --git a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
index db943a6..47c5351 100644
--- a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
+++ b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
@@ -53,11 +53,8 @@
   memcpy(g_page, data, std::min(base::kPageSize, size));
 
   FtraceMetadata metadata{};
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting(),
-                                   {},
-                                   {},
-                                   /*symbolize_ksyms=*/false};
+  FtraceDataSourceConfig ds_config{
+      EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
   ds_config.event_filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
   ds_config.event_filter.AddEnabledEvent(
@@ -66,7 +63,7 @@
   NullTraceWriter null_writer;
   CpuReader::ProcessPagesForDataSource(&null_writer, &metadata, /*cpu=*/0,
                                        &ds_config, g_page, /*pages_read=*/1,
-                                       table, /*symbolizer*/ nullptr);
+                                       table);
 }
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index dd596ef..2d10829 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -37,7 +37,6 @@
 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/power.gen.h"
 #include "protos/perfetto/trace/ftrace/sched.gen.h"
 #include "protos/perfetto/trace/trace_packet.gen.h"
 #include "src/traced/probes/ftrace/test/test_messages.gen.h"
@@ -62,11 +61,8 @@
 namespace {
 
 FtraceDataSourceConfig EmptyConfig() {
-  return FtraceDataSourceConfig{EventFilter{},
-                                DisabledCompactSchedConfigForTesting(),
-                                {},
-                                {},
-                                false /*symbolize_ksyms*/};
+  return FtraceDataSourceConfig{
+      EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
 }
 
 constexpr uint64_t kNanoInSecond = 1000 * 1000 * 1000;
@@ -116,20 +112,24 @@
 template <class ZeroT, class ProtoT>
 class ProtoProvider {
  public:
-  explicit ProtoProvider(size_t chunk_size) : chunk_size_(chunk_size) {}
+  explicit ProtoProvider(size_t chunk_size)
+      : chunk_size_(chunk_size), delegate_(chunk_size_), stream_(&delegate_) {
+    delegate_.set_writer(&stream_);
+    writer_.Reset(&stream_);
+  }
   ~ProtoProvider() = default;
 
-  ZeroT* writer() { return writer_.get(); }
-  void ResetWriter() { writer_.Reset(); }
+  ZeroT* writer() { return &writer_; }
 
   // Stitch together the scattered chunks into a single buffer then attempt
   // to parse the buffer as a FtraceEventBundle. Returns the FtraceEventBundle
   // on success and nullptr on failure.
   std::unique_ptr<ProtoT> ParseProto() {
     auto bundle = std::unique_ptr<ProtoT>(new ProtoT());
-    std::vector<uint8_t> buffer = writer_.SerializeAsArray();
-    if (!bundle->ParseFromArray(buffer.data(), buffer.size()))
+    std::vector<uint8_t> buffer = delegate_.StitchSlices();
+    if (!bundle->ParseFromArray(buffer.data(), buffer.size())) {
       return nullptr;
+    }
     return bundle;
   }
 
@@ -138,7 +138,9 @@
   ProtoProvider& operator=(const ProtoProvider&) = delete;
 
   size_t chunk_size_;
-  protozero::HeapBuffered<ZeroT> writer_;
+  protozero::ScatteredHeapBuffer delegate_;
+  protozero::ScatteredStreamWriter stream_;
+  ZeroT writer_;
 };
 
 using BundleProvider = ProtoProvider<protos::pbzero::FtraceEventBundle,
@@ -816,11 +818,8 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   EnabledCompactSchedConfigForTesting(),
-                                   {},
-                                   {},
-                                   false /* symbolize_ksyms*/};
+  FtraceDataSourceConfig ds_config{
+      EventFilter{}, EnabledCompactSchedConfigForTesting(), {}, {}};
   ds_config.event_filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
@@ -847,7 +846,6 @@
   ASSERT_TRUE(bundle);
   EXPECT_EQ(0u, bundle->event().size());
   EXPECT_FALSE(bundle->has_compact_sched());
-  bundle_provider.ResetWriter();
 
   // Instead, sched switch fields were buffered:
   EXPECT_LT(0u, compact_buffer.sched_switch().size());
@@ -998,21 +996,10 @@
     }
 
     {
-      // char* -> string
-      event->fields.emplace_back(Field{});
-      Field* field = &event->fields.back();
-      field->ftrace_offset = 56;
-      field->ftrace_size = 8;
-      field->ftrace_type = kFtraceStringPtr;
-      field->proto_field_id = 503;
-      field->proto_field_type = ProtoSchemaType::kString;
-    }
-
-    {
       // dataloc -> string
       event->fields.emplace_back(Field{});
       Field* field = &event->fields.back();
-      field->ftrace_offset = 65;
+      field->ftrace_offset = 57;
       field->ftrace_size = 4;
       field->ftrace_type = kFtraceDataLoc;
       field->proto_field_id = 502;
@@ -1023,7 +1010,7 @@
       // char -> string
       event->fields.emplace_back(Field{});
       Field* field = &event->fields.back();
-      field->ftrace_offset = 69;
+      field->ftrace_offset = 61;
       field->ftrace_size = 0;
       field->ftrace_type = kFtraceCString;
       field->proto_field_id = 501;
@@ -1036,12 +1023,10 @@
     }
   }
 
-  PrintkMap printk_formats;
-  printk_formats.insert(0xffffff8504f51b23, "my_printk_format_string");
   ProtoTranslationTable table(
       &ftrace_, events, std::move(common_fields),
       ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-      InvalidCompactSchedEventFormatForTesting(), printk_formats);
+      InvalidCompactSchedEventFormatForTesting());
 
   FakeEventProvider provider(base::kPageSize);
 
@@ -1068,7 +1053,6 @@
   writer.Write<int64_t>(k64BitKernelBlockDeviceId);  // Dev id 64
   writer.Write<int64_t>(99u);                        // Inode 64
   writer.WriteFixedString(16, "Hello");
-  writer.Write<uint64_t>(0xffffff8504f51b23ULL);  // char* (printk formats)
   writer.Write<uint8_t>(0);  // Deliberately mis-aligning.
   writer.Write<uint32_t>(40 | 6 << 16);
   writer.WriteFixedString(300, "Goodbye");
@@ -1092,14 +1076,13 @@
             static_cast<uint32_t>(kUserspaceBlockDeviceId));
   EXPECT_EQ(event->all_fields().field_inode_32(), 98u);
 // TODO(primiano): for some reason this fails on mac.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   EXPECT_EQ(event->all_fields().field_dev_64(), k64BitUserspaceBlockDeviceId);
 #endif
   EXPECT_EQ(event->all_fields().field_inode_64(), 99u);
   EXPECT_EQ(event->all_fields().field_char_16(), "Hello");
   EXPECT_EQ(event->all_fields().field_char(), "Goodbye");
   EXPECT_EQ(event->all_fields().field_data_loc(), "Hello");
-  EXPECT_EQ(event->all_fields().field_char_star(), "my_printk_format_string");
   EXPECT_THAT(metadata.pids, Contains(97));
   EXPECT_EQ(metadata.inode_and_device.size(), 2U);
   EXPECT_THAT(metadata.inode_and_device,
@@ -1182,8 +1165,7 @@
 
   TraceWriterForTesting trace_writer;
   CpuReader::ProcessPagesForDataSource(&trace_writer, &metadata, /*cpu=*/1,
-                                       &ds_config, buf, kTestPages, table,
-                                       /*symbolizer=*/nullptr);
+                                       &ds_config, buf, kTestPages, table);
 
   // Each packet should contain the parsed contents of a contiguous run of pages
   // without data loss.
@@ -1202,251 +1184,6 @@
   EXPECT_EQ(4u, packets[2].ftrace_events().event().size());
 }
 
-// Page containing an absolute timestamp (RINGBUF_TYPE_TIME_STAMP).
-static char g_abs_timestamp[] =
-    R"(
-00000000: 8949 fbfb 38e4 0400 6407 0000 0000 0000  .I..8...d.......
-00000010: 5032 0a2d 3b01 0100 0000 0000 7377 6170  P2.-;.......swap
-00000020: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
-00000030: 7800 0000 0000 0000 0000 0000 6776 6673  x...........gvfs
-00000040: 2d61 6663 2d76 6f6c 756d 6500 6483 0000  -afc-volume.d...
-00000050: 7800 0000 f0de 1700 3b01 0100 6483 0000  x.......;...d...
-00000060: 6776 6673 2d61 6663 2d76 6f6c 756d 6500  gvfs-afc-volume.
-00000070: 6483 0000 7800 0000 0100 0000 0000 0000  d...x...........
-00000080: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
-00000090: 0000 0000 7800 0000 aaa1 5c08 0401 1100  ....x.....\.....
-000000a0: 0000 0000 88fc 31eb 029f ffff 609e d3c0  ......1.....`...
-000000b0: ffff ffff 0076 b4a1 029f ffff 0020 0000  .....v....... ..
-000000c0: ffff ffff e477 1700 0301 1100 0000 0000  .....w..........
-000000d0: 88fc 31eb 029f ffff aa26 0100 3e01 1100  ..1......&..>...
-000000e0: 0000 0000 6b77 6f72 6b65 722f 7538 3a35  ....kworker/u8:5
-000000f0: 0000 0000 24c0 0c00 7800 0000 0100 0000  ....$...x.......
-00000100: 0300 0000 90e6 e700 3b01 0100 0000 0000  ........;.......
-00000110: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
-00000120: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
-00000130: 6b77 6f72 6b65 722f 7538 3a35 0000 0000  kworker/u8:5....
-00000140: 24c0 0c00 7800 0000 aa56 0300 3e01 0100  $...x....V..>...
-00000150: 24c0 0c00 6b77 6f72 6b65 722f 7538 3a31  $...kworker/u8:1
-00000160: 0000 0000 8eb5 0c00 7800 0000 0100 0000  ........x.......
-00000170: 0300 0000 06eb 0300 0201 0000 24c0 0c00  ............$...
-00000180: 6026 f22a 049f ffff f0e4 4cc0 ffff ffff  `&.*......L.....
-00000190: ca45 0f00 3e01 0100 24c0 0c00 646d 6372  .E..>...$...dmcr
-000001a0: 7970 745f 7772 6974 652f 3200 2601 0000  ypt_write/2.&...
-000001b0: 7800 0000 0100 0000 0100 0000 c617 0200  x...............
-000001c0: 0101 0000 24c0 0c00 6026 f22a 049f ffff  ....$...`&.*....
-000001d0: f0e4 4cc0 ffff ffff a47c 0000 0301 0100  ..L......|......
-000001e0: 24c0 0c00 6015 f22a 049f ffff 0685 0000  $...`..*........
-000001f0: 0201 0000 24c0 0c00 a05d f22a 049f ffff  ....$....].*....
-00000200: f0e4 4cc0 ffff ffff c6dd 0800 0101 0000  ..L.............
-00000210: 24c0 0c00 a05d f22a 049f ffff f0e4 4cc0  $....].*......L.
-00000220: ffff ffff 8444 0000 0301 0100 24c0 0c00  .....D......$...
-00000230: 6059 f22a 049f ffff e672 0000 0201 0000  `Y.*.....r......
-00000240: 24c0 0c00 e050 f22a 049f ffff f0e4 4cc0  $....P.*......L.
-00000250: ffff ffff 4673 0a00 0101 0000 24c0 0c00  ....Fs......$...
-00000260: e050 f22a 049f ffff f0e4 4cc0 ffff ffff  .P.*......L.....
-00000270: 04ca 0000 0301 0100 24c0 0c00 2000 f22a  ........$... ..*
-00000280: 049f ffff 86b1 0000 0201 0000 24c0 0c00  ............$...
-00000290: 6015 f22a 049f ffff f0e4 4cc0 ffff ffff  `..*......L.....
-000002a0: e640 0c00 0101 0000 24c0 0c00 6015 f22a  .@......$...`..*
-000002b0: 049f ffff f0e4 4cc0 ffff ffff 64b4 0000  ......L.....d...
-000002c0: 0301 0100 24c0 0c00 2011 f22a 049f ffff  ....$... ..*....
-000002d0: 66b9 0000 0201 0000 24c0 0c00 a06e f22a  f.......$....n.*
-000002e0: 049f ffff f0e4 4cc0 ffff ffff 6ae1 4200  ......L.....j.B.
-000002f0: 3e01 1100 24c0 0c00 6a62 6432 2f64 6d2d  >...$...jbd2/dm-
-00000300: 312d 3800 0000 0000 6a01 0000 7800 0000  1-8.....j...x...
-00000310: 0100 0000 0300 0000 269b 0400 0101 0000  ........&.......
-00000320: 24c0 0c00 a06e f22a 049f ffff f0e4 4cc0  $....n.*......L.
-00000330: ffff ffff ff9d 6fb6 1f87 9c00 1000 0000  ......o.........
-00000340: 3b01 0100 24c0 0c00 6b77 6f72 6b65 722f  ;...$...kworker/
-00000350: 7538 3a35 0000 0000 24c0 0c00 7800 0000  u8:5....$...x...
-00000360: 8000 0000 0000 0000 7377 6170 7065 722f  ........swapper/
-00000370: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
-00000380: 6ad2 3802 0401 1100 0000 0000 c800 384b  j.8...........8K
-00000390: 029f ffff 7018 75c0 ffff ffff 00ac edce  ....p.u.........
-000003a0: 039f ffff 0020 0000 0000 0000 c4de 0000  ..... ..........
-000003b0: 0301 1100 0000 0000 c800 384b 029f ffff  ..........8K....
-000003c0: 8a27 0100 3e01 1100 0000 0000 6b77 6f72  .'..>.......kwor
-000003d0: 6b65 722f 303a 3200 0000 0000 48b4 0c00  ker/0:2.....H...
-000003e0: 7800 0000 0100 0000 0000 0000 706d 0800  x...........pm..
-000003f0: 3b01 0100 0000 0000 7377 6170 7065 722f  ;.......swapper/
-00000400: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
-00000410: 0000 0000 0000 0000 6b77 6f72 6b65 722f  ........kworker/
-00000420: 303a 3200 0000 0000 48b4 0c00 7800 0000  0:2.....H...x...
-00000430: 4636 0200 0201 0000 48b4 0c00 c800 384b  F6......H.....8K
-00000440: 029f ffff 7018 75c0 ffff ffff ca56 0500  ....p.u......V..
-00000450: 0401 0100 48b4 0c00 606a ad55 029f ffff  ....H...`j.U....
-00000460: f0e4 4cc0 ffff ffff 002c 04d0 039f ffff  ..L......,......
-00000470: 0020 0000 ffff ffff e435 0000 0301 0100  . .......5......
-00000480: 48b4 0c00 606a ad55 029f ffff ca67 0000  H...`j.U.....g..
-00000490: 3e01 0100 48b4 0c00 6b77 6f72 6b65 722f  >...H...kworker/
-000004a0: 7538 3a35 0000 0000 24c0 0c00 7800 0000  u8:5....$...x...
-000004b0: 0100 0000 0000 0000 e6fc 0200 0101 0000  ................
-000004c0: 48b4 0c00 c800 384b 029f ffff 7018 75c0  H.....8K....p.u.
-000004d0: ffff ffff 708f 0200 3b01 0100 48b4 0c00  ....p...;...H...
-000004e0: 6b77 6f72 6b65 722f 303a 3200 0000 0000  kworker/0:2.....
-000004f0: 48b4 0c00 7800 0000 8000 0000 0000 0000  H...x...........
-00000500: 6b77 6f72 6b65 722f 7538 3a35 0000 0000  kworker/u8:5....
-00000510: 24c0 0c00 7800 0000 0614 0100 0201 0000  $...x...........
-00000520: 24c0 0c00 606a ad55 029f ffff f0e4 4cc0  $...`j.U......L.
-00000530: ffff ffff ea7e 0c00 3e01 0100 24c0 0c00  .....~..>...$...
-00000540: 646d 6372 7970 745f 7772 6974 652f 3200  dmcrypt_write/2.
-00000550: 2601 0000 7800 0000 0100 0000 0100 0000  &...x...........
-00000560: 4645 0200 0101 0000 24c0 0c00 606a ad55  FE......$...`j.U
-00000570: 029f ffff f0e4 4cc0 ffff ffff b043 0900  ......L......C..
-00000580: 3b01 0100 24c0 0c00 6b77 6f72 6b65 722f  ;...$...kworker/
-00000590: 7538 3a35 0000 0000 24c0 0c00 7800 0000  u8:5....$...x...
-000005a0: 8000 0000 0000 0000 7377 6170 7065 722f  ........swapper/
-000005b0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
-000005c0: ca7a 3900 0401 1100 0000 0000 48bc d5a1  .z9.........H...
-000005d0: 029f ffff 10e2 62bb ffff ffff 00e0 40d0  ......b.......@.
-000005e0: 039f ffff 0020 0000 0000 0000 c4bb 0000  ..... ..........
-000005f0: 0301 1100 0000 0000 48bc d5a1 029f ffff  ........H.......
-00000600: 2aea 0000 3e01 1100 0000 0000 6b77 6f72  *...>.......kwor
-00000610: 6b65 722f 303a 3148 0000 0000 cfc1 0c00  ker/0:1H........
-00000620: 6400 0000 0100 0000 0000 0000 90bb 0600  d...............
-00000630: 3b01 0100 0000 0000 7377 6170 7065 722f  ;.......swapper/
-00000640: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
-00000650: 0000 0000 0000 0000 6b77 6f72 6b65 722f  ........kworker/
-00000660: 303a 3148 0000 0000 cfc1 0c00 6400 0000  0:1H........d...
-00000670: 8617 0200 0201 0000 cfc1 0c00 48bc d5a1  ............H...
-00000680: 029f ffff 10e2 62bb ffff ffff c68f 0400  ......b.........
-00000690: 0101 0000 cfc1 0c00 48bc d5a1 029f ffff  ........H.......
-000006a0: 10e2 62bb ffff ffff b063 0300 3b01 0100  ..b......c..;...
-000006b0: cfc1 0c00 6b77 6f72 6b65 722f 303a 3148  ....kworker/0:1H
-000006c0: 0000 0000 cfc1 0c00 6400 0000 8000 0000  ........d.......
-000006d0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
-000006e0: 0000 0000 0000 0000 7800 0000 4a10 ad01  ........x...J...
-000006f0: 3e01 1100 0000 0000 6a62 6432 2f64 6d2d  >.......jbd2/dm-
-00000700: 312d 3800 0000 0000 6a01 0000 7800 0000  1-8.....j...x...
-00000710: 0100 0000 0300 0000 ea27 b900 3e01 1100  .........'..>...
-00000720: 0000 0000 7263 755f 7363 6865 6400 0000  ....rcu_sched...
-00000730: 0000 0000 0d00 0000 7800 0000 0100 0000  ........x.......
-00000740: 0200 0000 3d00 0000 2c00 0000 0000 0000  ....=...,.......
-00000750: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000760: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-00000770: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-  )";
-
-TEST(CpuReaderTest, ParseAbsoluteTimestamp) {
-  BundleProvider bundle_provider(base::kPageSize);
-  auto page = PageFromXxd(g_abs_timestamp);
-
-  // Hand-build a translation table that handles sched_switch for this test
-  // page. We cannot reuse the test data format file, since the ftrace id for
-  // sched_switch in this page is different.
-  std::vector<Field> common_fields;
-  {  // common_pid
-    common_fields.emplace_back(Field{});
-    Field* field = &common_fields.back();
-    field->ftrace_offset = 4;
-    field->ftrace_size = 4;
-    field->ftrace_type = kFtraceCommonPid32;
-    field->proto_field_id = 2;
-    field->proto_field_type = ProtoSchemaType::kInt32;
-    SetTranslationStrategy(field->ftrace_type, field->proto_field_type,
-                           &field->strategy);
-  }
-  Event sched_switch_event{
-      "sched_switch",
-      "sched",
-      {
-          {8, 16, FtraceFieldType::kFtraceFixedCString, "prev_comm", 1,
-           ProtoSchemaType::kString,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {24, 4, FtraceFieldType::kFtracePid32, "prev_pid", 2,
-           ProtoSchemaType::kInt32,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {28, 4, FtraceFieldType::kFtraceInt32, "prev_prio", 3,
-           ProtoSchemaType::kInt32,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {32, 8, FtraceFieldType::kFtraceInt64, "prev_state", 4,
-           ProtoSchemaType::kInt64,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {40, 16, FtraceFieldType::kFtraceFixedCString, "next_comm", 5,
-           ProtoSchemaType::kString,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {56, 4, FtraceFieldType::kFtracePid32, "next_pid", 6,
-           ProtoSchemaType::kInt32,
-           TranslationStrategy::kInvalidTranslationStrategy},
-          {60, 4, FtraceFieldType::kFtraceInt32, "next_prio", 7,
-           ProtoSchemaType::kInt32,
-           TranslationStrategy::kInvalidTranslationStrategy},
-      },
-      /*ftrace_event_id=*/315,
-      /*proto_field_id=*/4,
-      /*size=*/64};
-  for (Field& field : sched_switch_event.fields) {
-    SetTranslationStrategy(field.ftrace_type, field.proto_field_type,
-                           &field.strategy);
-  }
-  std::vector<Event> events;
-  events.emplace_back(std::move(sched_switch_event));
-
-  NiceMock<MockFtraceProcfs> mock_ftrace;
-  PrintkMap printk_formats;
-  ProtoTranslationTable translation_table(
-      &mock_ftrace, events, std::move(common_fields),
-      ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-      InvalidCompactSchedEventFormatForTesting(), printk_formats);
-  ProtoTranslationTable* table = &translation_table;
-
-  FtraceDataSourceConfig ds_config = EmptyConfig();
-  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);
-
-  ASSERT_LT(0u, evt_bytes);
-
-  auto bundle = bundle_provider.ParseProto();
-  ASSERT_TRUE(bundle);
-
-  // There should be 9 sched_switch events within the above page.
-  // We assert that all of their timestamps are exactly as expected.
-  //
-  // The key record that we're testing is an absolute timestamp
-  // (RINGBUF_TYPE_TIME_STAMP) between the 3rd and 4th sched_switch events.
-  //
-  // This timestamp record starts at 0x334 bytes into the page.
-  // The event header (first 4 bytes): 0xb66f9dff
-  // -> type (bottom 5 bits): 31 (RINGBUF_TYPE_TIME_STAMP)
-  // -> bottom 27 bits of ts: 0x5b37cef
-  // Next 4 bytes have the top bits (28..59) of ts.
-  // -> post-shift: 0x4e438f8000000
-  // Adding the two parts of the timestamp, we get: 1376833332542703.
-  //
-  // The next event (sched_switch at 0x33c) after this timestamp has a
-  // delta-timestamp of 0 in its event header, so we expect the 4th
-  // sched_switch to have a timestamp of exactly 1376833332542703.
-  EXPECT_EQ(bundle->event().size(), 9u);
-
-  std::vector<uint64_t> switch_timestamps;
-  for (const auto& e : bundle->event())
-    switch_timestamps.push_back(e.timestamp());
-
-  uint64_t expected_timestamps[] = {
-      1376833327307547ull, 1376833327356434ull, 1376833332265799ull,
-      1376833332542703ull, 1376833333729055ull, 1376833333757142ull,
-      1376833333808564ull, 1376833333943445ull, 1376833333964012ull};
-
-  ASSERT_THAT(switch_timestamps,
-              testing::ElementsAreArray(expected_timestamps));
-}
-
 TEST(CpuReaderTest, TranslateBlockDeviceIDToUserspace) {
   const uint32_t kKernelBlockDeviceId = 271581216;
   const BlockDeviceID kUserspaceBlockDeviceId = 66336;
@@ -1909,95 +1646,6 @@
 // clang-format off
 // # tracer: nop
 // #
-// # entries-in-buffer/entries-written: 18/18   #P:8
-// #
-// #                              _-----=> irqs-off
-// #                             / _----=> need-resched
-// #                            | / _---=> hardirq/softirq
-// #                            || / _--=> preempt-depth
-// #                            ||| /     delay
-// #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
-// #              | |       |   ||||       |         |
-//            <...>-9290  [000] ....  1352.654573: suspend_resume: sync_filesystems[0] end
-//            <...>-9290  [000] ....  1352.665366: suspend_resume: freeze_processes[0] begin
-//            <...>-9290  [000] ....  1352.699711: suspend_resume: freeze_processes[0] end
-//            <...>-9290  [000] ....  1352.699718: suspend_resume: suspend_enter[1] end
-//            <...>-9290  [000] ....  1352.699723: suspend_resume: dpm_prepare[2] begin
-//            <...>-9290  [000] ....  1352.703470: suspend_resume: dpm_prepare[2] end
-//            <...>-9290  [000] ....  1352.703477: suspend_resume: dpm_suspend[2] begin
-//            <...>-9290  [000] ....  1352.720107: suspend_resume: dpm_resume[16] end
-//            <...>-9290  [000] ....  1352.720113: suspend_resume: dpm_complete[16] begin
-//            <...>-9290  [000] .n..  1352.724540: suspend_resume: dpm_complete[16] end
-//            <...>-9290  [000] ....  1352.724567: suspend_resume: resume_console[1] begin
-//            <...>-9290  [000] ....  1352.724570: suspend_resume: resume_console[1] end
-//            <...>-9290  [000] ....  1352.724574: suspend_resume: thaw_processes[0] begin
-static ExamplePage g_suspend_resume {
-    "synthetic",
-    R"(00000000: edba 155a 3201 0000 7401 0000 0000 0000  ...Z2...t.......
-00000010: 7e58 22cd 1201 0000 0600 0000 ac00 0000  ~X".............
-00000020: 4a24 0000 5a7a f504 85ff ffff 0000 0000  J$..Zz..........
-00000030: 0017 0000 c621 9614 ac00 0000 4a24 0000  .....!......J$..
-00000040: 1c7a f504 85ff ffff 0000 0000 0100 0000  .z..............
-00000050: e6f1 8141 ac00 0000 4a24 0000 1c7a f504  ...A....J$...z..
-00000060: 85ff ffff 0000 0000 0000 0000 8682 0300  ................
-00000070: ac00 0000 4a24 0000 4c7a f504 85ff ffff  ....J$..Lz......
-00000080: 0100 0000 0063 755f 0657 0200 ac00 0000  .....cu_.W......
-00000090: 4a24 0000 8ad5 0105 85ff ffff 0200 0000  J$..............
-000000a0: 0100 0000 06b5 2507 ac00 0000 4a24 0000  ......%.....J$..
-000000b0: 8ad5 0105 85ff ffff 0200 0000 0000 0000  ................
-000000c0: 460d 0300 ac00 0000 4a24 0000 51d5 0105  F.......J$..Q...
-000000d0: 85ff ffff 0200 0000 0117 0000 c63e b81f  .............>..
-000000e0: ac00 0000 4a24 0000 7fd5 0105 85ff ffff  ....J$..........
-000000f0: 1000 0000 0010 0b00 a6f9 0200 ac00 0000  ................
-00000100: 4a24 0000 96d5 0105 85ff ffff 1000 0000  J$..............
-00000110: 01c0 1f00 a6dd 7108 ac00 0400 4a24 0000  ......q.....J$..
-00000120: 96d5 0105 85ff ffff 1000 0000 0000 0000  ................
-00000130: c6f1 0c00 ac00 0000 4a24 0000 3d7a f504  ........J$..=z..
-00000140: 85ff ffff 0100 0000 01ea 24d5 a66c 0100  ..........$..l..
-00000150: ac00 0000 4a24 0000 3d7a f504 85ff ffff  ....J$..=z......
-00000160: 0100 0000 0000 0001 6636 0200 ac00 0000  ........f6......
-00000170: 4a24 0000 d178 f504 85ff ffff 0000 0000  J$...x..........
-00000180: 0100 0000 0000 0000 0000 0000 0000 0000  ................
-00000190: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-)"};
-
-TEST(CpuReaderTest, ParseSuspendResume) {
-  const ExamplePage* test_case = &g_suspend_resume;
-
-  BundleProvider bundle_provider(base::kPageSize);
-  ProtoTranslationTable* table = GetTable(test_case->name);
-  auto page = PageFromXxd(test_case->data);
-
-  FtraceDataSourceConfig ds_config = EmptyConfig();
-  ds_config.event_filter.AddEnabledEvent(
-      table->EventToFtraceId(GroupAndName("power", "suspend_resume")));
-
-  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());
-
-  CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-  auto bundle = bundle_provider.ParseProto();
-  ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 13u);
-  EXPECT_EQ(bundle->event()[0].suspend_resume().action(), "sync_filesystems");
-  EXPECT_EQ(bundle->event()[1].suspend_resume().action(), "freeze_processes");
-  EXPECT_EQ(bundle->event()[2].suspend_resume().action(), "freeze_processes");
-  EXPECT_EQ(bundle->event()[3].suspend_resume().action(), "suspend_enter");
-  // dpm_prepare deliberately missing from:
-  // src/traced/probes/ftrace/test/data/synthetic/printk_formats to ensure we
-  // handle that case correctly.
-  EXPECT_EQ(bundle->event()[4].suspend_resume().action(), "");
-}
-
-// clang-format off
-// # tracer: nop
-// #
 // # entries-in-buffer/entries-written: 1041/238740   #P:8
 // #
 // #                              _-----=> irqs-off
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index b8c23e2..afe73a1 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -1009,142 +1009,6 @@
        kUnsetFtraceId,
        112,
        kUnsetSize},
-      {"cpuhp_exit",
-       "cpuhp",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       343,
-       kUnsetSize},
-      {"cpuhp_multi_enter",
-       "cpuhp",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fun", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       344,
-       kUnsetSize},
-      {"cpuhp_enter",
-       "cpuhp",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fun", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       345,
-       kUnsetSize},
-      {"cpuhp_latency",
-       "cpuhp",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "time", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       346,
-       kUnsetSize},
-      {"cpuhp_pause",
-       "cpuhp",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "active_cpus", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpus", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pause", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "time", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       352,
-       kUnsetSize},
-      {"dma_heap_stat",
-       "dmabuf_heap",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "inode", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "total_allocated", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       351,
-       kUnsetSize},
-      {"tracing_mark_write",
-       "dpu",
-       {
-           {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},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       348,
-       kUnsetSize},
       {"ext4_da_write_begin",
        "ext4",
        {
@@ -3959,22 +3823,6 @@
        kUnsetFtraceId,
        273,
        kUnsetSize},
-      {"fastrpc_dma_stat",
-       "fastrpc",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "total_allocated", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       347,
-       kUnsetSize},
       {"fence_init",
        "fence",
        {
@@ -4105,25 +3953,6 @@
        kUnsetFtraceId,
        3,
        kUnsetSize},
-      {"tracing_mark_write",
-       "g2d",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       349,
-       kUnsetSize},
       {"gpu_mem_total",
        "gpu_mem",
        {
@@ -5204,25 +5033,6 @@
        kUnsetFtraceId,
        35,
        kUnsetSize},
-      {"tracing_mark_write",
-       "mali",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       350,
-       kUnsetSize},
       {"mdp_cmd_kickoff",
        "mdss",
        {
@@ -6176,42 +5986,6 @@
        kUnsetFtraceId,
        242,
        kUnsetSize},
-      {"sched_pi_setprio",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "newprio", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "oldprio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       353,
-       kUnsetSize},
-      {"scm_call_start",
-       "scm",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "arginfo", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "x0", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "x5", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       338,
-       kUnsetSize},
-      {"scm_call_end", "scm", {}, kUnsetFtraceId, 339, kUnsetSize},
       {"tracing_mark_write",
        "sde",
        {
@@ -6234,140 +6008,6 @@
        kUnsetFtraceId,
        333,
        kUnsetSize},
-      {"sde_evtlog",
-       "sde",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "evtlog_tag", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tag_id", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       354,
-       kUnsetSize},
-      {"sde_perf_calc_crtc",
-       "sde",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_ebi", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_llcc", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_mnoc", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "core_clk_rate", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "crtc", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ib_ebi", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ib_llcc", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ib_mnoc", 8, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       355,
-       kUnsetSize},
-      {"sde_perf_crtc_update",
-       "sde",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_ebi", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_llcc", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bw_ctl_mnoc", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "core_clk_rate", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "crtc", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "params", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "per_pipe_ib_ebi", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "per_pipe_ib_llcc", 8, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "per_pipe_ib_mnoc", 9, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "stop_req", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "update_bus", 11, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "update_clk", 12, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       356,
-       kUnsetSize},
-      {"sde_perf_set_qos_luts",
-       "sde",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fl", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fmt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lut", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lut_usage", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rt", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       357,
-       kUnsetSize},
-      {"sde_perf_update_bus",
-       "sde",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ab_quota", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bus_id", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ib_quota", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       358,
-       kUnsetSize},
       {"signal_deliver",
        "signal",
        {
@@ -6508,38 +6148,6 @@
        kUnsetFtraceId,
        236,
        kUnsetSize},
-      {"thermal_temperature",
-       "thermal",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "temp", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "temp_prev", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "thermal_zone", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       341,
-       kUnsetSize},
-      {"cdev_update",
-       "thermal",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       342,
-       kUnsetSize},
       {"mm_vmscan_direct_reclaim_begin",
        "vmscan",
        {
diff --git a/src/traced/probes/ftrace/event_info_constants.cc b/src/traced/probes/ftrace/event_info_constants.cc
index a3e59d2..5c020d9 100644
--- a/src/traced/probes/ftrace/event_info_constants.cc
+++ b/src/traced/probes/ftrace/event_info_constants.cc
@@ -99,8 +99,6 @@
     *out = kBoolToUint64;
   } else if (ftrace == kFtraceDataLoc && proto == ProtoSchemaType::kString) {
     *out = kDataLocToString;
-  } else if (ftrace == kFtraceSymAddr64 && proto == ProtoSchemaType::kUint64) {
-    *out = kFtraceSymAddr64ToUint64;
   } else {
     PERFETTO_DLOG("No translation strategy for '%s' -> '%s'", ToString(ftrace),
                   ProtoSchemaToString(proto));
diff --git a/src/traced/probes/ftrace/event_info_constants.h b/src/traced/probes/ftrace/event_info_constants.h
index 0283f12..923ee62 100644
--- a/src/traced/probes/ftrace/event_info_constants.h
+++ b/src/traced/probes/ftrace/event_info_constants.h
@@ -48,7 +48,6 @@
   kFtraceDevId32,
   kFtraceDevId64,
   kFtraceDataLoc,
-  kFtraceSymAddr64,
 };
 
 // Joint enum of FtraceFieldType (left) and ProtoFieldType (right).
@@ -84,7 +83,6 @@
   kDevId32ToUint64,
   kDevId64ToUint64,
   kDataLocToString,
-  kFtraceSymAddr64ToUint64,
 };
 
 inline const char* ToString(FtraceFieldType v) {
@@ -127,8 +125,6 @@
       return "devid64";
     case kFtraceDataLoc:
       return "__data_loc";
-    case kFtraceSymAddr64:
-      return "void*";
     case kInvalidFtraceFieldType:
       break;
   }
diff --git a/src/traced/probes/ftrace/event_info_unittest.cc b/src/traced/probes/ftrace/event_info_unittest.cc
index 5fbee6d..6c3f9d8 100644
--- a/src/traced/probes/ftrace/event_info_unittest.cc
+++ b/src/traced/probes/ftrace/event_info_unittest.cc
@@ -23,7 +23,7 @@
 namespace {
 using protozero::proto_utils::ProtoSchemaType;
 
-TEST(EventInfoTest, GetStaticEventInfoValidations) {
+TEST(EventInfoTest, GetStaticEventInfoSanityCheck) {
   std::vector<Event> events = GetStaticEventInfo();
   for (const Event& event : events) {
     // For each event the following fields should be filled
@@ -53,7 +53,7 @@
   }
 }
 
-TEST(EventInfoTest, GetStaticCommonFieldsInfoValidations) {
+TEST(EventInfoTest, GetStaticCommonFieldsInfoSanityCheck) {
   std::vector<Field> fields = GetStaticCommonFieldsInfo();
   for (const Field& field : fields) {
     // Non-empty name, group, and proto field id.
@@ -69,7 +69,7 @@
   }
 }
 
-TEST(EventInfoTest, SetTranslationStrategyValidations) {
+TEST(EventInfoTest, SetTranslationStrategySanityCheck) {
   TranslationStrategy strategy = kUint32ToUint32;
   ASSERT_FALSE(SetTranslationStrategy(kFtraceCString, ProtoSchemaType::kUint64,
                                       &strategy));
diff --git a/src/traced/probes/ftrace/format_parser.cc b/src/traced/probes/ftrace/format_parser.cc
new file mode 100644
index 0000000..2be687d
--- /dev/null
+++ b/src/traced/probes/ftrace/format_parser.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.
+ */
+
+#include "src/traced/probes/ftrace/format_parser.h"
+
+#include <string.h>
+
+#include <iosfwd>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace {
+
+#define MAX_FIELD_LENGTH 127
+#define STRINGIFY(x) STRINGIFY2(x)
+#define STRINGIFY2(x) #x
+
+const char* kCommonFieldPrefix = "common_";
+
+bool IsCommonFieldName(const std::string& name) {
+  return name.compare(0, strlen(kCommonFieldPrefix), kCommonFieldPrefix) == 0;
+}
+
+bool IsCIdentifier(const std::string& s) {
+  for (const char c : s) {
+    if (!(std::isalnum(c) || c == '_'))
+      return false;
+  }
+  return !s.empty() && !std::isdigit(s[0]);
+}
+
+bool ParseFtraceEventBody(base::StringSplitter* ss,
+                          std::vector<FtraceEvent::Field>* common_fields,
+                          std::vector<FtraceEvent::Field>* fields,
+                          bool disable_logging_for_testing) {
+  PERFETTO_DCHECK(common_fields || fields);
+  char buffer[MAX_FIELD_LENGTH + 1];
+  while (ss->Next()) {
+    const char* line = ss->cur_token();
+    uint16_t offset = 0;
+    uint16_t size = 0;
+    int is_signed = 0;
+    if (sscanf(line,
+               "\tfield:%" STRINGIFY(MAX_FIELD_LENGTH) "[^;];\toffset: "
+                                                       "%hu;\tsize: "
+                                                       "%hu;\tsigned: %d;",
+               buffer, &offset, &size, &is_signed) == 4) {
+      std::string type_and_name(buffer);
+
+      FtraceEvent::Field field{type_and_name, offset, size, is_signed == 1};
+
+      if (IsCommonFieldName(GetNameFromTypeAndName(type_and_name))) {
+        if (common_fields)
+          common_fields->push_back(field);
+      } else if (fields) {
+        fields->push_back(field);
+      }
+      continue;
+    }
+
+    if (strncmp(line, "print fmt:", 10) == 0) {
+      break;
+    }
+
+    if (!disable_logging_for_testing)
+      PERFETTO_DLOG("Cannot parse line: \"%s\"\n", line);
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+// For example:
+// "int foo" -> "foo"
+// "u8 foo[(int)sizeof(struct blah)]" -> "foo"
+// "char[] foo[16]" -> "foo"
+// "something_went_wrong" -> ""
+// "" -> ""
+std::string GetNameFromTypeAndName(const std::string& type_and_name) {
+  size_t right = type_and_name.size();
+  if (right == 0)
+    return "";
+
+  if (type_and_name[type_and_name.size() - 1] == ']') {
+    right = type_and_name.rfind('[');
+    if (right == std::string::npos)
+      return "";
+  }
+
+  size_t left = type_and_name.rfind(' ', right);
+  if (left == std::string::npos)
+    return "";
+  left++;
+
+  std::string result = type_and_name.substr(left, right - left);
+  if (!IsCIdentifier(result))
+    return "";
+
+  return result;
+}
+
+bool ParseFtraceEventBody(std::string input,
+                          std::vector<FtraceEvent::Field>* common_fields,
+                          std::vector<FtraceEvent::Field>* fields,
+                          bool disable_logging_for_testing) {
+  base::StringSplitter ss(std::move(input), '\n');
+  return ParseFtraceEventBody(&ss, common_fields, fields,
+                              disable_logging_for_testing);
+}
+
+bool ParseFtraceEvent(std::string input, FtraceEvent* output) {
+  char buffer[MAX_FIELD_LENGTH + 1];
+
+  bool has_id = false;
+  bool has_name = false;
+
+  uint32_t id = 0;
+  std::string name;
+  std::vector<FtraceEvent::Field> common_fields;
+  std::vector<FtraceEvent::Field> fields;
+
+  for (base::StringSplitter ss(std::move(input), '\n'); ss.Next();) {
+    const char* line = ss.cur_token();
+    if (!has_id && sscanf(line, "ID: %u", &id) == 1) {
+      has_id = true;
+      continue;
+    }
+
+    if (!has_name &&
+        sscanf(line, "name: %" STRINGIFY(MAX_FIELD_LENGTH) "s", buffer) == 1) {
+      name = std::string(buffer);
+      has_name = true;
+      continue;
+    }
+
+    if (strcmp("format:", line) == 0) {
+      ParseFtraceEventBody(&ss, &common_fields, &fields,
+                           /*disable_logging_for_testing=*/output == nullptr);
+      break;
+    }
+
+    if (output)
+      PERFETTO_DLOG("Cannot parse line: \"%s\"\n", line);
+    return false;
+  }
+
+  if (!has_id || !has_name || fields.empty()) {
+    if (output)
+      PERFETTO_DLOG("Could not parse format file: %s.\n",
+                    !has_id ? "no ID found"
+                            : !has_name ? "no name found" : "no fields found");
+    return false;
+  }
+
+  if (!output)
+    return true;
+
+  output->id = id;
+  output->name = name;
+  output->fields = std::move(fields);
+  output->common_fields = std::move(common_fields);
+
+  return true;
+}
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const FtraceEvent::Field& field) {
+  PrintTo(field, &os);
+  return os;
+}
+
+// Allow gtest to pretty print FtraceEvent::Field.
+void PrintTo(const FtraceEvent::Field& field, ::std::ostream* os) {
+  *os << "FtraceEvent::Field(" << field.type_and_name << ", " << field.offset
+      << ", " << field.size << ", " << field.is_signed << ")";
+}
+
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/format_parser.h b/src/traced/probes/ftrace/format_parser.h
new file mode 100644
index 0000000..65716f4
--- /dev/null
+++ b/src/traced/probes/ftrace/format_parser.h
@@ -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.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_H_
+#define SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_H_
+
+#include <stdint.h>
+#include <string>
+
+#include <iosfwd>
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace perfetto {
+
+struct FtraceEvent {
+  struct Field {
+    std::string type_and_name;
+    uint16_t offset;
+    uint16_t size;
+    bool is_signed;
+
+    bool operator==(const Field& other) const {
+      return std::tie(type_and_name, offset, size, is_signed) ==
+             std::tie(other.type_and_name, other.offset, other.size,
+                      other.is_signed);
+    }
+  };
+
+  // When making changes / additions to these structs, remember that
+  // proto_translation_table.cc has some fallback code for 'page_header' and
+  // the 'print' event that fill this struct.
+  std::string name;
+  uint32_t id;
+  std::vector<Field> common_fields;
+  std::vector<Field> fields;
+};
+
+std::string GetNameFromTypeAndName(const std::string& type_and_name);
+
+// Allow gtest to pretty print FtraceEvent::Field.
+::std::ostream& operator<<(::std::ostream& os, const FtraceEvent::Field&);
+void PrintTo(const FtraceEvent::Field& args, ::std::ostream* os);
+
+// Parses only the body (i.e. contents of format) of an ftrace event format
+// file, e.g.
+//
+//   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:dev_t dev;  offset:8;  size:4;  signed:0;
+//   field:ino_t ino;  offset:12;  size:4;  signed:0;
+//   field:ino_t dir;  offset:16;  size:4;  signed:0;
+//   field:__u16 mode;  offset:20;  size:2;  signed:0;
+bool ParseFtraceEventBody(std::string input,
+                          std::vector<FtraceEvent::Field>* common_fields,
+                          std::vector<FtraceEvent::Field>* fields,
+                          bool disable_logging_for_testing = false);
+// Parses ftrace event format file. This includes the headers specifying
+// name and ID of the event, e.g.
+//
+// name: ext4_allocate_inode
+// ID: 309
+// 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:dev_t dev;  offset:8;  size:4;  signed:0;
+//   field:ino_t ino;  offset:12;  size:4;  signed:0;
+//   field:ino_t dir;  offset:16;  size:4;  signed:0;
+//   field:__u16 mode;  offset:20;  size:2;  signed:0;
+bool ParseFtraceEvent(std::string input, FtraceEvent* output = nullptr);
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_H_
diff --git a/src/traced/probes/ftrace/format_parser/BUILD.gn b/src/traced/probes/ftrace/format_parser/BUILD.gn
deleted file mode 100644
index e9aa26e..0000000
--- a/src/traced/probes/ftrace/format_parser/BUILD.gn
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../../../gn/perfetto.gni")
-import("../../../../../gn/test.gni")
-
-source_set("format_parser") {
-  deps = [
-    "../../../../../gn:default_deps",
-    "../../../../base",
-  ]
-  sources = [
-    "format_parser.cc",
-    "format_parser.h",
-  ]
-}
-
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    ":format_parser",
-    "../../../../../gn:default_deps",
-    "../../../../../gn:gtest_and_gmock",
-  ]
-  sources = [ "format_parser_unittest.cc" ]
-}
diff --git a/src/traced/probes/ftrace/format_parser/format_parser.cc b/src/traced/probes/ftrace/format_parser/format_parser.cc
deleted file mode 100644
index 7d5ab59..0000000
--- a/src/traced/probes/ftrace/format_parser/format_parser.cc
+++ /dev/null
@@ -1,200 +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 "src/traced/probes/ftrace/format_parser/format_parser.h"
-
-#include <string.h>
-
-#include <cctype>
-#include <iosfwd>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace {
-
-#define MAX_FIELD_LENGTH 127
-#define STRINGIFY(x) STRINGIFY2(x)
-#define STRINGIFY2(x) #x
-
-const char* kCommonFieldPrefix = "common_";
-
-bool IsCommonFieldName(const std::string& name) {
-  return name.compare(0, strlen(kCommonFieldPrefix), kCommonFieldPrefix) == 0;
-}
-
-bool IsCIdentifier(const std::string& s) {
-  for (const char c : s) {
-    if (!(std::isalnum(c) || c == '_'))
-      return false;
-  }
-  return !s.empty() && !std::isdigit(s[0]);
-}
-
-bool ParseFtraceEventBody(base::StringSplitter* ss,
-                          std::vector<FtraceEvent::Field>* common_fields,
-                          std::vector<FtraceEvent::Field>* fields,
-                          bool disable_logging_for_testing) {
-  PERFETTO_DCHECK(common_fields || fields);
-  char buffer[MAX_FIELD_LENGTH + 1];
-  while (ss->Next()) {
-    const char* line = ss->cur_token();
-    uint16_t offset = 0;
-    uint16_t size = 0;
-    int is_signed = 0;
-    if (sscanf(line,
-               "\tfield:%" STRINGIFY(MAX_FIELD_LENGTH) "[^;];\toffset: "
-                                                       "%hu;\tsize: "
-                                                       "%hu;\tsigned: %d;",
-               buffer, &offset, &size, &is_signed) == 4) {
-      std::string type_and_name(buffer);
-
-      FtraceEvent::Field field{type_and_name, offset, size, is_signed == 1};
-
-      if (IsCommonFieldName(GetNameFromTypeAndName(type_and_name))) {
-        if (common_fields)
-          common_fields->push_back(field);
-      } else if (fields) {
-        fields->push_back(field);
-      }
-      continue;
-    }
-
-    if (strncmp(line, "print fmt:", 10) == 0) {
-      break;
-    }
-
-    if (!disable_logging_for_testing)
-      PERFETTO_DLOG("Cannot parse line: \"%s\"\n", line);
-    return false;
-  }
-  return true;
-}
-
-}  // namespace
-
-// For example:
-// "int foo" -> "foo"
-// "u8 foo[(int)sizeof(struct blah)]" -> "foo"
-// "char[] foo[16]" -> "foo"
-// "something_went_wrong" -> ""
-// "" -> ""
-std::string GetNameFromTypeAndName(const std::string& type_and_name) {
-  size_t right = type_and_name.size();
-  if (right == 0)
-    return "";
-
-  if (type_and_name[type_and_name.size() - 1] == ']') {
-    right = type_and_name.rfind('[');
-    if (right == std::string::npos)
-      return "";
-  }
-
-  size_t left = type_and_name.rfind(' ', right);
-  if (left == std::string::npos)
-    return "";
-  left++;
-
-  std::string result = type_and_name.substr(left, right - left);
-  if (!IsCIdentifier(result))
-    return "";
-
-  return result;
-}
-
-bool ParseFtraceEventBody(std::string input,
-                          std::vector<FtraceEvent::Field>* common_fields,
-                          std::vector<FtraceEvent::Field>* fields,
-                          bool disable_logging_for_testing) {
-  base::StringSplitter ss(std::move(input), '\n');
-  return ParseFtraceEventBody(&ss, common_fields, fields,
-                              disable_logging_for_testing);
-}
-
-bool ParseFtraceEvent(std::string input, FtraceEvent* output) {
-  char buffer[MAX_FIELD_LENGTH + 1];
-
-  bool has_id = false;
-  bool has_name = false;
-
-  uint32_t id = 0;
-  std::string name;
-  std::vector<FtraceEvent::Field> common_fields;
-  std::vector<FtraceEvent::Field> fields;
-
-  for (base::StringSplitter ss(std::move(input), '\n'); ss.Next();) {
-    const char* line = ss.cur_token();
-    if (!has_id && sscanf(line, "ID: %u", &id) == 1) {
-      has_id = true;
-      continue;
-    }
-
-    if (!has_name &&
-        sscanf(line, "name: %" STRINGIFY(MAX_FIELD_LENGTH) "s", buffer) == 1) {
-      name = std::string(buffer);
-      has_name = true;
-      continue;
-    }
-
-    if (strcmp("format:", line) == 0) {
-      ParseFtraceEventBody(&ss, &common_fields, &fields,
-                           /*disable_logging_for_testing=*/output == nullptr);
-      break;
-    }
-
-    if (output)
-      PERFETTO_DLOG("Cannot parse line: \"%s\"\n", line);
-    return false;
-  }
-
-  if (!has_id || !has_name || fields.empty()) {
-    if (output)
-      PERFETTO_DLOG("Could not parse format file: %s.\n",
-                    !has_id ? "no ID found"
-                            : !has_name ? "no name found" : "no fields found");
-    return false;
-  }
-
-  if (!output)
-    return true;
-
-  output->id = id;
-  output->name = name;
-  output->fields = std::move(fields);
-  output->common_fields = std::move(common_fields);
-
-  return true;
-}
-
-::std::ostream& operator<<(::std::ostream& os,
-                           const FtraceEvent::Field& field) {
-  PrintTo(field, &os);
-  return os;
-}
-
-// Allow gtest to pretty print FtraceEvent::Field.
-void PrintTo(const FtraceEvent::Field& field, ::std::ostream* os) {
-  *os << "FtraceEvent::Field(" << field.type_and_name << ", " << field.offset
-      << ", " << field.size << ", " << field.is_signed << ")";
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/format_parser/format_parser.h b/src/traced/probes/ftrace/format_parser/format_parser.h
deleted file mode 100644
index a8a5cdb..0000000
--- a/src/traced/probes/ftrace/format_parser/format_parser.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 SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_FORMAT_PARSER_H_
-#define SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_FORMAT_PARSER_H_
-
-#include <stdint.h>
-#include <string>
-
-#include <iosfwd>
-#include <iostream>
-#include <string>
-#include <tuple>
-#include <vector>
-
-namespace perfetto {
-
-struct FtraceEvent {
-  struct Field {
-    std::string type_and_name;
-    uint16_t offset;
-    uint16_t size;
-    bool is_signed;
-
-    bool operator==(const Field& other) const {
-      return std::tie(type_and_name, offset, size, is_signed) ==
-             std::tie(other.type_and_name, other.offset, other.size,
-                      other.is_signed);
-    }
-  };
-
-  // When making changes / additions to these structs, remember that
-  // proto_translation_table.cc has some fallback code for 'page_header' and
-  // the 'print' event that fill this struct.
-  std::string name;
-  uint32_t id;
-  std::vector<Field> common_fields;
-  std::vector<Field> fields;
-};
-
-std::string GetNameFromTypeAndName(const std::string& type_and_name);
-
-// Allow gtest to pretty print FtraceEvent::Field.
-::std::ostream& operator<<(::std::ostream& os, const FtraceEvent::Field&);
-void PrintTo(const FtraceEvent::Field& args, ::std::ostream* os);
-
-// Parses only the body (i.e. contents of format) of an ftrace event format
-// file, e.g.
-//
-//   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:dev_t dev;  offset:8;  size:4;  signed:0;
-//   field:ino_t ino;  offset:12;  size:4;  signed:0;
-//   field:ino_t dir;  offset:16;  size:4;  signed:0;
-//   field:__u16 mode;  offset:20;  size:2;  signed:0;
-bool ParseFtraceEventBody(std::string input,
-                          std::vector<FtraceEvent::Field>* common_fields,
-                          std::vector<FtraceEvent::Field>* fields,
-                          bool disable_logging_for_testing = false);
-// Parses ftrace event format file. This includes the headers specifying
-// name and ID of the event, e.g.
-//
-// name: ext4_allocate_inode
-// ID: 309
-// 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:dev_t dev;  offset:8;  size:4;  signed:0;
-//   field:ino_t ino;  offset:12;  size:4;  signed:0;
-//   field:ino_t dir;  offset:16;  size:4;  signed:0;
-//   field:__u16 mode;  offset:20;  size:2;  signed:0;
-bool ParseFtraceEvent(std::string input, FtraceEvent* output = nullptr);
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_FTRACE_FORMAT_PARSER_FORMAT_PARSER_H_
diff --git a/src/traced/probes/ftrace/format_parser/format_parser_unittest.cc b/src/traced/probes/ftrace/format_parser/format_parser_unittest.cc
deleted file mode 100644
index f4e9523..0000000
--- a/src/traced/probes/ftrace/format_parser/format_parser_unittest.cc
+++ /dev/null
@@ -1,145 +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 "src/traced/probes/ftrace/format_parser/format_parser.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-using testing::ElementsAre;
-using testing::Eq;
-
-TEST(FtraceEventParserTest, HappyPath) {
-  const std::string input = R"(name: the_name
-ID: 42
-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 client_name[64];	offset:8;	size:64;	signed:0;
-	field:const char * heap_name;	offset:72;	size:4;	signed:1;
-
-print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
-)";
-
-  FtraceEvent output;
-  EXPECT_TRUE(ParseFtraceEvent(input));
-  EXPECT_TRUE(ParseFtraceEvent(input, &output));
-  EXPECT_EQ(output.name, "the_name");
-  EXPECT_EQ(output.id, 42u);
-  EXPECT_THAT(
-      output.fields,
-      ElementsAre(
-          Eq(FtraceEvent::Field{"char client_name[64]", 8, 64, false}),
-          Eq(FtraceEvent::Field{"const char * heap_name", 72, 4, true})));
-  EXPECT_THAT(
-      output.common_fields,
-      ElementsAre(
-          Eq(FtraceEvent::Field{"unsigned short common_type", 0, 2, false}),
-          Eq(FtraceEvent::Field{"unsigned char common_flags", 2, 1, false}),
-          Eq(FtraceEvent::Field{"unsigned char common_preempt_count", 3, 1,
-                                false}),
-          Eq(FtraceEvent::Field{"int common_pid", 4, 4, true})));
-}
-
-TEST(FtraceEventParserTest, MissingName) {
-  const std::string input = R"(ID: 42
-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;
-
-print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
-)";
-
-  EXPECT_FALSE(ParseFtraceEvent(input));
-}
-
-TEST(FtraceEventParserTest, MissingID) {
-  const std::string input = R"(name: the_name
-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;
-
-print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
-)";
-
-  EXPECT_FALSE(ParseFtraceEvent(input));
-}
-
-TEST(FtraceEventParserTest, NoFields) {
-  const std::string input = R"(name: the_name
-ID: 10
-print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
-)";
-
-  EXPECT_FALSE(ParseFtraceEvent(input));
-}
-
-TEST(FtraceEventParserTest, BasicFuzzing) {
-  const std::string input = R"(name: the_name
-ID: 42
-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 client_name[64];	offset:8;	size:64;	signed:0;
-	field:const char * heap_name;	offset:72;	size:4;	signed:0;
-	field:size_t len;	offset:76;	size:4;	signed:0;
-	field:unsigned int mask;	offset:80;	size:4;	signed:0;
-	field:unsigned int flags;	offset:84;	size:4;	signed:0;
-
-print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
-)";
-
-  for (size_t i = 0; i < input.length(); i++) {
-    for (size_t j = 1; j < 10 && i + j < input.length(); j++) {
-      std::string copy = input;
-      copy.erase(i, j);
-      ParseFtraceEvent(copy);
-    }
-  }
-}
-
-TEST(FtraceEventParserTest, GetNameFromTypeAndName) {
-  EXPECT_EQ(GetNameFromTypeAndName("int foo"), "foo");
-  EXPECT_EQ(GetNameFromTypeAndName("int foo_bar"), "foo_bar");
-  EXPECT_EQ(GetNameFromTypeAndName("const char * foo"), "foo");
-  EXPECT_EQ(GetNameFromTypeAndName("const char foo[64]"), "foo");
-  EXPECT_EQ(GetNameFromTypeAndName("char[] foo[16]"), "foo");
-  EXPECT_EQ(GetNameFromTypeAndName("u8 foo[(int)sizeof(struct blah)]"), "foo");
-
-  EXPECT_EQ(GetNameFromTypeAndName(""), "");
-  EXPECT_EQ(GetNameFromTypeAndName("]"), "");
-  EXPECT_EQ(GetNameFromTypeAndName("["), "");
-  EXPECT_EQ(GetNameFromTypeAndName(" "), "");
-  EXPECT_EQ(GetNameFromTypeAndName(" []"), "");
-  EXPECT_EQ(GetNameFromTypeAndName(" ]["), "");
-  EXPECT_EQ(GetNameFromTypeAndName("char"), "");
-  EXPECT_EQ(GetNameFromTypeAndName("char *"), "");
-  EXPECT_EQ(GetNameFromTypeAndName("char 42"), "");
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/format_parser_unittest.cc b/src/traced/probes/ftrace/format_parser_unittest.cc
new file mode 100644
index 0000000..3e92f67
--- /dev/null
+++ b/src/traced/probes/ftrace/format_parser_unittest.cc
@@ -0,0 +1,145 @@
+/*
+ * 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/traced/probes/ftrace/format_parser.h"
+
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+using testing::ElementsAre;
+using testing::Eq;
+
+TEST(FtraceEventParserTest, HappyPath) {
+  const std::string input = R"(name: the_name
+ID: 42
+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 client_name[64];	offset:8;	size:64;	signed:0;
+	field:const char * heap_name;	offset:72;	size:4;	signed:1;
+
+print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
+)";
+
+  FtraceEvent output;
+  EXPECT_TRUE(ParseFtraceEvent(input));
+  EXPECT_TRUE(ParseFtraceEvent(input, &output));
+  EXPECT_EQ(output.name, "the_name");
+  EXPECT_EQ(output.id, 42u);
+  EXPECT_THAT(
+      output.fields,
+      ElementsAre(
+          Eq(FtraceEvent::Field{"char client_name[64]", 8, 64, false}),
+          Eq(FtraceEvent::Field{"const char * heap_name", 72, 4, true})));
+  EXPECT_THAT(
+      output.common_fields,
+      ElementsAre(
+          Eq(FtraceEvent::Field{"unsigned short common_type", 0, 2, false}),
+          Eq(FtraceEvent::Field{"unsigned char common_flags", 2, 1, false}),
+          Eq(FtraceEvent::Field{"unsigned char common_preempt_count", 3, 1,
+                                false}),
+          Eq(FtraceEvent::Field{"int common_pid", 4, 4, true})));
+}
+
+TEST(FtraceEventParserTest, MissingName) {
+  const std::string input = R"(ID: 42
+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;
+
+print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
+)";
+
+  EXPECT_FALSE(ParseFtraceEvent(input));
+}
+
+TEST(FtraceEventParserTest, MissingID) {
+  const std::string input = R"(name: the_name
+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;
+
+print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
+)";
+
+  EXPECT_FALSE(ParseFtraceEvent(input));
+}
+
+TEST(FtraceEventParserTest, NoFields) {
+  const std::string input = R"(name: the_name
+ID: 10
+print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
+)";
+
+  EXPECT_FALSE(ParseFtraceEvent(input));
+}
+
+TEST(FtraceEventParserTest, BasicFuzzing) {
+  const std::string input = R"(name: the_name
+ID: 42
+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 client_name[64];	offset:8;	size:64;	signed:0;
+	field:const char * heap_name;	offset:72;	size:4;	signed:0;
+	field:size_t len;	offset:76;	size:4;	signed:0;
+	field:unsigned int mask;	offset:80;	size:4;	signed:0;
+	field:unsigned int flags;	offset:84;	size:4;	signed:0;
+
+print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
+)";
+
+  for (size_t i = 0; i < input.length(); i++) {
+    for (size_t j = 1; j < 10 && i + j < input.length(); j++) {
+      std::string copy = input;
+      copy.erase(i, j);
+      ParseFtraceEvent(copy);
+    }
+  }
+}
+
+TEST(FtraceEventParserTest, GetNameFromTypeAndName) {
+  EXPECT_EQ(GetNameFromTypeAndName("int foo"), "foo");
+  EXPECT_EQ(GetNameFromTypeAndName("int foo_bar"), "foo_bar");
+  EXPECT_EQ(GetNameFromTypeAndName("const char * foo"), "foo");
+  EXPECT_EQ(GetNameFromTypeAndName("const char foo[64]"), "foo");
+  EXPECT_EQ(GetNameFromTypeAndName("char[] foo[16]"), "foo");
+  EXPECT_EQ(GetNameFromTypeAndName("u8 foo[(int)sizeof(struct blah)]"), "foo");
+
+  EXPECT_EQ(GetNameFromTypeAndName(""), "");
+  EXPECT_EQ(GetNameFromTypeAndName("]"), "");
+  EXPECT_EQ(GetNameFromTypeAndName("["), "");
+  EXPECT_EQ(GetNameFromTypeAndName(" "), "");
+  EXPECT_EQ(GetNameFromTypeAndName(" []"), "");
+  EXPECT_EQ(GetNameFromTypeAndName(" ]["), "");
+  EXPECT_EQ(GetNameFromTypeAndName("char"), "");
+  EXPECT_EQ(GetNameFromTypeAndName("char *"), "");
+  EXPECT_EQ(GetNameFromTypeAndName("char 42"), "");
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index 24b84b5..5c85e11 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -61,7 +61,7 @@
 
 std::pair<std::string, std::string> EventToStringGroupAndName(
     const std::string& event) {
-  auto slash_pos = event.find('/');
+  auto slash_pos = event.find("/");
   if (slash_pos == std::string::npos)
     return std::make_pair("", event);
   return std::make_pair(event.substr(0, slash_pos),
@@ -151,8 +151,7 @@
         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", &events);
-        events.insert(GroupAndName("mali", "tracing_mark_write"));
+        AddEventGroup(table, "mali_systrace", &events);
 
         AddEventGroup(table, "sde", &events);
         events.insert(GroupAndName("sde", "tracing_mark_write"));
@@ -165,13 +164,6 @@
         events.insert(GroupAndName("sde", "sde_evtlog"));
         events.insert(GroupAndName("sde", "sde_encoder_underrun"));
         events.insert(GroupAndName("sde", "sde_cmd_release_bw"));
-
-        AddEventGroup(table, "dpu", &events);
-        events.insert(GroupAndName("dpu", "tracing_mark_write"));
-
-        AddEventGroup(table, "g2d", &events);
-        events.insert(GroupAndName("g2d", "tracing_mark_write"));
-        events.insert(GroupAndName("g2d", "g2d_perf_update_qos"));
         continue;
       }
 
@@ -267,9 +259,6 @@
         events.insert(GroupAndName("clk", "clk_enable"));
         events.insert(GroupAndName("power", "cpu_frequency_limits"));
         events.insert(GroupAndName("power", "suspend_resume"));
-        events.insert(GroupAndName("cpuhp", "cpuhp_enter"));
-        events.insert(GroupAndName("cpuhp", "cpuhp_exit"));
-        events.insert(GroupAndName("cpuhp", "cpuhp_pause"));
         AddEventGroup(table, "msm_bus", &events);
         events.insert(GroupAndName("msm_bus", "bus_update_request_end"));
         events.insert(GroupAndName("msm_bus", "bus_update_request"));
@@ -389,6 +378,8 @@
         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"));
@@ -402,13 +393,6 @@
         // ion_stat supersedes ion_heap_grow / shrink for kernel 4.19+
         events.insert(GroupAndName("ion", "ion_stat"));
         events.insert(GroupAndName("mm_event", "mm_event_record"));
-        events.insert(GroupAndName("dmabuf_heap", "dma_heap_stat"));
-        continue;
-      }
-
-      if (category == "thermal") {
-        events.insert(GroupAndName("thermal", "thermal_temperature"));
-        events.insert(GroupAndName("thermal", "cdev_update"));
         continue;
       }
     }
@@ -518,11 +502,12 @@
 
   std::vector<std::string> apps(request.atrace_apps());
   std::vector<std::string> categories(request.atrace_categories());
+
   FtraceConfigId id = ++last_id_;
   ds_configs_.emplace(
       std::piecewise_construct, std::forward_as_tuple(id),
       std::forward_as_tuple(std::move(filter), compact_sched, std::move(apps),
-                            std::move(categories), request.symbolize_ksyms()));
+                            std::move(categories)));
   return id;
 }
 
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.h b/src/traced/probes/ftrace/ftrace_config_muxer.h
index 3965371..dc758ea 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.h
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.h
@@ -34,13 +34,11 @@
   FtraceDataSourceConfig(EventFilter _event_filter,
                          CompactSchedConfig _compact_sched,
                          std::vector<std::string> _atrace_apps,
-                         std::vector<std::string> _atrace_categories,
-                         bool _symbolize_ksyms)
+                         std::vector<std::string> _atrace_categories)
       : event_filter(std::move(_event_filter)),
         compact_sched(_compact_sched),
         atrace_apps(std::move(_atrace_apps)),
-        atrace_categories(std::move(_atrace_categories)),
-        symbolize_ksyms(_symbolize_ksyms) {}
+        atrace_categories(std::move(_atrace_categories)) {}
 
   // The event filter allows to quickly check if a certain ftrace event with id
   // x is enabled for this data source.
@@ -52,9 +50,6 @@
   // Used only in Android for ATRACE_EVENT/os.Trace() userspace annotations.
   std::vector<std::string> atrace_apps;
   std::vector<std::string> atrace_categories;
-
-  // When enabled will turn on the the kallsyms symbolizer in CpuReader.
-  const bool symbolize_ksyms;
 };
 
 // Ftrace is a bunch of globally modifiable persistent state.
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index c3602aa..d9b5911 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -84,8 +84,7 @@
                               events,
                               common_fields,
                               ftrace_page_header_spec,
-                              compact_sched_format,
-                              PrintkMap()) {}
+                              compact_sched_format) {}
   MOCK_METHOD1(GetOrCreateEvent, Event*(const GroupAndName& group_and_name));
   MOCK_CONST_METHOD1(GetEvent,
                      const Event*(const GroupAndName& group_and_name));
@@ -171,7 +170,7 @@
     return std::unique_ptr<ProtoTranslationTable>(new ProtoTranslationTable(
         &table_procfs_, events, std::move(common_fields),
         ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-        compact_format, PrintkMap()));
+        compact_format));
   }
 
   NiceMock<MockFtraceProcfs> table_procfs_;
diff --git a/src/traced/probes/ftrace/ftrace_config_utils.cc b/src/traced/probes/ftrace/ftrace_config_utils.cc
index 9f988e9..a655f72 100644
--- a/src/traced/probes/ftrace/ftrace_config_utils.cc
+++ b/src/traced/probes/ftrace/ftrace_config_utils.cc
@@ -21,14 +21,17 @@
 namespace perfetto {
 namespace {
 
-// Excludes \r, \n, escape sequences and control chars.
-bool IsPrintableASCIIOrSpace(char c) {
-  return c >= 32 && c < 127;
+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 (!IsPrintableASCIIOrSpace(str[i]))
+    if (!isalnum(str[i]) && !IsGoodAtracePunctuation(str[i]))
       return false;
   }
   return true;
@@ -37,7 +40,7 @@
 bool IsValidFtraceEventName(const std::string& str) {
   int slash_count = 0;
   for (size_t i = 0; i < str.size(); i++) {
-    if (!IsPrintableASCIIOrSpace(str[i]))
+    if (!isalnum(str[i]) && !IsGoodFtracePunctuation(str[i]))
       return false;
     if (str[i] == '/') {
       slash_count++;
diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc
index 53ac1e5..da88e3d 100644
--- a/src/traced/probes/ftrace/ftrace_controller.cc
+++ b/src/traced/probes/ftrace/ftrace_controller.cc
@@ -34,8 +34,6 @@
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/metatrace.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
-#include "src/kallsyms/kernel_symbol_map.h"
-#include "src/kallsyms/lazy_kernel_symbolizer.h"
 #include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
 #include "src/traced/probes/ftrace/cpu_reader.h"
 #include "src/traced/probes/ftrace/cpu_stats_parser.h"
@@ -97,6 +95,14 @@
 
 }  // namespace
 
+const char* const FtraceController::kTracingPaths[] = {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+    "/sys/kernel/tracing/", "/sys/kernel/debug/tracing/", nullptr,
+#else
+    "/sys/kernel/debug/tracing/", nullptr,
+#endif
+};
+
 // Method of last resort to reset ftrace state.
 // We don't know what state the rest of the system and process is so as far
 // as possible avoid allocations.
@@ -115,11 +121,15 @@
 }
 
 // static
+// TODO(taylori): Add a test for tracing paths in integration tests.
 std::unique_ptr<FtraceController> FtraceController::Create(
     base::TaskRunner* runner,
     Observer* observer) {
-  std::unique_ptr<FtraceProcfs> ftrace_procfs =
-      FtraceProcfs::CreateGuessingMountPoint();
+  size_t index = 0;
+  std::unique_ptr<FtraceProcfs> ftrace_procfs = nullptr;
+  while (!ftrace_procfs && kTracingPaths[index]) {
+    ftrace_procfs = FtraceProcfs::Create(kTracingPaths[index++]);
+  }
 
   if (!ftrace_procfs)
     return nullptr;
@@ -148,7 +158,6 @@
                                    Observer* observer)
     : task_runner_(task_runner),
       observer_(observer),
-      symbolizer_(new LazyKernelSymbolizer()),
       ftrace_procfs_(std::move(ftrace_procfs)),
       table_(std::move(table)),
       ftrace_config_muxer_(std::move(model)),
@@ -183,8 +192,7 @@
   size_t period_page_quota = ftrace_config_muxer_->GetPerCpuBufferSizePages();
   for (size_t cpu = 0; cpu < ftrace_procfs_->NumberOfCpus(); cpu++) {
     auto reader = std::unique_ptr<CpuReader>(
-        new CpuReader(cpu, table_.get(), symbolizer_.get(),
-                      ftrace_procfs_->OpenPipeForCpu(cpu)));
+        new CpuReader(cpu, table_.get(), ftrace_procfs_->OpenPipeForCpu(cpu)));
     per_cpu_.emplace_back(std::move(reader), period_page_quota);
   }
 
@@ -230,16 +238,6 @@
     return;
   }
 
-#if PERFETTO_DCHECK_IS_ON()
-  // The OnFtraceDataWrittenIntoDataSourceBuffers() below is supposed to clear
-  // all metadata, including the |kernel_addrs| map for symbolization.
-  for (FtraceDataSource* ds : started_data_sources_) {
-    FtraceMetadata* ftrace_metadata = ds->mutable_metadata();
-    PERFETTO_DCHECK(ftrace_metadata->kernel_addrs.empty());
-    PERFETTO_DCHECK(ftrace_metadata->last_kernel_addr_index_written == 0);
-  }
-#endif
-
   // 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());
@@ -345,7 +343,6 @@
   // non-graceful stop.
 
   per_cpu_.clear();
-  symbolizer_->Destroy();
 
   if (parsing_mem_.IsValid()) {
     parsing_mem_.AdviseDontNeed(parsing_mem_.Get(), parsing_mem_.size());
@@ -379,23 +376,6 @@
 
   started_data_sources_.insert(data_source);
   StartIfNeeded();
-
-  // If the config is requesting to symbolize kernel addresses, create the
-  // symbolizer and parse /proc/kallsyms (it will take 200-300 ms). This is not
-  // strictly required here but is to avoid hitting the parsing cost while
-  // processing the first ftrace event batch in CpuReader.
-  if (data_source->config().symbolize_ksyms()) {
-    if (data_source->config().initialize_ksyms_synchronously_for_testing()) {
-      symbolizer_->GetOrCreateKernelSymbolMap();
-    } else {
-      auto weak_this = weak_factory_.GetWeakPtr();
-      task_runner_->PostTask([weak_this] {
-        if (weak_this)
-          weak_this->symbolizer_->GetOrCreateKernelSymbolMap();
-      });
-    }
-  }
-
   return true;
 }
 
@@ -410,13 +390,6 @@
 
 void FtraceController::DumpFtraceStats(FtraceStats* stats) {
   DumpAllCpuStats(ftrace_procfs_.get(), stats);
-  if (symbolizer_ && symbolizer_->is_valid()) {
-    auto* symbol_map = symbolizer_->GetOrCreateKernelSymbolMap();
-    stats->kernel_symbols_parsed =
-        static_cast<uint32_t>(symbol_map->num_syms());
-    stats->kernel_symbols_mem_kb =
-        static_cast<uint32_t>(symbol_map->size_bytes() / 1024);
-  }
 }
 
 FtraceController::Observer::~Observer() = default;
diff --git a/src/traced/probes/ftrace/ftrace_controller.h b/src/traced/probes/ftrace/ftrace_controller.h
index 3e150a3..0004a91 100644
--- a/src/traced/probes/ftrace/ftrace_controller.h
+++ b/src/traced/probes/ftrace/ftrace_controller.h
@@ -40,7 +40,6 @@
 class FtraceConfigMuxer;
 class FtraceDataSource;
 class FtraceProcfs;
-class LazyKernelSymbolizer;
 class ProtoTranslationTable;
 struct FtraceStats;
 
@@ -50,6 +49,7 @@
 // Utility class for controlling ftrace.
 class FtraceController {
  public:
+  static const char* const kTracingPaths[];
 
   class Observer {
    public:
@@ -114,7 +114,6 @@
   base::TaskRunner* const task_runner_;
   Observer* const observer_;
   base::PagedMemory parsing_mem_;
-  std::unique_ptr<LazyKernelSymbolizer> symbolizer_;
   std::unique_ptr<FtraceProcfs> ftrace_procfs_;
   std::unique_ptr<ProtoTranslationTable> table_;
   std::unique_ptr<FtraceConfigMuxer> ftrace_config_muxer_;
diff --git a/src/traced/probes/ftrace/ftrace_controller_unittest.cc b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
index a3a02cc..dca24c8 100644
--- a/src/traced/probes/ftrace/ftrace_controller_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
@@ -20,7 +20,6 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "perfetto/ext/base/file_utils.h"
 #include "src/traced/probes/ftrace/compact_sched.h"
 #include "src/traced/probes/ftrace/cpu_reader.h"
 #include "src/traced/probes/ftrace/ftrace_config_muxer.h"
@@ -88,7 +87,7 @@
   return std::unique_ptr<Table>(
       new Table(ftrace, events, std::move(common_fields),
                 ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-                InvalidCompactSchedEventFormatForTesting(), PrintkMap()));
+                InvalidCompactSchedEventFormatForTesting()));
 }
 
 std::unique_ptr<FtraceConfigMuxer> FakeModel(FtraceProcfs* ftrace,
diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h
index cdfc138..8294f25 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.h
+++ b/src/traced/probes/ftrace/ftrace_metadata.h
@@ -35,23 +35,6 @@
 // Container for tracking miscellaneous information while parsing ftrace events,
 // scoped to an individual data source.
 struct FtraceMetadata {
-  struct KernelAddr {
-    KernelAddr(uint64_t _addr, uint32_t _index) : addr(_addr), index(_index) {}
-    uint64_t addr = 0;
-    uint32_t index = 0;
-
-    // We never keep more than one KernelAddr entry per address in the set. This
-    // is really just a workaround for the lack of a FlatMap.
-    // The |index| is written only after the entry is added to the set, to have
-    // a monotonic value that reflects the insertion order.
-    friend bool operator<(const KernelAddr& lhs, const KernelAddr& rhs) {
-      return lhs.addr < rhs.addr;
-    }
-    friend bool operator==(const KernelAddr& lhs, const KernelAddr& rhs) {
-      return lhs.addr == rhs.addr;
-    }
-  };
-
   FtraceMetadata() {
     // A sched_switch is 64 bytes, a page is 4096 bytes and we expect
     // 2 pid's per sched_switch. 4096/64*2=128. Give it a 2x margin.
@@ -59,8 +42,6 @@
 
     // We expect to see only a small number of task rename events.
     rename_pids.reserve(32);
-
-    kernel_addrs.reserve(256);
   }
 
   void AddDevice(BlockDeviceID device_id) {
@@ -104,26 +85,11 @@
     AddPid(pid);
   }
 
-  // Returns the index of the symbol (a monotonic counter, which is set when
-  // the symbol is inserted the first time).
-  uint32_t AddSymbolAddr(uint64_t addr) {
-    auto it_and_inserted = kernel_addrs.insert(KernelAddr(addr, 0));
-    // Deliberately prefer a branch here to always computing and passing
-    // size + 1 to the above.
-    if (it_and_inserted.second) {
-      const auto index = static_cast<uint32_t>(kernel_addrs.size());
-      it_and_inserted.first->index = index;
-    }
-    return it_and_inserted.first->index;
-  }
-
   void Clear() {
     inode_and_device.clear();
     rename_pids.clear();
     pids.clear();
     pids_cache.reset();
-    kernel_addrs.clear();
-    last_kernel_addr_index_written = 0;
     FinishEvent();
   }
 
@@ -140,12 +106,10 @@
   bool seen_device_id = false;
 #endif
   int32_t last_seen_common_pid = 0;
-  uint32_t last_kernel_addr_index_written = 0;
 
   base::FlatSet<InodeBlockPair> inode_and_device;
   base::FlatSet<int32_t> rename_pids;
   base::FlatSet<int32_t> pids;
-  base::FlatSet<KernelAddr> kernel_addrs;
 
   // This bitmap is a cache for |pids|. It speculates on the fact that on most
   // Android kernels, PID_MAX=32768. It saves ~1-2% cpu time on high load
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index 9176bae..480d303 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -69,27 +69,6 @@
 // static
 int FtraceProcfs::g_kmesg_fd = -1;  // Set by ProbesMain() in probes.cc .
 
-const char* const FtraceProcfs::kTracingPaths[] = {
-    "/sys/kernel/tracing/",
-    "/sys/kernel/debug/tracing/",
-    nullptr,
-};
-
-// static
-std::unique_ptr<FtraceProcfs> FtraceProcfs::CreateGuessingMountPoint(
-    const std::string& instance_path) {
-  std::unique_ptr<FtraceProcfs> ftrace_procfs;
-  size_t index = 0;
-  while (!ftrace_procfs && kTracingPaths[index]) {
-    std::string path = kTracingPaths[index++];
-    if (!instance_path.empty())
-      path += instance_path;
-
-    ftrace_procfs = Create(path);
-  }
-  return ftrace_procfs;
-}
-
 // static
 std::unique_ptr<FtraceProcfs> FtraceProcfs::Create(const std::string& root) {
   if (!CheckRootPath(root)) {
@@ -130,11 +109,6 @@
   return ReadFileIntoString(path);
 }
 
-std::string FtraceProcfs::ReadPrintkFormats() const {
-  std::string path = root_ + "printk_formats";
-  return ReadFileIntoString(path);
-}
-
 std::vector<std::string> FtraceProcfs::ReadEnabledEvents() {
   std::string path = root_ + "set_event";
   std::string s = ReadFileIntoString(path);
@@ -142,7 +116,7 @@
   std::vector<std::string> events;
   while (ss.Next()) {
     std::string event = ss.cur_token();
-    if (event.empty())
+    if (event.size() == 0)
       continue;
     events.push_back(base::StripChars(event, ":", '/'));
   }
@@ -178,15 +152,11 @@
   // on Android. The permissions to these files are configured in
   // platform/framework/native/cmds/atrace/atrace.rc.
   for (size_t cpu = 0; cpu < NumberOfCpus(); cpu++) {
-    ClearPerCpuTrace(cpu);
+    if (!ClearFile(root_ + "per_cpu/cpu" + std::to_string(cpu) + "/trace"))
+      PERFETTO_ELOG("Failed to clear buffer for CPU %zd", cpu);
   }
 }
 
-void FtraceProcfs::ClearPerCpuTrace(size_t cpu) {
-  if (!ClearFile(root_ + "per_cpu/cpu" + std::to_string(cpu) + "/trace"))
-    PERFETTO_ELOG("Failed to clear buffer for CPU %zd", cpu);
-}
-
 bool FtraceProcfs::WriteTraceMarker(const std::string& str) {
   std::string path = root_ + "trace_marker";
   return WriteToFile(path, str);
@@ -203,14 +173,14 @@
 
 bool FtraceProcfs::EnableTracing() {
   KernelLogWrite("perfetto: enabled ftrace\n");
-  PERFETTO_LOG("enabled ftrace in %s", root_.c_str());
+  PERFETTO_LOG("enabled ftrace");
   std::string path = root_ + "tracing_on";
   return WriteToFile(path, "1");
 }
 
 bool FtraceProcfs::DisableTracing() {
   KernelLogWrite("perfetto: disabled ftrace\n");
-  PERFETTO_LOG("disabled ftrace in %s", root_.c_str());
+  PERFETTO_LOG("disabled ftrace");
   std::string path = root_ + "tracing_on";
   return WriteToFile(path, "0");
 }
@@ -356,23 +326,6 @@
   return names;
 }
 
-uint32_t FtraceProcfs::ReadEventId(const std::string& group,
-                                   const std::string& name) const {
-  std::string path = root_ + "events/" + group + "/" + name + "/id";
-
-  std::string str;
-  if (!base::ReadFile(path, &str))
-    return 0;
-
-  if (str.size() && str[str.size() - 1] == '\n')
-    str.resize(str.size() - 1);
-
-  base::Optional<uint32_t> id = base::StringToUInt32(str);
-  if (!id)
-    return 0;
-  return *id;
-}
-
 // static
 bool FtraceProcfs::CheckRootPath(const std::string& root) {
   base::ScopedFile fd = base::OpenFile(root + "trace", O_RDONLY);
diff --git a/src/traced/probes/ftrace/ftrace_procfs.h b/src/traced/probes/ftrace/ftrace_procfs.h
index fb5d31c..3d8186f 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.h
+++ b/src/traced/probes/ftrace/ftrace_procfs.h
@@ -28,14 +28,6 @@
 
 class FtraceProcfs {
  public:
-  static const char* const kTracingPaths[];
-
-  // Tries creating an |FtraceProcfs| at the standard tracefs mount points.
-  // Takes an optional |instance_path| such as "instances/wifi/", in which case
-  // the returned object will be for that ftrace instance path.
-  static std::unique_ptr<FtraceProcfs> CreateGuessingMountPoint(
-      const std::string& instance_path = "");
-
   static std::unique_ptr<FtraceProcfs> Create(const std::string& root);
   static int g_kmesg_fd;
 
@@ -58,9 +50,6 @@
 
   virtual std::string ReadPageHeaderFormat() const;
 
-  // Read the printk formats file.
-  std::string ReadPrintkFormats() const;
-
   // Read the "/per_cpu/cpuXX/stats" file for the given |cpu|.
   std::string ReadCpuStats(size_t cpu) const;
 
@@ -76,9 +65,6 @@
   // Clears the trace buffers for all CPUs. Blocks until this is done.
   void ClearTrace();
 
-  // Clears the trace buffer for cpu. Blocks until this is done.
-  void ClearPerCpuTrace(size_t cpu);
-
   // Writes the string |str| as an event into the trace buffer.
   bool WriteTraceMarker(const std::string& str);
 
@@ -115,13 +101,6 @@
   virtual const std::set<std::string> GetEventNamesForGroup(
       const std::string& path) const;
 
-  // Returns the |id| for event with the given |group| and |name|. Returns 0 if
-  // the event doesn't exist, or its /id file could not be read. Not typically
-  // needed if already parsing the format file.
-  uint32_t ReadEventId(const std::string& group, const std::string& name) const;
-
-  std::string GetRootPath() const { return root_; }
-
  protected:
   // virtual and protected for testing.
   virtual bool WriteToFile(const std::string& path, const std::string& str);
diff --git a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
index 25e1aa7..8634d88 100644
--- a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
@@ -50,10 +50,11 @@
 namespace {
 
 std::string GetFtracePath() {
-  auto ftrace_procfs = FtraceProcfs::CreateGuessingMountPoint();
-  if (!ftrace_procfs)
-    return "";
-  return ftrace_procfs->GetRootPath();
+  size_t i = 0;
+  while (!FtraceProcfs::Create(FtraceController::kTracingPaths[i])) {
+    i++;
+  }
+  return std::string(FtraceController::kTracingPaths[i]);
 }
 
 std::string ReadFile(const std::string& name) {
diff --git a/src/traced/probes/ftrace/ftrace_stats.cc b/src/traced/probes/ftrace/ftrace_stats.cc
index a424cc9..eb3a99f 100644
--- a/src/traced/probes/ftrace/ftrace_stats.cc
+++ b/src/traced/probes/ftrace/ftrace_stats.cc
@@ -24,8 +24,6 @@
   for (const FtraceCpuStats& cpu_specific_stats : cpu_stats) {
     cpu_specific_stats.Write(writer->add_cpu_stats());
   }
-  writer->set_kernel_symbols_parsed(kernel_symbols_parsed);
-  writer->set_kernel_symbols_mem_kb(kernel_symbols_mem_kb);
 }
 
 void FtraceCpuStats::Write(protos::pbzero::FtraceCpuStats* writer) const {
diff --git a/src/traced/probes/ftrace/ftrace_stats.h b/src/traced/probes/ftrace/ftrace_stats.h
index 1dbcbe9..f7e6b94 100644
--- a/src/traced/probes/ftrace/ftrace_stats.h
+++ b/src/traced/probes/ftrace/ftrace_stats.h
@@ -46,8 +46,6 @@
 
 struct FtraceStats {
   std::vector<FtraceCpuStats> cpu_stats;
-  uint32_t kernel_symbols_parsed = 0;
-  uint32_t kernel_symbols_mem_kb = 0;
 
   void Write(protos::pbzero::FtraceStats*) const;
 };
diff --git a/src/traced/probes/ftrace/kallsyms/BUILD.gn b/src/traced/probes/ftrace/kallsyms/BUILD.gn
new file mode 100644
index 0000000..0c42b98
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/BUILD.gn
@@ -0,0 +1,52 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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("kallsyms") {
+  deps = [
+    "../../../../../gn:default_deps",
+    "../../../../../include/perfetto/protozero",
+    "../../../../base",
+  ]
+  sources = [
+    "kernel_symbol_map.cc",
+    "kernel_symbol_map.h",
+  ]
+}
+
+perfetto_unittest_source_set("unittests") {
+  testonly = true
+  deps = [
+    ":kallsyms",
+    "../../../../../gn:default_deps",
+    "../../../../../gn:gtest_and_gmock",
+    "../../../../base",
+  ]
+  sources = [ "kernel_symbol_map_unittest.cc" ]
+}
+
+if (enable_perfetto_benchmarks) {
+  source_set("benchmarks") {
+    testonly = true
+    deps = [
+      ":kallsyms",
+      "../../../../../gn:benchmark",
+      "../../../../../gn:default_deps",
+      "../../../../base",
+      "../../../../base:test_support",
+    ]
+    sources = [ "kernel_symbol_map_benchmark.cc" ]
+  }
+}
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc
new file mode 100644
index 0000000..f2d55f0
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/kallsyms/kernel_symbol_map.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/metatrace.h"
+#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/utils.h"
+#include "perfetto/protozero/proto_utils.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <utility>
+
+namespace perfetto {
+
+// On a Pixel 3 this gives an avg. lookup time of 600 ns and a memory usage
+// of 1.1 MB for 65k symbols. See go/kallsyms-parser-bench.
+size_t KernelSymbolMap::kSymIndexSampling = 16;
+size_t KernelSymbolMap::kTokenIndexSampling = 4;
+
+namespace {
+
+using TokenId = KernelSymbolMap::TokenTable::TokenId;
+constexpr size_t kSymNameMaxLen = 128;
+
+// Reads a kallsyms file in blocks of 4 pages each and decode its lines using
+// a simple FSM. Calls the passed lambda for each valid symbol.
+// It skips undefined symbols and other useless stuff.
+template <typename Lambda /* void(uint64_t, const char*) */>
+void ForEachSym(const std::string& kallsyms_path, Lambda fn) {
+  base::ScopedFile fd = base::OpenFile(kallsyms_path.c_str(), O_RDONLY);
+  if (!fd) {
+    PERFETTO_PLOG("Cannot open %s", kallsyms_path.c_str());
+    return;
+  }
+
+  // /proc/kallsyms looks as follows:
+  // 0000000000026a80 A bpf_trace_sds
+  //
+  // ffffffffc03a6000 T cpufreq_gov_powersave_init<TAB> [cpufreq_powersave]
+  // ffffffffc035d000 T cpufreq_gov_userspace_init<TAB> [cpufreq_userspace]
+  //
+  // We parse it with a state machine that has four states, one for each column.
+  // We don't care about the part in the square brackets and ignore everything
+  // after the symbol name.
+
+  static constexpr size_t kBufSize = 16 * 1024;
+  base::PagedMemory buffer = base::PagedMemory::Allocate(kBufSize);
+  enum { kSymAddr, kSymType, kSymName, kEatRestOfLine } state = kSymAddr;
+  uint64_t sym_addr = 0;
+  char sym_type = '\0';
+  char sym_name[kSymNameMaxLen + 1];
+  size_t sym_name_len = 0;
+  for (;;) {
+    char* buf = static_cast<char*>(buffer.Get());
+    auto rsize = PERFETTO_EINTR(read(*fd, buf, kBufSize));
+    if (rsize < 0) {
+      PERFETTO_PLOG("read(%s) failed", kallsyms_path.c_str());
+      return;
+    }
+    if (rsize == 0)
+      return;  // EOF
+    for (size_t i = 0; i < static_cast<size_t>(rsize); i++) {
+      char c = buf[i];
+      const bool is_space = c == ' ' || c == '\t';
+      switch (state) {
+        case kSymAddr:
+          if (c >= '0' && c <= '9') {
+            sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - '0');
+          } else if (c >= 'a' && c <= 'f') {
+            sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - 'a' + 10);
+          } else if (is_space) {
+            state = kSymType;
+          } else if (c == '\0') {
+            return;
+          } else {
+            PERFETTO_ELOG("kallsyms parser error: chr 0x%x @ off=%zu", c, i);
+            return;
+          }
+          break;
+
+        case kSymType:
+          if (is_space)
+            break;  // Eat leading spaces.
+          sym_type = c;
+          state = kSymName;
+          sym_name_len = 0;
+          break;
+
+        case kSymName:
+          if (is_space && sym_name_len == 0)
+            break;  // Eat leading spaces.
+          if (c && c != '\n' && !is_space && sym_name_len < kSymNameMaxLen) {
+            sym_name[sym_name_len++] = c;
+            break;
+          }
+          sym_name[sym_name_len] = '\0';
+          fn(sym_addr, sym_type, sym_name);
+          sym_addr = 0;
+          sym_type = '\0';
+          state = c == '\n' ? kSymAddr : kEatRestOfLine;
+          break;
+
+        case kEatRestOfLine:
+          if (c == '\n')
+            state = kSymAddr;
+          break;
+      }  // switch(state)
+    }    // for (char in buf)
+  }      // for (read chunk)
+}
+
+// Splits a symbol name into tokens using '_' as a separator, calling the passed
+// lambda for each token. It splits tokens in a way that allows the original
+// string to be rebuilt as-is by re-joining using a '_' between each token.
+// For instance:
+// _fo_a_b      ->  ["", fo, a, b]
+// __fo_a_b     ->  [_, fo, a, b]
+// __fo_a_b_    ->  [_, fo, a, b, ""]
+// __fo_a_b____ ->  [_, fo, a, b, ___]
+template <typename Lambda /* void(base::StringView) */>
+void Tokenize(const char* name, Lambda fn) {
+  const char* tok_start = name;
+  bool is_start_of_token = true;
+  bool tok_is_sep = false;
+  for (const char* ptr = name;; ptr++) {
+    const char c = *ptr;
+    if (is_start_of_token) {
+      tok_is_sep = *tok_start == '_';  // Deals with tokens made of '_'s.
+      is_start_of_token = false;
+    }
+    // Scan until either the end of string or the next character (which is a '_'
+    // in nominal cases, or anything != '_' for tokens made by 1+ '_').
+    if (c == '\0' || (!tok_is_sep && c == '_') || (tok_is_sep && c != '_')) {
+      size_t tok_len = static_cast<size_t>(ptr - tok_start);
+      if (tok_is_sep && c != '\0')
+        --tok_len;
+      fn(base::StringView(tok_start, tok_len));
+      if (c == '\0')
+        return;
+      tok_start = tok_is_sep ? ptr : ptr + 1;
+      is_start_of_token = true;
+    }
+  }
+}
+
+}  // namespace
+
+KernelSymbolMap::TokenTable::TokenTable() {
+  // Insert a null token as id 0. We can't just add "" because the empty string
+  // is special-cased and doesn't insert an actual token. So we push a string of
+  // size one that contains only the null character instead.
+  char null_tok = 0;
+  Add(std::string(&null_tok, 1));
+}
+
+KernelSymbolMap::TokenTable::~TokenTable() = default;
+
+// Adds a new token to the db. Does not dedupe identical token (with the
+// exception of the empty string). The caller has to deal with that.
+// Supports only ASCII characters in the range [1, 127].
+// The last character of the token will have the MSB set.
+TokenId KernelSymbolMap::TokenTable::Add(const std::string& token) {
+  const size_t token_size = token.size();
+  if (token_size == 0)
+    return 0;
+  TokenId id = num_tokens_++;
+
+  const size_t buf_size_before_insertion = buf_.size();
+  if (id % kTokenIndexSampling == 0)
+    index_.emplace_back(buf_size_before_insertion);
+
+  const size_t prev_size = buf_.size();
+  buf_.resize(prev_size + token_size);
+  char* tok_wptr = &buf_[prev_size];
+  for (size_t i = 0; i < token_size - 1; i++) {
+    PERFETTO_DCHECK((token.at(i) & 0x80) == 0);  // |token| must be ASCII only.
+    *(tok_wptr++) = token.at(i) & 0x7f;
+  }
+  *(tok_wptr++) = token.at(token_size - 1) | 0x80;
+  PERFETTO_DCHECK(tok_wptr == &buf_[buf_.size()]);
+  return id;
+}
+
+// NOTE: the caller need to mask the returned chars with 0x7f. The last char of
+// the StringView will have its MSB set (it's used as a EOF char internally).
+base::StringView KernelSymbolMap::TokenTable::Lookup(TokenId id) {
+  if (id == 0)
+    return base::StringView();
+  if (id > num_tokens_)
+    return base::StringView("<error>");
+  // We don't know precisely where the id-th token starts in the buffer. We
+  // store only one position every kTokenIndexSampling. From there, the token
+  // can be found with a linear scan of at most kTokenIndexSampling steps.
+  size_t index_off = id / kTokenIndexSampling;
+  PERFETTO_DCHECK(index_off < index_.size());
+  TokenId cur_id = static_cast<TokenId>(index_off * kTokenIndexSampling);
+  uint32_t begin = index_[index_off];
+  PERFETTO_DCHECK(begin == 0 || buf_[begin - 1] & 0x80);
+  const size_t buf_size = buf_.size();
+  for (uint32_t off = begin; off < buf_size; ++off) {
+    // Advance |off| until the end of the token (which has the MSB set).
+    if ((buf_[off] & 0x80) == 0)
+      continue;
+    if (cur_id == id)
+      return base::StringView(&buf_[begin], off - begin + 1);
+    ++cur_id;
+    begin = off + 1;
+  }
+  return base::StringView();
+}
+
+size_t KernelSymbolMap::Parse(const std::string& kallsyms_path) {
+  PERFETTO_METATRACE_SCOPED(TAG_FTRACE, KALLSYMS_PARSE);
+  using SymAddr = uint64_t;
+
+  struct TokenInfo {
+    uint32_t count = 0;
+    TokenId id = 0;
+  };
+
+  // Note if changing the container: the code below relies on stable iterators.
+  using TokenMap = std::map<std::string, TokenInfo>;
+  using TokenMapPtr = TokenMap::value_type*;
+  TokenMap tokens;
+
+  // Keep the (ordered) list of tokens for each symbol.
+  std::multimap<SymAddr, TokenMapPtr> symbols;
+
+  ForEachSym(kallsyms_path, [&](SymAddr addr, char type, const char* name) {
+    if (addr == 0 || (type != 't' && type != 'T') || name[0] == '$') {
+      return;
+    }
+
+    // Split each symbol name in tokens, using '_' as a separator (so that
+    // "foo_bar" -> ["foo", "bar"]). For each token hash:
+    // 1. Keep track of the frequency of each token.
+    // 2. Keep track of the list of token hashes for each symbol.
+    Tokenize(name, [&tokens, &symbols, addr](base::StringView token) {
+      // Strip the .cfi part if present.
+      if (token.substr(token.size() - 4) == ".cfi")
+        token = token.substr(0, token.size() - 4);
+      auto it_and_ins = tokens.emplace(token.ToStdString(), TokenInfo{});
+      it_and_ins.first->second.count++;
+      symbols.emplace(addr, &*it_and_ins.first);
+    });
+  });
+
+  // At this point we have broken down each symbol into a set of token hashes.
+  // Now generate the token ids, putting high freq tokens first, so they use
+  // only one byte to varint encode.
+
+  // This block limits the lifetime of |tokens_by_freq|.
+  {
+    std::vector<TokenMapPtr> tokens_by_freq;
+    tokens_by_freq.resize(tokens.size());
+    size_t tok_idx = 0;
+    for (auto& kv : tokens)
+      tokens_by_freq[tok_idx++] = &kv;
+
+    auto comparer = [](TokenMapPtr a, TokenMapPtr b) {
+      PERFETTO_DCHECK(a && b);
+      return b->second.count < a->second.count;
+    };
+    std::sort(tokens_by_freq.begin(), tokens_by_freq.end(), comparer);
+    for (TokenMapPtr tinfo : tokens_by_freq) {
+      tinfo->second.id = tokens_.Add(tinfo->first);
+    }
+  }
+  tokens_.shrink_to_fit();
+
+  buf_.resize(2 * 1024 * 1024);  // Based on real-word observations.
+  base_addr_ = symbols.empty() ? 0 : symbols.begin()->first;
+  SymAddr prev_sym_addr = base_addr_;
+  uint8_t* wptr = buf_.data();
+
+  for (auto it = symbols.begin(); it != symbols.end();) {
+    const SymAddr sym_addr = it->first;
+
+    // Find the iterator to the first token of the next symbol (or the end).
+    auto sym_start = it;
+    auto sym_end = it;
+    while (sym_end != symbols.end() && sym_end->first == sym_addr)
+      ++sym_end;
+
+    // The range [sym_start, sym_end) has all the tokens for the current symbol.
+    uint32_t size_before = static_cast<uint32_t>(wptr - buf_.data());
+
+    // Make sure there is enough headroom to write the symbol.
+    if (buf_.size() - size_before < 1024) {
+      buf_.resize(buf_.size() + 32768);
+      wptr = buf_.data() + size_before;
+    }
+
+    uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
+    const size_t sym_num = num_syms_++;
+    if (sym_num % kSymIndexSampling == 0)
+      index_.emplace_back(std::make_pair(sym_rel_addr, size_before));
+    PERFETTO_DCHECK(sym_addr >= prev_sym_addr);
+    uint32_t delta = static_cast<uint32_t>(sym_addr - prev_sym_addr);
+    wptr = protozero::proto_utils::WriteVarInt(delta, wptr);
+    // Append all the token ids.
+    for (it = sym_start; it != sym_end;) {
+      PERFETTO_DCHECK(it->first == sym_addr);
+      TokenId token_id = it->second->second.id << 1;
+      ++it;
+      token_id |= (it == sym_end) ? 1 : 0;  // Last one has LSB set to 1.
+      wptr = protozero::proto_utils::WriteVarInt(token_id, wptr);
+    }
+    prev_sym_addr = sym_addr;
+  }  // for (symbols)
+
+  buf_.resize(static_cast<size_t>(wptr - buf_.data()));
+  buf_.shrink_to_fit();
+
+  PERFETTO_DLOG(
+      "Loaded %zu kalllsyms entries. Mem usage: %zu B (addresses) + %zu B "
+      "(tokens), total: %zu B",
+      num_syms_, addr_bytes(), tokens_.size_bytes(), size_bytes());
+
+  return num_syms_;
+}
+
+std::string KernelSymbolMap::Lookup(uint64_t sym_addr) {
+  if (index_.empty() || sym_addr < base_addr_)
+    return "";
+
+  // First find the highest symbol address <= sym_addr.
+  // Start with a binary search using the sparse index.
+
+  const uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
+  auto it = std::upper_bound(index_.cbegin(), index_.cend(),
+                             std::make_pair(sym_rel_addr, 0u));
+  if (it != index_.cbegin())
+    --it;
+
+  // Then continue with a linear scan (of at most kSymIndexSampling steps).
+  uint32_t addr = it->first;
+  uint32_t off = it->second;
+  const uint8_t* rdptr = &buf_[off];
+  const uint8_t* const buf_end = &buf_[buf_.size()];
+  bool parsing_addr = true;
+  const uint8_t* next_rdptr = nullptr;
+  for (bool is_first_addr = true;; is_first_addr = false) {
+    uint64_t v = 0;
+    const auto* prev_rdptr = rdptr;
+    rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
+    if (rdptr == prev_rdptr)
+      break;
+    if (parsing_addr) {
+      addr += is_first_addr ? 0 : static_cast<uint32_t>(v);
+      parsing_addr = false;
+      if (addr > sym_rel_addr)
+        break;
+      next_rdptr = rdptr;
+    } else {
+      // This is a token. Wait for the EOF maker.
+      parsing_addr = (v & 1) == 1;
+    }
+  }
+
+  if (!next_rdptr)
+    return "";
+
+  // The address has been found. Now rejoin the tokens to form the symbol name.
+
+  rdptr = next_rdptr;
+  std::string sym_name;
+  sym_name.reserve(kSymNameMaxLen);
+  for (bool eof = false, is_first_token = true; !eof; is_first_token = false) {
+    uint64_t v = 0;
+    const auto* old = rdptr;
+    rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
+    if (rdptr == old)
+      break;
+    eof = v & 1;
+    base::StringView token = tokens_.Lookup(static_cast<TokenId>(v >> 1));
+    if (!is_first_token)
+      sym_name.push_back('_');
+    for (size_t i = 0; i < token.size(); i++)
+      sym_name.push_back(token.at(i) & 0x7f);
+  }
+  return sym_name;
+}
+
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h
new file mode 100644
index 0000000..c13546a
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_KALLSYMS_KERNEL_SYMBOL_MAP_H_
+#define SRC_TRACED_PROBES_FTRACE_KALLSYMS_KERNEL_SYMBOL_MAP_H_
+
+#include <stdint.h>
+#include <array>
+#include <forward_list>
+#include <vector>
+
+namespace perfetto {
+
+namespace base {
+class StringView;
+}
+
+// A parser and memory-efficient container for /proc/kallsyms.
+// It can store a full kernel symbol table in ~1.2MB of memory and perform fast
+// lookups using logarithmic binary searches + bounded linear scans.
+//
+// /proc/kallsyms is a ~10 MB text file that contains the map of kernel symbols,
+// as follows:
+// ffffff8f77682f8c t el0_sync_invalid
+// ffffff8f77683060 t el0_irq_invalid
+// ...
+// In a typipcal Android kernel, it consists of 213K lines. Out of these, only
+// 116K are interesting for the sake of symbolizing kernel functions, the rest
+// are .rodata (variables), weak or other useless symbols.
+// Still, even keeping around 116K pointers would require 116K * 8 ~= 1 MB of
+// memory, without accounting for any strings for the symbols names.
+// The SUM(str.len) for the 116K symbol names adds up to 2.7 MB (without
+// counting their addresses).
+// However consider the following:
+// - Symbol addresses are mostly contiguous. Modulo the initial KASLR loading
+//   address, most symbols are few hundreds bytes apart from each other.
+// - Symbol names are made of tokens that are quite frequent (token: the result
+//   of name.split('_')). If we tokenize the 2.7 MB of strings, the resulting
+//   SUM(distinct_token.len) goes down 2.7MB -> 146 KB. This is because tokens
+//   like "get", "set" or "event" show up thousands of times.
+// - Symbol names are ASCII strings using only 7 out of 8 bits.
+//
+// In the light of this, the in-memory architecture of this data structure is
+// as follows:
+// We keep two tables around: (1) a token table and (2) a symbol table. Both
+// table are a flat byte vector with some sparse lookaside index to make lookups
+// faster and avoid full linear scans.
+//
+// Token table
+// -----------
+// The token table is a flat char buffer. Tokens are variable size (>0). Each
+// token is identified by its ordinality, so token id 3 is the 3rd token in
+// the table. All tokens are concatenated together.
+// Given the ASCII encoding, the MSB is used as a terminator. So instead of
+// wasting an extra NUL byte for each string, the last char of each token has
+// the MSB set.
+// Furthermore, a lookaside index stores the offset of tokens (i.e. Token N
+// starts at offset O in the buffer) to allow fast lookups. In order to avoid
+// wasting too much memory, the index is sparse and track the offsets of only
+// one every kTokenIndexSamplinig tokens.
+// When looking up a token ID N, the table seeks at the offset of the closest
+// token <= N, and then scans linearly the next (at most kTokenIndexSamplinig)
+// tokens, counting the MSBs found, until the right token id is found.
+// buf:   set*get*kernel*load*fpsimd*return*wrapper*el0*skip*sync*neon*bit*aes
+//        ^                   ^                         ^
+//        |                   |                         |
+// index: 0@0                 4@15                      8@21
+
+// Symbol table
+// ------------
+// The symbol table is a flat char buffer that stores for each symbol: its
+// address + the list of token indexes in the token table. The main caveats are
+// that:
+// - Symbol addresses are delta encoded (delta from prev symbol's addr).
+// - Both delta addresses and token indexes are var-int encoded.
+// - The LSB of token indexes is used as EOF marker (i.e. the next varint is
+//   the delta-addr for the next symbol). This time the LSB is used because of
+//   the varint encoding.
+// At parsing time symbols are ordered by address and tokens are sorted by
+// frequency, so that the top used 64 tokens can be represented with 1 byte.
+// (Rationale for 64: 1 byte = 8 bits. The MSB bit of each byte is used for the
+// varint encoding, the LSB bit of each number is used as end-of-tokens marker.
+// There are 6 bits left -> 64 indexes can be represented using one byte).
+// In summary the symbol table looks as follows:
+//
+// Base address: 0xbeef0000
+// Symbol buffer:
+// 0 1|0  4|0  6|1    // 0xbeef0000: 1,4,6 -> get_fpsimd_wrapper
+// 8 7|0  3|1         // 0xbeef0008: 7,3   -> el0_load
+// ...
+// Like in the case of the token table, a lookaside index keeps track of the
+// offset of one every kSymIndexSamplinig addresses.
+// The Lookup(ADDR) function operates as follows:
+// 1. Performs a logarithmic binary search in the symbols index, finding the
+//    offset of the closest addres <= ADDR.
+// 2. Skip over at most kSymIndexSamplinig until the symbol is found.
+// 3. For each token index, lookup the corresponding token string and
+//    concatenate them to build the symbol name.
+
+class KernelSymbolMap {
+ public:
+  // The two constants below are changeable only for the benchmark use.
+  // Trades off size of the root |index_| vs worst-case linear scans size.
+  // A higher number makes the index more sparse.
+  static size_t kSymIndexSampling;
+
+  // Trades off size of the TokenTable |index_| vs worst-case linear scans size.
+  static size_t kTokenIndexSampling;
+
+  // Parses a kallsyms file. Returns the number of valid symbols decoded.
+  size_t Parse(const std::string& kallsyms_path);
+
+  // Looks up the closest symbol (i.e. the one with the highest address <=
+  // |addr|) from its absolute 64-bit address.
+  // Returns an empty string if the symbol is not found (which can happen only
+  // if the passed |addr| is < min(addr)).
+  std::string Lookup(uint64_t addr);
+
+  // Returns the numberr of valid symbols decoded.
+  size_t num_syms() const { return num_syms_; }
+
+  // Returns the size in bytes used by the adddress table (without counting
+  // the tokens).
+  size_t addr_bytes() const { return buf_.size() + index_.size() * 8; }
+
+  // Returns the total memory usage in bytes.
+  size_t size_bytes() const { return addr_bytes() + tokens_.size_bytes(); }
+
+  // Token table.
+  class TokenTable {
+   public:
+    using TokenId = uint32_t;
+    TokenTable();
+    ~TokenTable();
+    TokenId Add(const std::string&);
+    base::StringView Lookup(TokenId);
+    size_t size_bytes() const { return buf_.size() + index_.size() * 4; }
+
+    void shrink_to_fit() {
+      buf_.shrink_to_fit();
+      index_.shrink_to_fit();
+    }
+
+   private:
+    TokenId num_tokens_ = 0;
+
+    std::vector<char> buf_;  // Token buffer.
+
+    // The value i-th in the vector contains the offset (within |buf_|) of the
+    // (i * kTokenIndexSamplinig)-th token.
+    std::vector<uint32_t> index_;
+  };
+
+ private:
+  TokenTable tokens_;  // Token table.
+
+  uint64_t base_addr_ = 0;    // Address of the first symbol (after sorting).
+  size_t num_syms_ = 0;       // Number of valid symbols stored.
+  std::vector<uint8_t> buf_;  // Symbol buffer.
+
+  // The key is (address - base_addr_), the value is the byte offset in |buf_|
+  // where the symbol entry starts (i.e. the start of the varint that tells the
+  // delta from the previous symbol).
+  std::vector<std::pair<uint32_t /*rel_addr*/, uint32_t /*offset*/>> index_;
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_KALLSYMS_KERNEL_SYMBOL_MAP_H_
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc
new file mode 100644
index 0000000..cdd4e38
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc
@@ -0,0 +1,116 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 <set>
+#include <unordered_set>
+
+#include <benchmark/benchmark.h>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/utils.h"
+#include "src/base/test/utils.h"
+#include "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h"
+
+namespace {
+
+bool IsBenchmarkFunctionalOnly() {
+  return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
+}
+
+void BenchmarkArgs(benchmark::internal::Benchmark* b) {
+  if (IsBenchmarkFunctionalOnly()) {
+    b->Ranges({{16, 16}, {16, 16}});
+  } else {
+    b->RangeMultiplier(2)->Ranges({{4, 512}, {4, 512}});
+  }
+}
+
+struct ExpectedSym {
+  uint64_t addr;
+  const char* name;
+};
+
+// This set of symbols has been chosen by randomly picking 40 random symbols
+// from the original kallsyms.
+ExpectedSym kExpectedSyms[] = {
+    {0xffffff8f79c0d978, "__map_memblock"},
+    {0xffffff8f78fddbb8, "smack_inode_getsecid"},
+    {0xffffff8f78fe43b4, "msm_smmu_set_attribute"},
+    {0xffffff8f79d23e20, "__initcall_41_dm_verity_init6"},
+    {0xffffff8f74206c5c, "sme_update_fast_transition_enabled"},
+    {0xffffff8f74878c8c, "tavil_hph_idle_detect_put"},
+    {0xffffff8f78fd7db0, "privileged_wrt_inode_uidgid"},
+    {0xffffff8f78ffe030, "__hrtimer_tasklet_trampoline"},
+    {0xffffff8f78fd86b0, "store_enable"},
+    {0xffffff8f78ffbcb8, "raw6_exit_net"},
+    {0xffffff8f78ffa6ec, "idProduct_show"},
+    {0xffffff8f78fd99c0, "perf_tp_event"},
+    {0xffffff8f78fe1468, "rpmh_tx_done"},
+    {0xffffff8f78fda274, "page_unlock_anon_vma_read"},
+    {0xffffff8f78ffedfc, "vmstat_period_ms_operations_open"},
+    {0xffffff8f78fe0148, "devm_gpio_request"},
+    {0xffffff8f77915028, "ctx_sched_out"},
+    {0xffffff8f77ccdc2c, "gcm_hash_crypt_remain_continue"},
+    {0xffffff8f790022ec, "loop_init"},
+    {0xffffff8f78ff0004, "pcim_release"},
+    {0xffffff8f78fe1d8c, "uart_close"},
+    {0xffffff8f78fda9d4, "pipe_lock"},
+    {0xffffff8f78e62c68, "local_bh_enable.117091"},
+    {0xffffff8f78fd918c, "fork_idle"},
+    {0xffffff8f78fe24c4, "drm_dp_downstream_debug"},
+    {0xffffff8f78ff41d0, "inet_addr_onlink"},
+    {0xffffff8f78fdf2d4, "idr_alloc"},
+    {0xffffff8f78ff073c, "fts_remove"},
+    {0xffffff8f78ffe294, "xfrm4_local_error"},
+    {0xffffff8f79001994, "cpu_feature_match_PMULL_init"},
+    {0xffffff8f78ff4740, "xfrm_state_find"},
+    {0xffffff8f78ff58b0, "inet_del_offload"},
+    {0xffffff8f742041ac, "csr_is_conn_state_connected_infra"},
+    {0xffffff8f78fe1fd4, "diag_add_client"},
+    {0xffffff8f78ffc000, "trace_raw_output_mm_vmscan_kswapd_sleep"},
+    {0xffffff8f78fe6388, "scsi_queue_insert"},
+    {0xffffff8f78fdd480, "selinux_sb_clone_mnt_opts"},
+    {0xffffff8f78fe0e9c, "clk_fixed_rate_recalc_rate"},
+    {0xffffff8f78fedaec, "cap_inode_killpriv"},
+    {0xffffff8f79002b64, "audio_amrwb_init"},
+};
+
+}  // namespace
+
+static void BM_KallSyms(benchmark::State& state) {
+  perfetto::KernelSymbolMap::kTokenIndexSampling =
+      static_cast<size_t>(state.range(0));
+  perfetto::KernelSymbolMap::kSymIndexSampling =
+      static_cast<size_t>(state.range(1));
+  perfetto::KernelSymbolMap kallsyms;
+
+  // Don't run the benchmark on the CI as it requires pushing all test data,
+  // which slows down significantly the CI.
+  const bool skip = IsBenchmarkFunctionalOnly();
+  if (!skip) {
+    kallsyms.Parse(perfetto::base::GetTestDataPath("test/data/kallsyms.txt"));
+  }
+
+  for (auto _ : state) {
+    for (size_t i = 0; i < perfetto::base::ArraySize(kExpectedSyms); i++) {
+      const auto& exp = kExpectedSyms[i];
+      PERFETTO_CHECK(skip || kallsyms.Lookup(exp.addr) == exp.name);
+    }
+  }
+
+  state.counters["mem"] = kallsyms.size_bytes();
+}
+
+BENCHMARK(BM_KallSyms)->Apply(BenchmarkArgs);
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc
new file mode 100644
index 0000000..942820a
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/kallsyms/kernel_symbol_map.h"
+
+#include <inttypes.h>
+
+#include <random>
+#include <unordered_map>
+
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/temp_file.h"
+
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+using TokenId = KernelSymbolMap::TokenTable::TokenId;
+
+std::string Lookup(KernelSymbolMap::TokenTable& tokens, TokenId id) {
+  base::StringView sv = tokens.Lookup(id);
+  std::string str;
+  str.reserve(sv.size() + 1);
+  for (const char c : sv)
+    str.push_back(c & 0x7f);
+  return str;
+}
+
+TEST(KernelSymbolMapTest, TokenTable) {
+  KernelSymbolMap::TokenTable tokens;
+  ASSERT_EQ(tokens.Add("a"), 1u);
+  ASSERT_EQ(tokens.Add("bb"), 2u);
+  ASSERT_EQ(tokens.Add("ccc"), 3u);
+  ASSERT_EQ(tokens.Add("foobar"), 4u);
+  ASSERT_EQ(tokens.Add("foobaz"), 5u);
+  ASSERT_EQ(tokens.Add("_"), 6u);
+  ASSERT_EQ(Lookup(tokens, 0), "");
+  ASSERT_EQ(Lookup(tokens, 1), "a");
+  ASSERT_EQ(Lookup(tokens, 2), "bb");
+  ASSERT_EQ(Lookup(tokens, 3), "ccc");
+  ASSERT_EQ(Lookup(tokens, 4), "foobar");
+  ASSERT_EQ(Lookup(tokens, 5), "foobaz");
+  ASSERT_EQ(Lookup(tokens, 6), "_");
+  ASSERT_EQ(Lookup(tokens, 0), "");
+  ASSERT_EQ(Lookup(tokens, 42), "<error>");
+}
+
+TEST(KernelSymbolMapTest, ManyTokens) {
+  KernelSymbolMap::TokenTable tokens;
+  std::unordered_map<TokenId, std::string> tok_map;
+  static std::minstd_rand rng(0);
+  for (int rep = 0; rep < 10000; rep++) {
+    static const size_t kNameMax = 128;
+    std::string sym_name;
+    sym_name.reserve(kNameMax);
+    size_t len = 1 + (rng() % kNameMax);
+    for (size_t j = 0; j < len; j++)
+      sym_name.push_back(rng() & 0x7f);
+    TokenId id = tokens.Add(sym_name);
+    ASSERT_EQ(tok_map.count(id), 0u);
+    tok_map[id] = sym_name;
+  }
+  for (const auto& kv : tok_map) {
+    ASSERT_EQ(Lookup(tokens, kv.first), kv.second);
+  }
+}
+
+TEST(KernelSymbolMapTest, EdgeCases) {
+  base::TempFile tmp = base::TempFile::Create();
+  static const char kContents[] = R"(ffffff8f73e2fa10 t one
+ffffff8f73e2fa20 t two_
+ffffff8f73e2fa30 t _three  [module_name_ignored]
+ffffff8f73e2fa40 x ignore
+ffffff8f73e2fa40 t _fo_ur_
+ffffff8f73e2fa50 t _five__.cfi
+ffffff8f73e2fa60 t __si__x__
+ffffff8f73e2fa70 t ___se___v_e__n___
+ffffff8f73e2fa80 t _eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_should_be_truncated_exactly_here_because_this_is_the_128_char_TRUNCATED_HERE
+ffffff8f73e2fa90 t NiNe
+)";
+  base::WriteAll(tmp.fd(), kContents, sizeof(kContents));
+  base::FlushFile(tmp.fd());
+
+  KernelSymbolMap kallsyms;
+  EXPECT_EQ(kallsyms.Lookup(0x42), "");
+
+  kallsyms.Parse(tmp.path().c_str());
+  EXPECT_EQ(kallsyms.num_syms(), 9u);
+
+  // Test first exact lookups.
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa10ULL), "one");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa20ULL), "two_");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa30LL), "_three");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa40ULL), "_fo_ur_");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa50ULL), "_five__");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa60ULL), "__si__x__");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa70ULL), "___se___v_e__n___");
+  EXPECT_EQ(
+      kallsyms.Lookup(0xffffff8f73e2fa80ULL),
+      "_eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_"
+      "should_be_truncated_exactly_here_because_this_is_the_128_char");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa90ULL), "NiNe");
+
+  // Now check bound searches.
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa00ULL), "");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa11ULL), "one");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa19ULL), "one");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa71ULL), "___se___v_e__n___");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa91ULL), "NiNe");
+  EXPECT_EQ(kallsyms.Lookup(0xffffff8fffffffffULL), "NiNe");
+}
+
+TEST(KernelSymbolMapTest, GoldenTest) {
+  std::string fake_kallsyms;
+  fake_kallsyms.reserve(8 * 1024 * 1024);
+  static std::minstd_rand rng(0);
+  static const size_t kNameMax = 64;
+  std::map<uint64_t, std::string> symbols;
+  for (int rep = 0; rep < 1000; rep++) {
+    uint64_t addr = static_cast<uint64_t>(rng());
+    if (symbols.count(addr))
+      continue;
+    static const char kCharset[] = "_abcdef";
+    char sym_name[kNameMax + 1];  // Deliberately not initialized.
+    size_t sym_name_len = 1 + (rng() % kNameMax);
+    for (size_t i = 0; i < sym_name_len; i++)
+      sym_name[i] = kCharset[rng() % strlen(kCharset)];
+    sym_name[sym_name_len] = '\0';
+    char line[kNameMax + 40];
+    sprintf(line, "%" PRIx64 " t %s\n", addr, sym_name);
+    symbols[addr] = sym_name;
+    fake_kallsyms += line;
+  }
+  base::TempFile tmp = base::TempFile::Create();
+  base::WriteAll(tmp.fd(), fake_kallsyms.data(), fake_kallsyms.size());
+  base::FlushFile(tmp.fd());
+
+  KernelSymbolMap kallsyms;
+  kallsyms.Parse(tmp.path().c_str());
+  ASSERT_EQ(kallsyms.num_syms(), symbols.size());
+  for (const auto& kv : symbols) {
+    ASSERT_EQ(kallsyms.Lookup(kv.first), kv.second);
+  }
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/printk_formats_parser.cc b/src/traced/probes/ftrace/printk_formats_parser.cc
deleted file mode 100644
index 274e981..0000000
--- a/src/traced/probes/ftrace/printk_formats_parser.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/traced/probes/ftrace/printk_formats_parser.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-
-namespace perfetto {
-
-PrintkMap ParsePrintkFormats(const std::string& format) {
-  PrintkMap mapping;
-  for (base::StringSplitter lines(format, '\n'); lines.Next();) {
-    // Lines have the format:
-    // 0xdeadbeef : "not alive cow"
-    // and may be duplicated.
-    std::string line(lines.cur_token());
-
-    auto index = line.find(':');
-    if (index == std::string::npos)
-      continue;
-    std::string raw_address = line.substr(0, index);
-    std::string name = line.substr(index);
-
-    // Remove colon, space and surrounding quotes:
-    raw_address = base::StripSuffix(raw_address, " ");
-    name = base::StripPrefix(name, ":");
-    name = base::StripPrefix(name, " ");
-    name = base::StripPrefix(name, "\"");
-    name = base::StripSuffix(name, "\"");
-
-    if (name.empty())
-      continue;
-
-    base::Optional<uint64_t> address = base::StringToUInt64(raw_address, 16);
-    if (address && address.value() != 0)
-      mapping.insert(address.value(), name);
-  }
-  return mapping;
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/printk_formats_parser.h b/src/traced/probes/ftrace/printk_formats_parser.h
deleted file mode 100644
index df7e556..0000000
--- a/src/traced/probes/ftrace/printk_formats_parser.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACED_PROBES_FTRACE_PRINTK_FORMATS_PARSER_H_
-#define SRC_TRACED_PROBES_FTRACE_PRINTK_FORMATS_PARSER_H_
-
-#include <string>
-
-#include "perfetto/base/flat_set.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-
-struct PrintkEntry {
-  uint64_t address;
-  std::string name;
-
-  PrintkEntry(uint64_t _address) : PrintkEntry(_address, "") {}
-
-  PrintkEntry(uint64_t _address, std::string _name)
-      : address(_address), name(_name) {}
-
-  bool operator<(const PrintkEntry& other) const {
-    return address < other.address;
-  }
-
-  bool operator==(const PrintkEntry& other) const {
-    return address == other.address;
-  }
-};
-
-class PrintkMap {
- public:
-  void insert(uint64_t address, std::string name) {
-    set_.insert(PrintkEntry(address, name));
-  }
-
-  base::StringView at(uint64_t address) const {
-    auto it = set_.find(address);
-    if (it == set_.end()) {
-      return base::StringView();
-    }
-    return base::StringView(it->name);
-  }
-
-  size_t size() const { return set_.size(); }
-
-  size_t empty() const { return set_.empty(); }
-
-  base::FlatSet<PrintkEntry> set_;
-};
-
-PrintkMap ParsePrintkFormats(const std::string& format);
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_FTRACE_PRINTK_FORMATS_PARSER_H_
diff --git a/src/traced/probes/ftrace/printk_formats_parser_unittest.cc b/src/traced/probes/ftrace/printk_formats_parser_unittest.cc
deleted file mode 100644
index 59d282d..0000000
--- a/src/traced/probes/ftrace/printk_formats_parser_unittest.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/traced/probes/ftrace/printk_formats_parser.h"
-
-#include "test/gtest_and_gmock.h"
-
-using ::testing::Contains;
-using ::testing::Eq;
-using ::testing::IsEmpty;
-using ::testing::Key;
-using ::testing::Not;
-using ::testing::Pair;
-
-namespace perfetto {
-namespace {
-
-TEST(PrintkFormatParserTest, AllZeros) {
-  std::string format = R"(0x0 : "Rescheduling interrupts"
-0x0 : "Function call interrupts"
-0x0 : "CPU stop interrupts"
-0x0 : "Timer broadcast interrupts"
-0x0 : "IRQ work interrupts"
-0x0 : "CPU wakeup interrupts"
-0x0 : "CPU backtrace"
-0x0 : "rcu_sched"
-0x0 : "rcu_bh"
-0x0 : "rcu_preempt"
-)";
-
-  PrintkMap result = ParsePrintkFormats(format);
-  EXPECT_THAT(result, IsEmpty());
-}
-
-TEST(PrintkFormatParserTest, VariousAddresses) {
-  std::string format = R"(0x1 : "First line"
-0x1 : "First line"
-0x2 : "Unfortunate: colon"
-0x3 : ""
-0xffffff92349439b8 : "Large address"
-0x9 : "Last line")";
-
-  PrintkMap result = ParsePrintkFormats(format);
-  EXPECT_THAT(result.at(1), Eq("First line"));
-  EXPECT_THAT(result.at(2), Eq("Unfortunate: colon"));
-  EXPECT_THAT(result.at(18446743602145278392ULL), Eq("Large address"));
-  EXPECT_THAT(result.at(9), Eq("Last line"));
-  EXPECT_THAT(result.at(3), Eq(""));
-}
-
-TEST(PrintkFormatParserTest, RobustToRubbish) {
-  std::string format = R"(
-: leading colon
-trailing colon:
-multiple colons: : : : :
-Empty line:
-
-Just colon:
-:
-: "No address"
-No name:
-0x1 :
-0xbadhexaddress : "Bad hex address"
-0x2 : No quotes
-0x3:"No gap"
-"Wrong way round" : 0x4
-)";
-
-  PrintkMap result = ParsePrintkFormats(format);
-  EXPECT_THAT(result.at(2), Eq("No quotes"));
-  EXPECT_THAT(result.at(3), Eq("No gap"));
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/proto_translation_table.cc b/src/traced/probes/ftrace/proto_translation_table.cc
index 9a69745..44fe5f5 100644
--- a/src/traced/probes/ftrace/proto_translation_table.cc
+++ b/src/traced/probes/ftrace/proto_translation_table.cc
@@ -239,7 +239,6 @@
     case kFtraceUint64:
     case kFtraceInode32:
     case kFtraceInode64:
-    case kFtraceSymAddr64:
       *proto_type = ProtoSchemaType::kUint64;
       *proto_field_id = GenericFtraceEvent::Field::kUintValueFieldNumber;
       break;
@@ -288,15 +287,6 @@
     return true;
   }
 
-  // Kernel addresses that need symbolization via kallsyms. Only 64-bit kernels
-  // are supported for now. 32-bit kernels seems to be going away.
-  if ((base::StartsWith(type_and_name, "void*") ||
-       base::StartsWith(type_and_name, "void *")) &&
-      size == 8) {
-    *out = kFtraceSymAddr64;
-    return true;
-  }
-
   // Variable length strings: "char foo" + size: 0 (as in 'print').
   if (base::StartsWith(type_and_name, "char ") && size == 0) {
     *out = kFtraceCString;
@@ -424,7 +414,7 @@
     if (contents.empty() || !ParseFtraceEvent(contents, &ftrace_event)) {
       if (!strcmp(event.group, "ftrace") && !strcmp(event.name, "print")) {
         // On some "user" builds of Android <P the ftrace/print event is not
-        // selinux-allowed. Thankfully this event is an always-on built-in
+        // selinux-whitelisted. Thankfully this event is an always-on built-in
         // so we don't need to write to its 'enable' file. However we need to
         // know its binary layout to decode it, so we hardcode it.
         ftrace_event.id = 5;  // Seems quite stable across kernels.
@@ -463,12 +453,9 @@
   // about their format hold for this kernel.
   CompactSchedEventFormat compact_sched = ValidateFormatForCompactSched(events);
 
-  std::string text = ftrace_procfs->ReadPrintkFormats();
-  PrintkMap printk_formats = ParsePrintkFormats(text);
-
-  auto table = std::unique_ptr<ProtoTranslationTable>(new ProtoTranslationTable(
-      ftrace_procfs, events, std::move(common_fields), header_spec,
-      compact_sched, std::move(printk_formats)));
+  auto table = std::unique_ptr<ProtoTranslationTable>(
+      new ProtoTranslationTable(ftrace_procfs, events, std::move(common_fields),
+                                header_spec, compact_sched));
   return table;
 }
 
@@ -477,15 +464,13 @@
     const std::vector<Event>& events,
     std::vector<Field> common_fields,
     FtracePageHeaderSpec ftrace_page_header_spec,
-    CompactSchedEventFormat compact_sched_format,
-    PrintkMap printk_formats)
+    CompactSchedEventFormat compact_sched_format)
     : ftrace_procfs_(ftrace_procfs),
       events_(BuildEventsDeque(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),
-      printk_formats_(printk_formats) {
+      compact_sched_format_(compact_sched_format) {
   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 c822cd5..2cf0926 100644
--- a/src/traced/probes/ftrace/proto_translation_table.h
+++ b/src/traced/probes/ftrace/proto_translation_table.h
@@ -30,8 +30,7 @@
 #include "perfetto/ext/base/scoped_file.h"
 #include "src/traced/probes/ftrace/compact_sched.h"
 #include "src/traced/probes/ftrace/event_info.h"
-#include "src/traced/probes/ftrace/format_parser/format_parser.h"
-#include "src/traced/probes/ftrace/printk_formats_parser.h"
+#include "src/traced/probes/ftrace/format_parser.h"
 
 namespace perfetto {
 
@@ -100,8 +99,7 @@
                         const std::vector<Event>& events,
                         std::vector<Field> common_fields,
                         FtracePageHeaderSpec ftrace_page_header_spec,
-                        CompactSchedEventFormat compact_sched_format,
-                        PrintkMap printk_formats);
+                        CompactSchedEventFormat compact_sched_format);
 
   size_t largest_id() const { return largest_id_; }
 
@@ -166,10 +164,6 @@
     return compact_sched_format_;
   }
 
-  base::StringView LookupTraceString(uint64_t address) const {
-    return printk_formats_.at(address);
-  }
-
  private:
   ProtoTranslationTable(const ProtoTranslationTable&) = delete;
   ProtoTranslationTable& operator=(const ProtoTranslationTable&) = delete;
@@ -190,7 +184,6 @@
   FtracePageHeaderSpec ftrace_page_header_spec_{};
   std::set<std::string> interned_strings_;
   CompactSchedEventFormat compact_sched_format_;
-  PrintkMap printk_formats_;
 };
 
 // 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 0210f71..1ca013a 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -397,7 +397,7 @@
   ProtoTranslationTable table(
       &ftrace, events, std::move(common_fields),
       ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-      InvalidCompactSchedEventFormatForTesting(), PrintkMap());
+      InvalidCompactSchedEventFormatForTesting());
 
   EXPECT_EQ(table.largest_id(), 100ul);
   EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_one", "foo")), 1ul);
diff --git a/src/traced/probes/ftrace/test/data/synthetic/available_events b/src/traced/probes/ftrace/test/data/synthetic/available_events
index 2ee225a..500dcb2 100644
--- a/src/traced/probes/ftrace/test/data/synthetic/available_events
+++ b/src/traced/probes/ftrace/test/data/synthetic/available_events
@@ -7,8 +7,3 @@
 clk:clk_disable
 clk:clk_set_rate
 sde:tracing_mark_write
-fastrpc:fastrpc_dma_stat
-dpu:tracing_mark_write
-g2d:tracing_mark_write
-power:suspend_resume
-cpuhp:cpuhp_pause
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/format b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/format
deleted file mode 100644
index fd990fb..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: cpuhp_enter
-ID: 33
-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:unsigned int cpu;	offset:8;	size:4;	signed:0;
-	field:int target;	offset:12;	size:4;	signed:1;
-	field:int idx;	offset:16;	size:4;	signed:1;
-	field:void * fun;	offset:24;	size:8;	signed:0;
-
-print fmt: "cpu: %04u target: %3d step: %3d (%pf)", REC->cpu, REC->target, REC->idx, REC->fun
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/id b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/id
deleted file mode 100644
index bb95160..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_enter/id
+++ /dev/null
@@ -1 +0,0 @@
-33
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/format b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/format
deleted file mode 100644
index ec5fdde..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: cpuhp_exit
-ID: 34
-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:unsigned int cpu;	offset:8;	size:4;	signed:0;
-	field:int state;	offset:12;	size:4;	signed:1;
-	field:int idx;	offset:16;	size:4;	signed:1;
-	field:int ret;	offset:20;	size:4;	signed:1;
-
-print fmt: " cpu: %04u  state: %3d step: %3d ret: %d", REC->cpu, REC->state, REC->idx, REC->ret
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/id b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/id
deleted file mode 100644
index a787364..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_exit/id
+++ /dev/null
@@ -1 +0,0 @@
-34
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/format b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/format
deleted file mode 100644
index 9d01304..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: cpuhp_latency
-ID: 35
-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:unsigned int cpu;	offset:8;	size:4;	signed:0;
-	field:unsigned int state;	offset:12;	size:4;	signed:0;
-	field:u64 time;	offset:16;	size:8;	signed:0;
-	field:int ret;	offset:24;	size:4;	signed:1;
-
-print fmt: " cpu:%d state:%s latency:%llu USEC ret: %d", REC->cpu, REC->state ? "online" : "offline", REC->time, REC->ret
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/id b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/id
deleted file mode 100644
index 8f92bfd..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_latency/id
+++ /dev/null
@@ -1 +0,0 @@
-35
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/format b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/format
deleted file mode 100644
index fef4f62..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: cpuhp_multi_enter
-ID: 36
-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:unsigned int cpu;	offset:8;	size:4;	signed:0;
-	field:int target;	offset:12;	size:4;	signed:1;
-	field:int idx;	offset:16;	size:4;	signed:1;
-	field:void * fun;	offset:24;	size:8;	signed:0;
-
-print fmt: "cpu: %04u target: %3d step: %3d (%pf)", REC->cpu, REC->target, REC->idx, REC->fun
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/id b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/id
deleted file mode 100644
index 7facc89..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_multi_enter/id
+++ /dev/null
@@ -1 +0,0 @@
-36
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_pause/format b/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_pause/format
deleted file mode 100644
index e0ff5e8..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/cpuhp/cpuhp_pause/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: cpuhp_pause
-ID: 68
-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:unsigned int cpus;	offset:8;	size:4;	signed:0;
-	field:unsigned int active_cpus;	offset:12;	size:4;	signed:0;
-	field:unsigned int time;	offset:16;	size:4;	signed:0;
-	field:unsigned char pause;	offset:20;	size:1;	signed:0;
-
-print fmt: "req_cpus=0x%x act_cpus=0x%x time=%u us paused=%d", REC->cpus, REC->active_cpus, REC->time, REC->pause
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/dmabuf_heap/dma_heap_stat/format b/src/traced/probes/ftrace/test/data/synthetic/events/dmabuf_heap/dma_heap_stat/format
deleted file mode 100644
index cf23ff8..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/dmabuf_heap/dma_heap_stat/format
+++ /dev/null
@@ -1,13 +0,0 @@
-name: dma_heap_stat
-ID: 1304
-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:unsigned long inode;	offset:8;	size:8;	signed:0;
-	field:long len;	offset:16;	size:8;	signed:1;
-	field:unsigned long total_allocated;	offset:24;	size:8;	signed:0;
-
-print fmt: "inode=%lu len=%ldB total_allocated=%luB", REC->inode, REC->len, REC->total_allocated
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/dpu/tracing_mark_write/format b/src/traced/probes/ftrace/test/data/synthetic/events/dpu/tracing_mark_write/format
deleted file mode 100644
index 51e0e8b..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/dpu/tracing_mark_write/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: tracing_mark_write
-ID: 1280
-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 type;	offset:8;	size:1;	signed:0;
-	field:int pid;	offset:12;	size:4;	signed:1;
-	field:__data_loc char[] name;	offset:16;	size:4;	signed:0;
-	field:int value;	offset:20;	size:4;	signed:1;
-
-print fmt: "%c|%d|%s|%d", REC->type, REC->pid, __get_str(name), REC->value
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/fastrpc/fastrpc_dma_stat/format b/src/traced/probes/ftrace/test/data/synthetic/events/fastrpc/fastrpc_dma_stat/format
deleted file mode 100644
index d9a922f..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/fastrpc/fastrpc_dma_stat/format
+++ /dev/null
@@ -1,13 +0,0 @@
-name: fastrpc_dma_stat
-ID: 1039
-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:int cid;	offset:8;	size:4;	signed:1;
-	field:long len;	offset:16;	size:8;	signed:1;
-	field:unsigned long total_allocated;	offset:24;	size:8;	signed:0;
-
-print fmt: "cid=%u len=%ldB total_allocated=%ldB", REC->cid, REC->len, REC->total_allocated
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/g2d/tracing_mark_write/format b/src/traced/probes/ftrace/test/data/synthetic/events/g2d/tracing_mark_write/format
deleted file mode 100644
index f17c68b..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/g2d/tracing_mark_write/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: tracing_mark_write
-ID: 1202
-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 type;	offset:8;	size:1;	signed:0;
-	field:int pid;	offset:12;	size:4;	signed:1;
-	field:__data_loc char[] name;	offset:16;	size:4;	signed:0;
-	field:int value;	offset:20;	size:4;	signed:1;
-
-print fmt: "%c|%d|%s|%d", REC->type, REC->pid, __get_str(name), REC->value
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/mali/tracing_mark_write/format b/src/traced/probes/ftrace/test/data/synthetic/events/mali/tracing_mark_write/format
deleted file mode 100644
index 4be4037..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/mali/tracing_mark_write/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: tracing_mark_write
-ID: 1409
-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 type;        offset:8;       size:1; signed:0;
-        field:int pid;  offset:12;      size:4; signed:1;
-        field:__data_loc char[] name;   offset:16;      size:4; signed:0;
-        field:int value;        offset:20;      size:4; signed:1;
-
-print fmt: "%c|%d|%s|%d", REC->type, REC->pid, __get_str(name), REC->value
\ No newline at end of file
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/power/suspend_resume/format b/src/traced/probes/ftrace/test/data/synthetic/events/power/suspend_resume/format
deleted file mode 100644
index aabfb0b..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/power/suspend_resume/format
+++ /dev/null
@@ -1,13 +0,0 @@
-name: suspend_resume
-ID: 172
-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:const char * action;	offset:8;	size:8;	signed:0;
-	field:int val;	offset:16;	size:4;	signed:1;
-	field:bool start;	offset:20;	size:1;	signed:0;
-
-print fmt: "%s[%u] %s", REC->action, (unsigned int)REC->val, (REC->start)?"begin":"end"
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_pi_setprio/format b/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_pi_setprio/format
deleted file mode 100644
index 818f484..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_pi_setprio/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: sched_pi_setprio
-ID: 77
-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 oldprio;	offset:28;	size:4;	signed:1;
-	field:int newprio;	offset:32;	size:4;	signed:1;
-
-print fmt: "comm=%s pid=%d oldprio=%d newprio=%d", REC->comm, REC->pid, REC->oldprio, REC->newprio
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_evtlog/format b/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_evtlog/format
deleted file mode 100644
index 8b3cda1..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_evtlog/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: sde_evtlog
-ID: 590
-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:int pid;	offset:8;	size:4;	signed:1;
-	field:__data_loc char[] evtlog_tag;	offset:12;	size:4;	signed:0;
-	field:u32 tag_id;	offset:16;	size:4;	signed:0;
-	field:u32 data[15];	offset:20;	size:60;	signed:0;
-
-print fmt: "%d|%s:%d|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x", REC->pid, __get_str(evtlog_tag), REC->tag_id, REC->data[0], REC->data[1], REC->data[2], REC->data[3], REC->data[4], REC->data[5], REC->data[6], REC->data[7], REC->data[8], REC->data[9], REC->data[10], REC->data[11], REC->data[12], REC->data[13], REC->data[14]
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_calc_crtc/format b/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_calc_crtc/format
deleted file mode 100644
index 728bd05..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_calc_crtc/format
+++ /dev/null
@@ -1,18 +0,0 @@
-name: sde_perf_calc_crtc
-ID: 591
-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:u32 crtc;	offset:8;	size:4;	signed:0;
-	field:u64 bw_ctl_mnoc;	offset:16;	size:8;	signed:0;
-	field:u64 bw_ctl_llcc;	offset:24;	size:8;	signed:0;
-	field:u64 bw_ctl_ebi;	offset:32;	size:8;	signed:0;
-	field:u64 ib_mnoc;	offset:40;	size:8;	signed:0;
-	field:u64 ib_llcc;	offset:48;	size:8;	signed:0;
-	field:u64 ib_ebi;	offset:56;	size:8;	signed:0;
-	field:u32 core_clk_rate;	offset:64;	size:4;	signed:0;
-
-print fmt: "crtc=%d mnoc=[%llu, %llu] llcc=[%llu %llu] ebi=[%llu, %llu] clk_rate=%u", REC->crtc, REC->bw_ctl_mnoc, REC->ib_mnoc, REC->bw_ctl_llcc, REC->ib_llcc, REC->bw_ctl_ebi, REC->ib_ebi, REC->core_clk_rate
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_crtc_update/format b/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_crtc_update/format
deleted file mode 100644
index fda8a78..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_crtc_update/format
+++ /dev/null
@@ -1,22 +0,0 @@
-name: sde_perf_crtc_update
-ID: 592
-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:u32 crtc;	offset:8;	size:4;	signed:0;
-	field:u64 bw_ctl_mnoc;	offset:16;	size:8;	signed:0;
-	field:u64 per_pipe_ib_mnoc;	offset:24;	size:8;	signed:0;
-	field:u64 bw_ctl_llcc;	offset:32;	size:8;	signed:0;
-	field:u64 per_pipe_ib_llcc;	offset:40;	size:8;	signed:0;
-	field:u64 bw_ctl_ebi;	offset:48;	size:8;	signed:0;
-	field:u64 per_pipe_ib_ebi;	offset:56;	size:8;	signed:0;
-	field:u32 core_clk_rate;	offset:64;	size:4;	signed:0;
-	field:bool stop_req;	offset:68;	size:1;	signed:0;
-	field:u32 update_bus;	offset:72;	size:4;	signed:0;
-	field:u32 update_clk;	offset:76;	size:4;	signed:0;
-	field:int params;	offset:80;	size:4;	signed:1;
-
-print fmt: "crtc=%d mnoc=[%llu %llu] llcc=[%llu %llu] ebi=[%llu %llu] clk=%u stop=%d ubus=%d uclk=%d %d", REC->crtc, REC->bw_ctl_mnoc, REC->per_pipe_ib_mnoc, REC->bw_ctl_llcc, REC->per_pipe_ib_llcc, REC->bw_ctl_ebi, REC->per_pipe_ib_ebi, REC->core_clk_rate, REC->stop_req, REC->update_bus, REC->update_clk, REC->params
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_set_qos_luts/format b/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_set_qos_luts/format
deleted file mode 100644
index 6762f3d..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_set_qos_luts/format
+++ /dev/null
@@ -1,16 +0,0 @@
-name: sde_perf_set_qos_luts
-ID: 595
-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:u32 pnum;	offset:8;	size:4;	signed:0;
-	field:u32 fmt;	offset:12;	size:4;	signed:0;
-	field:bool rt;	offset:16;	size:1;	signed:0;
-	field:u32 fl;	offset:20;	size:4;	signed:0;
-	field:u64 lut;	offset:24;	size:8;	signed:0;
-	field:u32 lut_usage;	offset:32;	size:4;	signed:0;
-
-print fmt: "pnum=%d fmt=%x rt=%d fl=%d lut=0x%llx lut_usage=%d", REC->pnum, REC->fmt, REC->rt, REC->fl, REC->lut, REC->lut_usage
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_update_bus/format b/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_update_bus/format
deleted file mode 100644
index f8a0e58..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sde/sde_perf_update_bus/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: sde_perf_update_bus
-ID: 596
-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:int client;	offset:8;	size:4;	signed:1;
-	field:u32 bus_id;	offset:12;	size:4;	signed:0;
-	field:u64 ab_quota;	offset:16;	size:8;	signed:0;
-	field:u64 ib_quota;	offset:24;	size:8;	signed:0;
-
-print fmt: "Request client:%d bus_id:%d ab=%llu ib=%llu", REC->client, REC->bus_id, REC->ab_quota, REC->ib_quota
diff --git a/src/traced/probes/ftrace/test/data/synthetic/printk_formats b/src/traced/probes/ftrace/test/data/synthetic/printk_formats
deleted file mode 100644
index 5f0f8c6..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/printk_formats
+++ /dev/null
@@ -1,5 +0,0 @@
-0xffffff850501d52e : "Entries can be duplicated"
-0xffffff8504f57a1c : "freeze_processes"
-0xffffff8504f57a1c : "freeze_processes"
-0xffffff8504f57a5a : "sync_filesystems"
-0xffffff8504f57a4c : "suspend_enter"
diff --git a/src/traced/probes/ftrace/test/explorer.html b/src/traced/probes/ftrace/test/explorer.html
index a474df5..a567b10 100755
--- a/src/traced/probes/ftrace/test/explorer.html
+++ b/src/traced/probes/ftrace/test/explorer.html
@@ -160,30 +160,12 @@
   });
 }
 
-function delay(t, v) {
- return new Promise(resolve => { 
-   setTimeout(resolve.bind(null, v), t)
- });
-}
-
-// Limit the number of outstanding fetch requests to avoid causing
-// problems in the browser.
-let GET_URL_TOKENS = 400;
-async function geturl(url) {
+function geturl(url) {
   console.log('Fetch:', url);
   if (gCache.has(url)) return Promise.resolve(gCache.get(url));
-
-  while (GET_URL_TOKENS === 0) {
-    // Retry in 1000ms +/- 250ms to avoid all the requests lining up.
-    await delay(1000 + 500 * (Math.random() - 0.5));
-  }
-  GET_URL_TOKENS -= 1;
-
   return fetch(url).then(r => r.text()).then(text => {
     gCache.set(url, text);
     return text;
-  }).finally(() => {
-    GET_URL_TOKENS += 1;
   });
 }
 
@@ -260,7 +242,7 @@
   return m('.context', [
     m('h1', {class: 'title'}, 'Ftrace Format Explorer'),
     m('input[type=text][placeholder=Filter]', {
-      oninput: e => gFilterText = e.target.value,
+      oninput: m.withAttr('value', value => gFilterText = value),
       value: filterText,
     }),
     m('ul',
@@ -284,7 +266,7 @@
   if (!r2) r2 = records[0];
   let f1 = getfiletext(r1.url);
   let f2 = getfiletext(r2.url);
-  let diff = Diff.diffChars(f1, f2);
+  let diff = JsDiff.diffChars(f1, f2);
 
   let es = diff.map(part => {
     let color = part.added ? 'green' : part.removed ? 'red' : 'grey';
diff --git a/src/traced/probes/ftrace/test/test_messages.proto b/src/traced/probes/ftrace/test/test_messages.proto
index 3d584d9..1e6ece4 100644
--- a/src/traced/probes/ftrace/test/test_messages.proto
+++ b/src/traced/probes/ftrace/test/test_messages.proto
@@ -32,5 +32,4 @@
   optional string field_char_16 = 500;
   optional string field_char = 501;
   optional string field_data_loc = 502;
-  optional string field_char_star = 503;
 }
diff --git a/src/traced/probes/ftrace/test/test_proto_gen.py b/src/traced/probes/ftrace/test/test_proto_gen.py
index 13ad62b..a7f63e2 100755
--- a/src/traced/probes/ftrace/test/test_proto_gen.py
+++ b/src/traced/probes/ftrace/test/test_proto_gen.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/src/traced/probes/initial_display_state/initial_display_state_data_source.cc b/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
index f5b9583..08bb0fa 100644
--- a/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
+++ b/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
@@ -73,8 +73,7 @@
     auto weak_this = GetWeakPtr();
 
     uint32_t delay_ms =
-        poll_period_ms_ -
-        static_cast<uint32_t>(base::GetWallTimeMs().count() % poll_period_ms_);
+        poll_period_ms_ - (base::GetWallTimeMs().count() % poll_period_ms_);
     task_runner_->PostDelayedTask(
         [weak_this]() -> void {
           if (weak_this) {
diff --git a/src/traced/probes/kmem_activity_trigger.cc b/src/traced/probes/kmem_activity_trigger.cc
deleted file mode 100644
index 589cdab..0000000
--- a/src/traced/probes/kmem_activity_trigger.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/kmem_activity_trigger.h"
-
-#include <unistd.h>
-
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/waitable_event.h"
-#include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "src/traced/probes/probes_producer.h"
-
-namespace perfetto {
-
-namespace {
-constexpr uint32_t kTriggerIntervalMs = 60 * 1000;  // 1 min.
-constexpr size_t kPerCpuTraceBufferSizeInPages = 1;
-constexpr char kTriggerName[] = "kmem_activity";
-
-}  // namespace
-
-// This is called by traced_probes' ProbesMain().
-KmemActivityTrigger::KmemActivityTrigger()
-    : task_runner_(base::ThreadTaskRunner::CreateAndStart()) {
-  task_runner_.PostTask(
-      [this]() { worker_data_.reset(new WorkerData(&task_runner_)); });
-}
-
-KmemActivityTrigger::~KmemActivityTrigger() {
-  base::WaitableEvent evt;
-  task_runner_.PostTask([this, &evt]() {
-    worker_data_.reset();  // Destroy the WorkerData object.
-    evt.Notify();
-  });
-  evt.Wait();
-}
-
-KmemActivityTrigger::WorkerData::~WorkerData() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (ftrace_procfs_) {
-    ftrace_procfs_->DisableTracing();
-    ftrace_procfs_->ClearTrace();
-  }
-  DisarmFtraceFDWatches();
-}
-
-KmemActivityTrigger::WorkerData::WorkerData(base::TaskRunner* task_runner)
-    : task_runner_(task_runner), weak_ptr_factory_(this) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  ftrace_procfs_ =
-      FtraceProcfs::CreateGuessingMountPoint("instances/mm_events/");
-  if (!ftrace_procfs_) {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-    PERFETTO_LOG(
-        "mm_events ftrace instance not found. Triggering of traces on memory "
-        "pressure will not be available on this device.");
-#endif
-    return;
-  }
-
-  ftrace_procfs_->SetCpuBufferSizeInPages(kPerCpuTraceBufferSizeInPages);
-
-  // Enable mm trace events
-  ftrace_procfs_->DisableAllEvents();
-  ftrace_procfs_->EnableEvent("vmscan", "mm_vmscan_direct_reclaim_begin");
-  ftrace_procfs_->EnableEvent("compaction", "mm_compaction_begin");
-  ftrace_procfs_->EnableTracing();
-
-  num_cpus_ = ftrace_procfs_->NumberOfCpus();
-  for (size_t cpu = 0; cpu < num_cpus_; cpu++) {
-    trace_pipe_fds_.emplace_back(ftrace_procfs_->OpenPipeForCpu(cpu));
-    auto& scoped_fd = trace_pipe_fds_.back();
-    if (!scoped_fd) {
-      PERFETTO_PLOG("Failed to open trace_pipe_raw for cpu %zu", cpu);
-      // Deliberately keeping this into the |trace_pipe_fds_| array so there is
-      // a 1:1 mapping between CPU number and index in the array.
-    } else {
-        // Attempt reading from the trace pipe to detect if the CPU is disabled,
-        // since open() doesn't fail. (b/169210648, b/178929757) This doesn't block
-        // as OpenPipeForCpu() opens the pipe in non-blocking mode.
-        char ch;
-        if (base::Read(scoped_fd.get(), &ch, sizeof(char)) < 0 && errno == ENODEV) {
-            scoped_fd.reset();
-        }
-    }
-  }
-
-  ArmFtraceFDWatches();
-}
-
-void KmemActivityTrigger::WorkerData::ArmFtraceFDWatches() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  if (fd_watches_armed_)
-    return;
-  fd_watches_armed_ = true;
-  for (size_t cpu = 0; cpu < trace_pipe_fds_.size(); cpu++) {
-    const auto& scoped_fd = trace_pipe_fds_[cpu];
-    if (!scoped_fd)
-      continue;  // Can happen if the initial open() failed (CPU hotplug).
-    ftrace_procfs_->ClearPerCpuTrace(cpu);
-    task_runner_->AddFileDescriptorWatch(scoped_fd.get(), [weak_this, cpu] {
-      if (weak_this)
-        weak_this->OnFtracePipeWakeup(cpu);
-    });
-  }
-}
-
-void KmemActivityTrigger::WorkerData::DisarmFtraceFDWatches() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!fd_watches_armed_)
-    return;
-  fd_watches_armed_ = false;
-  for (const base::ScopedFile& fd : trace_pipe_fds_) {
-    if (fd)
-      task_runner_->RemoveFileDescriptorWatch(fd.get());
-  }
-}
-
-void KmemActivityTrigger::WorkerData::OnFtracePipeWakeup(size_t cpu) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("KmemActivityTrigger ftrace pipe wakeup on cpu %zu", cpu);
-  ftrace_procfs_->ClearPerCpuTrace(cpu);
-
-  if (!fd_watches_armed_) {
-    // If false, another task for another CPU got here, disarmed the watches
-    // and posted the re-arming. Don't append another task.
-    return;
-  }
-
-  ProbesProducer* probes_producer = ProbesProducer::GetInstance();
-  if (probes_producer)
-    probes_producer->ActivateTrigger(kTriggerName);
-
-  // Once a ftrace pipe wakes up, disarm the poll() and re-enable only after
-  // kTriggerIntervalMs. This is to avoid spinning on the pipes if there is too
-  // much ftrace activity (b/178929757).
-
-  DisarmFtraceFDWatches();
-
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      [weak_this] {
-        if (weak_this)
-          weak_this->ArmFtraceFDWatches();
-      },
-      kTriggerIntervalMs);
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/kmem_activity_trigger.h b/src/traced/probes/kmem_activity_trigger.h
deleted file mode 100644
index 4eb50c6..0000000
--- a/src/traced/probes/kmem_activity_trigger.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_KMEM_ACTIVITY_TRIGGER_H_
-#define SRC_TRACED_PROBES_KMEM_ACTIVITY_TRIGGER_H_
-
-#include <memory>
-#include <vector>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/thread_task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-
-namespace perfetto {
-
-class FtraceProcfs;
-
-class KmemActivityTrigger {
- public:
-  KmemActivityTrigger();
-  ~KmemActivityTrigger();
-
- private:
-  // This object lives entirely on the KmemActivityTrigger |task_runner_|.
-  class WorkerData {
-   public:
-    WorkerData(base::TaskRunner*);
-    ~WorkerData();
-    void InitializeOnThread();
-    void ArmFtraceFDWatches();
-    void DisarmFtraceFDWatches();
-    void OnFtracePipeWakeup(size_t cpu);
-
-   private:
-    // All the fields below are accessed only on the dedicated |task_runner_|.
-    base::TaskRunner* const task_runner_;
-    std::unique_ptr<FtraceProcfs> ftrace_procfs_;
-    std::vector<base::ScopedFile> trace_pipe_fds_;
-    size_t num_cpus_ = 0;
-    bool fd_watches_armed_ = false;
-
-    // Keep last.
-    base::WeakPtrFactory<WorkerData> weak_ptr_factory_;
-    PERFETTO_THREAD_CHECKER(thread_checker_)
-  };
-
-  base::ThreadTaskRunner task_runner_;
-  std::unique_ptr<WorkerData> worker_data_;
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_KMEM_ACTIVITY_TRIGGER_H_
diff --git a/src/traced/probes/packages_list/BUILD.gn b/src/traced/probes/packages_list/BUILD.gn
index 669fa18..0f17596 100644
--- a/src/traced/probes/packages_list/BUILD.gn
+++ b/src/traced/probes/packages_list/BUILD.gn
@@ -14,21 +14,9 @@
 
 import("../../../../gn/test.gni")
 
-source_set("packages_list_parser") {
-  deps = [
-    "../../../../gn:default_deps",
-    "../../../base",
-  ]
-  sources = [
-    "packages_list_parser.cc",
-    "packages_list_parser.h",
-  ]
-}
-
 source_set("packages_list") {
   public_deps = [ "../../../tracing/core" ]
   deps = [
-    ":packages_list_parser",
     "..:data_source",
     "../../../../gn:default_deps",
     "../../../../include/perfetto/ext/traced",
@@ -48,7 +36,6 @@
   testonly = true
   deps = [
     ":packages_list",
-    ":packages_list_parser",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
     "../../../../protos/perfetto/trace/android:cpp",
@@ -56,5 +43,5 @@
     "../../../../src/base:test_support",
     "../../../../src/tracing/test:test_support",
   ]
-  sources = [ "packages_list_unittest.cc" ]
+  sources = [ "packages_list_data_source_unittest.cc" ]
 }
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 f9919b8..68fa662 100644
--- a/src/traced/probes/packages_list/packages_list_data_source.cc
+++ b/src/traced/probes/packages_list/packages_list_data_source.cc
@@ -22,8 +22,6 @@
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
-#include "src/traced/probes/packages_list/packages_list_parser.h"
-
 using perfetto::protos::pbzero::PackagesListConfig;
 
 namespace perfetto {
@@ -59,6 +57,60 @@
   return parsed_fully;
 }
 
+bool ReadPackagesListLine(char* line, Package* package) {
+  size_t idx = 0;
+  for (base::StringSplitter ss(line, ' '); ss.Next();) {
+    switch (idx) {
+      case 0:
+        package->name = std::string(ss.cur_token(), ss.cur_token_size());
+        break;
+      case 1: {
+        char* end;
+        long long uid = strtoll(ss.cur_token(), &end, 10);
+        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
+          PERFETTO_ELOG("Failed to parse packages.list uid.");
+          return false;
+        }
+        package->uid = static_cast<uint64_t>(uid);
+        break;
+      }
+      case 2: {
+        char* end;
+        long long debuggable = strtoll(ss.cur_token(), &end, 10);
+        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
+          PERFETTO_ELOG("Failed to parse packages.list debuggable.");
+          return false;
+        }
+        package->debuggable = debuggable != 0;
+        break;
+      }
+      case 6: {
+        char* end;
+        long long profilable_from_shell = strtoll(ss.cur_token(), &end, 10);
+        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
+          PERFETTO_ELOG("Failed to parse packages.list profilable_from_shell.");
+          return false;
+        }
+        package->profileable_from_shell = profilable_from_shell != 0;
+        break;
+      }
+      case 7: {
+        char* end;
+        long long version_code = strtoll(ss.cur_token(), &end, 10);
+        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
+          PERFETTO_ELOG("Failed to parse packages.list version_code: %s.",
+                        ss.cur_token());
+          return false;
+        }
+        package->version_code = version_code;
+        break;
+      }
+    }
+    ++idx;
+  }
+  return true;
+}
+
 PackagesListDataSource::PackagesListDataSource(
     const DataSourceConfig& ds_config,
     TracingSessionID session_id,
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 b19472b..5dd3fdc 100644
--- a/src/traced/probes/packages_list/packages_list_data_source.h
+++ b/src/traced/probes/packages_list/packages_list_data_source.h
@@ -35,6 +35,15 @@
 
 class TraceWriter;
 
+struct Package {
+  std::string name;
+  uint64_t uid = 0;
+  bool debuggable = false;
+  bool profileable_from_shell = false;
+  int64_t version_code = 0;
+};
+
+bool ReadPackagesListLine(char* line, Package* package);
 bool ParsePackagesListStream(protos::pbzero::PackagesList* packages_list,
                              const base::ScopedFstream& fs,
                              const std::set<std::string>& package_name_filter);
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
new file mode 100644
index 0000000..cb311d2
--- /dev/null
+++ b/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/packages_list/packages_list_data_source.h"
+
+#include <stdio.h>
+
+#include <set>
+#include <string>
+
+#include "perfetto/ext/base/pipe.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/trace/android/packages_list.gen.h"
+#include "protos/perfetto/trace/android/packages_list.pbzero.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+TEST(PackagesListDataSourceTest, ParseLineNonProfileNonDebug) {
+  char kLine[] =
+      "com.test.app 1234 0 /data/user/0/com.test.app "
+      "default:targetSdkVersion=12452 1234,5678 0 1111\n";
+  Package pkg;
+  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
+  EXPECT_EQ(pkg.name, "com.test.app");
+  EXPECT_EQ(pkg.debuggable, false);
+  EXPECT_EQ(pkg.profileable_from_shell, false);
+  EXPECT_EQ(pkg.version_code, 1111);
+}
+
+TEST(PackagesListDataSourceTest, ParseLineProfileNonDebug) {
+  char kLine[] =
+      "com.test.app 1234 0 /data/user/0/com.test.app "
+      "default:targetSdkVersion=12452 1234,5678 1 1111\n";
+  Package pkg;
+  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
+  EXPECT_EQ(pkg.name, "com.test.app");
+  EXPECT_EQ(pkg.debuggable, false);
+  EXPECT_EQ(pkg.profileable_from_shell, true);
+  EXPECT_EQ(pkg.version_code, 1111);
+}
+
+TEST(PackagesListDataSourceTest, ParseLineNonProfileDebug) {
+  char kLine[] =
+      "com.test.app 1234 1 /data/user/0/com.test.app "
+      "default:targetSdkVersion=12452 1234,5678 0 1111\n";
+  Package pkg;
+  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
+  EXPECT_EQ(pkg.name, "com.test.app");
+  EXPECT_EQ(pkg.debuggable, true);
+  EXPECT_EQ(pkg.profileable_from_shell, false);
+  EXPECT_EQ(pkg.version_code, 1111);
+}
+
+TEST(PackagesListDataSourceTest, ParseLineProfileDebug) {
+  char kLine[] =
+      "com.test.app 1234 1 /data/user/0/com.test.app "
+      "default:targetSdkVersion=12452 1234,5678 1 1111\n";
+  Package pkg;
+  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
+  EXPECT_EQ(pkg.name, "com.test.app");
+  EXPECT_EQ(pkg.debuggable, true);
+  EXPECT_EQ(pkg.profileable_from_shell, true);
+  EXPECT_EQ(pkg.version_code, 1111);
+}
+
+TEST(PackagesListDataSourceTest, EmptyNameFilterIncludesAll) {
+  char buf[] =
+      "com.test.one 1000 0 /data/user/0/com.test.one "
+      "default:targetSdkVersion=10 none 0 10\n"
+      "com.test.two 1001 0 /data/user/0/com.test.two "
+      "default:targetSdkVersion=10 1065,3002 0 20\n"
+      "com.test.three 1002 0 /data/user/0/com.test.three "
+      "default:targetSdkVersion=10 1065,3002 0 30\n";
+
+  // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
+  // requires a higher target API (23) than we use for portability.
+  auto pipe = base::Pipe::Create();
+  PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
+  pipe.wr.reset();
+  auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
+  pipe.rd.release();  // now owned by |fs|
+
+  protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
+  std::set<std::string> filter{};
+
+  ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
+
+  protos::gen::PackagesList parsed_list;
+  parsed_list.ParseFromString(packages_list.SerializeAsString());
+
+  EXPECT_FALSE(parsed_list.read_error());
+  EXPECT_FALSE(parsed_list.parse_error());
+  // all entries
+  EXPECT_EQ(parsed_list.packages_size(), 3);
+  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
+  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
+  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.two");
+  EXPECT_EQ(parsed_list.packages()[1].version_code(), 20);
+  EXPECT_EQ(parsed_list.packages()[2].name(), "com.test.three");
+  EXPECT_EQ(parsed_list.packages()[2].version_code(), 30);
+}
+
+TEST(PackagesListDataSourceTest, NameFilter) {
+  char buf[] =
+      "com.test.one 1000 0 /data/user/0/com.test.one "
+      "default:targetSdkVersion=10 none 0 10\n"
+      "com.test.two 1001 0 /data/user/0/com.test.two "
+      "default:targetSdkVersion=10 1065,3002 0 20\n"
+      "com.test.three 1002 0 /data/user/0/com.test.three "
+      "default:targetSdkVersion=10 1065,3002 0 30\n";
+
+  // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
+  // requires a higher target API (23) than we use for portability.
+  auto pipe = base::Pipe::Create();
+  PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
+  pipe.wr.reset();
+  auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
+  pipe.rd.release();  // now owned by |fs|
+
+  protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
+  std::set<std::string> filter{"com.test.one", "com.test.three"};
+
+  ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
+
+  protos::gen::PackagesList parsed_list;
+  parsed_list.ParseFromString(packages_list.SerializeAsString());
+
+  EXPECT_FALSE(parsed_list.read_error());
+  EXPECT_FALSE(parsed_list.parse_error());
+  // two named entries
+  EXPECT_EQ(parsed_list.packages_size(), 2);
+  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
+  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
+  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.three");
+  EXPECT_EQ(parsed_list.packages()[1].version_code(), 30);
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/traced/probes/packages_list/packages_list_parser.cc b/src/traced/probes/packages_list/packages_list_parser.cc
deleted file mode 100644
index 9b58e20..0000000
--- a/src/traced/probes/packages_list/packages_list_parser.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/traced/probes/packages_list/packages_list_parser.h"
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-
-namespace perfetto {
-
-bool ReadPackagesListLine(char* line, Package* package) {
-  size_t idx = 0;
-  for (base::StringSplitter ss(line, ' '); ss.Next();) {
-    switch (idx) {
-      case 0:
-        package->name = std::string(ss.cur_token(), ss.cur_token_size());
-        break;
-      case 1: {
-        char* end;
-        long long uid = strtoll(ss.cur_token(), &end, 10);
-        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
-          PERFETTO_ELOG("Failed to parse packages.list uid.");
-          return false;
-        }
-        package->uid = static_cast<uint64_t>(uid);
-        break;
-      }
-      case 2: {
-        char* end;
-        long long debuggable = strtoll(ss.cur_token(), &end, 10);
-        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
-          PERFETTO_ELOG("Failed to parse packages.list debuggable.");
-          return false;
-        }
-        package->debuggable = debuggable != 0;
-        break;
-      }
-      case 6: {
-        char* end;
-        long long profilable_from_shell = strtoll(ss.cur_token(), &end, 10);
-        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
-          PERFETTO_ELOG("Failed to parse packages.list profilable_from_shell.");
-          return false;
-        }
-        package->profileable_from_shell = profilable_from_shell != 0;
-        break;
-      }
-      case 7: {
-        char* end;
-        long long version_code = strtoll(ss.cur_token(), &end, 10);
-        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
-          PERFETTO_ELOG("Failed to parse packages.list version_code: %s.",
-                        ss.cur_token());
-          return false;
-        }
-        package->version_code = version_code;
-        break;
-      }
-      case 8: {
-        char* end;
-        long long profileable = strtoll(ss.cur_token(), &end, 10);
-        if ((*end != '\0' && *end != '\n') || *ss.cur_token() == '\0') {
-          PERFETTO_ELOG("Failed to parse packages.list profileable.");
-          return false;
-        }
-        package->profileable = profileable != 0;
-        break;
-      }
-      case 9:
-        package->installed_by =
-            std::string(ss.cur_token(), ss.cur_token_size());
-        break;
-    }
-    ++idx;
-  }
-  return true;
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/packages_list/packages_list_parser.h b/src/traced/probes/packages_list/packages_list_parser.h
deleted file mode 100644
index 9cbecd1..0000000
--- a/src/traced/probes/packages_list/packages_list_parser.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACED_PROBES_PACKAGES_LIST_PACKAGES_LIST_PARSER_H_
-#define SRC_TRACED_PROBES_PACKAGES_LIST_PACKAGES_LIST_PARSER_H_
-
-#include <inttypes.h>
-#include <string>
-
-namespace perfetto {
-
-struct Package {
-  std::string name;
-  uint64_t uid = 0;
-  bool debuggable = false;
-  bool profileable_from_shell = false;
-  int64_t version_code = 0;
-  bool profileable = false;
-  std::string installed_by;
-};
-
-bool ReadPackagesListLine(char* line, Package* package);
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_PACKAGES_LIST_PACKAGES_LIST_PARSER_H_
diff --git a/src/traced/probes/packages_list/packages_list_unittest.cc b/src/traced/probes/packages_list/packages_list_unittest.cc
deleted file mode 100644
index acfc791..0000000
--- a/src/traced/probes/packages_list/packages_list_unittest.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.
- */
-
-#include "src/traced/probes/packages_list/packages_list_data_source.h"
-
-#include <stdio.h>
-
-#include <set>
-#include <string>
-
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/android/packages_list.gen.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-#include "src/traced/probes/packages_list/packages_list_parser.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-TEST(PackagesListDataSourceTest, ParseLineNonProfileNonDebug) {
-  char kLine[] =
-      "com.test.app 1234 0 /data/user/0/com.test.app "
-      "default:targetSdkVersion=12452 1234,5678 0 1111\n";
-  Package pkg;
-  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
-  EXPECT_EQ(pkg.name, "com.test.app");
-  EXPECT_EQ(pkg.debuggable, false);
-  EXPECT_EQ(pkg.profileable_from_shell, false);
-  EXPECT_EQ(pkg.version_code, 1111);
-}
-
-TEST(PackagesListDataSourceTest, ParseLineProfileNonDebug) {
-  char kLine[] =
-      "com.test.app 1234 0 /data/user/0/com.test.app "
-      "default:targetSdkVersion=12452 1234,5678 1 1111\n";
-  Package pkg;
-  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
-  EXPECT_EQ(pkg.name, "com.test.app");
-  EXPECT_EQ(pkg.debuggable, false);
-  EXPECT_EQ(pkg.profileable_from_shell, true);
-  EXPECT_EQ(pkg.version_code, 1111);
-}
-
-TEST(PackagesListDataSourceTest, ParseLineNonProfileDebug) {
-  char kLine[] =
-      "com.test.app 1234 1 /data/user/0/com.test.app "
-      "default:targetSdkVersion=12452 1234,5678 0 1111\n";
-  Package pkg;
-  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
-  EXPECT_EQ(pkg.name, "com.test.app");
-  EXPECT_EQ(pkg.debuggable, true);
-  EXPECT_EQ(pkg.profileable_from_shell, false);
-  EXPECT_EQ(pkg.version_code, 1111);
-}
-
-TEST(PackagesListDataSourceTest, ParseLineProfileDebug) {
-  char kLine[] =
-      "com.test.app 1234 1 /data/user/0/com.test.app "
-      "default:targetSdkVersion=12452 1234,5678 1 1111\n";
-  Package pkg;
-  ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
-  EXPECT_EQ(pkg.name, "com.test.app");
-  EXPECT_EQ(pkg.debuggable, true);
-  EXPECT_EQ(pkg.profileable_from_shell, true);
-  EXPECT_EQ(pkg.version_code, 1111);
-}
-
-TEST(PackagesListDataSourceTest, EmptyNameFilterIncludesAll) {
-  char buf[] =
-      "com.test.one 1000 0 /data/user/0/com.test.one "
-      "default:targetSdkVersion=10 none 0 10\n"
-      "com.test.two 1001 0 /data/user/0/com.test.two "
-      "default:targetSdkVersion=10 1065,3002 0 20\n"
-      "com.test.three 1002 0 /data/user/0/com.test.three "
-      "default:targetSdkVersion=10 1065,3002 0 30\n";
-
-  // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
-  // requires a higher target API (23) than we use for portability.
-  auto pipe = base::Pipe::Create();
-  PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
-  pipe.wr.reset();
-  auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
-  pipe.rd.release();  // now owned by |fs|
-
-  protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
-  std::set<std::string> filter{};
-
-  ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
-
-  protos::gen::PackagesList parsed_list;
-  parsed_list.ParseFromString(packages_list.SerializeAsString());
-
-  EXPECT_FALSE(parsed_list.read_error());
-  EXPECT_FALSE(parsed_list.parse_error());
-  // all entries
-  EXPECT_EQ(parsed_list.packages_size(), 3);
-  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
-  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
-  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.two");
-  EXPECT_EQ(parsed_list.packages()[1].version_code(), 20);
-  EXPECT_EQ(parsed_list.packages()[2].name(), "com.test.three");
-  EXPECT_EQ(parsed_list.packages()[2].version_code(), 30);
-}
-
-TEST(PackagesListDataSourceTest, NameFilter) {
-  char buf[] =
-      "com.test.one 1000 0 /data/user/0/com.test.one "
-      "default:targetSdkVersion=10 none 0 10\n"
-      "com.test.two 1001 0 /data/user/0/com.test.two "
-      "default:targetSdkVersion=10 1065,3002 0 20\n"
-      "com.test.three 1002 0 /data/user/0/com.test.three "
-      "default:targetSdkVersion=10 1065,3002 0 30\n";
-
-  // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
-  // requires a higher target API (23) than we use for portability.
-  auto pipe = base::Pipe::Create();
-  PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
-  pipe.wr.reset();
-  auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
-  pipe.rd.release();  // now owned by |fs|
-
-  protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
-  std::set<std::string> filter{"com.test.one", "com.test.three"};
-
-  ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
-
-  protos::gen::PackagesList parsed_list;
-  parsed_list.ParseFromString(packages_list.SerializeAsString());
-
-  EXPECT_FALSE(parsed_list.read_error());
-  EXPECT_FALSE(parsed_list.parse_error());
-  // two named entries
-  EXPECT_EQ(parsed_list.packages_size(), 2);
-  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
-  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
-  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.three");
-  EXPECT_EQ(parsed_list.packages()[1].version_code(), 30);
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/traced/probes/power/BUILD.gn b/src/traced/probes/power/BUILD.gn
index fc28f67..7b75c6a 100644
--- a/src/traced/probes/power/BUILD.gn
+++ b/src/traced/probes/power/BUILD.gn
@@ -18,7 +18,6 @@
     "..:data_source",
     "../../../../gn:default_deps",
     "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/common:zero",
     "../../../../protos/perfetto/config/power:zero",
     "../../../../protos/perfetto/trace:zero",
     "../../../../protos/perfetto/trace/power:zero",
diff --git a/src/traced/probes/power/android_power_data_source.cc b/src/traced/probes/power/android_power_data_source.cc
index 1dccb1a..0b4e749 100644
--- a/src/traced/probes/power/android_power_data_source.cc
+++ b/src/traced/probes/power/android_power_data_source.cc
@@ -28,11 +28,9 @@
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/android_internal/health_hal.h"
 #include "src/android_internal/lazy_library_loader.h"
-#include "src/android_internal/power_stats.h"
+#include "src/android_internal/power_stats_hal.h"
 
-#include "protos/perfetto/common/android_energy_consumer_descriptor.pbzero.h"
 #include "protos/perfetto/config/power/android_power_config.pbzero.h"
-#include "protos/perfetto/trace/power/android_energy_estimation_breakdown.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"
@@ -41,10 +39,7 @@
 
 namespace {
 constexpr uint32_t kMinPollIntervalMs = 100;
-constexpr uint32_t kDefaultPollIntervalMs = 1000;
 constexpr size_t kMaxNumRails = 32;
-constexpr size_t kMaxNumEnergyConsumer = 32;
-constexpr size_t kMaxNumPowerEntities = 256;
 }  // namespace
 
 // static
@@ -60,9 +55,6 @@
   PERFETTO_LAZY_LOAD(android_internal::GetAvailableRails, get_available_rails_);
   PERFETTO_LAZY_LOAD(android_internal::GetRailEnergyData,
                      get_rail_energy_data_);
-  PERFETTO_LAZY_LOAD(android_internal::GetEnergyConsumerInfo,
-                     get_energy_consumer_info_);
-  PERFETTO_LAZY_LOAD(android_internal::GetEnergyConsumed, get_energy_consumed_);
 
   base::Optional<int64_t> GetCounter(android_internal::BatteryCounter counter) {
     if (!get_battery_counter_)
@@ -80,10 +72,7 @@
     std::vector<android_internal::RailDescriptor> rail_descriptors(
         kMaxNumRails);
     size_t num_rails = rail_descriptors.size();
-    if (!get_available_rails_(&rail_descriptors[0], &num_rails)) {
-      PERFETTO_ELOG("Failed to retrieve rail descriptors.");
-      num_rails = 0;
-    }
+    get_available_rails_(&rail_descriptors[0], &num_rails);
     rail_descriptors.resize(num_rails);
     return rail_descriptors;
   }
@@ -94,43 +83,10 @@
 
     std::vector<android_internal::RailEnergyData> energy_data(kMaxNumRails);
     size_t num_rails = energy_data.size();
-    if (!get_rail_energy_data_(&energy_data[0], &num_rails)) {
-      PERFETTO_ELOG("Failed to retrieve rail energy data.");
-      num_rails = 0;
-    }
+    get_rail_energy_data_(&energy_data[0], &num_rails);
     energy_data.resize(num_rails);
     return energy_data;
   }
-
-  std::vector<android_internal::EnergyConsumerInfo> GetEnergyConsumerInfo() {
-    if (!get_energy_consumer_info_)
-      return std::vector<android_internal::EnergyConsumerInfo>();
-
-    std::vector<android_internal::EnergyConsumerInfo> consumers(
-        kMaxNumEnergyConsumer);
-    size_t num_power_entities = consumers.size();
-    if (!get_energy_consumer_info_(&consumers[0], &num_power_entities)) {
-      PERFETTO_ELOG("Failed to retrieve energy consumer info.");
-      num_power_entities = 0;
-    }
-    consumers.resize(num_power_entities);
-    return consumers;
-  }
-
-  std::vector<android_internal::EnergyEstimationBreakdown> GetEnergyConsumed() {
-    if (!get_energy_consumed_)
-      return std::vector<android_internal::EnergyEstimationBreakdown>();
-
-    std::vector<android_internal::EnergyEstimationBreakdown> energy_breakdown(
-        kMaxNumPowerEntities);
-    size_t num_power_entities = energy_breakdown.size();
-    if (!get_energy_consumed_(&energy_breakdown[0], &num_power_entities)) {
-      PERFETTO_ELOG("Failed to retrieve energy estimation breakdown.");
-      num_power_entities = 0;
-    }
-    energy_breakdown.resize(num_power_entities);
-    return energy_breakdown;
-  }
 };
 
 AndroidPowerDataSource::AndroidPowerDataSource(
@@ -141,18 +97,12 @@
     : ProbesDataSource(session_id, &descriptor),
       task_runner_(task_runner),
       rail_descriptors_logged_(false),
-      energy_consumer_loggged_(false),
       writer_(std::move(writer)),
       weak_factory_(this) {
   using protos::pbzero::AndroidPowerConfig;
   AndroidPowerConfig::Decoder pcfg(cfg.android_power_config_raw());
   poll_interval_ms_ = pcfg.battery_poll_ms();
   rails_collection_enabled_ = pcfg.collect_power_rails();
-  energy_breakdown_collection_enabled_ =
-      pcfg.collect_energy_estimation_breakdown();
-
-  if (poll_interval_ms_ == 0)
-    poll_interval_ms_ = kDefaultPollIntervalMs;
 
   if (poll_interval_ms_ < kMinPollIntervalMs) {
     PERFETTO_ELOG("Battery poll interval of %" PRIu32
@@ -199,11 +149,10 @@
         if (weak_this)
           weak_this->Tick();
       },
-      poll_interval_ms_ - static_cast<uint32_t>(now_ms % poll_interval_ms_));
+      poll_interval_ms_ - (now_ms % poll_interval_ms_));
 
   WriteBatteryCounters();
   WritePowerRailsData();
-  WriteEnergyEstimationBreakdown();
 }
 
 void AndroidPowerDataSource::WriteBatteryCounters() {
@@ -259,7 +208,7 @@
     // all rail names etc. on each one.
     rail_descriptors_logged_ = true;
     auto rail_descriptors = lib_->GetRailDescriptors();
-    if (rail_descriptors.empty()) {
+    if (rail_descriptors.size() == 0) {
       // No rails to collect data for. Don't try again in the next iteration.
       rails_collection_enabled_ = false;
       return;
@@ -282,55 +231,6 @@
   }
 }
 
-void AndroidPowerDataSource::WriteEnergyEstimationBreakdown() {
-  if (!energy_breakdown_collection_enabled_)
-    return;
-  auto timestamp = static_cast<uint64_t>(base::GetBootTimeNs().count());
-
-  TraceWriter::TracePacketHandle packet;
-  protos::pbzero::AndroidEnergyEstimationBreakdown* energy_estimation_proto =
-      nullptr;
-
-  if (!energy_consumer_loggged_) {
-    energy_consumer_loggged_ = true;
-    packet = writer_->NewTracePacket();
-    energy_estimation_proto = packet->set_android_energy_estimation_breakdown();
-    auto* descriptor_proto =
-        energy_estimation_proto->set_energy_consumer_descriptor();
-    auto consumers = lib_->GetEnergyConsumerInfo();
-    for (const auto& consumer : consumers) {
-      auto* desc_proto = descriptor_proto->add_energy_consumers();
-      desc_proto->set_energy_consumer_id(consumer.energy_consumer_id);
-      desc_proto->set_ordinal(consumer.ordinal);
-      desc_proto->set_type(consumer.type);
-      desc_proto->set_name(consumer.name);
-    }
-  }
-
-  auto energy_breakdowns = lib_->GetEnergyConsumed();
-  for (const auto& breakdown : energy_breakdowns) {
-    if (breakdown.uid == android_internal::ALL_UIDS_FOR_CONSUMER) {
-      // Finalize packet before calling NewTracePacket.
-      if (packet) {
-        packet->Finalize();
-      }
-      packet = writer_->NewTracePacket();
-      packet->set_timestamp(timestamp);
-      energy_estimation_proto =
-          packet->set_android_energy_estimation_breakdown();
-      energy_estimation_proto->set_energy_consumer_id(
-          breakdown.energy_consumer_id);
-      energy_estimation_proto->set_energy_uws(breakdown.energy_uws);
-    } else {
-      PERFETTO_CHECK(energy_estimation_proto != nullptr);
-      auto* uid_breakdown_proto =
-          energy_estimation_proto->add_per_uid_breakdown();
-      uid_breakdown_proto->set_uid(breakdown.uid);
-      uid_breakdown_proto->set_energy_uws(breakdown.energy_uws);
-    }
-  }
-}
-
 void AndroidPowerDataSource::Flush(FlushRequestID,
                                    std::function<void()> callback) {
   writer_->Flush(callback);
diff --git a/src/traced/probes/power/android_power_data_source.h b/src/traced/probes/power/android_power_data_source.h
index 4fecfda..0977d11 100644
--- a/src/traced/probes/power/android_power_data_source.h
+++ b/src/traced/probes/power/android_power_data_source.h
@@ -55,15 +55,12 @@
   void Tick();
   void WriteBatteryCounters();
   void WritePowerRailsData();
-  void WriteEnergyEstimationBreakdown();
 
   base::TaskRunner* const task_runner_;
   uint32_t poll_interval_ms_ = 0;
   std::bitset<8> counters_enabled_;
   bool rails_collection_enabled_;
   bool rail_descriptors_logged_;
-  bool energy_consumer_loggged_;
-  bool energy_breakdown_collection_enabled_;
   std::unique_ptr<TraceWriter> writer_;
   std::unique_ptr<DynamicLibLoader> lib_;
   base::WeakPtrFactory<AndroidPowerDataSource> weak_factory_;  // Keep last.
diff --git a/src/traced/probes/probes.cc b/src/traced/probes/probes.cc
index b02b6d5..b05fd02 100644
--- a/src/traced/probes/probes.cc
+++ b/src/traced/probes/probes.cc
@@ -15,63 +15,56 @@
  */
 
 #include <fcntl.h>
+#include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/version.h"
 #include "perfetto/ext/traced/traced.h"
 #include "perfetto/ext/tracing/ipc/default_socket.h"
 
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "src/traced/probes/kmem_activity_trigger.h"
 #include "src/traced/probes/probes_producer.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
+#include "perfetto_version.gen.h"
+#else
+#define PERFETTO_GET_GIT_REVISION() "unknown"
+#endif
+
 namespace perfetto {
 
-int PERFETTO_EXPORT_ENTRYPOINT ProbesMain(int argc, char** argv) {
+int __attribute__((visibility("default"))) ProbesMain(int argc, char** argv) {
   enum LongOption {
     OPT_CLEANUP_AFTER_CRASH = 1000,
     OPT_VERSION,
-    OPT_BACKGROUND,
   };
 
-  bool background = false;
-
-  static const option long_options[] = {
-      {"background", no_argument, nullptr, OPT_BACKGROUND},
+  static const struct option long_options[] = {
       {"cleanup-after-crash", no_argument, nullptr, OPT_CLEANUP_AFTER_CRASH},
       {"version", no_argument, nullptr, OPT_VERSION},
       {nullptr, 0, nullptr, 0}};
 
+  int option_index;
   for (;;) {
-    int option = getopt_long(argc, argv, "", long_options, nullptr);
+    int option = getopt_long(argc, argv, "", long_options, &option_index);
     if (option == -1)
       break;
     switch (option) {
-      case OPT_BACKGROUND:
-        background = true;
-        break;
       case OPT_CLEANUP_AFTER_CRASH:
         HardResetFtraceState();
         return 0;
       case OPT_VERSION:
-        printf("%s\n", base::GetVersionString());
+        printf("%s\n", PERFETTO_GET_GIT_REVISION());
         return 0;
       default:
-        PERFETTO_ELOG("Usage: %s [--background|--cleanup-after-crash|--version]", argv[0]);
+        PERFETTO_ELOG("Usage: %s [--cleanup-after-crash|--version]", argv[0]);
         return 1;
     }
   }
 
-  if (background) {
-    base::Daemonize();
-  }
-
   base::Watchdog* watchdog = base::Watchdog::GetInstance();
   // The memory watchdog will be updated soon after connect, once the shmem
   // buffer size is known, in ProbesProducer::OnTracingSetup().
@@ -98,12 +91,6 @@
   base::UnixTaskRunner task_runner;
   ProbesProducer producer;
   producer.ConnectWithRetries(GetProducerSocket(), &task_runner);
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  // Start the thread that polls mm_event instance and triggers
-  KmemActivityTrigger kmem_activity_trigger;
-#endif
-
   task_runner.Run();
   return 0;
 }
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index 9907a73..69072c7 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -33,7 +33,6 @@
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/trace_config.h"
-#include "src/android_stats/statsd_logging_helper.h"
 #include "src/traced/probes/android_log/android_log_data_source.h"
 #include "src/traced/probes/common/cpu_freq_info.h"
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
@@ -87,19 +86,8 @@
 //                    +--------------+
 //
 
-ProbesProducer* ProbesProducer::instance_ = nullptr;
-
-ProbesProducer* ProbesProducer::GetInstance() {
-  return instance_;
-}
-
-ProbesProducer::ProbesProducer() : weak_factory_(this) {
-  PERFETTO_CHECK(instance_ == nullptr);
-  instance_ = this;
-}
-
+ProbesProducer::ProbesProducer() : weak_factory_(this) {}
 ProbesProducer::~ProbesProducer() {
-  instance_ = nullptr;
   // The ftrace data sources must be deleted before the ftrace controller.
   data_sources_.clear();
   ftrace_.reset();
@@ -141,6 +129,7 @@
   // 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
   // recreating it again.
+  // TODO(hjd): Add e2e test for this.
 
   base::TaskRunner* task_runner = task_runner_;
   const char* socket_name = socket_name_;
@@ -505,7 +494,7 @@
       if (ps->on_demand_dumps_enabled())
         ps_data_source = ps;
     }
-  }  // for (session_data_sources_)
+  }    // for (session_data_sources_)
 }
 
 void ProbesProducer::ConnectWithRetries(const char* socket_name,
@@ -538,18 +527,4 @@
   connection_backoff_ms_ = kInitialConnectionBackoffMs;
 }
 
-void ProbesProducer::ActivateTrigger(std::string trigger) {
-  android_stats::MaybeLogTriggerEvent(
-      PerfettoTriggerAtom::kProbesProducerTrigger, trigger);
-
-  task_runner_->PostTask([this, trigger]() {
-    if (!endpoint_) {
-      android_stats::MaybeLogTriggerEvent(
-          PerfettoTriggerAtom::kProbesProducerTriggerFail, trigger);
-      return;
-    }
-    endpoint_->ActivateTriggers({trigger});
-  });
-}
-
 }  // namespace perfetto
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index eb4df63..39d6425 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -44,8 +44,6 @@
   ProbesProducer();
   ~ProbesProducer() override;
 
-  static ProbesProducer* GetInstance();
-
   // Producer Impl:
   void OnConnect() override;
   void OnDisconnect() override;
@@ -80,9 +78,6 @@
   std::unique_ptr<ProbesDataSource> CreateAndroidPowerDataSource(
       TracingSessionID session_id,
       const DataSourceConfig& config);
-  std::unique_ptr<ProbesDataSource> CreateAndroidPowerStatsDataSource(
-      TracingSessionID session_id,
-      const DataSourceConfig& config);
   std::unique_ptr<ProbesDataSource> CreateAndroidLogDataSource(
       TracingSessionID session_id,
       const DataSourceConfig& config);
@@ -98,11 +93,8 @@
   std::unique_ptr<ProbesDataSource> CreateInitialDisplayStateDataSource(
       TracingSessionID session_id,
       const DataSourceConfig& config);
-  void ActivateTrigger(std::string trigger);
 
  private:
-  static ProbesProducer* instance_;
-
   enum State {
     kNotStarted = 0,
     kNotConnected,
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index 9dafa72..6adb342 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -54,13 +54,27 @@
 // was provided in the config. The cache is trimmed if it exceeds this size.
 const size_t kThreadTimeInStateCacheSize = 10000;
 
+inline int32_t ParseIntValue(const char* str) {
+  int32_t ret = 0;
+  for (;;) {
+    char c = *(str++);
+    if (!c)
+      break;
+    if (c < '0' || c > '9')
+      return 0;
+    ret *= 10;
+    ret += static_cast<int32_t>(c - '0');
+  }
+  return ret;
+}
+
 int32_t ReadNextNumericDir(DIR* dirp) {
   while (struct dirent* dir_ent = readdir(dirp)) {
     if (dir_ent->d_type != DT_DIR)
       continue;
-    auto int_value = base::CStringToInt32(dir_ent->d_name);
+    int32_t int_value = ParseIntValue(dir_ent->d_name);
     if (int_value)
-      return *int_value;
+      return int_value;
   }
   return 0;
 }
@@ -369,9 +383,7 @@
     return;
   ProcessStatsDataSource& thiz = *weak_this;
   uint32_t period_ms = thiz.poll_period_ms_;
-  uint32_t delay_ms =
-      period_ms -
-      static_cast<uint32_t>(base::GetWallTimeMs().count() % period_ms);
+  uint32_t delay_ms = period_ms - (base::GetWallTimeMs().count() % period_ms);
   thiz.task_runner_->PostDelayedTask(
       std::bind(&ProcessStatsDataSource::Tick, weak_this), delay_ms);
   thiz.WriteAllProcessStats();
@@ -387,9 +399,9 @@
 }
 
 void ProcessStatsDataSource::WriteAllProcessStats() {
-  // TODO(primiano): implement filtering of processes by names.
+  // TODO(primiano): implement whitelisting of processes by names.
   // TODO(primiano): Have a pid cache to avoid wasting cycles reading kthreads
-  // proc files over and over. Same for non-filtered processes (see above).
+  // proc files over and over. Same for non-whitelist processes (see above).
 
   CacheProcFsScanStartTimestamp();
   PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, PS_WRITE_ALL_PROCESS_STATS);
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 bb123d1..9278e1c 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -18,7 +18,6 @@
 
 #include <dirent.h>
 
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/tracing/core/data_source_config.h"
@@ -394,7 +393,7 @@
 
   // Cleanup |fake_proc|. TempDir checks that the directory is empty.
   for (std::string& path : dirs_to_delete)
-    base::Rmdir(path);
+    rmdir(path.c_str());
 }
 
 TEST_F(ProcessStatsDataSourceTest, CacheProcessStats) {
@@ -462,7 +461,7 @@
   }
 
   // Cleanup |fake_proc|. TempDir checks that the directory is empty.
-  base::Rmdir(path);
+  rmdir(path);
 }
 
 TEST_F(ProcessStatsDataSourceTest, ThreadTimeInState) {
@@ -650,7 +649,7 @@
   EXPECT_THAT(thread.cpu_freq_full(), true);
 
   for (const std::string& path : dirs_to_delete)
-    base::Rmdir(path);
+    rmdir(path.c_str());
 }
 
 }  // namespace
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 3d75ff2..2d939ec 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.cc
@@ -138,21 +138,19 @@
     stat_enabled_fields_ |= 1ul << static_cast<uint32_t>(*counter);
   }
 
-  std::array<uint32_t, 4> periods_ms{};
-  std::array<uint32_t, 4> ticks{};
+  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[3] = ClampTo10Ms(cfg.devfreq_period_ms(), "devfreq_period_ms");
 
   tick_period_ms_ = 0;
   for (uint32_t ms : periods_ms) {
     if (ms && (ms < tick_period_ms_ || tick_period_ms_ == 0))
       tick_period_ms_ = ms;
   }
-
   if (tick_period_ms_ == 0)
     return;  // No polling configured.
 
@@ -167,7 +165,6 @@
   meminfo_ticks_ = ticks[0];
   vmstat_ticks_ = ticks[1];
   stat_ticks_ = ticks[2];
-  devfreq_ticks_ = ticks[3];
 }
 
 void SysStatsDataSource::Start() {
@@ -182,9 +179,7 @@
   SysStatsDataSource& thiz = *weak_this;
 
   uint32_t period_ms = thiz.tick_period_ms_;
-  uint32_t delay_ms =
-      period_ms -
-      static_cast<uint32_t>(base::GetWallTimeMs().count() % period_ms);
+  uint32_t delay_ms = period_ms - (base::GetWallTimeMs().count() % period_ms);
   thiz.task_runner_->PostDelayedTask(
       std::bind(&SysStatsDataSource::Tick, weak_this), delay_ms);
   thiz.ReadSysStats();
@@ -208,61 +203,12 @@
   if (stat_ticks_ && tick_ % stat_ticks_ == 0)
     ReadStat(sys_stats);
 
-  if (devfreq_ticks_ && tick_ % devfreq_ticks_ == 0)
-    ReadDevfreq(sys_stats);
-
   sys_stats->set_collection_end_timestamp(
       static_cast<uint64_t>(base::GetBootTimeNs().count()));
 
   tick_++;
 }
 
-void SysStatsDataSource::ReadDevfreq(protos::pbzero::SysStats* sys_stats) {
-  base::ScopedDir devfreq_dir = OpenDevfreqDir();
-  if (devfreq_dir) {
-    while (struct dirent* dir_ent = readdir(*devfreq_dir)) {
-      // Entries in /sys/class/devfreq are symlinks to /devices/platform
-      if (dir_ent->d_type != DT_LNK)
-        continue;
-      const char* name = dir_ent->d_name;
-      const char* file_content = ReadDevfreqCurFreq(name);
-      auto value = static_cast<uint64_t>(strtoll(file_content, nullptr, 10));
-      auto* devfreq = sys_stats->add_devfreq();
-      devfreq->set_key(name);
-      devfreq->set_value(value);
-    }
-  }
-}
-
-base::ScopedDir SysStatsDataSource::OpenDevfreqDir() {
-  const char* base_dir = "/sys/class/devfreq/";
-  base::ScopedDir devfreq_dir(opendir(base_dir));
-  if (!devfreq_dir && !devfreq_error_logged_) {
-    devfreq_error_logged_ = true;
-    PERFETTO_PLOG("failed to opendir(/sys/class/devfreq)");
-  }
-  return devfreq_dir;
-}
-
-const char* SysStatsDataSource::ReadDevfreqCurFreq(
-    const std::string& deviceName) {
-  const char* devfreq_base_path = "/sys/class/devfreq";
-  const char* freq_file_name = "cur_freq";
-  char cur_freq_path[256];
-  snprintf(cur_freq_path, sizeof(cur_freq_path), "%s/%s/%s", devfreq_base_path,
-           deviceName.c_str(), freq_file_name);
-  base::ScopedFile fd = OpenReadOnly(cur_freq_path);
-  if (!fd && !devfreq_error_logged_) {
-    devfreq_error_logged_ = true;
-    PERFETTO_PLOG("Failed to open %s", cur_freq_path);
-    return "";
-  }
-  size_t rsize = ReadFile(&fd, cur_freq_path);
-  if (!rsize)
-    return "";
-  return static_cast<char*>(read_buf_.Get());
-}
-
 void SysStatsDataSource::ReadMeminfo(protos::pbzero::SysStats* sys_stats) {
   size_t rsize = ReadFile(&meminfo_fd_, "/proc/meminfo");
   if (!rsize)
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 cf47770..df47176 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.h
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.h
@@ -64,10 +64,6 @@
   void set_ns_per_user_hz_for_testing(uint64_t ns) { ns_per_user_hz_ = ns; }
   uint32_t tick_for_testing() const { return tick_; }
 
-  // Virtual for testing
-  virtual base::ScopedDir OpenDevfreqDir();
-  virtual const char* ReadDevfreqCurFreq(const std::string& name);
-
  private:
   struct CStrCmp {
     bool operator()(const char* a, const char* b) const {
@@ -83,7 +79,6 @@
   void ReadMeminfo(protos::pbzero::SysStats* sys_stats);
   void ReadVmstat(protos::pbzero::SysStats* sys_stats);
   void ReadStat(protos::pbzero::SysStats* sys_stats);
-  void ReadDevfreq(protos::pbzero::SysStats* sys_stats);
   size_t ReadFile(base::ScopedFile*, const char* path);
 
   base::TaskRunner* const task_runner_;
@@ -102,8 +97,6 @@
   uint32_t vmstat_ticks_ = 0;
   uint32_t stat_ticks_ = 0;
   uint32_t stat_enabled_fields_ = 0;
-  uint32_t devfreq_ticks_ = 0;
-  bool devfreq_error_logged_ = false;
 
   base::WeakPtrFactory<SysStatsDataSource> weak_factory_;  // Keep last.
 };
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 b239ffa..49af8a4 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,7 +16,6 @@
 
 #include <unistd.h>
 
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
@@ -131,7 +130,6 @@
 pgsteal_kswapd_dma 19471476
 pgsteal_kswapd_normal 21138380
 pgsteal_kswapd_movable 0
-pgsteal_direct 91537
 pgsteal_direct_dma 40625
 pgsteal_direct_normal 50912
 pgsteal_direct_movable 0
@@ -187,26 +185,6 @@
 procs_blocked 0
 softirq 84611084 10220177 28299167 155083 3035679 6390543 66234 4396819 15604187 0 16443195)";
 
-const char kDevfreq1[] = "1000000";
-const char kDevfreq2[] = "20000000";
-
-class TestSysStatsDataSource : public SysStatsDataSource {
- public:
-  TestSysStatsDataSource(base::TaskRunner* task_runner,
-                         TracingSessionID id,
-                         std::unique_ptr<TraceWriter> writer,
-                         const DataSourceConfig& config,
-                         OpenFunction open_fn)
-      : SysStatsDataSource(task_runner,
-                           id,
-                           std::move(writer),
-                           config,
-                           open_fn) {}
-
-  MOCK_METHOD0(OpenDevfreqDir, base::ScopedDir());
-  MOCK_METHOD1(ReadDevfreqCurFreq, const char*(const std::string& deviceName));
-};
-
 base::ScopedFile MockOpenReadOnly(const char* path) {
   base::TempFile tmp_ = base::TempFile::CreateUnlinked();
   if (!strcmp(path, "/proc/meminfo")) {
@@ -223,14 +201,13 @@
 
 class SysStatsDataSourceTest : public ::testing::Test {
  protected:
-  std::unique_ptr<TestSysStatsDataSource> GetSysStatsDataSource(
+  std::unique_ptr<SysStatsDataSource> GetSysStatsDataSource(
       const DataSourceConfig& cfg) {
     auto writer =
         std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
     writer_raw_ = writer.get();
-    auto instance =
-        std::unique_ptr<TestSysStatsDataSource>(new TestSysStatsDataSource(
-            &task_runner_, 0, std::move(writer), cfg, MockOpenReadOnly));
+    auto instance = std::unique_ptr<SysStatsDataSource>(new SysStatsDataSource(
+        &task_runner_, 0, std::move(writer), cfg, MockOpenReadOnly));
     instance->set_ns_per_user_hz_for_testing(1000000000ull / 100);  // 100 Hz.
     instance->Start();
     return instance;
@@ -274,7 +251,6 @@
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_EQ(sys_stats.devfreq_size(), 0);
 
   using KV = std::pair<int, uint64_t>;
   std::vector<KV> kvs;
@@ -303,7 +279,6 @@
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_EQ(sys_stats.devfreq_size(), 0);
   EXPECT_GE(sys_stats.meminfo_size(), 10);
 }
 
@@ -315,7 +290,6 @@
   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);
-  sys_cfg.add_vmstat_counters(C::VMSTAT_PGSTEAL_DIRECT);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
@@ -326,7 +300,6 @@
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_EQ(sys_stats.devfreq_size(), 0);
 
   using KV = std::pair<int, uint64_t>;
   std::vector<KV> kvs;
@@ -335,9 +308,7 @@
 
   EXPECT_THAT(kvs, UnorderedElementsAre(KV{C::VMSTAT_NR_FREE_PAGES, 16449},  //
                                         KV{C::VMSTAT_PGACTIVATE, 11897892},  //
-                                        KV{C::VMSTAT_PGMIGRATE_FAIL, 3439},  //
-                                        KV{C::VMSTAT_PGSTEAL_DIRECT, 91537}  //
-                                        ));
+                                        KV{C::VMSTAT_PGMIGRATE_FAIL, 3439}));
 }
 
 TEST_F(SysStatsDataSourceTest, VmstatAll) {
@@ -354,70 +325,9 @@
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_EQ(sys_stats.devfreq_size(), 0);
   EXPECT_GE(sys_stats.vmstat_size(), 10);
 }
 
-TEST_F(SysStatsDataSourceTest, DevfreqAll) {
-  DataSourceConfig config;
-  protos::gen::SysStatsConfig sys_cfg;
-  sys_cfg.set_devfreq_period_ms(10);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
-
-  // Create dirs and symlinks, but only read the symlinks.
-  std::vector<std::string> dirs_to_delete;
-  std::vector<std::string> symlinks_to_delete;
-  auto make_devfreq_paths = [&symlinks_to_delete, &dirs_to_delete](
-                                base::TempDir& temp_dir, base::TempDir& sym_dir,
-                                const char* name) {
-    char path[256];
-    sprintf(path, "%s/%s", temp_dir.path().c_str(), name);
-    dirs_to_delete.push_back(path);
-    mkdir(path, 0755);
-    char sym_path[256];
-    sprintf(sym_path, "%s/%s", sym_dir.path().c_str(), name);
-    symlinks_to_delete.push_back(sym_path);
-    symlink(path, sym_path);
-  };
-  auto fake_devfreq = base::TempDir::Create();
-  auto fake_devfreq_symdir = base::TempDir::Create();
-  static const char* const devfreq_names[] = {"10010.devfreq_device_a",
-                                              "10020.devfreq_device_b"};
-  for (auto dev : devfreq_names) {
-    make_devfreq_paths(fake_devfreq, fake_devfreq_symdir, dev);
-  }
-
-  EXPECT_CALL(*data_source, OpenDevfreqDir())
-      .WillRepeatedly(Invoke([&fake_devfreq_symdir] {
-        return base::ScopedDir(opendir(fake_devfreq_symdir.path().c_str()));
-      }));
-  EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10010.devfreq_device_a"))
-      .WillRepeatedly(Return(kDevfreq1));
-  EXPECT_CALL(*data_source, ReadDevfreqCurFreq("10020.devfreq_device_b"))
-      .WillRepeatedly(Return(kDevfreq2));
-
-  WaitTick(data_source.get());
-
-  protos::gen::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);
-
-  using KV = std::pair<std::string, uint64_t>;
-  std::vector<KV> kvs;
-  for (const auto& kv : sys_stats.devfreq())
-    kvs.push_back({kv.key(), kv.value()});
-  EXPECT_THAT(kvs,
-              UnorderedElementsAre(KV{"10010.devfreq_device_a", 1000000},
-                                   KV{"10020.devfreq_device_b", 20000000}));
-  for (const std::string& path : dirs_to_delete)
-    base::Rmdir(path);
-  for (const std::string& path : symlinks_to_delete)
-    remove(path.c_str());
-}
-
 TEST_F(SysStatsDataSourceTest, StatAll) {
   DataSourceConfig config;
   protos::gen::SysStatsConfig sys_cfg;
diff --git a/src/traced/service/BUILD.gn b/src/traced/service/BUILD.gn
index 2ff0007..2b7798b 100644
--- a/src/traced/service/BUILD.gn
+++ b/src/traced/service/BUILD.gn
@@ -42,6 +42,9 @@
     "../../tracing/core:service",
     "../../tracing/ipc/service",
   ]
+  if (enable_perfetto_version_gen) {
+    deps += [ "//gn/standalone:gen_git_revision" ]
+  }
   sources = [
     "builtin_producer.cc",
     "builtin_producer.h",
diff --git a/src/traced/service/builtin_producer.cc b/src/traced/service/builtin_producer.cc
index 1e10ed1..8538c00 100644
--- a/src/traced/service/builtin_producer.cc
+++ b/src/traced/service/builtin_producer.cc
@@ -17,11 +17,11 @@
 #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/utils.h"
 #include "perfetto/ext/base/weak_ptr.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
@@ -62,10 +62,10 @@
 
 void BuiltinProducer::ConnectInProcess(TracingService* svc) {
   endpoint_ = svc->ConnectProducer(
-      this, base::GetCurrentUserId(), "traced",
+      this, geteuid(), "traced",
       /*shared_memory_size_hint_bytes=*/16 * 1024, /*in_process=*/true,
       TracingService::ProducerSMBScrapingMode::kDisabled,
-      /*shared_memory_page_size_hint_bytes=*/4096);
+      /*shmem_page_size_hint_bytes=*/4096);
 }
 
 void BuiltinProducer::OnConnect() {
diff --git a/src/traced/service/service.cc b/src/traced/service/service.cc
index 6d9ba8b..4a876f5 100644
--- a/src/traced/service/service.cc
+++ b/src/traced/service/service.cc
@@ -14,141 +14,48 @@
  * limitations under the License.
  */
 
+#include <getopt.h>
 #include <stdio.h>
-#include <algorithm>
 
-#include "perfetto/ext/base/getopt.h"
-#include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/version.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"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#define PERFETTO_SET_SOCKET_PERMISSIONS
-#include <fcntl.h>
-#include <grp.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
+#include "perfetto_version.gen.h"
+#else
+#define PERFETTO_GET_GIT_REVISION() "unknown"
 #endif
 
 namespace perfetto {
-namespace {
-#if defined(PERFETTO_SET_SOCKET_PERMISSIONS)
-void SetSocketPermissions(const std::string& socket_name,
-                          const std::string& group_name,
-                          const std::string& mode_bits) {
-  PERFETTO_CHECK(!socket_name.empty());
-  PERFETTO_CHECK(!group_name.empty());
-  struct group* socket_group = nullptr;
-  // Query the group ID of |group|.
-  do {
-    socket_group = getgrnam(group_name.c_str());
-  } while (socket_group == nullptr && errno == EINTR);
-  if (socket_group == nullptr) {
-    PERFETTO_FATAL("Failed to get group information of %s ",
-                   group_name.c_str());
-  }
 
-  if (PERFETTO_EINTR(
-          chown(socket_name.c_str(), geteuid(), socket_group->gr_gid))) {
-    PERFETTO_FATAL("Failed to chown %s ", socket_name.c_str());
-  }
-
-  // |mode| accepts values like "0660" as "rw-rw----" mode bits.
-  auto mode_value = base::StringToInt32(mode_bits, 8);
-  if (!(mode_bits.size() == 4 && mode_value.has_value())) {
-    PERFETTO_FATAL(
-        "The chmod option must be a 4-digit octal number, e.g. 0660");
-  }
-  if (PERFETTO_EINTR(chmod(socket_name.c_str(),
-                           static_cast<mode_t>(mode_value.value())))) {
-    PERFETTO_FATAL("Failed to chmod %s", socket_name.c_str());
-  }
-}
-#endif  // defined(PERFETTO_SET_SOCKET_PERMISSIONS)
-
-void PrintUsage(const char* prog_name) {
-  PERFETTO_ELOG(R"(
-Usage: %s [option] ...
-Options and arguments
-    --background : Exits immediately and continues running in the background
-    --version : print the version number and exit.
-    --set-socket-permissions <permissions> : sets group ownership and permission
-        mode bits of the producer and consumer sockets.
-        <permissions> format: <prod_group>:<prod_mode>:<cons_group>:<cons_mode>,
-        where <prod_group> is the group name for chgrp the producer socket,
-        <prod_mode> is the mode bits (e.g. 0660) for chmod the produce socket,
-        <cons_group> is the group name for chgrp the consumer socket, and
-        <cons_mode> is the mode bits (e.g. 0660) for chmod the consumer socket.
-Example: %s --set-socket-permissions traced-producer:0660:traced-consumer:0660
-    starts the service and sets the group ownership of the producer and consumer
-    sockets to "traced-producer" and "traced-consumer", respectively. Both
-    producer and consumer sockets are chmod with 0660  (rw-rw----) mode bits.
-)",
-                prog_name, prog_name);
-}
-}  // namespace
-
-int PERFETTO_EXPORT_ENTRYPOINT ServiceMain(int argc, char** argv) {
+int __attribute__((visibility("default"))) ServiceMain(int argc, char** argv) {
   enum LongOption {
     OPT_VERSION = 1000,
-    OPT_SET_SOCKET_PERMISSIONS = 1001,
-    OPT_BACKGROUND,
   };
 
-  bool background = false;
-
-  static const option long_options[] = {
-      {"background", no_argument, nullptr, OPT_BACKGROUND},
+  static const struct option long_options[] = {
       {"version", no_argument, nullptr, OPT_VERSION},
-      {"set-socket-permissions", required_argument, nullptr,
-       OPT_SET_SOCKET_PERMISSIONS},
       {nullptr, 0, nullptr, 0}};
 
-  std::string producer_socket_group, consumer_socket_group,
-      producer_socket_mode, consumer_socket_mode;
-
+  int option_index;
   for (;;) {
-    int option = getopt_long(argc, argv, "", long_options, nullptr);
+    int option = getopt_long(argc, argv, "", long_options, &option_index);
     if (option == -1)
       break;
     switch (option) {
-      case OPT_BACKGROUND:
-        background = true;
-        break;
       case OPT_VERSION:
-        printf("%s\n", base::GetVersionString());
+        printf("%s\n", PERFETTO_GET_GIT_REVISION());
         return 0;
-      case OPT_SET_SOCKET_PERMISSIONS: {
-        // Check that the socket permission argument is well formed.
-        auto parts = base::SplitString(std::string(optarg), ":");
-        PERFETTO_CHECK(parts.size() == 4);
-        PERFETTO_CHECK(
-            std::all_of(parts.cbegin(), parts.cend(),
-                        [](const std::string& part) { return !part.empty(); }));
-        producer_socket_group = parts[0];
-        producer_socket_mode = parts[1];
-        consumer_socket_group = parts[2];
-        consumer_socket_mode = parts[3];
-        break;
-      }
       default:
-        PrintUsage(argv[0]);
+        PERFETTO_ELOG("Usage: %s [--version]", argv[0]);
         return 1;
     }
   }
 
-  if (background) {
-    base::Daemonize();
-  }
-
   base::UnixTaskRunner task_runner;
   std::unique_ptr<ServiceIPCHost> svc;
   svc = ServiceIPCHost::CreateInstance(&task_runner);
@@ -161,30 +68,13 @@
   PERFETTO_CHECK((!env_prod && !env_cons) || (env_prod && env_cons));
   bool started;
   if (env_prod) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    PERFETTO_CHECK(false);
-#else
     base::ScopedFile producer_fd(atoi(env_prod));
     base::ScopedFile consumer_fd(atoi(env_cons));
     started = svc->Start(std::move(producer_fd), std::move(consumer_fd));
-#endif
   } else {
-    remove(GetProducerSocket());
-    remove(GetConsumerSocket());
+    unlink(GetProducerSocket());
+    unlink(GetConsumerSocket());
     started = svc->Start(GetProducerSocket(), GetConsumerSocket());
-
-    if (!producer_socket_group.empty()) {
-#if defined(PERFETTO_SET_SOCKET_PERMISSIONS)
-      SetSocketPermissions(GetProducerSocket(), producer_socket_group,
-                           producer_socket_mode);
-      SetSocketPermissions(GetConsumerSocket(), consumer_socket_group,
-                           consumer_socket_mode);
-#else
-      PERFETTO_ELOG(
-          "Setting socket permissions is not supported on this platform");
-      return 1;
-#endif
-    }
   }
 
   if (!started) {
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 2440d39..a6ea494 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -31,8 +31,6 @@
   ]
   if (enable_perfetto_ipc) {
     public_deps += [ ":system_backend" ]
-  } else {
-    public_deps += [ ":system_backend_fake" ]
   }
 }
 
@@ -51,13 +49,15 @@
 }
 
 # Separate target because the embedder might not want this (e.g. on Windows).
-source_set("platform_impl") {
-  deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/tracing",
-    "../base",
-  ]
-  sources = [ "platform_posix.cc" ]
+if (is_linux || is_mac || is_android) {
+  source_set("platform_posix") {
+    deps = [
+      "../../gn:default_deps",
+      "../../include/perfetto/tracing",
+      "../base",
+    ]
+    sources = [ "platform_posix.cc" ]
+  }
 }
 
 # Fake platform that allows buiding the client lib on all OSes. You can only use
@@ -82,14 +82,12 @@
   sources = [ "trace_writer_base.cc" ]
 }
 
-# Base target for the client API. On its own doesn't provide any backend other
-# than the unsupported one.
+# Base target for the client API. On its own doesn't provide any backend.
 source_set("client_api_without_backends") {
   deps = [
     "../../include/perfetto/tracing/core",
     "../../protos/perfetto/common:zero",
     "../../protos/perfetto/config:cpp",
-    "../../protos/perfetto/config/interceptors:zero",
     "../../protos/perfetto/config/track_event:cpp",
     "../base",
     "core",
@@ -99,28 +97,17 @@
     "../../include/perfetto/tracing",
   ]
   sources = [
-    "console_interceptor.cc",
     "data_source.cc",
     "debug_annotation.cc",
     "event_context.cc",
-    "interceptor.cc",
-    "internal/checked_scope.cc",
-    "internal/interceptor_trace_writer.cc",
-    "internal/tracing_backend_fake.cc",
-    "internal/tracing_muxer_fake.cc",
-    "internal/tracing_muxer_fake.h",
     "internal/tracing_muxer_impl.cc",
     "internal/tracing_muxer_impl.h",
     "internal/track_event_internal.cc",
-    "internal/track_event_interned_fields.cc",
     "platform.cc",
-    "traced_value.cc",
     "tracing.cc",
-    "tracing_policy.cc",
     "track.cc",
     "track_event_category_registry.cc",
     "track_event_legacy.cc",
-    "track_event_state_tracker.cc",
     "virtual_destructors.cc",
   ]
   assert_no_deps = [ "core:service" ]
@@ -132,37 +119,6 @@
   }
 }
 
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    "../../protos/perfetto/trace:lite",
-    "../../protos/perfetto/trace/track_event:lite",
-    "../base",
-    "../base:test_support",
-    "test:test_support",
-  ]
-
-  sources = []
-
-  # TODO(primiano): remove the build_with_chromium conditional once the root
-  # //BUILD.gn:libperfetto (in chromium) stops adding tracing:platform_fake.
-  # The problem is the following: in chrome builds we end up with duplicate
-  # symbol definitions in the test because both platorm (impl and fake) are
-  # present: impl added here and fake coming from chromium's base (full path:
-  # perfetto_unittests -> //(chromium)base:test_support -> //(chromium)base
-  # -> libperfetto -> platform_fake.
-  if (!build_with_chromium) {
-    deps += [
-      ":client_api_without_backends",
-      ":platform_impl",
-    ]
-    sources += [
-      "traced_proto_unittest.cc",
-      "traced_value_unittest.cc",
-    ]
-  }
-}
-
 # System backend: connects to an external "traced" instance via a UNIX socket.
 # Requires the IPC layer and is supported only on posix systems.
 if (enable_perfetto_ipc) {
@@ -179,15 +135,6 @@
     ]
     sources = [ "internal/system_tracing_backend.cc" ]
   }
-} else {
-  source_set("system_backend_fake") {
-    public_deps = [ "../../include/perfetto/tracing" ]
-    deps = [
-      "../../gn:default_deps",
-      "../base",
-    ]
-    sources = [ "internal/system_tracing_backend_fake.cc" ]
-  }
 }
 
 # In-process backend: starts the tracing service in-process on a dedicated
@@ -209,10 +156,10 @@
   source_set("benchmarks") {
     testonly = true
     deps = [
-      ":platform_impl",
+      ":platform_posix",
       "../..:libperfetto_client_experimental",
-      "../../gn:benchmark",
-      "../../gn:default_deps",
+      "../../../../../gn:benchmark",
+      "../../../../../gn:default_deps",
     ]
     sources = [ "api_benchmark.cc" ]
   }
diff --git a/src/tracing/console_interceptor.cc b/src/tracing/console_interceptor.cc
deleted file mode 100644
index 99ce956..0000000
--- a/src/tracing/console_interceptor.cc
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/tracing/console_interceptor.h"
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/tracing/internal/track_event_internal.h"
-
-#include "protos/perfetto/common/interceptor_descriptor.gen.h"
-#include "protos/perfetto/config/data_source_config.gen.h"
-#include "protos/perfetto/config/interceptor_config.gen.h"
-#include "protos/perfetto/config/interceptors/console_config.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.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"
-
-#include <algorithm>
-#include <cmath>
-#include <tuple>
-
-namespace perfetto {
-
-// sRGB color.
-struct ConsoleColor {
-  uint8_t r;
-  uint8_t g;
-  uint8_t b;
-};
-
-namespace {
-
-int g_output_fd_for_testing;
-
-// Google Turbo colormap.
-constexpr std::array<ConsoleColor, 16> kTurboColors = {{
-    ConsoleColor{0x30, 0x12, 0x3b},
-    ConsoleColor{0x40, 0x40, 0xa1},
-    ConsoleColor{0x46, 0x6b, 0xe3},
-    ConsoleColor{0x41, 0x93, 0xfe},
-    ConsoleColor{0x28, 0xbb, 0xeb},
-    ConsoleColor{0x17, 0xdc, 0xc2},
-    ConsoleColor{0x32, 0xf1, 0x97},
-    ConsoleColor{0x6d, 0xfd, 0x62},
-    ConsoleColor{0xa4, 0xfc, 0x3b},
-    ConsoleColor{0xcd, 0xeb, 0x34},
-    ConsoleColor{0xed, 0xcf, 0x39},
-    ConsoleColor{0xfd, 0xab, 0x33},
-    ConsoleColor{0xfa, 0x7d, 0x20},
-    ConsoleColor{0xea, 0x50, 0x0d},
-    ConsoleColor{0xd0, 0x2f, 0x04},
-    ConsoleColor{0xa9, 0x15, 0x01},
-}};
-
-constexpr size_t kHueBits = 4;
-constexpr uint32_t kMaxHue = kTurboColors.size() << kHueBits;
-constexpr uint8_t kLightness = 128u;
-constexpr ConsoleColor kWhiteColor{0xff, 0xff, 0xff};
-
-const char kDim[] = "\x1b[90m";
-const char kDefault[] = "\x1b[39m";
-const char kReset[] = "\x1b[0m";
-
-#define FMT_RGB_SET "\x1b[38;2;%d;%d;%dm"
-#define FMT_RGB_SET_BG "\x1b[48;2;%d;%d;%dm"
-
-ConsoleColor Mix(ConsoleColor a, ConsoleColor b, uint8_t ratio) {
-  return {
-      static_cast<uint8_t>(a.r + (((b.r - a.r) * ratio) >> 8)),
-      static_cast<uint8_t>(a.g + (((b.g - a.g) * ratio) >> 8)),
-      static_cast<uint8_t>(a.b + (((b.b - a.b) * ratio) >> 8)),
-  };
-}
-
-ConsoleColor HueToRGB(uint32_t hue) {
-  PERFETTO_DCHECK(hue < kMaxHue);
-  uint32_t c1 = hue >> kHueBits;
-  uint32_t c2 =
-      std::min(static_cast<uint32_t>(kTurboColors.size() - 1), c1 + 1u);
-  uint32_t ratio = hue & ((1 << kHueBits) - 1);
-  return Mix(kTurboColors[c1], kTurboColors[c2],
-             static_cast<uint8_t>(ratio | (ratio << kHueBits)));
-}
-
-uint32_t CounterToHue(uint32_t counter) {
-  // We split the hue space into 8 segments, reversing the order of bits so
-  // successive counter values will be far from each other.
-  uint32_t reversed =
-      ((counter & 0x7) >> 2) | ((counter & 0x3)) | ((counter & 0x1) << 2);
-  return reversed * kMaxHue / 8;
-}
-
-}  // namespace
-
-class ConsoleInterceptor::Delegate : public TrackEventStateTracker::Delegate {
- public:
-  explicit Delegate(InterceptorContext&);
-  ~Delegate() override;
-
-  TrackEventStateTracker::SessionState* GetSessionState() override;
-  void OnTrackUpdated(TrackEventStateTracker::Track&) override;
-  void OnTrackEvent(const TrackEventStateTracker::Track&,
-                    const TrackEventStateTracker::ParsedTrackEvent&) override;
-
- private:
-  using SelfHandle = LockedHandle<ConsoleInterceptor>;
-
-  InterceptorContext& context_;
-  base::Optional<SelfHandle> locked_self_;
-};
-
-ConsoleInterceptor::~ConsoleInterceptor() = default;
-
-ConsoleInterceptor::ThreadLocalState::ThreadLocalState(
-    ThreadLocalStateArgs& args) {
-  if (auto self = args.GetInterceptorLocked()) {
-    start_time_ns = self->start_time_ns_;
-    use_colors = self->use_colors_;
-    fd = self->fd_;
-  }
-}
-
-ConsoleInterceptor::ThreadLocalState::~ThreadLocalState() = default;
-
-ConsoleInterceptor::Delegate::Delegate(InterceptorContext& context)
-    : context_(context) {}
-ConsoleInterceptor::Delegate::~Delegate() = default;
-
-TrackEventStateTracker::SessionState*
-ConsoleInterceptor::Delegate::GetSessionState() {
-  // When the session state is retrieved for the first time, it is cached (and
-  // kept locked) until we return from OnTracePacket. This avoids having to lock
-  // and unlock the instance multiple times per invocation.
-  if (locked_self_.has_value())
-    return &locked_self_.value()->session_state_;
-  locked_self_ =
-      base::make_optional<SelfHandle>(context_.GetInterceptorLocked());
-  return &locked_self_.value()->session_state_;
-}
-
-void ConsoleInterceptor::Delegate::OnTrackUpdated(
-    TrackEventStateTracker::Track& track) {
-  auto track_color = HueToRGB(CounterToHue(track.index));
-  std::array<char, 16> title;
-  if (!track.name.empty()) {
-    snprintf(title.data(), title.size(), "%s", track.name.c_str());
-  } else if (track.pid && track.tid) {
-    snprintf(title.data(), title.size(), "%u:%u",
-             static_cast<uint32_t>(track.pid),
-             static_cast<uint32_t>(track.tid));
-  } else if (track.pid) {
-    snprintf(title.data(), title.size(), "%" PRId64, track.pid);
-  } else {
-    snprintf(title.data(), title.size(), "%" PRIu64, track.uuid);
-  }
-  int title_width = static_cast<int>(title.size());
-
-  auto& tls = context_.GetThreadLocalState();
-  std::array<char, 128> message_prefix{};
-  ssize_t written = 0;
-  if (tls.use_colors) {
-    written = snprintf(message_prefix.data(), message_prefix.size(),
-                       FMT_RGB_SET_BG " %s%s %-*.*s", track_color.r,
-                       track_color.g, track_color.b, kReset, kDim, title_width,
-                       title_width, title.data());
-  } else {
-    written = snprintf(message_prefix.data(), message_prefix.size(), "%-*.*s",
-                       title_width + 2, title_width, title.data());
-  }
-  if (written < 0)
-    written = message_prefix.size();
-  track.user_data.assign(message_prefix.begin(),
-                         message_prefix.begin() + written);
-}
-
-void ConsoleInterceptor::Delegate::OnTrackEvent(
-    const TrackEventStateTracker::Track& track,
-    const TrackEventStateTracker::ParsedTrackEvent& event) {
-  // Start printing.
-  auto& tls = context_.GetThreadLocalState();
-  tls.buffer_pos = 0;
-
-  // Print timestamp and track identifier.
-  SetColor(context_, kDim);
-  Printf(context_, "[%7.3lf] %.*s",
-         static_cast<double>(event.timestamp_ns - tls.start_time_ns) / 1e9,
-         static_cast<int>(track.user_data.size()), track.user_data.data());
-
-  // Print category.
-  Printf(context_, "%-5.*s ",
-         std::min(5, static_cast<int>(event.category.size)),
-         event.category.data);
-
-  // Print stack depth.
-  for (size_t i = 0; i < event.stack_depth; i++) {
-    Printf(context_, "-  ");
-  }
-
-  // Print slice name.
-  auto slice_color = HueToRGB(event.name_hash % kMaxHue);
-  auto highlight_color = Mix(slice_color, kWhiteColor, kLightness);
-  if (event.track_event.type() == protos::pbzero::TrackEvent::TYPE_SLICE_END) {
-    SetColor(context_, kDefault);
-    Printf(context_, "} ");
-  }
-  SetColor(context_, highlight_color);
-  Printf(context_, "%.*s", static_cast<int>(event.name.size), event.name.data);
-  SetColor(context_, kReset);
-  if (event.track_event.type() ==
-      protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN) {
-    SetColor(context_, kDefault);
-    Printf(context_, " {");
-  }
-
-  // Print annotations.
-  if (event.track_event.has_debug_annotations()) {
-    PrintDebugAnnotations(context_, event.track_event, slice_color,
-                          highlight_color);
-  }
-
-  // TODO(skyostil): Print typed arguments.
-
-  // Print duration for longer events.
-  constexpr uint64_t kNsPerMillisecond = 1000000u;
-  if (event.duration_ns >= 10 * kNsPerMillisecond) {
-    SetColor(context_, kDim);
-    Printf(context_, " +%" PRIu64 "ms", event.duration_ns / kNsPerMillisecond);
-  }
-  SetColor(context_, kReset);
-  Printf(context_, "\n");
-}
-
-// static
-void ConsoleInterceptor::Register() {
-  perfetto::protos::gen::InterceptorDescriptor desc;
-  desc.set_name("console");
-  Interceptor<ConsoleInterceptor>::Register(desc);
-}
-
-// static
-void ConsoleInterceptor::SetOutputFdForTesting(int fd) {
-  g_output_fd_for_testing = fd;
-}
-
-void ConsoleInterceptor::OnSetup(const SetupArgs& args) {
-  int fd = STDOUT_FILENO;
-  if (g_output_fd_for_testing)
-    fd = g_output_fd_for_testing;
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
-  bool use_colors = isatty(fd);
-#else
-  bool use_colors = false;
-#endif
-  protos::pbzero::ConsoleConfig::Decoder config(
-      args.config.interceptor_config().console_config_raw());
-  if (config.has_enable_colors())
-    use_colors = config.enable_colors();
-  if (config.output() == protos::pbzero::ConsoleConfig::OUTPUT_STDOUT) {
-    fd = STDOUT_FILENO;
-  } else if (config.output() == protos::pbzero::ConsoleConfig::OUTPUT_STDERR) {
-    fd = STDERR_FILENO;
-  }
-  fd_ = fd;
-  use_colors_ = use_colors;
-}
-
-void ConsoleInterceptor::OnStart(const StartArgs&) {
-  start_time_ns_ = internal::TrackEventInternal::GetTimeNs();
-}
-
-void ConsoleInterceptor::OnStop(const StopArgs&) {}
-
-// static
-void ConsoleInterceptor::OnTracePacket(InterceptorContext context) {
-  {
-    auto& tls = context.GetThreadLocalState();
-    Delegate delegate(context);
-    perfetto::protos::pbzero::TracePacket::Decoder packet(
-        context.packet_data.data, context.packet_data.size);
-    TrackEventStateTracker::ProcessTracePacket(delegate, tls.sequence_state,
-                                               packet);
-  }  // (Potential) lock scope for session state.
-  Flush(context);
-}
-
-// static
-void ConsoleInterceptor::Printf(InterceptorContext& context,
-                                const char* format,
-                                ...) {
-  auto& tls = context.GetThreadLocalState();
-  ssize_t remaining = static_cast<ssize_t>(tls.message_buffer.size()) -
-                      static_cast<ssize_t>(tls.buffer_pos);
-  int written = 0;
-  if (remaining > 0) {
-    va_list args;
-    va_start(args, format);
-    written = vsnprintf(&tls.message_buffer[tls.buffer_pos],
-                        static_cast<size_t>(remaining), format, args);
-    PERFETTO_DCHECK(written >= 0);
-    va_end(args);
-  }
-
-  // In case of buffer overflow, flush to the fd and write the latest message to
-  // it directly instead.
-  if (remaining <= 0 || written > remaining) {
-    FILE* output = (tls.fd == STDOUT_FILENO) ? stdout : stderr;
-    if (g_output_fd_for_testing) {
-      output = fdopen(dup(g_output_fd_for_testing), "w");
-    }
-    Flush(context);
-    va_list args;
-    va_start(args, format);
-    vfprintf(output, format, args);
-    va_end(args);
-    if (g_output_fd_for_testing) {
-      fclose(output);
-    }
-  } else if (written > 0) {
-    tls.buffer_pos += static_cast<size_t>(written);
-  }
-}
-
-// static
-void ConsoleInterceptor::Flush(InterceptorContext& context) {
-  auto& tls = context.GetThreadLocalState();
-  ssize_t res = base::WriteAll(tls.fd, &tls.message_buffer[0], tls.buffer_pos);
-  PERFETTO_DCHECK(res == static_cast<ssize_t>(tls.buffer_pos));
-  tls.buffer_pos = 0;
-}
-
-// static
-void ConsoleInterceptor::SetColor(InterceptorContext& context,
-                                  const ConsoleColor& color) {
-  auto& tls = context.GetThreadLocalState();
-  if (!tls.use_colors)
-    return;
-  Printf(context, FMT_RGB_SET, color.r, color.g, color.b);
-}
-
-// static
-void ConsoleInterceptor::SetColor(InterceptorContext& context,
-                                  const char* color) {
-  auto& tls = context.GetThreadLocalState();
-  if (!tls.use_colors)
-    return;
-  Printf(context, "%s", color);
-}
-
-// static
-void ConsoleInterceptor::PrintDebugAnnotations(
-    InterceptorContext& context,
-    const protos::pbzero::TrackEvent_Decoder& track_event,
-    const ConsoleColor& slice_color,
-    const ConsoleColor& highlight_color) {
-  SetColor(context, slice_color);
-  Printf(context, "(");
-
-  bool is_first = true;
-  for (auto it = track_event.debug_annotations(); it; it++) {
-    perfetto::protos::pbzero::DebugAnnotation::Decoder annotation(*it);
-    SetColor(context, slice_color);
-    if (!is_first)
-      Printf(context, ", ");
-
-    PrintDebugAnnotationName(context, annotation);
-    Printf(context, ":");
-
-    SetColor(context, highlight_color);
-    PrintDebugAnnotationValue(context, annotation);
-
-    is_first = false;
-  }
-  SetColor(context, slice_color);
-  Printf(context, ")");
-}
-
-// static
-void ConsoleInterceptor::PrintDebugAnnotationName(
-    InterceptorContext& context,
-    const perfetto::protos::pbzero::DebugAnnotation::Decoder& annotation) {
-  auto& tls = context.GetThreadLocalState();
-  protozero::ConstChars name{};
-  if (annotation.name_iid()) {
-    name.data =
-        tls.sequence_state.debug_annotation_names[annotation.name_iid()].data();
-    name.size =
-        tls.sequence_state.debug_annotation_names[annotation.name_iid()].size();
-  } else if (annotation.has_name()) {
-    name.data = annotation.name().data;
-    name.size = annotation.name().size;
-  }
-  Printf(context, "%.*s", static_cast<int>(name.size), name.data);
-}
-
-// static
-void ConsoleInterceptor::PrintDebugAnnotationValue(
-    InterceptorContext& context,
-    const perfetto::protos::pbzero::DebugAnnotation::Decoder& annotation) {
-  if (annotation.has_bool_value()) {
-    Printf(context, "%s", annotation.bool_value() ? "true" : "false");
-  } else if (annotation.has_uint_value()) {
-    Printf(context, "%" PRIu64, annotation.uint_value());
-  } else if (annotation.has_int_value()) {
-    Printf(context, "%" PRId64, annotation.int_value());
-  } else if (annotation.has_double_value()) {
-    Printf(context, "%f", annotation.double_value());
-  } else if (annotation.has_string_value()) {
-    Printf(context, "%.*s", static_cast<int>(annotation.string_value().size),
-           annotation.string_value().data);
-  } else if (annotation.has_pointer_value()) {
-    Printf(context, "%p", reinterpret_cast<void*>(annotation.pointer_value()));
-  } else if (annotation.has_legacy_json_value()) {
-    Printf(context, "%.*s",
-           static_cast<int>(annotation.legacy_json_value().size),
-           annotation.legacy_json_value().data);
-  } else if (annotation.has_dict_entries()) {
-    Printf(context, "{");
-    bool is_first = true;
-    for (auto it = annotation.dict_entries(); it; ++it) {
-      if (!is_first)
-        Printf(context, ", ");
-      perfetto::protos::pbzero::DebugAnnotation::Decoder key_value(*it);
-      PrintDebugAnnotationName(context, key_value);
-      Printf(context, ":");
-      PrintDebugAnnotationValue(context, key_value);
-      is_first = false;
-    }
-    Printf(context, "}");
-  } else if (annotation.has_array_values()) {
-    Printf(context, "[");
-    bool is_first = true;
-    for (auto it = annotation.array_values(); it; ++it) {
-      if (!is_first)
-        Printf(context, ", ");
-      perfetto::protos::pbzero::DebugAnnotation::Decoder key_value(*it);
-      PrintDebugAnnotationValue(context, key_value);
-      is_first = false;
-    }
-    Printf(context, "]");
-  } else {
-    Printf(context, "{}");
-  }
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc b/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
index 6d901d8..8ef2660 100644
--- a/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
+++ b/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
@@ -87,7 +87,7 @@
   // perfetto::Consumer implementation.
   void OnConnect() override;
   void OnDisconnect() override;
-  void OnTracingDisabled(const std::string& error) override;
+  void OnTracingDisabled() override;
   void OnTraceData(std::vector<TracePacket>, bool has_more) override;
   void OnDetach(bool) override;
   void OnAttach(bool, const TraceConfig&) override;
@@ -198,9 +198,9 @@
   consumer_endpoint_->StartTracing();
 }
 
-void TracingSession::OnTracingDisabled(const std::string& error) {
+void TracingSession::OnTracingDisabled() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("OnTracingDisabled %s", error.c_str());
+  PERFETTO_DLOG("OnTracingDisabled");
 
   struct stat stat_buf {};
   int res = fstat(buf_fd_.get(), &stat_buf);
@@ -287,11 +287,11 @@
   void ThreadMain();  // Called on |task_runner_| thread.
 
   std::mutex mutex_;
+  std::thread thread_;
   std::unique_ptr<base::UnixTaskRunner> task_runner_;
   std::condition_variable task_runner_initialized_;
   Handle last_handle_ = 0;
   std::map<Handle, std::unique_ptr<TracingSession>> sessions_;
-  std::thread thread_;  // Keep last.
 };
 
 TracingController* TracingController::GetInstance() {
@@ -299,9 +299,9 @@
   return instance;
 }
 
-TracingController::TracingController() {
+TracingController::TracingController()
+    : thread_(&TracingController::ThreadMain, this) {
   std::unique_lock<std::mutex> lock(mutex_);
-  thread_ = std::thread(&TracingController::ThreadMain, this);
   task_runner_initialized_.wait(lock, [this] { return !!task_runner_; });
 }
 
diff --git a/src/tracing/core/BUILD.gn b/src/tracing/core/BUILD.gn
index c81c716..141d250 100644
--- a/src/tracing/core/BUILD.gn
+++ b/src/tracing/core/BUILD.gn
@@ -59,9 +59,7 @@
     "../../../protos/perfetto/config:zero",
     "../../../protos/perfetto/trace:zero",
     "../../../protos/perfetto/trace/perfetto:zero",  # For MetatraceWriter.
-    "../../android_stats",
     "../../base",
-    "../../protozero/filtering:message_filter",
   ]
   sources = [
     "metatrace_writer.cc",
@@ -73,12 +71,6 @@
     "tracing_service_impl.cc",
     "tracing_service_impl.h",
   ]
-  if (is_android && perfetto_build_with_android) {
-    deps += [
-      "../../android_internal:headers",
-      "../../android_internal:lazy_library_loader",
-    ]
-  }
 }
 
 perfetto_unittest_source_set("unittests") {
@@ -137,8 +129,8 @@
     deps = [
       ":core",
       ":service",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
+      "../../../../../gn:benchmark",
+      "../../../../../gn:default_deps",
       "../../../protos/perfetto/trace:zero",
       "../../../protos/perfetto/trace/ftrace:zero",
       "../../protozero",
@@ -151,6 +143,6 @@
   sources = [ "packet_stream_validator_fuzzer.cc" ]
   deps = [
     ":service",
-    "../../../gn:default_deps",
+    "../../../../../gn:default_deps",
   ]
 }
diff --git a/src/tracing/core/id_allocator.cc b/src/tracing/core/id_allocator.cc
index 4b32473..588e917 100644
--- a/src/tracing/core/id_allocator.cc
+++ b/src/tracing/core/id_allocator.cc
@@ -56,12 +56,4 @@
   ids_[id] = false;
 }
 
-bool IdAllocatorGeneric::IsEmpty() const {
-  for (const auto id : ids_) {
-    if (id)
-      return false;
-  }
-  return true;
-}
-
 }  // namespace perfetto
diff --git a/src/tracing/core/id_allocator.h b/src/tracing/core/id_allocator.h
index c19d843..7f912c3 100644
--- a/src/tracing/core/id_allocator.h
+++ b/src/tracing/core/id_allocator.h
@@ -39,8 +39,6 @@
   uint32_t AllocateGeneric();
   void FreeGeneric(uint32_t);
 
-  bool IsEmpty() const;
-
  private:
   IdAllocatorGeneric(const IdAllocatorGeneric&) = delete;
   IdAllocatorGeneric& operator=(const IdAllocatorGeneric&) = delete;
diff --git a/src/tracing/core/null_trace_writer.cc b/src/tracing/core/null_trace_writer.cc
index 3e7af89..40fe9a5 100644
--- a/src/tracing/core/null_trace_writer.cc
+++ b/src/tracing/core/null_trace_writer.cc
@@ -18,14 +18,16 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/utils.h"
+
 #include "perfetto/protozero/message.h"
 
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
-NullTraceWriter::NullTraceWriter() : delegate_(4096), stream_(&delegate_) {
-  cur_packet_.reset(new protozero::RootMessage<protos::pbzero::TracePacket>());
+NullTraceWriter::NullTraceWriter()
+    : delegate_(base::kPageSize), stream_(&delegate_) {
+  cur_packet_.reset(new protos::pbzero::TracePacket());
   cur_packet_->Finalize();  // To avoid the DCHECK in NewTracePacket().
 }
 
diff --git a/src/tracing/core/null_trace_writer.h b/src/tracing/core/null_trace_writer.h
index 4f6c707..fabbca7 100644
--- a/src/tracing/core/null_trace_writer.h
+++ b/src/tracing/core/null_trace_writer.h
@@ -19,7 +19,6 @@
 
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/root_message.h"
 #include "perfetto/protozero/scattered_stream_null_delegate.h"
 
 namespace perfetto {
@@ -48,8 +47,7 @@
 
   // The packet returned via NewTracePacket(). Its owned by this class,
   // TracePacketHandle has just a pointer to it.
-  std::unique_ptr<protozero::RootMessage<protos::pbzero::TracePacket>>
-      cur_packet_;
+  std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
 };
 
 }  // namespace perfetto
diff --git a/src/tracing/core/null_trace_writer_unittest.cc b/src/tracing/core/null_trace_writer_unittest.cc
index dfc3f47..03374da 100644
--- a/src/tracing/core/null_trace_writer_unittest.cc
+++ b/src/tracing/core/null_trace_writer_unittest.cc
@@ -33,7 +33,7 @@
 
 TEST(NullTraceWriterTest, Writing) {
   NullTraceWriter writer;
-  for (size_t i = 0; i < 10000; i++) {
+  for (size_t i = 0; i < 3 * base::kPageSize; i++) {
     auto packet = writer.NewTracePacket();
     packet->set_for_testing()->set_str("Hello, world!");
   }
diff --git a/src/tracing/core/packet_stream_validator.cc b/src/tracing/core/packet_stream_validator.cc
index 72a20f5..3d2d846 100644
--- a/src/tracing/core/packet_stream_validator.cc
+++ b/src/tracing/core/packet_stream_validator.cc
@@ -72,11 +72,8 @@
     varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
     if (octet & 0x80) {
       varint_shift_ += 7;
-      if (varint_shift_ >= 64) {
-        // Do not invoke UB on next call.
-        varint_shift_ = 0;
+      if (varint_shift_ >= 64)
         state_ = kInvalidVarInt;
-      }
       return 0;
     }
     uint64_t varint = varint_;
diff --git a/src/tracing/core/shared_memory_abi.cc b/src/tracing/core/shared_memory_abi.cc
index 9461848..75b9713 100644
--- a/src/tracing/core/shared_memory_abi.cc
+++ b/src/tracing/core/shared_memory_abi.cc
@@ -73,7 +73,6 @@
 constexpr uint32_t SharedMemoryABI::kNumChunksForLayout[];
 constexpr const char* SharedMemoryABI::kChunkStateStr[];
 constexpr const size_t SharedMemoryABI::kInvalidPageIdx;
-constexpr const size_t SharedMemoryABI::kMinPageSize;
 constexpr const size_t SharedMemoryABI::kMaxPageSize;
 constexpr const size_t SharedMemoryABI::kPacketSizeDropPacket;
 
@@ -124,7 +123,7 @@
   static_assert((kAllChunksComplete & kChunkMask) == kChunkComplete,
                 "kAllChunksComplete out of sync with kChunkComplete");
 
-  // Check the consistency of the kMax... constants.
+  // Sanity check the consistency of the kMax... constants.
   static_assert(sizeof(ChunkHeader::writer_id) == sizeof(WriterID),
                 "WriterID size");
   ChunkHeader chunk_header{};
@@ -134,10 +133,10 @@
   chunk_header.writer_id.store(static_cast<uint16_t>(-1));
   PERFETTO_CHECK(kMaxWriterID <= chunk_header.writer_id.load());
 
-  PERFETTO_CHECK(page_size >= kMinPageSize);
+  PERFETTO_CHECK(page_size >= base::kPageSize);
   PERFETTO_CHECK(page_size <= kMaxPageSize);
-  PERFETTO_CHECK(page_size % kMinPageSize == 0);
-  PERFETTO_CHECK(reinterpret_cast<uintptr_t>(start) % kMinPageSize == 0);
+  PERFETTO_CHECK(page_size % base::kPageSize == 0);
+  PERFETTO_CHECK(reinterpret_cast<uintptr_t>(start) % base::kPageSize == 0);
   PERFETTO_CHECK(size % page_size == 0);
 }
 
diff --git a/src/tracing/core/shared_memory_abi_unittest.cc b/src/tracing/core/shared_memory_abi_unittest.cc
index 7069cd7..aed8893 100644
--- a/src/tracing/core/shared_memory_abi_unittest.cc
+++ b/src/tracing/core/shared_memory_abi_unittest.cc
@@ -107,7 +107,7 @@
       ASSERT_EQ(SharedMemoryABI::kChunkBeingWritten,
                 abi.GetChunkState(page_idx, chunk_idx));
 
-      // Check chunk bounds.
+      // Sanity check chunk bounds.
       size_t expected_chunk_size =
           (page_size() - sizeof(SharedMemoryABI::PageHeader)) / num_chunks;
       expected_chunk_size = expected_chunk_size - (expected_chunk_size % 4);
@@ -142,14 +142,6 @@
           chunk.header()->packets.load().flags &
           SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
 
-      // Test clearing the needs patching flag.
-      chunk.SetFlag(SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-      ASSERT_TRUE(chunk.header()->packets.load().flags &
-                  SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-      chunk.ClearNeedsPatchingFlag();
-      ASSERT_FALSE(chunk.header()->packets.load().flags &
-                   SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-
       // Reacquiring the same chunk should fail.
       ASSERT_FALSE(abi.TryAcquireChunkForWriting(page_idx, chunk_idx, &header)
                        .is_valid());
diff --git a/src/tracing/core/shared_memory_arbiter_impl.cc b/src/tracing/core/shared_memory_arbiter_impl.cc
index 39ddd4b..c19c96a 100644
--- a/src/tracing/core/shared_memory_arbiter_impl.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl.cc
@@ -249,9 +249,7 @@
     MaybeUnboundBufferID target_buffer,
     PatchList* patch_list) {
   // Note: chunk will be invalid if the call came from SendPatches().
-  base::TaskRunner* task_runner_to_post_delayed_callback_on = nullptr;
-  // The delay with which the flush will be posted.
-  uint32_t flush_delay_ms = 0;
+  base::TaskRunner* task_runner_to_post_callback_on = nullptr;
   base::WeakPtr<SharedMemoryArbiterImpl> weak_this;
   {
     std::lock_guard<std::mutex> scoped_lock(lock_);
@@ -261,11 +259,9 @@
 
       // Flushing the commit is only supported while we're |fully_bound_|. If we
       // aren't, we'll flush when |fully_bound_| is updated.
-      if (fully_bound_ && !delayed_flush_scheduled_) {
+      if (fully_bound_) {
         weak_this = weak_ptr_factory_.GetWeakPtr();
-        task_runner_to_post_delayed_callback_on = task_runner_;
-        flush_delay_ms = batch_commits_duration_ms_;
-        delayed_flush_scheduled_ = true;
+        task_runner_to_post_callback_on = task_runner_;
       }
     }
 
@@ -274,31 +270,10 @@
       PERFETTO_DCHECK(chunk.writer_id() == writer_id);
       uint8_t chunk_idx = chunk.chunk_idx();
       bytes_pending_commit_ += chunk.size();
-      size_t page_idx;
-      // If the chunk needs patching, it should not be marked as complete yet,
-      // because this would indicate to the service that the producer will not
-      // be writing to it anymore, while the producer might still apply patches
-      // to the chunk later on. In particular, when re-reading (e.g. because of
-      // periodic scraping) a completed chunk, the service expects the flags of
-      // that chunk not to be removed between reads. So, let's say the producer
-      // marked the chunk as complete here and the service then read it for the
-      // first time. If the producer then fully patched the chunk, thus removing
-      // the kChunkNeedsPatching flag, and the service re-read the chunk after
-      // the patching, the service would be thrown off by the removed flag.
-      if (direct_patching_enabled_ &&
-          (chunk.GetPacketCountAndFlags().second &
-           SharedMemoryABI::ChunkHeader::kChunkNeedsPatching)) {
-        page_idx = shmem_abi_.GetPageAndChunkIndex(std::move(chunk)).first;
-      } else {
-        // If the chunk doesn't need patching, we can mark it as complete
-        // immediately. This allows the service to read it in full while
-        // scraping, which would not be the case if the chunk was left in a
-        // kChunkBeingWritten state.
-        page_idx = shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
-      }
+      size_t page_idx = shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
 
-      // DO NOT access |chunk| after this point, it has been std::move()-d
-      // above.
+      // DO NOT access |chunk| after this point, has been std::move()-d above.
+
       CommitDataRequest::ChunksToMove* ctm =
           commit_data_req_->add_chunks_to_move();
       ctm->set_page(static_cast<uint32_t>(page_idx));
@@ -306,174 +281,45 @@
       ctm->set_target_buffer(target_buffer);
     }
 
-    // Process the completed patches for previous chunks from the |patch_list|.
-    CommitDataRequest::ChunkToPatch* last_patch_req = nullptr;
+    // Get the completed patches for previous chunks from the |patch_list|
+    // and attach them.
+    ChunkID last_chunk_id = 0;  // 0 is irrelevant but keeps the compiler happy.
+    CommitDataRequest::ChunkToPatch* last_chunk_req = nullptr;
     while (!patch_list->empty() && patch_list->front().is_patched()) {
-      Patch curr_patch = patch_list->front();
+      if (!last_chunk_req || last_chunk_id != patch_list->front().chunk_id) {
+        last_chunk_req = commit_data_req_->add_chunks_to_patch();
+        last_chunk_req->set_writer_id(writer_id);
+        last_chunk_id = patch_list->front().chunk_id;
+        last_chunk_req->set_chunk_id(last_chunk_id);
+        last_chunk_req->set_target_buffer(target_buffer);
+      }
+      auto* patch_req = last_chunk_req->add_patches();
+      patch_req->set_offset(patch_list->front().offset);
+      patch_req->set_data(&patch_list->front().size_field[0],
+                          patch_list->front().size_field.size());
       patch_list->pop_front();
-      // Patches for the same chunk are contiguous in the |patch_list|. So, to
-      // determine if there are any other patches that apply to the chunk that
-      // is being patched, check if the next patch in the |patch_list| applies
-      // to the same chunk.
-      bool chunk_needs_more_patching =
-          !patch_list->empty() &&
-          patch_list->front().chunk_id == curr_patch.chunk_id;
-
-      if (direct_patching_enabled_ &&
-          TryDirectPatchLocked(writer_id, curr_patch,
-                               chunk_needs_more_patching)) {
-        continue;
-      }
-
-      // The chunk that this patch applies to has already been released to the
-      // service, so it cannot be patches here. Add the patch to the commit data
-      // request, so that it can be sent to the service and applied there.
-      if (!last_patch_req ||
-          last_patch_req->chunk_id() != curr_patch.chunk_id) {
-        last_patch_req = commit_data_req_->add_chunks_to_patch();
-        last_patch_req->set_writer_id(writer_id);
-        last_patch_req->set_chunk_id(curr_patch.chunk_id);
-        last_patch_req->set_target_buffer(target_buffer);
-      }
-      auto* patch = last_patch_req->add_patches();
-      patch->set_offset(curr_patch.offset);
-      patch->set_data(&curr_patch.size_field[0], curr_patch.size_field.size());
     }
-
     // Patches are enqueued in the |patch_list| in order and are notified to
     // the service when the chunk is returned. The only case when the current
     // patch list is incomplete is if there is an unpatched entry at the head of
     // the |patch_list| that belongs to the same ChunkID as the last one we are
     // about to send to the service.
-    if (last_patch_req && !patch_list->empty() &&
-        patch_list->front().chunk_id == last_patch_req->chunk_id()) {
-      last_patch_req->set_has_more_patches(true);
-    }
-
-    // If the buffer is filling up or if we are given a patch for a chunk
-    // that was already sent to the service, we don't want to wait for the next
-    // delayed flush to happen and we flush immediately. Otherwise, if we
-    // accumulate the patch and a crash occurs before the patch is sent, the
-    // service will not know of the patch and won't be able to reconstruct the
-    // trace.
-    if (fully_bound_ &&
-        (last_patch_req || bytes_pending_commit_ >= shmem_abi_.size() / 2)) {
-      weak_this = weak_ptr_factory_.GetWeakPtr();
-      task_runner_to_post_delayed_callback_on = task_runner_;
-      flush_delay_ms = 0;
+    if (last_chunk_req && !patch_list->empty() &&
+        patch_list->front().chunk_id == last_chunk_id) {
+      last_chunk_req->set_has_more_patches(true);
     }
   }  // scoped_lock(lock_)
 
-  // We shouldn't post tasks while locked.
-  // |task_runner_to_post_delayed_callback_on| remains valid after unlocking,
-  // because |task_runner_| is never reset.
-  if (task_runner_to_post_delayed_callback_on) {
-    task_runner_to_post_delayed_callback_on->PostDelayedTask(
-        [weak_this] {
-          if (!weak_this)
-            return;
-          {
-            std::lock_guard<std::mutex> scoped_lock(weak_this->lock_);
-            // Clear |delayed_flush_scheduled_|, allowing the next call to
-            // UpdateCommitDataRequest to start another batching period.
-            weak_this->delayed_flush_scheduled_ = false;
-          }
-          weak_this->FlushPendingCommitDataRequests();
-        },
-        flush_delay_ms);
+  // We shouldn't post tasks while locked. |task_runner_to_post_callback_on|
+  // remains valid after unlocking, because |task_runner_| is never reset.
+  if (task_runner_to_post_callback_on) {
+    task_runner_to_post_callback_on->PostTask([weak_this] {
+      if (weak_this)
+        weak_this->FlushPendingCommitDataRequests();
+    });
   }
 }
 
-bool SharedMemoryArbiterImpl::TryDirectPatchLocked(
-    WriterID writer_id,
-    const Patch& patch,
-    bool chunk_needs_more_patching) {
-  // Search the chunks that are being batched in |commit_data_req_| for a chunk
-  // that needs patching and that matches the provided |writer_id| and
-  // |patch.chunk_id|. Iterate |commit_data_req_| in reverse, since
-  // |commit_data_req_| is appended to at the end with newly-returned chunks,
-  // and patches are more likely to apply to chunks that have been returned
-  // recently.
-  SharedMemoryABI::Chunk chunk;
-  bool chunk_found = false;
-  auto& chunks_to_move = commit_data_req_->chunks_to_move();
-  for (auto ctm_it = chunks_to_move.rbegin(); ctm_it != chunks_to_move.rend();
-       ++ctm_it) {
-    uint32_t layout = shmem_abi_.GetPageLayout(ctm_it->page());
-    auto chunk_state =
-        shmem_abi_.GetChunkStateFromLayout(layout, ctm_it->chunk());
-    // Note: the subset of |commit_data_req_| chunks that still need patching is
-    // also the subset of chunks that are still being written to. The rest of
-    // the chunks in |commit_data_req_| do not need patching and have already
-    // been marked as complete.
-    if (chunk_state != SharedMemoryABI::kChunkBeingWritten)
-      continue;
-
-    chunk =
-        shmem_abi_.GetChunkUnchecked(ctm_it->page(), layout, ctm_it->chunk());
-    if (chunk.writer_id() == writer_id &&
-        chunk.header()->chunk_id.load(std::memory_order_relaxed) ==
-            patch.chunk_id) {
-      chunk_found = true;
-      break;
-    }
-  }
-
-  if (!chunk_found) {
-    // The chunk has already been committed to the service and the patch cannot
-    // be applied in the producer.
-    return false;
-  }
-
-  // Apply the patch.
-  size_t page_idx;
-  uint8_t chunk_idx;
-  std::tie(page_idx, chunk_idx) = shmem_abi_.GetPageAndChunkIndex(chunk);
-  PERFETTO_DCHECK(shmem_abi_.GetChunkState(page_idx, chunk_idx) ==
-                  SharedMemoryABI::ChunkState::kChunkBeingWritten);
-  auto chunk_begin = chunk.payload_begin();
-  uint8_t* ptr = chunk_begin + patch.offset;
-  PERFETTO_CHECK(ptr <= chunk.end() - SharedMemoryABI::kPacketHeaderSize);
-  // DCHECK that we are writing into a zero-filled size field and not into
-  // valid data. It relies on ScatteredStreamWriter::ReserveBytes() to
-  // zero-fill reservations in debug builds.
-  const char zero[SharedMemoryABI::kPacketHeaderSize]{};
-  PERFETTO_DCHECK(memcmp(ptr, &zero, SharedMemoryABI::kPacketHeaderSize) == 0);
-
-  memcpy(ptr, &patch.size_field[0], SharedMemoryABI::kPacketHeaderSize);
-
-  if (!chunk_needs_more_patching) {
-    // Mark that the chunk doesn't need more patching and mark it as complete,
-    // as the producer will not write to it anymore. This allows the service to
-    // read the chunk in full while scraping, which would not be the case if the
-    // chunk was left in a kChunkBeingWritten state.
-    chunk.ClearNeedsPatchingFlag();
-    shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
-  }
-
-  return true;
-}
-
-void SharedMemoryArbiterImpl::SetBatchCommitsDuration(
-    uint32_t batch_commits_duration_ms) {
-  std::lock_guard<std::mutex> scoped_lock(lock_);
-  batch_commits_duration_ms_ = batch_commits_duration_ms;
-}
-
-bool SharedMemoryArbiterImpl::EnableDirectSMBPatching() {
-  std::lock_guard<std::mutex> scoped_lock(lock_);
-  if (!direct_patching_supported_by_service_) {
-    return false;
-  }
-
-  return direct_patching_enabled_ = true;
-}
-
-void SharedMemoryArbiterImpl::SetDirectSMBPatchingSupportedByService() {
-  std::lock_guard<std::mutex> scoped_lock(lock_);
-  direct_patching_supported_by_service_ = true;
-}
-
 // This function is quite subtle. When making changes keep in mind these two
 // challenges:
 // 1) If the producer stalls and we happen to be on the |task_runner_| IPC
@@ -524,27 +370,6 @@
       // should have been replaced.
       PERFETTO_DCHECK(all_placeholders_replaced);
 
-      // In order to allow patching in the producer we delay the kChunkComplete
-      // transition and keep batched chunks in the kChunkBeingWritten state.
-      // Since we are about to notify the service of all batched chunks, it will
-      // not be possible to apply any more patches to them and we need to move
-      // them to kChunkComplete - otherwise the service won't look at them.
-      for (auto& ctm : commit_data_req_->chunks_to_move()) {
-        uint32_t layout = shmem_abi_.GetPageLayout(ctm.page());
-        auto chunk_state =
-            shmem_abi_.GetChunkStateFromLayout(layout, ctm.chunk());
-        // Note: the subset of |commit_data_req_| chunks that still need
-        // patching is also the subset of chunks that are still being written
-        // to. The rest of the chunks in |commit_data_req_| do not need patching
-        // and have already been marked as complete.
-        if (chunk_state != SharedMemoryABI::kChunkBeingWritten)
-          continue;
-
-        SharedMemoryABI::Chunk chunk =
-            shmem_abi_.GetChunkUnchecked(ctm.page(), layout, ctm.chunk());
-        shmem_abi_.ReleaseChunkAsComplete(std::move(chunk));
-      }
-
       req = std::move(commit_data_req_);
       bytes_pending_commit_ = 0;
     }
@@ -561,13 +386,6 @@
   }
 }
 
-bool SharedMemoryArbiterImpl::TryShutdown() {
-  std::lock_guard<std::mutex> scoped_lock(lock_);
-  did_shutdown_ = true;
-  // Shutdown is safe if there are no active trace writers for this arbiter.
-  return active_writer_ids_.IsEmpty();
-}
-
 std::unique_ptr<TraceWriter> SharedMemoryArbiterImpl::CreateTraceWriter(
     BufferID target_buffer,
     BufferExhaustedPolicy buffer_exhausted_policy) {
@@ -791,10 +609,8 @@
 
   {
     std::lock_guard<std::mutex> scoped_lock(lock_);
-    if (did_shutdown_)
-      return std::unique_ptr<TraceWriter>(new NullTraceWriter());
-
     id = active_writer_ids_.Allocate();
+
     if (!id)
       return std::unique_ptr<TraceWriter>(new NullTraceWriter());
 
diff --git a/src/tracing/core/shared_memory_arbiter_impl.h b/src/tracing/core/shared_memory_arbiter_impl.h
index 3f679c4..766059c 100644
--- a/src/tracing/core/shared_memory_arbiter_impl.h
+++ b/src/tracing/core/shared_memory_arbiter_impl.h
@@ -35,7 +35,6 @@
 namespace perfetto {
 
 class PatchList;
-class Patch;
 class TraceWriter;
 class TraceWriterImpl;
 
@@ -127,6 +126,10 @@
                    MaybeUnboundBufferID target_buffer,
                    PatchList* patch_list);
 
+  // Forces a synchronous commit of the completed packets without waiting for
+  // the next task.
+  void FlushPendingCommitDataRequests(std::function<void()> callback = {});
+
   SharedMemoryABI* shmem_abi_for_testing() { return &shmem_abi_; }
 
   static void set_default_layout_for_testing(SharedMemoryABI::PageLayout l) {
@@ -148,16 +151,6 @@
       uint16_t target_buffer_reservation_id) override;
   void NotifyFlushComplete(FlushRequestID) override;
 
-  void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms) override;
-
-  bool EnableDirectSMBPatching() override;
-
-  void SetDirectSMBPatchingSupportedByService() override;
-
-  void FlushPendingCommitDataRequests(
-      std::function<void()> callback = {}) override;
-  bool TryShutdown() 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(); }
@@ -190,18 +183,6 @@
                                MaybeUnboundBufferID target_buffer,
                                PatchList* patch_list);
 
-  // Search the chunks that are being batched in |commit_data_req_| for a chunk
-  // that needs patching and that matches the provided |writer_id| and
-  // |patch.chunk_id|. If found, apply |patch| to that chunk, and if
-  // |chunk_needs_more_patching| is true, clear the needs patching flag of the
-  // chunk and mark it as complete - to allow the service to read it (and other
-  // chunks after it) during scraping. Returns true if the patch was applied,
-  // false otherwise.
-  //
-  // Note: the caller must be holding |lock_| for the duration of the call.
-  bool TryDirectPatchLocked(WriterID writer_id,
-                            const Patch& patch,
-                            bool chunk_needs_more_patching);
   std::unique_ptr<TraceWriter> CreateTraceWriterInternal(
       MaybeUnboundBufferID target_buffer,
       BufferExhaustedPolicy);
@@ -228,7 +209,6 @@
   bool UpdateFullyBoundLocked();
 
   const bool initially_bound_;
-
   // Only accessed on |task_runner_| after the producer endpoint was bound.
   TracingService::ProducerEndpoint* producer_endpoint_ = nullptr;
 
@@ -242,7 +222,6 @@
   std::unique_ptr<CommitDataRequest> commit_data_req_;
   size_t bytes_pending_commit_ = 0;  // SUM(chunk.size() : commit_data_req_).
   IdAllocator<WriterID> active_writer_ids_;
-  bool did_shutdown_ = false;
 
   // Whether the arbiter itself and all startup target buffer reservations are
   // bound. Note that this can become false again later if a new target buffer
@@ -259,24 +238,6 @@
   // reservation was unbound.
   std::vector<std::function<void()>> pending_flush_callbacks_;
 
-  // See SharedMemoryArbiter::SetBatchCommitsDuration.
-  uint32_t batch_commits_duration_ms_ = 0;
-
-  // See SharedMemoryArbiter::EnableDirectSMBPatching.
-  bool direct_patching_enabled_ = false;
-
-  // See SharedMemoryArbiter::SetDirectSMBPatchingSupportedByService.
-  bool direct_patching_supported_by_service_ = false;
-
-  // Indicates whether we have already scheduled a delayed flush for the
-  // purposes of batching. Set to true at the beginning of a batching period and
-  // cleared at the end of the period. Immediate flushes that happen during a
-  // batching period will empty the |commit_data_req| (triggering an immediate
-  // IPC to the service), but will not clear this flag and the
-  // previously-scheduled delayed flush will still occur at the end of the
-  // batching period.
-  bool delayed_flush_scheduled_ = false;
-
   // Stores target buffer reservations for writers created via
   // CreateStartupTraceWriter(). A bound reservation sets
   // TargetBufferReservation::resolved to true and is associated with the actual
diff --git a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
index 2b6da0a..0326bcb 100644
--- a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
@@ -35,9 +35,8 @@
 
 namespace perfetto {
 
-using testing::_;
 using testing::Invoke;
-using testing::Mock;
+using testing::_;
 
 class MockProducerEndpoint : public TracingService::ProducerEndpoint {
  public:
@@ -147,83 +146,6 @@
   task_runner_->RunUntilCheckpoint("on_commit_2");
 }
 
-TEST_P(SharedMemoryArbiterImplTest, BatchCommits) {
-  SharedMemoryArbiterImpl::set_default_layout_for_testing(
-      SharedMemoryABI::PageLayout::kPageDiv1);
-
-  // Batching period is 0s - chunks are being committed as soon as they are
-  // returned.
-  SharedMemoryABI::Chunk chunk =
-      arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDefault);
-  ASSERT_TRUE(chunk.is_valid());
-  EXPECT_CALL(mock_producer_endpoint_, CommitData(_, _)).Times(1);
-  PatchList ignored;
-  arbiter_->ReturnCompletedChunk(std::move(chunk), 0, &ignored);
-  task_runner_->RunUntilIdle();
-  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&mock_producer_endpoint_));
-
-  // Since we cannot explicitly control the passage of time in task_runner_, to
-  // simulate a non-zero batching period and a commit at the end of it, set the
-  // batching duration to a very large value and call
-  // FlushPendingCommitDataRequests to manually trigger the commit.
-  arbiter_->SetDirectSMBPatchingSupportedByService();
-  ASSERT_TRUE(arbiter_->EnableDirectSMBPatching());
-  arbiter_->SetBatchCommitsDuration(UINT32_MAX);
-
-  // First chunk that will be batched. CommitData should not be called
-  // immediately this time.
-  chunk = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDefault);
-  ASSERT_TRUE(chunk.is_valid());
-  EXPECT_CALL(mock_producer_endpoint_, CommitData(_, _)).Times(0);
-  // We'll pretend that the chunk needs patching. This is done in order to
-  // verify that chunks that need patching are not marked as complete (i.e. they
-  // are kept in state kChunkBeingWritten) before the batching period ends - in
-  // case a patch for them arrives during the batching period.
-  chunk.SetFlag(SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-  arbiter_->ReturnCompletedChunk(std::move(chunk), 1, &ignored);
-  task_runner_->RunUntilIdle();
-  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&mock_producer_endpoint_));
-  ASSERT_EQ(SharedMemoryABI::kChunkBeingWritten,
-            arbiter_->shmem_abi_for_testing()->GetChunkState(1u, 0u));
-
-  // Add a second chunk to the batch. This should also not trigger an immediate
-  // call to CommitData.
-  chunk = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDefault);
-  ASSERT_TRUE(chunk.is_valid());
-  EXPECT_CALL(mock_producer_endpoint_, CommitData(_, _)).Times(0);
-  arbiter_->ReturnCompletedChunk(std::move(chunk), 2, &ignored);
-  task_runner_->RunUntilIdle();
-  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&mock_producer_endpoint_));
-  // This chunk does not need patching, so it should be marked as complete even
-  // before the end of the batching period - to allow the service to read it in
-  // full.
-  ASSERT_EQ(SharedMemoryABI::kChunkComplete,
-            arbiter_->shmem_abi_for_testing()->GetChunkState(2u, 0u));
-
-  // Make sure that CommitData gets called once (should happen at the end
-  // of the batching period), with the two chunks in the batch.
-  EXPECT_CALL(mock_producer_endpoint_, CommitData(_, _))
-      .WillOnce(Invoke([](const CommitDataRequest& req,
-                          MockProducerEndpoint::CommitDataCallback) {
-        ASSERT_EQ(2, req.chunks_to_move_size());
-
-        // Verify that this is the first chunk that we expect to have been
-        // batched.
-        ASSERT_EQ(1u, req.chunks_to_move()[0].page());
-        ASSERT_EQ(0u, req.chunks_to_move()[0].chunk());
-        ASSERT_EQ(1u, req.chunks_to_move()[0].target_buffer());
-
-        // Verify that this is the second chunk that we expect to have been
-        // batched.
-        ASSERT_EQ(2u, req.chunks_to_move()[1].page());
-        ASSERT_EQ(0u, req.chunks_to_move()[1].chunk());
-        ASSERT_EQ(2u, req.chunks_to_move()[1].target_buffer());
-      }));
-
-  // Pretend we've reached the end of the batching period.
-  arbiter_->FlushPendingCommitDataRequests();
-}
-
 // Helper for verifying trace writer id allocations.
 class TraceWriterIdChecker : public FakeProducerEndpoint {
  public:
@@ -290,22 +212,6 @@
   EXPECT_TRUE(id_checking_endpoint.unregistered_ids_.all());
 }
 
-TEST_P(SharedMemoryArbiterImplTest, Shutdown) {
-  std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(1);
-  EXPECT_TRUE(writer);
-  EXPECT_FALSE(arbiter_->TryShutdown());
-
-  // We still get a valid trace writer after shutdown, but it's a null one
-  // that's not connected to the arbiter.
-  std::unique_ptr<TraceWriter> writer2 = arbiter_->CreateTraceWriter(2);
-  EXPECT_TRUE(writer2);
-  EXPECT_EQ(writer2->writer_id(), 0);
-
-  // Shutdown will succeed once the only non-null writer goes away.
-  writer.reset();
-  EXPECT_TRUE(arbiter_->TryShutdown());
-}
-
 // Verify that getting a new chunk doesn't stall when kDrop policy is chosen.
 TEST_P(SharedMemoryArbiterImplTest, BufferExhaustedPolicyDrop) {
   // Grab all chunks in the SMB.
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index ce6fa34..2227870 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -84,8 +84,9 @@
 
 bool TraceBuffer::Initialize(size_t size) {
   static_assert(
-      SharedMemoryABI::kMinPageSize % sizeof(ChunkRecord) == 0,
+      base::kPageSize % sizeof(ChunkRecord) == 0,
       "sizeof(ChunkRecord) must be an integer divider of a page size");
+  PERFETTO_CHECK(size % base::kPageSize == 0);
   data_ = base::PagedMemory::Allocate(
       size, base::PagedMemory::kMayFail | base::PagedMemory::kDontCommit);
   if (!data_.IsValid()) {
@@ -120,7 +121,7 @@
       base::AlignUp<sizeof(ChunkRecord)>(size + sizeof(ChunkRecord));
   if (PERFETTO_UNLIKELY(record_size > max_chunk_size_)) {
     stats_.set_abi_violations(stats_.abi_violations() + 1);
-    PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+    PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
     return;
   }
 
@@ -171,18 +172,7 @@
                           prev->num_fragments > num_fragments ||
                           (prev->flags & chunk_flags) != prev->flags)) {
       stats_.set_abi_violations(stats_.abi_violations() + 1);
-      PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
-      return;
-    }
-
-    // If this chunk was previously copied with the same number of fragments and
-    // the number didn't change, there's no need to copy it again. If the
-    // previous chunk was complete already, this should always be the case.
-    PERFETTO_DCHECK(suppress_client_dchecks_for_testing_ ||
-                    !record_meta->is_complete() ||
-                    (chunk_complete && prev->num_fragments == num_fragments));
-    if (prev->num_fragments == num_fragments) {
-      TRACE_BUFFER_DLOG("  skipping recommit of identical chunk");
+      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
       return;
     }
 
@@ -199,7 +189,18 @@
     if (subsequent_it != index_.end() &&
         subsequent_it->second.num_fragments_read > 0) {
       stats_.set_abi_violations(stats_.abi_violations() + 1);
-      PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
+      return;
+    }
+
+    // If this chunk was previously copied with the same number of fragments and
+    // the number didn't change, there's no need to copy it again. If the
+    // previous chunk was complete already, this should always be the case.
+    PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_ ||
+                    !record_meta->is_complete() ||
+                    (chunk_complete && prev->num_fragments == num_fragments));
+    if (prev->num_fragments == num_fragments) {
+      TRACE_BUFFER_DLOG("  skipping recommit of identical chunk");
       return;
     }
 
@@ -207,7 +208,7 @@
     if (record_meta->num_fragments_read > prev->num_fragments) {
       PERFETTO_ELOG(
           "TraceBuffer read too many fragments from an incomplete chunk");
-      PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
       return;
     }
 
@@ -825,7 +826,7 @@
     // The producer has a bug or is malicious and did declare that the chunk
     // contains more packets beyond its boundaries.
     stats_.set_abi_violations(stats_.abi_violations() + 1);
-    PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+    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())) {
@@ -855,7 +856,7 @@
     // R).
     if (packet_size != SharedMemoryABI::kPacketSizeDropPacket) {
       stats_.set_abi_violations(stats_.abi_violations() + 1);
-      PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
     } else {
       stats_.set_trace_writer_packet_loss(stats_.trace_writer_packet_loss() +
                                           1);
@@ -883,7 +884,7 @@
     // We have at least one more packet to parse. It should be within the chunk.
     if (chunk_meta->cur_fragment_offset + sizeof(ChunkRecord) >=
         chunk_meta->chunk_record->size) {
-      PERFETTO_DCHECK(suppress_client_dchecks_for_testing_);
+      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
     }
   }
 
diff --git a/src/tracing/core/trace_buffer.h b/src/tracing/core/trace_buffer.h
index 5196623..a95c2f6 100644
--- a/src/tracing/core/trace_buffer.h
+++ b/src/tracing/core/trace_buffer.h
@@ -204,14 +204,6 @@
   // batch of patches for the chunk or there is more.
   // If |other_patches_pending| == false, the chunk is marked as ready to be
   // consumed. If true, the state of the chunk is not altered.
-  //
-  // Note: If the producer is batching commits (see shared_memory_arbiter.h), it
-  // will also attempt to do patching locally. Namely, if nested messages are
-  // completed while the chunk on which they started is being batched (i.e.
-  // before it has been committed to the service), the producer will apply the
-  // respective patches to the batched chunk. These patches will not be sent to
-  // the service - i.e. only the patches that the producer did not manage to
-  // apply before committing the chunk will be applied here.
   bool TryPatchChunkContents(ProducerID,
                              WriterID,
                              ChunkID,
@@ -657,7 +649,7 @@
   // When true disable some DCHECKs that have been put in place to detect
   // bugs in the producers. This is for tests that feed malicious inputs and
   // hence mimic a buggy producer.
-  bool suppress_client_dchecks_for_testing_ = false;
+  bool suppress_sanity_dchecks_for_testing_ = false;
 };
 
 }  // namespace perfetto
diff --git a/src/tracing/core/trace_buffer_unittest.cc b/src/tracing/core/trace_buffer_unittest.cc
index a7bf27a..f7012a5 100644
--- a/src/tracing/core/trace_buffer_unittest.cc
+++ b/src/tracing/core/trace_buffer_unittest.cc
@@ -124,8 +124,8 @@
         trace_buffer_->index_.lower_bound(key));
   }
 
-  void SuppressClientDchecksForTesting() {
-    trace_buffer_->suppress_client_dchecks_for_testing_ = true;
+  void SuppressSanityDchecksForTesting() {
+    trace_buffer_->suppress_sanity_dchecks_for_testing_ = true;
   }
 
   std::vector<ChunkMetaKey> GetIndex() {
@@ -978,7 +978,7 @@
 
 TEST_F(TraceBufferTest, Malicious_ZeroSizedChunk) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(32, 'a')
       .CopyIntoTraceBuffer();
@@ -1002,7 +1002,7 @@
 // in a no-op.
 TEST_F(TraceBufferTest, Malicious_ChunkTooBig) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(4096, 'a')
       .AddPacket(2048, 'b')
@@ -1013,7 +1013,7 @@
 
 TEST_F(TraceBufferTest, Malicious_DeclareMorePacketsBeyondBoundaries) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(64, 'a')
       .IncrementNumPackets()
@@ -1034,7 +1034,7 @@
 
 TEST_F(TraceBufferTest, Malicious_ZeroVarintHeader) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   // Create a standalone chunk where the varint header is == 0.
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(4, 'a')
@@ -1054,7 +1054,7 @@
 // end of the buffer).
 TEST_F(TraceBufferTest, Malicious_OverflowingVarintHeader) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(4079, 'a')  // 4079 := 4096 - sizeof(ChunkRecord) - 1
       .AddPacket({0x82})  // 0x8*: that the varint continues on the next byte.
@@ -1067,7 +1067,7 @@
 
 TEST_F(TraceBufferTest, Malicious_VarintHeaderTooBig) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
 
   // Add a valid chunk.
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
@@ -1108,7 +1108,7 @@
 // contains an enormous varint number that tries to overflow.
 TEST_F(TraceBufferTest, Malicious_JumboVarint) {
   ResetBuffer(64 * 1024);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
 
   std::vector<uint8_t> chunk;
   chunk.insert(chunk.end(), 64 * 1024 - sizeof(ChunkRecord) * 2, 0xff);
@@ -1128,7 +1128,7 @@
 // skipped.
 TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderInSequence) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(4, 'a', kContOnNextChunk)
       .CopyIntoTraceBuffer();
@@ -1161,7 +1161,7 @@
 // zero-sized fragment should be skipped.
 TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderAtEndOfChunk) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(4, 'a')
       .AddPacket(4, 'b', kContOnNextChunk)
@@ -1206,7 +1206,7 @@
 
 TEST_F(TraceBufferTest, Malicious_OverrideWithShorterChunkSize) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(2048, 'a')
       .CopyIntoTraceBuffer();
@@ -1222,7 +1222,7 @@
 
 TEST_F(TraceBufferTest, Malicious_OverrideWithShorterChunkSizeAfterRead) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
 
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(30, 'a')
@@ -1256,7 +1256,7 @@
 
 TEST_F(TraceBufferTest, Malicious_OverrideWithDifferentOffsetAfterRead) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
 
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(30, 'a')
@@ -1433,7 +1433,7 @@
 
   // Overriding a complete packet here would trigger a DCHECK because the packet
   // was already marked as complete.
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(20, 'a')
       .AddPacket(30, 'b')
@@ -1450,7 +1450,7 @@
 // See also the Malicious_Override* tests above.
 TEST_F(TraceBufferTest, Override_ReCommitInvalid) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(20, 'a')
       .AddPacket(30, 'b')
@@ -1738,7 +1738,7 @@
 
 TEST_F(TraceBufferTest, MissingPacketsOnSequence) {
   ResetBuffer(4096);
-  SuppressClientDchecksForTesting();
+  SuppressSanityDchecksForTesting();
   CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
       .AddPacket(10, 'a')
       .AddPacket(10, 'b')
diff --git a/src/tracing/core/trace_writer_for_testing.cc b/src/tracing/core/trace_writer_for_testing.cc
index c308394..838f93e 100644
--- a/src/tracing/core/trace_writer_for_testing.cc
+++ b/src/tracing/core/trace_writer_for_testing.cc
@@ -25,9 +25,11 @@
 namespace perfetto {
 
 TraceWriterForTesting::TraceWriterForTesting()
-    : delegate_(4096, 4096), stream_(&delegate_) {
+    : delegate_(static_cast<size_t>(base::kPageSize),
+                static_cast<size_t>(base::kPageSize)),
+      stream_(&delegate_) {
   delegate_.set_writer(&stream_);
-  cur_packet_.reset(new protozero::RootMessage<protos::pbzero::TracePacket>());
+  cur_packet_.reset(new protos::pbzero::TracePacket());
   cur_packet_->Finalize();  // To avoid the DCHECK in NewTracePacket().
 }
 
diff --git a/src/tracing/core/trace_writer_for_testing.h b/src/tracing/core/trace_writer_for_testing.h
index 16c7c76..f066fee 100644
--- a/src/tracing/core/trace_writer_for_testing.h
+++ b/src/tracing/core/trace_writer_for_testing.h
@@ -20,7 +20,6 @@
 
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/root_message.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "protos/perfetto/trace/trace_packet.gen.h"
 
@@ -54,8 +53,7 @@
 
   // The packet returned via NewTracePacket(). Its owned by this class,
   // TracePacketHandle has just a pointer to it.
-  std::unique_ptr<protozero::RootMessage<protos::pbzero::TracePacket>>
-      cur_packet_;
+  std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
 };
 
 }  // namespace perfetto
diff --git a/src/tracing/core/trace_writer_impl.cc b/src/tracing/core/trace_writer_impl.cc
index 4cfa734..f0705ae 100644
--- a/src/tracing/core/trace_writer_impl.cc
+++ b/src/tracing/core/trace_writer_impl.cc
@@ -24,9 +24,7 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/thread_annotations.h"
-#include "perfetto/protozero/message.h"
 #include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/root_message.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -56,7 +54,7 @@
   // more gracefully and always return a no-op TracePacket in NewTracePacket().
   PERFETTO_CHECK(id_ != 0);
 
-  cur_packet_.reset(new protozero::RootMessage<protos::pbzero::TracePacket>());
+  cur_packet_.reset(new protos::pbzero::TracePacket());
   cur_packet_->Finalize();  // To avoid the DCHECK in NewTracePacket().
 }
 
@@ -65,9 +63,6 @@
     cur_packet_->Finalize();
     Flush();
   }
-  // This call may cause the shared memory arbiter (and the underlying memory)
-  // to get asynchronously deleted if this was the last trace writer targeting
-  // the arbiter and the arbiter was marked for shutdown.
   shmem_arbiter_->ReleaseWriterID(id_);
 }
 
@@ -79,14 +74,8 @@
     shmem_arbiter_->ReturnCompletedChunk(std::move(cur_chunk_), target_buffer_,
                                          &patch_list_);
   } else {
-    // When in stall mode, all patches should have been returned with the last
-    // chunk, since the last packet was completed. In drop_packets_ mode, this
-    // may not be the case because the packet may have been fragmenting when
-    // SMB exhaustion occurred and |cur_chunk_| became invalid. In this case,
-    // drop_packets_ should be true.
-    PERFETTO_DCHECK(patch_list_.empty() || drop_packets_);
+    PERFETTO_DCHECK(patch_list_.empty());
   }
-
   // Always issue the Flush request, even if there is nothing to flush, just
   // for the sake of getting the callback posted back.
   shmem_arbiter_->FlushPendingCommitDataRequests(callback);
diff --git a/src/tracing/core/trace_writer_impl.h b/src/tracing/core/trace_writer_impl.h
index 9f3b970..be2daef 100644
--- a/src/tracing/core/trace_writer_impl.h
+++ b/src/tracing/core/trace_writer_impl.h
@@ -24,7 +24,6 @@
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/root_message.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
 #include "perfetto/tracing/buffer_exhausted_policy.h"
 #include "src/tracing/core/patch_list.h"
@@ -93,8 +92,7 @@
 
   // The packet returned via NewTracePacket(). Its owned by this class,
   // TracePacketHandle has just a pointer to it.
-  std::unique_ptr<protozero::RootMessage<protos::pbzero::TracePacket>>
-      cur_packet_;
+  std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
 
   // The start address of |cur_packet_| within |cur_chunk_|. Used to figure out
   // fragments sizes when a TracePacket write is interrupted by GetNewBuffer().
diff --git a/src/tracing/core/trace_writer_impl_unittest.cc b/src/tracing/core/trace_writer_impl_unittest.cc
index e59e897..b40a172 100644
--- a/src/tracing/core/trace_writer_impl_unittest.cc
+++ b/src/tracing/core/trace_writer_impl_unittest.cc
@@ -95,12 +95,11 @@
   // TODO(primiano): check also the content of the packets decoding the protos.
 }
 
-TEST_P(TraceWriterImplTest, FragmentingPacketWithProducerAndServicePatching) {
+TEST_P(TraceWriterImplTest, FragmentingPacket) {
   const BufferID kBufId = 42;
   std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(kBufId);
 
-  // Write a packet that's guaranteed to span more than a single chunk, but less
-  // than two chunks.
+  // Write a packet that's guaranteed to span more than a single chunk.
   auto packet = writer->NewTracePacket();
   size_t chunk_size = page_size() / 4;
   std::stringstream large_string_writer;
@@ -118,30 +117,6 @@
   EXPECT_EQ(kBufId, last_commit.chunks_to_move()[0].target_buffer());
   EXPECT_EQ(0, last_commit.chunks_to_patch_size());
 
-  // We will simulate a batching cycle by first setting the batching period to a
-  // very large value and then force-flushing when we are done writing data.
-  arbiter_->SetDirectSMBPatchingSupportedByService();
-  ASSERT_TRUE(arbiter_->EnableDirectSMBPatching());
-  arbiter_->SetBatchCommitsDuration(UINT32_MAX);
-
-  // Write a second packet that's guaranteed to span more than a single chunk.
-  // Starting a new trace packet should cause the patches for the first packet
-  // (i.e. for the first chunk) to be queued for sending to the service. They
-  // cannot be applied locally because the first chunk was already committed.
-  packet->Finalize();
-  auto packet2 = writer->NewTracePacket();
-  packet2->set_for_testing()->set_str(large_string.data(), large_string.size());
-
-  // Starting a new packet yet again should cause the patches for the second
-  // packet (i.e. for the second chunk) to be applied in the producer, because
-  // the second chunk has not been committed yet.
-  packet2->Finalize();
-  auto packet3 = writer->NewTracePacket();
-
-  // Simulate the end of the batching period, which should trigger a commit to
-  // the service.
-  arbiter_->FlushPendingCommitDataRequests();
-
   SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
 
   // The first allocated chunk should be complete but need patching, since the
@@ -156,80 +131,11 @@
   ASSERT_TRUE(chunk.header()->packets.load().flags &
               SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
 
-  // Verify that a patch for the first chunk was sent to the service.
-  ASSERT_EQ(1, last_commit.chunks_to_patch_size());
-  EXPECT_EQ(writer->writer_id(), last_commit.chunks_to_patch()[0].writer_id());
-  EXPECT_EQ(kBufId, last_commit.chunks_to_patch()[0].target_buffer());
-  EXPECT_EQ(chunk.header()->chunk_id.load(),
-            last_commit.chunks_to_patch()[0].chunk_id());
-  EXPECT_FALSE(last_commit.chunks_to_patch()[0].has_more_patches());
-  ASSERT_EQ(1, last_commit.chunks_to_patch()[0].patches_size());
-
-  // Verify that the second chunk was committed.
-  ASSERT_EQ(1, last_commit.chunks_to_move_size());
-  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].page());
-  EXPECT_EQ(1u, last_commit.chunks_to_move()[0].chunk());
-  EXPECT_EQ(kBufId, last_commit.chunks_to_move()[0].target_buffer());
-
-  // The second chunk should be in a complete state and should not need
-  // patching, as the patches to it should have been applied in the producer.
-  ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0u, 1u));
-  auto chunk2 = abi->TryAcquireChunkForReading(0u, 1u);
-  ASSERT_TRUE(chunk2.is_valid());
-  ASSERT_EQ(2, chunk2.header()->packets.load().count);
-  ASSERT_TRUE(chunk2.header()->packets.load().flags &
-              SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
-  ASSERT_FALSE(chunk2.header()->packets.load().flags &
-               SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-}
-
-TEST_P(TraceWriterImplTest, FragmentingPacketWithoutEnablingProducerPatching) {
-  // We will simulate a batching cycle by first setting the batching period to a
-  // very large value and will force flush to simulate a flush happening when we
-  // believe it should - in this case when a patch is encountered.
-  //
-  // Note: direct producer-side patching should be disabled by default.
-  arbiter_->SetBatchCommitsDuration(UINT32_MAX);
-
-  const BufferID kBufId = 42;
-  std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(kBufId);
-
-  // Write a packet that's guaranteed to span more than a single chunk.
-  auto packet = 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();
-  packet->set_for_testing()->set_str(large_string.data(), large_string.size());
-
-  // Starting a new packet should cause the first chunk and its patches to be
-  // committed to the service.
+  // Starting a new packet should cause patches to be applied.
   packet->Finalize();
   auto packet2 = writer->NewTracePacket();
   arbiter_->FlushPendingCommitDataRequests();
-
-  // The first allocated chunk should be complete but need patching, since the
-  // packet extended past the chunk and no patches for the packet size or string
-  // field size were applied in the producer.
-  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(1, chunk.header()->packets.load().count);
-  ASSERT_TRUE(chunk.header()->packets.load().flags &
-              SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-  ASSERT_TRUE(chunk.header()->packets.load().flags &
-              SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
-
-  // The first chunk was committed.
-  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());
-
-  // The patches for the first chunk were committed.
+  EXPECT_EQ(0, last_commit.chunks_to_move_size());
   ASSERT_EQ(1, last_commit.chunks_to_patch_size());
   EXPECT_EQ(writer->writer_id(), last_commit.chunks_to_patch()[0].writer_id());
   EXPECT_EQ(kBufId, last_commit.chunks_to_patch()[0].target_buffer());
@@ -444,59 +350,6 @@
                SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
 }
 
-// Regression test that verifies that flushing a TraceWriter while a fragmented
-// packet still has uncommitted patches doesn't hit a DCHECK / crash the writer
-// thread.
-TEST_P(TraceWriterImplTest, FlushAfterFragmentingPacketWhileBufferExhausted) {
-  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 but one of the remaining chunks in the SMB in new writers.
-  std::array<std::unique_ptr<TraceWriter>, kNumPages * 4 - 2> 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 two chunks, causing
-  // |writer| to attempt to acquire two new chunks, but fail to acquire the
-  // second.
-  auto packet2 = writer->NewTracePacket();
-  size_t chunk_size = page_size() / 4;
-  std::stringstream large_string_writer;
-  for (size_t pos = 0; pos < chunk_size * 2; 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 two chunks should be committed.
-  arbiter_->FlushPendingCommitDataRequests();
-  const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
-  ASSERT_EQ(2, last_commit.chunks_to_move_size());
-
-  // Flushing should succeed, even though some patches are still in the writer's
-  // patch list.
-  packet2->Finalize();
-  writer->Flush();
-}
-
 // 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 3a4c2a9..36b8b22 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -17,7 +17,6 @@
 #include "src/tracing/core/tracing_service_impl.h"
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/tracing/core/forward_decls.h"
 
 #include <errno.h>
 #include <inttypes.h>
@@ -35,15 +34,11 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <sys/system_properties.h>
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include "src/android_internal/lazy_library_loader.h"    // nogncheck
-#include "src/android_internal/tracing_service_proxy.h"  // nogncheck
-#endif  // PERFETTO_ANDROID_BUILD
-#endif  // PERFETTO_OS_ANDROID
+#endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #define PERFETTO_HAS_CHMOD
 #include <sys/stat.h>
 #endif
@@ -51,16 +46,12 @@
 #include <algorithm>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/status.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/metatrace.h"
 #include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/version.h"
 #include "perfetto/ext/base/watchdog.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/consumer.h"
 #include "perfetto/ext/tracing/core/observable_events.h"
 #include "perfetto/ext/tracing/core/producer.h"
@@ -73,8 +64,6 @@
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/tracing_service_capabilities.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
-#include "src/android_stats/statsd_logging_helper.h"
-#include "src/protozero/filtering/message_filter.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"
@@ -94,21 +83,8 @@
 // from the IPC layer, but we should never assume that that the producer calls
 // come in the right order or their arguments are sane / within bounds.
 
-// This is a macro because we want the call-site line number for the ELOG.
-#define PERFETTO_SVC_ERR(...) \
-  (PERFETTO_ELOG(__VA_ARGS__), ::perfetto::base::ErrStatus(__VA_ARGS__))
-
 namespace perfetto {
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-// These are the only SELinux approved dir for trace files that are created
-// directly by traced.
-const char* kTraceDirBasePath = "/data/misc/perfetto-traces/";
-const char* kAndroidProductionBugreportTracePath =
-    "/data/misc/perfetto-traces/bugreport/systrace.pftrace";
-#endif
-
 namespace {
 constexpr int kMaxBuffersPerConsumer = 128;
 constexpr uint32_t kDefaultSnapshotsIntervalMs = 10 * 1000;
@@ -119,7 +95,6 @@
 constexpr int64_t kMinSecondsBetweenTracesGuardrail = 5 * 60;
 
 constexpr uint32_t kMillisPerHour = 3600000;
-constexpr uint32_t kMillisPerDay = kMillisPerHour * 24;
 constexpr uint32_t kMaxTracingDurationMillis = 7 * 24 * kMillisPerHour;
 
 // These apply only if enable_extra_guardrails is true.
@@ -148,6 +123,13 @@
 
 #define IOV_MAX 1024  // Linux compatible limit.
 
+// uid checking is a NOP on Windows.
+uid_t getuid() {
+  return 0;
+}
+uid_t geteuid() {
+  return 0;
+}
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
         // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
 
@@ -201,17 +183,12 @@
   page_size = std::min<size_t>(page_size, kMaxPageSize);
   shm_size = std::min<size_t>(shm_size, TracingServiceImpl::kMaxShmSize);
 
-  // The tracing page size has to be multiple of 4K. On some systems (e.g. Mac
-  // on Arm64) the system page size can be larger (e.g., 16K). That doesn't
-  // matter here, because the tracing page size is just a logical partitioning
-  // and does not have any dependencies on kernel mm syscalls (read: it's fine
-  // to have trace page sizes of 4K on a system where the kernel page size is
-  // 16K).
-  bool page_size_is_valid = page_size >= SharedMemoryABI::kMinPageSize;
-  page_size_is_valid &= page_size % SharedMemoryABI::kMinPageSize == 0;
+  // Page size has to be multiple of system's page size.
+  bool page_size_is_valid = page_size >= base::kPageSize;
+  page_size_is_valid &= page_size % base::kPageSize == 0;
 
   // Only allow power of two numbers of pages, i.e. 1, 2, 4, 8 pages.
-  size_t num_pages = page_size / SharedMemoryABI::kMinPageSize;
+  size_t num_pages = page_size / base::kPageSize;
   page_size_is_valid &= (num_pages & (num_pages - 1)) == 0;
 
   if (!page_size_is_valid || shm_size < page_size ||
@@ -239,53 +216,27 @@
   return filter_matches || filter_regex_matches;
 }
 
-// Used when:
-// 1. TraceConfig.write_into_file == true and output_path is not empty.
-// 2. Calling SaveTraceForBugreport(), from perfetto --save-for-bugreport.
-base::ScopedFile CreateTraceFile(const std::string& path, bool overwrite) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  // This is NOT trying to preserve any security property, SELinux does that.
-  // It just improves the actionability of the error when people try to save the
-  // trace in a location that is not SELinux-allowed (a generic "permission
-  // denied" vs "don't put it here, put it there").
-  if (!base::StartsWith(path, kTraceDirBasePath)) {
+// Used when write_into_file == true and output_path is not empty.
+base::ScopedFile CreateTraceFile(const std::string& path) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+  static const char kBase[] = "/data/misc/perfetto-traces/";
+  if (!base::StartsWith(path, kBase) || path.rfind('/') != strlen(kBase) - 1) {
     PERFETTO_ELOG("Invalid output_path %s. On Android it must be within %s.",
-                  path.c_str(), kTraceDirBasePath);
+                  path.c_str(), kBase);
     return base::ScopedFile();
   }
 #endif
   // O_CREAT | O_EXCL will fail if the file exists already.
-  const int flags = O_RDWR | O_CREAT | (overwrite ? O_TRUNC : O_EXCL);
-  auto fd = base::OpenFile(path, flags, 0600);
-  if (fd) {
-#if defined(PERFETTO_HAS_CHMOD)
-    // Passing 0644 directly above won't work because of umask.
-    PERFETTO_CHECK(fchmod(*fd, 0644) == 0);
-#endif
-  } else {
+  auto fd = base::OpenFile(path, O_RDWR | O_CREAT | O_EXCL, 0600);
+  if (!fd)
     PERFETTO_PLOG("Failed to create %s", path.c_str());
-  }
+#if defined(PERFETTO_HAS_CHMOD)
+  // Passing 0644 directly above won't work because of umask.
+  PERFETTO_CHECK(fchmod(*fd, 0644) == 0);
+#endif
   return fd;
 }
 
-std::string GetBugreportTmpPath() {
-  return GetBugreportPath() + ".tmp";
-}
-
-bool ShouldLogEvent(const TraceConfig& cfg) {
-  switch (cfg.statsd_logging()) {
-    case TraceConfig::STATSD_LOGGING_ENABLED:
-      return true;
-    case TraceConfig::STATSD_LOGGING_DISABLED:
-      return false;
-    case TraceConfig::STATSD_LOGGING_UNSPECIFIED:
-      // For backward compatibility with older versions of perfetto_cmd.
-      return cfg.enable_extra_guardrails();
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
 }  // namespace
 
 // These constants instead are defined in the header because are used by tests.
@@ -296,16 +247,6 @@
 constexpr uint32_t TracingServiceImpl::kDataSourceStopTimeoutMs;
 constexpr uint8_t TracingServiceImpl::kSyncMarker[];
 
-std::string GetBugreportPath() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
-    PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  return kAndroidProductionBugreportTracePath;
-#else
-  // Only for tests, SaveTraceForBugreport is not used on other OSes.
-  return base::GetSysTempDir() + "/bugreport.pftrace";
-#endif
-}
-
 // static
 std::unique_ptr<TracingService> TracingService::CreateInstance(
     std::unique_ptr<SharedMemory::Factory> shm_factory,
@@ -319,10 +260,8 @@
     base::TaskRunner* task_runner)
     : task_runner_(task_runner),
       shm_factory_(std::move(shm_factory)),
-      uid_(base::GetCurrentUserId()),
+      uid_(getuid()),
       buffer_ids_(kMaxTraceBufferID),
-      trigger_probability_rand_(
-          static_cast<uint32_t>(base::GetWallTimeNs().count())),
       weak_ptr_factory_(this) {
   PERFETTO_DCHECK(task_runner_);
 }
@@ -339,11 +278,10 @@
                                     bool in_process,
                                     ProducerSMBScrapingMode smb_scraping_mode,
                                     size_t shared_memory_page_size_hint_bytes,
-                                    std::unique_ptr<SharedMemory> shm,
-                                    const std::string& sdk_version) {
+                                    std::unique_ptr<SharedMemory> shm) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
 
-  if (lockdown_mode_ && uid != base::GetCurrentUserId()) {
+  if (lockdown_mode_ && uid != geteuid()) {
     PERFETTO_DLOG("Lockdown mode. Rejecting producer with UID %ld",
                   static_cast<unsigned long>(uid));
     return nullptr;
@@ -369,8 +307,8 @@
   }
 
   std::unique_ptr<ProducerEndpointImpl> endpoint(new ProducerEndpointImpl(
-      id, uid, this, task_runner_, producer, producer_name, sdk_version,
-      in_process, smb_scraping_enabled));
+      id, uid, this, task_runner_, producer, producer_name, in_process,
+      smb_scraping_enabled));
   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;
@@ -378,11 +316,7 @@
 
   // Producer::OnConnect() should run before Producer::OnTracingSetup(). The
   // latter may be posted by SetupSharedMemory() below, so post OnConnect() now.
-  auto weak_ptr = endpoint->weak_ptr_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_ptr] {
-    if (weak_ptr)
-      weak_ptr->producer_->OnConnect();
-  });
+  task_runner_->PostTask(std::bind(&Producer::OnConnect, endpoint->producer_));
 
   if (shm) {
     // The producer supplied an SMB. This is used only by Chrome; in the most
@@ -450,18 +384,19 @@
 std::unique_ptr<TracingService::ConsumerEndpoint>
 TracingServiceImpl::ConnectConsumer(Consumer* consumer, uid_t uid) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("Consumer %p connected from UID %" PRIu64,
-                reinterpret_cast<void*>(consumer), static_cast<uint64_t>(uid));
+  PERFETTO_DLOG("Consumer %p connected", reinterpret_cast<void*>(consumer));
   std::unique_ptr<ConsumerEndpointImpl> endpoint(
       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->weak_ptr_factory_.GetWeakPtr();
+  auto weak_ptr = endpoint->GetWeakPtr();
   task_runner_->PostTask([weak_ptr] {
-    if (weak_ptr)
-      weak_ptr->consumer_->OnConnect();
+    if (!weak_ptr) {
+      return;
+    }
+    weak_ptr->consumer_->OnConnect();
   });
   return std::unique_ptr<ConsumerEndpoint>(std::move(endpoint));
 }
@@ -538,41 +473,32 @@
   return true;
 }
 
-base::Status TracingServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer,
-                                               const TraceConfig& cfg,
-                                               base::ScopedFile fd) {
+bool TracingServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer,
+                                       const TraceConfig& cfg,
+                                       base::ScopedFile fd) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DLOG("Enabling tracing for consumer %p",
                 reinterpret_cast<void*>(consumer));
-  MaybeLogUploadEvent(cfg, PerfettoStatsdAtom::kTracedEnableTracing);
   if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_SET)
     lockdown_mode_ = true;
   if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_CLEAR)
     lockdown_mode_ = false;
-
-  // Scope |tracing_session| to this block to prevent accidental use of a null
-  // pointer later in this function.
-  {
-    TracingSession* tracing_session =
-        GetTracingSession(consumer->tracing_session_id_);
-    if (tracing_session) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingExistingTraceSession);
-      return PERFETTO_SVC_ERR(
-          "A Consumer is trying to EnableTracing() but another tracing "
-          "session is already active (forgot a call to FreeBuffers() ?)");
-    }
+  TracingSession* tracing_session =
+      GetTracingSession(consumer->tracing_session_id_);
+  if (tracing_session) {
+    PERFETTO_DLOG(
+        "A Consumer is trying to EnableTracing() but another tracing session "
+        "is already active (forgot a call to FreeBuffers() ?)");
+    return false;
   }
 
   const uint32_t max_duration_ms = cfg.enable_extra_guardrails()
                                        ? kGuardrailsMaxTracingDurationMillis
                                        : kMaxTracingDurationMillis;
   if (cfg.duration_ms() > max_duration_ms) {
-    MaybeLogUploadEvent(cfg,
-                        PerfettoStatsdAtom::kTracedEnableTracingTooLongTrace);
-    return PERFETTO_SVC_ERR("Requested too long trace (%" PRIu32
-                            "ms  > %" PRIu32 " ms)",
-                            cfg.duration_ms(), max_duration_ms);
+    PERFETTO_ELOG("Requested too long trace (%" PRIu32 "ms  > %" PRIu32 " ms)",
+                  cfg.duration_ms(), max_duration_ms);
+    return false;
   }
 
   const bool has_trigger_config = cfg.trigger_config().trigger_mode() !=
@@ -580,91 +506,57 @@
   if (has_trigger_config && (cfg.trigger_config().trigger_timeout_ms() == 0 ||
                              cfg.trigger_config().trigger_timeout_ms() >
                                  kGuardrailsMaxTracingDurationMillis)) {
-    MaybeLogUploadEvent(
-        cfg, PerfettoStatsdAtom::kTracedEnableTracingInvalidTriggerTimeout);
-    return PERFETTO_SVC_ERR(
+    PERFETTO_ELOG(
         "Traces with START_TRACING triggers must provide a positive "
         "trigger_timeout_ms < 7 days (received %" PRIu32 "ms)",
         cfg.trigger_config().trigger_timeout_ms());
+    return false;
   }
 
   if (has_trigger_config && cfg.duration_ms() != 0) {
-    MaybeLogUploadEvent(
-        cfg, PerfettoStatsdAtom::kTracedEnableTracingDurationWithTrigger);
-    return PERFETTO_SVC_ERR(
+    PERFETTO_ELOG(
         "duration_ms was set, this must not be set for traces with triggers.");
-  }
-
-  if (cfg.trigger_config().trigger_mode() ==
-          TraceConfig::TriggerConfig::STOP_TRACING &&
-      cfg.write_into_file()) {
-    // We don't support this usecase because there are subtle assumptions which
-    // break around TracingServiceEvents and windowed sorting (i.e. if we don't
-    // drain the events in ReadBuffers because we are waiting for STOP_TRACING,
-    // we can end up queueing up a lot of TracingServiceEvents and emitting them
-    // wildy out of order breaking windowed sorting in trace processor).
-    MaybeLogUploadEvent(
-        cfg, PerfettoStatsdAtom::kTracedEnableTracingStopTracingWriteIntoFile);
-    return PERFETTO_SVC_ERR(
-        "Specifying trigger mode STOP_TRACING and write_into_file together is "
-        "unsupported");
+    return false;
   }
 
   std::unordered_set<std::string> triggers;
   for (const auto& trigger : cfg.trigger_config().triggers()) {
     if (!triggers.insert(trigger.name()).second) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingDuplicateTriggerName);
-      return PERFETTO_SVC_ERR("Duplicate trigger name: %s",
-                              trigger.name().c_str());
+      PERFETTO_ELOG("Duplicate trigger name: %s", trigger.name().c_str());
+      return false;
     }
   }
 
   if (cfg.enable_extra_guardrails()) {
     if (cfg.deferred_start()) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingInvalidDeferredStart);
-      return PERFETTO_SVC_ERR(
+      PERFETTO_ELOG(
           "deferred_start=true is not supported in unsupervised traces");
+      return false;
     }
     uint64_t buf_size_sum = 0;
-    for (const auto& buf : cfg.buffers()) {
-      if (buf.size_kb() % 4 != 0) {
-        MaybeLogUploadEvent(
-            cfg, PerfettoStatsdAtom::kTracedEnableTracingInvalidBufferSize);
-        return PERFETTO_SVC_ERR(
-            "buffers.size_kb must be a multiple of 4, got %" PRIu32,
-            buf.size_kb());
-      }
+    for (const auto& buf : cfg.buffers())
       buf_size_sum += buf.size_kb();
-    }
     if (buf_size_sum > kGuardrailsMaxTracingBufferSizeKb) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingBufferSizeTooLarge);
-      return PERFETTO_SVC_ERR("Requested too large trace buffer (%" PRIu64
-                              "kB  > %" PRIu32 " kB)",
-                              buf_size_sum, kGuardrailsMaxTracingBufferSizeKb);
+      PERFETTO_ELOG("Requested too large trace buffer (%" PRIu64
+                    "kB  > %" PRIu32 " kB)",
+                    buf_size_sum, kGuardrailsMaxTracingBufferSizeKb);
+      return false;
     }
   }
 
   if (cfg.buffers_size() > kMaxBuffersPerConsumer) {
-    MaybeLogUploadEvent(cfg,
-                        PerfettoStatsdAtom::kTracedEnableTracingTooManyBuffers);
-    return PERFETTO_SVC_ERR("Too many buffers configured (%d)",
-                            cfg.buffers_size());
+    PERFETTO_ELOG("Too many buffers configured (%d)", cfg.buffers_size());
+    return false;
   }
 
   if (!cfg.unique_session_name().empty()) {
     const std::string& name = cfg.unique_session_name();
     for (auto& kv : tracing_sessions_) {
       if (kv.second.config.unique_session_name() == name) {
-        MaybeLogUploadEvent(
-            cfg, PerfettoStatsdAtom::kTracedEnableTracingDuplicateSessionName);
-        static const char fmt[] =
-            "A trace with this unique session name (%s) already exists";
-        // This happens frequently, don't make it an "E"LOG.
-        PERFETTO_LOG(fmt, name.c_str());
-        return base::ErrStatus(fmt, name.c_str());
+        PERFETTO_ELOG(
+            "A trace with this unique session name (%s) already exists",
+            name.c_str());
+        return false;
       }
     }
   }
@@ -689,31 +581,29 @@
     if (previous_s == 0) {
       previous_s = now_s;
     } else {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingSessionNameTooRecent);
-      return PERFETTO_SVC_ERR(
+      PERFETTO_ELOG(
           "A trace with unique session name \"%s\" began less than %" PRId64
           "s ago (%" PRId64 "s)",
           name.c_str(), kMinSecondsBetweenTracesGuardrail, now_s - previous_s);
+      return false;
     }
   }
 
-  const int sessions_for_uid = static_cast<int>(std::count_if(
+  const long sessions_for_uid = std::count_if(
       tracing_sessions_.begin(), tracing_sessions_.end(),
       [consumer](const decltype(tracing_sessions_)::value_type& s) {
         return s.second.consumer_uid == consumer->uid_;
-      }));
+      });
 
   int per_uid_limit = kMaxConcurrentTracingSessionsPerUid;
   if (consumer->uid_ == 1066 /* AID_STATSD*/) {
     per_uid_limit = kMaxConcurrentTracingSessionsForStatsdUid;
   }
   if (sessions_for_uid >= per_uid_limit) {
-    MaybeLogUploadEvent(
-        cfg, PerfettoStatsdAtom::kTracedEnableTracingTooManySessionsForUid);
-    return PERFETTO_SVC_ERR(
-        "Too many concurrent tracing sesions (%d) for uid %d limit is %d",
+    PERFETTO_ELOG(
+        "Too many concurrent tracing sesions (%ld) for uid %d limit is %d",
         sessions_for_uid, static_cast<int>(consumer->uid_), per_uid_limit);
+    return false;
   }
 
   // TODO(primiano): This is a workaround to prevent that a producer gets stuck
@@ -721,70 +611,29 @@
   // instances than free pages in the buffer. This is really a bug in
   // trace_probes and the way it handles stalls in the shmem buffer.
   if (tracing_sessions_.size() >= kMaxConcurrentTracingSessions) {
-    MaybeLogUploadEvent(
-        cfg, PerfettoStatsdAtom::kTracedEnableTracingTooManyConcurrentSessions);
-    return PERFETTO_SVC_ERR("Too many concurrent tracing sesions (%zu)",
-                            tracing_sessions_.size());
-  }
-
-  // If the trace config provides a filter bytecode, setup the filter now.
-  // If the filter loading fails, abort the tracing session rather than running
-  // unfiltered.
-  std::unique_ptr<protozero::MessageFilter> trace_filter;
-  if (cfg.has_trace_filter()) {
-    const auto& filt = cfg.trace_filter();
-    const std::string& bytecode = filt.bytecode();
-    trace_filter.reset(new protozero::MessageFilter());
-    if (!trace_filter->LoadFilterBytecode(bytecode.data(), bytecode.size())) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingInvalidFilter);
-      return PERFETTO_SVC_ERR("Trace filter bytecode invalid, aborting");
-    }
-    // The filter is created using perfetto.protos.Trace as root message
-    // (because that makes it possible to play around with the `proto_filter`
-    // tool on actual traces). Here in the service, however, we deal with
-    // perfetto.protos.TracePacket(s), which are one level down (Trace.packet).
-    // The IPC client (or the write_into_filte logic in here) are responsible
-    // for pre-pending the packet preamble (See GetProtoPreamble() calls), but
-    // the preamble is not there at ReadBuffer time. Hence we change the root of
-    // the filtering to start at the Trace.packet level.
-    uint32_t packet_field_id = TracePacket::kPacketFieldNumber;
-    if (!trace_filter->SetFilterRoot(&packet_field_id, 1)) {
-      MaybeLogUploadEvent(
-          cfg, PerfettoStatsdAtom::kTracedEnableTracingInvalidFilter);
-      return PERFETTO_SVC_ERR("Failed to set filter root.");
-    }
+    PERFETTO_ELOG("Too many concurrent tracing sesions (%zu)",
+                  tracing_sessions_.size());
+    return false;
   }
 
   const TracingSessionID tsid = ++last_tracing_session_id_;
-  TracingSession* tracing_session =
-      &tracing_sessions_
-           .emplace(std::piecewise_construct, std::forward_as_tuple(tsid),
-                    std::forward_as_tuple(tsid, consumer, cfg, task_runner_))
+  tracing_session =
+      &tracing_sessions_.emplace(tsid, TracingSession(tsid, consumer, cfg))
            .first->second;
 
-  if (trace_filter)
-    tracing_session->trace_filter = std::move(trace_filter);
-
   if (cfg.write_into_file()) {
     if (!fd ^ !cfg.output_path().empty()) {
-      tracing_sessions_.erase(tsid);
-      MaybeLogUploadEvent(
-          tracing_session->config,
-          PerfettoStatsdAtom::kTracedEnableTracingInvalidFdOutputFile);
-      return PERFETTO_SVC_ERR(
+      PERFETTO_ELOG(
           "When write_into_file==true either a FD needs to be passed or "
           "output_path must be populated (but not both)");
+      tracing_sessions_.erase(tsid);
+      return false;
     }
     if (!cfg.output_path().empty()) {
-      fd = CreateTraceFile(cfg.output_path(), /*overwrite=*/false);
+      fd = CreateTraceFile(cfg.output_path());
       if (!fd) {
-        MaybeLogUploadEvent(
-            tracing_session->config,
-            PerfettoStatsdAtom::kTracedEnableTracingFailedToCreateFile);
         tracing_sessions_.erase(tsid);
-        return PERFETTO_SVC_ERR("Failed to create the trace file %s",
-                                cfg.output_path().c_str());
+        return false;
       }
     }
     tracing_session->write_into_file = std::move(fd);
@@ -845,10 +694,7 @@
       buffers_.erase(global_id);
     }
     tracing_sessions_.erase(tsid);
-    MaybeLogUploadEvent(tracing_session->config,
-                        PerfettoStatsdAtom::kTracedEnableTracingOom);
-    return PERFETTO_SVC_ERR(
-        "Failed to allocate tracing buffers: OOM or too many buffers");
+    return false;
   }
 
   consumer->tracing_session_id_ = tsid;
@@ -918,7 +764,7 @@
   if (!cfg.deferred_start() && !has_start_trigger)
     return StartTracing(tsid);
 
-  return base::OkStatus();
+  return true;
 }
 
 void TracingServiceImpl::ChangeTraceConfig(ConsumerEndpointImpl* consumer,
@@ -964,7 +810,7 @@
     std::vector<std::string> new_producer_name_filter;
     std::vector<std::string> new_producer_name_regex_filter;
     bool found_data_source = false;
-    for (const auto& it : updated_cfg.data_sources()) {
+    for (auto it : updated_cfg.data_sources()) {
       if (cfg_data_source.config().name() == it.config().name()) {
         new_producer_name_filter = it.producer_name_filter();
         new_producer_name_regex_filter = it.producer_name_regex_filter();
@@ -1039,73 +885,39 @@
   }
 }
 
-base::Status TracingServiceImpl::StartTracing(TracingSessionID tsid) {
+bool TracingServiceImpl::StartTracing(TracingSessionID tsid) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
   TracingSession* tracing_session = GetTracingSession(tsid);
   if (!tracing_session) {
-    return PERFETTO_SVC_ERR(
-        "StartTracing() failed, invalid session ID %" PRIu64, tsid);
+    PERFETTO_DLOG("StartTracing() failed, invalid session ID %" PRIu64, tsid);
+    return false;
   }
 
-  MaybeLogUploadEvent(tracing_session->config,
-                      PerfettoStatsdAtom::kTracedStartTracing);
-
   if (tracing_session->state != TracingSession::CONFIGURED) {
-    MaybeLogUploadEvent(
-        tracing_session->config,
-        PerfettoStatsdAtom::kTracedStartTracingInvalidSessionState);
-    return PERFETTO_SVC_ERR("StartTracing() failed, invalid session state: %d",
-                            tracing_session->state);
+    PERFETTO_DLOG("StartTracing() failed, invalid session state: %d",
+                  tracing_session->state);
+    return false;
   }
 
   tracing_session->state = TracingSession::STARTED;
 
-  // We store the start of trace snapshot separately as it's important to make
-  // sure we can interpret all the data in the trace and storing it in the ring
-  // buffer means it could be overwritten by a later snapshot.
-  if (!tracing_session->config.builtin_data_sources()
-           .disable_clock_snapshotting()) {
-    SnapshotClocks(&tracing_session->initial_clock_snapshot);
-  }
-
-  // We don't snapshot the clocks here because we just did this above.
-  SnapshotLifecyleEvent(
-      tracing_session,
-      protos::pbzero::TracingServiceEvent::kTracingStartedFieldNumber,
-      false /* snapshot_clocks */);
-
   // Periodically snapshot clocks, stats, sync markers while the trace is
   // active. The snapshots are emitted on the future ReadBuffers() calls, which
   // means that:
   //  (a) If we're streaming to a file (or to a consumer) while tracing, we
   //      write snapshots periodically into the trace.
   //  (b) If ReadBuffers() is only called after tracing ends, we emit the latest
-  //      snapshot into the trace. For clock snapshots, we keep track of the
-  //      snapshot recorded at the beginning of the session
-  //      (initial_clock_snapshot above), as well as the most recent sampled
-  //      snapshots that showed significant new drift between different clocks.
-  //      The latter clock snapshots are sampled periodically and at lifecycle
-  //      events.
-  base::PeriodicTask::Args snapshot_task_args;
-  snapshot_task_args.start_first_task_immediately = true;
-  snapshot_task_args.use_suspend_aware_timer =
-      tracing_session->config.builtin_data_sources()
-          .prefer_suspend_clock_for_snapshot();
-  snapshot_task_args.task = [weak_this, tsid] {
-    if (weak_this)
-      weak_this->PeriodicSnapshotTask(tsid);
-  };
-  snapshot_task_args.period_ms =
-      tracing_session->config.builtin_data_sources().snapshot_interval_ms();
-  if (!snapshot_task_args.period_ms)
-    snapshot_task_args.period_ms = kDefaultSnapshotsIntervalMs;
-  tracing_session->snapshot_periodic_task.Start(snapshot_task_args);
+  //      snapshot into the trace. For clock snapshots, we keep track of a
+  //      snapshot recorded at the beginning of the session as well as the most
+  //      recent snapshot that showed significant new drift between different
+  //      clocks. This way, we emit useful snapshots for both stop-when-full and
+  //      ring-buffer tracing modes.
+  PeriodicSnapshotTask(tracing_session, /*is_initial_snapshot=*/true);
 
   // Trigger delayed task if the trace is time limited.
   const uint32_t trace_duration_ms = tracing_session->config.duration_ms();
   if (trace_duration_ms > 0) {
+    auto weak_this = weak_ptr_factory_.GetWeakPtr();
     task_runner_->PostDelayedTask(
         [weak_this, tsid] {
           // Skip entirely the flush if the trace session doesn't exist anymore.
@@ -1131,6 +943,7 @@
 
   // Start the periodic drain tasks if we should to save the trace into a file.
   if (tracing_session->config.write_into_file()) {
+    auto weak_this = weak_ptr_factory_.GetWeakPtr();
     task_runner_->PostDelayedTask(
         [weak_this, tsid] {
           if (weak_this)
@@ -1159,9 +972,7 @@
     }
     StartDataSourceInstance(producer, tracing_session, &data_source);
   }
-
-  MaybeNotifyAllDataSourcesStarted(tracing_session);
-  return base::OkStatus();
+  return true;
 }
 
 void TracingServiceImpl::StartDataSourceInstance(
@@ -1200,9 +1011,6 @@
     return;
   }
 
-  MaybeLogUploadEvent(tracing_session->config,
-                      PerfettoStatsdAtom::kTracedDisableTracing);
-
   switch (tracing_session->state) {
     // Spurious call to DisableTracing() while already disabled, nothing to do.
     case TracingSession::DISABLED:
@@ -1246,11 +1054,6 @@
                            disable_immediately);
   }
 
-  // If the periodic task is running, we can stop the periodic snapshot timer
-  // here instead of waiting until FreeBuffers to prevent useless snapshots
-  // which won't be read.
-  tracing_session->snapshot_periodic_task.Reset();
-
   // Either this request is flagged with |disable_immediately| or there are no
   // data sources that are requesting a final handshake. In both cases just mark
   // the session as disabled immediately, notify the consumer and flush the
@@ -1327,13 +1130,8 @@
     return;
 
   PERFETTO_DLOG("All data sources started");
-
-  SnapshotLifecyleEvent(
-      tracing_session,
-      protos::pbzero::TracingServiceEvent::kAllDataSourcesStartedFieldNumber,
-      true /* snapshot_clocks */);
-
   tracing_session->did_notify_all_data_source_started = true;
+  tracing_session->time_all_data_source_started = base::GetBootTimeNs();
   tracing_session->consumer_maybe_null->OnAllDataSourcesStarted();
 }
 
@@ -1381,19 +1179,7 @@
   PERFETTO_DCHECK_THREAD(thread_checker_);
   auto* producer = GetProducer(producer_id);
   PERFETTO_DCHECK(producer);
-
-  int64_t now_ns = base::GetBootTimeNs().count();
   for (const auto& trigger_name : triggers) {
-    PERFETTO_DLOG("Received ActivateTriggers request for \"%s\"",
-                  trigger_name.c_str());
-    base::Hash hash;
-    hash.Update(trigger_name.c_str(), trigger_name.size());
-
-    uint64_t trigger_name_hash = hash.digest();
-    size_t count_in_window =
-        PurgeExpiredAndCountTriggerInWindow(now_ns, trigger_name_hash);
-
-    bool trigger_applied = false;
     for (auto& id_and_tracing_session : tracing_sessions_) {
       auto& tracing_session = id_and_tracing_session.second;
       TracingSessionID tsid = id_and_tracing_session.first;
@@ -1417,35 +1203,11 @@
         continue;
       }
 
-      // Use a random number between 0 and 1 to check if we should allow this
-      // trigger through or not.
-      double trigger_rnd =
-          trigger_rnd_override_for_testing_ > 0
-              ? trigger_rnd_override_for_testing_
-              : trigger_probability_dist_(trigger_probability_rand_);
-      PERFETTO_DCHECK(trigger_rnd >= 0 && trigger_rnd < 1);
-      if (trigger_rnd < iter->skip_probability()) {
-        MaybeLogTriggerEvent(tracing_session.config,
-                             PerfettoTriggerAtom::kTracedLimitProbability,
-                             trigger_name);
-        continue;
-      }
-
-      // If we already triggered more times than the limit, silently ignore
-      // this trigger.
-      if (iter->max_per_24_h() > 0 && count_in_window >= iter->max_per_24_h()) {
-        MaybeLogTriggerEvent(tracing_session.config,
-                             PerfettoTriggerAtom::kTracedLimitMaxPer24h,
-                             trigger_name);
-        continue;
-      }
-      trigger_applied = true;
-
       const bool triggers_already_received =
           !tracing_session.received_triggers.empty();
       tracing_session.received_triggers.push_back(
-          {static_cast<uint64_t>(now_ns), iter->name(), producer->name_,
-           producer->uid_});
+          {static_cast<uint64_t>(base::GetBootTimeNs().count()), iter->name(),
+           producer->name_, producer->uid_});
       auto weak_this = weak_ptr_factory_.GetWeakPtr();
       switch (tracing_session.config.trigger_config().trigger_mode()) {
         case TraceConfig::TriggerConfig::START_TRACING:
@@ -1459,10 +1221,6 @@
           PERFETTO_DLOG("Triggering '%s' on tracing session %" PRIu64
                         " with duration of %" PRIu32 "ms.",
                         iter->name().c_str(), tsid, iter->stop_delay_ms());
-          MaybeLogUploadEvent(tracing_session.config,
-                              PerfettoStatsdAtom::kTracedTriggerStartTracing,
-                              iter->name());
-
           // We override the trace duration to be the trigger's requested
           // value, this ensures that the trace will end after this amount
           // of time has passed.
@@ -1480,10 +1238,6 @@
           PERFETTO_DLOG("Triggering '%s' on tracing session %" PRIu64
                         " with duration of %" PRIu32 "ms.",
                         iter->name().c_str(), tsid, iter->stop_delay_ms());
-          MaybeLogUploadEvent(tracing_session.config,
-                              PerfettoStatsdAtom::kTracedTriggerStopTracing,
-                              iter->name());
-
           // Now that we've seen a trigger we need to stop, flush, and disable
           // this session after the configured |stop_delay_ms|.
           task_runner_->PostDelayedTask(
@@ -1502,10 +1256,6 @@
           PERFETTO_ELOG("Trigger activated but trigger mode unspecified.");
           break;
       }
-    }  // for (.. : tracing_sessions_)
-
-    if (trigger_applied) {
-      trigger_history_.emplace_back(TriggerHistory{now_ns, trigger_name_hash});
     }
   }
 }
@@ -1547,26 +1297,13 @@
   for (auto& producer_id_and_producer : producers_)
     ScrapeSharedMemoryBuffers(tracing_session, producer_id_and_producer.second);
 
-  SnapshotLifecyleEvent(
-      tracing_session,
-      protos::pbzero::TracingServiceEvent::kTracingDisabledFieldNumber,
-      true /* snapshot_clocks */);
-
   if (tracing_session->write_into_file) {
     tracing_session->write_period_ms = 0;
     ReadBuffers(tracing_session->id, nullptr);
   }
 
-  if (tracing_session->on_disable_callback_for_bugreport) {
-    std::move(tracing_session->on_disable_callback_for_bugreport)();
-    tracing_session->on_disable_callback_for_bugreport = nullptr;
-  }
-
-  MaybeLogUploadEvent(tracing_session->config,
-                      PerfettoStatsdAtom::kTracedNotifyTracingDisabled);
-
   if (tracing_session->consumer_maybe_null)
-    tracing_session->consumer_maybe_null->NotifyOnTracingDisabled("");
+    tracing_session->consumer_maybe_null->NotifyOnTracingDisabled();
 }
 
 void TracingServiceImpl::Flush(TracingSessionID tsid,
@@ -1677,20 +1414,15 @@
                                        ConsumerEndpoint::FlushCallback callback,
                                        bool success) {
   TracingSession* tracing_session = GetTracingSession(tsid);
-  if (!tracing_session) {
-    callback(false);
-    return;
+  if (tracing_session) {
+    // Producers may not have been able to flush all their data, even if they
+    // indicated flush completion. If possible, also collect uncommitted chunks
+    // to make sure we have everything they wrote so far.
+    for (auto& producer_id_and_producer : producers_) {
+      ScrapeSharedMemoryBuffers(tracing_session,
+                                producer_id_and_producer.second);
+    }
   }
-  // Producers may not have been able to flush all their data, even if they
-  // indicated flush completion. If possible, also collect uncommitted chunks
-  // to make sure we have everything they wrote so far.
-  for (auto& producer_id_and_producer : producers_) {
-    ScrapeSharedMemoryBuffers(tracing_session, producer_id_and_producer.second);
-  }
-  SnapshotLifecyleEvent(
-      tracing_session,
-      protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
-      true /* snapshot_clocks */);
   callback(success);
 }
 
@@ -1816,9 +1548,8 @@
   PERFETTO_DLOG("Triggering final flush for %" PRIu64, tsid);
   auto weak_this = weak_ptr_factory_.GetWeakPtr();
   Flush(tsid, 0, [weak_this, tsid](bool success) {
-    // This was a DLOG up to Jun 2021 (v16, Android S).
-    PERFETTO_LOG("FlushAndDisableTracing(%" PRIu64 ") done, success=%d", tsid,
-                 success);
+    PERFETTO_DLOG("Flush done (success: %d), disabling trace session %" PRIu64,
+                  success, tsid);
     if (!weak_this)
       return;
     TracingSession* session = weak_this->GetTracingSession(tsid);
@@ -1850,8 +1581,7 @@
         if (weak_this)
           weak_this->PeriodicFlushTask(tsid, /*post_next_only=*/false);
       },
-      flush_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
-                                              flush_period_ms));
+      flush_period_ms - (base::GetWallTimeMs().count() % flush_period_ms));
 
   if (post_next_only)
     return;
@@ -1880,8 +1610,7 @@
           weak_this->PeriodicClearIncrementalStateTask(
               tsid, /*post_next_only=*/false);
       },
-      clear_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
-                                              clear_period_ms));
+      clear_period_ms - (base::GetWallTimeMs().count() % clear_period_ms));
 
   if (post_next_only)
     return;
@@ -1934,8 +1663,7 @@
   // packets like TraceConfig and Clock snapshots. So we bail out early and let
   // the consumer know there is no data.
   if (!tracing_session->config.trigger_config().triggers().empty() &&
-      tracing_session->received_triggers.empty() &&
-      !tracing_session->seized_for_bugreport) {
+      tracing_session->received_triggers.empty()) {
     PERFETTO_DLOG(
         "ReadBuffers(): tracing session has not received a trigger yet.");
     return false;
@@ -1950,41 +1678,31 @@
     // If the consumer enabled tracing and asked to save the contents into the
     // passed file makes little sense to also try to read the buffers over IPC,
     // as that would just steal data from the periodic draining task.
-    PERFETTO_ELOG("Consumer trying to read from write_into_file session.");
+    PERFETTO_DFATAL("Consumer trying to read from write_into_file session.");
     return false;
   }
 
   std::vector<TracePacket> packets;
   packets.reserve(1024);  // Just an educated guess to avoid trivial expansions.
 
-  // If a bugreport request happened and the trace was stolen for that, give
-  // an empty trace with a clear signal to the consumer. This deals only with
-  // the case of readback-from-IPC. A similar code-path deals with the
-  // write_into_file case in MaybeSaveTraceForBugreport().
-  if (tracing_session->seized_for_bugreport && consumer) {
-    if (!tracing_session->config.builtin_data_sources()
-             .disable_service_events()) {
-      EmitSeizedForBugreportLifecycleEvent(&packets);
-    }
-    EmitLifecycleEvents(tracing_session, &packets);
-    consumer->consumer_->OnTraceData(std::move(packets), /*has_more=*/false);
-    return true;
-  }
-
-  if (!tracing_session->initial_clock_snapshot.empty()) {
+  if (!tracing_session->initial_clock_snapshot_.empty()) {
     EmitClockSnapshot(tracing_session,
-                      std::move(tracing_session->initial_clock_snapshot),
-                      &packets);
+                      std::move(tracing_session->initial_clock_snapshot_),
+                      /*set_root_timestamp=*/true, &packets);
   }
 
-  for (auto& snapshot : tracing_session->clock_snapshot_ring_buffer) {
-    PERFETTO_DCHECK(!snapshot.empty());
-    EmitClockSnapshot(tracing_session, std::move(snapshot), &packets);
+  if (!tracing_session->last_clock_snapshot_.empty()) {
+    // We don't want to put a root timestamp in periodic clock snapshot packets
+    // as they may be emitted very out of order with respect to the actual trace
+    // packets, since consuming the trace may happen at any point after it
+    // starts.
+    EmitClockSnapshot(tracing_session,
+                      std::move(tracing_session->last_clock_snapshot_),
+                      /*set_root_timestamp=*/false, &packets);
   }
-  tracing_session->clock_snapshot_ring_buffer.clear();
 
   if (tracing_session->should_emit_sync_marker) {
-    EmitSyncMarker(&packets);
+    SnapshotSyncMarker(&packets);
     tracing_session->should_emit_sync_marker = false;
   }
 
@@ -1994,12 +1712,8 @@
   }
   if (!tracing_session->config.builtin_data_sources().disable_system_info())
     MaybeEmitSystemInfo(tracing_session, &packets);
-
-  // Note that in the proto comment, we guarantee that the tracing_started
-  // lifecycle event will be emitted before any data packets so make sure to
-  // keep this before reading the tracing buffers.
   if (!tracing_session->config.builtin_data_sources().disable_service_events())
-    EmitLifecycleEvents(tracing_session, &packets);
+    MaybeEmitServiceEvents(tracing_session, &packets);
 
   size_t packets_bytes = 0;  // SUM(slice.size() for each slice in |packets|).
   size_t total_slices = 0;   // SUM(#slices in |packets|).
@@ -2087,77 +1801,23 @@
 
   const bool has_more = did_hit_threshold;
 
-  size_t prev_packets_size = packets.size();
-  if (!tracing_session->config.builtin_data_sources()
-           .disable_service_events()) {
-    // We don't bother snapshotting clocks here because we wouldn't be able to
-    // emit it and we shouldn't have significant drift from the last snapshot in
-    // any case.
-    SnapshotLifecyleEvent(tracing_session,
-                          protos::pbzero::TracingServiceEvent::
-                              kReadTracingBuffersCompletedFieldNumber,
-                          false /* snapshot_clocks */);
-    EmitLifecycleEvents(tracing_session, &packets);
-  }
-
   // Only emit the stats when there is 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.
   if (!has_more && tracing_session->should_emit_stats) {
-    EmitStats(tracing_session, &packets);
+    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();
+    }
   }
 
-  // Add sizes of packets emitted by the EmitLifecycleEvents + EmitStats.
-  for (size_t i = prev_packets_size; i < packets.size(); ++i) {
-    packets_bytes += packets[i].size();
-    total_slices += packets[i].slices().size();
-  }
-
-  // +-------------------------------------------------------------------------+
-  // | NO MORE CHANGES TO |packets| AFTER THIS POINT.                          |
-  // +-------------------------------------------------------------------------+
-
-  // If the tracing session specified a filter, run all packets through the
-  // filter and replace them with the filter results.
-  // The process below mantains the cardinality of input packets. Even if an
-  // entire packet is filtered out, we emit a zero-sized TracePacket proto. That
-  // makes debugging and reasoning about the trace stats easier.
-  // This place swaps the contents of each |packets| entry in place.
-  if (tracing_session->trace_filter) {
-    auto& trace_filter = *tracing_session->trace_filter;
-    // The filter root shoud be reset from protos.Trace to protos.TracePacket
-    // by the earlier call to SetFilterRoot() in EnableTracing().
-    PERFETTO_DCHECK(trace_filter.root_msg_index() != 0);
-    std::vector<protozero::MessageFilter::InputSlice> filter_input;
-    for (auto it = packets.begin(); it != packets.end(); ++it) {
-      const auto& packet_slices = it->slices();
-      filter_input.clear();
-      filter_input.resize(packet_slices.size());
-      ++tracing_session->filter_input_packets;
-      tracing_session->filter_input_bytes += it->size();
-      for (size_t i = 0; i < packet_slices.size(); ++i)
-        filter_input[i] = {packet_slices[i].start, packet_slices[i].size};
-      auto filtered_packet = trace_filter.FilterMessageFragments(
-          &filter_input[0], filter_input.size());
-
-      // Replace the packet in-place with the filtered one (unless failed).
-      *it = TracePacket();
-      if (filtered_packet.error) {
-        ++tracing_session->filter_errors;
-        PERFETTO_DLOG("Trace packet filtering failed @ packet %" PRIu64,
-                      tracing_session->filter_input_packets);
-        continue;
-      }
-      tracing_session->filter_output_bytes += filtered_packet.size;
-      it->AddSlice(Slice::TakeOwnership(std::move(filtered_packet.data),
-                                        filtered_packet.size));
-
-    }  // for (packet)
-  }    // if (trace_filter)
-
   // 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.
@@ -2243,7 +1903,7 @@
   }  // if (tracing_session->write_into_file)
 
   if (has_more) {
-    auto weak_consumer = consumer->weak_ptr_factory_.GetWeakPtr();
+    auto weak_consumer = consumer->GetWeakPtr();
     auto weak_this = weak_ptr_factory_.GetWeakPtr();
     task_runner_->PostTask([weak_this, weak_consumer, tsid] {
       if (!weak_this || !weak_consumer)
@@ -2281,28 +1941,18 @@
     buffers_.erase(buffer_id);
   }
   bool notify_traceur = tracing_session->config.notify_traceur();
-  bool is_long_trace =
-      (tracing_session->config.write_into_file() &&
-       tracing_session->config.file_write_period_ms() < kMillisPerDay);
-  bool seized_for_bugreport = tracing_session->seized_for_bugreport;
   tracing_sessions_.erase(tsid);
-  tracing_session = nullptr;
   UpdateMemoryGuardrail();
 
   PERFETTO_LOG("Tracing session %" PRIu64 " ended, total sessions:%zu", tsid,
                tracing_sessions_.size());
 
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) && \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  if (notify_traceur && (seized_for_bugreport || is_long_trace)) {
-    PERFETTO_LAZY_LOAD(android_internal::NotifyTraceSessionEnded, notify_fn);
-    if (!notify_fn || !notify_fn(seized_for_bugreport))
-      PERFETTO_ELOG("Failed to notify Traceur long tracing has ended");
-  }
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  static const char kTraceurProp[] = "sys.trace.trace_end_signal";
+  if (notify_traceur && __system_property_set(kTraceurProp, "1"))
+    PERFETTO_ELOG("Failed to setprop %s=1", kTraceurProp);
 #else
   base::ignore_result(notify_traceur);
-  base::ignore_result(is_long_trace);
-  base::ignore_result(seized_for_bugreport);
 #endif
 }
 
@@ -2385,16 +2035,11 @@
       if (it->first == producer_id && it->second.data_source_name == name) {
         DataSourceInstanceID ds_inst_id = it->second.instance_id;
         if (it->second.state != DataSourceInstance::STOPPED) {
-          if (it->second.state != DataSourceInstance::STOPPING) {
+          if (it->second.state != DataSourceInstance::STOPPING)
             StopDataSourceInstance(producer, &kv.second, &it->second,
                                    /* disable_immediately = */ false);
-          }
-
           // Mark the instance as stopped immediately, since we are
           // unregistering it below.
-          //
-          //  The StopDataSourceInstance above might have set the state to
-          //  STOPPING so this condition isn't an else.
           if (it->second.state == DataSourceInstance::STOPPING)
             NotifyDataSourceStopped(producer_id, ds_inst_id);
         }
@@ -2487,27 +2132,6 @@
   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());
-  if (tracing_session->consumer_uid == 1066 /* AID_STATSD */ &&
-      tracing_session->config.statsd_metadata().triggering_config_uid() !=
-          2000 /* AID_SHELL */
-      && tracing_session->config.statsd_metadata().triggering_config_uid() !=
-             0 /* AID_ROOT */) {
-    // StatsD can be triggered either by shell, root or an app that has DUMP and
-    // USAGE_STATS permission. When triggered by shell or root, we do not want
-    // to consider the trace a trusted system trace, as it was initiated by the
-    // user. Otherwise, it has to come from an app with DUMP and
-    // PACKAGE_USAGE_STATS, which has to be preinstalled and trusted by the
-    // system.
-    // Check for shell / root: https://bit.ly/3b7oZNi
-    // Check for DUMP or PACKAGE_USAGE_STATS: https://bit.ly/3ep0NrR
-    ds_config.set_session_initiator(
-        DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM);
-  } else {
-    // Unset in case the consumer set it.
-    // We need to be able to trust this field.
-    ds_config.set_session_initiator(
-        DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED);
-  }
   ds_config.set_tracing_session_id(tracing_session->id);
   BufferID global_id = tracing_session->buffers_index[relative_buffer_id];
   PERFETTO_DCHECK(global_id);
@@ -2770,85 +2394,61 @@
 #endif
 }
 
-void TracingServiceImpl::PeriodicSnapshotTask(TracingSessionID tsid) {
-  auto* tracing_session = GetTracingSession(tsid);
-  if (!tracing_session)
-    return;
-  if (tracing_session->state != TracingSession::STARTED)
-    return;
+void TracingServiceImpl::PeriodicSnapshotTask(TracingSession* tracing_session,
+                                              bool is_initial_snapshot) {
   tracing_session->should_emit_sync_marker = true;
   tracing_session->should_emit_stats = true;
-  MaybeSnapshotClocksIntoRingBuffer(tracing_session);
+
+  if (!tracing_session->config.builtin_data_sources()
+           .disable_clock_snapshotting()) {
+    if (is_initial_snapshot)
+      SnapshotClocks(&tracing_session->initial_clock_snapshot_);
+    SnapshotClocks(&tracing_session->last_clock_snapshot_);
+  }
+
+  uint32_t interval_ms =
+      tracing_session->config.builtin_data_sources().snapshot_interval_ms();
+  if (!interval_ms)
+    interval_ms = kDefaultSnapshotsIntervalMs;
+
+  TracingSessionID tsid = tracing_session->id;
+  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  task_runner_->PostDelayedTask(
+      [weak_this, tsid] {
+        if (!weak_this)
+          return;
+        auto* tracing_session_ptr = weak_this->GetTracingSession(tsid);
+        if (!tracing_session_ptr)
+          return;
+        if (tracing_session_ptr->state != TracingSession::STARTED)
+          return;
+        weak_this->PeriodicSnapshotTask(tracing_session_ptr,
+                                        /*is_initial_snapshot=*/false);
+      },
+      interval_ms - (base::GetWallTimeMs().count() % interval_ms));
 }
 
-void TracingServiceImpl::SnapshotLifecyleEvent(TracingSession* tracing_session,
-                                               uint32_t field_id,
-                                               bool snapshot_clocks) {
-  // field_id should be an id of a field in TracingServiceEvent.
-  auto& lifecycle_events = tracing_session->lifecycle_events;
-  auto event_it =
-      std::find_if(lifecycle_events.begin(), lifecycle_events.end(),
-                   [field_id](const TracingSession::LifecycleEvent& event) {
-                     return event.field_id == field_id;
-                   });
+void TracingServiceImpl::SnapshotSyncMarker(std::vector<TracePacket>* packets) {
+  // The sync marks are used to tokenize large traces efficiently.
+  // See description in trace_packet.proto.
+  if (sync_marker_packet_size_ == 0) {
+    // The marker ABI expects that the marker is written after the uid.
+    // Protozero guarantees that fields are written in the same order of the
+    // calls. The ResynchronizeTraceStreamUsingSyncMarker test verifies the ABI.
+    protozero::StaticBuffered<protos::pbzero::TracePacket> packet(
+        &sync_marker_packet_[0], sizeof(sync_marker_packet_));
+    packet->set_trusted_uid(static_cast<int32_t>(uid_));
+    packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
 
-  TracingSession::LifecycleEvent* event;
-  if (event_it == lifecycle_events.end()) {
-    lifecycle_events.emplace_back(field_id);
-    event = &lifecycle_events.back();
-  } else {
-    event = &*event_it;
+    // Keep this last.
+    packet->set_synchronization_marker(kSyncMarker, sizeof(kSyncMarker));
+    sync_marker_packet_size_ = packet.Finalize();
   }
-
-  // Snapshot the clocks before capturing the timestamp for the event so we can
-  // use this snapshot to resolve the event timestamp if necessary.
-  if (snapshot_clocks)
-    MaybeSnapshotClocksIntoRingBuffer(tracing_session);
-
-  // Erase before emplacing to prevent a unncessary doubling of memory if
-  // not needed.
-  if (event->timestamps.size() >= event->max_size) {
-    event->timestamps.erase_front(1 + event->timestamps.size() -
-                                  event->max_size);
-  }
-  event->timestamps.emplace_back(base::GetBootTimeNs().count());
+  packets->emplace_back();
+  packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_);
 }
 
-void TracingServiceImpl::MaybeSnapshotClocksIntoRingBuffer(
-    TracingSession* tracing_session) {
-  if (tracing_session->config.builtin_data_sources()
-          .disable_clock_snapshotting()) {
-    return;
-  }
-
-  // We are making an explicit copy of the latest snapshot (if it exists)
-  // because SnapshotClocks reads this data and computes the drift based on its
-  // content. If the clock drift is high enough, it will update the contents of
-  // |snapshot| and return true. Otherwise, it will return false.
-  TracingSession::ClockSnapshotData snapshot =
-      tracing_session->clock_snapshot_ring_buffer.empty()
-          ? TracingSession::ClockSnapshotData()
-          : tracing_session->clock_snapshot_ring_buffer.back();
-  bool did_update = SnapshotClocks(&snapshot);
-  if (did_update) {
-    // This means clocks drifted enough since last snapshot. See the comment
-    // in SnapshotClocks.
-    auto* snapshot_buffer = &tracing_session->clock_snapshot_ring_buffer;
-
-    // Erase before emplacing to prevent a unncessary doubling of memory if
-    // not needed.
-    static constexpr uint32_t kClockSnapshotRingBufferSize = 16;
-    if (snapshot_buffer->size() >= kClockSnapshotRingBufferSize) {
-      snapshot_buffer->erase_front(1 + snapshot_buffer->size() -
-                                   kClockSnapshotRingBufferSize);
-    }
-    snapshot_buffer->emplace_back(std::move(snapshot));
-  }
-}
-
-// Returns true when the data in |snapshot_data| is updated with the new state
-// of the clocks and false otherwise.
-bool TracingServiceImpl::SnapshotClocks(
+void TracingServiceImpl::SnapshotClocks(
     TracingSession::ClockSnapshotData* snapshot_data) {
   // Minimum drift that justifies replacing a prior clock snapshot that hasn't
   // been emitted into the trace yet (see comment below).
@@ -2856,8 +2456,8 @@
 
   TracingSession::ClockSnapshotData new_snapshot_data;
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&   \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&    \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
   struct {
     clockid_t id;
@@ -2887,7 +2487,9 @@
         static_cast<uint32_t>(clock.type),
         static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count())));
   }
-#else  // OS_APPLE || OS_WIN && OS_NACL
+#else   // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) &&
+        // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&
+        // !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
   auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
   // The default trace clock is boot time, so we always need to emit a path to
   // it. However since we don't actually have a boot time source on these
@@ -2896,7 +2498,9 @@
       std::make_pair(protos::pbzero::BUILTIN_CLOCK_BOOTTIME, wall_time_ns));
   new_snapshot_data.push_back(
       std::make_pair(protos::pbzero::BUILTIN_CLOCK_MONOTONIC, wall_time_ns));
-#endif
+#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) &&
+        // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&
+        // !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
 
   // If we're about to update a session's latest clock snapshot that hasn't been
   // emitted into the trace yet, check whether the clocks have drifted enough to
@@ -2930,22 +2534,27 @@
       }
     }
     if (!update_snapshot)
-      return false;
+      return;
     snapshot_data->clear();
   }
 
   *snapshot_data = std::move(new_snapshot_data);
-  return true;
 }
 
 void TracingServiceImpl::EmitClockSnapshot(
     TracingSession* tracing_session,
     TracingSession::ClockSnapshotData snapshot_data,
+    bool set_root_timestamp,
     std::vector<TracePacket>* packets) {
-  PERFETTO_DCHECK(!tracing_session->config.builtin_data_sources()
-                       .disable_clock_snapshotting());
-
   protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+  if (set_root_timestamp) {
+    // First timestamp from the snapshot is the default time domain (BOOTTIME on
+    // systems that support it, or walltime otherwise).
+    PERFETTO_DCHECK(snapshot_data[0].first ==
+                    protos::gen::BUILTIN_CLOCK_BOOTTIME);
+    packet->set_timestamp(snapshot_data[0].second);
+  }
+
   auto* snapshot = packet->set_clock_snapshot();
 
   protos::gen::BuiltinClock trace_clock =
@@ -2966,28 +2575,8 @@
   SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
-void TracingServiceImpl::EmitSyncMarker(std::vector<TracePacket>* packets) {
-  // The sync marks are used to tokenize large traces efficiently.
-  // See description in trace_packet.proto.
-  if (sync_marker_packet_size_ == 0) {
-    // The marker ABI expects that the marker is written after the uid.
-    // Protozero guarantees that fields are written in the same order of the
-    // calls. The ResynchronizeTraceStreamUsingSyncMarker test verifies the ABI.
-    protozero::StaticBuffered<protos::pbzero::TracePacket> packet(
-        &sync_marker_packet_[0], sizeof(sync_marker_packet_));
-    packet->set_trusted_uid(static_cast<int32_t>(uid_));
-    packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
-
-    // Keep this last.
-    packet->set_synchronization_marker(kSyncMarker, sizeof(kSyncMarker));
-    sync_marker_packet_size_ = packet.Finalize();
-  }
-  packets->emplace_back();
-  packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_);
-}
-
-void TracingServiceImpl::EmitStats(TracingSession* tracing_session,
-                                   std::vector<TracePacket>* packets) {
+void TracingServiceImpl::SnapshotStats(TracingSession* tracing_session,
+                                       std::vector<TracePacket>* packets) {
   protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
   packet->set_trusted_uid(static_cast<int32_t>(uid_));
   packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
@@ -3009,14 +2598,6 @@
   trace_stats.set_patches_discarded(patches_discarded_);
   trace_stats.set_invalid_packets(tracing_session->invalid_packets);
 
-  if (tracing_session->trace_filter) {
-    auto* filt_stats = trace_stats.mutable_filter_stats();
-    filt_stats->set_input_packets(tracing_session->filter_input_packets);
-    filt_stats->set_input_bytes(tracing_session->filter_input_bytes);
-    filt_stats->set_output_bytes(tracing_session->filter_output_bytes);
-    filt_stats->set_errors(tracing_session->filter_errors);
-  }
-
   for (BufferID buf_id : tracing_session->buffers_index) {
     TraceBuffer* buf = GetBufferByID(buf_id);
     if (!buf) {
@@ -3049,7 +2630,7 @@
   tracing_session->did_emit_system_info = true;
   protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
   auto* info = packet->set_system_info();
-  info->set_tracing_service_version(base::GetVersionString());
+  base::ignore_result(info);  // For PERFETTO_OS_WIN.
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
   struct utsname uname_info;
@@ -3075,50 +2656,19 @@
   SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
-void TracingServiceImpl::EmitLifecycleEvents(
+void TracingServiceImpl::MaybeEmitServiceEvents(
     TracingSession* tracing_session,
     std::vector<TracePacket>* packets) {
-  using TimestampedPacket =
-      std::pair<int64_t /* ts */, std::vector<uint8_t> /* serialized packet */>;
-
-  std::vector<TimestampedPacket> timestamped_packets;
-  for (auto& event : tracing_session->lifecycle_events) {
-    for (int64_t ts : event.timestamps) {
-      protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
-      packet->set_timestamp(static_cast<uint64_t>(ts));
-      packet->set_trusted_uid(static_cast<int32_t>(uid_));
-      packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
-
-      auto* service_event = packet->set_service_event();
-      service_event->AppendVarInt(event.field_id, 1);
-      timestamped_packets.emplace_back(ts, packet.SerializeAsArray());
-    }
-    event.timestamps.clear();
+  int64_t all_start_ns = tracing_session->time_all_data_source_started.count();
+  if (!tracing_session->did_emit_all_data_source_started && all_start_ns > 0) {
+    tracing_session->did_emit_all_data_source_started = true;
+    protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+    packet->set_timestamp(static_cast<uint64_t>(all_start_ns));
+    packet->set_trusted_uid(static_cast<int32_t>(uid_));
+    packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+    packet->set_service_event()->set_all_data_sources_started(true);
+    SerializeAndAppendPacket(packets, packet.SerializeAsArray());
   }
-
-  // We sort by timestamp here to ensure that the "sequence" of lifecycle
-  // packets has monotonic timestamps like other sequences in the trace.
-  // Note that these events could still be out of order with respect to other
-  // events on the service packet sequence (e.g. trigger received packets).
-  std::sort(timestamped_packets.begin(), timestamped_packets.end(),
-            [](const TimestampedPacket& a, const TimestampedPacket& b) {
-              return a.first < b.first;
-            });
-
-  for (const auto& pair : timestamped_packets)
-    SerializeAndAppendPacket(packets, std::move(pair.second));
-}
-
-void TracingServiceImpl::EmitSeizedForBugreportLifecycleEvent(
-    std::vector<TracePacket>* packets) {
-  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
-  packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
-  packet->set_trusted_uid(static_cast<int32_t>(uid_));
-  packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
-  auto* service_event = packet->set_service_event();
-  service_event->AppendVarInt(
-      protos::pbzero::TracingServiceEvent::kSeizedForBugreportFieldNumber, 1);
-  SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
 void TracingServiceImpl::MaybeEmitReceivedTriggers(
@@ -3143,131 +2693,6 @@
   }
 }
 
-bool TracingServiceImpl::MaybeSaveTraceForBugreport(
-    std::function<void()> callback) {
-  TracingSession* max_session = nullptr;
-  TracingSessionID max_tsid = 0;
-  for (auto& session_id_and_session : tracing_sessions_) {
-    auto& session = session_id_and_session.second;
-    const int32_t score = session.config.bugreport_score();
-    // Exclude sessions with 0 (or below) score. By default tracing sessions
-    // should NOT be eligible to be attached to bugreports.
-    if (score <= 0 || session.state != TracingSession::STARTED)
-      continue;
-
-    // Also don't try to steal long traces with write_into_file if their content
-    // has been already partially written into a file, as we would get partial
-    // traces on both sides. We can't just copy the original file into the
-    // bugreport because the file could be too big (GBs) for bugreports.
-    // The only case where it's legit to steal traces with write_into_file, is
-    // when the consumer specified a very large write_period_ms (e.g. 24h),
-    // meaning that this is effectively a ring-buffer trace. Traceur (the
-    // Android System Tracing app), which uses --detach, does this to have a
-    // consistent invocation path for long-traces and ring-buffer-mode traces.
-    if (session.write_into_file && session.bytes_written_into_file > 0)
-      continue;
-
-    // If we are already in the process of finalizing another trace for
-    // bugreport, don't even start another one, as they would try to write onto
-    // the same file.
-    if (session.on_disable_callback_for_bugreport)
-      return false;
-
-    if (!max_session || score > max_session->config.bugreport_score()) {
-      max_session = &session;
-      max_tsid = session_id_and_session.first;
-    }
-  }
-
-  // No eligible trace found.
-  if (!max_session)
-    return false;
-
-  PERFETTO_LOG("Seizing trace for bugreport. tsid:%" PRIu64
-               " state:%d wf:%d score:%d name:\"%s\"",
-               max_tsid, max_session->state, !!max_session->write_into_file,
-               max_session->config.bugreport_score(),
-               max_session->config.unique_session_name().c_str());
-
-  auto br_fd = CreateTraceFile(GetBugreportTmpPath(), /*overwrite=*/true);
-  if (!br_fd)
-    return false;
-
-  if (max_session->write_into_file) {
-    auto fd = *max_session->write_into_file;
-    // If we are stealing a write_into_file session, add a marker that explains
-    // why the trace has been stolen rather than creating an empty file. This is
-    // only for write_into_file traces. A similar code path deals with the case
-    // of reading-back a seized trace from IPC in ReadBuffers().
-    if (!max_session->config.builtin_data_sources().disable_service_events()) {
-      std::vector<TracePacket> packets;
-      EmitSeizedForBugreportLifecycleEvent(&packets);
-      for (auto& packet : packets) {
-        char* preamble;
-        size_t preamble_size = 0;
-        std::tie(preamble, preamble_size) = packet.GetProtoPreamble();
-        base::WriteAll(fd, preamble, preamble_size);
-        for (const Slice& slice : packet.slices()) {
-          base::WriteAll(fd, slice.start, slice.size);
-        }
-      }  // for (packets)
-    }    // if (!disable_service_events())
-  }      // if (max_session->write_into_file)
-  max_session->write_into_file = std::move(br_fd);
-  max_session->on_disable_callback_for_bugreport = std::move(callback);
-  max_session->seized_for_bugreport = true;
-
-  // Post a task to avoid that early FlushAndDisableTracing() failures invoke
-  // the callback before we return. That would re-enter in a weird way the
-  // callstack of the calling ConsumerEndpointImpl::SaveTraceForBugreport().
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_this, max_tsid] {
-    if (weak_this)
-      weak_this->FlushAndDisableTracing(max_tsid);
-  });
-  return true;
-}
-
-void TracingServiceImpl::MaybeLogUploadEvent(const TraceConfig& cfg,
-                                             PerfettoStatsdAtom atom,
-                                             const std::string& trigger_name) {
-  if (!ShouldLogEvent(cfg))
-    return;
-
-  // If the UUID is not set for some reason, don't log anything.
-  if (cfg.trace_uuid_lsb() == 0 && cfg.trace_uuid_msb() == 0)
-    return;
-
-  android_stats::MaybeLogUploadEvent(atom, cfg.trace_uuid_lsb(),
-                                     cfg.trace_uuid_msb(), trigger_name);
-}
-
-void TracingServiceImpl::MaybeLogTriggerEvent(const TraceConfig& cfg,
-                                              PerfettoTriggerAtom atom,
-                                              const std::string& trigger_name) {
-  if (!ShouldLogEvent(cfg))
-    return;
-  android_stats::MaybeLogTriggerEvent(atom, trigger_name);
-}
-
-size_t TracingServiceImpl::PurgeExpiredAndCountTriggerInWindow(
-    int64_t now_ns,
-    uint64_t trigger_name_hash) {
-  PERFETTO_DCHECK(
-      std::is_sorted(trigger_history_.begin(), trigger_history_.end()));
-  size_t remove_count = 0;
-  size_t trigger_count = 0;
-  for (const TriggerHistory& h : trigger_history_) {
-    if (h.timestamp_ns < now_ns - trigger_window_ns_) {
-      remove_count++;
-    } else if (h.name_hash == trigger_name_hash) {
-      trigger_count++;
-    }
-  }
-  trigger_history_.erase_front(remove_count);
-  return trigger_count;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // TracingServiceImpl::ConsumerEndpointImpl implementation
 ////////////////////////////////////////////////////////////////////////////////
@@ -3288,13 +2713,12 @@
   consumer_->OnDisconnect();
 }
 
-void TracingServiceImpl::ConsumerEndpointImpl::NotifyOnTracingDisabled(
-    const std::string& error) {
+void TracingServiceImpl::ConsumerEndpointImpl::NotifyOnTracingDisabled() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  task_runner_->PostTask([weak_this, error /* deliberate copy */] {
+  auto weak_this = GetWeakPtr();
+  task_runner_->PostTask([weak_this] {
     if (weak_this)
-      weak_this->consumer_->OnTracingDisabled(error);
+      weak_this->consumer_->OnTracingDisabled();
   });
 }
 
@@ -3302,9 +2726,8 @@
     const TraceConfig& cfg,
     base::ScopedFile fd) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto status = service_->EnableTracing(this, cfg, std::move(fd));
-  if (!status.ok())
-    NotifyOnTracingDisabled(status.message());
+  if (!service_->EnableTracing(this, cfg, std::move(fd)))
+    NotifyOnTracingDisabled();
 }
 
 void TracingServiceImpl::ConsumerEndpointImpl::ChangeTraceConfig(
@@ -3371,7 +2794,7 @@
 void TracingServiceImpl::ConsumerEndpointImpl::Detach(const std::string& key) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   bool success = service_->DetachConsumer(this, key);
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  auto weak_this = GetWeakPtr();
   task_runner_->PostTask([weak_this, success] {
     if (weak_this)
       weak_this->consumer_->OnDetach(success);
@@ -3381,7 +2804,7 @@
 void TracingServiceImpl::ConsumerEndpointImpl::Attach(const std::string& key) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   bool success = service_->AttachConsumer(this, key);
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  auto weak_this = GetWeakPtr();
   task_runner_->PostTask([weak_this, success] {
     if (!weak_this)
       return;
@@ -3405,7 +2828,7 @@
     success = true;
     stats = service_->GetTraceStats(session);
   }
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  auto weak_this = GetWeakPtr();
   task_runner_->PostTask([weak_this, success, stats] {
     if (weak_this)
       weak_this->consumer_->OnTraceStats(success, stats);
@@ -3471,12 +2894,18 @@
   observable_events->set_all_data_sources_started(true);
 }
 
+base::WeakPtr<TracingServiceImpl::ConsumerEndpointImpl>
+TracingServiceImpl::ConsumerEndpointImpl::GetWeakPtr() {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
 ObservableEvents*
 TracingServiceImpl::ConsumerEndpointImpl::AddObservableEvents() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   if (!observable_events_) {
     observable_events_.reset(new ObservableEvents());
-    auto weak_this = weak_ptr_factory_.GetWeakPtr();
+    auto weak_this = GetWeakPtr();
     task_runner_->PostTask([weak_this] {
       if (!weak_this)
         return;
@@ -3495,7 +2924,6 @@
   TracingServiceState svc_state;
 
   const auto& sessions = service_->tracing_sessions_;
-  svc_state.set_tracing_service_version(base::GetVersionString());
   svc_state.set_num_sessions(static_cast<int>(sessions.size()));
 
   int num_started = 0;
@@ -3507,7 +2935,6 @@
     auto* producer = svc_state.add_producers();
     producer->set_id(static_cast<int>(kv.first));
     producer->set_name(kv.second->name_);
-    producer->set_sdk_version(kv.second->sdk_version_);
     producer->set_uid(static_cast<int32_t>(producer->uid()));
   }
 
@@ -3535,25 +2962,6 @@
   callback(caps);
 }
 
-void TracingServiceImpl::ConsumerEndpointImpl::SaveTraceForBugreport(
-    SaveTraceForBugreportCallback consumer_callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto on_complete_callback = [consumer_callback] {
-    if (rename(GetBugreportTmpPath().c_str(), GetBugreportPath().c_str())) {
-      consumer_callback(false, "rename(" + GetBugreportTmpPath() + ", " +
-                                   GetBugreportPath() + ") failed (" +
-                                   strerror(errno) + ")");
-    } else {
-      consumer_callback(true, GetBugreportPath());
-    }
-  };
-  if (!service_->MaybeSaveTraceForBugreport(std::move(on_complete_callback))) {
-    consumer_callback(false,
-                      "No trace with TraceConfig.bugreport_score > 0 eligible "
-                      "for bug reporting was found");
-  }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // TracingServiceImpl::ProducerEndpointImpl implementation
 ////////////////////////////////////////////////////////////////////////////////
@@ -3565,7 +2973,6 @@
     base::TaskRunner* task_runner,
     Producer* producer,
     const std::string& producer_name,
-    const std::string& sdk_version,
     bool in_process,
     bool smb_scraping_enabled)
     : id_(id),
@@ -3574,7 +2981,6 @@
       task_runner_(task_runner),
       producer_(producer),
       name_(producer_name),
-      sdk_version_(sdk_version),
       in_process_(in_process),
       smb_scraping_enabled_(smb_scraping_enabled),
       weak_ptr_factory_(this) {}
@@ -3696,7 +3102,6 @@
     inproc_shmem_arbiter_.reset(new SharedMemoryArbiterImpl(
         shared_memory_->start(), shared_memory_->size(),
         shared_buffer_page_size_kb_ * 1024, this, task_runner_));
-    inproc_shmem_arbiter_->SetDirectSMBPatchingSupportedByService();
   }
 
   OnTracingSetup();
@@ -3854,19 +3259,10 @@
 TracingServiceImpl::TracingSession::TracingSession(
     TracingSessionID session_id,
     ConsumerEndpointImpl* consumer,
-    const TraceConfig& new_config,
-    base::TaskRunner* task_runner)
+    const TraceConfig& new_config)
     : id(session_id),
       consumer_maybe_null(consumer),
       consumer_uid(consumer->uid_),
-      config(new_config),
-      snapshot_periodic_task(task_runner) {
-  // all_data_sources_flushed is special because we store up to 64 events of
-  // this type. Other events will go through the default case in
-  // SnapshotLifecycleEvent() where they will be given a max history of 1.
-  lifecycle_events.emplace_back(
-      protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
-      64 /* max_size */);
-}
+      config(new_config) {}
 
 }  // namespace perfetto
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 401aaa1..f05dfeb 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -22,17 +22,13 @@
 #include <map>
 #include <memory>
 #include <mutex>
-#include <random>
 #include <set>
 #include <utility>
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/base/status.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/circular_queue.h"
 #include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/periodic_task.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"
@@ -44,13 +40,8 @@
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/forward_decls.h"
 #include "perfetto/tracing/core/trace_config.h"
-#include "src/android_stats/perfetto_atoms.h"
 #include "src/tracing/core/id_allocator.h"
 
-namespace protozero {
-class MessageFilter;
-}
-
 namespace perfetto {
 
 namespace base {
@@ -70,7 +61,7 @@
   struct DataSourceInstance;
 
  public:
-  static constexpr size_t kDefaultShmPageSize = 4096ul;
+  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;
@@ -87,7 +78,6 @@
                          base::TaskRunner*,
                          Producer*,
                          const std::string& producer_name,
-                         const std::string& sdk_version,
                          bool in_process,
                          bool smb_scraping_enabled);
     ~ProducerEndpointImpl() override;
@@ -155,7 +145,6 @@
     size_t shmem_page_size_hint_bytes_ = 0;
     bool is_shmem_provided_by_producer_ = false;
     const std::string name_;
-    std::string sdk_version_;
     bool in_process_;
     bool smb_scraping_enabled_;
 
@@ -190,7 +179,8 @@
                          uid_t uid);
     ~ConsumerEndpointImpl() override;
 
-    void NotifyOnTracingDisabled(const std::string& error);
+    void NotifyOnTracingDisabled();
+    base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr();
 
     // TracingService::ConsumerEndpoint implementation.
     void EnableTracing(const TraceConfig&, base::ScopedFile) override;
@@ -206,7 +196,6 @@
     void ObserveEvents(uint32_t enabled_event_types) override;
     void QueryServiceState(QueryServiceStateCallback) override;
     void QueryCapabilities(QueryCapabilitiesCallback) override;
-    void SaveTraceForBugreport(SaveTraceForBugreportCallback) override;
 
     // Will queue a task to notify the consumer about the state change.
     void OnDataSourceInstanceStateChange(const ProducerEndpointImpl&,
@@ -269,12 +258,12 @@
   bool DetachConsumer(ConsumerEndpointImpl*, const std::string& key);
   bool AttachConsumer(ConsumerEndpointImpl*, const std::string& key);
   void DisconnectConsumer(ConsumerEndpointImpl*);
-  base::Status EnableTracing(ConsumerEndpointImpl*,
-                             const TraceConfig&,
-                             base::ScopedFile);
+  bool EnableTracing(ConsumerEndpointImpl*,
+                     const TraceConfig&,
+                     base::ScopedFile);
   void ChangeTraceConfig(ConsumerEndpointImpl*, const TraceConfig&);
 
-  base::Status StartTracing(TracingSessionID);
+  bool StartTracing(TracingSessionID);
   void DisableTracing(TracingSessionID, bool disable_immediately = false);
   void Flush(TracingSessionID tsid,
              uint32_t timeout_ms,
@@ -293,8 +282,7 @@
       ProducerSMBScrapingMode smb_scraping_mode =
           ProducerSMBScrapingMode::kDefault,
       size_t shared_memory_page_size_hint_bytes = 0,
-      std::unique_ptr<SharedMemory> shm = nullptr,
-      const std::string& sdk_version = {}) override;
+      std::unique_ptr<SharedMemory> shm = nullptr) override;
 
   std::unique_ptr<TracingService::ConsumerEndpoint> ConnectConsumer(
       Consumer*,
@@ -314,17 +302,6 @@
   friend class TracingServiceImplTest;
   friend class TracingIntegrationTest;
 
-  static constexpr int64_t kOneDayInNs = 24ll * 60 * 60 * 1000 * 1000 * 1000;
-
-  struct TriggerHistory {
-    int64_t timestamp_ns;
-    uint64_t name_hash;
-
-    bool operator<(const TriggerHistory& other) const {
-      return timestamp_ns < other.timestamp_ns;
-    }
-  };
-
   struct RegisteredDataSource {
     ProducerID producer_id;
     DataSourceDescriptor descriptor;
@@ -381,20 +358,14 @@
       DISABLING_WAITING_STOP_ACKS
     };
 
-    TracingSession(TracingSessionID,
-                   ConsumerEndpointImpl*,
-                   const TraceConfig&,
-                   base::TaskRunner*);
-    TracingSession(TracingSession&&) = delete;
-    TracingSession& operator=(TracingSession&&) = delete;
+    TracingSession(TracingSessionID, ConsumerEndpointImpl*, const TraceConfig&);
 
     size_t num_buffers() const { return buffers_index.size(); }
 
     uint32_t delay_to_next_write_period_ms() const {
       PERFETTO_DCHECK(write_period_ms > 0);
       return write_period_ms -
-             static_cast<uint32_t>(base::GetWallTimeMs().count() %
-                                   write_period_ms);
+             (base::GetWallTimeMs().count() % write_period_ms);
     }
 
     uint32_t flush_timeout_ms() {
@@ -520,43 +491,23 @@
     // Packets that failed validation of the TrustedPacket.
     uint64_t invalid_packets = 0;
 
-    // Set to true on the first call to MaybeNotifyAllDataSourcesStarted().
+    // Set to true on the first call to OnAllDataSourcesStarted().
     bool did_notify_all_data_source_started = false;
-
-    // Stores all lifecycle events of a particular type (i.e. associated with a
-    // single field id in the TracingServiceEvent proto).
-    struct LifecycleEvent {
-      LifecycleEvent(uint32_t f_id, uint32_t m_size = 1)
-          : field_id(f_id), max_size(m_size), timestamps(m_size) {}
-
-      // The field id of the event in the TracingServiceEvent proto.
-      uint32_t field_id;
-
-      // Stores the max size of |timestamps|. Set to 1 by default (in
-      // the constructor) but can be overriden in TraceSession constructor
-      // if a larger size is required.
-      uint32_t max_size;
-
-      // Stores the timestamps emitted for each event type (in nanoseconds).
-      // Emitted into the trace and cleared when the consumer next calls
-      // ReadBuffers.
-      base::CircularQueue<int64_t> timestamps;
-    };
-    std::vector<LifecycleEvent> lifecycle_events;
+    bool did_emit_all_data_source_started = false;
+    base::TimeNanos time_all_data_source_started = {};
 
     using ClockSnapshotData =
         std::vector<std::pair<uint32_t /*clock_id*/, uint64_t /*ts*/>>;
 
     // Initial clock snapshot, captured at trace start time (when state goes to
     // TracingSession::STARTED). Emitted into the trace when the consumer first
-    // calls ReadBuffers().
-    ClockSnapshotData initial_clock_snapshot;
+    // begins reading the trace.
+    ClockSnapshotData initial_clock_snapshot_;
 
-    // Stores clock snapshots to emit into the trace as a ring buffer. This
-    // buffer is populated both periodically and when lifecycle events happen
-    // but only when significant clock drift is detected. Emitted into the trace
-    // and cleared when the consumer next calls ReadBuffers().
-    base::CircularQueue<ClockSnapshotData> clock_snapshot_ring_buffer;
+    // Most recent clock snapshot, captured periodically after the trace was
+    // started. Emitted into the trace when the consumer next calls
+    // ReadBuffers().
+    ClockSnapshotData last_clock_snapshot_;
 
     State state = DISABLED;
 
@@ -572,22 +523,6 @@
     uint32_t write_period_ms = 0;
     uint64_t max_file_size_bytes = 0;
     uint64_t bytes_written_into_file = 0;
-
-    // Set when using SaveTraceForBugreport(). This callback will be called
-    // when the tracing session ends and the data has been saved into the file.
-    std::function<void()> on_disable_callback_for_bugreport;
-    bool seized_for_bugreport = false;
-
-    // Periodic task for snapshotting service events (e.g. clocks, sync markers
-    // etc)
-    base::PeriodicTask snapshot_periodic_task;
-
-    // When non-NULL the packets should be post-processed using the filter.
-    std::unique_ptr<protozero::MessageFilter> trace_filter;
-    uint64_t filter_input_packets = 0;
-    uint64_t filter_input_bytes = 0;
-    uint64_t filter_output_bytes = 0;
-    uint64_t filter_errors = 0;
   };
 
   TracingServiceImpl(const TracingServiceImpl&) = delete;
@@ -613,32 +548,28 @@
   // shared memory and trace buffers.
   void UpdateMemoryGuardrail();
 
-  void StartDataSourceInstance(ProducerEndpointImpl*,
-                               TracingSession*,
-                               DataSourceInstance*);
-  void StopDataSourceInstance(ProducerEndpointImpl*,
-                              TracingSession*,
-                              DataSourceInstance*,
+  void StartDataSourceInstance(ProducerEndpointImpl* producer,
+                               TracingSession* tracing_session,
+                               DataSourceInstance* instance);
+  void StopDataSourceInstance(ProducerEndpointImpl* producer,
+                              TracingSession* tracing_session,
+                              DataSourceInstance* instance,
                               bool disable_immediately);
-  void PeriodicSnapshotTask(TracingSessionID);
-  void MaybeSnapshotClocksIntoRingBuffer(TracingSession*);
-  bool SnapshotClocks(TracingSession::ClockSnapshotData*);
-  void SnapshotLifecyleEvent(TracingSession*,
-                             uint32_t field_id,
-                             bool snapshot_clocks);
-  void EmitClockSnapshot(TracingSession*,
+  void PeriodicSnapshotTask(TracingSession* tracing_session,
+                            bool is_initial_snapshot);
+  void SnapshotSyncMarker(std::vector<TracePacket>*);
+  void SnapshotClocks(TracingSession::ClockSnapshotData*);
+  void EmitClockSnapshot(TracingSession* tracing_session,
                          TracingSession::ClockSnapshotData,
+                         bool set_root_timestamp,
                          std::vector<TracePacket>*);
-  void EmitSyncMarker(std::vector<TracePacket>*);
-  void EmitStats(TracingSession*, std::vector<TracePacket>*);
-  TraceStats GetTraceStats(TracingSession*);
-  void EmitLifecycleEvents(TracingSession*, std::vector<TracePacket>*);
-  void EmitSeizedForBugreportLifecycleEvent(std::vector<TracePacket>*);
+  void SnapshotStats(TracingSession*, std::vector<TracePacket>*);
+  TraceStats GetTraceStats(TracingSession* tracing_session);
+  void MaybeEmitServiceEvents(TracingSession*, std::vector<TracePacket>*);
   void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*);
   void MaybeEmitSystemInfo(TracingSession*, std::vector<TracePacket>*);
   void MaybeEmitReceivedTriggers(TracingSession*, std::vector<TracePacket>*);
   void MaybeNotifyAllDataSourcesStarted(TracingSession*);
-  bool MaybeSaveTraceForBugreport(std::function<void()> callback);
   void OnFlushTimeout(TracingSessionID, FlushRequestID);
   void OnDisableTracingTimeout(TracingSessionID);
   void DisableTracingNotifyConsumerAndFlushFile(TracingSession*);
@@ -646,18 +577,11 @@
   void CompleteFlush(TracingSessionID tsid,
                      ConsumerEndpoint::FlushCallback callback,
                      bool success);
-  void ScrapeSharedMemoryBuffers(TracingSession*, ProducerEndpointImpl*);
+  void ScrapeSharedMemoryBuffers(TracingSession* tracing_session,
+                                 ProducerEndpointImpl* producer);
   void PeriodicClearIncrementalStateTask(TracingSessionID, bool post_next_only);
   TraceBuffer* GetBufferByID(BufferID);
   void OnStartTriggersTimeout(TracingSessionID tsid);
-  void MaybeLogUploadEvent(const TraceConfig&,
-                           PerfettoStatsdAtom atom,
-                           const std::string& trigger_name = "");
-  void MaybeLogTriggerEvent(const TraceConfig&,
-                            PerfettoTriggerAtom atom,
-                            const std::string& trigger_name);
-  size_t PurgeExpiredAndCountTriggerInWindow(int64_t now_ns,
-                                             uint64_t trigger_name_hash);
 
   base::TaskRunner* const task_runner_;
   std::unique_ptr<SharedMemory::Factory> shm_factory_;
@@ -678,19 +602,9 @@
   std::map<BufferID, std::unique_ptr<TraceBuffer>> buffers_;
   std::map<std::string, int64_t> session_to_last_trace_s_;
 
-  // Contains timestamps of triggers.
-  // The queue is sorted by timestamp and invocations older than
-  // |trigger_window_ns_| are purged when a trigger happens.
-  base::CircularQueue<TriggerHistory> trigger_history_;
-
   bool smb_scraping_enabled_ = false;
   bool lockdown_mode_ = false;
-  uint32_t min_write_period_ms_ = 100;       // Overridable for testing.
-  int64_t trigger_window_ns_ = kOneDayInNs;  // Overridable for testing.
-
-  std::minstd_rand trigger_probability_rand_;
-  std::uniform_real_distribution<> trigger_probability_dist_;
-  double trigger_rnd_override_for_testing_ = 0;  // Overridable for testing.
+  uint32_t min_write_period_ms_ = 100;  // Overridable for testing.
 
   uint8_t sync_marker_packet_[32];  // Lazily initialized.
   size_t sync_marker_packet_size_ = 0;
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index bd4062a..4ad5f30 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -62,7 +62,6 @@
 using ::testing::Property;
 using ::testing::StrictMock;
 using ::testing::StringMatchResultListener;
-using ::testing::StrNe;
 
 namespace perfetto {
 
@@ -195,14 +194,6 @@
                    name.c_str());
   }
 
-  void SetTriggerWindowNs(int64_t window_ns) {
-    svc->trigger_window_ns_ = window_ns;
-  }
-
-  void OverrideNextTriggerRandomNumber(double number) {
-    svc->trigger_rnd_override_for_testing_ = number;
-  }
-
   base::TestTaskRunner task_runner;
   std::unique_ptr<TracingServiceImpl> svc;
 };
@@ -715,18 +706,16 @@
   auto checkpoint_name = "on_tracing_disabled_consumer_1_and_2";
   auto on_tracing_disabled = task_runner.CreateCheckpoint(checkpoint_name);
   std::atomic<size_t> counter(0);
-  EXPECT_CALL(*consumer_1, OnTracingDisabled(_))
-      .WillOnce(InvokeWithoutArgs([&]() {
-        if (++counter == 2u) {
-          on_tracing_disabled();
-        }
-      }));
-  EXPECT_CALL(*consumer_2, OnTracingDisabled(_))
-      .WillOnce(InvokeWithoutArgs([&]() {
-        if (++counter == 2u) {
-          on_tracing_disabled();
-        }
-      }));
+  EXPECT_CALL(*consumer_1, OnTracingDisabled()).WillOnce(Invoke([&]() {
+    if (++counter == 2u) {
+      on_tracing_disabled();
+    }
+  }));
+  EXPECT_CALL(*consumer_2, OnTracingDisabled()).WillOnce(Invoke([&]() {
+    if (++counter == 2u) {
+      on_tracing_disabled();
+    }
+  }));
 
   EXPECT_CALL(*producer, StopDataSource(id1));
   EXPECT_CALL(*producer, StopDataSource(id2));
@@ -1170,237 +1159,12 @@
       HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
 }
 
-TEST_F(TracingServiceImplTest, SecondTriggerHitsLimit) {
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(128);
-
-  auto* trigger_config = trace_config.mutable_trigger_config();
-  trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
-  trigger_config->set_trigger_timeout_ms(8.64e+7);
-
-  auto* trigger = trigger_config->add_triggers();
-  trigger->set_name("trigger_name");
-  trigger->set_stop_delay_ms(1);
-  trigger->set_max_per_24_h(1);
-
-  auto* ds = trace_config.add_data_sources()->mutable_config();
-
-  // First session.
-  {
-    std::unique_ptr<MockProducer> producer = CreateMockProducer();
-    producer->Connect(svc.get(), "mock_producer_a");
-    producer->RegisterDataSource("data_source_a");
-
-    std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-    consumer->Connect(svc.get());
-
-    ds->set_name("data_source_a");
-    consumer->EnableTracing(trace_config);
-    producer->WaitForTracingSetup();
-
-    producer->WaitForDataSourceSetup("data_source_a");
-    producer->WaitForDataSourceStart("data_source_a");
-
-    std::vector<std::string> req;
-    req.push_back("trigger_name");
-    producer->endpoint()->ActivateTriggers(req);
-
-    ASSERT_EQ(1u, tracing_session()->received_triggers.size());
-    EXPECT_EQ("trigger_name",
-              tracing_session()->received_triggers[0].trigger_name);
-
-    auto writer = producer->CreateTraceWriter("data_source_a");
-    producer->WaitForFlush(writer.get());
-
-    producer->WaitForDataSourceStop("data_source_a");
-    consumer->WaitForTracingDisabled();
-    EXPECT_THAT(
-        consumer->ReadBuffers(),
-        HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
-  }
-
-  // Second session.
-  {
-    std::unique_ptr<MockProducer> producer = CreateMockProducer();
-    producer->Connect(svc.get(), "mock_producer_b");
-    producer->RegisterDataSource("data_source_b");
-
-    std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-    consumer->Connect(svc.get());
-
-    ds->set_name("data_source_b");
-    consumer->EnableTracing(trace_config);
-    producer->WaitForTracingSetup();
-
-    producer->WaitForDataSourceSetup("data_source_b");
-    producer->WaitForDataSourceStart("data_source_b");
-
-    std::vector<std::string> req;
-    req.push_back("trigger_name");
-    producer->endpoint()->ActivateTriggers(req);
-
-    ASSERT_EQ(0u, tracing_session()->received_triggers.size());
-
-    consumer->DisableTracing();
-    consumer->FreeBuffers();
-
-    producer->WaitForDataSourceStop("data_source_b");
-    consumer->WaitForTracingDisabled();
-  }
-}
-
-TEST_F(TracingServiceImplTest, SecondTriggerDoesntHitLimit) {
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(128);
-
-  auto* trigger_config = trace_config.mutable_trigger_config();
-  trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
-  trigger_config->set_trigger_timeout_ms(8.64e+7);
-
-  auto* trigger = trigger_config->add_triggers();
-  trigger->set_name("trigger_name");
-  trigger->set_stop_delay_ms(1);
-  trigger->set_max_per_24_h(1);
-
-  auto* ds = trace_config.add_data_sources()->mutable_config();
-
-  // Set the trigger window size to something really small so the second
-  // session is still allowed through.
-  SetTriggerWindowNs(1);
-
-  // First session.
-  {
-    std::unique_ptr<MockProducer> producer = CreateMockProducer();
-    producer->Connect(svc.get(), "mock_producer_a");
-    producer->RegisterDataSource("data_source_a");
-
-    std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-    consumer->Connect(svc.get());
-
-    ds->set_name("data_source_a");
-    consumer->EnableTracing(trace_config);
-    producer->WaitForTracingSetup();
-
-    producer->WaitForDataSourceSetup("data_source_a");
-    producer->WaitForDataSourceStart("data_source_a");
-
-    std::vector<std::string> req;
-    req.push_back("trigger_name");
-    producer->endpoint()->ActivateTriggers(req);
-
-    ASSERT_EQ(1u, tracing_session()->received_triggers.size());
-    EXPECT_EQ("trigger_name",
-              tracing_session()->received_triggers[0].trigger_name);
-
-    auto writer = producer->CreateTraceWriter("data_source_a");
-    producer->WaitForFlush(writer.get());
-
-    producer->WaitForDataSourceStop("data_source_a");
-    consumer->WaitForTracingDisabled();
-    EXPECT_THAT(
-        consumer->ReadBuffers(),
-        HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
-  }
-
-  // Sleep 1 micro so that we're sure that the window time would have elapsed.
-  base::SleepMicroseconds(1);
-
-  // Second session.
-  {
-    std::unique_ptr<MockProducer> producer = CreateMockProducer();
-    producer->Connect(svc.get(), "mock_producer_b");
-    producer->RegisterDataSource("data_source_b");
-
-    std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-    consumer->Connect(svc.get());
-
-    ds->set_name("data_source_b");
-    consumer->EnableTracing(trace_config);
-    producer->WaitForTracingSetup();
-
-    producer->WaitForDataSourceSetup("data_source_b");
-    producer->WaitForDataSourceStart("data_source_b");
-
-    std::vector<std::string> req;
-    req.push_back("trigger_name");
-    producer->endpoint()->ActivateTriggers(req);
-
-    ASSERT_EQ(1u, tracing_session()->received_triggers.size());
-    EXPECT_EQ("trigger_name",
-              tracing_session()->received_triggers[0].trigger_name);
-
-    auto writer = producer->CreateTraceWriter("data_source_b");
-    producer->WaitForFlush(writer.get());
-
-    producer->WaitForDataSourceStop("data_source_b");
-    consumer->WaitForTracingDisabled();
-    EXPECT_THAT(
-        consumer->ReadBuffers(),
-        HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
-  }
-}
-
-TEST_F(TracingServiceImplTest, SkipProbability) {
-  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);
-  trace_config.add_data_sources()->mutable_config()->set_name("data_source");
-  auto* trigger_config = trace_config.mutable_trigger_config();
-  trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
-  auto* trigger = trigger_config->add_triggers();
-  trigger->set_name("trigger_name");
-  trigger->set_stop_delay_ms(1);
-  trigger->set_skip_probability(0.15);
-
-  trigger_config->set_trigger_timeout_ms(8.64e+7);
-
-  consumer->EnableTracing(trace_config);
-  producer->WaitForTracingSetup();
-
-  producer->WaitForDataSourceSetup("data_source");
-  producer->WaitForDataSourceStart("data_source");
-
-  std::vector<std::string> req;
-  req.push_back("trigger_name");
-
-  // This is below the probability of 0.15 so should be skipped.
-  OverrideNextTriggerRandomNumber(0.14);
-  producer->endpoint()->ActivateTriggers(req);
-
-  ASSERT_EQ(0u, tracing_session()->received_triggers.size());
-
-  // This is above the probaility of 0.15 so should be allowed.
-  OverrideNextTriggerRandomNumber(0.16);
-  producer->endpoint()->ActivateTriggers(req);
-
-  auto writer = producer->CreateTraceWriter("data_source");
-  producer->WaitForFlush(writer.get());
-
-  ASSERT_EQ(1u, tracing_session()->received_triggers.size());
-  EXPECT_EQ("trigger_name",
-            tracing_session()->received_triggers[0].trigger_name);
-
-  producer->WaitForDataSourceStop("data_source");
-  consumer->WaitForTracingDisabled();
-  EXPECT_THAT(
-      consumer->ReadBuffers(),
-      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
-}
-
 TEST_F(TracingServiceImplTest, LockdownMode) {
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());
 
   std::unique_ptr<MockProducer> producer = CreateMockProducer();
-  producer->Connect(svc.get(), "mock_producer_sameuid",
-                    base::GetCurrentUserId());
+  producer->Connect(svc.get(), "mock_producer_sameuid", geteuid());
   producer->RegisterDataSource("data_source");
 
   TraceConfig trace_config;
@@ -1415,9 +1179,8 @@
   producer->WaitForDataSourceStart("data_source");
 
   std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
-  auto x =
-      svc->ConnectProducer(producer_otheruid.get(),
-                           base::GetCurrentUserId() + 1, "mock_producer_ouid");
+  auto x = svc->ConnectProducer(producer_otheruid.get(), geteuid() + 1,
+                                "mock_producer_ouid");
   EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
   task_runner.RunUntilIdle();
   Mock::VerifyAndClearExpectations(producer_otheruid.get());
@@ -1433,8 +1196,7 @@
   producer->WaitForDataSourceStart("data_source");
 
   std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
-  producer_otheruid->Connect(svc.get(), "mock_producer_ouid2",
-                             base::GetCurrentUserId() + 1);
+  producer_otheruid->Connect(svc.get(), "mock_producer_ouid2", geteuid() + 1);
 
   consumer->DisableTracing();
   producer->WaitForDataSourceStop("data_source");
@@ -1627,14 +1389,12 @@
 
   // The preamble packets are:
   // Trace start clock snapshot
-  // Trace most recent clock snapshot
-  // Trace synchronisation
   // Config
   // SystemInfo
-  // Tracing started (TracingServiceEvent)
+  // Trace read clock snapshot
+  // Trace synchronisation
   // All data source started (TracingServiceEvent)
-  // Tracing disabled (TracingServiceEvent)
-  static const int kNumPreamblePackets = 8;
+  static const int kNumPreamblePackets = 6;
   static const int kNumTestPackets = 9;
   static const char kPayload[] = "1234567890abcdef-";
 
@@ -1784,7 +1544,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, base::GetCurrentUserId(),
+    producer[i]->Connect(svc.get(), name, geteuid(),
                          kSizes[i].hint_size_kb * 1024,
                          kSizes[i].hint_page_size_kb * 1024);
     producer[i]->RegisterDataSource("data_source");
@@ -3013,9 +2773,9 @@
   EXPECT_CALL(*producer, SetupDataSource(_, _)).Times(0);
   consumer->EnableTracing(trace_config);
 
-  // The trace is aborted immediately, the default timeout here is just some
-  // slack for the thread ping-pongs for slow devices.
-  consumer->WaitForTracingDisabled();
+  // The trace is aborted immediately, 5s here is just some slack for the thread
+  // ping-pongs for slow devices.
+  consumer->WaitForTracingDisabled(5000);
 }
 
 TEST_F(TracingServiceImplTest, GetTraceStats) {
@@ -3273,40 +3033,6 @@
   }
 }
 
-TEST_F(TracingServiceImplTest,
-       ObserveAllDataSourceStartedWithoutMatchingInstances) {
-  std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-  consumer->Connect(svc.get());
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(128);
-
-  consumer->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
-
-  // EnableTracing() should immediately cause ALL_DATA_SOURCES_STARTED, because
-  // there aren't any matching data sources registered.
-  consumer->EnableTracing(trace_config);
-
-  auto events = consumer->WaitForObservableEvents();
-  ObservableEvents::DataSourceInstanceStateChange change;
-  EXPECT_TRUE(events.all_data_sources_started());
-
-  consumer->DisableTracing();
-  consumer->WaitForTracingDisabled();
-
-  EXPECT_THAT(
-      consumer->ReadBuffers(),
-      Contains(Property(
-          &protos::gen::TracePacket::service_event,
-          Property(&protos::gen::TracingServiceEvent::all_data_sources_started,
-                   Eq(true)))));
-  consumer->FreeBuffers();
-
-  task_runner.RunUntilIdle();
-
-  Mock::VerifyAndClearExpectations(consumer.get());
-}
-
 // Similar to ObserveAllDataSourceStarted, but covers the case of some data
 // sources not supporting the |notify_on_start|.
 TEST_F(TracingServiceImplTest, ObserveAllDataSourceStartedOnlySomeWillAck) {
@@ -3414,121 +3140,6 @@
   }
 }
 
-TEST_F(TracingServiceImplTest, LifecycleEventSmoke) {
-  using TracingServiceEvent = protos::gen::TracingServiceEvent;
-  using TracingServiceEventFnPtr = bool (TracingServiceEvent::*)() const;
-  auto has_lifecycle_field = [](TracingServiceEventFnPtr ptr) {
-    return Contains(Property(&protos::gen::TracePacket::service_event,
-                             Property(ptr, Eq(true))));
-  };
-  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);
-  trace_config.add_data_sources()->mutable_config()->set_name("data_source");
-
-  consumer->EnableTracing(trace_config);
-
-  producer->WaitForTracingSetup();
-  producer->WaitForDataSourceSetup("data_source");
-  producer->WaitForDataSourceStart("data_source");
-  task_runner.RunUntilIdle();
-
-  auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets,
-              has_lifecycle_field(&TracingServiceEvent::tracing_started));
-  EXPECT_THAT(packets, has_lifecycle_field(
-                           &TracingServiceEvent::all_data_sources_started));
-  EXPECT_THAT(packets,
-              has_lifecycle_field(
-                  &TracingServiceEvent::read_tracing_buffers_completed));
-
-  std::unique_ptr<TraceWriter> writer =
-      producer->CreateTraceWriter("data_source");
-  {
-    auto tp = writer->NewTracePacket();
-    tp->set_for_testing()->set_str("payload");
-  }
-
-  auto flush_request = consumer->Flush();
-  producer->WaitForFlush(writer.get());
-  ASSERT_TRUE(flush_request.WaitForReply());
-
-  packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, has_lifecycle_field(
-                           &TracingServiceEvent::all_data_sources_flushed));
-  EXPECT_THAT(packets,
-              has_lifecycle_field(
-                  &TracingServiceEvent::read_tracing_buffers_completed));
-
-  consumer->DisableTracing();
-  producer->WaitForDataSourceStop("data_source");
-  consumer->WaitForTracingDisabled();
-
-  packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets,
-              has_lifecycle_field(&TracingServiceEvent::tracing_disabled));
-  EXPECT_THAT(packets,
-              has_lifecycle_field(
-                  &TracingServiceEvent::read_tracing_buffers_completed));
-}
-
-TEST_F(TracingServiceImplTest, LifecycleMultipleFlushEventsQueued) {
-  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);
-  trace_config.add_data_sources()->mutable_config()->set_name("data_source");
-
-  consumer->EnableTracing(trace_config);
-
-  producer->WaitForTracingSetup();
-  producer->WaitForDataSourceSetup("data_source");
-  producer->WaitForDataSourceStart("data_source");
-  task_runner.RunUntilIdle();
-
-  std::unique_ptr<TraceWriter> writer =
-      producer->CreateTraceWriter("data_source");
-  {
-    auto tp = writer->NewTracePacket();
-    tp->set_for_testing()->set_str("payload");
-  }
-
-  auto flush_request = consumer->Flush();
-  producer->WaitForFlush(writer.get());
-  ASSERT_TRUE(flush_request.WaitForReply());
-
-  {
-    auto tp = writer->NewTracePacket();
-    tp->set_for_testing()->set_str("payload");
-  }
-
-  flush_request = consumer->Flush();
-  producer->WaitForFlush(writer.get());
-  ASSERT_TRUE(flush_request.WaitForReply());
-
-  auto packets = consumer->ReadBuffers();
-  uint32_t count = 0;
-  for (const auto& packet : packets) {
-    count += packet.service_event().all_data_sources_flushed();
-  }
-  ASSERT_EQ(count, 2u);
-
-  consumer->DisableTracing();
-  producer->WaitForDataSourceStop("data_source");
-  consumer->WaitForTracingDisabled();
-}
-
 TEST_F(TracingServiceImplTest, QueryServiceState) {
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());
@@ -3598,15 +3209,14 @@
 
   // Create a bunch of legit sessions (2 uids * 5 sessions).
   for (int i = 0; i < kMaxConcurrentTracingSessionsPerUid * kUids; i++) {
-    start_new_session(/*uid=*/static_cast<uid_t>(i) % kUids);
+    start_new_session(/*uid=*/i % kUids);
   }
 
   // Any other session now should fail for the two uids.
   for (int i = 0; i <= kUids; i++) {
-    auto* consumer = start_new_session(/*uid=*/static_cast<uid_t>(i) % kUids);
+    auto* consumer = start_new_session(/*uid=*/i % kUids);
     auto on_fail = task_runner.CreateCheckpoint("uid_" + std::to_string(i));
-    EXPECT_CALL(*consumer, OnTracingDisabled(StrNe("")))
-        .WillOnce(InvokeWithoutArgs(on_fail));
+    EXPECT_CALL(*consumer, OnTracingDisabled()).WillOnce(Invoke(on_fail));
   }
 
   // Wait for failure (only after both attempts).
diff --git a/src/tracing/debug_annotation.cc b/src/tracing/debug_annotation.cc
index add115a..81e889c 100644
--- a/src/tracing/debug_annotation.cc
+++ b/src/tracing/debug_annotation.cc
@@ -16,15 +16,33 @@
 
 #include "perfetto/tracing/debug_annotation.h"
 
-#include "perfetto/tracing/traced_value.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 
 namespace perfetto {
 
 DebugAnnotation::~DebugAnnotation() = default;
 
-void DebugAnnotation::WriteIntoTracedValue(TracedValue context) const {
-  Add(context.context_);
+namespace internal {
+
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+                          const char* value) {
+  annotation->set_string_value(value);
 }
 
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+                          const std::string& value) {
+  annotation->set_string_value(value);
+}
+
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+                          const void* value) {
+  annotation->set_pointer_value(reinterpret_cast<uint64_t>(value));
+}
+
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+                          const DebugAnnotation& custom_annotation) {
+  custom_annotation.Add(annotation);
+}
+
+}  // namespace internal
 }  // namespace perfetto
diff --git a/src/tracing/interceptor.cc b/src/tracing/interceptor.cc
deleted file mode 100644
index 30d2e3f..0000000
--- a/src/tracing/interceptor.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/tracing/interceptor.h"
-
-#include "perfetto/tracing/internal/tracing_muxer.h"
-
-namespace perfetto {
-
-InterceptorBase::~InterceptorBase() = default;
-InterceptorBase::ThreadLocalState::~ThreadLocalState() = default;
-
-// static
-void InterceptorBase::RegisterImpl(
-    const InterceptorDescriptor& descriptor,
-    std::function<std::unique_ptr<InterceptorBase>()> factory,
-    InterceptorBase::TLSFactory tls_factory,
-    InterceptorBase::TracePacketCallback on_trace_packet) {
-  auto* tracing_impl = internal::TracingMuxer::Get();
-  tracing_impl->RegisterInterceptor(descriptor, factory, tls_factory,
-                                    on_trace_packet);
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/internal/checked_scope.cc b/src/tracing/internal/checked_scope.cc
deleted file mode 100644
index 7de79e2..0000000
--- a/src/tracing/internal/checked_scope.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/checked_scope.h"
-
-#include <utility>
-
-namespace perfetto {
-namespace internal {
-
-#if PERFETTO_DCHECK_IS_ON()
-CheckedScope::CheckedScope(CheckedScope* parent_scope)
-    : parent_scope_(parent_scope) {
-  if (parent_scope_) {
-    PERFETTO_DCHECK(parent_scope_->is_active());
-    parent_scope_->set_is_active(false);
-  }
-}
-
-CheckedScope::~CheckedScope() {
-  Reset();
-}
-
-void CheckedScope::Reset() {
-  if (!is_active_) {
-    // The only case when inactive scope could be destroyed is when Reset() was
-    // called explicitly or the contents of the object were moved away.
-    PERFETTO_DCHECK(deleted_);
-    return;
-  }
-  is_active_ = false;
-  deleted_ = true;
-  if (parent_scope_)
-    parent_scope_->set_is_active(true);
-}
-
-CheckedScope::CheckedScope(CheckedScope&& other) {
-  *this = std::move(other);
-}
-
-CheckedScope& CheckedScope::operator=(CheckedScope&& other) {
-  is_active_ = other.is_active_;
-  parent_scope_ = other.parent_scope_;
-  deleted_ = other.deleted_;
-
-  other.is_active_ = false;
-  other.parent_scope_ = nullptr;
-  other.deleted_ = true;
-
-  return *this;
-}
-#endif
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/in_process_tracing_backend.cc b/src/tracing/internal/in_process_tracing_backend.cc
index 1df0f4b..378185c 100644
--- a/src/tracing/internal/in_process_tracing_backend.cc
+++ b/src/tracing/internal/in_process_tracing_backend.cc
@@ -42,6 +42,7 @@
   ~InProcessShm() override;
   void* start() const override;
   size_t size() const override;
+  int fd() const override;
 
  private:
   base::PagedMemory mem_;
@@ -66,6 +67,10 @@
   return mem_.size();
 }
 
+int InProcessShm::fd() const {
+  return -1;
+}
+
 InProcessShmFactory::~InProcessShmFactory() = default;
 std::unique_ptr<SharedMemory> InProcessShmFactory::CreateSharedMemory(
     size_t size) {
diff --git a/src/tracing/internal/interceptor_trace_writer.cc b/src/tracing/internal/interceptor_trace_writer.cc
deleted file mode 100644
index fed2c9a..0000000
--- a/src/tracing/internal/interceptor_trace_writer.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/tracing/internal/interceptor_trace_writer.h"
-
-#include "perfetto/ext/tracing/core/trace_writer.h"
-
-namespace perfetto {
-namespace internal {
-
-// static
-std::atomic<uint32_t> InterceptorTraceWriter::next_sequence_id_{};
-
-InterceptorTraceWriter::InterceptorTraceWriter(
-    std::unique_ptr<InterceptorBase::ThreadLocalState> tls,
-    InterceptorBase::TracePacketCallback packet_callback,
-    DataSourceStaticState* static_state,
-    uint32_t instance_index)
-    : tls_(std::move(tls)),
-      packet_callback_(std::move(packet_callback)),
-      static_state_(static_state),
-      instance_index_(instance_index),
-      sequence_id_(++next_sequence_id_) {}
-
-InterceptorTraceWriter::~InterceptorTraceWriter() = default;
-
-protozero::MessageHandle<protos::pbzero::TracePacket>
-InterceptorTraceWriter::NewTracePacket() {
-  Flush();
-  auto packet = TraceWriter::TracePacketHandle(cur_packet_.get());
-  packet->set_trusted_packet_sequence_id(sequence_id_);
-  return packet;
-}
-
-void InterceptorTraceWriter::Flush(std::function<void()> callback) {
-  if (!cur_packet_.empty()) {
-    InterceptorBase::TracePacketCallbackArgs args{};
-    args.static_state = static_state_;
-    args.instance_index = instance_index_;
-    args.tls = tls_.get();
-
-    const auto& slices = cur_packet_.GetSlices();
-    if (slices.size() == 1) {
-      // Fast path: the current packet fits into a single slice.
-      auto slice_range = slices.begin()->GetUsedRange();
-      args.packet_data = protozero::ConstBytes{
-          slice_range.begin,
-          static_cast<size_t>(slice_range.end - slice_range.begin)};
-      bytes_written_ += static_cast<uint64_t>(args.packet_data.size);
-      packet_callback_(std::move(args));
-    } else {
-      // Fallback: stitch together multiple slices.
-      auto stitched_data = cur_packet_.SerializeAsArray();
-      args.packet_data =
-          protozero::ConstBytes{stitched_data.data(), stitched_data.size()};
-      bytes_written_ += static_cast<uint64_t>(stitched_data.size());
-      packet_callback_(std::move(args));
-    }
-    cur_packet_.Reset();
-  }
-  if (callback)
-    callback();
-}
-
-uint64_t InterceptorTraceWriter::written() const {
-  return bytes_written_;
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/system_tracing_backend.cc b/src/tracing/internal/system_tracing_backend.cc
index 5aa3493..987f956 100644
--- a/src/tracing/internal/system_tracing_backend.cc
+++ b/src/tracing/internal/system_tracing_backend.cc
@@ -19,7 +19,6 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/tracing/core/tracing_service.h"
-#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"
 
@@ -41,18 +40,17 @@
   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, nullptr,
-      nullptr, ProducerIPCClient::ConnectionFlags::kRetryIfUnreachable);
+      args.shmem_size_hint_bytes, args.shmem_page_size_hint_bytes);
   PERFETTO_CHECK(endpoint);
   return endpoint;
 }
 
 std::unique_ptr<ConsumerEndpoint> SystemTracingBackend::ConnectConsumer(
-    const ConnectConsumerArgs& args) {
-  auto endpoint = ConsumerIPCClient::Connect(GetConsumerSocket(), args.consumer,
-                                             args.task_runner);
-  PERFETTO_CHECK(endpoint);
-  return endpoint;
+    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
diff --git a/src/tracing/internal/system_tracing_backend_fake.cc b/src/tracing/internal/system_tracing_backend_fake.cc
deleted file mode 100644
index 9ca90d0..0000000
--- a/src/tracing/internal/system_tracing_backend_fake.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/tracing/internal/system_tracing_backend.h"
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace internal {
-
-// static
-TracingBackend* SystemTracingBackend::GetInstance() {
-  PERFETTO_FATAL("System tracing not implemented");
-  return nullptr;
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/tracing_backend_fake.cc b/src/tracing/internal/tracing_backend_fake.cc
deleted file mode 100644
index 3c64fed..0000000
--- a/src/tracing/internal/tracing_backend_fake.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_backend_fake.h"
-
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-
-namespace perfetto {
-namespace internal {
-
-namespace {
-
-class UnsupportedProducerEndpoint : public ProducerEndpoint {
- public:
-  UnsupportedProducerEndpoint(Producer* producer, base::TaskRunner* task_runner)
-      : producer_(producer), task_runner_(task_runner) {
-    // The SDK will attempt to reconnect the producer, so instead we allow it
-    // to connect successfully, but never start any sessions.
-    auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
-    task_runner_->PostTask([weak_ptr] {
-      if (weak_ptr)
-        weak_ptr->producer_->OnConnect();
-    });
-  }
-  ~UnsupportedProducerEndpoint() override { producer_->OnDisconnect(); }
-
-  void RegisterDataSource(const DataSourceDescriptor&) override {}
-  void UnregisterDataSource(const std::string& /*name*/) override {}
-
-  void RegisterTraceWriter(uint32_t /*writer_id*/,
-                           uint32_t /*target_buffer*/) override {}
-  void UnregisterTraceWriter(uint32_t /*writer_id*/) override {}
-
-  void CommitData(const CommitDataRequest&,
-                  CommitDataCallback callback = {}) override {
-    callback();
-  }
-
-  SharedMemory* shared_memory() const override { return nullptr; }
-  size_t shared_buffer_page_size_kb() const override { return 0; }
-
-  std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID /*target_buffer*/,
-      BufferExhaustedPolicy = BufferExhaustedPolicy::kDefault) override {
-    return nullptr;
-  }
-
-  SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
-  bool IsShmemProvidedByProducer() const override { return false; }
-
-  void NotifyFlushComplete(FlushRequestID) override {}
-  void NotifyDataSourceStarted(DataSourceInstanceID) override {}
-  void NotifyDataSourceStopped(DataSourceInstanceID) override {}
-  void ActivateTriggers(const std::vector<std::string>&) override {}
-
-  void Sync(std::function<void()> callback) override { callback(); }
-
- private:
-  Producer* const producer_;
-  base::TaskRunner* const task_runner_;
-  base::WeakPtrFactory<UnsupportedProducerEndpoint> weak_ptr_factory_{
-      this};  // Keep last.
-};
-
-class UnsupportedConsumerEndpoint : public ConsumerEndpoint {
- public:
-  UnsupportedConsumerEndpoint(Consumer* consumer, base::TaskRunner* task_runner)
-      : consumer_(consumer), task_runner_(task_runner) {
-    // The SDK will not to reconnect the consumer, so we just disconnect it
-    // immediately, which will cancel the tracing session.
-    auto weak_this = weak_ptr_factory_.GetWeakPtr();
-    task_runner_->PostTask([weak_this] {
-      if (weak_this)
-        weak_this->consumer_->OnDisconnect();
-    });
-  }
-  ~UnsupportedConsumerEndpoint() override = default;
-
-  void EnableTracing(const TraceConfig&,
-                     base::ScopedFile = base::ScopedFile()) override {}
-  void ChangeTraceConfig(const TraceConfig&) override {}
-
-  void StartTracing() override {}
-  void DisableTracing() override {}
-
-  void Flush(uint32_t /*timeout_ms*/, FlushCallback callback) override {
-    callback(/*success=*/false);
-  }
-
-  void ReadBuffers() override {}
-  void FreeBuffers() override {}
-
-  void Detach(const std::string& /*key*/) override {}
-  void Attach(const std::string& /*key*/) override {}
-
-  void GetTraceStats() override {}
-  void ObserveEvents(uint32_t /*events_mask*/) override {}
-  void QueryServiceState(QueryServiceStateCallback) override {}
-  void QueryCapabilities(QueryCapabilitiesCallback) override {}
-
-  void SaveTraceForBugreport(SaveTraceForBugreportCallback) override {}
-
- private:
-  Consumer* const consumer_;
-  base::TaskRunner* const task_runner_;
-  base::WeakPtrFactory<UnsupportedConsumerEndpoint> weak_ptr_factory_{
-      this};  // Keep last.
-};
-
-}  // namespace
-
-// static
-TracingBackend* TracingBackendFake::GetInstance() {
-  static auto* instance = new TracingBackendFake();
-  return instance;
-}
-
-TracingBackendFake::TracingBackendFake() = default;
-
-std::unique_ptr<ProducerEndpoint> TracingBackendFake::ConnectProducer(
-    const ConnectProducerArgs& args) {
-  return std::unique_ptr<ProducerEndpoint>(
-      new UnsupportedProducerEndpoint(args.producer, args.task_runner));
-}
-
-std::unique_ptr<ConsumerEndpoint> TracingBackendFake::ConnectConsumer(
-    const ConnectConsumerArgs& args) {
-  return std::unique_ptr<ConsumerEndpoint>(
-      new UnsupportedConsumerEndpoint(args.consumer, args.task_runner));
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_fake.cc b/src/tracing/internal/tracing_muxer_fake.cc
deleted file mode 100644
index fd4e0b5..0000000
--- a/src/tracing/internal/tracing_muxer_fake.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_fake.h"
-
-namespace perfetto {
-namespace internal {
-namespace {
-
-PERFETTO_NORETURN void FailUninitialized() {
-  PERFETTO_FATAL(
-      "Tracing not initialized. Call perfetto::Tracing::Initialize() first.");
-}
-
-}  // namespace
-
-#if PERFETTO_HAS_NO_DESTROY()
-// static
-PERFETTO_NO_DESTROY TracingMuxerFake::FakePlatform
-    TracingMuxerFake::FakePlatform::instance{};
-// static
-PERFETTO_NO_DESTROY TracingMuxerFake TracingMuxerFake::instance{};
-#endif  // PERFETTO_HAS_NO_DESTROY()
-
-TracingMuxerFake::FakePlatform::~FakePlatform() = default;
-
-Platform::ThreadLocalObject*
-TracingMuxerFake::FakePlatform::GetOrCreateThreadLocalObject() {
-  FailUninitialized();
-}
-
-std::unique_ptr<base::TaskRunner>
-TracingMuxerFake::FakePlatform::CreateTaskRunner(const CreateTaskRunnerArgs&) {
-  FailUninitialized();
-}
-
-std::string TracingMuxerFake::FakePlatform::GetCurrentProcessName() {
-  FailUninitialized();
-}
-
-bool TracingMuxerFake::RegisterDataSource(const DataSourceDescriptor&,
-                                          DataSourceFactory,
-                                          DataSourceStaticState*) {
-  FailUninitialized();
-}
-
-std::unique_ptr<TraceWriterBase> TracingMuxerFake::CreateTraceWriter(
-    DataSourceStaticState*,
-    uint32_t,
-    DataSourceState*,
-    BufferExhaustedPolicy) {
-  FailUninitialized();
-}
-
-void TracingMuxerFake::DestroyStoppedTraceWritersForCurrentThread() {
-  FailUninitialized();
-}
-
-void TracingMuxerFake::RegisterInterceptor(
-    const InterceptorDescriptor&,
-    InterceptorFactory,
-    InterceptorBase::TLSFactory,
-    InterceptorBase::TracePacketCallback) {
-  FailUninitialized();
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_fake.h b/src/tracing/internal/tracing_muxer_fake.h
deleted file mode 100644
index 0c2902b..0000000
--- a/src/tracing/internal/tracing_muxer_fake.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_FAKE_H_
-#define SRC_TRACING_INTERNAL_TRACING_MUXER_FAKE_H_
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/tracing/internal/tracing_muxer.h"
-
-namespace perfetto {
-namespace internal {
-
-// An always-fail implementation of TracingMuxer. Before tracing has been
-// initialiazed, all muxer operations will route here and fail with a helpful
-// error message. This is to avoid introducing null checks in
-// performance-critical parts of the codebase.
-class TracingMuxerFake : public TracingMuxer {
-  class FakePlatform : public Platform {
-   public:
-    ~FakePlatform() override;
-    ThreadLocalObject* GetOrCreateThreadLocalObject() override;
-    std::unique_ptr<base::TaskRunner> CreateTaskRunner(
-        const CreateTaskRunnerArgs&) override;
-    std::string GetCurrentProcessName() override;
-
-    static FakePlatform instance;
-  };
-
- public:
-  TracingMuxerFake() : TracingMuxer(&FakePlatform::instance) {}
-
-  static constexpr TracingMuxerFake* Get() {
-#if PERFETTO_HAS_NO_DESTROY()
-    return &instance;
-#else
-    return nullptr;
-#endif
-  }
-
-  // TracingMuxer implementation.
-  bool RegisterDataSource(const DataSourceDescriptor&,
-                          DataSourceFactory,
-                          DataSourceStaticState*) override;
-  std::unique_ptr<TraceWriterBase> CreateTraceWriter(
-      DataSourceStaticState*,
-      uint32_t data_source_instance_index,
-      DataSourceState*,
-      BufferExhaustedPolicy buffer_exhausted_policy) override;
-  void DestroyStoppedTraceWritersForCurrentThread() override;
-  void RegisterInterceptor(const InterceptorDescriptor&,
-                           InterceptorFactory,
-                           InterceptorBase::TLSFactory,
-                           InterceptorBase::TracePacketCallback) override;
-
- private:
-  static TracingMuxerFake instance;
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_INTERNAL_TRACING_MUXER_FAKE_H_
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 1fb5ae8..79eb734 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -27,89 +27,22 @@
 #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/shared_memory_arbiter.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"
 #include "perfetto/tracing/buffer_exhausted_policy.h"
 #include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/core/tracing_service_state.h"
 #include "perfetto/tracing/data_source.h"
 #include "perfetto/tracing/internal/data_source_internal.h"
-#include "perfetto/tracing/internal/interceptor_trace_writer.h"
-#include "perfetto/tracing/internal/tracing_backend_fake.h"
 #include "perfetto/tracing/trace_writer_base.h"
 #include "perfetto/tracing/tracing.h"
 #include "perfetto/tracing/tracing_backend.h"
 
-#include "protos/perfetto/config/interceptor_config.gen.h"
-
-#include "src/tracing/internal/tracing_muxer_fake.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <io.h>  // For dup()
-#else
-#include <unistd.h>  // For dup()
-#endif
-
 namespace perfetto {
 namespace internal {
 
 namespace {
 
-// A task runner which prevents calls to DataSource::Trace() while an operation
-// is in progress. Used to guard against unexpected re-entrancy where the
-// user-provided task runner implementation tries to enter a trace point under
-// the hood.
-class NonReentrantTaskRunner : public base::TaskRunner {
- public:
-  NonReentrantTaskRunner(TracingMuxer* muxer,
-                         std::unique_ptr<base::TaskRunner> task_runner)
-      : muxer_(muxer), task_runner_(std::move(task_runner)) {}
-
-  // base::TaskRunner implementation.
-  void PostTask(std::function<void()> task) override {
-    CallWithGuard([&] { task_runner_->PostTask(std::move(task)); });
-  }
-
-  void PostDelayedTask(std::function<void()> task, uint32_t delay_ms) override {
-    CallWithGuard(
-        [&] { task_runner_->PostDelayedTask(std::move(task), delay_ms); });
-  }
-
-  void AddFileDescriptorWatch(base::PlatformHandle fd,
-                              std::function<void()> callback) override {
-    CallWithGuard(
-        [&] { task_runner_->AddFileDescriptorWatch(fd, std::move(callback)); });
-  }
-
-  void RemoveFileDescriptorWatch(base::PlatformHandle fd) override {
-    CallWithGuard([&] { task_runner_->RemoveFileDescriptorWatch(fd); });
-  }
-
-  bool RunsTasksOnCurrentThread() const override {
-    bool result;
-    CallWithGuard([&] { result = task_runner_->RunsTasksOnCurrentThread(); });
-    return result;
-  }
-
- private:
-  template <typename T>
-  void CallWithGuard(T lambda) const {
-    auto* root_tls = muxer_->GetOrCreateTracingTLS();
-    if (PERFETTO_UNLIKELY(root_tls->is_in_trace_point)) {
-      lambda();
-      return;
-    }
-    ScopedReentrancyAnnotator scoped_annotator(*root_tls);
-    lambda();
-  }
-
-  TracingMuxer* const muxer_;
-  std::unique_ptr<base::TaskRunner> task_runner_;
-};
-
 class StopArgsImpl : public DataSourceBase::StopArgs {
  public:
   std::function<void()> HandleStopAsynchronously() const override {
@@ -131,37 +64,14 @@
 }  // namespace
 
 // ----- Begin of TracingMuxerImpl::ProducerImpl
-TracingMuxerImpl::ProducerImpl::ProducerImpl(
-    TracingMuxerImpl* muxer,
-    TracingBackendId backend_id,
-    uint32_t shmem_batch_commits_duration_ms)
-    : muxer_(muxer),
-      backend_id_(backend_id),
-      shmem_batch_commits_duration_ms_(shmem_batch_commits_duration_ms) {}
-
+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) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DCHECK(!connected_);
-  connection_id_++;
-
-  // Adopt the endpoint into a shared pointer so that we can safely share it
-  // across threads that create trace writers. The custom deleter function
-  // ensures that the endpoint is always destroyed on the muxer's thread. (Note
-  // that |task_runner| is assumed to outlive tracing sessions on all threads.)
-  auto* task_runner = muxer_->task_runner_.get();
-  auto deleter = [task_runner](ProducerEndpoint* e) {
-    task_runner->PostTask([e] { delete e; });
-  };
-  std::shared_ptr<ProducerEndpoint> service(endpoint.release(), deleter);
-  // This atomic store is needed because another thread might be concurrently
-  // creating a trace writer using the previous (disconnected) |service_|. See
-  // CreateTraceWriter().
-  std::atomic_store(&service_, std::move(service));
-  // Don't try to use the service here since it may not have connected yet. See
-  // OnConnect().
+  service_ = std::move(endpoint);
 }
 
 void TracingMuxerImpl::ProducerImpl::OnConnect() {
@@ -175,31 +85,19 @@
 void TracingMuxerImpl::ProducerImpl::OnDisconnect() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   connected_ = false;
-  // Active data sources for this producer will be stopped by
-  // DestroyStoppedTraceWritersForCurrentThread() since the reconnected producer
-  // will have a different connection id (even before it has finished
-  // connecting).
-  registered_data_sources_.reset();
-  // Keep the old service around as a dead connection in case it has active
-  // trace writers. We can't clear |service_| here because other threads may be
-  // concurrently creating new trace writers. The reconnection below will
-  // atomically swap the new service in place of the old one.
-  dead_services_.push_back(service_);
-  // Try reconnecting the producer.
-  muxer_->OnProducerDisconnected(this);
+  // TODO: handle more graceful.
+  PERFETTO_ELOG("Cannot connect to traced. Is it running?");
 }
 
 void TracingMuxerImpl::ProducerImpl::OnTracingSetup() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  service_->MaybeSharedMemoryArbiter()->SetBatchCommitsDuration(
-      shmem_batch_commits_duration_ms_);
 }
 
 void TracingMuxerImpl::ProducerImpl::SetupDataSource(
     DataSourceInstanceID id,
     const DataSourceConfig& cfg) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  muxer_->SetupDataSource(backend_id_, connection_id_, id, cfg);
+  muxer_->SetupDataSource(backend_id_, id, cfg);
 }
 
 void TracingMuxerImpl::ProducerImpl::StartDataSource(DataSourceInstanceID id,
@@ -223,41 +121,19 @@
 }
 
 void TracingMuxerImpl::ProducerImpl::ClearIncrementalState(
-    const DataSourceInstanceID* instances,
-    size_t instance_count) {
+    const DataSourceInstanceID*,
+    size_t) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (size_t inst_idx = 0; inst_idx < instance_count; inst_idx++) {
-    muxer_->ClearDataSourceIncrementalState(backend_id_, instances[inst_idx]);
-  }
+  // TODO(skyostil): Mark each affected data source's incremental state as
+  // needing to be cleared.
 }
-
-void TracingMuxerImpl::ProducerImpl::SweepDeadServices() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto is_unused = [](const std::shared_ptr<ProducerEndpoint>& endpoint) {
-    auto* arbiter = endpoint->MaybeSharedMemoryArbiter();
-    return !arbiter || arbiter->TryShutdown();
-  };
-  for (auto it = dead_services_.begin(); it != dead_services_.end();) {
-    auto next_it = it;
-    next_it++;
-    if (is_unused(*it)) {
-      dead_services_.erase(it);
-    }
-    it = next_it;
-  }
-}
-
 // ----- End of TracingMuxerImpl::ProducerImpl methods.
 
 // ----- Begin of TracingMuxerImpl::ConsumerImpl
 TracingMuxerImpl::ConsumerImpl::ConsumerImpl(TracingMuxerImpl* muxer,
-                                             BackendType backend_type,
                                              TracingBackendId backend_id,
                                              TracingSessionGlobalID session_id)
-    : muxer_(muxer),
-      backend_type_(backend_type),
-      backend_id_(backend_id),
-      session_id_(session_id) {}
+    : muxer_(muxer), backend_id_(backend_id), session_id_(session_id) {}
 
 TracingMuxerImpl::ConsumerImpl::~ConsumerImpl() = default;
 
@@ -265,8 +141,8 @@
     std::unique_ptr<ConsumerEndpoint> endpoint) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   service_ = std::move(endpoint);
-  // Don't try to use the service here since it may not have connected yet. See
-  // OnConnect().
+  // Observe data source instance events so we get notified when tracing starts.
+  service_->ObserveEvents(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
 }
 
 void TracingMuxerImpl::ConsumerImpl::OnConnect() {
@@ -274,55 +150,27 @@
   PERFETTO_DCHECK(!connected_);
   connected_ = true;
 
-  // Observe data source instance events so we get notified when tracing starts.
-  service_->ObserveEvents(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES |
-                          ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
-
   // If the API client configured and started tracing before we connected,
   // tell the backend about it now.
-  if (trace_config_)
+  if (trace_config_) {
     muxer_->SetupTracingSession(session_id_, trace_config_);
-  if (start_pending_)
-    muxer_->StartTracingSession(session_id_);
-  if (get_trace_stats_pending_) {
-    auto callback = std::move(get_trace_stats_callback_);
-    get_trace_stats_callback_ = nullptr;
-    muxer_->GetTraceStats(session_id_, std::move(callback));
+    if (start_pending_)
+      muxer_->StartTracingSession(session_id_);
+    if (stop_pending_)
+      muxer_->StopTracingSession(session_id_);
   }
-  if (query_service_state_callback_) {
-    auto callback = std::move(query_service_state_callback_);
-    query_service_state_callback_ = nullptr;
-    muxer_->QueryServiceState(session_id_, std::move(callback));
-  }
-  if (stop_pending_)
-    muxer_->StopTracingSession(session_id_);
 }
 
 void TracingMuxerImpl::ConsumerImpl::OnDisconnect() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  if (!connected_ && backend_type_ == kSystemBackend) {
-    PERFETTO_ELOG(
-        "Unable to connect to the system tracing service as a consumer. On "
-        "Android, use the \"perfetto\" command line tool instead to start "
-        "system-wide tracing sessions");
-  }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-
-  // Notify the client about disconnection.
-  NotifyError(TracingError{TracingError::kDisconnected, "Peer disconnected"});
-
-  // Make sure the client doesn't hang in a blocking start/stop because of the
-  // disconnection.
-  NotifyStartComplete();
-  NotifyStopComplete();
-
   // 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.
@@ -344,15 +192,10 @@
   service_.reset();
 }
 
-void TracingMuxerImpl::ConsumerImpl::OnTracingDisabled(
-    const std::string& error) {
+void TracingMuxerImpl::ConsumerImpl::OnTracingDisabled() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DCHECK(!stopped_);
   stopped_ = true;
-
-  if (!error.empty())
-    NotifyError(TracingError{TracingError::kTracingFailed, error});
-
   // 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();
@@ -361,10 +204,6 @@
 
 void TracingMuxerImpl::ConsumerImpl::NotifyStartComplete() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (start_complete_callback_) {
-    muxer_->task_runner_->PostTask(std::move(start_complete_callback_));
-    start_complete_callback_ = nullptr;
-  }
   if (blocking_start_complete_callback_) {
     muxer_->task_runner_->PostTask(
         std::move(blocking_start_complete_callback_));
@@ -372,14 +211,6 @@
   }
 }
 
-void TracingMuxerImpl::ConsumerImpl::NotifyError(const TracingError& error) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (error_callback_) {
-    muxer_->task_runner_->PostTask(
-        std::bind(std::move(error_callback_), error));
-  }
-}
-
 void TracingMuxerImpl::ConsumerImpl::NotifyStopComplete() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   if (stop_complete_callback_) {
@@ -422,7 +253,7 @@
   auto callback = read_trace_callback_;
   muxer_->task_runner_->PostTask([callback, buf, has_more] {
     TracingSession::ReadTraceCallbackArgs callback_arg{};
-    callback_arg.data = buf->empty() ? nullptr : &(*buf)[0];
+    callback_arg.data = buf->size() ? &(*buf)[0] : nullptr;
     callback_arg.size = buf->size();
     callback_arg.has_more = has_more;
     callback(callback_arg);
@@ -442,16 +273,10 @@
           state_change.state() ==
           ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED;
     }
-  }
-
-  if (events.instance_state_changes_size() ||
-      events.all_data_sources_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. In the case where there are no matching data sources for the
-    // session, the service will report the all_data_sources_started() event
-    // without adding any instances (only since Android S / Perfetto v10.0).
-    if (start_complete_callback_ || blocking_start_complete_callback_) {
+    // 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; });
@@ -461,22 +286,10 @@
   }
 }
 
-void TracingMuxerImpl::ConsumerImpl::OnTraceStats(
-    bool success,
-    const TraceStats& trace_stats) {
-  if (!get_trace_stats_callback_)
-    return;
-  TracingSession::GetTraceStatsCallbackArgs callback_arg{};
-  callback_arg.success = success;
-  callback_arg.trace_stats_data = trace_stats.SerializeAsArray();
-  muxer_->task_runner_->PostTask(
-      std::bind(std::move(get_trace_stats_callback_), std::move(callback_arg)));
-  get_trace_stats_callback_ = nullptr;
-}
-
 // 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
@@ -487,9 +300,8 @@
 
 TracingMuxerImpl::TracingSessionImpl::TracingSessionImpl(
     TracingMuxerImpl* muxer,
-    TracingSessionGlobalID session_id,
-    BackendType backend_type)
-    : muxer_(muxer), session_id_(session_id), backend_type_(backend_type) {}
+    TracingSessionGlobalID session_id)
+    : muxer_(muxer), session_id_(session_id) {}
 
 // Can be destroyed from any thread.
 TracingMuxerImpl::TracingSessionImpl::~TracingSessionImpl() {
@@ -506,15 +318,6 @@
   auto session_id = session_id_;
   std::shared_ptr<TraceConfig> trace_config(new TraceConfig(cfg));
   if (fd >= 0) {
-    base::ignore_result(backend_type_);  // For -Wunused in the amalgamation.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    if (backend_type_ != kInProcessBackend) {
-      PERFETTO_FATAL(
-          "Passing a file descriptor to TracingSession::Setup() is only "
-          "supported with the kInProcessBackend on Windows. Use "
-          "TracingSession::ReadTrace() instead");
-    }
-#endif
     trace_config->set_write_into_file(true);
     fd = dup(fd);
   }
@@ -531,16 +334,6 @@
       [muxer, session_id] { muxer->StartTracingSession(session_id); });
 }
 
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::ChangeTraceConfig(
-    const TraceConfig& cfg) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cfg] {
-    muxer->ChangeTracingSessionConfig(session_id, cfg);
-  });
-}
-
 // Can be called from any thread except the service thread.
 void TracingMuxerImpl::TracingSessionImpl::StartBlocking() {
   PERFETTO_DCHECK(!muxer_->task_runner_->RunsTasksOnCurrentThread());
@@ -549,11 +342,6 @@
   base::WaitableEvent tracing_started;
   muxer->task_runner_->PostTask([muxer, session_id, &tracing_started] {
     auto* consumer = muxer->FindConsumer(session_id);
-    if (!consumer) {
-      // TODO(skyostil): Signal an error to the user.
-      tracing_started.Notify();
-      return;
-    }
     PERFETTO_DCHECK(!consumer->blocking_start_complete_callback_);
     consumer->blocking_start_complete_callback_ = [&] {
       tracing_started.Notify();
@@ -564,23 +352,6 @@
 }
 
 // Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::Flush(
-    std::function<void(bool)> user_callback,
-    uint32_t timeout_ms) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, timeout_ms, user_callback] {
-    auto* consumer = muxer->FindConsumer(session_id);
-    if (!consumer) {
-      std::move(user_callback)(false);
-      return;
-    }
-    muxer->FlushTracingSession(session_id, timeout_ms,
-                               std::move(user_callback));
-  });
-}
-
-// Can be called from any thread.
 void TracingMuxerImpl::TracingSessionImpl::Stop() {
   auto* muxer = muxer_;
   auto session_id = session_id_;
@@ -596,11 +367,6 @@
   base::WaitableEvent tracing_stopped;
   muxer->task_runner_->PostTask([muxer, session_id, &tracing_stopped] {
     auto* consumer = muxer->FindConsumer(session_id);
-    if (!consumer) {
-      // TODO(skyostil): Signal an error to the user.
-      tracing_stopped.Notify();
-      return;
-    }
     PERFETTO_DCHECK(!consumer->blocking_stop_complete_callback_);
     consumer->blocking_stop_complete_callback_ = [&] {
       tracing_stopped.Notify();
@@ -620,72 +386,19 @@
 }
 
 // Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::SetOnStartCallback(
-    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);
-    if (!consumer)
-      return;
-    consumer->start_complete_callback_ = cb;
-  });
-}
-
-// Can be called from any thread
-void TracingMuxerImpl::TracingSessionImpl::SetOnErrorCallback(
-    std::function<void(TracingError)> cb) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cb] {
-    auto* consumer = muxer->FindConsumer(session_id);
-    if (!consumer) {
-      // Notify the client about concurrent disconnection of the session.
-      if (cb)
-        cb(TracingError{TracingError::kDisconnected, "Peer disconnected"});
-      return;
-    }
-    consumer->error_callback_ = 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);
-    if (!consumer)
-      return;
     consumer->stop_complete_callback_ = cb;
   });
 }
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::GetTraceStats(
-    GetTraceStatsCallback cb) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cb] {
-    muxer->GetTraceStats(session_id, std::move(cb));
-  });
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::QueryServiceState(
-    QueryServiceStateCallback cb) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cb] {
-    muxer->QueryServiceState(session_id, std::move(cb));
-  });
-}
-
 // ----- End of TracingMuxerImpl::TracingSessionImpl
 
 // static
-TracingMuxer* TracingMuxer::instance_ = TracingMuxerFake::Get();
+TracingMuxer* TracingMuxer::instance_ = nullptr;
 
 // This is called by perfetto::Tracing::Initialize().
 // Can be called on any thread. Typically, but not necessarily, that will be
@@ -694,11 +407,9 @@
     : TracingMuxer(args.platform ? args.platform
                                  : Platform::GetDefaultPlatform()) {
   PERFETTO_DETACH_FROM_THREAD(thread_checker_);
-  instance_ = this;
 
   // Create the thread where muxer, producers and service will live.
-  task_runner_.reset(
-      new NonReentrantTaskRunner(this, platform_->CreateTaskRunner({})));
+  task_runner_ = platform_->CreateTaskRunner({});
 
   // Run the initializer on that thread.
   task_runner_->PostTask([this, args] { Initialize(args); });
@@ -707,8 +418,6 @@
 void TracingMuxerImpl::Initialize(const TracingInitArgs& args) {
   PERFETTO_DCHECK_THREAD(thread_checker_);  // Rebind the thread checker.
 
-  policy_ = args.tracing_policy;
-
   auto add_backend = [this, &args](TracingBackend* backend, BackendType type) {
     if (!backend) {
       // We skip the log in release builds because the *_backend_fake.cc code
@@ -722,16 +431,14 @@
     rb.backend = backend;
     rb.id = backend_id;
     rb.type = type;
-    rb.producer.reset(new ProducerImpl(this, backend_id,
-                                       args.shmem_batch_commits_duration_ms));
-    rb.producer_conn_args.producer = rb.producer.get();
-    rb.producer_conn_args.producer_name = platform_->GetCurrentProcessName();
-    rb.producer_conn_args.task_runner = task_runner_.get();
-    rb.producer_conn_args.shmem_size_hint_bytes =
-        args.shmem_size_hint_kb * 1024;
-    rb.producer_conn_args.shmem_page_size_hint_bytes =
-        args.shmem_page_size_hint_kb * 1024;
-    rb.producer->Initialize(rb.backend->ConnectProducer(rb.producer_conn_args));
+    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) {
@@ -752,12 +459,6 @@
   if (args.backends & ~(kSystemBackend | kInProcessBackend | kCustomBackend)) {
     PERFETTO_FATAL("Unsupported tracing backend type");
   }
-
-  // Fallback backend for consumer creation for an unsupported backend type.
-  // This backend simply fails any attempt to start a tracing session.
-  // NOTE: This backend instance has to be added last.
-  add_backend(internal::TracingBackendFake::GetInstance(),
-              BackendType::kUnspecifiedBackend);
 }
 
 // Can be called from any thread (but not concurrently).
@@ -796,44 +497,8 @@
   return true;
 }
 
-// Can be called from any thread (but not concurrently).
-void TracingMuxerImpl::RegisterInterceptor(
-    const InterceptorDescriptor& descriptor,
-    InterceptorFactory factory,
-    InterceptorBase::TLSFactory tls_factory,
-    InterceptorBase::TracePacketCallback packet_callback) {
-  task_runner_->PostTask(
-      [this, descriptor, factory, tls_factory, packet_callback] {
-        // Ignore repeated registrations.
-        for (const auto& interceptor : interceptors_) {
-          if (interceptor.descriptor.name() == descriptor.name()) {
-            PERFETTO_DCHECK(interceptor.tls_factory == tls_factory);
-            PERFETTO_DCHECK(interceptor.packet_callback == packet_callback);
-            return;
-          }
-        }
-        // Only allow certain interceptors for now.
-        if (descriptor.name() != "test_interceptor" &&
-            descriptor.name() != "console") {
-          PERFETTO_ELOG(
-              "Interceptors are experimental. If you want to use them, please "
-              "get in touch with the project maintainers "
-              "(https://perfetto.dev/docs/contributing/"
-              "getting-started#community).");
-          return;
-        }
-        interceptors_.emplace_back();
-        RegisteredInterceptor& interceptor = interceptors_.back();
-        interceptor.descriptor = descriptor;
-        interceptor.factory = factory;
-        interceptor.tls_factory = tls_factory;
-        interceptor.packet_callback = packet_callback;
-      });
-}
-
 // Called by the service of one of the backends.
 void TracingMuxerImpl::SetupDataSource(TracingBackendId backend_id,
-                                       uint32_t backend_connection_id,
                                        DataSourceInstanceID instance_id,
                                        const DataSourceConfig& cfg) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
@@ -885,34 +550,11 @@
                        DataSourceInstanceID>::value,
           "data_source_instance_id type mismatch");
       internal_state->backend_id = backend_id;
-      internal_state->backend_connection_id = backend_connection_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();
-      internal_state->interceptor = nullptr;
-      internal_state->interceptor_id = 0;
-
-      if (cfg.has_interceptor_config()) {
-        for (size_t j = 0; j < interceptors_.size(); j++) {
-          if (cfg.interceptor_config().name() ==
-              interceptors_[j].descriptor.name()) {
-            PERFETTO_DLOG("Intercepting data source %" PRIu64
-                          " \"%s\" into \"%s\"",
-                          instance_id, cfg.name().c_str(),
-                          cfg.interceptor_config().name().c_str());
-            internal_state->interceptor_id = static_cast<uint32_t>(j + 1);
-            internal_state->interceptor = interceptors_[j].factory();
-            internal_state->interceptor->OnSetup({cfg});
-            break;
-          }
-        }
-        if (!internal_state->interceptor_id) {
-          PERFETTO_ELOG("Unknown interceptor configured for data source: %s",
-                        cfg.interceptor_config().name().c_str());
-        }
-      }
 
       // This must be made at the end. See matching acquire-load in
       // DataSource::Trace().
@@ -948,8 +590,6 @@
   start_args.internal_instance_index = ds.instance_idx;
 
   std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
-  if (ds.internal_state->interceptor)
-    ds.internal_state->interceptor->OnStart({});
   ds.internal_state->trace_lambda_enabled = true;
   ds.internal_state->data_source->OnStart(start_args);
 }
@@ -982,8 +622,6 @@
 
   {
     std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
-    if (ds.internal_state->interceptor)
-      ds.internal_state->interceptor->OnStop({});
     ds.internal_state->data_source->OnStop(stop_args);
   }
 
@@ -1030,86 +668,8 @@
   // |backends_| is append-only, Backend instances are always valid.
   PERFETTO_CHECK(backend_id < backends_.size());
   ProducerImpl* producer = backends_[backend_id].producer.get();
-  if (!producer)
-    return;
-  if (producer->connected_) {
-    // Flush any commits that might have been batched by SharedMemoryArbiter.
-    producer->service_->MaybeSharedMemoryArbiter()
-        ->FlushPendingCommitDataRequests();
+  if (producer && producer->connected_)
     producer->service_->NotifyDataSourceStopped(instance_id);
-  }
-  producer->SweepDeadServices();
-}
-
-void TracingMuxerImpl::ClearDataSourceIncrementalState(
-    TracingBackendId backend_id,
-    DataSourceInstanceID instance_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("Clearing incremental state for data source %" PRIu64,
-                instance_id);
-  auto ds = FindDataSource(backend_id, instance_id);
-  if (!ds) {
-    PERFETTO_ELOG("Could not find data source to clear incremental state for");
-    return;
-  }
-  // Make DataSource::TraceContext::GetIncrementalState() eventually notice that
-  // the incremental state should be cleared.
-  ds.static_state->incremental_state_generation.fetch_add(
-      1, std::memory_order_relaxed);
-}
-
-void TracingMuxerImpl::SyncProducersForTesting() {
-  std::mutex mutex;
-  std::condition_variable cv;
-
-  // IPC-based producers don't report connection errors explicitly for each
-  // command, but instead with an asynchronous callback
-  // (ProducerImpl::OnDisconnected). This means that the sync command below
-  // may have completed but failed to reach the service because of a
-  // disconnection, but we can't tell until the disconnection message comes
-  // through. To guard against this, we run two whole rounds of sync round-trips
-  // before returning; the first one will detect any disconnected producers and
-  // the second one will ensure any reconnections have completed and all data
-  // sources are registered in the service again.
-  for (size_t i = 0; i < 2; i++) {
-    size_t countdown = std::numeric_limits<size_t>::max();
-    task_runner_->PostTask([this, &mutex, &cv, &countdown] {
-      {
-        std::unique_lock<std::mutex> countdown_lock(mutex);
-        countdown = backends_.size();
-      }
-      for (auto& backend : backends_) {
-        auto* producer = backend.producer.get();
-        producer->service_->Sync([&mutex, &cv, &countdown] {
-          std::unique_lock<std::mutex> countdown_lock(mutex);
-          countdown--;
-          cv.notify_one();
-        });
-      }
-    });
-
-    {
-      std::unique_lock<std::mutex> countdown_lock(mutex);
-      cv.wait(countdown_lock, [&countdown] { return !countdown; });
-    }
-  }
-
-  // Check that all producers are indeed connected.
-  bool done = false;
-  bool all_producers_connected = true;
-  task_runner_->PostTask([this, &mutex, &cv, &done, &all_producers_connected] {
-    for (auto& backend : backends_)
-      all_producers_connected &= backend.producer->connected_;
-    std::unique_lock<std::mutex> lock(mutex);
-    done = true;
-    cv.notify_one();
-  });
-
-  {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [&done] { return done; });
-  }
-  PERFETTO_DCHECK(all_producers_connected);
 }
 
 void TracingMuxerImpl::DestroyStoppedTraceWritersForCurrentThread() {
@@ -1131,9 +691,7 @@
 
       DataSourceState* ds_state = static_state->TryGet(inst);
       if (ds_state && ds_state->backend_id == ds_tls.backend_id &&
-          ds_state->backend_connection_id == ds_tls.backend_connection_id &&
-          ds_state->buffer_id == ds_tls.buffer_id &&
-          ds_state->data_source_instance_id == ds_tls.data_source_instance_id) {
+          ds_state->buffer_id == ds_tls.buffer_id) {
         continue;
       }
 
@@ -1162,14 +720,13 @@
       if (!backend.producer->connected_)
         continue;
 
-      PERFETTO_DCHECK(rds.static_state->index < kMaxDataSources);
+      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);
-      rds.descriptor.set_handles_incremental_state_clear(true);
       backend.producer->service_->RegisterDataSource(rds.descriptor);
       backend.producer->registered_data_sources_.set(rds.static_state->index);
     }
@@ -1230,42 +787,6 @@
   // TODO implement support for the deferred-start + fast-triggering case.
 }
 
-void TracingMuxerImpl::ChangeTracingSessionConfig(
-    TracingSessionGlobalID session_id,
-    const TraceConfig& trace_config) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto* consumer = FindConsumer(session_id);
-
-  if (!consumer)
-    return;
-
-  if (!consumer->trace_config_) {
-    // Changing the config is only supported for started sessions.
-    PERFETTO_ELOG("Must call Setup(config) and Start() first");
-    return;
-  }
-
-  consumer->trace_config_ = std::make_shared<TraceConfig>(trace_config);
-  if (consumer->connected_)
-    consumer->service_->ChangeTraceConfig(trace_config);
-}
-
-void TracingMuxerImpl::FlushTracingSession(TracingSessionGlobalID session_id,
-                                           uint32_t timeout_ms,
-                                           std::function<void(bool)> callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer || consumer->start_pending_ || consumer->stop_pending_ ||
-      !consumer->trace_config_) {
-    PERFETTO_ELOG("Flush() can be called only after Start() and before Stop()");
-    std::move(callback)(false);
-    return;
-  }
-
-  consumer->service_->Flush(timeout_ms, std::move(callback));
-}
-
 void TracingMuxerImpl::StopTracingSession(TracingSessionGlobalID session_id) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   auto* consumer = FindConsumer(session_id);
@@ -1328,95 +849,20 @@
     std::function<void(TracingSession::ReadTraceCallbackArgs)> callback) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   auto* consumer = FindConsumer(session_id);
-  if (!consumer) {
-    // TODO(skyostil): Signal an error to the user.
-    TracingSession::ReadTraceCallbackArgs callback_arg{};
-    callback(callback_arg);
+  if (!consumer)
     return;
-  }
   PERFETTO_DCHECK(!consumer->read_trace_callback_);
   consumer->read_trace_callback_ = std::move(callback);
   consumer->service_->ReadBuffers();
 }
 
-void TracingMuxerImpl::GetTraceStats(
-    TracingSessionGlobalID session_id,
-    TracingSession::GetTraceStatsCallback callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer) {
-    TracingSession::GetTraceStatsCallbackArgs callback_arg{};
-    callback_arg.success = false;
-    callback(std::move(callback_arg));
-    return;
-  }
-  PERFETTO_DCHECK(!consumer->get_trace_stats_callback_);
-  consumer->get_trace_stats_callback_ = std::move(callback);
-  if (!consumer->connected_) {
-    consumer->get_trace_stats_pending_ = true;
-    return;
-  }
-  consumer->get_trace_stats_pending_ = false;
-  consumer->service_->GetTraceStats();
-}
-
-void TracingMuxerImpl::QueryServiceState(
-    TracingSessionGlobalID session_id,
-    TracingSession::QueryServiceStateCallback callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer) {
-    TracingSession::QueryServiceStateCallbackArgs callback_arg{};
-    callback_arg.success = false;
-    callback(std::move(callback_arg));
-    return;
-  }
-  PERFETTO_DCHECK(!consumer->query_service_state_callback_);
-  if (!consumer->connected_) {
-    consumer->query_service_state_callback_ = std::move(callback);
-    return;
-  }
-  auto callback_wrapper = [callback](bool success,
-                                     protos::gen::TracingServiceState state) {
-    TracingSession::QueryServiceStateCallbackArgs callback_arg{};
-    callback_arg.success = success;
-    callback_arg.service_state_data = state.SerializeAsArray();
-    callback(std::move(callback_arg));
-  };
-  consumer->service_->QueryServiceState(std::move(callback_wrapper));
-}
-
-void TracingMuxerImpl::SetBatchCommitsDurationForTesting(
-    uint32_t batch_commits_duration_ms,
-    BackendType backend_type) {
-  for (RegisteredBackend& backend : backends_) {
-    if (backend.producer && backend.producer->connected_ &&
-        backend.type == backend_type) {
-      backend.producer->service_->MaybeSharedMemoryArbiter()
-          ->SetBatchCommitsDuration(batch_commits_duration_ms);
-    }
-  }
-}
-
-bool TracingMuxerImpl::EnableDirectSMBPatchingForTesting(
-    BackendType backend_type) {
-  for (RegisteredBackend& backend : backends_) {
-    if (backend.producer && backend.producer->connected_ &&
-        backend.type == backend_type &&
-        !backend.producer->service_->MaybeSharedMemoryArbiter()
-             ->EnableDirectSMBPatching()) {
-      return false;
-    }
-  }
-  return true;
-}
-
 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();
       }
     }
@@ -1424,24 +870,6 @@
   return nullptr;
 }
 
-void TracingMuxerImpl::InitializeConsumer(TracingSessionGlobalID session_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer)
-    return;
-
-  TracingBackendId backend_id = consumer->backend_id_;
-  // |backends_| is append-only, Backend instances are always valid.
-  PERFETTO_CHECK(backend_id < backends_.size());
-  RegisteredBackend& backend = backends_[backend_id];
-
-  TracingBackend::ConnectConsumerArgs conn_args;
-  conn_args.consumer = consumer;
-  conn_args.task_runner = task_runner_.get();
-  consumer->Initialize(backend.backend->ConnectConsumer(conn_args));
-}
-
 void TracingMuxerImpl::OnConsumerDisconnected(ConsumerImpl* consumer) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   for (RegisteredBackend& backend : backends_) {
@@ -1454,36 +882,6 @@
   }
 }
 
-void TracingMuxerImpl::SetMaxProducerReconnectionsForTesting(uint32_t count) {
-  max_producer_reconnections_.store(count);
-}
-
-void TracingMuxerImpl::OnProducerDisconnected(ProducerImpl* producer) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (RegisteredBackend& backend : backends_) {
-    if (backend.producer.get() != producer)
-      continue;
-    // Try reconnecting the disconnected producer. If the connection succeeds,
-    // all the data sources will be automatically re-registered.
-    if (producer->connection_id_ > max_producer_reconnections_.load()) {
-      // Avoid reconnecting a failing producer too many times. Instead we just
-      // leak the producer instead of trying to avoid further complicating
-      // cross-thread trace writer creation.
-      PERFETTO_ELOG("Producer disconnected too many times; not reconnecting");
-      continue;
-    }
-    backend.producer->Initialize(
-        backend.backend->ConnectProducer(backend.producer_conn_args));
-  }
-
-  // Increment the generation counter to atomically ensure that:
-  // 1. Old trace writers from the severed connection eventually get cleaned up
-  //    by DestroyStoppedTraceWritersForCurrentThread().
-  // 2. No new trace writers can be created for the SharedMemoryArbiter from the
-  //    old connection.
-  TracingMuxer::generation_++;
-}
-
 TracingMuxerImpl::FindDataSourceRes TracingMuxerImpl::FindDataSource(
     TracingBackendId backend_id,
     DataSourceInstanceID instance_id) {
@@ -1503,119 +901,50 @@
 
 // Can be called from any thread.
 std::unique_ptr<TraceWriterBase> TracingMuxerImpl::CreateTraceWriter(
-    DataSourceStaticState* static_state,
-    uint32_t data_source_instance_index,
     DataSourceState* data_source,
     BufferExhaustedPolicy buffer_exhausted_policy) {
-  if (PERFETTO_UNLIKELY(data_source->interceptor_id)) {
-    // If the session is being intercepted, return a heap-backed trace writer
-    // instead. This is safe because all the data given to the interceptor is
-    // either thread-local (|instance_index|), statically allocated
-    // (|static_state|) or constant after initialization (|interceptor|). Access
-    // to the interceptor instance itself through |data_source| is protected by
-    // a statically allocated lock (similarly to the data source instance).
-    auto& interceptor = interceptors_[data_source->interceptor_id - 1];
-    return std::unique_ptr<TraceWriterBase>(new InterceptorTraceWriter(
-        interceptor.tls_factory(static_state, data_source_instance_index),
-        interceptor.packet_callback, static_state, data_source_instance_index));
-  }
   ProducerImpl* producer = backends_[data_source->backend_id].producer.get();
-  // Atomically load the current service endpoint. We keep the pointer as a
-  // shared pointer on the stack to guard against it from being concurrently
-  // modified on the thread by ProducerImpl::Initialize() swapping in a
-  // reconnected service on the muxer task runner thread.
-  //
-  // The endpoint may also be concurrently modified by SweepDeadServices()
-  // clearing out old disconnected services. We guard against that by
-  // SharedMemoryArbiter keeping track of any outstanding trace writers. After
-  // shutdown has started, the trace writer created below will be a null one
-  // which will drop any written data. See SharedMemoryArbiter::TryShutdown().
-  //
-  // We use an atomic pointer instead of holding a lock because
-  // CreateTraceWriter posts tasks under the hood.
-  std::shared_ptr<ProducerEndpoint> service =
-      std::atomic_load(&producer->service_);
-  return service->CreateTraceWriter(data_source->buffer_id,
-                                    buffer_exhausted_policy);
+  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 requested_backend_type) {
+    BackendType backend_type) {
   TracingSessionGlobalID session_id = ++next_tracing_session_id_;
 
   // |backend_type| can only specify one backend, not an OR-ed mask.
-  PERFETTO_CHECK((requested_backend_type & (requested_backend_type - 1)) == 0);
+  PERFETTO_CHECK((backend_type & (backend_type - 1)) == 0);
 
   // Capturing |this| is fine because the TracingMuxer is a leaky singleton.
-  task_runner_->PostTask([this, requested_backend_type, session_id] {
+  task_runner_->PostTask([this, backend_type, session_id] {
     for (RegisteredBackend& backend : backends_) {
-      if (requested_backend_type && backend.type &&
-          backend.type != requested_backend_type) {
+      if (backend_type && backend.type != backend_type)
         continue;
-      }
 
-      TracingBackendId backend_id = backend.id;
-
-      // Create the consumer now, even if we have to ask the embedder below, so
-      // that any other tasks executing after this one can find the consumer and
-      // change its pending attributes.
       backend.consumers.emplace_back(
-          new ConsumerImpl(this, backend.type, backend.id, session_id));
-
-      // The last registered backend in |backends_| is the unsupported backend
-      // without a valid type.
-      if (!backend.type) {
-        PERFETTO_ELOG(
-            "No tracing backend ready for type=%d, consumer will disconnect",
-            requested_backend_type);
-        InitializeConsumer(session_id);
-        return;
-      }
-
-      // Check if the embedder wants to be asked for permission before
-      // connecting the consumer.
-      if (!policy_) {
-        InitializeConsumer(session_id);
-        return;
-      }
-
-      TracingPolicy::ShouldAllowConsumerSessionArgs args;
-      args.backend_type = backend.type;
-      args.result_callback = [this, backend_id, session_id](bool allow) {
-        task_runner_->PostTask([this, backend_id, session_id, allow] {
-          if (allow) {
-            InitializeConsumer(session_id);
-            return;
-          }
-
-          PERFETTO_ELOG(
-              "Consumer session for backend type type=%d forbidden, "
-              "consumer will disconnect",
-              backends_[backend_id].type);
-
-          auto* consumer = FindConsumer(session_id);
-          if (!consumer)
-            return;
-
-          consumer->OnDisconnect();
-        });
-      };
-      policy_->ShouldAllowConsumerSession(args);
+          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_DFATAL("Not reached");
+    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, requested_backend_type));
+      new TracingSessionImpl(this, session_id));
 }
 
 void TracingMuxerImpl::InitializeInstance(const TracingInitArgs& args) {
-  if (instance_ != TracingMuxerFake::Get())
+  if (instance_)
     PERFETTO_FATAL("Tracing already initialized");
-  new TracingMuxerImpl(args);
+  instance_ = new TracingMuxerImpl(args);
 }
 
 TracingMuxer::~TracingMuxer() = default;
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
index d0898a7..6c19902 100644
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ b/src/tracing/internal/tracing_muxer_impl.h
@@ -23,7 +23,6 @@
 #include <array>
 #include <atomic>
 #include <bitset>
-#include <list>
 #include <map>
 #include <memory>
 #include <vector>
@@ -39,9 +38,6 @@
 #include "perfetto/tracing/internal/basic_types.h"
 #include "perfetto/tracing/internal/tracing_muxer.h"
 #include "perfetto/tracing/tracing.h"
-
-#include "protos/perfetto/common/interceptor_descriptor.gen.h"
-
 namespace perfetto {
 
 class ConsumerEndpoint;
@@ -103,61 +99,31 @@
                           DataSourceFactory,
                           DataSourceStaticState*) override;
   std::unique_ptr<TraceWriterBase> CreateTraceWriter(
-      DataSourceStaticState*,
-      uint32_t data_source_instance_index,
       DataSourceState*,
       BufferExhaustedPolicy buffer_exhausted_policy) override;
   void DestroyStoppedTraceWritersForCurrentThread() override;
-  void RegisterInterceptor(const InterceptorDescriptor&,
-                           InterceptorFactory,
-                           InterceptorBase::TLSFactory,
-                           InterceptorBase::TracePacketCallback) override;
 
   std::unique_ptr<TracingSession> CreateTracingSession(BackendType);
 
   // Producer-side bookkeeping methods.
   void UpdateDataSourcesOnAllBackends();
   void SetupDataSource(TracingBackendId,
-                       uint32_t backend_connection_id,
                        DataSourceInstanceID,
                        const DataSourceConfig&);
   void StartDataSource(TracingBackendId, DataSourceInstanceID);
   void StopDataSource_AsyncBegin(TracingBackendId, DataSourceInstanceID);
   void StopDataSource_AsyncEnd(TracingBackendId, DataSourceInstanceID);
-  void ClearDataSourceIncrementalState(TracingBackendId, DataSourceInstanceID);
-  void SyncProducersForTesting();
 
   // Consumer-side bookkeeping methods.
   void SetupTracingSession(TracingSessionGlobalID,
                            const std::shared_ptr<TraceConfig>&,
                            base::ScopedFile trace_fd = base::ScopedFile());
   void StartTracingSession(TracingSessionGlobalID);
-  void ChangeTracingSessionConfig(TracingSessionGlobalID, const TraceConfig&);
   void StopTracingSession(TracingSessionGlobalID);
   void DestroyTracingSession(TracingSessionGlobalID);
-  void FlushTracingSession(TracingSessionGlobalID,
-                           uint32_t,
-                           std::function<void(bool)>);
   void ReadTracingSessionData(
       TracingSessionGlobalID,
       std::function<void(TracingSession::ReadTraceCallbackArgs)>);
-  void GetTraceStats(TracingSessionGlobalID,
-                     TracingSession::GetTraceStatsCallback);
-  void QueryServiceState(TracingSessionGlobalID,
-                         TracingSession::QueryServiceStateCallback);
-
-  // Sets the batching period to |batch_commits_duration_ms| on the backends
-  // with type |backend_type|.
-  void SetBatchCommitsDurationForTesting(uint32_t batch_commits_duration_ms,
-                                         BackendType backend_type);
-
-  // Enables direct SMB patching on the backends with type |backend_type| (see
-  // SharedMemoryArbiter::EnableDirectSMBPatching). Returns true if the
-  // operation succeeded for all backends with type |backend_type|, false
-  // otherwise.
-  bool EnableDirectSMBPatchingForTesting(BackendType backend_type);
-
-  void SetMaxProducerReconnectionsForTesting(uint32_t count);
 
  private:
   // For each TracingBackend we create and register one ProducerImpl instance.
@@ -169,9 +135,7 @@
   // because the Producer virtual methods don't allow to identify the service.
   class ProducerImpl : public Producer {
    public:
-    ProducerImpl(TracingMuxerImpl*,
-                 TracingBackendId,
-                 uint32_t shmem_batch_commits_duration_ms);
+    ProducerImpl(TracingMuxerImpl*, TracingBackendId);
     ~ProducerImpl() override;
 
     void Initialize(std::unique_ptr<ProducerEndpoint> endpoint);
@@ -191,38 +155,17 @@
     void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
     void ClearIncrementalState(const DataSourceInstanceID*, size_t) override;
 
-    void SweepDeadServices();
-
     PERFETTO_THREAD_CHECKER(thread_checker_)
     TracingMuxerImpl* const muxer_;
     TracingBackendId const backend_id_;
     bool connected_ = false;
-    uint32_t connection_id_ = 0;
-
-    const uint32_t shmem_batch_commits_duration_ms_ = 0;
 
     // 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_{};
 
-    // A collection of disconnected service endpoints. Since trace writers on
-    // arbitrary threads might continue writing data to disconnected services,
-    // we keep the old services around and periodically try to clean up ones
-    // that no longer have any writers (see SweepDeadServices).
-    std::list<std::shared_ptr<ProducerEndpoint>> dead_services_;
-
-    // The currently active service endpoint is maintained as an atomic shared
-    // pointer so it won't get deleted from underneath threads that are creating
-    // trace writers. At any given time one endpoint can be shared (and thus
-    // kept alive) by the |service_| pointer, an entry in |dead_services_| and
-    // as a pointer on the stack in CreateTraceWriter() (on an arbitrary
-    // thread). The endpoint is never shared outside ProducerImpl itself.
-    //
-    // WARNING: Any *write* access to this variable or any *read* access from a
-    // non-muxer thread must be done through std::atomic_{load,store} to avoid
-    // data races.
-    std::shared_ptr<ProducerEndpoint> service_;  // Keep last.
+    std::unique_ptr<ProducerEndpoint> service_;  // Keep last.
   };
 
   // For each TracingSession created by the API client (Tracing::NewTrace() we
@@ -233,10 +176,7 @@
   // tracing sessions.
   class ConsumerImpl : public Consumer {
    public:
-    ConsumerImpl(TracingMuxerImpl*,
-                 BackendType,
-                 TracingBackendId,
-                 TracingSessionGlobalID);
+    ConsumerImpl(TracingMuxerImpl*, TracingBackendId, TracingSessionGlobalID);
     ~ConsumerImpl() override;
 
     void Initialize(std::unique_ptr<ConsumerEndpoint> endpoint);
@@ -244,7 +184,7 @@
     // perfetto::Consumer implementation.
     void OnConnect() override;
     void OnDisconnect() override;
-    void OnTracingDisabled(const std::string& error) 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;
@@ -252,14 +192,12 @@
     void OnObservableEvents(const ObservableEvents&) override;
 
     void NotifyStartComplete();
-    void NotifyError(const TracingError&);
     void NotifyStopComplete();
 
     // Will eventually inform the |muxer_| when it is safe to remove |this|.
     void Disconnect();
 
     TracingMuxerImpl* const muxer_;
-    BackendType const backend_type_;
     TracingBackendId const backend_id_;
     TracingSessionGlobalID const session_id_;
     bool connected_ = false;
@@ -273,10 +211,6 @@
     // need to wait until the session has started before stopping it.
     bool stop_pending_ = false;
 
-    // Similarly we need to buffer a call to get trace statistics if the
-    // consumer wasn't connected yet.
-    bool get_trace_stats_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).
@@ -287,17 +221,9 @@
     std::shared_ptr<TraceConfig> trace_config_;
     base::ScopedFile trace_fd_;
 
-    // If the API client passes a callback to start, we should invoke this when
-    // NotifyStartComplete() is invoked.
-    std::function<void()> start_complete_callback_;
-
     // An internal callback used to implement StartBlocking().
     std::function<void()> blocking_start_complete_callback_;
 
-    // If the API client passes a callback to get notification about the
-    // errors, we should invoke this when NotifyError() is invoked.
-    std::function<void(TracingError)> error_callback_;
-
     // If the API client passes a callback to stop, we should invoke this when
     // OnTracingDisabled() is invoked.
     std::function<void()> stop_complete_callback_;
@@ -309,12 +235,6 @@
     std::function<void(TracingSession::ReadTraceCallbackArgs)>
         read_trace_callback_;
 
-    // Callback passed to GetTraceStats().
-    TracingSession::GetTraceStatsCallback get_trace_stats_callback_;
-
-    // Callback for a pending call to QueryServiceState().
-    TracingSession::QueryServiceStateCallback query_service_state_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>;
@@ -328,26 +248,19 @@
   // Tracing::CreateTracingSession().
   class TracingSessionImpl : public TracingSession {
    public:
-    TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID, BackendType);
+    TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID);
     ~TracingSessionImpl() override;
     void Setup(const TraceConfig&, int fd) override;
     void Start() override;
     void StartBlocking() override;
-    void SetOnStartCallback(std::function<void()>) override;
-    void SetOnErrorCallback(std::function<void(TracingError)>) override;
     void Stop() override;
     void StopBlocking() override;
-    void Flush(std::function<void(bool)>, uint32_t timeout_ms) override;
     void ReadTrace(ReadTraceCallback) override;
     void SetOnStopCallback(std::function<void()>) override;
-    void GetTraceStats(GetTraceStatsCallback) override;
-    void QueryServiceState(QueryServiceStateCallback) override;
-    void ChangeTraceConfig(const TraceConfig&) override;
 
    private:
     TracingMuxerImpl* const muxer_;
     TracingSessionGlobalID const session_id_;
-    BackendType const backend_type_;
   };
 
   struct RegisteredDataSource {
@@ -356,20 +269,12 @@
     DataSourceStaticState* static_state = nullptr;
   };
 
-  struct RegisteredInterceptor {
-    protos::gen::InterceptorDescriptor descriptor;
-    InterceptorFactory factory{};
-    InterceptorBase::TLSFactory tls_factory{};
-    InterceptorBase::TracePacketCallback packet_callback{};
-  };
-
   struct RegisteredBackend {
     // Backends are supposed to have static lifetime.
     TracingBackend* backend = nullptr;
     TracingBackendId id = 0;
     BackendType type{};
 
-    TracingBackend::ConnectProducerArgs producer_conn_args;
     std::unique_ptr<ProducerImpl> producer;
 
     // The calling code can request more than one concurrently active tracing
@@ -380,9 +285,7 @@
   explicit TracingMuxerImpl(const TracingInitArgs&);
   void Initialize(const TracingInitArgs& args);
   ConsumerImpl* FindConsumer(TracingSessionGlobalID session_id);
-  void InitializeConsumer(TracingSessionGlobalID session_id);
   void OnConsumerDisconnected(ConsumerImpl* consumer);
-  void OnProducerDisconnected(ProducerImpl* producer);
 
   struct FindDataSourceRes {
     FindDataSourceRes() = default;
@@ -399,15 +302,9 @@
   std::unique_ptr<base::TaskRunner> task_runner_;
   std::vector<RegisteredDataSource> data_sources_;
   std::vector<RegisteredBackend> backends_;
-  std::vector<RegisteredInterceptor> interceptors_;
-  TracingPolicy* policy_ = nullptr;
 
   std::atomic<TracingSessionGlobalID> next_tracing_session_id_{};
 
-  // Maximum number of times we will try to reconnect producer backend.
-  // Should only be modified for testing purposes.
-  std::atomic<uint32_t> max_producer_reconnections_{100u};
-
   PERFETTO_THREAD_CHECKER(thread_checker_)
 };
 
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 736c312..94c2a77 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -20,7 +20,6 @@
 #include "perfetto/base/thread_utils.h"
 #include "perfetto/base/time.h"
 #include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/internal/track_event_interned_fields.h"
 #include "perfetto/tracing/track_event.h"
 #include "perfetto/tracing/track_event_category_registry.h"
 #include "perfetto/tracing/track_event_interned_data_index.h"
@@ -32,12 +31,6 @@
 #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
 
 namespace perfetto {
-
-TrackEventSessionObserver::~TrackEventSessionObserver() = default;
-void TrackEventSessionObserver::OnSetup(const DataSourceBase::SetupArgs&) {}
-void TrackEventSessionObserver::OnStart(const DataSourceBase::StartArgs&) {}
-void TrackEventSessionObserver::OnStop(const DataSourceBase::StopArgs&) {}
-
 namespace internal {
 
 BaseTrackEventInternedDataIndex::~BaseTrackEventInternedDataIndex() = default;
@@ -49,18 +42,52 @@
 static constexpr const char kSlowTag[] = "slow";
 static constexpr const char kDebugTag[] = "debug";
 
-void ForEachObserver(
-    std::function<bool(TrackEventSessionObserver*&)> callback) {
-  // Session observers, shared by all track event data source instances.
-  static constexpr int kMaxObservers = 8;
-  static std::recursive_mutex* mutex = new std::recursive_mutex{};  // Leaked.
-  static std::array<TrackEventSessionObserver*, kMaxObservers> observers{};
-  std::unique_lock<std::recursive_mutex> lock(*mutex);
-  for (auto& o : observers) {
-    if (!callback(o))
-      break;
+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,
+                  size_t length) {
+    auto category = interned_data->add_event_categories();
+    category->set_iid(iid);
+    category->set_name(value, length);
   }
-}
+};
+
+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);
+  }
+};
+
+struct InternedDebugAnnotationName
+    : public TrackEventInternedDataIndex<
+          InternedDebugAnnotationName,
+          perfetto::protos::pbzero::InternedData::
+              kDebugAnnotationNamesFieldNumber,
+          const char*,
+          SmallInternedDataTraits> {
+  static void Add(protos::pbzero::InternedData* interned_data,
+                  size_t iid,
+                  const char* value) {
+    auto name = interned_data->add_debug_annotation_names();
+    name->set_iid(iid);
+    name->set_name(value);
+  }
+};
 
 enum class MatchType { kExact, kPattern };
 
@@ -92,12 +119,6 @@
 }  // namespace
 
 // static
-const Track TrackEventInternal::kDefaultTrack{};
-
-// static
-std::atomic<int> TrackEventInternal::session_count_{};
-
-// static
 bool TrackEventInternal::Initialize(
     const TrackEventCategoryRegistry& registry,
     bool (*register_data_source)(const DataSourceDescriptor&)) {
@@ -131,69 +152,22 @@
 }
 
 // static
-bool TrackEventInternal::AddSessionObserver(
-    TrackEventSessionObserver* observer) {
-  bool result = false;
-  ForEachObserver([&](TrackEventSessionObserver*& o) {
-    if (!o) {
-      o = observer;
-      result = true;
-      return false;
-    }
-    return true;
-  });
-  return result;
-}
-
-// static
-void TrackEventInternal::RemoveSessionObserver(
-    TrackEventSessionObserver* observer) {
-  ForEachObserver([&](TrackEventSessionObserver*& o) {
-    if (o == observer) {
-      o = nullptr;
-      return false;
-    }
-    return true;
-  });
-}
-
-// static
 void TrackEventInternal::EnableTracing(
     const TrackEventCategoryRegistry& registry,
     const protos::gen::TrackEventConfig& config,
-    const DataSourceBase::SetupArgs& args) {
+    uint32_t instance_index) {
   for (size_t i = 0; i < registry.category_count(); i++) {
     if (IsCategoryEnabled(registry, config, *registry.GetCategory(i)))
-      registry.EnableCategoryForInstance(i, args.internal_instance_index);
+      registry.EnableCategoryForInstance(i, instance_index);
   }
-  ForEachObserver([&](TrackEventSessionObserver*& o) {
-    if (o)
-      o->OnSetup(args);
-    return true;
-  });
-}
-
-// static
-void TrackEventInternal::OnStart(const DataSourceBase::StartArgs& args) {
-  session_count_.fetch_add(1);
-  ForEachObserver([&](TrackEventSessionObserver*& o) {
-    if (o)
-      o->OnStart(args);
-    return true;
-  });
 }
 
 // static
 void TrackEventInternal::DisableTracing(
     const TrackEventCategoryRegistry& registry,
-    const DataSourceBase::StopArgs& args) {
-  ForEachObserver([&](TrackEventSessionObserver*& o) {
-    if (o)
-      o->OnStop(args);
-    return true;
-  });
+    uint32_t instance_index) {
   for (size_t i = 0; i < registry.category_count(); i++)
-    registry.DisableCategoryForInstance(i, args.internal_instance_index);
+    registry.DisableCategoryForInstance(i, instance_index);
 }
 
 // static
@@ -223,14 +197,6 @@
         }
         break;
       }
-      // No match? Must be a dynamic category.
-      DynamicCategory dyn_category(std::string(member_name, name_size));
-      Category ref_category{Category::FromDynamicCategory(dyn_category)};
-      if (IsCategoryEnabled(registry, config, ref_category)) {
-        result = true;
-        // Break ForEachGroupMember() loop.
-        return false;
-      }
       // No match found => keep iterating.
       return true;
     });
@@ -303,11 +269,6 @@
 }
 
 // static
-int TrackEventInternal::GetSessionCount() {
-  return session_count_.load();
-}
-
-// static
 void TrackEventInternal::ResetIncrementalState(TraceWriterBase* trace_writer,
                                                uint64_t timestamp) {
   auto default_track = ThreadTrack::Current();
@@ -358,8 +319,11 @@
     perfetto::protos::pbzero::TrackEvent::Type type,
     uint64_t timestamp) {
   PERFETTO_DCHECK(g_main_thread);
-  PERFETTO_DCHECK(!incr_state->was_cleared);
 
+  if (incr_state->was_cleared) {
+    incr_state->was_cleared = false;
+    ResetIncrementalState(trace_writer, timestamp);
+  }
   auto packet = NewTracePacket(trace_writer, timestamp);
   EventContext ctx(std::move(packet), incr_state);
 
@@ -369,9 +333,7 @@
 
   // We assume that |category| and |name| point to strings with static lifetime.
   // This means we can use their addresses as interning keys.
-  // TODO(skyostil): Intern categories at compile time.
-  if (category && type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
-      type != protos::pbzero::TrackEvent::TYPE_COUNTER) {
+  if (category && type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
     category->ForEachGroupMember(
         [&](const char* member_name, size_t name_size) {
           size_t category_iid =
@@ -380,7 +342,7 @@
           return true;
         });
   }
-  if (name && type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
+  if (name) {
     size_t name_iid = InternedEventName::Get(&ctx, name);
     track_event->set_name_iid(name_iid);
   }
diff --git a/src/tracing/internal/track_event_interned_fields.cc b/src/tracing/internal/track_event_interned_fields.cc
deleted file mode 100644
index 804aeb4..0000000
--- a/src/tracing/internal/track_event_interned_fields.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_interned_fields.h"
-
-namespace perfetto {
-namespace internal {
-
-InternedEventCategory::~InternedEventCategory() = default;
-
-// static
-void InternedEventCategory::Add(protos::pbzero::InternedData* interned_data,
-                                size_t iid,
-                                const char* value,
-                                size_t length) {
-  auto category = interned_data->add_event_categories();
-  category->set_iid(iid);
-  category->set_name(value, length);
-}
-
-InternedEventName::~InternedEventName() = default;
-
-// static
-void InternedEventName::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);
-}
-
-InternedDebugAnnotationName::~InternedDebugAnnotationName() = default;
-
-// static
-void InternedDebugAnnotationName::Add(
-    protos::pbzero::InternedData* interned_data,
-    size_t iid,
-    const char* value) {
-  auto name = interned_data->add_debug_annotation_names();
-  name->set_iid(iid);
-  name->set_name(value);
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/ipc/consumer/BUILD.gn b/src/tracing/ipc/consumer/BUILD.gn
index 03c9559..0a2dcc2 100644
--- a/src/tracing/ipc/consumer/BUILD.gn
+++ b/src/tracing/ipc/consumer/BUILD.gn
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("../../../../gn/perfetto.gni")
-import("../../../../gn/perfetto_component.gni")
 
 assert(enable_perfetto_ipc)
 
@@ -33,10 +32,6 @@
     "..:common",
     "../../../../gn:default_deps",
     "../../../base",
+    "../../../ipc:client",
   ]
-  if (perfetto_component_type == "static_library") {
-    deps += [ "../../../ipc:perfetto_ipc" ]
-  } else {
-    deps += [ "../../../ipc:client" ]
-  }
 }
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index e77c03f..7d60e5e 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -46,9 +46,7 @@
                                              Consumer* consumer,
                                              base::TaskRunner* task_runner)
     : consumer_(consumer),
-      ipc_channel_(
-          ipc::Client::CreateInstance({service_sock_name, /*sock_retry=*/false},
-                                      task_runner)),
+      ipc_channel_(ipc::Client::CreateInstance(service_sock_name, task_runner)),
       consumer_port_(this /* event_listener */),
       weak_ptr_factory_(this) {
   ipc_channel_->BindService(consumer_port_.GetWeakPtr());
@@ -65,7 +63,7 @@
 void ConsumerIPCClientImpl::OnDisconnect() {
   PERFETTO_DLOG("Tracing service connection failure");
   connected_ = false;
-  consumer_->OnDisconnect();  // Note: may delete |this|.
+  consumer_->OnDisconnect();
 }
 
 void ConsumerIPCClientImpl::EnableTracing(const TraceConfig& trace_config,
@@ -75,14 +73,6 @@
     return;
   }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  if (fd) {
-    consumer_->OnTracingDisabled(
-        "Passing FDs for write_into_file is not supported on Windows");
-    return;
-  }
-#endif
-
   protos::gen::EnableTracingRequest req;
   *req.mutable_trace_config() = trace_config;
   ipc::Deferred<protos::gen::EnableTracingResponse> async_response;
@@ -99,7 +89,7 @@
   consumer_port_.EnableTracing(req, std::move(async_response), *fd);
 }
 
-void ConsumerIPCClientImpl::ChangeTraceConfig(const TraceConfig& trace_config) {
+void ConsumerIPCClientImpl::ChangeTraceConfig(const TraceConfig&) {
   if (!connected_) {
     PERFETTO_DLOG(
         "Cannot ChangeTraceConfig(), not connected to tracing service");
@@ -113,7 +103,6 @@
           PERFETTO_DLOG("ChangeTraceConfig() failed");
       });
   protos::gen::ChangeTraceConfigRequest req;
-  *req.mutable_trace_config() = trace_config;
   consumer_port_.ChangeTraceConfig(req, std::move(async_response));
 }
 
@@ -190,18 +179,8 @@
 
 void ConsumerIPCClientImpl::OnEnableTracingResponse(
     ipc::AsyncResult<protos::gen::EnableTracingResponse> response) {
-  std::string error;
-  // |response| might be empty when the request gets rejected (if the connection
-  // with the service is dropped all outstanding requests are auto-rejected).
-  if (!response) {
-    error =
-        "EnableTracing IPC request rejected. This is likely due to a loss of "
-        "the traced connection";
-  } else {
-    error = response->error();
-  }
   if (!response || response->disabled())
-    consumer_->OnTracingDisabled(error);
+    consumer_->OnTracingDisabled();
 }
 
 void ConsumerIPCClientImpl::FreeBuffers() {
@@ -343,7 +322,7 @@
       [this](ipc::AsyncResult<protos::gen::ObserveEventsResponse> response) {
         // Skip empty response, which the service sends to close the stream.
         if (!response.has_more()) {
-          PERFETTO_DCHECK(!response.success());
+          PERFETTO_DCHECK(!response->events().instance_state_changes().size());
           return;
         }
         consumer_->OnObservableEvents(response->events());
@@ -432,30 +411,4 @@
   consumer_port_.QueryCapabilities(req, std::move(async_response));
 }
 
-void ConsumerIPCClientImpl::SaveTraceForBugreport(
-    SaveTraceForBugreportCallback callback) {
-  if (!connected_) {
-    PERFETTO_DLOG(
-        "Cannot SaveTraceForBugreport(), not connected to tracing service");
-    return;
-  }
-
-  protos::gen::SaveTraceForBugreportRequest req;
-  ipc::Deferred<protos::gen::SaveTraceForBugreportResponse> async_response;
-  async_response.Bind(
-      [callback](ipc::AsyncResult<protos::gen::SaveTraceForBugreportResponse>
-                     response) {
-        if (!response) {
-          // If the IPC fails, we are talking to an older version of the service
-          // that didn't support SaveTraceForBugreport at all.
-          callback(
-              false,
-              "The tracing service doesn't support SaveTraceForBugreport()");
-        } else {
-          callback(response->success(), response->msg());
-        }
-      });
-  consumer_port_.SaveTraceForBugreport(req, std::move(async_response));
-}
-
 }  // namespace perfetto
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
index 7d7d6fa..ff305f6 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
@@ -73,7 +73,6 @@
   void ObserveEvents(uint32_t enabled_event_types) override;
   void QueryServiceState(QueryServiceStateCallback) override;
   void QueryCapabilities(QueryCapabilitiesCallback) override;
-  void SaveTraceForBugreport(SaveTraceForBugreportCallback) override;
 
   // ipc::ServiceProxy::EventListener implementation.
   // These methods are invoked by the IPC layer, which knows nothing about
diff --git a/src/tracing/ipc/default_socket.cc b/src/tracing/ipc/default_socket.cc
index 3ad5cee..519bb06 100644
--- a/src/tracing/ipc/default_socket.cc
+++ b/src/tracing/ipc/default_socket.cc
@@ -17,79 +17,34 @@
 #include "perfetto/ext/tracing/ipc/default_socket.h"
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/ipc/basic_types.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 
 #include <stdlib.h>
-#include <unistd.h>
 
 namespace perfetto {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-// On non-Android platforms, check /run/perfetto/ before using /tmp/ as the
-// socket base directory.
-namespace {
-const char* kRunPerfettoBaseDir = "/run/perfetto/";
-
-bool UseRunPerfettoBaseDir() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-  // Note that the trailing / in |kRunPerfettoBaseDir| ensures we are checking
-  // against a directory, not a file.
-  int res = PERFETTO_EINTR(access(kRunPerfettoBaseDir, X_OK));
-  if (!res)
-    return true;
-
-  // If the path doesn't exist (ENOENT), fail silently to the caller. Otherwise,
-  // fail with an explicit error message.
-  if (errno != ENOENT) {
-    PERFETTO_PLOG("%s exists but cannot be accessed. Falling back on /tmp/ ",
-                  kRunPerfettoBaseDir);
-  }
-  return false;
-#else
-  return false;
-#endif
-}
-
-}  // anonymous namespace
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 
 static_assert(kInvalidUid == ipc::kInvalidUid, "kInvalidUid mismatching");
 
 const char* GetProducerSocket() {
-  const char* name = getenv("PERFETTO_PRODUCER_SOCK_NAME");
+  static const char* name = getenv("PERFETTO_PRODUCER_SOCK_NAME");
   if (name == nullptr) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    name = "127.0.0.1:32278";
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     name = "/dev/socket/traced_producer";
 #else
-    // Use /run/perfetto if it exists. Then fallback to /tmp.
-    static const char* producer_socket =
-        UseRunPerfettoBaseDir() ? "/run/perfetto/traced-producer.sock"
-                                : "/tmp/perfetto-producer";
-    name = producer_socket;
+    name = "/tmp/perfetto-producer";
 #endif
   }
   return name;
 }
 
 const char* GetConsumerSocket() {
-  const char* name = getenv("PERFETTO_CONSUMER_SOCK_NAME");
+  static const char* name = getenv("PERFETTO_CONSUMER_SOCK_NAME");
   if (name == nullptr) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    name = "127.0.0.1:32279";
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     name = "/dev/socket/traced_consumer";
 #else
-    // Use /run/perfetto if it exists. Then fallback to /tmp.
-    static const char* consumer_socket =
-        UseRunPerfettoBaseDir() ? "/run/perfetto/traced-consumer.sock"
-                                : "/tmp/perfetto-consumer";
-    name = consumer_socket;
+    name = "/tmp/perfetto-consumer";
 #endif
   }
   return name;
diff --git a/src/tracing/ipc/posix_shared_memory.cc b/src/tracing/ipc/posix_shared_memory.cc
index 3a59948..5fc7982 100644
--- a/src/tracing/ipc/posix_shared_memory.cc
+++ b/src/tracing/ipc/posix_shared_memory.cc
@@ -16,10 +16,6 @@
 
 #include "src/tracing/ipc/posix_shared_memory.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-
 #include <fcntl.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -131,5 +127,3 @@
 }
 
 }  // namespace perfetto
-
-#endif  // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/ipc/posix_shared_memory.h b/src/tracing/ipc/posix_shared_memory.h
index 18c7dd7..e637015 100644
--- a/src/tracing/ipc/posix_shared_memory.h
+++ b/src/tracing/ipc/posix_shared_memory.h
@@ -17,12 +17,6 @@
 #ifndef SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
 #define SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
 
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-
 #include <stddef.h>
 
 #include <memory>
@@ -56,7 +50,7 @@
 
   ~PosixSharedMemory() override;
 
-  int fd() const { return fd_.get(); }
+  int fd() const override { return fd_.get(); }
 
   // SharedMemory implementation.
   void* start() const override { return start_; }
@@ -76,5 +70,4 @@
 
 }  // namespace perfetto
 
-#endif  // OS_LINUX || OS_ANDROID || OS_APPLE
 #endif  // SRC_TRACING_IPC_POSIX_SHARED_MEMORY_H_
diff --git a/src/tracing/ipc/posix_shared_memory_unittest.cc b/src/tracing/ipc/posix_shared_memory_unittest.cc
index b3c5967..e5589d0 100644
--- a/src/tracing/ipc/posix_shared_memory_unittest.cc
+++ b/src/tracing/ipc/posix_shared_memory_unittest.cc
@@ -16,10 +16,6 @@
 
 #include "src/tracing/ipc/posix_shared_memory.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -47,12 +43,12 @@
 TEST(PosixSharedMemoryTest, DestructorUnmapsMemory) {
   PosixSharedMemory::Factory factory;
   std::unique_ptr<SharedMemory> shm =
-      factory.CreateSharedMemory(base::GetSysPageSize());
+      factory.CreateSharedMemory(base::kPageSize);
   ASSERT_NE(shm.get(), nullptr);
   void* const shm_start = shm->start();
   const size_t shm_size = shm->size();
   ASSERT_NE(nullptr, shm_start);
-  ASSERT_EQ(base::GetSysPageSize(), shm_size);
+  ASSERT_EQ(base::kPageSize, shm_size);
 
   memcpy(shm_start, "test", 5);
   ASSERT_TRUE(base::vm_test_utils::IsMapped(shm_start, shm_size));
@@ -63,11 +59,11 @@
 
 TEST(PosixSharedMemoryTest, DestructorClosesFD) {
   std::unique_ptr<PosixSharedMemory> shm =
-      PosixSharedMemory::Create(base::GetSysPageSize());
+      PosixSharedMemory::Create(base::kPageSize);
   ASSERT_NE(shm.get(), nullptr);
   int fd = shm->fd();
   ASSERT_GE(fd, 0);
-  ASSERT_EQ(static_cast<off_t>(base::GetSysPageSize()), lseek(fd, 0, SEEK_END));
+  ASSERT_EQ(static_cast<off_t>(base::kPageSize), lseek(fd, 0, SEEK_END));
 
   shm.reset();
   ASSERT_TRUE(IsFileDescriptorClosed(fd));
@@ -76,7 +72,7 @@
 TEST(PosixSharedMemoryTest, AttachToFdWithoutSeals) {
   base::TempFile tmp_file = base::TempFile::CreateUnlinked();
   const int fd_num = tmp_file.fd();
-  ASSERT_EQ(0, ftruncate(fd_num, static_cast<off_t>(base::GetSysPageSize())));
+  ASSERT_EQ(0, ftruncate(fd_num, base::kPageSize));
   ASSERT_EQ(7, base::WriteAll(fd_num, "foobar", 7));
 
   std::unique_ptr<PosixSharedMemory> shm = PosixSharedMemory::AttachToFd(
@@ -85,7 +81,7 @@
   void* const shm_start = shm->start();
   const size_t shm_size = shm->size();
   ASSERT_NE(nullptr, shm_start);
-  ASSERT_EQ(base::GetSysPageSize(), shm_size);
+  ASSERT_EQ(base::kPageSize, shm_size);
   ASSERT_EQ(0, memcmp("foobar", shm_start, 7));
 
   ASSERT_FALSE(IsFileDescriptorClosed(fd_num));
@@ -98,7 +94,7 @@
 TEST(PosixSharedMemoryTest, AttachToFdRequiresSeals) {
   base::TempFile tmp_file = base::TempFile::CreateUnlinked();
   const int fd_num = tmp_file.fd();
-  ASSERT_EQ(0, ftruncate(fd_num, static_cast<off_t>(base::GetSysPageSize())));
+  ASSERT_EQ(0, ftruncate(fd_num, base::kPageSize));
 
   std::unique_ptr<PosixSharedMemory> shm =
       PosixSharedMemory::AttachToFd(tmp_file.ReleaseFD());
@@ -112,15 +108,12 @@
 }
 
 TEST(PosixSharedMemoryTest, CreateAndMap) {
-  // Deliberately trying to cover cases where the shm size is smaller than the
-  // system page size (crbug.com/1116576).
-  const size_t kLessThanAPage = 2048;
   std::unique_ptr<PosixSharedMemory> shm =
-      PosixSharedMemory::Create(kLessThanAPage);
+      PosixSharedMemory::Create(base::kPageSize);
   void* const shm_start = shm->start();
   const size_t shm_size = shm->size();
   ASSERT_NE(shm_start, nullptr);
-  ASSERT_EQ(shm_size, kLessThanAPage);
+  ASSERT_EQ(shm_size, base::kPageSize);
 
   memcpy(shm_start, "test", 5);
   ASSERT_TRUE(base::vm_test_utils::IsMapped(shm_start, shm_size));
@@ -148,4 +141,3 @@
 
 }  // namespace
 }  // namespace perfetto
-#endif  // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/ipc/producer/BUILD.gn b/src/tracing/ipc/producer/BUILD.gn
index 8d37539..c7e0d8a 100644
--- a/src/tracing/ipc/producer/BUILD.gn
+++ b/src/tracing/ipc/producer/BUILD.gn
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("../../../../gn/perfetto.gni")
-import("../../../../gn/perfetto_component.gni")
 
 assert(enable_perfetto_ipc)
 
@@ -33,10 +32,6 @@
     "..:common",
     "../../../../gn:default_deps",
     "../../../base",
+    "../../../ipc:client",
   ]
-  if (perfetto_component_type == "static_library") {
-    deps += [ "../../../ipc:perfetto_ipc" ]
-  } else {
-    deps += [ "../../../ipc:client" ]
-  }
 }
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index 98072cd..58fc05d 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -21,7 +21,6 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/version.h"
 #include "perfetto/ext/ipc/client.h"
 #include "perfetto/ext/tracing/core/commit_data_request.h"
 #include "perfetto/ext/tracing/core/producer.h"
@@ -48,31 +47,9 @@
     size_t shared_memory_size_hint_bytes,
     size_t shared_memory_page_size_hint_bytes,
     std::unique_ptr<SharedMemory> shm,
-    std::unique_ptr<SharedMemoryArbiter> shm_arbiter,
-    ConnectionFlags conn_flags) {
-  return std::unique_ptr<TracingService::ProducerEndpoint>(
-      new ProducerIPCClientImpl(
-          {service_sock_name,
-           conn_flags ==
-               ProducerIPCClient::ConnectionFlags::kRetryIfUnreachable},
-          producer, producer_name, task_runner, smb_scraping_mode,
-          shared_memory_size_hint_bytes, shared_memory_page_size_hint_bytes,
-          std::move(shm), std::move(shm_arbiter)));
-}
-
-// static. (Declared in include/tracing/ipc/producer_ipc_client.h).
-std::unique_ptr<TracingService::ProducerEndpoint> ProducerIPCClient::Connect(
-    ipc::Client::ConnArgs conn_args,
-    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,
-    std::unique_ptr<SharedMemory> shm,
     std::unique_ptr<SharedMemoryArbiter> shm_arbiter) {
   return std::unique_ptr<TracingService::ProducerEndpoint>(
-      new ProducerIPCClientImpl(std::move(conn_args), producer, producer_name,
+      new ProducerIPCClientImpl(service_sock_name, producer, producer_name,
                                 task_runner, smb_scraping_mode,
                                 shared_memory_size_hint_bytes,
                                 shared_memory_page_size_hint_bytes,
@@ -80,7 +57,7 @@
 }
 
 ProducerIPCClientImpl::ProducerIPCClientImpl(
-    ipc::Client::ConnArgs conn_args,
+    const char* service_sock_name,
     Producer* producer,
     const std::string& producer_name,
     base::TaskRunner* task_runner,
@@ -91,8 +68,7 @@
     std::unique_ptr<SharedMemoryArbiter> shm_arbiter)
     : producer_(producer),
       task_runner_(task_runner),
-      ipc_channel_(
-          ipc::Client::CreateInstance(std::move(conn_args), task_runner)),
+      ipc_channel_(ipc::Client::CreateInstance(service_sock_name, task_runner)),
       producer_port_(this /* event_listener */),
       shared_memory_(std::move(shm)),
       shared_memory_arbiter_(std::move(shm_arbiter)),
@@ -116,9 +92,7 @@
   PERFETTO_DCHECK_THREAD(thread_checker_);
 }
 
-ProducerIPCClientImpl::~ProducerIPCClientImpl() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-}
+ProducerIPCClientImpl::~ProducerIPCClientImpl() = default;
 
 // Called by the IPC layer if the BindService() succeeds.
 void ProducerIPCClientImpl::OnConnect() {
@@ -133,8 +107,7 @@
       [this](ipc::AsyncResult<protos::gen::InitializeConnectionResponse> resp) {
         OnConnectionInitialized(
             resp.success(),
-            resp.success() ? resp->using_shmem_provided_by_producer() : false,
-            resp.success() ? resp->direct_smb_patching_supported() : false);
+            resp.success() ? resp->using_shmem_provided_by_producer() : false);
       });
   protos::gen::InitializeConnectionRequest req;
   req.set_producer_name(name_);
@@ -159,7 +132,7 @@
 
   int shm_fd = -1;
   if (shared_memory_) {
-    shm_fd = static_cast<PosixSharedMemory*>(shared_memory_.get())->fd();
+    shm_fd = shared_memory_->fd();
     req.set_producer_provided_shmem(true);
   }
 
@@ -170,7 +143,6 @@
   req.set_build_flags(
       protos::gen::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF);
 #endif
-  req.set_sdk_version(base::GetVersionString());
   producer_port_.InitializeConnection(req, std::move(on_init), shm_fd);
 
   // Create the back channel to receive commands from the Service.
@@ -194,21 +166,19 @@
   PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DLOG("Tracing service connection failure");
   connected_ = false;
+  producer_->OnDisconnect();
   data_sources_setup_.clear();
-  producer_->OnDisconnect();  // Note: may delete |this|.
 }
 
 void ProducerIPCClientImpl::OnConnectionInitialized(
     bool connection_succeeded,
-    bool using_shmem_provided_by_producer,
-    bool direct_smb_patching_supported) {
+    bool using_shmem_provided_by_producer) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   // If connection_succeeded == false, the OnDisconnect() call will follow next
   // and there we'll notify the |producer_|. TODO: add a test for this.
   if (!connection_succeeded)
     return;
   is_shmem_provided_by_producer_ = using_shmem_provided_by_producer;
-  direct_smb_patching_supported_ = direct_smb_patching_supported;
   producer_->OnConnect();
 
   // Bail out if the service failed to adopt our producer-allocated SMB.
@@ -269,8 +239,6 @@
       shared_memory_arbiter_ = SharedMemoryArbiter::CreateInstance(
           shared_memory_.get(), shared_buffer_page_size_kb_ * 1024, this,
           task_runner_);
-      if (direct_smb_patching_supported_)
-        shared_memory_arbiter_->SetDirectSMBPatchingSupportedByService();
     } else {
       // Producer-provided SMB (used by Chrome for startup tracing).
       PERFETTO_CHECK(is_shmem_provided_by_producer_ && shared_memory_ &&
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.h b/src/tracing/ipc/producer/producer_ipc_client_impl.h
index 3d66849..2995d38 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.h
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.h
@@ -23,7 +23,6 @@
 #include <vector>
 
 #include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/ipc/client.h"
 #include "perfetto/ext/ipc/service_proxy.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 #include "perfetto/ext/tracing/core/shared_memory.h"
@@ -38,6 +37,10 @@
 class TaskRunner;
 }  // namespace base
 
+namespace ipc {
+class Client;
+}  // namespace ipc
+
 class Producer;
 class SharedMemoryArbiter;
 
@@ -48,15 +51,16 @@
 class ProducerIPCClientImpl : public TracingService::ProducerEndpoint,
                               public ipc::ServiceProxy::EventListener {
  public:
-  ProducerIPCClientImpl(ipc::Client::ConnArgs,
-                        Producer*,
-                        const std::string& producer_name,
-                        base::TaskRunner*,
-                        TracingService::ProducerSMBScrapingMode,
-                        size_t shared_memory_size_hint_bytes,
-                        size_t shared_memory_page_size_hint_bytes,
-                        std::unique_ptr<SharedMemory> shm,
-                        std::unique_ptr<SharedMemoryArbiter> shm_arbiter);
+  ProducerIPCClientImpl(
+      const char* service_sock_name,
+      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,
+      std::unique_ptr<SharedMemory> shm = nullptr,
+      std::unique_ptr<SharedMemoryArbiter> shm_arbiter = nullptr);
   ~ProducerIPCClientImpl() override;
 
   // TracingService::ProducerEndpoint implementation.
@@ -87,13 +91,10 @@
   void OnConnect() override;
   void OnDisconnect() override;
 
-  ipc::Client* GetClientForTesting() { return ipc_channel_.get(); }
-
  private:
   // Invoked soon after having established the connection with the service.
   void OnConnectionInitialized(bool connection_succeeded,
-                               bool using_shmem_provided_by_producer,
-                               bool direct_smb_patching_supported);
+                               bool using_shmem_provided_by_producer);
 
   // Invoked when the remote Service sends an IPC to tell us to do something
   // (e.g. start/stop a data source).
@@ -120,7 +121,6 @@
   size_t shared_memory_size_hint_bytes_ = 0;
   TracingService::ProducerSMBScrapingMode const smb_scraping_mode_;
   bool is_shmem_provided_by_producer_ = false;
-  bool direct_smb_patching_supported_ = false;
   std::vector<std::function<void()>> pending_sync_reqs_;
   PERFETTO_THREAD_CHECKER(thread_checker_)
 };
diff --git a/src/tracing/ipc/service/BUILD.gn b/src/tracing/ipc/service/BUILD.gn
index d8c26d6..0bc401c 100644
--- a/src/tracing/ipc/service/BUILD.gn
+++ b/src/tracing/ipc/service/BUILD.gn
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 import("../../../../gn/perfetto.gni")
-import("../../../../gn/perfetto_component.gni")
 
 assert(enable_perfetto_ipc)
 
@@ -37,11 +36,7 @@
     "../../../../gn:default_deps",
     "../../../../protos/perfetto/ipc",
     "../../../base",
+    "../../../ipc:host",
     "../../core:service",
   ]
-  if (perfetto_component_type == "static_library") {
-    deps += [ "../../../ipc:perfetto_ipc" ]
-  } else {
-    deps += [ "../../../ipc:host" ]
-  }
 }
diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc
index daab5de..073bc74 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.cc
+++ b/src/tracing/ipc/service/consumer_ipc_service.cc
@@ -308,36 +308,6 @@
   response.Resolve(std::move(resp));
 }
 
-void ConsumerIPCService::SaveTraceForBugreport(
-    const protos::gen::SaveTraceForBugreportRequest&,
-    DeferredSaveTraceForBugreportResponse resp) {
-  RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
-  auto it = pending_bugreport_responses_.insert(
-      pending_bugreport_responses_.end(), std::move(resp));
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-  auto callback = [weak_this, it](bool success, const std::string& msg) {
-    if (weak_this)
-      weak_this->OnSaveTraceForBugreportCallback(success, msg, std::move(it));
-  };
-  remote_consumer->service_endpoint->SaveTraceForBugreport(callback);
-}
-
-// Called by the service in response to
-// service_endpoint->SaveTraceForBugreport().
-void ConsumerIPCService::OnSaveTraceForBugreportCallback(
-    bool success,
-    const std::string& msg,
-    PendingSaveTraceForBugreportResponses::iterator pending_response_it) {
-  DeferredSaveTraceForBugreportResponse response(
-      std::move(*pending_response_it));
-  pending_bugreport_responses_.erase(pending_response_it);
-  auto resp =
-      ipc::AsyncResult<protos::gen::SaveTraceForBugreportResponse>::Create();
-  resp->set_success(success);
-  resp->set_msg(msg);
-  response.Resolve(std::move(resp));
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // RemoteConsumer methods
 ////////////////////////////////////////////////////////////////////////////////
@@ -354,14 +324,11 @@
 // |service_endpoint| (in the RemoteConsumer dtor).
 void ConsumerIPCService::RemoteConsumer::OnDisconnect() {}
 
-void ConsumerIPCService::RemoteConsumer::OnTracingDisabled(
-    const std::string& error) {
+void ConsumerIPCService::RemoteConsumer::OnTracingDisabled() {
   if (enable_tracing_response.IsBound()) {
     auto result =
         ipc::AsyncResult<protos::gen::EnableTracingResponse>::Create();
     result->set_disabled(true);
-    if (!error.empty())
-      result->set_error(error);
     enable_tracing_response.Resolve(std::move(result));
   }
 }
diff --git a/src/tracing/ipc/service/consumer_ipc_service.h b/src/tracing/ipc/service/consumer_ipc_service.h
index e31f1c7..d513371 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.h
+++ b/src/tracing/ipc/service/consumer_ipc_service.h
@@ -69,8 +69,6 @@
                          DeferredQueryServiceStateResponse) override;
   void QueryCapabilities(const protos::gen::QueryCapabilitiesRequest&,
                          DeferredQueryCapabilitiesResponse) override;
-  void SaveTraceForBugreport(const protos::gen::SaveTraceForBugreportRequest&,
-                             DeferredSaveTraceForBugreportResponse) override;
   void OnClientDisconnected() override;
 
  private:
@@ -86,7 +84,7 @@
     // no connection here, these methods are posted straight away.
     void OnConnect() override;
     void OnDisconnect() override;
-    void OnTracingDisabled(const std::string& error) override;
+    void OnTracingDisabled() override;
     void OnTraceData(std::vector<TracePacket>, bool has_more) override;
     void OnDetach(bool) override;
     void OnAttach(bool, const TraceConfig&) override;
@@ -128,8 +126,6 @@
   using PendingQuerySvcResponses = std::list<DeferredQueryServiceStateResponse>;
   using PendingQueryCapabilitiesResponses =
       std::list<DeferredQueryCapabilitiesResponse>;
-  using PendingSaveTraceForBugreportResponses =
-      std::list<DeferredSaveTraceForBugreportResponse>;
 
   ConsumerIPCService(const ConsumerIPCService&) = delete;
   ConsumerIPCService& operator=(const ConsumerIPCService&) = delete;
@@ -144,10 +140,6 @@
                               PendingQuerySvcResponses::iterator);
   void OnQueryCapabilitiesCallback(const TracingServiceCapabilities&,
                                    PendingQueryCapabilitiesResponses::iterator);
-  void OnSaveTraceForBugreportCallback(
-      bool success,
-      const std::string& msg,
-      PendingSaveTraceForBugreportResponses::iterator);
 
   TracingService* const core_service_;
 
@@ -158,7 +150,6 @@
   PendingFlushResponses pending_flush_responses_;
   PendingQuerySvcResponses pending_query_service_responses_;
   PendingQueryCapabilitiesResponses pending_query_capabilities_responses_;
-  PendingSaveTraceForBugreportResponses pending_bugreport_responses_;
 
   base::WeakPtrFactory<ConsumerIPCService> weak_ptr_factory_;  // Keep last.
 };
diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc
index 76ae2e8..bd79f4f 100644
--- a/src/tracing/ipc/service/producer_ipc_service.cc
+++ b/src/tracing/ipc/service/producer_ipc_service.cc
@@ -79,16 +79,21 @@
       break;
   }
 
+  bool dcheck_mismatch = false;
 #if PERFETTO_DCHECK_IS_ON()
-  if (req.build_flags() ==
-      protos::gen::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF) {
-    PERFETTO_LOG(
-        "The producer is built with NDEBUG but the service binary was built "
-        "with the DEBUG flag. This will likely cause crashes.");
-    // The other way round (DEBUG producer with NDEBUG service) is expected to
-    // work.
-  }
+  dcheck_mismatch =
+      req.build_flags() ==
+      protos::gen::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF;
+#else
+  dcheck_mismatch =
+      req.build_flags() ==
+      protos::gen::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.");
+  }
 
   // If the producer provided an SMB, tell the service to attempt to adopt it.
   std::unique_ptr<SharedMemory> shmem;
@@ -114,8 +119,7 @@
       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(), std::move(shmem),
-      req.sdk_version());
+      req.shared_memory_page_size_hint_bytes(), std::move(shmem));
 
   // Could happen if the service has too many producers connected.
   if (!producer->service_endpoint) {
@@ -132,7 +136,6 @@
   auto async_res =
       ipc::AsyncResult<protos::gen::InitializeConnectionResponse>::Create();
   async_res->set_using_shmem_provided_by_producer(using_producer_shmem);
-  async_res->set_direct_smb_patching_supported(true);
   response.Resolve(std::move(async_res));
 }
 
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.cc b/src/tracing/ipc/service/service_ipc_host_impl.cc
index d19fef6..ad6f9ef 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.cc
+++ b/src/tracing/ipc/service/service_ipc_host_impl.cc
@@ -52,8 +52,8 @@
   return DoStart();
 }
 
-bool ServiceIPCHostImpl::Start(base::ScopedSocketHandle producer_socket_fd,
-                               base::ScopedSocketHandle consumer_socket_fd) {
+bool ServiceIPCHostImpl::Start(base::ScopedFile producer_socket_fd,
+                               base::ScopedFile consumer_socket_fd) {
   PERFETTO_CHECK(!svc_);  // Check if already started.
 
   // Initialize the IPC transport.
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.h b/src/tracing/ipc/service/service_ipc_host_impl.h
index 1aa73e1..d06ef60 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.h
+++ b/src/tracing/ipc/service/service_ipc_host_impl.h
@@ -39,8 +39,8 @@
   // ServiceIPCHost implementation.
   bool Start(const char* producer_socket_name,
              const char* consumer_socket_name) override;
-  bool Start(base::ScopedSocketHandle producer_socket_fd,
-             base::ScopedSocketHandle consumer_socket_fd) override;
+  bool Start(base::ScopedFile producer_socket_fd,
+             base::ScopedFile consumer_socket_fd) override;
 
   TracingService* service() const override;
 
diff --git a/src/tracing/platform_posix.cc b/src/tracing/platform_posix.cc
index 6b04aaf..75551fc 100644
--- a/src/tracing/platform_posix.cc
+++ b/src/tracing/platform_posix.cc
@@ -15,11 +15,6 @@
  */
 
 #include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
-
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/thread_task_runner.h"
 #include "perfetto/tracing/internal/tracing_tls.h"
@@ -47,6 +42,23 @@
   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() {
@@ -72,8 +84,7 @@
 
 std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
     const CreateTaskRunnerArgs&) {
-  return std::unique_ptr<base::TaskRunner>(
-      new base::ThreadTaskRunner(base::ThreadTaskRunner::CreateAndStart()));
+  return std::unique_ptr<base::TaskRunner>(new TaskRunnerInstance());
 }
 
 std::string PlatformPosix::GetCurrentProcessName() {
@@ -82,13 +93,38 @@
   std::string cmdline;
   base::ReadFile("/proc/self/cmdline", &cmdline);
   return cmdline.substr(0, cmdline.find('\0'));
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#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
@@ -98,4 +134,3 @@
 }
 
 }  // namespace perfetto
-#endif  // OS_LINUX || OS_ANDROID || OS_APPLE
diff --git a/src/tracing/test/BUILD.gn b/src/tracing/test/BUILD.gn
index fc63b18..dd500be 100644
--- a/src/tracing/test/BUILD.gn
+++ b/src/tracing/test/BUILD.gn
@@ -18,18 +18,13 @@
 
 perfetto_unittest_source_set("test_support") {
   testonly = true
-  public_deps = [
-    "../../../include/perfetto/test:test_support",
-    "../core:test_support",
-  ]
+  public_deps = [ "../core:test_support" ]
   deps = [
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
     "../../../protos/perfetto/trace:cpp",
-    "../../../protos/perfetto/trace:lite",
     "../../../protos/perfetto/trace:zero",
     "../../../protos/perfetto/trace/ftrace:cpp",
-    "../../../protos/perfetto/trace/track_event:lite",
     "../../base",
     "../../base:test_support",
     "../core",
@@ -43,12 +38,11 @@
     "fake_packet.h",
     "test_shared_memory.cc",
     "test_shared_memory.h",
-    "traced_value_test_support.cc",
   ]
 
   # These tests rely on test_task_runner.h which
-  # has no implementation for Windows or NaCL.
-  if (!is_win && !is_nacl) {
+  # has no Windows implementation.
+  if (!is_win) {
     sources += [
       "fake_producer_endpoint.h",
       "mock_consumer.cc",
@@ -74,21 +68,6 @@
       "../ipc/service",
     ]
     sources = [ "tracing_integration_test.cc" ]
-
-    # TODO(primiano): remove the build_with_chromium conditional once the root
-    # //BUILD.gn:libperfetto (in chromium) stops adding tracing:platform_fake.
-    # The problem is the following: in chrome builds we end up with duplicate
-    # symbol definitions in the test because both platorm (impl and fake) are
-    # present: impl added here and fake coming from chromium's base (full path:
-    # perfetto_unittests -> //(chromium)base:test_support -> //(chromium)base
-    # -> libperfetto -> platform_fake.
-    if (!build_with_chromium) {
-      deps += [
-        "..:client_api_without_backends",
-        "..:platform_impl",
-      ]
-      sources += [ "platform_unittest.cc" ]
-    }
   }
 }
 
@@ -98,7 +77,7 @@
     deps = [
       ":api_test_support",
       "../:client_api",
-      "../:platform_impl",
+      "../:platform_posix",
       "../../../:libperfetto_client_experimental",
       "../../../gn:default_deps",
       "../../../gn:gtest_and_gmock",
@@ -108,8 +87,6 @@
       "../../../protos/perfetto/config/track_event:cpp",
       "../../../protos/perfetto/trace:cpp",
       "../../../protos/perfetto/trace:zero",
-      "../../../protos/perfetto/trace/gpu:cpp",
-      "../../../protos/perfetto/trace/gpu:zero",
       "../../../protos/perfetto/trace/interned_data:cpp",
       "../../../protos/perfetto/trace/interned_data:zero",
       "../../../protos/perfetto/trace/profiling:cpp",
@@ -124,25 +101,18 @@
       "tracing_module_categories.h",
     ]
   }
+}
 
-  # 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 = [
-      "../../..:libperfetto_client_experimental",
-      "../../../gn:default_deps",
-      "../../base",
-      "../../tracing:client_api_without_backends",
-    ]
-
-    # The system tracing backend requires IPC support.
-    if (enable_perfetto_ipc) {
-      deps += [ "../../../test:test_helper" ]
-    }
-    sources = [
-      "api_test_support.cc",
-      "api_test_support.h",
-    ]
-  }
+# 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/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 061e2fe..375e999 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -21,7 +21,6 @@
 #include <functional>
 #include <list>
 #include <mutex>
-#include <regex>
 #include <thread>
 #include <vector>
 
@@ -31,10 +30,6 @@
 #include "perfetto/tracing.h"
 #include "test/gtest_and_gmock.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>  // For CreateFile().
-#endif
-
 // Deliberately not pulling any non-public perfetto header to spot accidental
 // header public -> non-public dependency while building this file.
 
@@ -51,28 +46,19 @@
 // yyy.gen.h includes are for the test readback path (the code in the test that
 // checks that the results are valid).
 #include "protos/perfetto/common/builtin_clock.pbzero.h"
-#include "protos/perfetto/common/interceptor_descriptor.gen.h"
-#include "protos/perfetto/common/trace_stats.gen.h"
-#include "protos/perfetto/common/tracing_service_state.gen.h"
 #include "protos/perfetto/common/track_event_descriptor.gen.h"
-#include "protos/perfetto/config/interceptor_config.gen.h"
 #include "protos/perfetto/config/track_event/track_event_config.gen.h"
 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h"
-#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.gen.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_common.gen.h"
 #include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/test_extensions.pbzero.h"
 #include "protos/perfetto/trace/trace.gen.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 #include "protos/perfetto/trace/track_event/log_message.gen.h"
@@ -99,7 +85,6 @@
     perfetto::Category("bar"),
     perfetto::Category("cat").SetTags("slow"),
     perfetto::Category("cat.verbose").SetTags("debug"),
-    perfetto::Category("cat-with-dashes"),
     perfetto::Category::Group("foo,bar"),
     perfetto::Category::Group("baz,bar,quux"),
     perfetto::Category::Group("red,green,blue,foo"),
@@ -112,8 +97,9 @@
                                   const char* /* function_name */,
                                   uint32_t /* line_number */>;
 
+namespace std {
 template <>
-struct std::hash<SourceLocation> {
+struct hash<SourceLocation> {
   size_t operator()(const SourceLocation& value) const {
     auto hasher = hash<size_t>();
     return hasher(reinterpret_cast<size_t>(get<0>(value))) ^
@@ -121,12 +107,14 @@
            hasher(get<2>(value));
   }
 };
+}  // namespace std
 
 // Represents an opaque (from Perfetto's point of view) thread identifier (e.g.,
 // base::PlatformThreadId in Chromium).
 struct MyThreadId {
-  explicit MyThreadId(int tid_) : tid(tid_) {}
+  MyThreadId(int pid_, int tid_) : pid(pid_), tid(tid_) {}
 
+  const int pid = 0;
   const int tid = 0;
 };
 
@@ -142,28 +130,36 @@
 namespace legacy {
 
 template <>
-ThreadTrack ConvertThreadId(const MyThreadId& thread) {
-  return perfetto::ThreadTrack::ForThread(
-      static_cast<base::PlatformThreadId>(thread.tid));
+bool ConvertThreadId(const MyThreadId& thread,
+                     uint64_t* track_uuid_out,
+                     int32_t* pid_override_out,
+                     int32_t* tid_override_out) {
+  if (!thread.pid && !thread.tid)
+    return false;
+  if (!thread.pid) {
+    // Thread in current process.
+    *track_uuid_out = perfetto::ThreadTrack::ForThread(
+                          static_cast<base::PlatformThreadId>(thread.tid))
+                          .uuid;
+  } else {
+    // Thread in another process.
+    *pid_override_out = thread.pid;
+    *tid_override_out = thread.tid;
+  }
+  return true;
+}
+
+template <>
+uint64_t ConvertTimestampToTraceTimeNs(const MyTimestamp& timestamp) {
+  return timestamp.ts;
 }
 
 }  // namespace legacy
-
-template <>
-struct TraceTimestampTraits<MyTimestamp> {
-  static TraceTimestamp ConvertTimestampToTraceTimeNs(
-      const MyTimestamp& timestamp) {
-    return {TrackEvent::GetTraceClockId(), timestamp.ts};
-  }
-};
-
 }  // namespace perfetto
 
 namespace {
 
-using perfetto::TracingInitArgs;
 using ::testing::_;
-using ::testing::ContainerEq;
 using ::testing::ElementsAre;
 using ::testing::HasSubstr;
 using ::testing::Invoke;
@@ -176,9 +172,13 @@
 // ------------------------------
 // Declarations of helper classes
 // ------------------------------
+static constexpr auto kWaitEventTimeout = std::chrono::seconds(5);
 
-class WaitableTestEvent {
- public:
+struct WaitableTestEvent {
+  std::mutex mutex_;
+  std::condition_variable cv_;
+  bool notified_ = false;
+
   bool notified() {
     std::unique_lock<std::mutex> lock(mutex_);
     return notified_;
@@ -186,25 +186,17 @@
 
   void Wait() {
     std::unique_lock<std::mutex> lock(mutex_);
-    // TSAN gets confused by wait_for, which we would use here in a perfect
-    // world.
-    cv_.wait(lock, [this] { return notified_; });
+    if (!cv_.wait_for(lock, kWaitEventTimeout, [this] { return notified_; })) {
+      fprintf(stderr, "Timed out while waiting for event\n");
+      abort();
+    }
   }
 
   void Notify() {
-    {
-      std::lock_guard<std::mutex> lock(mutex_);
-      notified_ = true;
-    }
-    // Do not notify while holding the lock, because then we wake up the other
-    // end, only for it to fail to acquire the lock.
+    std::unique_lock<std::mutex> lock(mutex_);
+    notified_ = true;
     cv_.notify_one();
   }
-
- private:
-  std::mutex mutex_;
-  std::condition_variable cv_;
-  bool notified_ = false;
 };
 
 class MockDataSource;
@@ -232,11 +224,8 @@
   TestDataSourceHandle* handle_ = nullptr;
 };
 
-constexpr int kTestDataSourceArg = 123;
-
 class MockDataSource2 : public perfetto::DataSource<MockDataSource2> {
  public:
-  MockDataSource2(int arg) { EXPECT_EQ(arg, kTestDataSourceArg); }
   void OnSetup(const SetupArgs&) override {}
   void OnStart(const StartArgs&) override {}
   void OnStop(const StopArgs&) override {}
@@ -265,19 +254,12 @@
   }
 
   std::unique_ptr<perfetto::TraceWriterBase> CreateTraceWriter(
-      perfetto::internal::DataSourceStaticState*,
-      uint32_t,
       perfetto::internal::DataSourceState*,
       perfetto::BufferExhaustedPolicy) override {
     return nullptr;
   }
 
   void DestroyStoppedTraceWritersForCurrentThread() override {}
-  void RegisterInterceptor(
-      const perfetto::InterceptorDescriptor&,
-      InterceptorFactory,
-      perfetto::InterceptorBase::TLSFactory,
-      perfetto::InterceptorBase::TracePacketCallback) override {}
 
   std::vector<DataSource> data_sources;
 
@@ -291,7 +273,6 @@
   ~TestIncrementalState() { destroyed = true; }
 
   int count = 100;
-  bool flag = false;
   static bool constructed;
   static bool destroyed;
 };
@@ -331,70 +312,24 @@
   }
 };
 
-class TestTracingPolicy : public perfetto::TracingPolicy {
- public:
-  void ShouldAllowConsumerSession(
-      const ShouldAllowConsumerSessionArgs& args) override {
-    EXPECT_NE(args.backend_type, perfetto::BackendType::kUnspecifiedBackend);
-    args.result_callback(should_allow_consumer_connection);
-  }
-
-  bool should_allow_consumer_connection = true;
-};
-
-TestTracingPolicy* g_test_tracing_policy = new TestTracingPolicy();  // Leaked.
-
 // -------------------------
 // Declaration of test class
 // -------------------------
-class PerfettoApiTest : public ::testing::TestWithParam<perfetto::BackendType> {
+class PerfettoApiTest : public ::testing::Test {
  public:
   static PerfettoApiTest* instance;
 
   void SetUp() override {
     instance = this;
-    g_test_tracing_policy->should_allow_consumer_connection = true;
 
-    // Start a fresh system service for this test, tearing down any previous
-    // service that was running.
-    uint32_t supported_backends =
-        perfetto::kInProcessBackend | perfetto::kSystemBackend;
-    if (!perfetto::test::StartSystemService())
-      supported_backends &= ~perfetto::kSystemBackend;
-
-    // If the system backend wasn't supported, skip all system backend tests.
-    auto backend = GetParam();
-    if (!(supported_backends & backend))
-      GTEST_SKIP();
-
-    static bool was_initialized;
-    if (!was_initialized) {
-      EXPECT_FALSE(perfetto::Tracing::IsInitialized());
-      was_initialized = true;
-    } else {
-      EXPECT_TRUE(perfetto::Tracing::IsInitialized());
-    }
-
-    // Since the client API can only be initialized once per process, initialize
-    // both the in-process and system backends for every test here. The actual
-    // service to be used is chosen by the test parameter.
-    TracingInitArgs args;
-    args.backends = supported_backends;
-    args.tracing_policy = g_test_tracing_policy;
+    perfetto::TracingInitArgs args;
+    args.backends = perfetto::kInProcessBackend;
     perfetto::Tracing::Initialize(args);
     RegisterDataSource<MockDataSource>("my_data_source");
     perfetto::TrackEvent::Register();
 
     // Make sure our data source always has a valid handle.
     data_sources_["my_data_source"];
-
-    // If this wasn't the first test to run in this process, any producers
-    // connected to the old system service will have been disconnected by the
-    // service restarting above. Wait for all producers to connect again before
-    // proceeding with the test.
-    perfetto::test::SyncProducers();
-
-    perfetto::test::DisableReconnectLimit();
   }
 
   void TearDown() override { instance = nullptr; }
@@ -411,15 +346,10 @@
 
   TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
                                      int fd = -1) {
-    return NewTrace(cfg, /*backend_type=*/GetParam(), fd);
-  }
-
-  TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
-                                     perfetto::BackendType backend_type,
-                                     int fd = -1) {
     sessions_.emplace_back();
     TestTracingSessionHandle* handle = &sessions_.back();
-    handle->session = perfetto::Tracing::NewTrace(backend_type);
+    handle->session =
+        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend);
     handle->session->SetOnStopCallback([handle] { handle->on_stop.Notify(); });
     handle->session->Setup(cfg, fd);
     return handle;
@@ -506,7 +436,6 @@
     std::map<uint64_t, std::string> categories;
     std::map<uint64_t, std::string> event_names;
     std::map<uint64_t, std::string> debug_annotation_names;
-    std::set<uint64_t> seen_tracks;
     perfetto::protos::gen::Trace parsed_trace;
     EXPECT_TRUE(
         parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
@@ -520,14 +449,6 @@
         categories.clear();
         event_names.clear();
         debug_annotation_names.clear();
-        seen_tracks.clear();
-      }
-
-      if (packet.has_track_descriptor()) {
-        // Make sure we haven't seen any events on this track before the
-        // descriptor was written.
-        EXPECT_EQ(seen_tracks.find(packet.track_descriptor().uuid()),
-                  seen_tracks.end());
       }
 
       if (!packet.has_track_event())
@@ -559,14 +480,6 @@
       }
       const auto& track_event = packet.track_event();
       std::string slice;
-
-      if (track_event.has_track_uuid()) {
-        seen_tracks.insert(track_event.track_uuid());
-        std::stringstream track;
-        track << "[track=" << track_event.track_uuid() << "]";
-        slice += track.str();
-      }
-
       switch (track_event.type()) {
         case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
           slice += "B";
@@ -663,19 +576,6 @@
     return slices;
   }
 
-  uint32_t GetMainThreadPacketSequenceId(
-      const perfetto::protos::gen::Trace& trace) {
-    for (const auto& packet : trace.packet()) {
-      if (packet.has_track_descriptor() &&
-          packet.track_descriptor().thread().tid() ==
-              static_cast<int32_t>(perfetto::base::GetThreadId())) {
-        return packet.trusted_packet_sequence_id();
-      }
-    }
-    ADD_FAILURE() << "Main thread not found";
-    return 0;
-  }
-
   std::map<std::string, TestDataSourceHandle> data_sources_;
   std::list<TestTracingSessionHandle> sessions_;  // Needs stable pointers.
 };
@@ -717,20 +617,7 @@
 // Test fixtures
 // -------------
 
-TEST_P(PerfettoApiTest, StartAndStopWithoutDataSources) {
-  // Create a new trace session without any data sources configured.
-  perfetto::TraceConfig cfg;
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* tracing_session = NewTrace(cfg);
-  // This should not timeout.
-  tracing_session->get()->StartBlocking();
-  tracing_session->get()->StopBlocking();
-}
-
-// Disabled by default because it leaks tracing sessions into subsequent tests,
-// which can result in the per-uid tracing session limit (5) to be hit in later
-// tests.
-TEST_P(PerfettoApiTest, DISABLED_TrackEventStartStopAndDestroy) {
+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).
@@ -745,14 +632,15 @@
   // 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(/*BackendType=*/GetParam()));
+    sessions.push_back(
+        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend));
     sessions[i]->Setup(cfg);
     sessions[i]->Start();
     sessions[i]->Stop();
   }
 }
 
-TEST_P(PerfettoApiTest, TrackEventStartStopAndStopBlocking) {
+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
@@ -767,7 +655,8 @@
   // 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(/*BackendType=*/GetParam()));
+    sessions.push_back(
+        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend));
     sessions[i]->Setup(cfg);
     sessions[i]->Start();
     sessions[i]->Stop();
@@ -777,59 +666,6 @@
   }
 }
 
-TEST_P(PerfettoApiTest, ChangeTraceConfiguration) {
-  // Setup the trace config.
-  perfetto::TraceConfig trace_config;
-  trace_config.set_duration_ms(2000);
-  trace_config.add_buffers()->set_size_kb(1024);
-  auto* data_source = trace_config.add_data_sources();
-
-  // Configure track events with category "foo".
-  auto* ds_cfg = data_source->mutable_config();
-  ds_cfg->set_name("track_event");
-  perfetto::protos::gen::TrackEventConfig te_cfg;
-  te_cfg.add_disabled_categories("*");
-  te_cfg.add_enabled_categories("foo");
-  ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
-
-  // Initially, exclude all producers (the client library's producer is named
-  // after current process's name, which will not match
-  // "all_producers_excluded").
-  data_source->add_producer_name_filter("all_producers_excluded");
-
-  auto* tracing_session = NewTrace(trace_config);
-
-  tracing_session->get()->StartBlocking();
-
-  // Emit a first trace event, this one should be filtered out due
-  // to the mismatching producer name filter.
-  TRACE_EVENT_BEGIN("foo", "EventFilteredOut");
-  TRACE_EVENT_END("foo");
-
-  // Remove the producer name filter by changing configs.
-  data_source->clear_producer_name_filter();
-  tracing_session->get()->ChangeTraceConfig(trace_config);
-
-  // We don't have a blocking version of ChangeTraceConfig, because there is
-  // currently no response to it from producers or the service. Instead, we sync
-  // the consumer and producer IPC streams for this test, to ensure that the
-  // producer_name_filter change has propagated.
-  tracing_session->get()->GetTraceStatsBlocking();  // sync consumer stream.
-  perfetto::test::SyncProducers();                  // sync producer stream.
-
-  // Emit a second trace event, this one should be included because
-  // the producer name filter was cleared.
-  TRACE_EVENT_BEGIN("foo", "EventIncluded");
-  TRACE_EVENT_END("foo");
-  tracing_session->get()->StopBlocking();
-
-  // Verify that only the second event is in the trace data.
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-  EXPECT_THAT(trace, Not(HasSubstr("EventFilteredOut")));
-  EXPECT_THAT(trace, HasSubstr("EventIncluded"));
-}
-
 // This is a build-only regression test that checks you can have a track event
 // inside a template.
 template <typename T>
@@ -837,15 +673,7 @@
   TRACE_EVENT_BEGIN("cat", "Name");
 }
 
-// This is a build-only regression test that checks you can specify the tracing
-// category as a template argument.
-constexpr const char kTestCategory[] = "foo";
-template <const char* category>
-void TestCategoryAsTemplateParameter() {
-  TRACE_EVENT_BEGIN(category, "Name");
-}
-
-TEST_P(PerfettoApiTest, TrackEvent) {
+TEST_F(PerfettoApiTest, TrackEvent) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"test"});
   tracing_session->get()->StartBlocking();
@@ -866,7 +694,7 @@
   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
   auto now = perfetto::TrackEvent::GetTraceTimeNs();
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   auto clock_id = perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
 #else
@@ -928,7 +756,7 @@
 
     EXPECT_GT(packet.timestamp(), 0u);
     EXPECT_LE(packet.timestamp(), now);
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
     EXPECT_FALSE(packet.has_timestamp_clock_id());
 #else
@@ -958,12 +786,11 @@
   EXPECT_TRUE(begin_found);
   EXPECT_TRUE(end_found);
 
-  // Dummy instantiation of test templates.
+  // Dummy instantiation of test template.
   TestTrackEventInsideTemplate(true);
-  TestCategoryAsTemplateParameter<kTestCategory>();
 }
 
-TEST_P(PerfettoApiTest, TrackEventCategories) {
+TEST_F(PerfettoApiTest, TrackEventCategories) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"bar"});
   tracing_session->get()->StartBlocking();
@@ -982,45 +809,7 @@
   EXPECT_THAT(trace, Not(HasSubstr("NotEnabled")));
 }
 
-TEST_P(PerfettoApiTest, ClearIncrementalState) {
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("incr_data_source");
-  TestIncrementalDataSource::Register(dsd);
-  perfetto::test::SyncProducers();
-
-  // Setup the trace config with an incremental state clearing period.
-  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");
-  auto* is_cfg = cfg.mutable_incremental_state_config();
-  is_cfg->set_clear_period_ms(10);
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Observe at least 5 incremental state resets.
-  constexpr size_t kMaxLoops = 100;
-  size_t loops = 0;
-  size_t times_cleared = 0;
-  while (times_cleared < 5) {
-    ASSERT_LT(loops++, kMaxLoops);
-    TestIncrementalDataSource::Trace(
-        [&](TestIncrementalDataSource::TraceContext ctx) {
-          auto* incr_state = ctx.GetIncrementalState();
-          if (!incr_state->flag) {
-            incr_state->flag = true;
-            times_cleared++;
-          }
-        });
-    std::this_thread::sleep_for(std::chrono::milliseconds(10));
-  }
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, TrackEventRegistrationWithModule) {
+TEST_F(PerfettoApiTest, TrackEventRegistrationWithModule) {
   MockTracingMuxer muxer;
 
   // Each track event namespace registers its own data source.
@@ -1038,7 +827,7 @@
             muxer.data_sources[1].static_state);
 }
 
-TEST_P(PerfettoApiTest, TrackEventDescriptor) {
+TEST_F(PerfettoApiTest, TrackEventDescriptor) {
   MockTracingMuxer muxer;
 
   perfetto::TrackEvent::Register();
@@ -1051,7 +840,7 @@
 
   // Check that the advertised categories match PERFETTO_DEFINE_CATEGORIES (see
   // above).
-  EXPECT_EQ(7, desc.available_categories_size());
+  EXPECT_EQ(6, desc.available_categories_size());
   EXPECT_EQ("test", desc.available_categories()[0].name());
   EXPECT_EQ("This is a test category",
             desc.available_categories()[0].description());
@@ -1062,12 +851,11 @@
   EXPECT_EQ("slow", desc.available_categories()[3].tags()[0]);
   EXPECT_EQ("cat.verbose", desc.available_categories()[4].name());
   EXPECT_EQ("debug", desc.available_categories()[4].tags()[0]);
-  EXPECT_EQ("cat-with-dashes", desc.available_categories()[5].name());
-  EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[6].name());
-  EXPECT_EQ("slow", desc.available_categories()[6].tags()[0]);
+  EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[5].name());
+  EXPECT_EQ("slow", desc.available_categories()[5].tags()[0]);
 }
 
-TEST_P(PerfettoApiTest, TrackEventSharedIncrementalState) {
+TEST_F(PerfettoApiTest, TrackEventSharedIncrementalState) {
   tracing_module::InitializeCategories();
 
   // Setup the trace config.
@@ -1094,7 +882,7 @@
   tracing_session->get()->StopBlocking();
 }
 
-TEST_P(PerfettoApiTest, TrackEventCategoriesWithModule) {
+TEST_F(PerfettoApiTest, TrackEventCategoriesWithModule) {
   // Check that categories defined in two different category registries are
   // enabled and disabled correctly.
   tracing_module::InitializeCategories();
@@ -1141,7 +929,7 @@
   }
 }
 
-TEST_P(PerfettoApiTest, TrackEventDynamicCategories) {
+TEST_F(PerfettoApiTest, TrackEventDynamicCategories) {
   // Setup the trace config.
   perfetto::TraceConfig cfg;
   cfg.set_duration_ms(500);
@@ -1205,7 +993,7 @@
   EXPECT_THAT(trace, HasSubstr("EventInSecondStaticallyNamedDynamicCategory"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventConcurrentSessions) {
+TEST_F(PerfettoApiTest, TrackEventConcurrentSessions) {
   // Check that categories that are enabled and disabled in two parallel tracing
   // sessions don't interfere.
 
@@ -1254,7 +1042,7 @@
   EXPECT_THAT(trace2, Not(HasSubstr("Session2_Third")));
 }
 
-TEST_P(PerfettoApiTest, TrackEventProcessAndThreadDescriptors) {
+TEST_F(PerfettoApiTest, TrackEventProcessAndThreadDescriptors) {
   // Thread and process descriptors can be set before tracing is enabled.
   perfetto::TrackEvent::SetProcessDescriptor(
       [](perfetto::protos::pbzero::TrackDescriptor* desc) {
@@ -1313,10 +1101,10 @@
 
   std::vector<perfetto::protos::gen::TrackDescriptor> descs;
   std::vector<perfetto::protos::gen::TrackDescriptor> thread_descs;
-  uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
+  constexpr uint32_t kMainThreadSequence = 2;
   for (const auto& packet : trace.packet()) {
     if (packet.has_track_descriptor()) {
-      if (packet.trusted_packet_sequence_id() == main_thread_sequence) {
+      if (packet.trusted_packet_sequence_id() == kMainThreadSequence) {
         descs.push_back(packet.track_descriptor());
       } else {
         thread_descs.push_back(packet.track_descriptor());
@@ -1353,7 +1141,7 @@
   EXPECT_NE(0, thread_descs[1].thread().tid());
 }
 
-TEST_P(PerfettoApiTest, CustomTrackDescriptor) {
+TEST_F(PerfettoApiTest, CustomTrackDescriptor) {
   // Setup the trace config.
   perfetto::TraceConfig cfg;
   cfg.set_duration_ms(500);
@@ -1368,8 +1156,6 @@
   auto track = perfetto::ProcessTrack::Current();
   auto desc = track.Serialize();
   desc.mutable_process()->set_process_name("testing.exe");
-  desc.mutable_thread()->set_tid(
-      static_cast<int32_t>(perfetto::base::GetThreadId()));
   desc.mutable_chrome_process()->set_process_priority(123);
   perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
   perfetto::TrackEvent::Flush();
@@ -1380,10 +1166,10 @@
   perfetto::protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
-  uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
+  constexpr uint32_t kMainThreadSequence = 2;
   bool found_desc = false;
   for (const auto& packet : trace.packet()) {
-    if (packet.trusted_packet_sequence_id() != main_thread_sequence)
+    if (packet.trusted_packet_sequence_id() != kMainThreadSequence)
       continue;
     if (packet.has_track_descriptor()) {
       auto td = packet.track_descriptor();
@@ -1398,7 +1184,7 @@
   EXPECT_TRUE(found_desc);
 }
 
-TEST_P(PerfettoApiTest, TrackEventCustomTrack) {
+TEST_F(PerfettoApiTest, TrackEventCustomTrack) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"bar"});
   tracing_session->get()->StartBlocking();
@@ -1440,7 +1226,7 @@
 
   // Check that the track uuids match on the begin and end events.
   const auto track = perfetto::Track(async_id);
-  uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
+  constexpr uint32_t kMainThreadSequence = 2;
   int event_count = 0;
   bool found_descriptor = false;
   for (const auto& packet : trace.packet()) {
@@ -1460,10 +1246,10 @@
     auto track_event = packet.track_event();
     if (track_event.type() ==
         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
-      EXPECT_EQ(main_thread_sequence, packet.trusted_packet_sequence_id());
+      EXPECT_EQ(kMainThreadSequence, packet.trusted_packet_sequence_id());
       EXPECT_EQ(track.uuid, track_event.track_uuid());
     } else {
-      EXPECT_NE(main_thread_sequence, packet.trusted_packet_sequence_id());
+      EXPECT_NE(kMainThreadSequence, packet.trusted_packet_sequence_id());
       EXPECT_EQ(track.uuid, track_event.track_uuid());
     }
     event_count++;
@@ -1473,109 +1259,7 @@
   perfetto::TrackEvent::EraseTrackDescriptor(track);
 }
 
-TEST_P(PerfettoApiTest, LegacyEventWithThreadOverride) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"cat"});
-  tracing_session->get()->StartBlocking();
-
-  TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("cat", "Name", 1,
-                                               MyThreadId(456), MyTimestamp{0});
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  perfetto::protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-
-  // Check that we wrote a track descriptor for the custom thread track, and
-  // that the event was associated with that track.
-  const auto track = perfetto::ThreadTrack::ForThread(456);
-  bool found_descriptor = false;
-  bool found_event = false;
-  for (const auto& packet : trace.packet()) {
-    if (packet.has_track_descriptor() &&
-        packet.track_descriptor().has_thread()) {
-      auto td = packet.track_descriptor().thread();
-      if (td.tid() == 456) {
-        EXPECT_EQ(track.uuid, packet.track_descriptor().uuid());
-        found_descriptor = true;
-      }
-    }
-
-    if (!packet.has_track_event())
-      continue;
-    auto track_event = packet.track_event();
-    if (track_event.legacy_event().phase() == TRACE_EVENT_PHASE_ASYNC_BEGIN) {
-      EXPECT_EQ(track.uuid, track_event.track_uuid());
-      found_event = true;
-    }
-  }
-  EXPECT_TRUE(found_descriptor);
-  EXPECT_TRUE(found_event);
-  perfetto::TrackEvent::EraseTrackDescriptor(track);
-}
-
-TEST_P(PerfettoApiTest, LegacyEventWithProcessOverride) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"cat"});
-  tracing_session->get()->StartBlocking();
-
-  // Note: there's no direct entrypoint for adding trace events for another
-  // process, so we're using the internal support macro here.
-  INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(
-      TRACE_EVENT_PHASE_INSTANT, "cat", "Name", 0, MyThreadId{789},
-      MyTimestamp{0}, TRACE_EVENT_FLAG_HAS_PROCESS_ID);
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  perfetto::protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-
-  // Check that the event has a pid_override matching MyThread above.
-  bool found_event = false;
-  for (const auto& packet : trace.packet()) {
-    if (!packet.has_track_event())
-      continue;
-    auto track_event = packet.track_event();
-    if (track_event.type() == perfetto::protos::gen::TrackEvent::TYPE_INSTANT) {
-      EXPECT_EQ(789, track_event.legacy_event().pid_override());
-      EXPECT_EQ(-1, track_event.legacy_event().tid_override());
-      found_event = true;
-    }
-  }
-  EXPECT_TRUE(found_event);
-}
-
-TEST_P(PerfettoApiTest, TrackDescriptorWrittenBeforeEvent) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"bar"});
-  tracing_session->get()->StartBlocking();
-
-  // Emit an event on a custom track.
-  TRACE_EVENT_INSTANT("bar", "Event", perfetto::Track(8086));
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  perfetto::protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-
-  // Check that the descriptor was written before the event.
-  std::set<uint64_t> seen_descriptors;
-  for (const auto& packet : trace.packet()) {
-    if (packet.has_track_descriptor())
-      seen_descriptors.insert(packet.track_descriptor().uuid());
-
-    if (!packet.has_track_event())
-      continue;
-    auto track_event = packet.track_event();
-    EXPECT_TRUE(seen_descriptors.find(track_event.track_uuid()) !=
-                seen_descriptors.end());
-  }
-}
-
-TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestamp) {
+TEST_F(PerfettoApiTest, TrackEventCustomTrackAndTimestamp) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"bar"});
   tracing_session->get()->StartBlocking();
@@ -1585,7 +1269,7 @@
 
   auto empty_lambda = [](perfetto::EventContext) {};
   constexpr uint64_t kBeginEventTime = 10;
-  const MyTimestamp kEndEventTime{15};
+  constexpr uint64_t kEndEventTime = 15;
   TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime, empty_lambda);
   TRACE_EVENT_END("bar", track, kEndEventTime, empty_lambda);
 
@@ -1610,7 +1294,7 @@
         EXPECT_EQ(packet.timestamp(), kBeginEventTime);
         break;
       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
-        EXPECT_EQ(packet.timestamp(), kEndEventTime.ts);
+        EXPECT_EQ(packet.timestamp(), kEndEventTime);
         break;
       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
         EXPECT_EQ(packet.timestamp(), kInstantEventTime);
@@ -1624,7 +1308,7 @@
   perfetto::TrackEvent::EraseTrackDescriptor(track);
 }
 
-TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestampNoLambda) {
+TEST_F(PerfettoApiTest, TrackEventCustomTrackAndTimestampNoLambda) {
   auto* tracing_session = NewTraceWithCategories({"bar"});
   tracing_session->get()->StartBlocking();
 
@@ -1664,7 +1348,7 @@
   EXPECT_EQ(event_count, 2);
 }
 
-TEST_P(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
+TEST_F(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"bar"});
   tracing_session->get()->StartBlocking();
@@ -1698,12 +1382,12 @@
   EXPECT_TRUE(found_descriptor);
 }
 
-TEST_P(PerfettoApiTest, TrackEventTypedArgs) {
+TEST_F(PerfettoApiTest, TrackEventTypedArgs) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
 
-  auto random_value = rand();
+  auto random_value = random();
   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
                     [random_value](perfetto::EventContext ctx) {
                       auto* log = ctx.event()->set_log_message();
@@ -1745,84 +1429,6 @@
   EXPECT_TRUE(found_args);
 }
 
-TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_SimpleRepeated) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"foo"});
-  tracing_session->get()->StartBlocking();
-
-  std::vector<uint64_t> flow_ids{1, 2, 3};
-  TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
-                    perfetto::protos::pbzero::TrackEvent::kFlowIds, flow_ids);
-  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::gen::Trace parsed_trace;
-  ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), 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::gen::TrackEvent::TYPE_SLICE_BEGIN) {
-      continue;
-    }
-
-    EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(1, 2, 3));
-    found_args = true;
-  }
-  EXPECT_TRUE(found_args);
-}
-
-TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_NestedSingle) {
-  struct LogMessage {
-    void WriteIntoTrace(
-        perfetto::TracedProto<perfetto::protos::pbzero::LogMessage> context)
-        const {
-      context->set_source_location_iid(1);
-      context->set_body_iid(2);
-    }
-  };
-
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"foo"});
-  tracing_session->get()->StartBlocking();
-
-  TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
-                    perfetto::protos::pbzero::TrackEvent::kLogMessage,
-                    LogMessage());
-  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::gen::Trace parsed_trace;
-  ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), 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::gen::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());
-    found_args = true;
-  }
-  EXPECT_TRUE(found_args);
-}
-
 struct InternedLogMessageBody
     : public perfetto::TrackEventInternedDataIndex<
           InternedLogMessageBody,
@@ -1842,7 +1448,7 @@
 
 int InternedLogMessageBody::commit_count = 0;
 
-TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterning) {
+TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterning) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
@@ -1909,7 +1515,7 @@
   }
 };
 
-TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByValue) {
+TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningByValue) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
@@ -1949,7 +1555,7 @@
   }
 };
 
-TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByHashing) {
+TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningByHashing) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
@@ -1996,7 +1602,7 @@
   }
 };
 
-TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningComplexValue) {
+TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningComplexValue) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
@@ -2024,7 +1630,7 @@
               ElementsAre("SomeFunction(file.cc:123): To be, or not to be"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventScoped) {
+TEST_F(PerfettoApiTest, TrackEventScoped) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"test"});
   tracing_session->get()->StartBlocking();
@@ -2056,105 +1662,7 @@
                   "E", "B:test.TestEvent", "B:test.AnotherEvent", "E", "E"));
 }
 
-// A class similar to what Protozero generates for extended message.
-class TestTrackEvent : public perfetto::protos::pbzero::TrackEvent {
- public:
-  static const int field_number = 9901;
-
-  void set_extension_value(int value) {
-    // 9900-10000 is the range of extension field numbers reserved for testing.
-    AppendTinyVarInt(field_number, value);
-  }
-};
-
-TEST_P(PerfettoApiTest, ExtensionClass) {
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  {
-    TRACE_EVENT("test", "TestEventWithExtensionArgs",
-                [&](perfetto::EventContext ctx) {
-                  ctx.event<perfetto::protos::pbzero::TestExtension>()
-                      ->add_int_extension_for_testing(42);
-                });
-  }
-
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  EXPECT_GE(raw_trace.size(), 0u);
-
-  bool found_extension = false;
-  perfetto::protos::pbzero::Trace_Decoder trace(
-      reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
-
-  for (auto it = trace.packet(); it; ++it) {
-    perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
-                                                         it->size());
-
-    if (!packet.has_track_event())
-      continue;
-
-    auto track_event = packet.track_event();
-    protozero::ProtoDecoder decoder(track_event.data, track_event.size);
-
-    for (protozero::Field f = decoder.ReadField(); f.valid();
-         f = decoder.ReadField()) {
-      if (f.id() == perfetto::protos::pbzero::TestExtension::
-                        FieldMetadata_IntExtensionForTesting::kFieldId) {
-        found_extension = true;
-      }
-    }
-  }
-
-  EXPECT_TRUE(found_extension);
-}
-
-TEST_P(PerfettoApiTest, InlineTypedExtensionField) {
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  {
-    TRACE_EVENT(
-        "test", "TestEventWithExtensionArgs",
-        perfetto::protos::pbzero::TestExtension::kIntExtensionForTesting,
-        std::vector<int>{42});
-  }
-
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  EXPECT_GE(raw_trace.size(), 0u);
-
-  bool found_extension = false;
-  perfetto::protos::pbzero::Trace_Decoder trace(
-      reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
-
-  for (auto it = trace.packet(); it; ++it) {
-    perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
-                                                         it->size());
-
-    if (!packet.has_track_event())
-      continue;
-
-    auto track_event = packet.track_event();
-    protozero::ProtoDecoder decoder(track_event.data, track_event.size);
-
-    for (protozero::Field f = decoder.ReadField(); f.valid();
-         f = decoder.ReadField()) {
-      if (f.id() == perfetto::protos::pbzero::TestExtension::
-                        FieldMetadata_IntExtensionForTesting::kFieldId) {
-        found_extension = true;
-      }
-    }
-  }
-
-  EXPECT_TRUE(found_extension);
-}
-
-TEST_P(PerfettoApiTest, TrackEventInstant) {
+TEST_F(PerfettoApiTest, TrackEventInstant) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"test"});
   tracing_session->get()->StartBlocking();
@@ -2168,48 +1676,13 @@
   EXPECT_THAT(slices, ElementsAre("I:test.TestEvent", "I:test.AnotherEvent"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventDefaultGlobalTrack) {
+TEST_F(PerfettoApiTest, TrackEventDebugAnnotations) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"test"});
   tracing_session->get()->StartBlocking();
 
-  TRACE_EVENT_INSTANT("test", "ThreadEvent");
-  TRACE_EVENT_INSTANT("test", "GlobalEvent", perfetto::Track::Global(0u));
-  perfetto::TrackEvent::Flush();
-
-  tracing_session->get()->StopBlocking();
-  auto slices = ReadSlicesFromTrace(tracing_session->get());
-  EXPECT_THAT(slices,
-              ElementsAre("I:test.ThreadEvent", "[track=0]I:test.GlobalEvent"));
-}
-
-TEST_P(PerfettoApiTest, TrackEventTrackFromPointer) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  perfetto::Track parent_track(1);
-  int* ptr = reinterpret_cast<int*>(2);
-  TRACE_EVENT_INSTANT("test", "Event",
-                      perfetto::Track::FromPointer(ptr, parent_track));
-  perfetto::TrackEvent::Flush();
-
-  perfetto::Track track(reinterpret_cast<uintptr_t>(ptr), parent_track);
-
-  tracing_session->get()->StopBlocking();
-  auto slices = ReadSlicesFromTrace(tracing_session->get());
-  EXPECT_THAT(slices, ElementsAre("[track=" + std::to_string(track.uuid) +
-                                  "]I:test.Event"));
-}
-
-TEST_P(PerfettoApiTest, TrackEventDebugAnnotations) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
-  enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
-  enum class MyClassEnum { VALUE };
+  enum MyEnum { ENUM_FOO, ENUM_BAR };
+  enum MySignedEnum { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
 
   TRACE_EVENT_BEGIN("test", "E", "bool_arg", false);
   TRACE_EVENT_BEGIN("test", "E", "int_arg", -123);
@@ -2219,16 +1692,11 @@
   TRACE_EVENT_BEGIN("test", "E", "str_arg", "hello", "str_arg2",
                     std::string("tracing"));
   TRACE_EVENT_BEGIN("test", "E", "ptr_arg",
-                    reinterpret_cast<void*>(static_cast<intptr_t>(0xbaadf00d)));
+                    reinterpret_cast<void*>(0xbaadf00d));
   TRACE_EVENT_BEGIN("test", "E", "size_t_arg", size_t{42});
   TRACE_EVENT_BEGIN("test", "E", "ptrdiff_t_arg", ptrdiff_t{-7});
   TRACE_EVENT_BEGIN("test", "E", "enum_arg", ENUM_BAR);
   TRACE_EVENT_BEGIN("test", "E", "signed_enum_arg", SIGNED_ENUM_FOO);
-  TRACE_EVENT_BEGIN("test", "E", "class_enum_arg", MyClassEnum::VALUE);
-  TRACE_EVENT_BEGIN("test", "E", "traced_value",
-                    [&](perfetto::TracedValue context) {
-                      std::move(context).WriteInt64(42);
-                    });
   perfetto::TrackEvent::Flush();
 
   tracing_session->get()->StopBlocking();
@@ -2242,11 +1710,10 @@
           "B:test.E(str_arg=(string)hello,str_arg2=(string)tracing)",
           "B:test.E(ptr_arg=(pointer)baadf00d)",
           "B:test.E(size_t_arg=(uint)42)", "B:test.E(ptrdiff_t_arg=(int)-7)",
-          "B:test.E(enum_arg=(uint)1)", "B:test.E(signed_enum_arg=(int)-1)",
-          "B:test.E(class_enum_arg=(int)0)", "B:test.E(traced_value=(int)42)"));
+          "B:test.E(enum_arg=(uint)1)", "B:test.E(signed_enum_arg=(int)-1)"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventCustomDebugAnnotations) {
+TEST_F(PerfettoApiTest, TrackEventCustomDebugAnnotations) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"test"});
   tracing_session->get()->StartBlocking();
@@ -2267,7 +1734,7 @@
           R"(B:test.E(normal_arg=(string)x,custom_arg=(json){"key": 123}))"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventCustomRawDebugAnnotations) {
+TEST_F(PerfettoApiTest, TrackEventCustomRawDebugAnnotations) {
   // Note: this class is also testing a non-moveable and non-copiable argument.
   class MyRawDebugAnnotation : public perfetto::DebugAnnotation {
    public:
@@ -2309,64 +1776,7 @@
                   "B:test.E(plain_arg=(int)42,raw_arg=(nested)nested_value)"));
 }
 
-TEST_P(PerfettoApiTest, ManyDebugAnnotations) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  TRACE_EVENT_BEGIN("test", "E", "arg1", 1, "arg2", 2, "arg3", 3);
-  perfetto::TrackEvent::Flush();
-
-  tracing_session->get()->StopBlocking();
-  auto slices = ReadSlicesFromTrace(tracing_session->get());
-  EXPECT_THAT(slices,
-              ElementsAre("B:test.E(arg1=(int)1,arg2=(int)2,arg3=(int)3)"));
-}
-
-TEST_P(PerfettoApiTest, DebugAnnotationAndLambda) {
-  // Create a new trace session.
-  auto* tracing_session = NewTraceWithCategories({"test"});
-  tracing_session->get()->StartBlocking();
-
-  enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
-  enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
-  enum class MyClassEnum { VALUE };
-
-  TRACE_EVENT_BEGIN(
-      "test", "E", "key", "value", [](perfetto::EventContext ctx) {
-        ctx.event()->set_log_message()->set_source_location_iid(42);
-      });
-  perfetto::TrackEvent::Flush();
-
-  tracing_session->get()->StopBlocking();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-
-  perfetto::protos::gen::Trace parsed_trace;
-  ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), 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::gen::TrackEvent::TYPE_SLICE_BEGIN)
-      continue;
-
-    EXPECT_TRUE(track_event.has_log_message());
-    const auto& log = track_event.log_message();
-    EXPECT_EQ(42u, log.source_location_iid());
-
-    const auto& dbg = track_event.debug_annotations()[0];
-    EXPECT_EQ("value", dbg.string_value());
-
-    found_args = true;
-  }
-  EXPECT_TRUE(found_args);
-}
-
-TEST_P(PerfettoApiTest, TrackEventComputedName) {
+TEST_F(PerfettoApiTest, TrackEventComputedName) {
   // Setup the trace config.
   perfetto::TraceConfig cfg;
   cfg.set_duration_ms(500);
@@ -2394,7 +1804,7 @@
                                   "B:test.Even", "B:test.Odd", "B:test.Even"));
 }
 
-TEST_P(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
+TEST_F(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});
   tracing_session->get()->StartBlocking();
@@ -2416,7 +1826,7 @@
   EXPECT_TRUE(called);
 }
 
-TEST_P(PerfettoApiTest, TrackEventConfig) {
+TEST_F(PerfettoApiTest, TrackEventConfig) {
   auto check_config = [&](perfetto::protos::gen::TrackEventConfig te_cfg) {
     perfetto::TraceConfig cfg;
     cfg.set_duration_ms(500);
@@ -2457,8 +1867,7 @@
         slices,
         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
-                    "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
-                    "B:$dynamic,$foo.DynamicGroupFooEvent",
+                    "B:test.TagEvent", "B:$dynamic,$foo.DynamicGroupFooEvent",
                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
   }
 
@@ -2473,16 +1882,6 @@
                                     "B:$dynamic,$foo.DynamicGroupFooEvent"));
   }
 
-  // Enable exactly one dynamic category.
-  {
-    perfetto::protos::gen::TrackEventConfig te_cfg;
-    te_cfg.add_disabled_categories("*");
-    te_cfg.add_enabled_categories("dynamic");
-    auto slices = check_config(te_cfg);
-    EXPECT_THAT(slices, ElementsAre("B:$dynamic,$foo.DynamicGroupFooEvent",
-                                    "B:$dynamic,$bar.DynamicGroupBarEvent"));
-  }
-
   // Enable two categories.
   {
     perfetto::protos::gen::TrackEventConfig te_cfg;
@@ -2508,8 +1907,7 @@
         slices,
         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
-                    "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
-                    "B:$dynamic,$foo.DynamicGroupFooEvent",
+                    "B:test.TagEvent", "B:$dynamic,$foo.DynamicGroupFooEvent",
                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
   }
 
@@ -2551,19 +1949,18 @@
     te_cfg.add_enabled_tags("slow");
     te_cfg.add_enabled_tags("debug");
     auto slices = check_config(te_cfg);
-    EXPECT_THAT(
-        slices,
-        ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
-                    "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
-                    "B:red,green,blue,yellow.MultiNone", "B:cat.SlowEvent",
-                    "B:cat.verbose.DebugEvent", "B:test.TagEvent",
-                    "B:disabled-by-default-cat.SlowDisabledEvent",
-                    "B:$dynamic,$foo.DynamicGroupFooEvent",
-                    "B:$dynamic,$bar.DynamicGroupBarEvent"));
+    EXPECT_THAT(slices,
+                ElementsAre("B:foo.FooEvent", "B:bar.BarEvent",
+                            "B:foo,bar.MultiFooBar", "B:baz,bar,quux.MultiBar",
+                            "B:red,green,blue,foo.MultiFoo", "B:cat.SlowEvent",
+                            "B:cat.verbose.DebugEvent", "B:test.TagEvent",
+                            "B:disabled-by-default-cat.SlowDisabledEvent",
+                            "B:$dynamic,$foo.DynamicGroupFooEvent",
+                            "B:$dynamic,$bar.DynamicGroupBarEvent"));
   }
 }
 
-TEST_P(PerfettoApiTest, OneDataSourceOneEvent) {
+TEST_F(PerfettoApiTest, OneDataSourceOneEvent) {
   auto* data_source = &data_sources_["my_data_source"];
 
   // Setup the trace config.
@@ -2639,176 +2036,13 @@
   EXPECT_TRUE(test_packet_found);
 }
 
-TEST_P(PerfettoApiTest, ReentrantTracing) {
-  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");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->Start();
-  data_source->on_start.Wait();
-
-  // Check that only one level of trace lambda calls is allowed.
-  std::atomic<int> trace_lambda_calls{0};
-  MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
-    trace_lambda_calls++;
-    MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
-      trace_lambda_calls++;
-    });
-  });
-
-  tracing_session->get()->StopBlocking();
-  EXPECT_EQ(trace_lambda_calls, 1);
-}
-
-TEST_P(PerfettoApiTest, ConsumerFlush) {
-  auto* data_source = &data_sources_["my_data_source"];
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  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);
-
-  tracing_session->get()->Start();
-  data_source->on_start.Wait();
-
-  MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
-    auto packet = ctx.NewTracePacket();
-    packet->set_timestamp(42);
-    packet->set_for_testing()->set_str("flushed event");
-    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();
-  });
-
-  EXPECT_TRUE(tracing_session->get()->FlushBlocking());
-
-  // Deliberately doing ReadTraceBlocking() before StopBlocking() to avoid
-  // hitting the auto scrape-on-stop behavior of the service.
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  tracing_session->get()->StopBlocking();
-
-  ASSERT_GE(raw_trace.size(), 0u);
-  perfetto::protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), 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(), "flushed event");
-    test_packet_found = true;
-  }
-  EXPECT_TRUE(test_packet_found);
-}
-
-TEST_P(PerfettoApiTest, WithBatching) {
-  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);
-
-  tracing_session->get()->Start();
-  data_source->on_setup.Wait();
-  data_source->on_start.Wait();
-
-  std::stringstream first_large_message;
-  for (size_t i = 0; i < 512; i++)
-    first_large_message << i << ". Something wicked this way comes. ";
-  auto first_large_message_str = first_large_message.str();
-
-  // Emit one trace event before we begin batching.
-  MockDataSource::Trace(
-      [&first_large_message_str](MockDataSource::TraceContext ctx) {
-        auto packet = ctx.NewTracePacket();
-        packet->set_timestamp(42);
-        packet->set_for_testing()->set_str(first_large_message_str);
-        packet->Finalize();
-      });
-
-  // Simulate the start of a batching cycle by first setting the batching period
-  // to a very large value and then force-flushing when we are done writing
-  // data.
-  ASSERT_TRUE(
-      perfetto::test::EnableDirectSMBPatching(/*BackendType=*/GetParam()));
-  perfetto::test::SetBatchCommitsDuration(UINT32_MAX,
-                                          /*BackendType=*/GetParam());
-
-  std::stringstream second_large_message;
-  for (size_t i = 0; i < 512; i++)
-    second_large_message << i << ". Something else wicked this way comes. ";
-  auto second_large_message_str = second_large_message.str();
-
-  // Emit another trace event.
-  MockDataSource::Trace(
-      [&second_large_message_str](MockDataSource::TraceContext ctx) {
-        auto packet = ctx.NewTracePacket();
-        packet->set_timestamp(43);
-        packet->set_for_testing()->set_str(second_large_message_str);
-        packet->Finalize();
-
-        // Simulate the end of the batching cycle.
-        ctx.Flush();
-      });
-
-  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::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-  bool test_packet_1_found = false;
-  bool test_packet_2_found = false;
-  for (const auto& packet : trace.packet()) {
-    if (!packet.has_for_testing())
-      continue;
-    EXPECT_TRUE(packet.timestamp() == 42U || packet.timestamp() == 43U);
-    if (packet.timestamp() == 42U) {
-      EXPECT_FALSE(test_packet_1_found);
-      EXPECT_EQ(packet.for_testing().str(), first_large_message_str);
-      test_packet_1_found = true;
-    } else {
-      EXPECT_FALSE(test_packet_2_found);
-      EXPECT_EQ(packet.for_testing().str(), second_large_message_str);
-      test_packet_2_found = true;
-    }
-  }
-  EXPECT_TRUE(test_packet_1_found && test_packet_2_found);
-}
-
-TEST_P(PerfettoApiTest, BlockingStartAndStop) {
+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, kTestDataSourceArg);
-  perfetto::test::SyncProducers();
+  MockDataSource2::Register(dsd);
 
   // Setup the trace config.
   perfetto::TraceConfig cfg;
@@ -2831,7 +2065,7 @@
   EXPECT_TRUE(tracing_session->on_stop.notified());
 }
 
-TEST_P(PerfettoApiTest, BlockingStartAndStopOnEmptySession) {
+TEST_F(PerfettoApiTest, BlockingStartAndStopOnEmptySession) {
   // Setup the trace config.
   perfetto::TraceConfig cfg;
   cfg.set_duration_ms(500);
@@ -2846,7 +2080,7 @@
   EXPECT_TRUE(tracing_session->on_stop.notified());
 }
 
-TEST_P(PerfettoApiTest, WriteEventsAfterDeferredStop) {
+TEST_F(PerfettoApiTest, WriteEventsAfterDeferredStop) {
   auto* data_source = &data_sources_["my_data_source"];
   data_source->handle_stop_asynchronously = true;
 
@@ -2873,7 +2107,7 @@
   // 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.
-  std::this_thread::sleep_for(std::chrono::milliseconds(250));
+  usleep(250 * 1000);
 
   MockDataSource::Trace([&lambda_called](MockDataSource::TraceContext ctx) {
     auto packet = ctx.NewTracePacket();
@@ -2911,7 +2145,7 @@
   EXPECT_EQ(test_packet_found, 1);
 }
 
-TEST_P(PerfettoApiTest, RepeatedStartAndStop) {
+TEST_F(PerfettoApiTest, RepeatedStartAndStop) {
   perfetto::TraceConfig cfg;
   cfg.set_duration_ms(500);
   cfg.add_buffers()->set_size_kb(1024);
@@ -2929,38 +2163,38 @@
   }
 }
 
-TEST_P(PerfettoApiTest, SetupWithFile) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  if (GetParam() == perfetto::kSystemBackend)
-    GTEST_SKIP() << "write_into_file + system mode is not supported on Windows";
+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
-  auto temp_file = perfetto::test::CreateTempFile();
+  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, temp_file.fd);
+  auto* tracing_session = NewTrace(cfg, fd);
   tracing_session->get()->StartBlocking();
   tracing_session->get()->StopBlocking();
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   // Check that |fd| didn't get closed.
-  EXPECT_EQ(0, fcntl(temp_file.fd, F_GETFD, 0));
-#endif
+  EXPECT_EQ(0, fcntl(fd, F_GETFD, 0));
   // Check that the trace got written.
-  EXPECT_GT(lseek(temp_file.fd, 0, SEEK_END), 0);
-  EXPECT_EQ(0, close(temp_file.fd));
+  EXPECT_GT(lseek(fd, 0, SEEK_END), 0);
+  EXPECT_EQ(0, close(fd));
   // Clean up.
-  EXPECT_EQ(0, remove(temp_file.path.c_str()));
+  EXPECT_EQ(0, unlink(temp_file));
 }
 
-TEST_P(PerfettoApiTest, MultipleRegistrations) {
+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));
-  perfetto::test::SyncProducers();
 
   // Setup the trace config.
   perfetto::TraceConfig cfg;
@@ -2984,11 +2218,10 @@
   EXPECT_EQ(trace_lambda_calls, 1);
 }
 
-TEST_P(PerfettoApiTest, CustomIncrementalState) {
+TEST_F(PerfettoApiTest, CustomIncrementalState) {
   perfetto::DataSourceDescriptor dsd;
   dsd.set_name("incr_data_source");
   TestIncrementalDataSource::Register(dsd);
-  perfetto::test::SyncProducers();
 
   // Setup the trace config.
   perfetto::TraceConfig cfg;
@@ -3038,7 +2271,7 @@
 
 // Regression test for b/139110180. Checks that GetDataSourceLocked() can be
 // called from OnStart() and OnStop() callbacks without deadlocking.
-TEST_P(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
+TEST_F(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
   auto* data_source = &data_sources_["my_data_source"];
 
   // Setup the trace config.
@@ -3091,187 +2324,11 @@
   EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
 }
 
-TEST_P(PerfettoApiTest, OnStartCallback) {
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(60000);
-  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);
-
-  WaitableTestEvent got_start;
-  tracing_session->get()->SetOnStartCallback([&] { got_start.Notify(); });
-  tracing_session->get()->Start();
-  got_start.Wait();
-
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, OnErrorCallback) {
-  perfetto::TraceConfig cfg;
-
-  // Requesting too long |duration_ms| will cause EnableTracing() to fail.
-  cfg.set_duration_ms(static_cast<uint32_t>(-1));
-  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);
-
-  WaitableTestEvent got_error;
-  tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
-    EXPECT_EQ(perfetto::TracingError::kTracingFailed, error.code);
-    EXPECT_FALSE(error.message.empty());
-    got_error.Notify();
-  });
-
-  tracing_session->get()->Start();
-  got_error.Wait();
-
-  // Registered error callback will be triggered also by OnDisconnect()
-  // function. This may happen after exiting this test what would result in
-  // system crash (|got_error| will not exist at that time). To prevent that
-  // scenario, error callback has to be cleared.
-  tracing_session->get()->SetOnErrorCallback(nullptr);
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, UnsupportedBackend) {
-  // Create a new trace session with an invalid backend type specified.
-  // Specifically, the custom backend isn't initialized for these tests.
-  perfetto::TraceConfig cfg;
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* tracing_session = NewTrace(cfg, perfetto::BackendType::kCustomBackend);
-
-  // Creating the consumer should cause an asynchronous disconnect error.
-  WaitableTestEvent got_error;
-  tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
-    EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
-    EXPECT_FALSE(error.message.empty());
-    got_error.Notify();
-  });
-  got_error.Wait();
-
-  // Clear the callback for test tear down.
-  tracing_session->get()->SetOnErrorCallback(nullptr);
-  // Synchronize the consumer channel to ensure the callback has propagated.
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, ForbiddenConsumer) {
-  g_test_tracing_policy->should_allow_consumer_connection = false;
-
-  // Create a new trace session while consumer connections are forbidden.
-  perfetto::TraceConfig cfg;
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* tracing_session = NewTrace(cfg);
-
-  // Creating the consumer should cause an asynchronous disconnect error.
-  WaitableTestEvent got_error;
-  tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
-    EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
-    EXPECT_FALSE(error.message.empty());
-    got_error.Notify();
-  });
-  got_error.Wait();
-
-  // Clear the callback for test tear down.
-  tracing_session->get()->SetOnErrorCallback(nullptr);
-  // Synchronize the consumer channel to ensure the callback has propagated.
-  tracing_session->get()->StopBlocking();
-
-  g_test_tracing_policy->should_allow_consumer_connection = true;
-}
-
-TEST_P(PerfettoApiTest, GetTraceStats) {
-  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();
-
-  // Asynchronous read.
-  WaitableTestEvent got_stats;
-  tracing_session->get()->GetTraceStats(
-      [&got_stats](perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
-        perfetto::protos::gen::TraceStats trace_stats;
-        EXPECT_TRUE(args.success);
-        EXPECT_TRUE(trace_stats.ParseFromArray(args.trace_stats_data.data(),
-                                               args.trace_stats_data.size()));
-        EXPECT_EQ(1, trace_stats.buffer_stats_size());
-        got_stats.Notify();
-      });
-  got_stats.Wait();
-
-  // Blocking read.
-  auto stats = tracing_session->get()->GetTraceStatsBlocking();
-  perfetto::protos::gen::TraceStats trace_stats;
-  EXPECT_TRUE(stats.success);
-  EXPECT_TRUE(trace_stats.ParseFromArray(stats.trace_stats_data.data(),
-                                         stats.trace_stats_data.size()));
-  EXPECT_EQ(1, trace_stats.buffer_stats_size());
-
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, QueryServiceState) {
-  class QueryTestDataSource : public perfetto::DataSource<QueryTestDataSource> {
-  };
-  RegisterDataSource<QueryTestDataSource>("query_test_data_source");
-  perfetto::test::SyncProducers();
-
-  auto tracing_session =
-      perfetto::Tracing::NewTrace(/*BackendType=*/GetParam());
-  // Asynchronous read.
-  WaitableTestEvent got_state;
-  tracing_session->QueryServiceState(
-      [&got_state](
-          perfetto::TracingSession::QueryServiceStateCallbackArgs result) {
-        perfetto::protos::gen::TracingServiceState state;
-        EXPECT_TRUE(result.success);
-        EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
-                                         result.service_state_data.size()));
-        EXPECT_EQ(1, state.producers_size());
-        EXPECT_NE(std::string::npos,
-                  state.producers()[0].name().find("integrationtest"));
-        bool found_ds = false;
-        for (const auto& ds : state.data_sources())
-          found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
-        EXPECT_TRUE(found_ds);
-        got_state.Notify();
-      });
-  got_state.Wait();
-
-  // Blocking read.
-  auto result = tracing_session->QueryServiceStateBlocking();
-  perfetto::protos::gen::TracingServiceState state;
-  EXPECT_TRUE(result.success);
-  EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
-                                   result.service_state_data.size()));
-  EXPECT_EQ(1, state.producers_size());
-  EXPECT_NE(std::string::npos,
-            state.producers()[0].name().find("integrationtest"));
-  bool found_ds = false;
-  for (const auto& ds : state.data_sources())
-    found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
-  EXPECT_TRUE(found_ds);
-}
-
-TEST_P(PerfettoApiTest, LegacyTraceEvents) {
-  auto is_new_session = [] {
-    bool result;
-    TRACE_EVENT_IS_NEW_TRACE(&result);
-    return result;
-  };
-
+TEST_F(PerfettoApiTest, LegacyTraceEvents) {
   // Create a new trace session.
-  EXPECT_FALSE(is_new_session());
   auto* tracing_session =
       NewTraceWithCategories({"cat", TRACE_DISABLED_BY_DEFAULT("cat")});
   tracing_session->get()->StartBlocking();
-  EXPECT_TRUE(is_new_session());
-  EXPECT_FALSE(is_new_session());
 
   // Basic events.
   TRACE_EVENT_INSTANT0("cat", "LegacyEvent", TRACE_EVENT_SCOPE_GLOBAL);
@@ -3293,7 +2350,7 @@
   // Event with id, thread id and timestamp (and dynamic name).
   TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
       "cat", std::string("LegacyWithIdTidAndTimestamp").c_str(), 1,
-      MyThreadId(123), MyTimestamp{3});
+      MyThreadId(123, 456), MyTimestamp{3});
 
   // Event with id.
   TRACE_COUNTER1("cat", "LegacyCounter", 1234);
@@ -3308,21 +2365,20 @@
   EXPECT_THAT(
       slices,
       ElementsAre(
-          "[track=0]I:cat.LegacyEvent", "B:cat.LegacyEvent(arg=(int)123)",
-          "E(arg=(string)string,arg2=(double)0.123)", "B:cat.ScopedLegacyEvent",
-          "E",
+          "I:cat.LegacyEvent", "B:cat.LegacyEvent(arg=(int)123)",
+          "E.LegacyEvent(arg=(string)string,arg2=(double)0.123)",
+          "B:cat.ScopedLegacyEvent", "E",
           "B(bind_id=3671771902)(flow_direction=1):disabled-by-default-cat."
           "LegacyFlowEvent",
-          "[track=0]I:cat.LegacyInstantEvent",
-          std::string("[track=") +
-              std::to_string(perfetto::ThreadTrack::ForThread(123).uuid) +
-              "]Legacy_S(unscoped_id=1):cat.LegacyWithIdTidAndTimestamp",
+          "I:cat.LegacyInstantEvent",
+          "Legacy_S(unscoped_id=1)(pid_override=123)(tid_override=456):cat."
+          "LegacyWithIdTidAndTimestamp",
           "Legacy_C:cat.LegacyCounter(value=(int)1234)",
           "Legacy_C(unscoped_id=1234):cat.LegacyCounterWithId(value=(int)9000)",
           "Legacy_M:cat.LegacyMetadata"));
 }
 
-TEST_P(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"cat"});
   tracing_session->get()->StartBlocking();
@@ -3341,7 +2397,7 @@
                           "B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
 }
 
-TEST_P(PerfettoApiTest, LegacyTraceEventsWithConcurrentSessions) {
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithConcurrentSessions) {
   // Make sure that a uniquely owned debug annotation can be written into
   // multiple concurrent tracing sessions.
 
@@ -3366,7 +2422,7 @@
               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
 }
 
-TEST_P(PerfettoApiTest, LegacyTraceEventsWithId) {
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithId) {
   auto* tracing_session = NewTraceWithCategories({"cat"});
   tracing_session->get()->StartBlocking();
 
@@ -3387,7 +2443,7 @@
                                   "string\"):cat.WithScope"));
 }
 
-TEST_P(PerfettoApiTest, LegacyTraceEventsWithFlow) {
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithFlow) {
   auto* tracing_session = NewTraceWithCategories({"cat"});
   tracing_session->get()->StartBlocking();
 
@@ -3423,7 +2479,7 @@
                           "E"));
 }
 
-TEST_P(PerfettoApiTest, LegacyCategoryGroupEnabledState) {
+TEST_F(PerfettoApiTest, LegacyCategoryGroupEnabledState) {
   bool foo_status;
   bool bar_status;
   bool dynamic_status;
@@ -3441,19 +2497,7 @@
   EXPECT_FALSE(*foo_enabled);
   EXPECT_FALSE(*bar_enabled);
 
-  // The category group enabled pointer can also be retrieved with a
-  // runtime-computed category name.
-  std::string computed_cat("cat");
-  const uint8_t* computed_enabled =
-      TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(computed_cat.c_str());
-  EXPECT_FALSE(*computed_enabled);
-
-  // The enabled pointers can be converted back to category names.
-  EXPECT_EQ("foo", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(foo_enabled));
-  EXPECT_EQ("bar", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(bar_enabled));
-  EXPECT_EQ("cat", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(computed_enabled));
-
-  auto* tracing_session = NewTraceWithCategories({"foo", "dynamic", "cat"});
+  auto* tracing_session = NewTraceWithCategories({"foo", "dynamic"});
   tracing_session->get()->StartBlocking();
   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
@@ -3464,7 +2508,6 @@
 
   EXPECT_TRUE(*foo_enabled);
   EXPECT_FALSE(*bar_enabled);
-  EXPECT_TRUE(*computed_enabled);
 
   tracing_session->get()->StopBlocking();
   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
@@ -3475,10 +2518,9 @@
   EXPECT_FALSE(dynamic_status);
   EXPECT_FALSE(*foo_enabled);
   EXPECT_FALSE(*bar_enabled);
-  EXPECT_FALSE(*computed_enabled);
 }
 
-TEST_P(PerfettoApiTest, CategoryEnabledState) {
+TEST_F(PerfettoApiTest, CategoryEnabledState) {
   perfetto::DynamicCategory dynamic{"dynamic"};
   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
@@ -3505,525 +2547,8 @@
   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
 }
 
-class TestInterceptor : public perfetto::Interceptor<TestInterceptor> {
- public:
-  static TestInterceptor* instance;
-
-  struct ThreadLocalState : public perfetto::InterceptorBase::ThreadLocalState {
-    ThreadLocalState(ThreadLocalStateArgs& args) {
-      // Test accessing instance state from the TLS constructor.
-      if (auto self = args.GetInterceptorLocked()) {
-        self->tls_initialized = true;
-      }
-    }
-
-    std::map<uint64_t, std::string> event_names;
-  };
-
-  TestInterceptor(const std::string& constructor_arg) {
-    EXPECT_EQ(constructor_arg, "Constructor argument");
-    // Note: some tests in this suite register multiple track event data
-    // sources. We only track data for the first in this test.
-    if (!instance)
-      instance = this;
-  }
-
-  ~TestInterceptor() override {
-    if (instance != this)
-      return;
-    instance = nullptr;
-    EXPECT_TRUE(setup_called);
-    EXPECT_TRUE(start_called);
-    EXPECT_TRUE(stop_called);
-    EXPECT_TRUE(tls_initialized);
-  }
-
-  void OnSetup(const SetupArgs&) override {
-    EXPECT_FALSE(setup_called);
-    EXPECT_FALSE(start_called);
-    EXPECT_FALSE(stop_called);
-    setup_called = true;
-  }
-
-  void OnStart(const StartArgs&) override {
-    EXPECT_TRUE(setup_called);
-    EXPECT_FALSE(start_called);
-    EXPECT_FALSE(stop_called);
-    start_called = true;
-  }
-
-  void OnStop(const StopArgs&) override {
-    EXPECT_TRUE(setup_called);
-    EXPECT_TRUE(start_called);
-    EXPECT_FALSE(stop_called);
-    stop_called = true;
-  }
-
-  static void OnTracePacket(InterceptorContext context) {
-    perfetto::protos::pbzero::TracePacket::Decoder packet(
-        context.packet_data.data, context.packet_data.size);
-    EXPECT_TRUE(packet.trusted_packet_sequence_id() > 0);
-    {
-      auto self = context.GetInterceptorLocked();
-      ASSERT_TRUE(self);
-      EXPECT_TRUE(self->setup_called);
-      EXPECT_TRUE(self->start_called);
-      EXPECT_FALSE(self->stop_called);
-      EXPECT_TRUE(self->tls_initialized);
-    }
-
-    auto& tls = context.GetThreadLocalState();
-    if (packet.sequence_flags() &
-        perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
-      tls.event_names.clear();
-    }
-    if (packet.has_interned_data()) {
-      perfetto::protos::pbzero::InternedData::Decoder interned_data(
-          packet.interned_data());
-      for (auto it = interned_data.event_names(); it; it++) {
-        perfetto::protos::pbzero::EventName::Decoder entry(*it);
-        tls.event_names[entry.iid()] = entry.name().ToStdString();
-      }
-    }
-    if (packet.has_track_event()) {
-      perfetto::protos::pbzero::TrackEvent::Decoder track_event(
-          packet.track_event());
-      uint64_t name_iid = track_event.name_iid();
-      auto self = context.GetInterceptorLocked();
-      self->events.push_back(tls.event_names[name_iid].c_str());
-    }
-  }
-
-  bool setup_called = false;
-  bool start_called = false;
-  bool stop_called = false;
-  bool tls_initialized = false;
-  std::vector<std::string> events;
-};
-
-TestInterceptor* TestInterceptor::instance;
-
-TEST_P(PerfettoApiTest, TracePacketInterception) {
-  perfetto::InterceptorDescriptor desc;
-  desc.set_name("test_interceptor");
-  TestInterceptor::Register(desc, std::string("Constructor argument"));
-
-  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->mutable_interceptor_config()->set_name("test_interceptor");
-
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-  EXPECT_EQ(0u, TestInterceptor::instance->events.size());
-
-  // The interceptor should see an event immediately without any explicit
-  // flushing.
-  TRACE_EVENT_BEGIN("foo", "Hip");
-  EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip"));
-
-  // Emit another event with the same title to test interning.
-  TRACE_EVENT_BEGIN("foo", "Hip");
-  EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip", "Hip"));
-
-  // Emit an event from another thread. It should still reach the same
-  // interceptor instance.
-  std::thread thread([] { TRACE_EVENT_BEGIN("foo", "Hooray"); });
-  thread.join();
-  EXPECT_THAT(TestInterceptor::instance->events,
-              ElementsAre("Hip", "Hip", "Hooray"));
-
-  // Emit a packet that spans multiple segments and must be stitched together.
-  TestInterceptor::instance->events.clear();
-  static char long_title[8192];
-  memset(long_title, 'a', sizeof(long_title) - 1);
-  long_title[sizeof(long_title) - 1] = 0;
-  TRACE_EVENT_BEGIN("foo", long_title);
-  EXPECT_THAT(TestInterceptor::instance->events, ElementsAre(long_title));
-
-  tracing_session->get()->StopBlocking();
-}
-
-void EmitConsoleEvents() {
-  TRACE_EVENT_INSTANT("foo", "Instant event");
-  TRACE_EVENT("foo", "Scoped event");
-  TRACE_EVENT_BEGIN("foo", "Nested event");
-  TRACE_EVENT_INSTANT("foo", "Instant event");
-  TRACE_EVENT_INSTANT("foo", "Annotated event", "foo", 1, "bar", "hello");
-  TRACE_EVENT_END("foo");
-  uint64_t async_id = 4004;
-  auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
-  perfetto::TrackEvent::SetTrackDescriptor(
-      track, [](perfetto::protos::pbzero::TrackDescriptor* desc) {
-        desc->set_name("AsyncTrack");
-      });
-  TRACE_EVENT_BEGIN("test", "AsyncEvent", track);
-
-  std::thread thread([&] {
-    TRACE_EVENT("foo", "EventFromAnotherThread");
-    TRACE_EVENT_INSTANT("foo", "Instant event");
-    TRACE_EVENT_END("test", track);
-  });
-  thread.join();
-
-  TRACE_EVENT_INSTANT(
-      "foo", "More annotations", "dict",
-      [](perfetto::TracedValue context) {
-        auto dict = std::move(context).WriteDictionary();
-        dict.Add("key", 123);
-      },
-      "array",
-      [](perfetto::TracedValue context) {
-        auto array = std::move(context).WriteArray();
-        array.Append("first");
-        array.Append("second");
-      });
-}
-
-TEST_P(PerfettoApiTest, ConsoleInterceptorPrint) {
-  perfetto::ConsoleInterceptor::Register();
-
-  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->mutable_interceptor_config()->set_name("console");
-
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-  EmitConsoleEvents();
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_P(PerfettoApiTest, ConsoleInterceptorVerify) {
-  perfetto::ConsoleInterceptor::Register();
-  auto temp_file = perfetto::test::CreateTempFile();
-  perfetto::ConsoleInterceptor::SetOutputFdForTesting(temp_file.fd);
-
-  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->mutable_interceptor_config()->set_name("console");
-
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-  EmitConsoleEvents();
-  tracing_session->get()->StopBlocking();
-  perfetto::ConsoleInterceptor::SetOutputFdForTesting(0);
-
-  std::vector<std::string> lines;
-  FILE* f = fdopen(temp_file.fd, "r");
-  fseek(f, 0u, SEEK_SET);
-  std::array<char, 128> line{};
-  while (fgets(line.data(), line.size(), f)) {
-    // Ignore timestamps and process/thread ids.
-    std::string s(line.data() + 28);
-    // Filter out durations.
-    s = std::regex_replace(s, std::regex(" [+][0-9]*ms"), "");
-    lines.push_back(std::move(s));
-  }
-  fclose(f);
-  EXPECT_EQ(0, remove(temp_file.path.c_str()));
-
-  // clang-format off
-  std::vector<std::string> golden_lines = {
-      "foo   Instant event\n",
-      "foo   Scoped event {\n",
-      "foo   -  Nested event {\n",
-      "foo   -  -  Instant event\n",
-      "foo   -  -  Annotated event(foo:1, bar:hello)\n",
-      "foo   -  } Nested event\n",
-      "test  AsyncEvent {\n",
-      "foo   EventFromAnotherThread {\n",
-      "foo   -  Instant event\n",
-      "test  } AsyncEvent\n",
-      "foo   } EventFromAnotherThread\n",
-      "foo   -  More annotations(dict:{key:123}, array:[first, second])\n",
-      "foo   } Scoped event\n",
-  };
-  // clang-format on
-  EXPECT_THAT(lines, ContainerEq(golden_lines));
-}
-
-TEST_P(PerfettoApiTest, TrackEventObserver) {
-  class Observer : public perfetto::TrackEventSessionObserver {
-   public:
-    ~Observer() override = default;
-
-    void OnSetup(const perfetto::DataSourceBase::SetupArgs&) {
-      // Since other tests here register multiple track event data sources,
-      // ignore all but the first notifications.
-      if (setup_called)
-        return;
-      setup_called = true;
-      if (unsubscribe_at_setup)
-        perfetto::TrackEvent::RemoveSessionObserver(this);
-      // This event isn't recorded in the trace because tracing isn't active yet
-      // when OnSetup is called.
-      TRACE_EVENT_INSTANT("foo", "OnSetup");
-      // However the active tracing categories have already been updated at this
-      // point.
-      EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
-      EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
-    }
-
-    void OnStart(const perfetto::DataSourceBase::StartArgs&) {
-      if (start_called)
-        return;
-      start_called = true;
-      EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
-      EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
-      TRACE_EVENT_INSTANT("foo", "OnStart");
-    }
-
-    void OnStop(const perfetto::DataSourceBase::StopArgs&) {
-      if (stop_called)
-        return;
-      stop_called = true;
-      EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
-      EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
-      TRACE_EVENT_INSTANT("foo", "OnStop");
-      perfetto::TrackEvent::Flush();
-    }
-
-    bool setup_called{};
-    bool start_called{};
-    bool stop_called{};
-    bool unsubscribe_at_setup{};
-  };
-
-  EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
-  {
-    Observer observer;
-    perfetto::TrackEvent::AddSessionObserver(&observer);
-
-    auto* tracing_session = NewTraceWithCategories({"foo"});
-    tracing_session->get()->StartBlocking();
-    EXPECT_TRUE(observer.setup_called);
-    EXPECT_TRUE(observer.start_called);
-    tracing_session->get()->StopBlocking();
-    EXPECT_TRUE(observer.stop_called);
-    perfetto::TrackEvent::RemoveSessionObserver(&observer);
-    auto slices = ReadSlicesFromTrace(tracing_session->get());
-    EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStop"));
-  }
-
-  // No notifications after removing observer.
-  {
-    Observer observer;
-    perfetto::TrackEvent::AddSessionObserver(&observer);
-    perfetto::TrackEvent::RemoveSessionObserver(&observer);
-    auto* tracing_session = NewTraceWithCategories({"foo"});
-    tracing_session->get()->StartBlocking();
-    EXPECT_FALSE(observer.setup_called);
-    EXPECT_FALSE(observer.start_called);
-    tracing_session->get()->StopBlocking();
-    EXPECT_FALSE(observer.stop_called);
-  }
-
-  // Removing observer in a callback.
-  {
-    Observer observer;
-    observer.unsubscribe_at_setup = true;
-    perfetto::TrackEvent::AddSessionObserver(&observer);
-    auto* tracing_session = NewTraceWithCategories({"foo"});
-    tracing_session->get()->StartBlocking();
-    EXPECT_TRUE(observer.setup_called);
-    EXPECT_FALSE(observer.start_called);
-    tracing_session->get()->StopBlocking();
-    EXPECT_FALSE(observer.stop_called);
-    perfetto::TrackEvent::RemoveSessionObserver(&observer);
-  }
-
-  // Multiple observers.
-  {
-    Observer observer1;
-    Observer observer2;
-    perfetto::TrackEvent::AddSessionObserver(&observer1);
-    perfetto::TrackEvent::AddSessionObserver(&observer2);
-    auto* tracing_session = NewTraceWithCategories({"foo"});
-    tracing_session->get()->StartBlocking();
-    tracing_session->get()->StopBlocking();
-    perfetto::TrackEvent::RemoveSessionObserver(&observer1);
-    perfetto::TrackEvent::RemoveSessionObserver(&observer2);
-    auto slices = ReadSlicesFromTrace(tracing_session->get());
-    EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStart",
-                                    "I:foo.OnStop", "I:foo.OnStop"));
-  }
-
-  // Multiple observers with one being removed midway.
-  {
-    Observer observer1;
-    Observer observer2;
-    perfetto::TrackEvent::AddSessionObserver(&observer1);
-    perfetto::TrackEvent::AddSessionObserver(&observer2);
-    auto* tracing_session = NewTraceWithCategories({"foo"});
-    tracing_session->get()->StartBlocking();
-    perfetto::TrackEvent::RemoveSessionObserver(&observer1);
-    tracing_session->get()->StopBlocking();
-    perfetto::TrackEvent::RemoveSessionObserver(&observer2);
-    auto slices = ReadSlicesFromTrace(tracing_session->get());
-    EXPECT_THAT(slices,
-                ElementsAre("I:foo.OnStart", "I:foo.OnStart", "I:foo.OnStop"));
-  }
-  EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
-struct __attribute__((capability("mutex"))) MockMutex {
-  void Lock() __attribute__((acquire_capability())) {}
-  void Unlock() __attribute__((release_capability())) {}
-};
-
-struct AnnotatedObject {
-  MockMutex mutex;
-  int value __attribute__((guarded_by(mutex))) = {};
-};
-
-TEST_P(PerfettoApiTest, ThreadSafetyAnnotation) {
-  AnnotatedObject obj;
-
-  // Access to the locked field is only allowed while holding the mutex.
-  obj.mutex.Lock();
-  obj.value = 1;
-  obj.mutex.Unlock();
-
-  auto* tracing_session = NewTraceWithCategories({"cat"});
-  tracing_session->get()->StartBlocking();
-
-  // It should be possible to trace the field while holding the lock.
-  obj.mutex.Lock();
-  TRACE_EVENT_INSTANT("cat", "Instant", "value", obj.value);
-  TRACE_EVENT_INSTANT1("cat", "InstantLegacy", 0, "value", obj.value);
-  { TRACE_EVENT("cat", "Scoped", "value", obj.value); }
-  { TRACE_EVENT1("cat", "ScopedLegacy", "value", obj.value); }
-  obj.mutex.Unlock();
-
-  perfetto::TrackEvent::Flush();
-  tracing_session->get()->StopBlocking();
-  auto slices = ReadSlicesFromTrace(tracing_session->get());
-  EXPECT_THAT(slices, ElementsAre("I:cat.Instant(value=(int)1)",
-                                  "[track=0]I:cat.InstantLegacy(value=(int)1)",
-                                  "B:cat.Scoped(value=(int)1)", "E",
-                                  "B:cat.ScopedLegacy(value=(int)1)", "E"));
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
-
-TEST_P(PerfettoApiTest, Counters) {
-  auto* tracing_session = NewTraceWithCategories({"cat"});
-  tracing_session->get()->StartBlocking();
-
-  // Describe a counter track.
-  perfetto::CounterTrack fps_track = perfetto::CounterTrack("Framerate", "fps");
-
-  // Emit an integer sample.
-  TRACE_COUNTER("cat", fps_track, 120);
-
-  // Global tracks can be constructed at build time.
-  constexpr auto goats_track =
-      perfetto::CounterTrack::Global("Goats teleported", "goats x 1000")
-          .set_unit_multiplier(1000);
-  static_assert(goats_track.uuid == 0x6072fc234f82df11,
-                "Counter track uuid mismatch");
-
-  // Emit some floating point samples.
-  TRACE_COUNTER("cat", goats_track, 0.25);
-  TRACE_COUNTER("cat", goats_track, 0.5);
-  TRACE_COUNTER("cat", goats_track, 0.75);
-
-  // Emit a sample using an inline track name.
-  TRACE_COUNTER("cat", "Voltage", 220);
-
-  // Emit sample with a custom timestamp.
-  TRACE_COUNTER("cat",
-                perfetto::CounterTrack("Power", "GW").set_category("dmc"),
-                MyTimestamp(1985u), 1.21f);
-  perfetto::TrackEvent::Flush();
-
-  tracing_session->get()->StopBlocking();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-
-  perfetto::protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-  std::map<uint64_t, std::string> counter_names;
-  std::vector<std::string> counter_samples;
-  for (const auto& packet : trace.packet()) {
-    if (packet.has_track_event()) {
-      auto event = packet.track_event();
-      EXPECT_EQ(perfetto::protos::gen::TrackEvent_Type_TYPE_COUNTER,
-                event.type());
-      std::stringstream sample;
-      std::string counter_name = counter_names[event.track_uuid()];
-      sample << counter_name << " = ";
-      if (event.has_counter_value()) {
-        sample << event.counter_value();
-      } else if (event.has_double_counter_value()) {
-        sample << event.double_counter_value();
-      }
-      if (counter_name == "Power") {
-        EXPECT_EQ(1985u, packet.timestamp());
-      }
-      counter_samples.push_back(sample.str());
-    }
-
-    if (!packet.has_track_descriptor() ||
-        !packet.track_descriptor().has_counter()) {
-      continue;
-    }
-    auto desc = packet.track_descriptor();
-    counter_names[desc.uuid()] = desc.name();
-    if (desc.name() == "Framerate") {
-      EXPECT_EQ("fps", desc.counter().unit_name());
-    } else if (desc.name() == "Goats teleported") {
-      EXPECT_EQ("goats x 1000", desc.counter().unit_name());
-      EXPECT_EQ(1000, desc.counter().unit_multiplier());
-    } else if (desc.name() == "Power") {
-      EXPECT_EQ("GW", desc.counter().unit_name());
-      EXPECT_EQ("dmc", desc.counter().categories()[0]);
-    }
-  }
-  EXPECT_EQ(4u, counter_names.size());
-  EXPECT_THAT(counter_samples,
-              ElementsAre("Framerate = 120", "Goats teleported = 0.25",
-                          "Goats teleported = 0.5", "Goats teleported = 0.75",
-                          "Voltage = 220", "Power = 1.21"));
-}
-
-struct BackendTypeAsString {
-  std::string operator()(
-      const ::testing::TestParamInfo<perfetto::BackendType>& info) const {
-    switch (info.param) {
-      case perfetto::kInProcessBackend:
-        return "InProc";
-      case perfetto::kSystemBackend:
-        return "System";
-      case perfetto::kCustomBackend:
-        return "Custom";
-      case perfetto::kUnspecifiedBackend:
-        return "Unspec";
-    }
-    return nullptr;
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(PerfettoApiTest,
-                         PerfettoApiTest,
-                         ::testing::Values(perfetto::kInProcessBackend,
-                                           perfetto::kSystemBackend),
-                         BackendTypeAsString());
-
 }  // namespace
 
-PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
-PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
-PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
-                                            TestIncrementalDataSourceTraits);
-
 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
diff --git a/src/tracing/test/api_test_support.cc b/src/tracing/test/api_test_support.cc
index 0142d28..5689a74 100644
--- a/src/tracing/test/api_test_support.cc
+++ b/src/tracing/test/api_test_support.cc
@@ -18,115 +18,13 @@
 
 #include "perfetto/base/proc_utils.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "src/tracing/internal/tracing_muxer_impl.h"
-
-#include <sstream>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_IPC)
-#include "test/test_helper.h"
-#endif
 
 namespace perfetto {
 namespace test {
 
-#if PERFETTO_BUILDFLAG(PERFETTO_IPC)
-namespace {
-
-class InProcessSystemService {
- public:
-  InProcessSystemService()
-      : test_helper_(&task_runner_, TestHelper::Mode::kStartDaemons) {
-    // Will always start service because we explicitly set kStartDaemons.
-    test_helper_.StartServiceIfRequired();
-  }
-
- private:
-  perfetto::base::TestTaskRunner task_runner_;
-  perfetto::TestHelper test_helper_;
-};
-
-}  // namespace
-
-bool StartSystemService() {
-  static InProcessSystemService* system_service;
-
-  // If there already was a system service running, make sure the new one is
-  // running before tearing down the old one. This avoids a 1 second
-  // reconnection delay between each test since the connection to the new
-  // service succeeds immediately.
-  std::unique_ptr<InProcessSystemService> old_service(system_service);
-  system_service = new InProcessSystemService();
-
-  // Tear down the service at process exit to make sure temporary files get
-  // deleted.
-  static bool cleanup_registered;
-  if (!cleanup_registered) {
-    atexit([] { delete system_service; });
-    cleanup_registered = true;
-  }
-  return true;
-}
-#else   // !PERFETTO_BUILDFLAG(PERFETTO_IPC)
-bool StartSystemService() {
-  return false;
-}
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_IPC)
-
 int32_t GetCurrentProcessId() {
   return static_cast<int32_t>(base::GetProcessId());
 }
 
-void SyncProducers() {
-  auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
-      perfetto::internal::TracingMuxer::Get());
-  muxer->SyncProducersForTesting();
-}
-
-void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms,
-                             BackendType backend_type) {
-  auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
-      perfetto::internal::TracingMuxer::Get());
-  muxer->SetBatchCommitsDurationForTesting(batch_commits_duration_ms,
-                                           backend_type);
-}
-
-void DisableReconnectLimit() {
-  auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
-      perfetto::internal::TracingMuxer::Get());
-  muxer->SetMaxProducerReconnectionsForTesting(
-      std::numeric_limits<uint32_t>::max());
-}
-
-bool EnableDirectSMBPatching(BackendType backend_type) {
-  auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
-      perfetto::internal::TracingMuxer::Get());
-  return muxer->EnableDirectSMBPatchingForTesting(backend_type);
-}
-
-TestTempFile CreateTempFile() {
-  TestTempFile res{};
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  char temp_file[255]{};
-  sprintf(temp_file, "%s\\perfetto-XXXXXX", getenv("TMP"));
-  PERFETTO_CHECK(_mktemp_s(temp_file, strlen(temp_file) + 1) == 0);
-  HANDLE handle =
-      ::CreateFileA(temp_file, GENERIC_READ | GENERIC_WRITE,
-                    FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS,
-                    FILE_ATTRIBUTE_TEMPORARY, nullptr);
-  PERFETTO_CHECK(handle && handle != INVALID_HANDLE_VALUE);
-  res.fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle), 0);
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
-  res.fd = mkstemp(temp_file);
-#else
-  char temp_file[] = "/tmp/perfetto-XXXXXXXX";
-  res.fd = mkstemp(temp_file);
-#endif
-  res.path = temp_file;
-  PERFETTO_CHECK(res.fd > 0);
-  return res;
-}
-
 }  // namespace test
 }  // namespace perfetto
diff --git a/src/tracing/test/api_test_support.h b/src/tracing/test/api_test_support.h
index 33a7a53..9409caf 100644
--- a/src/tracing/test/api_test_support.h
+++ b/src/tracing/test/api_test_support.h
@@ -27,29 +27,11 @@
 //  IMPORTANT: This header must not pull any non-public perfetto header.
 
 #include <stdint.h>
-#include "perfetto/tracing.h"
 
 namespace perfetto {
 namespace test {
 
 int32_t GetCurrentProcessId();
-bool StartSystemService();
-void SyncProducers();
-
-void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms,
-                             BackendType backend_type);
-
-bool EnableDirectSMBPatching(BackendType backend_type);
-
-void DisableReconnectLimit();
-
-struct TestTempFile {
-  int fd;
-  std::string path;
-};
-
-// The caller must close(2) the returned TempFile.fd.
-TestTempFile CreateTempFile();
 
 }  // namespace test
 }  // namespace perfetto
diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc
index 2d7dc4c..e7cf3b1 100644
--- a/src/tracing/test/mock_consumer.cc
+++ b/src/tracing/test/mock_consumer.cc
@@ -73,8 +73,7 @@
   static int i = 0;
   auto checkpoint_name = "on_tracing_disabled_consumer_" + std::to_string(i++);
   auto on_tracing_disabled = task_runner_->CreateCheckpoint(checkpoint_name);
-  EXPECT_CALL(*this, OnTracingDisabled(_))
-      .WillOnce(testing::InvokeWithoutArgs(on_tracing_disabled));
+  EXPECT_CALL(*this, OnTracingDisabled()).WillOnce(Invoke(on_tracing_disabled));
   task_runner_->RunUntilCheckpoint(checkpoint_name, timeout_ms);
 }
 
diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h
index 9ba12b4..a1f050e 100644
--- a/src/tracing/test/mock_consumer.h
+++ b/src/tracing/test/mock_consumer.h
@@ -69,7 +69,7 @@
   // Consumer implementation.
   MOCK_METHOD0(OnConnect, void());
   MOCK_METHOD0(OnDisconnect, void());
-  MOCK_METHOD1(OnTracingDisabled, void(const std::string& /*error*/));
+  MOCK_METHOD0(OnTracingDisabled, void());
   MOCK_METHOD2(OnTraceData,
                void(std::vector<TracePacket>* /*packets*/, bool /*has_more*/));
   MOCK_METHOD1(OnDetach, void(bool));
diff --git a/src/tracing/test/platform_unittest.cc b/src/tracing/test/platform_unittest.cc
deleted file mode 100644
index 8608664..0000000
--- a/src/tracing/test/platform_unittest.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <atomic>
-
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/waitable_event.h"
-#include "perfetto/tracing/internal/tracing_tls.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-internal::TracingTLS* GetTLS() {
-  return static_cast<internal::TracingTLS*>(
-      Platform::GetDefaultPlatform()->GetOrCreateThreadLocalObject());
-}
-
-// We use this class only as a listener to detect thread-local destruction.
-class FakeTraceWriter : public TraceWriterBase {
- public:
-  std::atomic<bool>* destroyed_flag;
-
-  ~FakeTraceWriter() override { *destroyed_flag = true; }
-  protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket() {
-    PERFETTO_CHECK(false);
-  }
-  void Flush(std::function<void()>) override {}
-  uint64_t written() const override { return 0; }
-};
-
-// This test mainly checks that the thread at-exit logic works properly and
-// destroys the TracingTLS when a thread exits.
-TEST(PlatformUnittest, ThreadingAndTLSDtor) {
-  auto* platform = Platform::GetDefaultPlatform();
-  if (!platform)
-    GTEST_SKIP() << "Platform::GetDefaultPlatform() not implemented";
-
-  auto proc_name = platform->GetCurrentProcessName();
-  EXPECT_FALSE(proc_name.empty());
-
-  // Create two threads.
-
-  Platform::CreateTaskRunnerArgs tr_args{};
-  auto thread1 = platform->CreateTaskRunner(tr_args);
-  ASSERT_TRUE(thread1);
-
-  auto thread2 = platform->CreateTaskRunner(tr_args);
-  ASSERT_TRUE(thread2);
-
-  // Check that the TLS is actually thread-local.
-
-  thread1->PostTask([] { GetTLS()->generation = 101; });
-  thread2->PostTask([] { GetTLS()->generation = 102; });
-  std::atomic<bool> thread1_destroyed{};
-  std::atomic<bool> thread2_destroyed{};
-
-  // Now post another task on each thread. The task will:
-  // 1. Check that the generation matches what previously set.
-  // 2. Create a FakeTraceWriter and wire up a destruction event.
-  base::WaitableEvent evt1;
-  thread1->PostTask([&] {
-    EXPECT_EQ(GetTLS()->generation, 101u);
-    GetTLS()->data_sources_tls[0].per_instance[0].Reset();
-    std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
-    tw->destroyed_flag = &thread1_destroyed;
-    GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
-    evt1.Notify();
-  });
-  evt1.Wait();
-
-  base::WaitableEvent evt2;
-  thread2->PostTask([&] {
-    EXPECT_EQ(GetTLS()->generation, 102u);
-    GetTLS()->data_sources_tls[0].per_instance[0].Reset();
-    std::unique_ptr<FakeTraceWriter> tw(new FakeTraceWriter());
-    tw->destroyed_flag = &thread2_destroyed;
-    GetTLS()->data_sources_tls[0].per_instance[0].trace_writer = std::move(tw);
-    evt2.Notify();
-  });
-  evt2.Wait();
-
-  EXPECT_FALSE(thread1_destroyed);
-  EXPECT_FALSE(thread2_destroyed);
-
-  thread1.reset();
-  EXPECT_TRUE(thread1_destroyed);
-  EXPECT_FALSE(thread2_destroyed);
-
-  thread2.reset();
-  EXPECT_TRUE(thread2_destroyed);
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/tracing/test/test_shared_memory.h b/src/tracing/test/test_shared_memory.h
index 9db6bcb..2a323bf 100644
--- a/src/tracing/test/test_shared_memory.h
+++ b/src/tracing/test/test_shared_memory.h
@@ -41,6 +41,7 @@
 
   void* start() const override { return mem_.Get(); }
   size_t size() const override { return size_; }
+  int fd() const override { return -1; }
 
   base::PagedMemory mem_;
   size_t size_;
diff --git a/src/tracing/test/traced_value_test_support.cc b/src/tracing/test/traced_value_test_support.cc
deleted file mode 100644
index ad296d7..0000000
--- a/src/tracing/test/traced_value_test_support.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/test/traced_value_test_support.h"
-
-#include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pb.h"
-
-#include <sstream>
-
-namespace perfetto {
-
-namespace internal {
-
-namespace {
-
-void WriteAsJSON(const protos::DebugAnnotation& value, std::stringstream& ss) {
-  if (value.has_bool_value()) {
-    if (value.bool_value()) {
-      ss << "true";
-    } else {
-      ss << "false";
-    }
-  } else if (value.has_uint_value()) {
-    ss << value.uint_value();
-  } else if (value.has_int_value()) {
-    ss << value.int_value();
-  } else if (value.has_double_value()) {
-    ss << value.double_value();
-  } else if (value.has_string_value()) {
-    ss << value.string_value();
-  } else if (value.has_pointer_value()) {
-    // Printing pointer values via ostream is really platform-specific, so do
-    // not try to convert it to void* before printing.
-    ss << "0x" << std::hex << value.pointer_value() << std::dec;
-  } else if (value.dict_entries_size() > 0) {
-    ss << "{";
-    for (int i = 0; i < value.dict_entries_size(); ++i) {
-      if (i > 0)
-        ss << ",";
-      auto item = value.dict_entries(i);
-      ss << item.name();
-      ss << ":";
-      WriteAsJSON(item, ss);
-    }
-    ss << "}";
-  } else if (value.array_values_size() > 0) {
-    ss << "[";
-    for (int i = 0; i < value.array_values_size(); ++i) {
-      auto item = value.array_values(i);
-      if (i > 0)
-        ss << ",";
-      WriteAsJSON(item, ss);
-    }
-    ss << "]";
-  } else {
-    ss << "{}";
-  }
-}
-
-}  // namespace
-
-std::string DebugAnnotationToString(const std::string& data) {
-  std::stringstream ss;
-  protos::DebugAnnotation result;
-  result.ParseFromString(data);
-  WriteAsJSON(result, ss);
-  return ss.str();
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 3fc8d4b..8e4ec3a 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -15,6 +15,7 @@
  */
 
 #include <inttypes.h>
+#include <unistd.h>
 
 #include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/tracing/core/consumer.h"
@@ -44,12 +45,12 @@
 namespace perfetto {
 namespace {
 
-using testing::_;
 using testing::Invoke;
 using testing::InvokeWithoutArgs;
+using testing::_;
 
-ipc::TestSocket kProducerSock{"tracing_test-producer"};
-ipc::TestSocket kConsumerSock{"tracing_test-consumer"};
+constexpr char kProducerSockName[] = TEST_SOCK_NAME("tracing_test-producer");
+constexpr char kConsumerSockName[] = TEST_SOCK_NAME("tracing_test-consumer");
 
 // TODO(rsavitski): consider using src/tracing/test/mock_producer.h.
 class MockProducer : public Producer {
@@ -79,7 +80,7 @@
   // Producer implementation.
   MOCK_METHOD0(OnConnect, void());
   MOCK_METHOD0(OnDisconnect, void());
-  MOCK_METHOD1(OnTracingDisabled, void(const std::string& /*error*/));
+  MOCK_METHOD0(OnTracingDisabled, void());
   MOCK_METHOD2(OnTracePackets, void(std::vector<TracePacket>*, bool));
   MOCK_METHOD1(OnDetach, void(bool));
   MOCK_METHOD2(OnAttach, void(bool, const TraceConfig&));
@@ -118,17 +119,17 @@
 class TracingIntegrationTest : public ::testing::Test {
  public:
   void SetUp() override {
-    kProducerSock.Destroy();
-    kConsumerSock.Destroy();
+    DESTROY_TEST_SOCK(kProducerSockName);
+    DESTROY_TEST_SOCK(kConsumerSockName);
     task_runner_.reset(new base::TestTaskRunner());
 
     // Create the service host.
     svc_ = ServiceIPCHost::CreateInstance(task_runner_.get());
-    svc_->Start(kProducerSock.name(), kConsumerSock.name());
+    svc_->Start(kProducerSockName, kConsumerSockName);
 
     // Create and connect a Producer.
     producer_endpoint_ = ProducerIPCClient::Connect(
-        kProducerSock.name(), &producer_, "perfetto.mock_producer",
+        kProducerSockName, &producer_, "perfetto.mock_producer",
         task_runner_.get(), GetProducerSMBScrapingMode());
     auto on_producer_connect =
         task_runner_->CreateCheckpoint("on_producer_connect");
@@ -142,7 +143,7 @@
 
     // Create and connect a Consumer.
     consumer_endpoint_ = ConsumerIPCClient::Connect(
-        kConsumerSock.name(), &consumer_, task_runner_.get());
+        kConsumerSockName, &consumer_, task_runner_.get());
     auto on_consumer_connect =
         task_runner_->CreateCheckpoint("on_consumer_connect");
     EXPECT_CALL(consumer_, OnConnect()).WillOnce(Invoke(on_consumer_connect));
@@ -174,8 +175,8 @@
     ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&consumer_));
 
     task_runner_.reset();
-    kProducerSock.Destroy();
-    kConsumerSock.Destroy();
+    DESTROY_TEST_SOCK(kProducerSockName);
+    DESTROY_TEST_SOCK(kConsumerSockName);
   }
 
   virtual TracingService::ProducerSMBScrapingMode GetProducerSMBScrapingMode() {
@@ -296,10 +297,8 @@
           Invoke([&num_pack_rx, all_packets_rx, &trace_config,
                   &saw_clock_snapshot, &saw_trace_config, &saw_trace_stats](
                      std::vector<TracePacket>* packets, bool has_more) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
             const int kExpectedMinNumberOfClocks = 1;
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-            const int kExpectedMinNumberOfClocks = 2;
 #else
             const int kExpectedMinNumberOfClocks = 6;
 #endif
@@ -339,42 +338,11 @@
   auto on_tracing_disabled =
       task_runner_->CreateCheckpoint("on_tracing_disabled");
   EXPECT_CALL(producer_, StopDataSource(_));
-  EXPECT_CALL(consumer_, OnTracingDisabled(_))
-      .WillOnce(InvokeWithoutArgs(on_tracing_disabled));
+  EXPECT_CALL(consumer_, OnTracingDisabled())
+      .WillOnce(Invoke(on_tracing_disabled));
   task_runner_->RunUntilCheckpoint("on_tracing_disabled");
 }
 
-// Regression test for b/172950370.
-TEST_F(TracingIntegrationTest, ValidErrorOnDisconnection) {
-  // Start tracing.
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(4096 * 10);
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("perfetto.test");
-  consumer_endpoint_->EnableTracing(trace_config);
-
-  auto on_create_ds_instance =
-      task_runner_->CreateCheckpoint("on_create_ds_instance");
-  EXPECT_CALL(producer_, OnTracingSetup());
-
-  // Store the arguments passed to SetupDataSource() and later check that they
-  // match the ones passed to StartDataSource().
-  EXPECT_CALL(producer_, SetupDataSource(_, _));
-  EXPECT_CALL(producer_, StartDataSource(_, _))
-      .WillOnce(InvokeWithoutArgs(on_create_ds_instance));
-  task_runner_->RunUntilCheckpoint("on_create_ds_instance");
-
-  EXPECT_CALL(consumer_, OnTracingDisabled(_))
-      .WillOnce(Invoke([](const std::string& err) {
-        EXPECT_THAT(err,
-                    testing::HasSubstr("EnableTracing IPC request rejected"));
-      }));
-
-  // TearDown() will destroy the service via svc_.reset(). That will drop the
-  // connection and trigger the EXPECT_CALL(OnTracingDisabled) above.
-}
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 TEST_F(TracingIntegrationTest, WriteIntoFile) {
   // Start tracing.
   TraceConfig trace_config;
@@ -422,8 +390,8 @@
   auto on_tracing_disabled =
       task_runner_->CreateCheckpoint("on_tracing_disabled");
   EXPECT_CALL(producer_, StopDataSource(_));
-  EXPECT_CALL(consumer_, OnTracingDisabled(_))
-      .WillOnce(InvokeWithoutArgs(on_tracing_disabled));
+  EXPECT_CALL(consumer_, OnTracingDisabled())
+      .WillOnce(Invoke(on_tracing_disabled));
   task_runner_->RunUntilCheckpoint("on_tracing_disabled");
 
   // Check that |tmp_file| contains a valid trace.proto message.
@@ -455,7 +423,6 @@
   ASSERT_GT(num_clock_snapshot_packet, 0u);
   ASSERT_GT(num_system_info_packet, 0u);
 }
-#endif
 
 class TracingIntegrationTestWithSMBScrapingProducer
     : public TracingIntegrationTest {
@@ -549,12 +516,9 @@
 
   auto on_tracing_disabled =
       task_runner_->CreateCheckpoint("on_tracing_disabled");
-  auto on_stop_ds = task_runner_->CreateCheckpoint("on_stop_ds");
-  EXPECT_CALL(producer_, StopDataSource(_))
-      .WillOnce(InvokeWithoutArgs(on_stop_ds));
-  EXPECT_CALL(consumer_, OnTracingDisabled(_))
-      .WillOnce(InvokeWithoutArgs(on_tracing_disabled));
-  task_runner_->RunUntilCheckpoint("on_stop_ds");
+  EXPECT_CALL(producer_, StopDataSource(_));
+  EXPECT_CALL(consumer_, OnTracingDisabled())
+      .WillOnce(Invoke(on_tracing_disabled));
   task_runner_->RunUntilCheckpoint("on_tracing_disabled");
 }
 
diff --git a/src/tracing/test/tracing_module.cc b/src/tracing/test/tracing_module.cc
index 743ff68..d4fef2e 100644
--- a/src/tracing/test/tracing_module.cc
+++ b/src/tracing/test/tracing_module.cc
@@ -103,11 +103,4 @@
   puts("Hello");
 }
 
-void FunctionWithOneCounterEvent() {
-  TRACE_COUNTER("cat1", "CounterName", 4096);
-  // 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
index 76c105c..7ed9364 100644
--- a/src/tracing/test/tracing_module.h
+++ b/src/tracing/test/tracing_module.h
@@ -38,7 +38,6 @@
 void FunctionWithOneScopedTrackEvent();
 void FunctionWithOneTrackEventWithDebugAnnotations();
 void FunctionWithOneTrackEventWithCustomTrack();
-void FunctionWithOneCounterEvent();
 
 // Legacy events.
 void FunctionWithOneLegacyEvent();
diff --git a/src/tracing/traced_proto_unittest.cc b/src/tracing/traced_proto_unittest.cc
deleted file mode 100644
index e5c84f1..0000000
--- a/src/tracing/traced_proto_unittest.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/traced_proto.h"
-
-#include "perfetto/tracing/track_event.h"
-#include "protos/perfetto/trace/test_event.gen.h"
-#include "protos/perfetto/trace/test_event.pb.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.gen.h"
-#include "protos/perfetto/trace/track_event/track_event.pb.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-
-class TracedProtoTest : public ::testing::Test {
- public:
-  TracedProtoTest() : context_(track_event_.get(), &incremental_state_) {}
-
-  EventContext& context() { return context_; }
-
- private:
-  protozero::HeapBuffered<protos::pbzero::TrackEvent> track_event_;
-  internal::TrackEventIncrementalState incremental_state_;
-  EventContext context_;
-};
-
-using TestPayload = protos::pbzero::TestEvent::TestPayload;
-
-TEST_F(TracedProtoTest, SingleInt) {
-  protozero::HeapBuffered<TestPayload> event;
-  WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kSingleInt,
-                       42);
-
-  protos::TestEvent::TestPayload result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_TRUE(result.has_single_int());
-  EXPECT_EQ(result.single_int(), 42);
-}
-
-TEST_F(TracedProtoTest, RepeatedInt) {
-  protozero::HeapBuffered<TestPayload> event;
-  WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kRepeatedInts,
-                       std::vector<int>{1, 2, 3});
-
-  protos::TestEvent::TestPayload result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_THAT(result.repeated_ints(), ::testing::ElementsAre(1, 2, 3));
-}
-
-TEST_F(TracedProtoTest, SingleString) {
-  protozero::HeapBuffered<TestPayload> event;
-  WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kSingleString,
-                       "foo");
-
-  protos::TestEvent::TestPayload result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_TRUE(result.has_single_string());
-  EXPECT_EQ(result.single_string(), "foo");
-}
-
-TEST_F(TracedProtoTest, RepeatedString) {
-  protozero::HeapBuffered<TestPayload> event;
-  WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kStr,
-                       std::vector<std::string>{"foo", "bar"});
-
-  protos::TestEvent::TestPayload result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_THAT(result.str(), ::testing::ElementsAre("foo", "bar"));
-}
-
-namespace {
-
-struct Foo {
-  void WriteIntoTrace(TracedProto<TestPayload> message) const {
-    message->set_single_int(42);
-  }
-};
-
-}  // namespace
-
-TEST_F(TracedProtoTest, SingleNestedMessage) {
-  protozero::HeapBuffered<protos::pbzero::TestEvent> event;
-  WriteIntoTracedProto(context().Wrap(event.get()),
-                       protos::pbzero::TestEvent::kPayload, Foo());
-
-  protos::TestEvent result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_EQ(result.payload().single_int(), 42);
-}
-
-TEST_F(TracedProtoTest, RepeatedNestedMessage) {
-  protozero::HeapBuffered<TestPayload> event;
-  WriteIntoTracedProto(context().Wrap(event.get()), TestPayload::kNested,
-                       std::vector<Foo>{Foo(), Foo()});
-
-  protos::TestEvent::TestPayload result;
-  result.ParseFromString(event.SerializeAsString());
-  EXPECT_EQ(result.nested_size(), 2);
-  EXPECT_EQ(result.nested(0).single_int(), 42);
-  EXPECT_EQ(result.nested(1).single_int(), 42);
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/traced_value.cc b/src/tracing/traced_value.cc
deleted file mode 100644
index 9ac3fd2..0000000
--- a/src/tracing/traced_value.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/traced_value.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/tracing/debug_annotation.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-
-namespace perfetto {
-
-namespace internal {
-
-TracedValue CreateTracedValueFromProto(
-    protos::pbzero::DebugAnnotation* context) {
-  return TracedValue::CreateFromProto(context);
-}
-
-}  // namespace internal
-
-// static
-TracedValue TracedValue::CreateFromProto(
-    protos::pbzero::DebugAnnotation* context) {
-  return TracedValue(context, nullptr);
-}
-
-void TracedValue::WriteInt64(int64_t value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_int_value(value);
-}
-
-void TracedValue::WriteUInt64(uint64_t value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_uint_value(value);
-}
-
-void TracedValue::WriteDouble(double value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_double_value(value);
-}
-
-void TracedValue::WriteBoolean(bool value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_bool_value(value);
-}
-
-void TracedValue::WriteString(const char* value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_string_value(value);
-}
-
-void TracedValue::WriteString(const char* value, size_t len) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_string_value(value, len);
-}
-
-void TracedValue::WriteString(const std::string& value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_string_value(value);
-}
-
-void TracedValue::WritePointer(const void* value) && {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  context_->set_pointer_value(reinterpret_cast<uint64_t>(value));
-}
-
-TracedDictionary TracedValue::WriteDictionary() && {
-  // Note: this passes |checked_scope_.is_active_| bit to the parent to be
-  // picked up later by the new TracedDictionary.
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  checked_scope_.Reset();
-
-  PERFETTO_DCHECK(!context_->is_finalized());
-  return TracedDictionary(context_, checked_scope_.parent_scope());
-}
-
-TracedArray TracedValue::WriteArray() && {
-  // Note: this passes |checked_scope_.is_active_| bit to the parent to be
-  // picked up later by the new TracedDictionary.
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  checked_scope_.Reset();
-
-  PERFETTO_DCHECK(!context_->is_finalized());
-  return TracedArray(context_, checked_scope_.parent_scope());
-}
-
-TracedValue TracedArray::AppendItem() {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return TracedValue(context_->add_array_values(), &checked_scope_);
-}
-
-TracedDictionary TracedArray::AppendDictionary() {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AppendItem().WriteDictionary();
-}
-
-TracedArray TracedArray::AppendArray() {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AppendItem().WriteArray();
-}
-
-TracedValue TracedDictionary::AddItem(StaticString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  protos::pbzero::DebugAnnotation* item = context_->add_dict_entries();
-  item->set_name(key.value);
-  return TracedValue(item, &checked_scope_);
-}
-
-TracedValue TracedDictionary::AddItem(DynamicString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  protos::pbzero::DebugAnnotation* item = context_->add_dict_entries();
-  item->set_name(key.value);
-  return TracedValue(item, &checked_scope_);
-}
-
-TracedDictionary TracedDictionary::AddDictionary(StaticString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AddItem(key).WriteDictionary();
-}
-
-TracedDictionary TracedDictionary::AddDictionary(DynamicString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AddItem(key).WriteDictionary();
-}
-
-TracedArray TracedDictionary::AddArray(StaticString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AddItem(key).WriteArray();
-}
-
-TracedArray TracedDictionary::AddArray(DynamicString key) {
-  PERFETTO_DCHECK(checked_scope_.is_active());
-  return AddItem(key).WriteArray();
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/traced_value_unittest.cc b/src/tracing/traced_value_unittest.cc
deleted file mode 100644
index 66c86db..0000000
--- a/src/tracing/traced_value_unittest.cc
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/traced_value.h"
-
-#include <array>
-#include <deque>
-#include <forward_list>
-#include <map>
-#include <queue>
-#include <set>
-#include <sstream>
-#include <stack>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "perfetto/base/template_util.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/test/traced_value_test_support.h"
-#include "perfetto/tracing/debug_annotation.h"
-#include "perfetto/tracing/track_event.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pb.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-
-// static asserts checking for conversion support for known types.
-
-#define ASSERT_TYPE_SUPPORTED(T)                           \
-  static_assert(check_traced_value_support<T>::value, ""); \
-  static_assert(internal::has_traced_value_support<T>::value, "")
-
-#define ASSERT_TYPE_NOT_SUPPORTED(T) \
-  static_assert(!internal::has_traced_value_support<T>::value, "")
-
-struct NonSupportedType {};
-
-ASSERT_TYPE_SUPPORTED(bool);
-
-ASSERT_TYPE_NOT_SUPPORTED(NonSupportedType);
-
-// Integer types.
-ASSERT_TYPE_SUPPORTED(short int);
-ASSERT_TYPE_SUPPORTED(unsigned short int);
-ASSERT_TYPE_SUPPORTED(int);
-ASSERT_TYPE_SUPPORTED(unsigned int);
-ASSERT_TYPE_SUPPORTED(long int);
-ASSERT_TYPE_SUPPORTED(unsigned long int);
-ASSERT_TYPE_SUPPORTED(long long int);
-ASSERT_TYPE_SUPPORTED(unsigned long long int);
-
-// References and const references types.
-ASSERT_TYPE_SUPPORTED(int&);
-ASSERT_TYPE_SUPPORTED(const int&);
-ASSERT_TYPE_NOT_SUPPORTED(NonSupportedType&);
-ASSERT_TYPE_NOT_SUPPORTED(const NonSupportedType&);
-
-// Character types.
-ASSERT_TYPE_SUPPORTED(signed char);
-ASSERT_TYPE_SUPPORTED(unsigned char);
-ASSERT_TYPE_SUPPORTED(char);
-ASSERT_TYPE_SUPPORTED(wchar_t);
-
-// Float types.
-ASSERT_TYPE_SUPPORTED(float);
-ASSERT_TYPE_SUPPORTED(double);
-ASSERT_TYPE_SUPPORTED(long double);
-
-// Strings.
-ASSERT_TYPE_SUPPORTED(const char*);
-ASSERT_TYPE_SUPPORTED(const char[]);
-ASSERT_TYPE_SUPPORTED(const char[2]);
-ASSERT_TYPE_SUPPORTED(std::string);
-
-// Pointers.
-ASSERT_TYPE_SUPPORTED(int*);
-ASSERT_TYPE_SUPPORTED(const int*);
-ASSERT_TYPE_SUPPORTED(void*);
-ASSERT_TYPE_SUPPORTED(const void*);
-ASSERT_TYPE_SUPPORTED(std::nullptr_t);
-ASSERT_TYPE_NOT_SUPPORTED(NonSupportedType*);
-ASSERT_TYPE_NOT_SUPPORTED(const NonSupportedType*);
-
-// Arrays.
-ASSERT_TYPE_NOT_SUPPORTED(int[]);
-ASSERT_TYPE_NOT_SUPPORTED(const int[]);
-ASSERT_TYPE_NOT_SUPPORTED(NonSupportedType[]);
-ASSERT_TYPE_NOT_SUPPORTED(const NonSupportedType[]);
-ASSERT_TYPE_SUPPORTED(int (&)[3]);
-ASSERT_TYPE_SUPPORTED(const int (&)[3]);
-ASSERT_TYPE_NOT_SUPPORTED(NonSupportedType (&)[3]);
-ASSERT_TYPE_NOT_SUPPORTED(const NonSupportedType (&)[3]);
-
-// STL containers.
-ASSERT_TYPE_SUPPORTED(std::vector<int>);
-ASSERT_TYPE_NOT_SUPPORTED(std::vector<NonSupportedType>);
-
-using array_int_t = std::array<int, 4>;
-ASSERT_TYPE_SUPPORTED(array_int_t);
-ASSERT_TYPE_SUPPORTED(std::deque<int>);
-ASSERT_TYPE_SUPPORTED(std::forward_list<int>);
-ASSERT_TYPE_SUPPORTED(std::list<int>);
-ASSERT_TYPE_NOT_SUPPORTED(std::stack<int>);
-ASSERT_TYPE_NOT_SUPPORTED(std::queue<int>);
-ASSERT_TYPE_NOT_SUPPORTED(std::priority_queue<int>);
-ASSERT_TYPE_SUPPORTED(std::set<int>);
-ASSERT_TYPE_SUPPORTED(std::multiset<int>);
-using map_int_int_t = std::map<int, int>;
-ASSERT_TYPE_NOT_SUPPORTED(map_int_int_t);
-using multimap_int_int_t = std::multimap<int, int>;
-ASSERT_TYPE_NOT_SUPPORTED(multimap_int_int_t);
-ASSERT_TYPE_SUPPORTED(std::unordered_set<int>);
-ASSERT_TYPE_SUPPORTED(std::unordered_multiset<int>);
-using unordered_map_int_int_t = std::unordered_map<int, int>;
-ASSERT_TYPE_NOT_SUPPORTED(unordered_map_int_int_t);
-using unordered_multimap_int_int_t = std::unordered_multimap<int, int>;
-ASSERT_TYPE_NOT_SUPPORTED(unordered_multimap_int_int_t);
-
-// unique_ptr.
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<int>);
-ASSERT_TYPE_NOT_SUPPORTED(std::unique_ptr<NonSupportedType>);
-
-
-TEST(TracedValueTest, FlatDictionary_Explicit) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  {
-    auto dict =
-        internal::CreateTracedValueFromProto(message.get()).WriteDictionary();
-    dict.AddItem("bool").WriteBoolean(true);
-    dict.AddItem("double").WriteDouble(0.0);
-    dict.AddItem("int").WriteInt64(2014);
-    dict.AddItem("string").WriteString("string");
-    dict.AddItem("truncated_string").WriteString("truncated_string", 9);
-    dict.AddItem("ptr").WritePointer(reinterpret_cast<void*>(0x1234));
-  }
-  EXPECT_EQ(
-      "{bool:true,double:0,int:2014,string:string,truncated_string:truncated,"
-      "ptr:0x1234}",
-      internal::DebugAnnotationToString(message.SerializeAsString()));
-}
-
-TEST(TracedValueTest, FlatDictionary_Short) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  {
-    auto dict =
-        internal::CreateTracedValueFromProto(message.get()).WriteDictionary();
-    dict.Add("bool", true);
-    dict.Add("double", 0.0);
-    dict.Add("int", 2014);
-    dict.Add("string", "string");
-    dict.Add("ptr", reinterpret_cast<void*>(0x1234));
-  }
-  EXPECT_EQ("{bool:true,double:0,int:2014,string:string,ptr:0x1234}",
-            internal::DebugAnnotationToString(message.SerializeAsString()));
-}
-
-TEST(TracedValueTest, Hierarchy_Explicit) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  {
-    auto root_dict =
-        internal::CreateTracedValueFromProto(message.get()).WriteDictionary();
-    {
-      auto array = root_dict.AddItem("a1").WriteArray();
-      array.AppendItem().WriteInt64(1);
-      array.AppendItem().WriteBoolean(true);
-      {
-        auto dict = array.AppendItem().WriteDictionary();
-        dict.AddItem("i2").WriteInt64(3);
-      }
-    }
-    root_dict.AddItem("b0").WriteBoolean(true);
-    root_dict.AddItem("d0").WriteDouble(0.0);
-    {
-      auto dict1 = root_dict.AddItem("dict1").WriteDictionary();
-      {
-        auto dict2 = dict1.AddItem("dict2").WriteDictionary();
-        dict2.AddItem("b2").WriteBoolean(false);
-      }
-      dict1.AddItem("i1").WriteInt64(2014);
-      dict1.AddItem("s1").WriteString("foo");
-    }
-    root_dict.AddItem("i0").WriteInt64(2014);
-    root_dict.AddItem("s0").WriteString("foo");
-  }
-
-  EXPECT_EQ(
-      "{"
-      "a1:[1,true,{i2:3}],"
-      "b0:true,"
-      "d0:0,"
-      "dict1:{dict2:{b2:false},i1:2014,s1:foo},"
-      "i0:2014,"
-      "s0:foo}",
-      internal::DebugAnnotationToString(message.SerializeAsString()));
-}
-
-TEST(TracedValueTest, Hierarchy_Short) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  {
-    auto root_dict =
-        internal::CreateTracedValueFromProto(message.get()).WriteDictionary();
-    {
-      auto array = root_dict.AddArray("a1");
-      array.Append(1);
-      array.Append(true);
-      {
-        auto dict = array.AppendDictionary();
-        dict.Add("i2", 3);
-      }
-    }
-    root_dict.Add("b0", true);
-    root_dict.Add("d0", 0.0);
-    {
-      auto dict1 = root_dict.AddDictionary("dict1");
-      {
-        auto dict2 = dict1.AddDictionary("dict2");
-        dict2.Add("b2", false);
-      }
-      dict1.Add("i1", 2014);
-      dict1.Add("s1", "foo");
-    }
-    root_dict.Add("i0", 2014);
-    root_dict.Add("s0", "foo");
-  }
-
-  EXPECT_EQ(
-      "{"
-      "a1:[1,true,{i2:3}],"
-      "b0:true,"
-      "d0:0,"
-      "dict1:{dict2:{b2:false},i1:2014,s1:foo},"
-      "i0:2014,"
-      "s0:foo}",
-      internal::DebugAnnotationToString(message.SerializeAsString()));
-}
-
-namespace {
-
-class HasWriteIntoTracedValueConvertorMember {
- public:
-  void WriteIntoTracedValue(TracedValue context) const {
-    auto dict = std::move(context).WriteDictionary();
-    dict.Add("int", 42);
-    dict.Add("bool", false);
-  }
-};
-
-class HasWriteIntoTraceConvertorMember {
- public:
-  void WriteIntoTrace(TracedValue context) const {
-    auto dict = std::move(context).WriteDictionary();
-    dict.Add("int", 42);
-    dict.Add("bool", false);
-  }
-};
-
-class HasExternalWriteIntoTraceConvertor {};
-class HasExternalWriteIntoTracedValueConvertor {};
-
-class HasAllConversionMethods {
- public:
-  void WriteIntoTracedValue(TracedValue context) const {
-    std::move(context).WriteString("T::WriteIntoTracedValue");
-  }
-
-  void operator()(TracedValue context) const {
-    std::move(context).WriteString("T::()");
-  }
-};
-
-class NoConversions {};
-
-class HasConstWriteMember {
- public:
-  void WriteIntoTracedValue(TracedValue context) const {
-    std::move(context).WriteString("T::WriteIntoTracedValue const");
-  }
-};
-
-class HasNonConstWriteMember {
- public:
-  void WriteIntoTracedValue(TracedValue context) {
-    std::move(context).WriteString("T::WriteIntoTracedValue");
-  }
-};
-
-class HasConstAndNonConstWriteMember {
- public:
-  void WriteIntoTracedValue(TracedValue context) {
-    std::move(context).WriteString("T::WriteIntoTracedValue");
-  }
-
-  void WriteIntoTracedValue(TracedValue context) const {
-    std::move(context).WriteString("T::WriteIntoTracedValue const");
-  }
-};
-
-}  // namespace
-
-template <>
-struct TraceFormatTraits<HasExternalWriteIntoTraceConvertor> {
-  static void WriteIntoTrace(TracedValue context,
-                             const HasExternalWriteIntoTraceConvertor&) {
-    std::move(context).WriteString("TraceFormatTraits::WriteIntoTrace");
-  }
-};
-
-template <>
-struct TraceFormatTraits<HasExternalWriteIntoTracedValueConvertor> {
-  static void WriteIntoTracedValue(
-      TracedValue context,
-      const HasExternalWriteIntoTracedValueConvertor&) {
-    std::move(context).WriteString("TraceFormatTraits::WriteIntoTracedValue");
-  }
-};
-
-template <>
-struct TraceFormatTraits<HasAllConversionMethods> {
-  static void WriteIntoTracedValue(TracedValue context,
-                                   const HasAllConversionMethods&) {
-    std::move(context).WriteString("TraceFormatTraits::WriteIntoTracedValue");
-  }
-};
-
-template <typename T>
-std::string ToStringWithFallback(T&& value, const std::string& fallback) {
-  protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-  WriteIntoTracedValueWithFallback(
-      internal::CreateTracedValueFromProto(message.get()),
-      std::forward<T>(value), fallback);
-  return internal::DebugAnnotationToString(message.SerializeAsString());
-}
-
-ASSERT_TYPE_SUPPORTED(HasWriteIntoTraceConvertorMember);
-ASSERT_TYPE_SUPPORTED(HasWriteIntoTracedValueConvertorMember);
-ASSERT_TYPE_SUPPORTED(HasExternalWriteIntoTraceConvertor);
-ASSERT_TYPE_SUPPORTED(HasExternalWriteIntoTracedValueConvertor);
-ASSERT_TYPE_SUPPORTED(HasAllConversionMethods);
-
-ASSERT_TYPE_SUPPORTED(HasConstWriteMember);
-ASSERT_TYPE_SUPPORTED(HasConstWriteMember&);
-ASSERT_TYPE_SUPPORTED(HasConstWriteMember*);
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<HasConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(std::vector<HasConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(const HasConstWriteMember);
-ASSERT_TYPE_SUPPORTED(const HasConstWriteMember&);
-ASSERT_TYPE_SUPPORTED(const HasConstWriteMember*);
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<const HasConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(const std::vector<HasConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(std::vector<const HasConstWriteMember*>);
-
-ASSERT_TYPE_SUPPORTED(HasNonConstWriteMember);
-ASSERT_TYPE_SUPPORTED(HasNonConstWriteMember&);
-ASSERT_TYPE_SUPPORTED(HasNonConstWriteMember*);
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<HasNonConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(std::vector<HasNonConstWriteMember>);
-ASSERT_TYPE_NOT_SUPPORTED(const HasNonConstWriteMember);
-ASSERT_TYPE_NOT_SUPPORTED(const HasNonConstWriteMember&);
-ASSERT_TYPE_NOT_SUPPORTED(const HasNonConstWriteMember*);
-ASSERT_TYPE_NOT_SUPPORTED(std::unique_ptr<const HasNonConstWriteMember>);
-ASSERT_TYPE_NOT_SUPPORTED(const std::vector<HasNonConstWriteMember>);
-ASSERT_TYPE_NOT_SUPPORTED(std::vector<const HasNonConstWriteMember*>);
-
-ASSERT_TYPE_SUPPORTED(HasConstAndNonConstWriteMember);
-ASSERT_TYPE_SUPPORTED(HasConstAndNonConstWriteMember&);
-ASSERT_TYPE_SUPPORTED(HasConstAndNonConstWriteMember*);
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<HasConstAndNonConstWriteMember>);
-ASSERT_TYPE_SUPPORTED(const HasConstAndNonConstWriteMember);
-ASSERT_TYPE_SUPPORTED(const HasConstAndNonConstWriteMember&);
-ASSERT_TYPE_SUPPORTED(const HasConstAndNonConstWriteMember*);
-ASSERT_TYPE_SUPPORTED(std::unique_ptr<const HasConstAndNonConstWriteMember*>);
-
-TEST(TracedValueTest, UserDefinedConvertors) {
-  HasWriteIntoTraceConvertorMember value1;
-  EXPECT_EQ(TracedValueToString(value1), "{int:42,bool:false}");
-  EXPECT_EQ(TracedValueToString(&value1), "{int:42,bool:false}");
-
-  HasWriteIntoTracedValueConvertorMember value2;
-  EXPECT_EQ(TracedValueToString(value2), "{int:42,bool:false}");
-  EXPECT_EQ(TracedValueToString(&value2), "{int:42,bool:false}");
-
-  HasExternalWriteIntoTracedValueConvertor value3;
-  EXPECT_EQ(TracedValueToString(value3),
-            "TraceFormatTraits::WriteIntoTracedValue");
-  EXPECT_EQ(TracedValueToString(&value3),
-            "TraceFormatTraits::WriteIntoTracedValue");
-
-  HasExternalWriteIntoTraceConvertor value4;
-  EXPECT_EQ(TracedValueToString(value4), "TraceFormatTraits::WriteIntoTrace");
-  EXPECT_EQ(TracedValueToString(&value4), "TraceFormatTraits::WriteIntoTrace");
-
-  HasAllConversionMethods value5;
-  EXPECT_EQ(TracedValueToString(value5), "T::WriteIntoTracedValue");
-  EXPECT_EQ(TracedValueToString(&value5), "T::WriteIntoTracedValue");
-}
-
-TEST(TracedValueTest, WriteAsLambda) {
-  EXPECT_EQ("42", TracedValueToString([&](TracedValue context) {
-              std::move(context).WriteInt64(42);
-            }));
-}
-
-#if PERFETTO_DCHECK_IS_ON()
-// This death test makes sense only when dchecks are enabled.
-TEST(TracedValueTest, FailOnIncorrectUsage) {
-  // A new call to AddItem is not allowed before the previous result is
-  // consumed.
-  EXPECT_DEATH(
-
-      {
-        protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-        auto dict = internal::CreateTracedValueFromProto(message.get())
-                        .WriteDictionary();
-        auto scope1 = dict.AddItem("key1");
-        auto scope2 = dict.AddItem("key2");
-        std::move(scope1).WriteInt64(1);
-        std::move(scope2).WriteInt64(2);
-      },
-      "");
-
-  // A new call to AppendItem is not allowed before the previous result is
-  // consumed.
-  EXPECT_DEATH(
-      {
-        protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-        auto array =
-            internal::CreateTracedValueFromProto(message.get()).WriteArray();
-        auto scope1 = array.AppendItem();
-        auto scope2 = array.AppendItem();
-        std::move(scope1).WriteInt64(1);
-        std::move(scope2).WriteInt64(2);
-      },
-      "");
-
-  // Writing to parent scope is not allowed.
-  EXPECT_DEATH(
-      {
-        protozero::HeapBuffered<protos::pbzero::DebugAnnotation> message;
-        auto outer_dict = internal::CreateTracedValueFromProto(message.get())
-                              .WriteDictionary();
-        {
-          auto inner_dict = outer_dict.AddDictionary("inner");
-          outer_dict.Add("key", "value");
-        }
-      },
-      "");
-}
-#endif  // PERFETTO_DCHECK_IS_ON()
-
-TEST(TracedValueTest, PrimitiveTypesSupport) {
-  EXPECT_EQ("0x0", TracedValueToString(nullptr));
-  EXPECT_EQ("0x1", TracedValueToString(reinterpret_cast<void*>(1)));
-
-  const int int_value = 1;
-  EXPECT_EQ("1", TracedValueToString(int_value));
-  EXPECT_EQ("1", TracedValueToString(&int_value));
-
-  EXPECT_EQ("1.5", TracedValueToString(1.5));
-  EXPECT_EQ("true", TracedValueToString(true));
-  EXPECT_EQ("foo", TracedValueToString("foo"));
-  EXPECT_EQ("bar", TracedValueToString(std::string("bar")));
-}
-
-TEST(TracedValueTest, UniquePtrSupport) {
-  std::unique_ptr<int> value1;
-  EXPECT_EQ("0x0", TracedValueToString(value1));
-
-  std::unique_ptr<int> value2(new int(4));
-  EXPECT_EQ("4", TracedValueToString(value2));
-}
-
-namespace {
-
-enum OldStyleEnum { kFoo, kBar };
-
-enum class NewStyleEnum { kValue1, kValue2 };
-
-enum class EnumWithPrettyPrint { kValue1, kValue2 };
-
-}  // namespace
-
-template <>
-struct TraceFormatTraits<EnumWithPrettyPrint> {
-  static void WriteIntoTracedValue(TracedValue context,
-                                   EnumWithPrettyPrint value) {
-    switch (value) {
-      case EnumWithPrettyPrint::kValue1:
-        std::move(context).WriteString("value1");
-        return;
-      case EnumWithPrettyPrint::kValue2:
-        std::move(context).WriteString("value2");
-        return;
-    }
-  }
-};
-
-TEST(TracedValueTest, EnumSupport) {
-  EXPECT_EQ(TracedValueToString(kFoo), "0");
-  EXPECT_EQ(TracedValueToString(NewStyleEnum::kValue2), "1");
-  EXPECT_EQ(TracedValueToString(EnumWithPrettyPrint::kValue2), "value2");
-}
-
-TEST(TracedValueTest, ContainerSupport) {
-  std::vector<std::list<int>> value1{{1, 2}, {3, 4}};
-  EXPECT_EQ("[[1,2],[3,4]]", TracedValueToString(value1));
-}
-
-TEST(TracedValueTest, WriteWithFallback) {
-  EXPECT_EQ("1", ToStringWithFallback(1, "fallback"));
-  EXPECT_EQ("true", ToStringWithFallback(true, "fallback"));
-  EXPECT_EQ("fallback", ToStringWithFallback(NonSupportedType(), "fallback"));
-}
-
-TEST(TracedValueTest, ConstAndNotConstSupport) {
-  {
-    HasConstWriteMember value;
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(value));
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(&value));
-
-    std::vector<HasConstWriteMember> arr(1, value);
-    EXPECT_EQ("[T::WriteIntoTracedValue const]", TracedValueToString(arr));
-  }
-
-  {
-    const HasConstWriteMember value;
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(value));
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(&value));
-
-    const std::vector<HasConstWriteMember> arr(1, value);
-    EXPECT_EQ("[T::WriteIntoTracedValue const]", TracedValueToString(arr));
-  }
-
-  {
-    HasNonConstWriteMember value;
-    EXPECT_EQ("T::WriteIntoTracedValue", TracedValueToString(value));
-    EXPECT_EQ("T::WriteIntoTracedValue", TracedValueToString(&value));
-
-    std::vector<HasNonConstWriteMember> arr(1, value);
-    EXPECT_EQ("[T::WriteIntoTracedValue]", TracedValueToString(arr));
-  }
-
-  {
-    HasConstAndNonConstWriteMember value;
-    EXPECT_EQ("T::WriteIntoTracedValue", TracedValueToString(value));
-    EXPECT_EQ("T::WriteIntoTracedValue", TracedValueToString(&value));
-
-    std::vector<HasConstAndNonConstWriteMember> arr(1, value);
-    EXPECT_EQ("[T::WriteIntoTracedValue]", TracedValueToString(arr));
-  }
-
-  {
-    const HasConstAndNonConstWriteMember value;
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(value));
-    EXPECT_EQ("T::WriteIntoTracedValue const", TracedValueToString(&value));
-
-    const std::vector<HasConstAndNonConstWriteMember> arr(1, value);
-    EXPECT_EQ("[T::WriteIntoTracedValue const]", TracedValueToString(arr));
-  }
-}
-
-// Note: interning of the dictionary keys is not implemented yet, so there is no
-// difference in behaviour for StaticString and DynamicString yet.
-TEST(TracedValueTest, DictionaryKeys) {
-  EXPECT_EQ("{literal:1}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-              dict.Add("literal", 1);
-            }));
-
-  EXPECT_EQ("{static:1}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-              const char* key = "static";
-              dict.Add(StaticString{key}, 1);
-            }));
-
-  EXPECT_EQ("{dynamic:1}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-              std::string key = "dynamic";
-              dict.Add(DynamicString{key.data()}, 1);
-            }));
-
-  EXPECT_EQ("{dynamic:1}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-              std::string key = "dynamic";
-              dict.Add(DynamicString{key.data(), key.length()}, 1);
-            }));
-
-  EXPECT_EQ("{dynamic:1}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-              std::string key = "dynamic";
-              dict.Add(DynamicString{key}, 1);
-            }));
-}
-
-TEST(TracedValueTest, EmptyDict) {
-  EXPECT_EQ("{}", TracedValueToString([&](TracedValue context) {
-              auto dict = std::move(context).WriteDictionary();
-            }));
-}
-
-TEST(TracedValueTest, EmptyArray) {
-  // For now we do not distinguish between empty arrays and empty dicts on proto
-  // level as trace processor ignores them anyway.
-  EXPECT_EQ("{}", TracedValueToString([&](TracedValue context) {
-              auto array = std::move(context).WriteArray();
-            }));
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/tracing.cc b/src/tracing/tracing.cc
index 019341e..c0149d9 100644
--- a/src/tracing/tracing.cc
+++ b/src/tracing/tracing.cc
@@ -15,77 +15,42 @@
  */
 
 #include "perfetto/tracing/tracing.h"
-
-#include <atomic>
-#include <condition_variable>
-#include <mutex>
-
-#include "perfetto/ext/base/waitable_event.h"
 #include "perfetto/tracing/internal/track_event_internal.h"
 #include "src/tracing/internal/tracing_muxer_impl.h"
 
+#include <condition_variable>
+#include <mutex>
+
 namespace perfetto {
-namespace {
-bool g_was_initialized = false;
-}
 
 // static
 void Tracing::InitializeInternal(const TracingInitArgs& args) {
+  static bool was_initialized = false;
   static TracingInitArgs init_args;
-  if (g_was_initialized) {
-    if (!(init_args == args)) {
-      PERFETTO_ELOG(
-          "Tracing::Initialize() called more than once with different args. "
-          "This is not supported, only the first call will have effect.");
-      PERFETTO_DCHECK(false);
-    }
+  if (was_initialized) {
+    // Should not be reinitialized with different args.
+    PERFETTO_DCHECK(init_args == args);
     return;
   }
 
   // Make sure the headers and implementation files agree on the build config.
   PERFETTO_CHECK(args.dcheck_is_on_ == PERFETTO_DCHECK_IS_ON());
-  if (args.log_message_callback) {
-    SetLogMessageCallback(args.log_message_callback);
-  }
   internal::TracingMuxerImpl::InitializeInstance(args);
   internal::TrackRegistry::InitializeInstance();
-  g_was_initialized = true;
+  was_initialized = true;
   init_args = args;
 }
 
-// static
-bool Tracing::IsInitialized() {
-  return g_was_initialized;
-}
-
 //  static
 std::unique_ptr<TracingSession> Tracing::NewTrace(BackendType backend) {
   return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
       ->CreateTracingSession(backend);
 }
 
-// Can be called from any thread.
-bool TracingSession::FlushBlocking(uint32_t timeout_ms) {
-  std::atomic<bool> flush_result;
-  base::WaitableEvent flush_ack;
-
-  // The non blocking Flush() can be called on any thread. It does the PostTask
-  // internally.
-  Flush(
-      [&flush_ack, &flush_result](bool res) {
-        flush_result = res;
-        flush_ack.Notify();
-      },
-      timeout_ms);
-  flush_ack.Wait();
-  return flush_result;
-}
-
 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) {
@@ -103,48 +68,4 @@
   return raw_trace;
 }
 
-TracingSession::GetTraceStatsCallbackArgs
-TracingSession::GetTraceStatsBlocking() {
-  std::mutex mutex;
-  std::condition_variable cv;
-  GetTraceStatsCallbackArgs result;
-  bool stats_read = false;
-
-  GetTraceStats(
-      [&mutex, &result, &stats_read, &cv](GetTraceStatsCallbackArgs args) {
-        result = std::move(args);
-        std::unique_lock<std::mutex> lock(mutex);
-        stats_read = true;
-        cv.notify_one();
-      });
-
-  {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [&stats_read] { return stats_read; });
-  }
-  return result;
-}
-
-TracingSession::QueryServiceStateCallbackArgs
-TracingSession::QueryServiceStateBlocking() {
-  std::mutex mutex;
-  std::condition_variable cv;
-  QueryServiceStateCallbackArgs result;
-  bool status_read = false;
-
-  QueryServiceState(
-      [&mutex, &result, &status_read, &cv](QueryServiceStateCallbackArgs args) {
-        result = std::move(args);
-        std::unique_lock<std::mutex> lock(mutex);
-        status_read = true;
-        cv.notify_one();
-      });
-
-  {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [&status_read] { return status_read; });
-  }
-  return result;
-}
-
 }  // namespace perfetto
diff --git a/src/tracing/tracing_policy.cc b/src/tracing/tracing_policy.cc
deleted file mode 100644
index 15df1a0..0000000
--- a/src/tracing/tracing_policy.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_policy.h"
-
-namespace perfetto {
-
-TracingPolicy::~TracingPolicy() = default;
-
-}  // namespace perfetto
diff --git a/src/tracing/track.cc b/src/tracing/track.cc
index c1e7e01..56525f7 100644
--- a/src/tracing/track.cc
+++ b/src/tracing/track.cc
@@ -16,15 +16,8 @@
 
 #include "perfetto/tracing/track.h"
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/thread_utils.h"
 #include "perfetto/ext/base/uuid.h"
 #include "perfetto/tracing/internal/track_event_data_source.h"
-#include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
 #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
@@ -52,22 +45,7 @@
   auto desc = Track::Serialize();
   auto pd = desc.mutable_process();
   pd->set_pid(static_cast<int32_t>(pid));
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  std::string cmdline;
-  if (base::ReadFile("/proc/self/cmdline", &cmdline)) {
-    // Since cmdline is a zero-terminated list of arguments, this ends up
-    // writing just the first element, i.e., the process name, into the process
-    // name field.
-    pd->set_process_name(cmdline.c_str());
-    base::StringSplitter splitter(std::move(cmdline), '\0');
-    while (splitter.Next()) {
-      pd->add_cmdline(
-          std::string(splitter.cur_token(), splitter.cur_token_size()));
-    }
-  }
-  // TODO(skyostil): Record command line on Windows and Mac.
-#endif
+  // TODO(skyostil): Record command line.
   return desc;
 }
 
@@ -81,9 +59,7 @@
   auto td = desc.mutable_thread();
   td->set_pid(static_cast<int32_t>(pid));
   td->set_tid(static_cast<int32_t>(tid));
-  std::string thread_name;
-  if (base::GetThreadName(thread_name))
-    td->set_thread_name(thread_name);
+  // TODO(skyostil): Record thread name.
   return desc;
 }
 
@@ -92,58 +68,7 @@
   desc->AppendRawProtoBytes(bytes.data(), bytes.size());
 }
 
-protos::gen::TrackDescriptor CounterTrack::Serialize() const {
-  auto desc = Track::Serialize();
-  desc.set_name(name_);
-  auto* counter = desc.mutable_counter();
-  if (category_)
-    counter->add_categories(category_);
-  if (unit_ != perfetto::protos::pbzero::CounterDescriptor::UNIT_UNSPECIFIED)
-    counter->set_unit(static_cast<protos::gen::CounterDescriptor_Unit>(unit_));
-  if (unit_name_)
-    counter->set_unit_name(unit_name_);
-  if (unit_multiplier_ != 1)
-    counter->set_unit_multiplier(unit_multiplier_);
-  if (is_incremental_)
-    counter->set_is_incremental(is_incremental_);
-  return desc;
-}
-
-void CounterTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
-  auto bytes = Serialize().SerializeAsString();
-  desc->AppendRawProtoBytes(bytes.data(), bytes.size());
-}
-
 namespace internal {
-namespace {
-
-uint64_t GetProcessStartTime() {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  std::string stat;
-  if (!base::ReadFile("/proc/self/stat", &stat))
-    return 0u;
-  // The stat file is a single line split into space-separated fields as "pid
-  // (comm) state ppid ...". However because the command name can contain any
-  // characters (including parentheses and spaces), we need to skip past it
-  // before parsing the rest of the fields. To do that, we look for the last
-  // instance of ") " (parentheses followed by space) and parse forward from
-  // that point.
-  size_t comm_end = stat.rfind(") ");
-  if (comm_end == std::string::npos)
-    return 0u;
-  stat = stat.substr(comm_end + strlen(") "));
-  base::StringSplitter splitter(stat, ' ');
-  for (size_t skip = 0; skip < 20; skip++) {
-    if (!splitter.Next())
-      return 0u;
-  }
-  return base::CStringToUInt64(splitter.cur_token()).value_or(0u);
-#else
-  return 0;
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-}
-
-}  // namespace
 
 // static
 TrackRegistry* TrackRegistry::instance_;
@@ -158,21 +83,7 @@
   if (instance_)
     return;
   instance_ = new TrackRegistry();
-
-  // Use the process start time + pid as the unique identifier for this process.
-  // This ensures that if there are two independent copies of the Perfetto SDK
-  // in the same process (e.g., one in the app and another in a system
-  // framework), events emitted by each will be consistently interleaved on
-  // common thread and process tracks.
-  if (uint64_t start_time = GetProcessStartTime()) {
-    base::Hash hash;
-    hash.Update(start_time);
-    hash.Update(base::GetProcessId());
-    Track::process_uuid = hash.digest();
-  } else {
-    // Fall back to a randomly generated identifier.
-    Track::process_uuid = static_cast<uint64_t>(base::Uuidv4().lsb());
-  }
+  Track::process_uuid = static_cast<uint64_t>(base::Uuidv4().lsb());
 }
 
 void TrackRegistry::UpdateTrack(Track track,
diff --git a/src/tracing/track_event_category_registry.cc b/src/tracing/track_event_category_registry.cc
index f69479e..6d9a649 100644
--- a/src/tracing/track_event_category_registry.cc
+++ b/src/tracing/track_event_category_registry.cc
@@ -41,6 +41,11 @@
   return perfetto::DynamicCategory{};
 }
 
+const Category* 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 {
diff --git a/src/tracing/track_event_legacy.cc b/src/tracing/track_event_legacy.cc
index 744416f..9a687c6 100644
--- a/src/tracing/track_event_legacy.cc
+++ b/src/tracing/track_event_legacy.cc
@@ -22,11 +22,12 @@
 namespace legacy {
 
 template <>
-ThreadTrack ConvertThreadId(const PerfettoLegacyCurrentThreadId&) {
-  // Because of the short-circuit in PERFETTO_INTERNAL_LEGACY_EVENT, we should
-  // never get here.
-  PERFETTO_DCHECK(false);
-  return ThreadTrack::Current();
+bool ConvertThreadId(const PerfettoLegacyCurrentThreadId&,
+                     uint64_t*,
+                     int32_t*,
+                     int32_t*) {
+  // No need to override anything for events on to the current thread.
+  return false;
 }
 
 }  // namespace legacy
diff --git a/src/tracing/track_event_state_tracker.cc b/src/tracing/track_event_state_tracker.cc
deleted file mode 100644
index 7cb1b09..0000000
--- a/src/tracing/track_event_state_tracker.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "perfetto/tracing/track_event_state_tracker.h"
-
-#include "perfetto/ext/base/hash.h"
-
-#include "protos/perfetto/common/interceptor_descriptor.gen.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.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 {
-
-TrackEventStateTracker::~TrackEventStateTracker() = default;
-TrackEventStateTracker::Delegate::~Delegate() = default;
-
-// static
-void TrackEventStateTracker::ProcessTracePacket(
-    Delegate& delegate,
-    SequenceState& sequence_state,
-    const protos::pbzero::TracePacket_Decoder& packet) {
-  UpdateIncrementalState(delegate, sequence_state, packet);
-
-  if (!packet.has_track_event())
-    return;
-  perfetto::protos::pbzero::TrackEvent::Decoder track_event(
-      packet.track_event());
-
-  // TODO(skyostil): Support incremental timestamps.
-  uint64_t timestamp = packet.timestamp();
-
-  Track* track = &sequence_state.track;
-  if (track_event.has_track_uuid()) {
-    auto* session_state = delegate.GetSessionState();
-    if (!session_state)
-      return;  // Tracing must have ended.
-    track = &session_state->tracks[track_event.track_uuid()];
-  }
-
-  // We only log the first category of each event.
-  protozero::ConstChars category{};
-  uint64_t category_iid = 0;
-  if (auto iid_it = track_event.category_iids()) {
-    category_iid = *iid_it;
-    category.data = sequence_state.event_categories[category_iid].data();
-    category.size = sequence_state.event_categories[category_iid].size();
-  } else if (auto cat_it = track_event.categories()) {
-    category.data = reinterpret_cast<const char*>(cat_it->data());
-    category.size = cat_it->size();
-  }
-
-  protozero::ConstChars name{};
-  uint64_t name_iid = track_event.name_iid();
-  uint64_t name_hash = 0;
-  uint64_t duration = 0;
-  if (name_iid) {
-    name.data = sequence_state.event_names[name_iid].data();
-    name.size = sequence_state.event_names[name_iid].size();
-  } else if (track_event.has_name()) {
-    name.data = track_event.name().data;
-    name.size = track_event.name().size;
-  }
-
-  if (name.data) {
-    base::Hash hash;
-    hash.Update(name.data, name.size);
-    name_hash = hash.digest();
-  }
-
-  size_t depth = track->stack.size();
-  switch (track_event.type()) {
-    case protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN: {
-      StackFrame frame;
-      frame.timestamp = timestamp;
-      frame.name_hash = name_hash;
-      if (track_event.has_track_uuid()) {
-        frame.name = name.ToStdString();
-        frame.category = category.ToStdString();
-      } else {
-        frame.name_iid = name_iid;
-        frame.category_iid = category_iid;
-      }
-      track->stack.push_back(std::move(frame));
-      break;
-    }
-    case protos::pbzero::TrackEvent::TYPE_SLICE_END:
-      if (!track->stack.empty()) {
-        const auto& prev_frame = track->stack.back();
-        if (prev_frame.name_iid) {
-          name.data = sequence_state.event_names[prev_frame.name_iid].data();
-          name.size = sequence_state.event_names[prev_frame.name_iid].size();
-        } else {
-          name.data = prev_frame.name.data();
-          name.size = prev_frame.name.size();
-        }
-        name_hash = prev_frame.name_hash;
-        if (prev_frame.category_iid) {
-          category.data =
-              sequence_state.event_categories[prev_frame.category_iid].data();
-          category.size =
-              sequence_state.event_categories[prev_frame.category_iid].size();
-        } else {
-          category.data = prev_frame.category.data();
-          category.size = prev_frame.category.size();
-        }
-        duration = timestamp - prev_frame.timestamp;
-        depth--;
-      }
-      break;
-    case protos::pbzero::TrackEvent::TYPE_INSTANT:
-      break;
-    case protos::pbzero::TrackEvent::TYPE_COUNTER:
-    case protos::pbzero::TrackEvent::TYPE_UNSPECIFIED:
-      // TODO(skyostil): Support counters.
-      return;
-  }
-
-  ParsedTrackEvent parsed_event{track_event};
-  parsed_event.timestamp_ns = timestamp;
-  parsed_event.duration_ns = duration;
-  parsed_event.stack_depth = depth;
-  parsed_event.category = category;
-  parsed_event.name = name;
-  parsed_event.name_hash = name_hash;
-  delegate.OnTrackEvent(*track, parsed_event);
-
-  if (track_event.type() == protos::pbzero::TrackEvent::TYPE_SLICE_END &&
-      !track->stack.empty()) {
-    track->stack.pop_back();
-  }
-}
-
-// static
-void TrackEventStateTracker::UpdateIncrementalState(
-    Delegate& delegate,
-    SequenceState& sequence_state,
-    const protos::pbzero::TracePacket_Decoder& packet) {
-#if PERFETTO_DCHECK_IS_ON()
-  if (!sequence_state.sequence_id) {
-    sequence_state.sequence_id = packet.trusted_packet_sequence_id();
-  } else {
-    PERFETTO_DCHECK(sequence_state.sequence_id ==
-                    packet.trusted_packet_sequence_id());
-  }
-#endif
-
-  if (packet.sequence_flags() &
-      perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
-    // Convert any existing event names and categories on the stack to
-    // non-interned strings so we can look up their names even after the
-    // incremental state is gone.
-    for (auto& frame : sequence_state.track.stack) {
-      if (frame.name_iid) {
-        frame.name = sequence_state.event_names[frame.name_iid];
-        frame.name_iid = 0u;
-      }
-      if (frame.category_iid) {
-        frame.category = sequence_state.event_categories[frame.category_iid];
-        frame.category_iid = 0u;
-      }
-    }
-    sequence_state.event_names.clear();
-    sequence_state.event_categories.clear();
-    sequence_state.debug_annotation_names.clear();
-    sequence_state.track.uuid = 0u;
-    sequence_state.track.index = 0u;
-  }
-  if (packet.has_interned_data()) {
-    perfetto::protos::pbzero::InternedData::Decoder interned_data(
-        packet.interned_data());
-    for (auto it = interned_data.event_names(); it; it++) {
-      perfetto::protos::pbzero::EventName::Decoder entry(*it);
-      sequence_state.event_names[entry.iid()] = entry.name().ToStdString();
-    }
-    for (auto it = interned_data.event_categories(); it; it++) {
-      perfetto::protos::pbzero::EventCategory::Decoder entry(*it);
-      sequence_state.event_categories[entry.iid()] = entry.name().ToStdString();
-    }
-    for (auto it = interned_data.debug_annotation_names(); it; it++) {
-      perfetto::protos::pbzero::DebugAnnotationName::Decoder entry(*it);
-      sequence_state.debug_annotation_names[entry.iid()] =
-          entry.name().ToStdString();
-    }
-  }
-  if (packet.has_trace_packet_defaults()) {
-    perfetto::protos::pbzero::TracePacketDefaults::Decoder defaults(
-        packet.trace_packet_defaults());
-    if (defaults.has_track_event_defaults()) {
-      perfetto::protos::pbzero::TrackEventDefaults::Decoder
-          track_event_defaults(defaults.track_event_defaults());
-      sequence_state.track.uuid = track_event_defaults.track_uuid();
-    }
-  }
-  if (packet.has_track_descriptor()) {
-    perfetto::protos::pbzero::TrackDescriptor::Decoder track_descriptor(
-        packet.track_descriptor());
-    auto* session_state = delegate.GetSessionState();
-    auto& track = session_state->tracks[track_descriptor.uuid()];
-    if (!track.index)
-      track.index = static_cast<uint32_t>(session_state->tracks.size() + 1);
-    track.uuid = track_descriptor.uuid();
-
-    track.name = track_descriptor.name().ToStdString();
-    track.pid = 0;
-    track.tid = 0;
-    if (track_descriptor.has_process()) {
-      perfetto::protos::pbzero::ProcessDescriptor::Decoder process(
-          track_descriptor.process());
-      track.pid = process.pid();
-      if (track.name.empty())
-        track.name = process.process_name().ToStdString();
-    } else if (track_descriptor.has_thread()) {
-      perfetto::protos::pbzero::ThreadDescriptor::Decoder thread(
-          track_descriptor.thread());
-      track.pid = thread.pid();
-      track.tid = thread.tid();
-      if (track.name.empty())
-        track.name = thread.thread_name().ToStdString();
-    }
-    delegate.OnTrackUpdated(track);
-
-    // Mirror properties to the default track of the sequence. Note that
-    // this does not catch updates to the default track written through other
-    // sequences.
-    if (track.uuid == sequence_state.track.uuid) {
-      sequence_state.track.index = track.index;
-      sequence_state.track.name = track.name;
-      sequence_state.track.pid = track.pid;
-      sequence_state.track.tid = track.tid;
-      sequence_state.track.user_data = track.user_data;
-    }
-  }
-}
-
-TrackEventStateTracker::ParsedTrackEvent::ParsedTrackEvent(
-    const perfetto::protos::pbzero::TrackEvent::Decoder& track_event_)
-    : track_event(track_event_) {}
-
-}  // namespace perfetto
diff --git a/src/tracing/virtual_destructors.cc b/src/tracing/virtual_destructors.cc
index d473551..d548c8e 100644
--- a/src/tracing/virtual_destructors.cc
+++ b/src/tracing/virtual_destructors.cc
@@ -26,10 +26,7 @@
 namespace perfetto {
 namespace internal {
 
-TracingTLS::~TracingTLS() {
-  // Avoid entering trace points while the thread is being torn down.
-  is_in_trace_point = true;
-}
+TracingTLS::~TracingTLS() = default;
 
 }  // namespace internal
 
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 64e683a..c7b7c15 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -16,69 +16,59 @@
 import("../gn/fuzzer.gni")
 import("../gn/perfetto.gni")
 
-if (!build_with_chromium && enable_perfetto_integration_tests) {
-  source_set("end_to_end_integrationtests") {
-    testonly = true
-    deps = [
-      ":test_helper",
-      "../gn:default_deps",
-      "../gn:gtest_and_gmock",
-      "../include/perfetto/ext/ipc",
-      "../include/perfetto/ext/traced",
-      "../include/perfetto/protozero",
-      "../protos/perfetto/config:cpp",
-      "../protos/perfetto/config:zero",
-      "../protos/perfetto/config/power:zero",
-      "../protos/perfetto/config/sys_stats:cpp",
-      "../protos/perfetto/trace:cpp",
-      "../protos/perfetto/trace:zero",
-      "../protos/perfetto/trace/ftrace:cpp",
-      "../protos/perfetto/trace/perfetto:cpp",
-      "../protos/perfetto/trace/power:cpp",
-      "../protos/perfetto/trace/sys_stats:cpp",
-      "../src/base:base",
-      "../src/base:test_support",
-    ]
-    if (enable_perfetto_traced_probes) {
-      deps += [
-        "../src/traced/probes/ftrace",
-        "../src/traced/probes/ftrace:ftrace_procfs",
-      ]
-    }
+source_set("end_to_end_integrationtests") {
+  testonly = true
+  deps = [
+    ":test_helper",
+    "../gn:default_deps",
+    "../gn:gtest_and_gmock",
+    "../include/perfetto/ext/ipc",
+    "../include/perfetto/ext/traced",
+    "../include/perfetto/protozero",
+    "../protos/perfetto/config:cpp",
+    "../protos/perfetto/config:zero",
+    "../protos/perfetto/config/power:zero",
+    "../protos/perfetto/trace:cpp",
+    "../protos/perfetto/trace:zero",
+    "../protos/perfetto/trace/ftrace:cpp",
+    "../protos/perfetto/trace/power:cpp",
+    "../src/base:base",
+    "../src/base:test_support",
+    "../src/traced/probes/ftrace",
+  ]
 
-    # These binaries are requires by the cmdline tests, which invoke perfetto
-    # and trigger_perfetto via Subprocess.
-    data_deps = [
-      "../src/perfetto_cmd:perfetto",
-      "../src/perfetto_cmd:trigger_perfetto",
-    ]
+  # These binaries are requires by the cmdline tests, which invoke perfetto
+  # and trigger_perfetto via Subprocess.
+  data_deps = [
+    "../src/perfetto_cmd:perfetto",
+    "../src/perfetto_cmd:trigger_perfetto",
+  ]
 
-    sources = [ "end_to_end_integrationtest.cc" ]
-    if (start_daemons_for_testing) {
-      cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
+  sources = [ "end_to_end_integrationtest.cc" ]
+  if (start_daemons_for_testing) {
+    cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
 
-      # In CTS mode we use /syste/bin/perfetto for the cmdline tests and the
-      # perfetto_cmd is not required. Outside of CTS mode, instead, we need to
-      # build the cmdline code as part of the test executable.
-      deps += [
-        "../src/perfetto_cmd",
-        "../src/perfetto_cmd:trigger_perfetto_cmd",
-      ]
-    }
-  }
-
-  executable("client_api_example") {
-    sources = [ "client_api_example.cc" ]
-    deps = [
-      "..:libperfetto_client_experimental",
-      "../gn:default_deps",
-      "../include/perfetto/tracing",
-      "../protos/perfetto/config/gpu:zero",
-      "../protos/perfetto/trace:zero",
-      "../protos/perfetto/trace/gpu:zero",
+    # In CTS mode we use /syste/bin/perfetto for the cmdline tests and the
+    # perfetto_cmd is not required. Outside of CTS mode, instead, we need to
+    # build the cmdline code as part of the test executable.
+    deps += [
+      "../src/perfetto_cmd",
+      "../src/perfetto_cmd:trigger_perfetto_cmd",
     ]
   }
-}  # if (!build_with_chromium && enable_perfetto_integration_tests)
+}
+
+executable("client_api_example") {
+  sources = [ "client_api_example.cc" ]
+  deps = [
+    "..:libperfetto_client_experimental",
+    "../gn:default_deps",
+    "../include/perfetto/tracing",
+    "../protos/perfetto/config/gpu:zero",
+    "../protos/perfetto/trace:zero",
+    "../protos/perfetto/trace/gpu:zero",
+  ]
+}
 
 perfetto_fuzzer_test("end_to_end_shared_memory_fuzzer") {
   sources = [ "end_to_end_shared_memory_fuzzer.cc" ]
@@ -106,46 +96,31 @@
   ]
 }
 
-# perfetto_fuzzer_test() targets are no-ops if is_fuzzer = false.
-if (enable_perfetto_benchmarks || is_fuzzer ||
-    enable_perfetto_integration_tests) {
-  source_set("test_helper") {
-    testonly = true
-    public_deps = [
-      "../protos/perfetto/trace:cpp",
-      "../src/tracing/ipc/consumer",
-      "../src/tracing/ipc/producer",
-      "../src/tracing/ipc/service",
-    ]
-    deps = [
-      "../gn:default_deps",
-      "../protos/perfetto/config:cpp",
-      "../protos/perfetto/trace:zero",
-      "../src/base:test_support",
-      "../src/ipc:perfetto_ipc",
-      "../src/tracing/ipc:common",
-    ]
-    sources = [
-      "fake_producer.cc",
-      "fake_producer.h",
-      "test_helper.cc",
-      "test_helper.h",
-    ]
-    if (is_android) {
-      sources += [
-        "android_test_utils.cc",
-        "android_test_utils.h",
-      ]
-    }
-    if (start_daemons_for_testing) {
-      cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
-    }
-    if (!build_with_chromium && enable_perfetto_traced_probes) {
-      deps += [
-        "../include/perfetto/ext/traced",
-        "../src/traced/probes:probes_src",
-      ]
-    }
+source_set("test_helper") {
+  testonly = true
+  public_deps = [
+    "../protos/perfetto/trace:cpp",
+    "../src/tracing/ipc/consumer",
+    "../src/tracing/ipc/producer",
+    "../src/tracing/ipc/service",
+  ]
+  deps = [
+    "../gn:default_deps",
+    "../include/perfetto/ext/traced",
+    "../protos/perfetto/config:cpp",
+    "../protos/perfetto/trace:zero",
+    "../src/base:test_support",
+    "../src/traced/probes:probes_src",
+    "../src/tracing/ipc:common",
+  ]
+  sources = [
+    "fake_producer.cc",
+    "fake_producer.h",
+    "test_helper.cc",
+    "test_helper.h",
+  ]
+  if (start_daemons_for_testing) {
+    cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
   }
 }
 
diff --git a/test/android_test_utils.cc b/test/android_test_utils.cc
deleted file mode 100644
index 8c6081a..0000000
--- a/test/android_test_utils.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 "test/android_test_utils.h"
-
-#include <stdlib.h>
-#include <sys/system_properties.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.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);
-  return std::string(buf) == "1";
-}
-
-bool IsUserBuild() {
-  char buf[PROP_VALUE_MAX + 1] = {};
-  int ret = __system_property_get("ro.build.type", buf);
-  PERFETTO_CHECK(ret >= 0);
-  return std::string(buf) == "user";
-}
-
-// 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);
-}
-
-int PidForProcessName(const std::string& name) {
-  std::string cmd = "pgrep -f ^" + name + "$";
-  FILE* fp = popen(cmd.c_str(), "re");
-  if (!fp)
-    return -1;
-
-  std::string out;
-  base::ReadFileStream(fp, &out);
-  pclose(fp);
-
-  char* endptr = nullptr;
-  int pid = static_cast<int>(strtol(out.c_str(), &endptr, 10));
-  if (*endptr != '\0' && *endptr != '\n')
-    return -1;
-  return pid;
-}
-
-void WaitForProcess(const std::string& process,
-                    const std::string& checkpoint_name,
-                    base::TestTaskRunner* task_runner,
-                    uint32_t delay_ms) {
-  bool desired_run_state = true;
-  const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
-  task_runner->PostDelayedTask(
-      [desired_run_state, task_runner, process, checkpoint] {
-        PollRunState(desired_run_state, task_runner, process,
-                     std::move(checkpoint));
-      },
-      delay_ms);
-}
-
-void StartAppActivity(const std::string& app_name,
-                      const std::string& activity_name,
-                      const std::string& checkpoint_name,
-                      base::TestTaskRunner* task_runner,
-                      uint32_t delay_ms) {
-  std::string start_cmd = "am start " + app_name + "/." + activity_name;
-  int status = system(start_cmd.c_str());
-  PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);
-  WaitForProcess(app_name, checkpoint_name, task_runner, 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());
-  PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);
-
-  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(const std::string& app_name) {
-  std::string stop_cmd = "am force-stop " + app_name;
-  system(stop_cmd.c_str());
-}
-
-}  // namespace perfetto
diff --git a/test/android_test_utils.h b/test/android_test_utils.h
deleted file mode 100644
index 30ee947..0000000
--- a/test/android_test_utils.h
+++ /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.
- */
-
-#ifndef TEST_ANDROID_TEST_UTILS_H_
-#define TEST_ANDROID_TEST_UTILS_H_
-
-#include <string>
-
-#include "src/base/test/test_task_runner.h"
-
-namespace perfetto {
-
-bool IsDebuggableBuild();
-bool IsUserBuild();
-
-bool IsAppRunning(const std::string& name);
-
-// returns -1 if the process wasn't found
-int PidForProcessName(const std::string& name);
-
-void WaitForProcess(const std::string& process,
-                    const std::string& checkpoint_name,
-                    base::TestTaskRunner* task_runner,
-                    uint32_t delay_ms = 1);
-
-void StartAppActivity(const std::string& app_name,
-                      const std::string& activity_name,
-                      const std::string& checkpoint_name,
-                      base::TestTaskRunner* task_runner,
-                      uint32_t delay_ms = 1);
-
-void StopApp(const std::string& app_name,
-             const std::string& checkpoint_name,
-             base::TestTaskRunner* task_runner);
-
-void StopApp(const std::string& app_name);
-
-}  // namespace perfetto
-
-#endif  // TEST_ANDROID_TEST_UTILS_H_
diff --git a/test/ci/common.sh b/test/ci/common.sh
index 83e82c3..a798448 100644
--- a/test/ci/common.sh
+++ b/test/ci/common.sh
@@ -18,16 +18,13 @@
 cd $(dirname ${BASH_SOURCE[0]})/../..
 OUT_PATH="out/dist"
 
-export PYTHONUNBUFFERED=1
+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
 
-# Assumes Linux. Windows should use /win/clang instead.
-if [[ -e buildtools/linux64/clang/bin/llvm-symbolizer ]]; then
-  export ASAN_SYMBOLIZER_PATH="$(readlink -f buildtools/linux64/clang/bin/llvm-symbolizer)"
-  export MSAN_SYMBOLIZER_PATH="$(readlink -f buildtools/linux64/clang/bin/llvm-symbolizer)"
-fi
-
 # 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
diff --git a/test/ci/linux_tests.sh b/test/ci/linux_tests.sh
index fd165f2..97df02c 100755
--- a/test/ci/linux_tests.sh
+++ b/test/ci/linux_tests.sh
@@ -25,7 +25,7 @@
 ${OUT_PATH}/perfetto_integrationtests
 ${OUT_PATH}/trace_processor_minimal_smoke_tests
 
-# If this is a split host+target build, use the trace_processor_shell binary
+# 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,
@@ -38,11 +38,10 @@
 mkdir -p /ci/artifacts/perf
 
 tools/diff_test_trace_processor.py \
+  --test-type=all \
   --perf-file=/ci/artifacts/perf/tp-perf-all.json \
   ${TP_SHELL}
 
-tools/run_python_api_tests.py ${TP_SHELL}
-
 # Don't run benchmarks under x86 (running out of address space because of 4GB)
 # limit or debug (too slow and pointless).
 HOST_CPU="$(tools/gn args --short --list=host_cpu ${OUT_PATH} | awk '{print $3}' | sed -e 's/^"//' -e 's/"$//')"
diff --git a/test/ci/ui_tests.sh b/test/ci/ui_tests.sh
index 9a1fa3a..6b59820 100755
--- a/test/ci/ui_tests.sh
+++ b/test/ci/ui_tests.sh
@@ -16,8 +16,10 @@
 INSTALL_BUILD_DEPS_ARGS="--ui"
 source $(dirname ${BASH_SOURCE[0]})/common.sh
 
-tools/node ui/build.js --out ${OUT_PATH}
+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/dist/ /ci/artifacts/ui
+cp -a ${OUT_PATH}/ui /ci/artifacts/
 
-tools/node ui/build.js --out ${OUT_PATH} --no-build --run-tests
+# Run the tests
+${OUT_PATH}/ui_unittests --ci
diff --git a/test/client_api_example.cc b/test/client_api_example.cc
index f8dfcc4..62c495d 100644
--- a/test/client_api_example.cc
+++ b/test/client_api_example.cc
@@ -88,7 +88,6 @@
 
 }  // namespace
 
-PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MyDataSource);
 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MyDataSource);
 
 int main() {
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 4c93db1..fcef973 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -35,16 +35,11 @@
     "client_api.cfg",
     "ftrace.cfg",
     "ftrace_largebuffer.cfg",
-    "ftrace_with_filter.cfg",
-    "ftrace_with_ksyms.cfg",
     "heapprofd.cfg",
     "long_trace.cfg",
-    "mm_events.cfg",
     "scheduling.cfg",
     "summary.cfg",
     "sys_stats.cfg",
-    "thermal.cfg",
-    "traced_perf.cfg",
   ]
 
   outputs = [ "$root_out_dir/{{source_file_part}}.protobuf" ]
@@ -54,14 +49,10 @@
   # 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)
-  protoc_ext = ""
-  if (host_os == "win") {
-    protoc_ext = ".exe"
-  }
 
   args = [
     "encode",
-    "--protoc=$protoc_rel_dir/protoc${protoc_ext}",
+    "--protoc=$protoc_rel_dir/protoc",
     "--input={{source}}",
     "--output={{source_file_part}}.protobuf",
   ]
diff --git a/test/configs/ftrace_with_filter.cfg b/test/configs/ftrace_with_filter.cfg
deleted file mode 100644
index 54c3161..0000000
--- a/test/configs/ftrace_with_filter.cfg
+++ /dev/null
@@ -1,36 +0,0 @@
-buffers {
-  size_kb: 65536
-}
-
-data_sources {
-  config {
-    name: "linux.ftrace"
-    target_buffer: 0
-    ftrace_config {
-      ftrace_events: "sched/sched_process_exec"
-      ftrace_events: "sched/sched_process_exit"
-      ftrace_events: "sched/sched_process_fork"
-      ftrace_events: "sched/sched_process_free"
-      ftrace_events: "sched/sched_process_hang"
-      ftrace_events: "sched/sched_process_wait"
-      ftrace_events: "sched/sched_switch"
-      ftrace_events: "sched/sched_wakeup_new"
-      ftrace_events: "sched/sched_wakeup"
-      ftrace_events: "sched/sched_waking"
-    }
-  }
-}
-
-data_sources {
-  config {
-    name: "linux.process_stats"
-    target_buffer: 0
-  }
-}
-
-trace_filter {
-  # A very minimal bytecode which allows only sched_switch and nothing more.
-  bytecode: "\013\001\000\013\002\101\121\151\321\002\000\011\023\003\031\000\012\002\043\004\000\012\007\000\273\341\337\347\016"
-}
-
-duration_ms: 10000
diff --git a/test/configs/ftrace_with_ksyms.cfg b/test/configs/ftrace_with_ksyms.cfg
deleted file mode 100644
index 3a18cfd..0000000
--- a/test/configs/ftrace_with_ksyms.cfg
+++ /dev/null
@@ -1,36 +0,0 @@
-duration_ms: 10000
-
-buffers {
-  size_kb: 65536
-}
-
-# Keep first so the early KALLSYMS_PARSE is recorded.
-data_sources {
-  config {
-    name: "perfetto.metatrace"
-    target_buffer: 0
-  }
-}
-
-data_sources {
-  config {
-    name: "linux.ftrace"
-    target_buffer: 0
-    ftrace_config {
-      symbolize_ksyms: true
-      ftrace_events: "kmem/rss_stat"
-      ftrace_events: "sched/sched_blocked_reason"
-      ftrace_events: "workqueue/workqueue_activate_work"
-      ftrace_events: "workqueue/workqueue_execute_end"
-      ftrace_events: "workqueue/workqueue_execute_start"
-      ftrace_events: "workqueue/workqueue_queue_work"
-    }
-  }
-}
-
-data_sources {
-  config {
-    name: "linux.process_stats"
-    target_buffer: 0
-  }
-}
diff --git a/test/configs/long_trace.cfg b/test/configs/long_trace.cfg
index 448c537..819c207 100644
--- a/test/configs/long_trace.cfg
+++ b/test/configs/long_trace.cfg
@@ -10,10 +10,6 @@
 # Writes the userspace buffer into the file every 2.5 seconds.
 file_write_period_ms: 2500
 
-# Commits the trace from the shared memory buffer to the central buffer
-# periodically. Otherwise, the --full-sort option will be required for
-# trace_processor_shell and traceconv when importing the trace.
-flush_period_ms: 20000
 
 # The trace buffers needs to be big enough to hold |file_write_period_ms| of
 # trace data. The trace buffer sizing depends on the number of trace categories
diff --git a/test/configs/mm_events.cfg b/test/configs/mm_events.cfg
deleted file mode 100644
index c7cf238..0000000
--- a/test/configs/mm_events.cfg
+++ /dev/null
@@ -1,68 +0,0 @@
-unique_session_name: "perfetto_mm_events_session"
-
-bugreport_score: 100
-
-buffers: {
-  size_kb: 512
-  fill_policy: DISCARD
-}
-
-data_sources: {
-  config {
-    name: "linux.sys_stats"
-    sys_stats_config {
-      vmstat_period_ms: 500
-      vmstat_counters: VMSTAT_NR_FREE_PAGES
-      vmstat_counters: VMSTAT_NR_SLAB_RECLAIMABLE
-      vmstat_counters: VMSTAT_NR_SLAB_UNRECLAIMABLE
-      vmstat_counters: VMSTAT_NR_ACTIVE_FILE
-      vmstat_counters: VMSTAT_NR_INACTIVE_FILE
-      vmstat_counters: VMSTAT_NR_ACTIVE_ANON
-      vmstat_counters: VMSTAT_NR_INACTIVE_ANON
-      vmstat_counters: VMSTAT_WORKINGSET_REFAULT
-      vmstat_counters: VMSTAT_WORKINGSET_ACTIVATE
-      vmstat_counters: VMSTAT_NR_FILE_PAGES
-      vmstat_counters: VMSTAT_PGPGIN
-      vmstat_counters: VMSTAT_PGPGOUT
-      vmstat_counters: VMSTAT_PSWPIN
-      vmstat_counters: VMSTAT_PSWPOUT
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_DMA
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_NORMAL
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_MOVABLE
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_DMA
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_NORMAL
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_MOVABLE
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_DMA
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_NORMAL
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_MOVABLE
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_DMA
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_NORMAL
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_MOVABLE
-      vmstat_counters: VMSTAT_COMPACT_MIGRATE_SCANNED
-      vmstat_counters: VMSTAT_COMPACT_FREE_SCANNED
-    }
-  }
-}
-
-data_sources: {
-  config {
-    name: "linux.ftrace"
-    ftrace_config {
-      ftrace_events: "vmscan/mm_vmscan_kswapd_wake"
-      ftrace_events: "vmscan/mm_vmscan_kswapd_sleep"
-      ftrace_events: "vmscan/mm_vmscan_direct_reclaim_begin"
-      ftrace_events: "vmscan/mm_vmscan_direct_reclaim_end"
-      ftrace_events: "compaction/mm_compaction_begin"
-      ftrace_events: "compaction/mm_compaction_end"
-    }
-  }
-}
-
-trigger_config {
-  trigger_mode: START_TRACING
-  trigger_timeout_ms: 120000
-  triggers {
-    name: "kmem_activity"
-    stop_delay_ms: 10000
-  }
-}
diff --git a/test/configs/scm.cfg b/test/configs/scm.cfg
deleted file mode 100644
index 109e175..0000000
--- a/test/configs/scm.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-buffers {
-  size_kb: 100024
-  fill_policy: RING_BUFFER
-}
-
-data_sources {
-  config {
-    name: "linux.ftrace"
-    target_buffer: 0
-    ftrace_config {
-      ftrace_events: "scm/scm_call_start"
-      ftrace_events: "scm/scm_call_end"
-    }
-  }
-}
-
-duration_ms: 10000
diff --git a/test/configs/thermal.cfg b/test/configs/thermal.cfg
deleted file mode 100644
index 214dfe4..0000000
--- a/test/configs/thermal.cfg
+++ /dev/null
@@ -1,21 +0,0 @@
-buffers: {
-    size_kb: 8960
-    fill_policy: DISCARD
-}
-buffers: {
-    size_kb: 1280
-    fill_policy: DISCARD
-}
-data_sources: {
-    config {
-        name: "linux.ftrace"
-        ftrace_config {
-            ftrace_events: "thermal/thermal_temperature"
-            ftrace_events: "thermal/cdev_update"
-            buffer_size_kb: 2048
-            drain_period_ms: 250
-        }
-    }
-}
-duration_ms: 10000
-
diff --git a/test/cts/Android.bp b/test/cts/Android.bp
index 3958566..1692c56 100644
--- a/test/cts/Android.bp
+++ b/test/cts/Android.bp
@@ -1,12 +1,3 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_perfetto_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
 cc_test {
   name: "CtsPerfettoTestCases",
   srcs: [
@@ -15,6 +6,7 @@
     "heapprofd_java_test_cts.cc",
     "heapprofd_test_cts.cc",
     "traced_perf_test_cts.cc",
+    "utils.cc",
     ":perfetto_protos_perfetto_config_cpp_gen",
   ],
   generated_headers: [
diff --git a/test/cts/AndroidTest.xml b/test/cts/AndroidTest.xml
index 2a9276c..81d39c3 100644
--- a/test/cts/AndroidTest.xml
+++ b/test/cts/AndroidTest.xml
@@ -26,7 +26,6 @@
         <option name="test-file-name" value="CtsPerfettoDebuggableApp.apk" />
         <option name="test-file-name" value="CtsPerfettoReleaseApp.apk" />
         <option name="test-file-name" value="CtsPerfettoProfileableApp.apk" />
-        <option name="test-file-name" value="CtsPerfettoNonProfileableApp.apk" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
@@ -34,6 +33,7 @@
         <option name="append-bitness" value="true" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="setprop persist.heapprofd.enable 1" />
         <option name="run-command" value="setprop persist.traced_perf.enable 1" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.GTest" >
diff --git a/test/cts/BUILD.gn b/test/cts/BUILD.gn
index 0404ceb..84a7860 100644
--- a/test/cts/BUILD.gn
+++ b/test/cts/BUILD.gn
@@ -38,6 +38,7 @@
     "heapprofd_java_test_cts.cc",
     "heapprofd_test_cts.cc",
     "traced_perf_test_cts.cc",
+    "utils.cc",
   ]
 }
 
diff --git a/test/cts/end_to_end_integrationtest_cts.cc b/test/cts/end_to_end_integrationtest_cts.cc
index 632db6d..c1539c7 100644
--- a/test/cts/end_to_end_integrationtest_cts.cc
+++ b/test/cts/end_to_end_integrationtest_cts.cc
@@ -20,7 +20,7 @@
 
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/android_test_utils.h"
+#include "test/cts/utils.h"
 #include "test/test_helper.h"
 
 #include "protos/perfetto/config/test_config.gen.h"
diff --git a/test/cts/heapprofd_java_test_cts.cc b/test/cts/heapprofd_java_test_cts.cc
index f7cfc1a..bad46b4 100644
--- a/test/cts/heapprofd_java_test_cts.cc
+++ b/test/cts/heapprofd_java_test_cts.cc
@@ -22,7 +22,7 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/android_test_utils.h"
+#include "test/cts/utils.h"
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
@@ -80,7 +80,7 @@
 
   // start tracing
   helper.StartTracing(trace_config);
-  helper.WaitForTracingDisabled();
+  helper.WaitForTracingDisabled(10000 /*ms*/);
   helper.ReadData();
   helper.WaitForReadData();
   PERFETTO_CHECK(IsAppRunning(app_name));
@@ -107,7 +107,7 @@
   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().types_size(), 0);
+    ASSERT_EQ(packet.heap_graph().type_names_size(), 0);
     ASSERT_EQ(packet.heap_graph().field_names_size(), 0);
   }
 }
@@ -128,7 +128,7 @@
   std::string app_name = "android.perfetto.cts.app.release";
   const auto& packets = ProfileRuntime(app_name);
 
-  if (!IsUserBuild())
+  if (IsDebuggableBuild())
     AssertGraphPresent(packets);
   else
     AssertNoProfileContents(packets);
diff --git a/test/cts/heapprofd_test_cts.cc b/test/cts/heapprofd_test_cts.cc
index 273efd8..05161b5 100644
--- a/test/cts/heapprofd_test_cts.cc
+++ b/test/cts/heapprofd_test_cts.cc
@@ -24,7 +24,7 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/android_test_utils.h"
+#include "test/cts/utils.h"
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
@@ -36,14 +36,14 @@
 namespace perfetto {
 namespace {
 
-constexpr uint64_t kTestSamplingInterval = 512;
-// Size of individual (repeated) allocations done by the test apps (must be
-// kept in sync with their sources).
-// Tests rely on the sampling behaviour where large allocations are recorded
-// at their actual size, so kExpectedIndividualAllocSz needs to be greater
-// than GetPassthroughTreshold(kExpectedIndividualAllocSz). See
-// src/profiling/memory/sampler.h.
+// Size of individual (repeated) allocations done by the test apps (must be kept
+// in sync with their sources).
+constexpr uint64_t kTestSamplingInterval = 4096;
 constexpr uint64_t kExpectedIndividualAllocSz = 4153;
+// Tests rely on the sampling behaviour where allocations larger than the
+// sampling interval are recorded at their actual size.
+static_assert(kExpectedIndividualAllocSz > kTestSamplingInterval,
+              "kTestSamplingInterval invalid");
 
 std::string RandomSessionName() {
   std::random_device rd;
@@ -58,7 +58,8 @@
 }
 
 std::vector<protos::gen::TracePacket> ProfileRuntime(
-    const std::string& app_name) {
+    const std::string& app_name,
+    const bool enable_extra_guardrails = false) {
   base::TestTaskRunner task_runner;
 
   // (re)start the target app's main activity
@@ -78,6 +79,7 @@
   TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(10 * 1024);
   trace_config.set_duration_ms(4000);
+  trace_config.set_enable_extra_guardrails(enable_extra_guardrails);
   trace_config.set_unique_session_name(RandomSessionName().c_str());
 
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
@@ -93,7 +95,7 @@
 
   // start tracing
   helper.StartTracing(trace_config);
-  helper.WaitForTracingDisabled();
+  helper.WaitForTracingDisabled(10000 /*ms*/);
   helper.ReadData();
   helper.WaitForReadData();
 
@@ -140,7 +142,7 @@
                    /*delay_ms=*/100);
   task_runner.RunUntilCheckpoint("target.app.running", 2000 /*ms*/);
 
-  helper.WaitForTracingDisabled();
+  helper.WaitForTracingDisabled(8000 /*ms*/);
   helper.ReadData();
   helper.WaitForReadData();
 
@@ -212,9 +214,10 @@
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, ReleaseAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.release";
-  const auto& packets = ProfileRuntime(app_name);
+TEST(HeapprofdCtsTest, ProfileableAppRuntimeExtraGuardrails) {
+  std::string app_name = "android.perfetto.cts.app.profileable";
+  const auto& packets = ProfileRuntime(app_name,
+                                       /*enable_extra_guardrails=*/true);
 
   if (IsUserBuild())
     AssertNoProfileContents(packets);
@@ -223,34 +226,39 @@
   StopApp(app_name);
 }
 
+TEST(HeapprofdCtsTest, ProfileableAppStartupExtraGuardrails) {
+  std::string app_name = "android.perfetto.cts.app.profileable";
+  const auto& packets = ProfileStartup(app_name,
+                                       /*enable_extra_guardrails=*/
+                                       true);
+  if (IsUserBuild())
+    AssertNoProfileContents(packets);
+  else
+    AssertExpectedAllocationsPresent(packets);
+  StopApp(app_name);
+}
+
+TEST(HeapprofdCtsTest, ReleaseAppRuntime) {
+  std::string app_name = "android.perfetto.cts.app.release";
+  const auto& packets = ProfileRuntime(app_name);
+
+  if (IsDebuggableBuild())
+    AssertExpectedAllocationsPresent(packets);
+  else
+    AssertNoProfileContents(packets);
+
+  StopApp(app_name);
+}
+
 TEST(HeapprofdCtsTest, ReleaseAppStartup) {
   std::string app_name = "android.perfetto.cts.app.release";
   const auto& packets = ProfileStartup(app_name);
 
-  if (IsUserBuild())
-    AssertNoProfileContents(packets);
-  else
+  if (IsDebuggableBuild())
     AssertExpectedAllocationsPresent(packets);
-  StopApp(app_name);
-}
+  else
+    AssertNoProfileContents(packets);
 
-TEST(HeapprofdCtsTest, NonProfileableAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.nonprofileable";
-  const auto& packets = ProfileRuntime(app_name);
-  if (IsUserBuild())
-    AssertNoProfileContents(packets);
-  else
-    AssertExpectedAllocationsPresent(packets);
-  StopApp(app_name);
-}
-
-TEST(HeapprofdCtsTest, NonProfileableAppStartup) {
-  std::string app_name = "android.perfetto.cts.app.nonprofileable";
-  const auto& packets = ProfileStartup(app_name);
-  if (IsUserBuild())
-    AssertNoProfileContents(packets);
-  else
-    AssertExpectedAllocationsPresent(packets);
   StopApp(app_name);
 }
 
diff --git a/test/cts/producer/Android.bp b/test/cts/producer/Android.bp
index 1503a39..bda36bd 100644
--- a/test/cts/producer/Android.bp
+++ b/test/cts/producer/Android.bp
@@ -12,15 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_perfetto_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
 android_test_helper_app {
     name: "CtsPerfettoProducerApp",
     // tag this module as a cts test artifact
@@ -35,6 +26,7 @@
     sdk_version: "current",
     jni_libs: [
         "libperfettocts_jni",
+        "libnativehelper_compat_libc++",
     ],
     jni_uses_platform_apis: true,
 }
diff --git a/test/cts/producer/AndroidManifest.xml b/test/cts/producer/AndroidManifest.xml
index 7a5d35d..6139dca 100755
--- a/test/cts/producer/AndroidManifest.xml
+++ b/test/cts/producer/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
     <application>
-        <activity android:name=".ProducerActivity" android:exported="true">
+        <activity android:name=".ProducerActivity" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/test/cts/producer/jni/Android.bp b/test/cts/producer/jni/Android.bp
index 696dc97..b97ecdb 100644
--- a/test/cts/producer/jni/Android.bp
+++ b/test/cts/producer/jni/Android.bp
@@ -1,18 +1,8 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_perfetto_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
 cc_library_shared {
   name: "libperfettocts_jni",
   srcs: [
     "fake_producer_jni.cc",
   ],
-  header_libs: ["jni_headers"],
   static_libs: [
     "libgtest",
     "libprotobuf-cpp-lite",
@@ -22,6 +12,7 @@
   shared_libs: [
     "libandroid",
     "liblog",
+    "libnativehelper_compat_libc++",
   ],
   compile_multilib: "both",
   stl: "libc++_static",
diff --git a/test/cts/test_apps/Android.bp b/test/cts/test_apps/Android.bp
index 1172be5..7b9891b 100644
--- a/test/cts/test_apps/Android.bp
+++ b/test/cts/test_apps/Android.bp
@@ -12,15 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_perfetto_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
 android_test_helper_app {
     name: "CtsPerfettoDebuggableApp",
     // tag this module as a cts test artifact
@@ -37,6 +28,7 @@
     sdk_version: "current",
     jni_libs: [
         "libperfettocts_native",
+        "libnativehelper_compat_libc++",
     ],
     jni_uses_platform_apis: true,
 }
@@ -57,6 +49,7 @@
     sdk_version: "current",
     jni_libs: [
         "libperfettocts_native",
+        "libnativehelper_compat_libc++",
     ],
     jni_uses_platform_apis: true,
 }
@@ -77,26 +70,7 @@
     sdk_version: "current",
     jni_libs: [
         "libperfettocts_native",
-    ],
-    jni_uses_platform_apis: true,
-}
-
-android_test_helper_app {
-    name: "CtsPerfettoNonProfileableApp",
-    // tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "vts10",
-        "general-tests",
-    ],
-
-    manifest: "AndroidManifest_nonprofileable.xml",
-
-    compile_multilib: "both",
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    jni_libs: [
-        "libperfettocts_native",
+        "libnativehelper_compat_libc++",
     ],
     jni_uses_platform_apis: true,
 }
diff --git a/test/cts/test_apps/AndroidManifest_debuggable.xml b/test/cts/test_apps/AndroidManifest_debuggable.xml
index 871544e..c85ab05 100755
--- a/test/cts/test_apps/AndroidManifest_debuggable.xml
+++ b/test/cts/test_apps/AndroidManifest_debuggable.xml
@@ -21,12 +21,11 @@
     <application android:debuggable="true">
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.debuggable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity"
-           android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.MainActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -34,12 +33,11 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.debuggable.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -47,3 +45,4 @@
         </activity-alias>
     </application>
 </manifest>
+
diff --git a/test/cts/test_apps/AndroidManifest_nonprofileable.xml b/test/cts/test_apps/AndroidManifest_nonprofileable.xml
deleted file mode 100755
index c4a716d..0000000
--- a/test/cts/test_apps/AndroidManifest_nonprofileable.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.nonprofileable">
-
-    <application>
-        <profileable android:shell="true" android:enabled="false"/>
-        <activity
-          android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
-        </activity>
-        <activity-alias
-          android:name="android.perfetto.cts.app.nonprofileable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity-alias>
-        <activity
-          android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
-        </activity>
-        <activity-alias
-          android:name="android.perfetto.cts.app.nonprofileable.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
-            <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/test_apps/AndroidManifest_profileable.xml b/test/cts/test_apps/AndroidManifest_profileable.xml
index 6322806..129e922 100755
--- a/test/cts/test_apps/AndroidManifest_profileable.xml
+++ b/test/cts/test_apps/AndroidManifest_profileable.xml
@@ -22,12 +22,11 @@
         <profileable android:shell="true"/>
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.profileable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.MainActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -35,12 +34,11 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.profileable.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/test/cts/test_apps/AndroidManifest_release.xml b/test/cts/test_apps/AndroidManifest_release.xml
index 83d9c47..5b64a94 100755
--- a/test/cts/test_apps/AndroidManifest_release.xml
+++ b/test/cts/test_apps/AndroidManifest_release.xml
@@ -21,12 +21,11 @@
     <application>
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.release.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity"
-          android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.MainActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -34,12 +33,11 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:exported="false">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.release.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="true">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -47,3 +45,4 @@
         </activity-alias>
     </application>
 </manifest>
+
diff --git a/test/cts/test_apps/jni/Android.bp b/test/cts/test_apps/jni/Android.bp
index dcbd960..3f50e72 100644
--- a/test/cts/test_apps/jni/Android.bp
+++ b/test/cts/test_apps/jni/Android.bp
@@ -13,27 +13,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_perfetto_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["external_perfetto_license"],
-}
-
 cc_library_shared {
   name: "libperfettocts_native",
   srcs: [
     "target.cc",
   ],
-  header_libs: ["jni_headers"],
   static_libs: [
     "perfetto_cts_jni_deps",
   ],
   shared_libs: [
     "libandroid",
     "liblog",
+    "libnativehelper_compat_libc++",
   ],
   compile_multilib: "both",
   stl: "libc++_static",
diff --git a/test/cts/traced_perf_test_cts.cc b/test/cts/traced_perf_test_cts.cc
index 831f8b3..bbc0add 100644
--- a/test/cts/traced_perf_test_cts.cc
+++ b/test/cts/traced_perf_test_cts.cc
@@ -18,12 +18,10 @@
 #include <sys/system_properties.h>
 #include <sys/types.h>
 
-#include <string>
-
 #include "perfetto/base/logging.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/android_test_utils.h"
+#include "test/cts/utils.h"
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
@@ -45,18 +43,6 @@
   return std::string(buf) == "1";
 }
 
-std::string RandomSessionName() {
-  std::random_device rd;
-  std::default_random_engine generator(rd());
-  std::uniform_int_distribution<char> distribution('a', 'z');
-
-  constexpr size_t kSessionNameLen = 20;
-  std::string result(kSessionNameLen, '\0');
-  for (size_t i = 0; i < kSessionNameLen; ++i)
-    result[i] = distribution(generator);
-  return result;
-}
-
 std::vector<protos::gen::TracePacket> ProfileSystemWide(std::string app_name) {
   base::TestTaskRunner task_runner;
 
@@ -79,7 +65,6 @@
   trace_config.add_buffers()->set_size_kb(20 * 1024);
   trace_config.set_duration_ms(3000);
   trace_config.set_data_source_stop_timeout_ms(8000);
-  trace_config.set_unique_session_name(RandomSessionName().c_str());
 
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("linux.perf");
@@ -184,23 +169,6 @@
   StopApp(app_name);
 }
 
-TEST(TracedPerfCtsTest, SystemWideNonProfileableApp) {
-  if (!HasPerfLsmHooks())
-    GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks";
-
-  std::string app_name = "android.perfetto.cts.app.nonprofileable";
-  const auto& packets = ProfileSystemWide(app_name);
-  int app_pid = PidForProcessName(app_name);
-  ASSERT_GT(app_pid, 0) << "failed to find pid for target process";
-
-  if (!IsUserBuild())
-    AssertHasSampledStacksForPid(packets, app_pid);
-  else
-    AssertNoStacksForPid(packets, app_pid);
-  PERFETTO_CHECK(IsAppRunning(app_name));
-  StopApp(app_name);
-}
-
 TEST(TracedPerfCtsTest, SystemWideReleaseApp) {
   if (!HasPerfLsmHooks())
     GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks";
@@ -210,7 +178,7 @@
   int app_pid = PidForProcessName(app_name);
   ASSERT_GT(app_pid, 0) << "failed to find pid for target process";
 
-  if (!IsUserBuild())
+  if (IsDebuggableBuild())
     AssertHasSampledStacksForPid(packets, app_pid);
   else
     AssertNoStacksForPid(packets, app_pid);
diff --git a/test/cts/utils.cc b/test/cts/utils.cc
new file mode 100644
index 0000000..1dd9b1e
--- /dev/null
+++ b/test/cts/utils.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "perfetto/ext/base/file_utils.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);
+  return std::string(buf) == "1";
+}
+
+bool IsUserBuild() {
+  char buf[PROP_VALUE_MAX + 1] = {};
+  int ret = __system_property_get("ro.build.type", buf);
+  PERFETTO_CHECK(ret >= 0);
+  return std::string(buf) == "user";
+}
+
+// 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);
+}
+
+int PidForProcessName(const std::string& name) {
+  std::string cmd = "pgrep -f ^" + name + "$";
+  FILE* fp = popen(cmd.c_str(), "re");
+  if (!fp)
+    return -1;
+
+  std::string out;
+  base::ReadFileStream(fp, &out);
+  pclose(fp);
+
+  char* endptr = nullptr;
+  int pid = static_cast<int>(strtol(out.c_str(), &endptr, 10));
+  if (*endptr != '\0' && *endptr != '\n')
+    return -1;
+  return pid;
+}
+
+void WaitForProcess(const std::string& process,
+                    const std::string& checkpoint_name,
+                    base::TestTaskRunner* task_runner,
+                    uint32_t delay_ms) {
+  bool desired_run_state = true;
+  const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
+  task_runner->PostDelayedTask(
+      [desired_run_state, task_runner, process, checkpoint] {
+        PollRunState(desired_run_state, task_runner, process,
+                     std::move(checkpoint));
+      },
+      delay_ms);
+}
+
+void StartAppActivity(const std::string& app_name,
+                      const std::string& activity_name,
+                      const std::string& checkpoint_name,
+                      base::TestTaskRunner* task_runner,
+                      uint32_t delay_ms) {
+  std::string start_cmd = "am start " + app_name + "/." + activity_name;
+  int status = system(start_cmd.c_str());
+  ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
+  WaitForProcess(app_name, checkpoint_name, task_runner, 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(const 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
new file mode 100644
index 0000000..724c367
--- /dev/null
+++ b/test/cts/utils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 IsUserBuild();
+
+bool IsAppRunning(const std::string& name);
+
+// returns -1 if the process wasn't found
+int PidForProcessName(const std::string& name);
+
+void WaitForProcess(const std::string& process,
+                    const std::string& checkpoint_name,
+                    base::TestTaskRunner* task_runner,
+                    uint32_t delay_ms = 1);
+
+void StartAppActivity(const std::string& app_name,
+                      const std::string& activity_name,
+                      const std::string& checkpoint_name,
+                      base::TestTaskRunner* task_runner,
+                      uint32_t delay_ms = 1);
+
+void StopApp(const std::string& app_name,
+             const std::string& checkpoint_name,
+             base::TestTaskRunner* task_runner);
+
+void StopApp(const std::string& app_name);
+
+}  // namespace perfetto
+
+#endif  // TEST_CTS_UTILS_H_
diff --git a/test/data b/test/data
new file mode 120000
index 0000000..e588247
--- /dev/null
+++ b/test/data
@@ -0,0 +1 @@
+../buildtools/test_data
\ No newline at end of file
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index ac7f8fa..ff1fe74 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -91,12 +91,10 @@
   uint64_t wall_ns =
       static_cast<uint64_t>(base::GetWallTimeNs().count()) - wall_start_ns;
 
-  state.counters["Ser CPU"] = benchmark::Counter(
-      100.0 * static_cast<double>(service_ns) / static_cast<double>(wall_ns));
-  state.counters["Ser ns/m"] = benchmark::Counter(
-      static_cast<double>(service_ns) / static_cast<double>(message_count));
-  state.counters["Pro CPU"] = benchmark::Counter(
-      100.0 * static_cast<double>(producer_ns) / static_cast<double>(wall_ns));
+  state.counters["Ser CPU"] = benchmark::Counter(100.0 * service_ns / wall_ns);
+  state.counters["Ser ns/m"] =
+      benchmark::Counter(1.0 * service_ns / message_count);
+  state.counters["Pro CPU"] = benchmark::Counter(100.0 * producer_ns / wall_ns);
   state.SetBytesProcessed(iterations * message_bytes * message_count);
 
   // Read back the buffer just to check correctness.
@@ -205,17 +203,13 @@
   uint64_t wall_ns =
       static_cast<uint64_t>(base::GetWallTimeNs().count()) - wall_start_ns;
 
-  state.counters["Ser CPU"] = benchmark::Counter(
-      100.0 * static_cast<double>(service_ns) / static_cast<double>(wall_ns));
+  state.counters["Ser CPU"] = benchmark::Counter(100.0 * service_ns / wall_ns);
   state.counters["Ser ns/m"] =
-      benchmark::Counter(1.0 * static_cast<double>(service_ns) /
-                         static_cast<double>(message_count));
-  state.counters["Con CPU"] = benchmark::Counter(
-      100.0 * static_cast<double>(consumer_ns) / static_cast<double>(wall_ns));
+      benchmark::Counter(1.0 * service_ns / message_count);
+  state.counters["Con CPU"] = benchmark::Counter(100.0 * consumer_ns / wall_ns);
   state.counters["Con Speed"] =
-      benchmark::Counter(static_cast<double>(iterations) * 1000.0 * 1000.0 *
-                         1000.0 * static_cast<double>(kBufferSizeBytes) /
-                         static_cast<double>(read_time_taken_ns));
+      benchmark::Counter(iterations * 1000.0 * 1000 * 1000 * kBufferSizeBytes /
+                         read_time_taken_ns);
 }
 
 void SaturateCpuProducerArgs(benchmark::internal::Benchmark* b) {
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 7b19368..7d001d6 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -34,7 +34,6 @@
 #include "perfetto/ext/traced/traced.h"
 #include "perfetto/ext/tracing/core/commit_data_request.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
 #include "perfetto/ext/tracing/ipc/default_socket.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
@@ -51,8 +50,6 @@
 #include "protos/perfetto/trace/ftrace/ftrace.gen.h"
 #include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.gen.h"
-#include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
 #include "protos/perfetto/trace/power/battery_counters.gen.h"
 #include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/trace.gen.h"
@@ -60,14 +57,6 @@
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "protos/perfetto/trace/trigger.gen.h"
 
-#include "protos/perfetto/common/sys_stats_counters.gen.h"
-#include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
-#include "protos/perfetto/trace/sys_stats/sys_stats.gen.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include "test/android_test_utils.h"
-#endif
-
 namespace perfetto {
 
 namespace {
@@ -76,6 +65,8 @@
 using ::testing::ElementsAreArray;
 using ::testing::HasSubstr;
 
+constexpr size_t kBuiltinPackets = 8;
+
 std::string RandomTraceFileName() {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
   constexpr char kSysTmpPath[] = "/data/misc/perfetto-traces";
@@ -120,6 +111,7 @@
     return subprocess_.returncode();
   }
 
+ private:
   Exec(const std::string& argv0,
        std::initializer_list<std::string> args,
        std::string input = "") {
@@ -135,24 +127,20 @@
 
     std::vector<std::string>& cmd = subprocess_.args.exec_cmd;
     if (kUseSystemBinaries) {
-      PERFETTO_CHECK(TestHelper::kDefaultMode ==
-                     TestHelper::Mode::kUseSystemService);
       cmd.push_back("/system/bin/" + argv0);
       cmd.insert(cmd.end(), args.begin(), args.end());
     } else {
-      PERFETTO_CHECK(TestHelper::kDefaultMode ==
-                     TestHelper::Mode::kStartDaemons);
       subprocess_.args.env.push_back(
           std::string("PERFETTO_PRODUCER_SOCK_NAME=") +
-          TestHelper::GetDefaultModeProducerSocketName());
+          TestHelper::GetProducerSocketName());
       subprocess_.args.env.push_back(
           std::string("PERFETTO_CONSUMER_SOCK_NAME=") +
-          TestHelper::GetDefaultModeConsumerSocketName());
+          TestHelper::GetConsumerSocketName());
       cmd.push_back(base::GetCurExecutableDir() + "/" + argv0);
       cmd.insert(cmd.end(), args.begin(), args.end());
     }
 
-    if (!base::FileExists(cmd[0])) {
+    if (access(cmd[0].c_str(), F_OK)) {
       PERFETTO_FATAL(
           "Cannot find %s. Make sure that the target has been built and, on "
           "Android, pushed to the device.",
@@ -173,7 +161,7 @@
     // This lambda will be called on the forked child process after having
     // setup pipe redirection and closed all FDs, right before the exec().
     // The Subprocesss harness will take care of closing also |sync_pipe_.wr|.
-    subprocess_.args.posix_entrypoint_for_testing = [sync_pipe_rd] {
+    subprocess_.args.entrypoint_for_testing = [sync_pipe_rd] {
       // Don't add any logging here, all file descriptors are closed and trying
       // to log will likely cause undefined behaviors.
       char ignored = 0;
@@ -185,7 +173,7 @@
     sync_pipe_.rd.reset();
   }
 
- private:
+  friend class PerfettoCmdlineTest;
   base::Subprocess subprocess_;
   base::Pipe sync_pipe_;
 };
@@ -193,7 +181,12 @@
 class PerfettoTest : public ::testing::Test {
  public:
   void SetUp() override {
-    ftrace_procfs_ = FtraceProcfs::CreateGuessingMountPoint();
+    // TODO(primiano): refactor this, it's copy/pasted in three places now.
+    size_t index = 0;
+    constexpr auto kTracingPaths = FtraceController::kTracingPaths;
+    while (!ftrace_procfs_ && kTracingPaths[index]) {
+      ftrace_procfs_ = FtraceProcfs::Create(kTracingPaths[index++]);
+    }
   }
 
   std::unique_ptr<FtraceProcfs> ftrace_procfs_;
@@ -253,33 +246,6 @@
   TestHelper test_helper_{&task_runner_};
 };
 
-// For the SaveForBugreport* tests.
-void SetTraceConfigForBugreportTest(TraceConfig* trace_config) {
-  trace_config->add_buffers()->set_size_kb(4096);
-  trace_config->set_duration_ms(60000);  // Will never hit this.
-  trace_config->set_bugreport_score(10);
-  auto* ds_config = trace_config->add_data_sources()->mutable_config();
-  ds_config->set_name("android.perfetto.FakeProducer");
-  ds_config->mutable_for_testing()->set_message_count(3);
-  ds_config->mutable_for_testing()->set_message_size(10);
-  ds_config->mutable_for_testing()->set_send_batch_on_register(true);
-}
-
-// For the SaveForBugreport* tests.
-static void VerifyBugreportTraceContents() {
-  // Read the trace written in the fixed location (/data/misc/perfetto-traces/
-  // on Android, /tmp/ on Linux/Mac) and make sure it has the right contents.
-  std::string trace_str;
-  base::ReadFile(GetBugreportPath(), &trace_str);
-  ASSERT_FALSE(trace_str.empty());
-  protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromString(trace_str));
-  int test_packets = 0;
-  for (const auto& p : trace.packet())
-    test_packets += p.has_for_testing() ? 1 : 0;
-  ASSERT_EQ(test_packets, 3);
-}
-
 }  // namespace
 
 // If we're building on Android and starting the daemons ourselves,
@@ -402,215 +368,6 @@
   ASSERT_EQ(marker_found, 1);
 }
 
-TEST_F(PerfettoTest, TreeHuggerOnly(TestKmemActivity)) {
-  using C = protos::gen::VmstatCounters;
-
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-
-  // Create kmem_activity trigger proc before starting service
-  auto kmem_activity_trigger_proc = Exec("trigger_perfetto", {"kmem_activity"});
-
-  helper.StartServiceIfRequired();
-
-#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-  ProbesProducerThread probes(TEST_PRODUCER_SOCK_NAME);
-  probes.Connect();
-#endif
-
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(1024);
-  trace_config.set_unique_session_name("kmem_activity_test");
-
-  auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
-  ftrace_ds_config->set_name("linux.ftrace");
-  protos::gen::FtraceConfig ftrace_config = CreateFtraceConfig({
-      "vmscan/mm_vmscan_kswapd_wake",
-      "vmscan/mm_vmscan_kswapd_sleep",
-      "vmscan/mm_vmscan_direct_reclaim_begin",
-      "vmscan/mm_vmscan_direct_reclaim_end",
-      "compaction/mm_compaction_begin",
-      "compaction/mm_compaction_end",
-  });
-  ftrace_ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
-
-  auto* sys_stats_ds_config = trace_config.add_data_sources()->mutable_config();
-  sys_stats_ds_config->set_name("linux.sys_stats");
-  protos::gen::SysStatsConfig sys_stats_config;
-  sys_stats_config.set_vmstat_period_ms(50);
-  std::vector<C> vmstat_counters = {
-      C::VMSTAT_NR_FREE_PAGES,
-      C::VMSTAT_NR_SLAB_RECLAIMABLE,
-      C::VMSTAT_NR_SLAB_UNRECLAIMABLE,
-      C::VMSTAT_NR_ACTIVE_FILE,
-      C::VMSTAT_NR_INACTIVE_FILE,
-      C::VMSTAT_NR_ACTIVE_ANON,
-      C::VMSTAT_NR_INACTIVE_ANON,
-      C::VMSTAT_WORKINGSET_REFAULT,
-      C::VMSTAT_WORKINGSET_ACTIVATE,
-      C::VMSTAT_NR_FILE_PAGES,
-      C::VMSTAT_PGPGIN,
-      C::VMSTAT_PGPGOUT,
-      C::VMSTAT_PSWPIN,
-      C::VMSTAT_PSWPOUT,
-      C::VMSTAT_PGSTEAL_KSWAPD_DMA,
-      C::VMSTAT_PGSTEAL_KSWAPD_NORMAL,
-      C::VMSTAT_PGSTEAL_KSWAPD_MOVABLE,
-      C::VMSTAT_PGSTEAL_DIRECT_DMA,
-      C::VMSTAT_PGSTEAL_DIRECT_NORMAL,
-      C::VMSTAT_PGSTEAL_DIRECT_MOVABLE,
-      C::VMSTAT_PGSCAN_KSWAPD_DMA,
-      C::VMSTAT_PGSCAN_KSWAPD_NORMAL,
-      C::VMSTAT_PGSCAN_KSWAPD_MOVABLE,
-      C::VMSTAT_PGSCAN_DIRECT_DMA,
-      C::VMSTAT_PGSCAN_DIRECT_NORMAL,
-      C::VMSTAT_PGSCAN_DIRECT_MOVABLE,
-      C::VMSTAT_COMPACT_MIGRATE_SCANNED,
-      C::VMSTAT_COMPACT_FREE_SCANNED,
-  };
-  for (const auto& counter : vmstat_counters) {
-    sys_stats_config.add_vmstat_counters(counter);
-  }
-  sys_stats_ds_config->set_sys_stats_config_raw(
-      sys_stats_config.SerializeAsString());
-
-  auto* trigger_cfg = trace_config.mutable_trigger_config();
-  trigger_cfg->set_trigger_mode(
-      protos::gen::TraceConfig::TriggerConfig::START_TRACING);
-  trigger_cfg->set_trigger_timeout_ms(15000);
-  auto* trigger = trigger_cfg->add_triggers();
-  trigger->set_name("kmem_activity");
-  // |stop_delay_ms| must be long enough that we can write the packets in
-  // before the trace finishes.
-  trigger->set_stop_delay_ms(1000);
-
-  helper.StartTracing(trace_config);
-
-  // Generating synthetic memory pressure to trigger kmem activity is
-  // inherently flaky on different devices. The same goes for writing
-  // /proc/sys/vm/compact_memory to trigger compaction, since compaction is
-  // only started if needed (even if explicitly triggered from proc).
-  // Trigger kmem activity using perfetto trigger.
-  std::string stderr_str;
-  EXPECT_EQ(0, kmem_activity_trigger_proc.Run(&stderr_str)) << stderr_str;
-
-  helper.WaitForTracingDisabled();
-
-  helper.ReadData();
-  helper.WaitForReadData();
-
-  const auto& packets = helper.trace();
-  ASSERT_GT(packets.size(), 0u);
-
-  bool sys_stats_captured = false;
-  for (const auto& packet : packets) {
-    for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
-      auto ftrace_event =
-          packet.ftrace_events().event()[static_cast<size_t>(ev)];
-      ASSERT_TRUE(ftrace_event.has_mm_vmscan_kswapd_wake() ||
-                  ftrace_event.has_mm_vmscan_kswapd_sleep() ||
-                  ftrace_event.has_mm_vmscan_direct_reclaim_begin() ||
-                  ftrace_event.has_mm_vmscan_direct_reclaim_end() ||
-                  ftrace_event.has_mm_compaction_begin() ||
-                  ftrace_event.has_mm_compaction_end());
-    }
-
-    if (packet.has_sys_stats()) {
-      sys_stats_captured = true;
-      const auto& sys_stats = packet.sys_stats();
-      const auto& vmstat = sys_stats.vmstat();
-      ASSERT_GT(vmstat.size(), 0u);
-      for (const auto& vmstat_value : vmstat) {
-        ASSERT_NE(std::find(vmstat_counters.begin(), vmstat_counters.end(),
-                            vmstat_value.key()),
-                  vmstat_counters.end());
-      }
-    }
-  }
-
-  // Don't explicitly check that ftrace events were captured, since this test
-  // doesn't rely on memory pressure.
-  ASSERT_TRUE(sys_stats_captured);
-}
-
-// Disable this test:
-// 1. On cuttlefish (x86-kvm). It's too slow when running on GCE (b/171771440).
-//    We cannot change the length of the production code in
-//    CanReadKernelSymbolAddresses() to deal with it.
-// 2. On user (i.e. non-userdebug) builds. As that doesn't work there by design.
-// 3. On ARM builds, because they fail on our CI.
-#if (PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) && defined(__i386__)) || \
-    defined(__arm__)
-#define MAYBE_KernelAddressSymbolization DISABLED_KernelAddressSymbolization
-#else
-#define MAYBE_KernelAddressSymbolization KernelAddressSymbolization
-#endif
-TEST_F(PerfettoTest, MAYBE_KernelAddressSymbolization) {
-  // On Android in-tree builds (TreeHugger): this test must always run to
-  // prevent selinux / property-related regressions. However it can run only on
-  // userdebug.
-  // On standalone builds and Linux, this can be optionally skipped because
-  // there it requires root to lower kptr_restrict.
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-  if (!IsDebuggableBuild())
-    GTEST_SKIP();
-#else
-  if (geteuid() != 0)
-    GTEST_SKIP();
-#endif
-
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-
-#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-  ProbesProducerThread probes(TEST_PRODUCER_SOCK_NAME);
-  probes.Connect();
-#endif
-
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(1024);
-
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("linux.ftrace");
-  protos::gen::FtraceConfig ftrace_cfg;
-  ftrace_cfg.set_symbolize_ksyms(true);
-  ftrace_cfg.set_initialize_ksyms_synchronously_for_testing(true);
-  ds_config->set_ftrace_config_raw(ftrace_cfg.SerializeAsString());
-
-  helper.StartTracing(trace_config);
-
-  // Synchronize with the ftrace data source. The kernel symbol map is loaded
-  // at this point.
-  helper.FlushAndWait(kDefaultTestTimeoutMs);
-  helper.DisableTracing();
-  helper.WaitForTracingDisabled();
-  helper.ReadData();
-  helper.WaitForReadData();
-
-  const auto& packets = helper.trace();
-  ASSERT_GT(packets.size(), 0u);
-
-  int symbols_parsed = -1;
-  for (const auto& packet : packets) {
-    if (!packet.has_ftrace_stats())
-      continue;
-    if (packet.ftrace_stats().phase() != protos::gen::FtraceStats::END_OF_TRACE)
-      continue;
-    symbols_parsed =
-        static_cast<int>(packet.ftrace_stats().kernel_symbols_parsed());
-  }
-  ASSERT_GT(symbols_parsed, 100);
-}
-
 // TODO(b/73453011): reenable on more platforms (including standalone Android).
 TEST_F(PerfettoTest, TreeHuggerOnly(TestBatteryTracing)) {
   base::TestTaskRunner task_runner;
@@ -661,8 +418,8 @@
     has_battery_packet = true;
     // Unfortunately we cannot make any assertions on the charge counter.
     // On some devices it can reach negative values (b/64685329).
-    EXPECT_GE(packet.battery().capacity_percent(), 0.f);
-    EXPECT_LE(packet.battery().capacity_percent(), 100.f);
+    EXPECT_GE(packet.battery().capacity_percent(), 0);
+    EXPECT_LE(packet.battery().capacity_percent(), 100);
   }
 
   ASSERT_TRUE(has_battery_packet);
@@ -754,75 +511,6 @@
   }
 }
 
-// This is a regression test see b/169051440 for context.
-//
-// In this test we ensure that traced will not crash if a Producer stops
-// responding or draining the socket (i.e. after we fill up the IPC buffer
-// traced doesn't block on trying to write to the IPC buffer and watchdog
-// doesn't kill it).
-TEST_F(PerfettoTest, UnresponsiveProducer) {
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-  auto* producer = helper.ConnectFakeProducer();
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(4096 * 10);
-  trace_config.set_duration_ms(100);
-  trace_config.set_flush_timeout_ms(1);
-  trace_config.set_data_source_stop_timeout_ms(1);
-
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.perfetto.FakeProducer");
-
-  static constexpr size_t kNumPackets = 1;
-  static constexpr uint32_t kRandomSeed = 42;
-  static constexpr uint32_t kMsgSize = 1024 * 1024 - 42;
-  ds_config->mutable_for_testing()->set_seed(kRandomSeed);
-  ds_config->mutable_for_testing()->set_message_count(kNumPackets);
-  ds_config->mutable_for_testing()->set_message_size(kMsgSize);
-  ds_config->mutable_for_testing()->set_send_batch_on_register(true);
-
-  // This string is just used to make the StartDataSource IPC larger.
-  ds_config->set_legacy_config(std::string(8192, '.'));
-  ds_config->set_target_buffer(0);
-
-  // Run one legit trace, this ensures that the producer above is
-  // valid and correct and mirrors real life producers.
-  helper.StartTracing(trace_config);
-  helper.WaitForProducerEnabled();
-  helper.WaitForTracingDisabled();
-
-  helper.ReadData();
-  helper.WaitForReadData(/* read_count */ 0, /* timeout_ms */ 10000);
-
-  const auto& packets = helper.trace();
-  ASSERT_EQ(packets.size(), 1u);
-  ASSERT_TRUE(packets[0].has_for_testing());
-  ASSERT_FALSE(packets[0].for_testing().str().empty());
-  helper.FreeBuffers();
-
-  // Switch the producer to ignoring the IPC socket. On a pixel 4 it took 13
-  // traces to fill up the IPC buffer and cause traced to block (and eventually
-  // watchdog to kill it).
-  helper.producer_thread()->get()->RemoveFileDescriptorWatch(
-      producer->unix_socket_fd());
-
-  trace_config.set_duration_ms(1);
-  for (uint32_t i = 0u; i < 15u; i++) {
-    helper.StartTracing(trace_config, base::ScopedFile());
-    helper.WaitForTracingDisabled(/* timeout_ms = */ 20000);
-    helper.FreeBuffers();
-  }
-  // We need to readd the FileDescriptor (otherwise when the UnixSocket attempts
-  // to remove it a the FakeProducer is destroyed will hit a CHECK failure.
-  helper.producer_thread()->get()->AddFileDescriptorWatch(
-      producer->unix_socket_fd(), []() {});
-}
-
 TEST_F(PerfettoTest, DetachAndReattach) {
   base::TestTaskRunner task_runner;
 
@@ -1004,125 +692,6 @@
   EXPECT_THAT(ds_found, ElementsAreArray(ds_expected));
 }
 
-TEST_F(PerfettoTest, SaveForBugreport) {
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-  helper.ConnectFakeProducer();
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  SetTraceConfigForBugreportTest(&trace_config);
-
-  helper.StartTracing(trace_config);
-  helper.WaitForProducerEnabled();
-
-  EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
-  helper.WaitForTracingDisabled();
-
-  VerifyBugreportTraceContents();
-
-  // Now read the trace returned to the consumer via ReadBuffers. This should
-  // be always empty because --save-for-bugreport takes it over and makes the
-  // buffers unreadable by the consumer (by virtue of force-setting
-  // write_into_file, which is incompatible with ReadBuffers()). The only
-  // content should be the |seized_for_bugreport| flag.
-  helper.ReadData();
-  helper.WaitForReadData();
-  const auto& packets = helper.full_trace();
-  ASSERT_EQ(packets.size(), 1u);
-  for (const auto& p : packets) {
-    ASSERT_TRUE(p.has_service_event());
-    ASSERT_TRUE(p.service_event().seized_for_bugreport());
-  }
-}
-
-// Tests that the SaveForBugreport logic works also for traces with
-// write_into_file = true (with a passed file descriptor).
-TEST_F(PerfettoTest, SaveForBugreport_WriteIntoFile) {
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-  helper.ConnectFakeProducer();
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  SetTraceConfigForBugreportTest(&trace_config);
-  trace_config.set_file_write_period_ms(60000);  // Will never hit this.
-  trace_config.set_write_into_file(true);
-
-  auto pipe_pair = base::Pipe::Create();
-  helper.StartTracing(trace_config, std::move(pipe_pair.wr));
-  helper.WaitForProducerEnabled();
-
-  EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
-  helper.WaitForTracingDisabled();
-
-  VerifyBugreportTraceContents();
-
-  // Now read the original file descriptor passed in.
-  std::string trace_bytes;
-  ASSERT_TRUE(base::ReadPlatformHandle(*pipe_pair.rd, &trace_bytes));
-  protos::gen::Trace trace;
-  ASSERT_TRUE(trace.ParseFromString(trace_bytes));
-  ASSERT_EQ(trace.packet().size(), 1u);
-  for (const auto& p : trace.packet()) {
-    ASSERT_TRUE(p.has_service_event());
-    ASSERT_TRUE(p.service_event().seized_for_bugreport());
-  }
-}
-
-// Tests that SaveTraceForBugreport() works also if the trace has triggers
-// defined and those triggers have not been hit. This is a regression test for
-// b/188008375 .
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-// Disabled due to b/191940560
-#define MAYBE_SaveForBugreport_Triggers DISABLED_SaveForBugreport_Triggers
-#else
-#define MAYBE_SaveForBugreport_Triggers SaveForBugreport_Triggers
-#endif
-TEST_F(PerfettoTest, MAYBE_SaveForBugreport_Triggers) {
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-  helper.ConnectFakeProducer();
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  SetTraceConfigForBugreportTest(&trace_config);
-  trace_config.set_duration_ms(0);  // set_trigger_timeout_ms is used instead.
-  auto* trigger_config = trace_config.mutable_trigger_config();
-  trigger_config->set_trigger_timeout_ms(8.64e+7);
-  trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
-  auto* trigger = trigger_config->add_triggers();
-  trigger->set_name("trigger_name");
-  trigger->set_stop_delay_ms(1);
-
-  helper.StartTracing(trace_config);
-  helper.WaitForProducerEnabled();
-
-  EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
-  helper.WaitForTracingDisabled();
-
-  VerifyBugreportTraceContents();
-
-  // Now read the original trace.
-  helper.ReadData();
-  helper.WaitForReadData();
-  const auto& packets = helper.full_trace();
-  ASSERT_EQ(packets.size(), 1u);
-  for (const auto& p : packets) {
-    ASSERT_TRUE(p.has_service_event());
-    ASSERT_TRUE(p.service_event().seized_for_bugreport());
-  }
-}
-
 // Disable cmdline tests on sanitizets because they use fork() and that messes
 // up leak / races detections, which has been fixed only recently (see
 // https://github.com/google/sanitizers/issues/836 ).
@@ -1178,12 +747,12 @@
   EXPECT_EQ(1, empty_config.Run(&stderr_));
   EXPECT_THAT(stderr_, HasSubstr("TraceConfig is empty"));
 
-  // Cannot make assertions on --upload because on standalone builds it fails
+  // 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, either_out_or_dropbox.Run(&stderr_));
-  EXPECT_THAT(stderr_, HasSubstr("Either --out or --upload"));
+  EXPECT_THAT(stderr_, HasSubstr("Either --out or --dropbox"));
 
   // Disallow mixing simple and file config.
   EXPECT_EQ(1, simple_and_file_1.Run(&stderr_));
@@ -1212,7 +781,7 @@
   EXPECT_THAT(stderr_, ContainsRegex("option.*--detach.*requires an argument"));
 
   EXPECT_EQ(1, detach_without_out_or_dropbox.Run(&stderr_));
-  EXPECT_THAT(stderr_, HasSubstr("--out or --upload is required"));
+  EXPECT_THAT(stderr_, HasSubstr("--out or --dropbox is required"));
 
   // Cannot trace and use --query.
   EXPECT_EQ(1, trace_and_query_1.Run(&stderr_));
@@ -1317,30 +886,23 @@
   base::ReadFile(path, &trace_str);
   protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
-  size_t for_testing_packets = 0;
-  size_t trigger_packets = 0;
-  size_t trace_config_packets = 0;
+  EXPECT_EQ(static_cast<int>(kBuiltinPackets + kMessageCount),
+            trace.packet_size());
   for (const auto& packet : trace.packet()) {
     if (packet.has_trace_config()) {
       // Ensure the trace config properly includes the trigger mode we set.
       auto kStartTrig = protos::gen::TraceConfig::TriggerConfig::START_TRACING;
       EXPECT_EQ(kStartTrig,
                 packet.trace_config().trigger_config().trigger_mode());
-      ++trace_config_packets;
     } else if (packet.has_trigger()) {
       // validate that the triggers are properly added to the trace.
       EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
-      ++trigger_packets;
     } else if (packet.has_for_testing()) {
       // Make sure that the data size is correctly set based on what we
       // requested.
       EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
-      ++for_testing_packets;
     }
   }
-  EXPECT_EQ(trace_config_packets, 1u);
-  EXPECT_EQ(trigger_packets, 1u);
-  EXPECT_EQ(for_testing_packets, kMessageCount);
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(StopTracingTrigger)) {
@@ -1412,17 +974,15 @@
   base::ReadFile(path, &trace_str);
   protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
+  EXPECT_EQ(static_cast<int>(kBuiltinPackets + 1 + kMessageCount),
+            trace.packet_size());
   bool seen_first_trigger = false;
-  size_t for_testing_packets = 0;
-  size_t trigger_packets = 0;
-  size_t trace_config_packets = 0;
   for (const auto& packet : trace.packet()) {
     if (packet.has_trace_config()) {
       // Ensure the trace config properly includes the trigger mode we set.
       auto kStopTrig = protos::gen::TraceConfig::TriggerConfig::STOP_TRACING;
       EXPECT_EQ(kStopTrig,
                 packet.trace_config().trigger_config().trigger_mode());
-      ++trace_config_packets;
     } else if (packet.has_trigger()) {
       // validate that the triggers are properly added to the trace.
       if (!seen_first_trigger) {
@@ -1431,17 +991,12 @@
       } else {
         EXPECT_EQ("trigger_name_3", packet.trigger().trigger_name());
       }
-      ++trigger_packets;
     } else if (packet.has_for_testing()) {
       // Make sure that the data size is correctly set based on what we
       // requested.
       EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
-      ++for_testing_packets;
     }
   }
-  EXPECT_EQ(trace_config_packets, 1u);
-  EXPECT_EQ(trigger_packets, 2u);
-  EXPECT_EQ(for_testing_packets, kMessageCount);
 }
 
 // Dropbox on the commandline client only works on android builds. So disable
@@ -1457,8 +1012,6 @@
   protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   trace_config.set_allow_user_build_tracing(true);
-  auto* incident_config = trace_config.mutable_incident_report_config();
-  incident_config->set_destination_package("foo.bar.baz");
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.perfetto.FakeProducer");
   ds_config->mutable_for_testing()->set_message_count(kMessageCount);
@@ -1502,7 +1055,7 @@
   background_trace.join();
 
   EXPECT_THAT(stderr_str,
-              ::testing::HasSubstr("Skipping write to incident. Empty trace."));
+              ::testing::HasSubstr("Skipping write to dropbox. Empty trace."));
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(StopTracingTriggerFromConfig)) {
diff --git a/test/end_to_end_shared_memory_fuzzer.cc b/test/end_to_end_shared_memory_fuzzer.cc
index 91f3629..ce53acf 100644
--- a/test/end_to_end_shared_memory_fuzzer.cc
+++ b/test/end_to_end_shared_memory_fuzzer.cc
@@ -83,7 +83,7 @@
         static_cast<BufferID>(source_config.target_buffer()));
     {
       auto packet = trace_writer->NewTracePacket();
-      packet->AppendRawProtoBytes(data_, size_);
+      packet->stream_writer_for_testing()->WriteBytes(data_, size_);
     }
     trace_writer->Flush();
 
@@ -140,20 +140,12 @@
   std::function<void()> on_produced_and_committed_;
 };
 
-class FuzzTestHelper : public TestHelper {
- public:
-  explicit FuzzTestHelper(base::TestTaskRunner* task_runner)
-      : TestHelper(task_runner) {}
-  // Do not verify the data, as it will most likely be corrupted.
-  void ReadTraceData(std::vector<TracePacket>) override {}
-};
-
 int FuzzSharedMemory(const uint8_t* data, size_t size);
 
 int FuzzSharedMemory(const uint8_t* data, size_t size) {
   base::TestTaskRunner task_runner;
 
-  FuzzTestHelper helper(&task_runner);
+  TestHelper helper(&task_runner);
   helper.StartServiceIfRequired();
 
   auto cp =
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index f716c90..2fc18a3 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -17,18 +17,16 @@
 #include "test/fake_producer.h"
 
 #include <mutex>
-#include <thread>
 
 #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/commit_data_request.h"
 #include "perfetto/ext/tracing/core/shared_memory_arbiter.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 "src/ipc/client_impl.h"
-#include "src/tracing/ipc/producer/producer_ipc_client_impl.h"
 
 #include "protos/perfetto/config/test_config.gen.h"
 #include "protos/perfetto/trace/test_event.pbzero.h"
@@ -56,7 +54,7 @@
       socket_name, this, "android.perfetto.FakeProducer", task_runner_,
       TracingService::ProducerSMBScrapingMode::kDefault,
       /*shared_memory_size_hint_bytes=*/0,
-      /*shared_memory_page_size_hint_bytes=*/4096, std::move(shm),
+      /*shared_memory_page_size_hint_bytes=*/base::kPageSize, std::move(shm),
       std::move(shm_arbiter));
   on_connect_ = std::move(on_connect);
   on_setup_data_source_instance_ = std::move(on_setup_data_source_instance);
@@ -162,15 +160,6 @@
   endpoint_->NotifyFlushComplete(flush_request_id);
 }
 
-base::SocketHandle FakeProducer::unix_socket_fd() {
-  // Since FakeProducer is only used in tests we can include and assume the
-  // implementation.
-  auto* producer = static_cast<ProducerIPCClientImpl*>(endpoint_.get());
-  auto* ipc_client =
-      static_cast<ipc::ClientImpl*>(producer->GetClientForTesting());
-  return ipc_client->GetUnixSocketForTesting()->fd();
-}
-
 void FakeProducer::SetupFromConfig(const protos::gen::TestConfig& config) {
   rnd_engine_ = std::minstd_rand0(config.seed());
   message_count_ = config.message_count();
@@ -211,8 +200,8 @@
       int64_t expected_time_taken = iterations * 1000;
       base::TimeMillis time_taken = base::GetWallTimeMs() - start;
       while (time_taken.count() < expected_time_taken) {
-        std::this_thread::sleep_for(
-            base::TimeMillis(expected_time_taken - time_taken.count()));
+        usleep(static_cast<useconds_t>(
+            (expected_time_taken - time_taken.count()) * 1000));
         time_taken = base::GetWallTimeMs() - start;
       }
     }
diff --git a/test/fake_producer.h b/test/fake_producer.h
index 27cd5d3..c38e40f 100644
--- a/test/fake_producer.h
+++ b/test/fake_producer.h
@@ -22,7 +22,6 @@
 #include <string>
 
 #include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/tracing/core/producer.h"
 #include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
@@ -82,9 +81,6 @@
   void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
                              size_t /*num_data_sources*/) override {}
 
-  // For testing, access to the fd used to communicate with the TracingService.
-  base::SocketHandle unix_socket_fd();
-
  private:
   void SetupFromConfig(const protos::gen::TestConfig& config);
   void EmitEventBatchOnTaskRunner(std::function<void()> callback);
diff --git a/test/gtest_and_gmock.h b/test/gtest_and_gmock.h
index 82918d8..90a8c85 100644
--- a/test/gtest_and_gmock.h
+++ b/test/gtest_and_gmock.h
@@ -25,8 +25,6 @@
 // 1 applies recursively also to the test translation units, 2 applies only
 // to gmock/gtest includes.
 
-#include "perfetto/base/build_config.h"
-
 #if defined(__GNUC__)  // GCC & clang
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wundef"
@@ -38,12 +36,7 @@
 
 #if defined(__clang__)
 #pragma GCC diagnostic ignored "-Wshift-sign-overflow"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
-// -Wcomma isn't supported on NaCL.
 #pragma GCC diagnostic ignored "-Wcomma"
-#endif  // PERFETTO_OS_NACL
-
 #endif
 
 #include <gmock/gmock.h>
diff --git a/test/gtest_logcat_printer.cc b/test/gtest_logcat_printer.cc
index a78fa88..f88e01b 100644
--- a/test/gtest_logcat_printer.cc
+++ b/test/gtest_logcat_printer.cc
@@ -58,14 +58,8 @@
 void LogcatPrinter::OnTestEnd(const testing::TestInfo& test_info) {
   const auto* result = test_info.result();
   const char* state = "N/A";
-  if (result) {
-    if (result->Passed())
-      state = "PASS";
-    else if (result->Skipped())
-      state = "SKIPPED";
-    else if (result->Failed())
-      state = "FAIL";
-  }
+  if (result)
+    state = result->Passed() ? "PASS" : "FAIL";
   PERFETTO_TEST_LOG("Test end: %s.%s [%s]", test_info.test_case_name(),
                     test_info.name(), state);
 }
diff --git a/test/trace_processor/startup/android_batt_counters.out b/test/metrics/android_batt_counters.out
similarity index 100%
rename from test/trace_processor/startup/android_batt_counters.out
rename to test/metrics/android_batt_counters.out
diff --git a/test/metrics/android_ion.out b/test/metrics/android_ion.out
new file mode 100644
index 0000000..c7094fb
--- /dev/null
+++ b/test/metrics/android_ion.out
@@ -0,0 +1,16 @@
+android_ion {
+  buffer {
+    name: "adsp"
+    avg_size_bytes: 1000.0
+    min_size_bytes: 1000.0
+    max_size_bytes: 1100.0
+    total_alloc_size_bytes: 1100.0
+  }
+  buffer {
+    name: "system"
+    avg_size_bytes: 1497.48743719
+    min_size_bytes: 1000.0
+    max_size_bytes: 2000.0
+    total_alloc_size_bytes: 2000.0
+  }
+}
diff --git a/test/metrics/android_ion.py b/test/metrics/android_ion.py
new file mode 100644
index 0000000..29e63fa
--- /dev/null
+++ b/test/metrics/android_ion.py
@@ -0,0 +1,33 @@
+#!/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()
+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', len=1000)
+trace.add_ion_event(ts=150, tid=3, heap_name='adsp', len=1000)
+trace.add_ion_event(ts=200, tid=3, heap_name='system', size=1000, len=1000)
+trace.add_ion_event(ts=299, tid=3, heap_name='adsp', size=1000, len=100)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_ion_stat.out b/test/metrics/android_ion_stat.out
similarity index 100%
rename from test/trace_processor/memory/android_ion_stat.out
rename to test/metrics/android_ion_stat.out
diff --git a/test/trace_processor/memory/android_ion_stat.textproto b/test/metrics/android_ion_stat.textproto
similarity index 100%
rename from test/trace_processor/memory/android_ion_stat.textproto
rename to test/metrics/android_ion_stat.textproto
diff --git a/test/metrics/android_lmk.py b/test/metrics/android_lmk.py
new file mode 100644
index 0000000..fab3acb
--- /dev/null
+++ b/test/metrics/android_lmk.py
@@ -0,0 +1,35 @@
+#!/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()
+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/trace_processor/memory/android_lmk_oom.out b/test/metrics/android_lmk_oom.out
similarity index 100%
rename from test/trace_processor/memory/android_lmk_oom.out
rename to test/metrics/android_lmk_oom.out
diff --git a/test/trace_processor/memory/android_lmk_reason.out b/test/metrics/android_lmk_reason.out
similarity index 100%
rename from test/trace_processor/memory/android_lmk_reason.out
rename to test/metrics/android_lmk_reason.out
diff --git a/test/metrics/android_lmk_reason.py b/test/metrics/android_lmk_reason.py
new file mode 100644
index 0000000..4fde7f3
--- /dev/null
+++ b/test/metrics/android_lmk_reason.py
@@ -0,0 +1,70 @@
+#!/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_packet()
+trace.add_process(1, 0, 'init')
+trace.add_process(2, 1, 'system_server')
+trace.add_process(3, 1, 'lmk_victim:no_data:ignored')
+trace.add_process(4, 1, 'lmk_victim:no_ion')
+trace.add_process(5, 1, 'lmk_victim:with_ion')
+trace.add_process(6, 1, 'process')
+trace.add_process(7, 1, 'lmk_victim:with_process')
+trace.add_process(8, 1, 'app:ui', 10001)
+trace.add_process(9, 1, 'lmk_victim:with_app')
+
+trace.add_package_list(ts=1, name="app", uid=10001, version_code=123)
+trace.add_package_list(ts=1, name="shared_uid_app", uid=10001, version_code=345)
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_kernel_lmk(ts=101, tid=3)
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=201, oom_score_adj=0, pid=4)
+trace.add_kernel_lmk(ts=202, tid=4)
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_ion_event(ts=301, tid=5, heap_name='system', len=1000)
+trace.add_oom_score_update(ts=302, oom_score_adj=100, pid=5)
+trace.add_kernel_lmk(ts=303, tid=5)
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=401, oom_score_adj=0, pid=6)
+trace.add_oom_score_update(ts=402, oom_score_adj=200, pid=7)
+trace.add_rss_stat(ts=403, tid=6, member=anon_member, size=2000)
+trace.add_kernel_lmk(ts=404, tid=7)
+trace.add_process_free(ts=405, tid=6, comm='', prio=0)
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=501, oom_score_adj=0, pid=8)
+trace.add_oom_score_update(ts=502, oom_score_adj=100, pid=9)
+trace.add_rss_stat(ts=503, tid=8, member=anon_member, size=2500)
+trace.add_rss_stat(ts=503, tid=8, member=swap_member, size=2500)
+trace.add_kernel_lmk(ts=504, tid=9)
+
+# Dummy trace event to ensure the trace does not end on an LMK.
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=1001, oom_score_adj=-800, pid=2)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_mem_by_priority.out b/test/metrics/android_mem_by_priority.out
similarity index 100%
rename from test/trace_processor/memory/android_mem_by_priority.out
rename to test/metrics/android_mem_by_priority.out
diff --git a/test/metrics/android_mem_by_priority.py b/test/metrics/android_mem_by_priority.py
new file mode 100644
index 0000000..6680e90
--- /dev/null
+++ b/test/metrics/android_mem_by_priority.py
@@ -0,0 +1,57 @@
+#!/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_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/trace_processor/memory/android_mem_counters.out b/test/metrics/android_mem_counters.out
similarity index 100%
rename from test/trace_processor/memory/android_mem_counters.out
rename to test/metrics/android_mem_counters.out
diff --git a/test/trace_processor/memory/android_mem_lmk.out b/test/metrics/android_mem_lmk.out
similarity index 100%
rename from test/trace_processor/memory/android_mem_lmk.out
rename to test/metrics/android_mem_lmk.out
diff --git a/test/trace_processor/parsing/android_package_list.out b/test/metrics/android_package_list.out
similarity index 100%
rename from test/trace_processor/parsing/android_package_list.out
rename to test/metrics/android_package_list.out
diff --git a/test/metrics/android_package_list.py b/test/metrics/android_package_list.py
new file mode 100644
index 0000000..e8dd0ae
--- /dev/null
+++ b/test/metrics/android_package_list.py
@@ -0,0 +1,24 @@
+#!/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_startup.out b/test/metrics/android_startup.out
new file mode 100644
index 0000000..ea6ce94
--- /dev/null
+++ b/test/metrics/android_startup.out
@@ -0,0 +1,38 @@
+android_startup {
+  startup {
+    startup_id: 2
+    package_name: "com.google.android.calendar"
+    process_name: "com.google.android.calendar"
+    process: {
+      name: "com.google.android.calendar"
+      uid: 10001
+      package {
+        package_name: "com.google.android.calendar"
+        apk_version_code: 123
+        debuggable: false
+      }
+      packages_for_uid {
+        package_name: "com.google.android.calendar"
+        apk_version_code: 123
+        debuggable: false
+      }
+    }
+    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
+        dur_ms: 8e-06
+      }
+      dur_ms: 0.000108
+    }
+  }
+}
diff --git a/test/metrics/android_startup.py b/test/metrics/android_startup.py
new file mode 100644
index 0000000..a6a94bb
--- /dev/null
+++ b/test/metrics/android_startup.py
@@ -0,0 +1,90 @@
+#!/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()
+trace.add_process(1, 0, 'init')
+trace.add_process(2, 1, 'system_server')
+trace.add_process(3, 1, 'com.google.android.calendar', 10001)
+trace.add_process(4, 1, 'com.google.android.calendar')
+
+trace.add_package_list(
+    ts=1, name='com.google.android.calendar', uid=10001, version_code=123)
+
+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
new file mode 100644
index 0000000..507fe12
--- /dev/null
+++ b/test/metrics/android_startup_battery.py
@@ -0,0 +1,27 @@
+#!/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
new file mode 100644
index 0000000..e26b0b3
--- /dev/null
+++ b/test/metrics/android_startup_breakdown.out
@@ -0,0 +1,43 @@
+android_startup {
+  startup {
+    startup_id: 1
+    package_name: "com.google.android.calendar"
+    process_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
+        dur_ms: 8e-06
+      }
+      time_bind_application {
+        dur_ns: 10
+        dur_ms: 1e-05
+      }
+      time_before_start_process {
+        dur_ns: 18
+        dur_ms: 1.8e-05
+      }
+      time_during_start_process {
+        dur_ns: 35
+        dur_ms: 3.5e-05
+      }
+      dur_ms: 0.000108
+      to_bind_application {
+        dur_ns: 83
+        dur_ms: 8.3e-05
+      }
+    }
+    activity_hosting_process_count: 1
+  }
+}
diff --git a/test/metrics/android_startup_breakdown.py b/test/metrics/android_startup_breakdown.py
new file mode 100644
index 0000000..8325284
--- /dev/null
+++ b/test/metrics/android_startup_breakdown.py
@@ -0,0 +1,57 @@
+#!/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()
+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/trace_processor/startup/android_startup_cpu.out b/test/metrics/android_startup_cpu.out
similarity index 100%
rename from test/trace_processor/startup/android_startup_cpu.out
rename to test/metrics/android_startup_cpu.out
diff --git a/test/metrics/android_startup_cpu.py b/test/metrics/android_startup_cpu.py
new file mode 100644
index 0000000..75aa7b6
--- /dev/null
+++ b/test/metrics/android_startup_cpu.py
@@ -0,0 +1,61 @@
+#!/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_system_info(fingerprint="fingerprint/walleye/P")
+
+trace.add_ftrace_packet(cpu=0)
+
+# CPU counters for CPU 0.
+trace.add_cpufreq(ts=9 * 1000000, freq=500000, cpu=0)
+trace.add_cpufreq(ts=15 * 1000000, freq=1400000, cpu=0)
+trace.add_cpufreq(ts=17 * 1000000, freq=2500000, cpu=0)
+
+# CPU counters for CPU 6.
+trace.add_cpufreq(ts=11 * 1000000, freq=2000000, cpu=6)
+trace.add_cpufreq(ts=15 * 1000000, freq=8000000, cpu=6)
+
+# Add 3 processes. This also adds one main thread per process.
+trace.add_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 * 1000000, prev_pid=0, next_pid=1)
+trace.add_sched(ts=12 * 1000000, prev_pid=1, next_pid=3)
+trace.add_sched(ts=16 * 1000000, prev_pid=3, next_pid=4)
+trace.add_sched(ts=17 * 1000000, prev_pid=4, next_pid=2)
+trace.add_sched(ts=19 * 1000000, prev_pid=2, next_pid=0)
+
+# Schedule threads in CPU 6.
+trace.add_ftrace_packet(cpu=6)
+trace.add_sched(ts=11 * 1000000, prev_pid=0, next_pid=5)
+trace.add_sched(ts=13 * 1000000, prev_pid=5, next_pid=6)
+trace.add_sched(ts=16 * 1000000, prev_pid=6, next_pid=3)
+trace.add_sched(ts=18 * 1000000, prev_pid=3, next_pid=0)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_powrails.out b/test/metrics/android_startup_powrails.out
similarity index 100%
rename from test/trace_processor/startup/android_startup_powrails.out
rename to test/metrics/android_startup_powrails.out
diff --git a/test/metrics/android_startup_powrails.py b/test/metrics/android_startup_powrails.py
new file mode 100644
index 0000000..f729ebd
--- /dev/null
+++ b/test/metrics/android_startup_powrails.py
@@ -0,0 +1,39 @@
+#!/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
new file mode 100644
index 0000000..3a3d5a8
--- /dev/null
+++ b/test/metrics/android_startup_process_track.out
@@ -0,0 +1,52 @@
+android_startup {
+  startup {
+    startup_id: 1
+    package_name: "com.google.android.calendar"
+    process_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
+        dur_ms: 2e-06
+      }
+      dur_ms: 4e-06
+    }
+    activity_hosting_process_count: 1
+  }
+  startup {
+    startup_id: 2
+    package_name: "com.google.android.calendar"
+    process_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
+        dur_ms: 2e-06
+      }
+      dur_ms: 4e-06
+    }
+    activity_hosting_process_count: 1
+  }
+}
diff --git a/test/metrics/android_startup_process_track.py b/test/metrics/android_startup_process_track.py
new file mode 100644
index 0000000..a65406f
--- /dev/null
+++ b/test/metrics/android_startup_process_track.py
@@ -0,0 +1,59 @@
+#!/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_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/trace_processor/tables/android_task_names.out b/test/metrics/android_task_names.out
similarity index 100%
rename from test/trace_processor/tables/android_task_names.out
rename to test/metrics/android_task_names.out
diff --git a/test/metrics/android_thread_time_in_state.out b/test/metrics/android_thread_time_in_state.out
new file mode 100644
index 0000000..1da6c89
--- /dev/null
+++ b/test/metrics/android_thread_time_in_state.out
@@ -0,0 +1,59 @@
+android_thread_time_in_state {
+  processes {
+    metadata {
+      name: "com.google.pid5"
+    }
+    metrics_by_core_type {
+      core_type: "unknown"
+      runtime_ms: 20
+    }
+    threads {
+      main_thread: true
+      metrics_by_core_type {
+        core_type: "unknown"
+        runtime_ms: 20
+      }
+    }
+  }
+  processes {
+    metadata {
+      name: "com.google.pid11"
+    }
+    metrics_by_core_type {
+      core_type: "unknown"
+      runtime_ms: 20
+    }
+    threads {
+      name: "tid11"
+      main_thread: true
+      metrics_by_core_type {
+        core_type: "unknown"
+        runtime_ms: 10
+      }
+    }
+    threads {
+      name: "tid12"
+      main_thread: false
+      metrics_by_core_type {
+        core_type: "unknown"
+        runtime_ms: 10
+      }
+    }
+  }
+  processes {
+    metadata {
+      name: "com.google.pid17"
+    }
+    metrics_by_core_type {
+      core_type: "unknown"
+      runtime_ms: 10
+    }
+    threads {
+      main_thread: true
+      metrics_by_core_type {
+        core_type: "unknown"
+        runtime_ms: 10
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/heap_graph_closest_proc.textproto b/test/metrics/heap_graph_closest_proc.textproto
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_closest_proc.textproto
rename to test/metrics/heap_graph_closest_proc.textproto
diff --git a/test/trace_processor/profiling/heap_profile.textproto b/test/metrics/heap_profile.textproto
similarity index 100%
rename from test/trace_processor/profiling/heap_profile.textproto
rename to test/metrics/heap_profile.textproto
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
new file mode 100644
index 0000000..6079714
--- /dev/null
+++ b/test/metrics/heap_profile_callsites.out
@@ -0,0 +1,68 @@
+heap_profile_callsites {
+  instance_stats {
+    pid: 2
+    process_name: "system_server"
+    process {
+      name: "system_server"
+      uid: 1000
+    }
+    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/trace_processor/profiling/heap_profile_no_symbols.textproto b/test/metrics/heap_profile_no_symbols.textproto
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_no_symbols.textproto
rename to test/metrics/heap_profile_no_symbols.textproto
diff --git a/test/trace_processor/profiling/heap_stats_closest_proc.out b/test/metrics/heap_stats_closest_proc.out
similarity index 100%
rename from test/trace_processor/profiling/heap_stats_closest_proc.out
rename to test/metrics/heap_stats_closest_proc.out
diff --git a/test/metrics/index b/test/metrics/index
new file mode 100644
index 0000000..06e9170
--- /dev/null
+++ b/test/metrics/index
@@ -0,0 +1,37 @@
+# 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_lmk.py android_lmk android_mem_lmk.out
+android_lmk_reason.py android_lmk_reason android_lmk_reason.out
+../trace_processor/oom_kill.textproto android_lmk android_lmk_oom.out
+
+android_ion.py android_ion android_ion.out
+android_ion_stat.textproto android_ion android_ion_stat.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
+heap_graph_closest_proc.textproto java_heap_stats heap_stats_closest_proc.out
+../trace_processor/heap_graph.textproto java_heap_histogram java_heap_histogram.out
+obfuscated_heap_graph.textproto unmapped_java_symbols unmapped_java_symbols.out
+
+# Json output
+../data/memory_counters.pb trace_metadata trace_metadata.json.out
+
+process_uids.textproto android_task_names android_task_names.out
+
+../trace_processor/thread_time_in_state.textproto android_thread_time_in_state android_thread_time_in_state.out
diff --git a/test/metrics/java_heap_histogram.out b/test/metrics/java_heap_histogram.out
new file mode 100644
index 0000000..8558371
--- /dev/null
+++ b/test/metrics/java_heap_histogram.out
@@ -0,0 +1,37 @@
+java_heap_histogram {
+  instance_stats {
+    upid: 2
+    process {
+      name: "system_server"
+      uid: 1000
+    }
+    samples {
+      ts: 10
+      type_count {
+        type_name: "DeobfuscatedA"
+        obj_count: 1
+        reachable_obj_count: 0
+      }
+      type_count {
+        type_name: "DeobfuscatedA[]"
+        obj_count: 1
+        reachable_obj_count: 1
+      }
+      type_count {
+        type_name: "FactoryProducerDelegateImplActor"
+        obj_count: 1
+        reachable_obj_count: 1
+      }
+      type_count {
+        type_name: "Foo"
+        obj_count: 2
+        reachable_obj_count: 1
+      }
+      type_count {
+        type_name: "java.lang.Class<DeobfuscatedA[]>"
+        obj_count: 1
+        reachable_obj_count: 0
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/java_heap_stats.out b/test/metrics/java_heap_stats.out
similarity index 100%
rename from test/trace_processor/profiling/java_heap_stats.out
rename to test/metrics/java_heap_stats.out
diff --git a/test/metrics/obfuscated_heap_graph.textproto b/test/metrics/obfuscated_heap_graph.textproto
new file mode 100644
index 0000000..4eb9ecf
--- /dev/null
+++ b/test/metrics/obfuscated_heap_graph.textproto
@@ -0,0 +1,76 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "com.google.android.gm"
+      uid: 10001
+    }
+  }
+}
+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: 0x02
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 3
+      self_size: 32
+    }
+    continued: true
+    index: 1
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  heap_graph {
+    pid: 2
+    type_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor"
+    }
+    type_names {
+      iid: 2
+      str: "a"
+    }
+    type_names {
+      iid: 3
+      str: "java.lang.Class<abc[]>"
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.a"
+    }
+    field_names {
+      iid: 2
+      str: "FactoryProducerDelegateImplActor FactoryProducerDelegateImplActor.b"
+    }
+    continued: false
+    index: 2
+  }
+}
diff --git a/test/trace_processor/tables/process_uids.textproto b/test/metrics/process_uids.textproto
similarity index 100%
rename from test/trace_processor/tables/process_uids.textproto
rename to test/metrics/process_uids.textproto
diff --git a/test/metrics/trace_metadata.json.out b/test/metrics/trace_metadata.json.out
new file mode 100644
index 0000000..031db4c
--- /dev/null
+++ b/test/metrics/trace_metadata.json.out
@@ -0,0 +1,12 @@
+{
+  "trace_metadata": {
+    "error_stats_entry": [
+      {
+        "name": "mismatched_sched_switch_tids",
+        "value": 5
+      }
+    ],
+    "trace_duration_ns": 9519159074,
+    "trace_size_bytes": 6365447
+  }
+}
diff --git a/test/metrics/trace_metadata.out b/test/metrics/trace_metadata.out
new file mode 100644
index 0000000..80d5bad
--- /dev/null
+++ b/test/metrics/trace_metadata.out
@@ -0,0 +1,8 @@
+trace_metadata {
+  error_stats_entry {
+    name: "mismatched_sched_switch_tids"
+    value: 5
+  }
+  trace_duration_ns: 9519159074,
+  trace_size_bytes: 6365447
+}
diff --git a/test/metrics/unmapped_java_symbols.out b/test/metrics/unmapped_java_symbols.out
new file mode 100644
index 0000000..4628dd9
--- /dev/null
+++ b/test/metrics/unmapped_java_symbols.out
@@ -0,0 +1,18 @@
+unmapped_java_symbols {
+  process_symbols {
+    process_metadata {
+      name: "com.google.android.gm"
+      uid: 10001
+    }
+    type_name: "FactoryProducerDelegateImplActor"
+    type_name: "a"
+    type_name: "abc"
+    field {
+      field_name: "FactoryProducerDelegateImplActor.a"
+    }
+    field {
+      field_name: "FactoryProducerDelegateImplActor.b"
+      field_type_name: "FactoryProducerDelegateImplActor"
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/unsymbolized_frames.out b/test/metrics/unsymbolized_frames.out
similarity index 100%
rename from test/trace_processor/profiling/unsymbolized_frames.out
rename to test/metrics/unsymbolized_frames.out
diff --git a/test/producer_socket_fuzzer.cc b/test/producer_socket_fuzzer.cc
index 9056122..5f7bc3a 100644
--- a/test/producer_socket_fuzzer.cc
+++ b/test/producer_socket_fuzzer.cc
@@ -62,8 +62,8 @@
       data, size, task_runner.CreateCheckpoint("data_sent"));
 
   std::unique_ptr<base::UnixSocket> sock = base::UnixSocket::Connect(
-      helper.GetDefaultModeProducerSocketName(), &fake_event_listener,
-      &task_runner, base::SockFamily::kUnix, base::SockType::kStream);
+      helper.GetProducerSocketName(), &fake_event_listener, &task_runner,
+      base::SockFamily::kUnix, base::SockType::kStream);
 
   task_runner.RunUntilCheckpoint("data_sent");
   return 0;
diff --git a/test/stress_test/BUILD.gn b/test/stress_test/BUILD.gn
deleted file mode 100644
index a5fa275..0000000
--- a/test/stress_test/BUILD.gn
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../gn/perfetto.gni")
-
-executable("stress_test") {
-  testonly = true
-  sources = [ "stress_test.cc" ]
-  data_deps = [
-    "../../src/perfetto_cmd:perfetto",
-    "../../src/traced/service:traced",
-  ]
-  deps = [
-    ":stress_producer",
-    "../..:libperfetto_client_experimental",
-    "../../gn:default_deps",
-    "../../include/perfetto/tracing",
-    "../../protos/perfetto/trace:zero",
-    "../../src/base",
-    "../../src/base:test_support",
-    "configs",
-  ]
-}
-
-executable("stress_producer") {
-  testonly = true
-  sources = [ "stress_producer.cc" ]
-  deps = [
-    "../..:libperfetto_client_experimental",
-    "../../gn:default_deps",
-    "../../include/perfetto/tracing",
-    "../../protos/perfetto/trace:zero",
-    "../../src/base",
-    "../../src/base:test_support",
-  ]
-}
diff --git a/test/stress_test/README.md b/test/stress_test/README.md
deleted file mode 100644
index 70ee1c2..0000000
--- a/test/stress_test/README.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Perfetto Stress Test
-
-This is a test harness that to stress test the client library (DataSource-level
-only for now).
-
-The test is based on a number of configs in /test/stress_test/configs/*.cfg
-(NOTE: they must be listed in configs/BUILD.gn).
-The config is a /protos/perfetto/config/stress_test_config.proto message, which
-embeds the configuration of the test and a whole trace config.
-
-Each configs defines a testing scenario, determining the general trace config
-and all the settings of the test (e.g., how many producer processes to spawn,
-the write timings).
-
-The test is based on exec()-ing `traced` (the tracing service), `perfetto` (the
-consumer cmdline client) and a variable number of `stress_producer` instances.
-
-`stress_producer` emits events at a configurable rate, writing predictable
-sequences of numbers / string, so that the test harness can easily detect
-corruptions, out-of-order events or gaps.
-
-After running each test, the `stress_test` binary reads back the trace and
-performs a bunch of checks:
-
-- Checks that the number of sequences is exactly equal to #processes x #threads.
-- Checks that each sequence has all the expected packets in the right sequence
-- Checks the payload and correctness of proto nesting of each trace packet.
-- Reports CPU/Memory/Context-switch numbers for the service and producer
-  processes.
-
-Each test config is isolated from the others. All processes are killed and
-re-spawned for each test.
-
-The stdout/err of each process is saved in a dedicated /tmp/ folder, as well as
-the resulting trace.
-
-## Building and running the test
-
-```bash
-# This will recursively build traced, perfetto and stress_producer.
-ninja -C out/default stress_test
-
-out/default/stress_test
-```
-
-will output:
-
-```txt
-[307.909] stress_test.cc:116      Saving test results in /tmp/perfetto-ltIBJgA0
-
-===============================================================
-Config: simple
-===============================================================
-Metric               Expected   Actual
-------               --------   ------
-#Errors              0          0
-Duration [ms]        3000       3109
-Num threads          1          1
-Num packets          1000       1001
-Trace size [KB]      168        170
-Svc RSS [MB]         4          2
-Prod RSS [MB]        ---        1
-Svc CPU [ms]         ---        10
-Prod CPU [ms]        ---        32
-Svc #ctxswitch       ---        103 / 20
-Prod #ctxswitch      ---        1022 / 1
-
-===============================================================
-Config: bursts
-===============================================================
-Metric               Expected   Actual
-------               --------   ------
-#Errors              0          0
-Duration [ms]        2000       2381
-Num threads          10         10
-Num packets          2675       20021
-Trace size [KB]      449        11063
-Svc RSS [MB]         32         17
-Prod RSS [MB]        ---        1
-Svc CPU [ms]         ---        98
-Prod CPU [ms]        ---        17
-Svc #ctxswitch       ---        704 / 1327
-Prod #ctxswitch      ---        421 / 1
-```
-
-```bash
-$ ls -Rlh /tmp/perfetto-ltIBJgA0
-total 0
-drwxr-xr-x  16 primiano  wheel   512B  5 Aug 09:16 bursts
-drwxr-xr-x   9 primiano  wheel   288B  5 Aug 09:16 simple
-drwxr-xr-x  38 primiano  wheel   1.2K  5 Aug 09:16 the_storm
-
-/tmp/perfetto-ltIBJgA0/bursts:
-total 22752
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 errors.log
--rw-r--r--  1 primiano  wheel   180B  5 Aug 09:16 perfetto.log
--rw-r--r--  1 primiano  wheel   441B  5 Aug 09:16 producer.0.log
-...
--rw-r--r--  1 primiano  wheel   441B  5 Aug 09:16 producer.9.log
--rw-------  1 primiano  wheel    11M  5 Aug 09:16 trace
--rw-r--r--  1 primiano  wheel   407B  5 Aug 09:16 traced.log
-
-/tmp/perfetto-ltIBJgA0/simple:
-total 400
-srwxr-xr-x  1 primiano  wheel     0B  5 Aug 09:16 consumer.sock
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 errors.log
--rw-r--r--  1 primiano  wheel   178B  5 Aug 09:16 perfetto.log
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 producer.0.log
-srwxr-xr-x  1 primiano  wheel     0B  5 Aug 09:16 producer.sock
--rw-------  1 primiano  wheel   167K  5 Aug 09:16 trace
--rw-r--r--  1 primiano  wheel   406B  5 Aug 09:16 traced.log
-
-/tmp/perfetto-ltIBJgA0/the_storm:
-total 524432
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 errors.log
--rw-r--r--  1 primiano  wheel   184B  5 Aug 09:16 perfetto.log
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 producer.0.log
-...
--rw-r--r--  1 primiano  wheel     0B  5 Aug 09:16 producer.127.log
--rw-------  1 primiano  wheel   248M  5 Aug 09:16 trace
--rw-r--r--  1 primiano  wheel   408B  5 Aug 09:16 traced.log
-```
-
-## TODOs
-
-The following scenarios requires more coverage:
-
-- Nested messages.
-- Force losses and check that the last_dropped flag is consistent.
-- Flushes and scraping.
-- Report data losses in the test output.
-- Multibuffer scenarios.
-- write_into_file=true.
-- Vary page size, smb size.
diff --git a/test/stress_test/configs/BUILD.gn b/test/stress_test/configs/BUILD.gn
deleted file mode 100644
index 1b6110b..0000000
--- a/test/stress_test/configs/BUILD.gn
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../gn/perfetto.gni")
-
-config("include_path") {
-  include_dirs = [ target_gen_dir ]
-}
-
-action("configs") {
-  testonly = true
-
-  sources = [
-    "backfills.cfg",
-    "bursts.cfg",
-    "heavy.cfg",
-    "simple.cfg",
-    "stalls.cfg",
-    "xxl_packets.cfg",
-  ]
-
-  protoc_target = "../../../gn:protoc($host_toolchain)"
-  protoc_out_dir = get_label_info(protoc_target, "root_out_dir")
-  protoc_rel_dir = rebase_path(protoc_out_dir, root_build_dir)
-  out_header = "$target_gen_dir/stress_test_config_blobs.h"
-  out_header_rel = rebase_path(out_header, root_build_dir)
-  protoc_ext = ""
-  if (host_os == "win") {
-    protoc_ext = ".exe"
-  }
-
-  deps = [ protoc_target ]
-  script = "../gen_configs_blob.py"
-  outputs = [ out_header ]
-  args = [
-    "--protoc=$protoc_rel_dir/protoc${protoc_ext}",
-    "--out=$out_header_rel",
-  ]
-  foreach(source, sources) {
-    args += [ rebase_path(source, root_build_dir) ]
-  }
-  public_configs = [ ":include_path" ]
-}
diff --git a/test/stress_test/configs/backfills.cfg b/test/stress_test/configs/backfills.cfg
deleted file mode 100644
index 24e1b17..0000000
--- a/test/stress_test/configs/backfills.cfg
+++ /dev/null
@@ -1,24 +0,0 @@
-# TODO(primiano): this fails with the errors below, investigate.
-# FAIL: TestEvent counter mismatch for sequence 2. Expected 100 got 99
-# FAIL: TestEvent counter mismatch for sequence 3. Expected 99 got 98
-# FAIL: TestEvent counter mismatch for sequence 4. Expected 106 got 105
-# FAIL: TestEvent counter mismatch for sequence 5. Expected 107 got 106
-# FAIL: TestEvent counter mismatch for sequence 6. Expected 102 got 101
-# FAIL: TestEvent counter mismatch for sequence 7. Expected 104 got 103
-# FAIL: TestEvent counter mismatch for sequence 8. Expected 111 got 110
-# FAIL: TestEvent counter mismatch for sequence 9. Expected 109 got 108
-
-num_processes: 1
-num_threads: 8
-
-steady_state_timings {
-  rate_mean: 100
-  payload_mean: 640
-  payload_write_time_ms: 100
-}
-
-trace_config {
-  duration_ms: 10000
-  buffers { size_kb: 500000 }
-  data_sources { config { name: "perfetto.stress_test" } }
-}
diff --git a/test/stress_test/configs/bursts.cfg b/test/stress_test/configs/bursts.cfg
deleted file mode 100644
index c8a0fdf..0000000
--- a/test/stress_test/configs/bursts.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-num_processes: 10
-num_threads: 1
-
-steady_state_timings {
-  rate_mean: 10
-  payload_mean: 128
-}
-
-# 250ms every 2s enter burst mode, bumping at 1000 events/s * 512 ~= 5 MB/s
-# (per thread) ~= 50 MB/s for the 10 processes.
-burst_period_ms: 2000
-burst_duration_ms: 250
-burst_timings {
-  rate_mean: 1000
-  payload_mean: 512
-}
-
-trace_config {
-  duration_ms: 2000
-  buffers { size_kb: 20000 }
-  data_sources { config { name: "perfetto.stress_test" } }
-}
diff --git a/test/stress_test/configs/heavy.cfg b/test/stress_test/configs/heavy.cfg
deleted file mode 100644
index c137d5c..0000000
--- a/test/stress_test/configs/heavy.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-num_processes: 32
-num_threads: 10
-nesting: 10
-
-steady_state_timings {
-  rate_mean: 10
-  payload_mean: 128
-}
-
-burst_period_ms: 2000
-burst_duration_ms: 250
-burst_timings {
-  rate_mean: 1000
-  payload_mean: 128
-}
-
-trace_config {
-  duration_ms: 5000
-  buffers { size_kb: 320000 }
-  data_sources { config { name: "perfetto.stress_test" } }
-
-  producers {
-    producer_name: "stress_producer"
-    shm_size_kb: 4000
-    page_size_kb: 4
-  }
-}
diff --git a/test/stress_test/configs/simple.cfg b/test/stress_test/configs/simple.cfg
deleted file mode 100644
index 4632574..0000000
--- a/test/stress_test/configs/simple.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-num_processes: 1
-num_threads: 1
-max_events: 1000
-nesting: 8
-
-# 500 events/s, ~128 bytes/event ~= 64 KB/s
-steady_state_timings {
-  rate_mean: 500
-  payload_mean: 128
-}
-
-trace_config {
-  duration_ms: 3000
-  buffers { size_kb: 8000 }
-  data_sources { config { name: "perfetto.stress_test" } }
-}
diff --git a/test/stress_test/configs/stalls.cfg b/test/stress_test/configs/stalls.cfg
deleted file mode 100644
index 344194f..0000000
--- a/test/stress_test/configs/stalls.cfg
+++ /dev/null
@@ -1,15 +0,0 @@
-num_processes: 8
-num_threads: 4
-max_events: 10000
-
-# 1K events/s * 10K = 10 MB/s per thread
-steady_state_timings {
-  rate_mean: 1000
-  payload_mean: 10000
-}
-
-trace_config {
-  duration_ms: 5000
-  buffers { size_kb: 500000 }
-  data_sources { config { name: "perfetto.stress_test" } }
-}
diff --git a/test/stress_test/configs/xxl_packets.cfg b/test/stress_test/configs/xxl_packets.cfg
deleted file mode 100644
index fbafb2a..0000000
--- a/test/stress_test/configs/xxl_packets.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-# Four threads writing large and nested packets of 32MB each every second.
-
-num_processes: 1
-num_threads: 4
-max_events: 5
-nesting: 2
-
-# Each writer will write packets of 16 MB ((1 + nesting=1) x payload 8MB)
-steady_state_timings {
-  rate_mean: 1
-  payload_mean: 8000000
-  payload_write_time_ms: 100
-}
-
-trace_config {
-  duration_ms: 10000
-  buffers {
-    size_kb: 500000
-    fill_policy: DISCARD
-  }
-  data_sources { config { name: "perfetto.stress_test" } }
-}
diff --git a/test/stress_test/gen_configs_blob.py b/test/stress_test/gen_configs_blob.py
deleted file mode 100644
index 83b7f91..0000000
--- a/test/stress_test/gen_configs_blob.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-""" Compiles the stress_test configs protos and bundles in a .h C++ array.
-
-This scripts takes all the configs in /test/stress_test/configs, compiles them
-with protoc and generates a C++ header which contains the configs' names and
-proto-encoded bytes.
-
-This is invoked by the build system and is used by the stress_test runner. The
-goal is making the stress_test binary hermetic and not depend on the repo.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-import os
-import sys
-import argparse
-import shutil
-import subprocess
-
-CUR_DIR = os.path.dirname(os.path.realpath(__file__))
-ROOT_DIR = os.path.dirname(os.path.dirname(CUR_DIR))
-CONFIGS_DIR = os.path.join(CUR_DIR, 'configs')
-
-
-def find_protoc():
-  for root, _, files in os.walk(os.path.join(ROOT_DIR, 'out')):
-    if 'protoc' in files:
-      return os.path.join(root, 'protoc')
-  return None
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--protoc')
-  parser.add_argument('--out', required=True)
-  parser.add_argument('cfgfiles', nargs='+')
-  args = parser.parse_args()
-
-  protoc = args.protoc or find_protoc()
-  assert protoc, 'protoc not found, pass --protoc /path/to/protoc'
-  assert os.path.exists(protoc), '{} does not exist'.format(protoc)
-  if protoc is not args.protoc:
-    print('Using protoc: {}'.format(protoc))
-
-  blobs = {}
-  for cfg_path in args.cfgfiles:
-    cfg_path = cfg_path.replace('\\', '/')
-    cfg_name = os.path.splitext(cfg_path)[0].split('/')[-1]
-    with open(cfg_path, 'r') as in_file:
-      compiled_proto = subprocess.check_output([
-          protoc,
-          '--encode=perfetto.protos.StressTestConfig',
-          '--proto_path=' + ROOT_DIR,
-          os.path.join(ROOT_DIR, 'protos', 'perfetto', 'config',
-                       'stress_test_config.proto'),
-      ],
-                                               stdin=in_file)
-    blobs[cfg_name] = bytearray(compiled_proto)
-
-  # Write the C++ header file
-  fout = open(args.out, 'wb')
-  include_guard = args.out.replace('/', '_').replace('.', '_').upper() + '_'
-  fout.write("""
-#ifndef {include_guard}
-#define {include_guard}
-
-#include <stddef.h>
-#include <stdint.h>
-
-// This file was autogenerated by ${gen_script}. Do not edit.
-
-namespace perfetto {{
-namespace {{
-
-struct StressTestConfigBlob {{
-  const char* name;
-  const uint8_t* data;
-  size_t size;
-}};\n\n""".format(
-      gen_script=__file__,
-      include_guard=include_guard,
-  ).encode())
-
-  configs_arr = '\nconst StressTestConfigBlob kStressTestConfigs[] = {\n'
-  for cfg_name, blob in blobs.items():
-    arr_str = ','.join(str(b) for b in blob)
-    line = 'const uint8_t _config_%s[]{%s};\n' % (cfg_name, arr_str)
-    fout.write(line.encode())
-    configs_arr += '  {{"{n}", _config_{n}, sizeof(_config_{n})}},\n'.format(
-        n=cfg_name)
-  configs_arr += '};\n'
-  fout.write(configs_arr.encode())
-  fout.write("""
-}  // namespace
-}  // namespace perfetto
-#endif\n""".encode())
-  fout.close()
-
-
-if __name__ == '__main__':
-  exit(main())
diff --git a/test/stress_test/stress_producer.cc b/test/stress_test/stress_producer.cc
deleted file mode 100644
index 49efa6e..0000000
--- a/test/stress_test/stress_producer.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <list>
-#include <random>
-#include <thread>
-
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/tracing.h"
-
-#include "protos/perfetto/config/stress_test_config.gen.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-
-using StressTestConfig = perfetto::protos::gen::StressTestConfig;
-
-namespace perfetto {
-namespace {
-
-StressTestConfig* g_cfg;
-
-class StressTestDataSource : public DataSource<StressTestDataSource> {
- public:
-  constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
-      BufferExhaustedPolicy::kStall;
-
-  void OnSetup(const SetupArgs& args) override;
-  void OnStart(const StartArgs&) override;
-  void OnStop(const StopArgs&) override;
-
- private:
-  class Worker {
-   public:
-    explicit Worker(uint32_t id) : id_(id) {}
-    void Start();
-    void Stop();
-    ~Worker() { Stop(); }
-
-   private:
-    void WorkerMain(uint32_t worker_id);
-    void FillPayload(const StressTestConfig::WriterTiming&,
-                     uint32_t seq,
-                     uint32_t nesting,
-                     protos::pbzero::TestEvent::TestPayload*);
-
-    const uint32_t id_;
-    std::thread thread_;
-    std::atomic<bool> quit_;
-    std::minstd_rand0 rnd_seq_;
-
-    // Use a different engine for the generation of random value, keep rnd_seq_
-    // dedicated to generating deterministic sequences.
-    std::minstd_rand0 rnd_gen_;
-  };
-
-  std::list<Worker> workers_;
-};
-
-// Called before the tracing session starts.
-void StressTestDataSource::OnSetup(const SetupArgs&) {
-  for (uint32_t i = 0; i < std::max(g_cfg->num_threads(), 1u); ++i)
-    workers_.emplace_back(i);
-}
-
-// Called when the tracing session starts.
-void StressTestDataSource::OnStart(const StartArgs&) {
-  for (auto& worker : workers_)
-    worker.Start();
-}
-
-// Called when the tracing session ends.
-void StressTestDataSource::OnStop(const StopArgs&) {
-  for (auto& worker : workers_)
-    worker.Stop();
-  workers_.clear();
-}
-
-void StressTestDataSource::Worker::Start() {
-  quit_.store(false);
-  thread_ = std::thread(&StressTestDataSource::Worker::WorkerMain, this, id_);
-}
-
-void StressTestDataSource::Worker::Stop() {
-  if (!thread_.joinable() || quit_)
-    return;
-  PERFETTO_DLOG("Stopping worker %u", id_);
-  quit_.store(true);
-  thread_.join();
-}
-
-void StressTestDataSource::Worker::WorkerMain(uint32_t worker_id) {
-  PERFETTO_DLOG("Worker %u starting", worker_id);
-  rnd_seq_ = std::minstd_rand0(0);
-  int64_t t_start = base::GetBootTimeNs().count();
-  int64_t num_msgs = 0;
-
-  const int64_t max_msgs = g_cfg->max_events()
-                               ? static_cast<int64_t>(g_cfg->max_events())
-                               : INT64_MAX;
-  bool is_last = false;
-  while (!is_last) {
-    is_last = quit_ || ++num_msgs >= max_msgs;
-
-    const int64_t now = base::GetBootTimeNs().count();
-    const auto elapsed_ms = static_cast<uint64_t>((now - t_start) / 1000000);
-
-    const auto* timings = &g_cfg->steady_state_timings();
-    if (g_cfg->burst_period_ms() &&
-        elapsed_ms % g_cfg->burst_period_ms() >
-            (g_cfg->burst_period_ms() - g_cfg->burst_duration_ms())) {
-      timings = &g_cfg->burst_timings();
-    }
-    std::normal_distribution<> rate_dist{timings->rate_mean(),
-                                         timings->rate_stddev()};
-
-    double period_ns = 1e9 / rate_dist(rnd_gen_);
-    period_ns = isnan(period_ns) || period_ns == 0.0 ? 1 : period_ns;
-    double expected_msgs = static_cast<double>(now - t_start) / period_ns;
-    int64_t delay_ns = 0;
-    if (static_cast<int64_t>(expected_msgs) < num_msgs)
-      delay_ns = static_cast<int64_t>(period_ns);
-    std::this_thread::sleep_for(
-        std::chrono::nanoseconds(static_cast<int64_t>(delay_ns)));
-
-    StressTestDataSource::Trace([&](StressTestDataSource::TraceContext ctx) {
-      const uint32_t seq = static_cast<uint32_t>(rnd_seq_());
-      auto packet = ctx.NewTracePacket();
-      packet->set_timestamp(static_cast<uint64_t>(now));
-      auto* test_event = packet->set_for_testing();
-      test_event->set_seq_value(seq);
-      test_event->set_counter(static_cast<uint64_t>(num_msgs));
-      if (is_last)
-        test_event->set_is_last(true);
-
-      FillPayload(*timings, seq, g_cfg->nesting(), test_event->set_payload());
-    });  // Trace().
-
-  }  // while (!quit)
-  PERFETTO_DLOG("Worker done");
-}
-
-void StressTestDataSource::Worker::FillPayload(
-    const StressTestConfig::WriterTiming& timings,
-    uint32_t seq,
-    uint32_t nesting,
-    protos::pbzero::TestEvent::TestPayload* payload) {
-  // Write the payload in two halves, optionally with some delay in the
-  // middle.
-  std::normal_distribution<> msg_size_dist{timings.payload_mean(),
-                                           timings.payload_stddev()};
-  auto payload_size =
-      static_cast<uint32_t>(std::max(std::round(msg_size_dist(rnd_gen_)), 0.0));
-  std::string buf;
-  buf.resize(payload_size / 2);
-  for (size_t i = 0; i < buf.size(); ++i) {
-    buf[i] = static_cast<char>(33 + ((seq + i) % 64));  // Stay ASCII.
-  }
-  payload->add_str(buf);
-  payload->set_remaining_nesting_depth(nesting);
-  if (timings.payload_write_time_ms() > 0) {
-    std::this_thread::sleep_for(
-        std::chrono::milliseconds(timings.payload_write_time_ms()));
-  }
-
-  if (nesting > 0)
-    FillPayload(timings, seq, nesting - 1, payload->add_nested());
-
-  payload->add_str(buf);
-}
-}  // namespace
-
-PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(StressTestDataSource);
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(StressTestDataSource);
-
-}  // namespace perfetto
-
-int main() {
-  perfetto::TracingInitArgs args;
-  args.backends = perfetto::kSystemBackend;
-
-  std::string config_blob;
-  if (isatty(fileno(stdin)))
-    PERFETTO_LOG("Reading StressTestConfig proto from stdin");
-  perfetto::base::ReadFileStream(stdin, &config_blob);
-
-  StressTestConfig cfg;
-  perfetto::g_cfg = &cfg;
-  if (config_blob.empty() || !cfg.ParseFromString(config_blob))
-    PERFETTO_FATAL("A StressTestConfig blob must be passed into stdin");
-
-  if (cfg.shmem_page_size_kb())
-    args.shmem_page_size_hint_kb = cfg.shmem_page_size_kb();
-  if (cfg.shmem_size_kb())
-    args.shmem_page_size_hint_kb = cfg.shmem_size_kb();
-
-  perfetto::Tracing::Initialize(args);
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("perfetto.stress_test");
-  perfetto::StressTestDataSource::Register(dsd);
-
-  for (;;) {
-    std::this_thread::sleep_for(std::chrono::seconds(30));
-  }
-}
diff --git a/test/stress_test/stress_test.cc b/test/stress_test/stress_test.cc
deleted file mode 100644
index c8e9503..0000000
--- a/test/stress_test/stress_test.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdarg.h>
-
-#include <chrono>
-#include <list>
-#include <map>
-#include <random>
-#include <regex>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-#include "perfetto/ext/base/ctrl_c_handler.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/subprocess.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/tracing.h"
-#include "perfetto/tracing/core/forward_decls.h"
-#include "perfetto/tracing/core/trace_config.h"
-#include "src/base/test/utils.h"
-
-#include "protos/perfetto/config/stress_test_config.gen.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#else
-#include <signal.h>
-#endif
-
-// Generated by gen_configs_blob.py. It defines the kStressTestConfigs array,
-// which contains a proto-encoded StressTestConfig message for each .cfg file
-// listed in /test/stress_test/configs/BUILD.gn.
-#include "test/stress_test/configs/stress_test_config_blobs.h"
-
-namespace perfetto {
-namespace {
-
-// TODO(primiano): We need a base::File to get around the awkwardness of
-// files on Windows being a mix of int and HANDLE (and open() vs CreateFile())
-// in our codebase.
-base::ScopedPlatformHandle OpenLogFile(const std::string& path) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  return base::ScopedPlatformHandle(::CreateFileA(
-      path.c_str(), GENERIC_READ | GENERIC_WRITE,
-      FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS, 0, nullptr));
-#else
-  return base::OpenFile(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
-#endif
-}
-
-using StressTestConfig = protos::gen::StressTestConfig;
-
-struct SigHandlerCtx {
-  std::atomic<bool> aborted{};
-  std::vector<int> pids_to_kill;
-};
-SigHandlerCtx* g_sig;
-
-struct TestResult {
-  const char* cfg_name = nullptr;
-  StressTestConfig cfg;
-  uint32_t run_time_ms = 0;
-  uint32_t trace_size_kb = 0;
-  uint32_t num_packets = 0;
-  uint32_t num_threads = 0;
-  uint32_t num_errors = 0;
-  base::Subprocess::ResourceUsage svc_rusage;
-  base::Subprocess::ResourceUsage prod_rusage;
-};
-
-struct ParsedTraceStats {
-  struct WriterThread {
-    uint64_t packets_seen = 0;
-    bool last_seen = false;
-    uint32_t last_seq = 0;
-    uint64_t seq_errors = 0;
-    uint64_t counter_errors = 0;
-    std::minstd_rand0 rnd_engine;
-  };
-
-  // One for each trusted_packet_sequence_id.
-  std::map<uint32_t, WriterThread> threads;
-};
-
-class TestHarness {
- public:
-  TestHarness();
-  void RunConfig(const char* cfg_name, const StressTestConfig&, bool verbose);
-  const std::list<TestResult>& test_results() const { return test_results_; }
-
- private:
-  void ReadbackTrace(const std::string&, ParsedTraceStats*);
-  void ParseTracePacket(const uint8_t*, size_t, ParsedTraceStats* ctx);
-  void AddFailure(const char* fmt, ...) PERFETTO_PRINTF_FORMAT(2, 3);
-
-  std::vector<std::string> env_;
-  std::list<TestResult> test_results_;
-  std::string results_dir_;
-  base::ScopedFile error_log_;
-};
-
-TestHarness::TestHarness() {
-  results_dir_ = base::GetSysTempDir() + "/perfetto-stress-test";
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  base::ignore_result(system(("rmdir \"" + results_dir_ + "\" /s /q").c_str()));
-#else
-  base::ignore_result(system(("rm -r -- \"" + results_dir_ + "\"").c_str()));
-#endif
-  PERFETTO_CHECK(base::Mkdir(results_dir_));
-  PERFETTO_LOG("Saving test results in %s", results_dir_.c_str());
-}
-
-void TestHarness::AddFailure(const char* fmt, ...) {
-  ++test_results_.back().num_errors;
-
-  char log_msg[512];
-  va_list args;
-  va_start(args, fmt);
-  int res = vsnprintf(log_msg, sizeof(log_msg), fmt, args);
-  va_end(args);
-
-  PERFETTO_ELOG("FAIL: %s", log_msg);
-
-  if (res > 0 && static_cast<size_t>(res) < sizeof(log_msg) - 2) {
-    log_msg[res++] = '\n';
-    log_msg[res++] = '\0';
-  }
-
-  base::WriteAll(*error_log_, log_msg, static_cast<size_t>(res));
-}
-
-void TestHarness::RunConfig(const char* cfg_name,
-                            const StressTestConfig& cfg,
-                            bool verbose) {
-  test_results_.emplace_back();
-  TestResult& test_result = test_results_.back();
-  test_result.cfg_name = cfg_name;
-  test_result.cfg = cfg;
-  g_sig->pids_to_kill.clear();
-
-  auto result_dir = results_dir_ + "/" + cfg_name;
-  PERFETTO_CHECK(base::Mkdir(result_dir));
-  error_log_ = base::OpenFile(result_dir + "/errors.log",
-                              O_RDWR | O_CREAT | O_TRUNC, 0644);
-
-  PERFETTO_ILOG("Starting \"%s\" - %s", cfg_name, result_dir.c_str());
-
-  env_.emplace_back("PERFETTO_PRODUCER_SOCK_NAME=" + result_dir +
-                    "/producer.sock");
-  env_.emplace_back("PERFETTO_CONSUMER_SOCK_NAME=" + result_dir +
-                    "/consumer.sock");
-  std::string bin_dir = base::GetCurExecutableDir();
-
-  // Start the service.
-  base::Subprocess traced({bin_dir + "/traced"});
-  traced.args.env = env_;
-  if (!verbose) {
-    traced.args.out_fd = OpenLogFile(result_dir + "/traced.log");
-    traced.args.stderr_mode = traced.args.stdout_mode = base::Subprocess::kFd;
-  }
-  traced.Start();
-  g_sig->pids_to_kill.emplace_back(traced.pid());
-  std::this_thread::sleep_for(std::chrono::milliseconds(100));
-  PERFETTO_CHECK(traced.Poll() == base::Subprocess::kRunning);
-
-  // Start the producer processes.
-  std::list<base::Subprocess> producers;
-  for (uint32_t i = 0; i < cfg.num_processes(); ++i) {
-    producers.emplace_back(base::Subprocess({bin_dir + "/stress_producer"}));
-    auto& producer = producers.back();
-    producer.args.input = cfg.SerializeAsString();
-    if (!verbose) {
-      producer.args.out_fd =
-          OpenLogFile(result_dir + "/producer." + std::to_string(i) + ".log");
-      producer.args.stderr_mode = producer.args.stdout_mode =
-          base::Subprocess::kFd;
-    }
-    producer.args.env = env_;
-    producer.Start();
-    g_sig->pids_to_kill.emplace_back(producer.pid());
-  }
-  std::this_thread::sleep_for(std::chrono::milliseconds(100));
-  for (auto& producer : producers)
-    PERFETTO_CHECK(producer.Poll() == base::Subprocess::kRunning);
-
-  auto trace_file_path = result_dir + "/trace";
-  base::Subprocess consumer(
-      {bin_dir + "/perfetto", "-c", "-", "-o", trace_file_path.c_str()});
-  consumer.args.env = env_;
-  consumer.args.input = cfg.trace_config().SerializeAsString();
-  if (!verbose) {
-    consumer.args.out_fd = OpenLogFile(result_dir + "/perfetto.log");
-    consumer.args.stderr_mode = consumer.args.stdout_mode =
-        base::Subprocess::kFd;
-  }
-  remove(trace_file_path.c_str());
-  consumer.Start();
-  int64_t t_start = base::GetBootTimeNs().count();
-  g_sig->pids_to_kill.emplace_back(consumer.pid());
-
-  std::this_thread::sleep_for(std::chrono::milliseconds(100));
-  PERFETTO_CHECK(consumer.Poll() == base::Subprocess::kRunning);
-
-  if (!consumer.Wait(
-          static_cast<int>(cfg.trace_config().duration_ms() + 30000))) {
-    AddFailure("Consumer didn't quit in time");
-    consumer.KillAndWaitForTermination();
-  }
-
-  int64_t t_end = base::GetBootTimeNs().count();
-
-  for (auto& producer : producers) {
-    producer.KillAndWaitForTermination();
-    test_result.prod_rusage = producer.posix_rusage();  // Only keep last one
-  }
-  producers.clear();
-  traced.KillAndWaitForTermination();
-
-  test_result.svc_rusage = traced.posix_rusage();
-  test_result.run_time_ms = static_cast<uint32_t>((t_end - t_start) / 1000000);
-
-  // Verify
-  // TODO(primiano): read back the TraceStats and check them as well.
-  ParsedTraceStats ctx;
-  ReadbackTrace(trace_file_path, &ctx);
-  auto exp_thd = cfg.num_processes() * cfg.num_threads();
-  if (ctx.threads.size() != exp_thd) {
-    AddFailure("Trace threads mismatch. Expected %u threads, got %zu", exp_thd,
-               ctx.threads.size());
-  }
-  for (const auto& it : ctx.threads) {
-    uint32_t seq_id = it.first;
-    const auto& thd = it.second;
-    if (!thd.last_seen) {
-      AddFailure("Last packet not seen for sequence %u", seq_id);
-    }
-    if (thd.seq_errors > 0) {
-      AddFailure("Sequence %u had %" PRIu64 " packets out of sync", seq_id,
-                 thd.seq_errors);
-    }
-    if (thd.counter_errors > 0) {
-      AddFailure("Sequence %u had %" PRIu64 " packets counter errors", seq_id,
-                 thd.counter_errors);
-    }
-  }
-
-  error_log_.reset();
-  PERFETTO_ILOG("Completed \"%s\"", cfg_name);
-}
-
-void TestHarness::ReadbackTrace(const std::string& trace_file_path,
-                                ParsedTraceStats* ctx) {
-  TestResult& test_result = test_results_.back();
-  using namespace protozero::proto_utils;
-  auto fd = base::OpenFile(trace_file_path.c_str(), O_RDONLY);
-  if (!fd)
-    return AddFailure("Trace file does not exist");
-  const off_t file_size = lseek(*fd, 0, SEEK_END);
-  lseek(*fd, 0, SEEK_SET);
-  if (file_size <= 0)
-    return AddFailure("Trace file is empty");
-
-  test_result.trace_size_kb = static_cast<uint32_t>(file_size / 1000);
-  std::string trace_data;
-  PERFETTO_CHECK(base::ReadFileDescriptor(*fd, &trace_data));
-  const auto* const start = reinterpret_cast<const uint8_t*>(trace_data.data());
-  const uint8_t* const end = start + file_size;
-
-  constexpr uint8_t kTracePacketTag = MakeTagLengthDelimited(1);
-
-  for (auto* ptr = start; (end - ptr) > 2;) {
-    const uint8_t* tokenizer_start = ptr;
-    if (*(ptr++) != kTracePacketTag) {
-      return AddFailure("Tokenizer failure at offset %zd", ptr - start);
-    }
-    uint64_t packet_size = 0;
-    ptr = ParseVarInt(ptr, end, &packet_size);
-    const uint8_t* const packet_start = ptr;
-    ptr += packet_size;
-    if ((ptr - tokenizer_start) < 2 || ptr > end)
-      return AddFailure("Got invalid packet size %" PRIu64 " at offset %zd",
-                        packet_size,
-                        static_cast<ssize_t>(packet_start - start));
-    ParseTracePacket(packet_start, static_cast<size_t>(packet_size), ctx);
-  }
-  test_result.num_threads = static_cast<uint32_t>(ctx->threads.size());
-}
-
-void TestHarness::ParseTracePacket(const uint8_t* start,
-                                   size_t size,
-                                   ParsedTraceStats* ctx) {
-  TestResult& test_result = test_results_.back();
-  protos::pbzero::TracePacket::Decoder packet(start, size);
-  if (!packet.has_for_testing())
-    return;
-
-  ++test_result.num_packets;
-  const uint32_t seq_id = packet.trusted_packet_sequence_id();
-
-  protos::pbzero::TestEvent::Decoder te(packet.for_testing());
-  auto t_it = ctx->threads.find(seq_id);
-  bool is_first_packet = false;
-  if (t_it == ctx->threads.end()) {
-    is_first_packet = true;
-    t_it = ctx->threads.emplace(seq_id, ParsedTraceStats::WriterThread()).first;
-  }
-  ParsedTraceStats::WriterThread& thd = t_it->second;
-
-  ++thd.packets_seen;
-  if (te.is_last()) {
-    if (thd.last_seen) {
-      return AddFailure(
-          "last_seen=true happened more than once for sequence %u", seq_id);
-    } else {
-      thd.last_seen = true;
-    }
-  }
-  if (is_first_packet) {
-    thd.rnd_engine = std::minstd_rand0(te.seq_value());
-  } else {
-    const uint32_t expected = static_cast<uint32_t>(thd.rnd_engine());
-    if (te.seq_value() != expected) {
-      thd.rnd_engine = std::minstd_rand0(te.seq_value());  // Resync the engine.
-      ++thd.seq_errors;
-      return AddFailure(
-          "TestEvent seq mismatch for sequence %u. Expected %u got %u", seq_id,
-          expected, te.seq_value());
-    }
-    if (te.counter() != thd.packets_seen) {
-      return AddFailure(
-          "TestEvent counter mismatch for sequence %u. Expected %" PRIu64
-          " got %" PRIu64,
-          seq_id, thd.packets_seen, te.counter());
-    }
-  }
-
-  if (!te.has_payload()) {
-    return AddFailure("TestEvent %u for sequence %u has no payload",
-                      te.seq_value(), seq_id);
-  }
-
-  // Check the validity of the payload. The payload might be nested. If that is
-  // the case, we need to check all levels.
-  protozero::ConstBytes payload_bounds = te.payload();
-  for (uint32_t depth = 0, last_depth = 0;; depth++) {
-    if (depth > 100) {
-      return AddFailure("Unexpectedly deep depth for event %u, sequence %u",
-                        te.seq_value(), seq_id);
-    }
-    protos::pbzero::TestEvent::TestPayload::Decoder payload(payload_bounds);
-    const uint32_t rem_depth = payload.remaining_nesting_depth();
-
-    // The payload is a repeated field and must have exactly two instances.
-    // The writer splits it always in two halves of identical size.
-    int num_payload_pieces = 0;
-    size_t last_size = 0;
-    for (auto it = payload.str(); it; ++it, ++num_payload_pieces) {
-      protozero::ConstChars payload_str = *it;
-      last_size = last_size ? last_size : payload_str.size;
-      if (payload_str.size != last_size) {
-        return AddFailure(
-            "Asymmetrical payload at depth %u, event id %u, sequence %u. "
-            "%zu != %zu",
-            depth, te.seq_value(), seq_id, last_size, payload_str.size);
-      }
-      // Check that the payload content matches the expected sequence.
-      for (size_t i = 0; i < payload_str.size; i++) {
-        char exp = static_cast<char>(33 + ((te.seq_value() + i) % 64));
-        if (payload_str.data[i] != exp) {
-          return AddFailure(
-              "Payload mismatch at %zu, depth %u, event id %u, sequence %u. "
-              "Expected: 0x%x, Actual: 0x%x",
-              i, depth, te.seq_value(), seq_id, exp, payload_str.data[i]);
-        }
-      }
-    }
-    if (num_payload_pieces != 2) {
-      return AddFailure(
-          "Broken payload at depth %u, event id %u, sequence %u. "
-          "Expecting 2 repeated str fields, got %d",
-          depth, te.seq_value(), seq_id, num_payload_pieces);
-    }
-
-    if (depth > 0 && rem_depth != last_depth - 1) {
-      return AddFailure(
-          "Unexpected nesting level (expected: %u, actual: %u) at depth %u, "
-          "event id %u, sequence %u",
-          rem_depth, last_depth - 1, depth, te.seq_value(), seq_id);
-    }
-
-    last_depth = rem_depth;
-    if (rem_depth == 0)
-      break;
-    if (payload.has_nested()) {
-      payload_bounds = *payload.nested();
-    } else {
-      payload_bounds = {nullptr, 0};
-    }
-  }
-}
-
-void CtrlCHandler() {
-  g_sig->aborted.store(true);
-  for (auto it = g_sig->pids_to_kill.rbegin(); it != g_sig->pids_to_kill.rend();
-       it++) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    base::ScopedPlatformHandle proc_handle(
-        ::OpenProcess(PROCESS_TERMINATE, false, *it));
-    ::TerminateProcess(*proc_handle, STATUS_CONTROL_C_EXIT);
-#else
-    kill(*it, SIGKILL);
-#endif
-  }
-}
-
-void StressTestMain(int argc, char** argv) {
-  TestHarness th;
-  std::regex filter;
-  bool has_filter = false;
-
-  bool verbose = false;
-  for (int i = 1; i < argc; ++i) {
-    if (!strcmp(argv[i], "-v")) {
-      verbose = true;
-    } else {
-      filter = std::regex(argv[i], std::regex::ECMAScript | std::regex::icase);
-      has_filter = true;
-    }
-  }
-
-  g_sig = new SigHandlerCtx();
-  base::InstallCtrCHandler(&CtrlCHandler);
-
-  for (size_t i = 0; i < base::ArraySize(kStressTestConfigs) && !g_sig->aborted;
-       ++i) {
-    const auto& cfg_blob = kStressTestConfigs[i];
-    StressTestConfig cfg;
-    std::cmatch ignored;
-    if (has_filter && !std::regex_search(cfg_blob.name, ignored, filter)) {
-      continue;
-    }
-    PERFETTO_CHECK(cfg.ParseFromArray(cfg_blob.data, cfg_blob.size));
-    th.RunConfig(cfg_blob.name, cfg, verbose);
-  }
-
-  for (const auto& tres : th.test_results()) {
-    const auto& cfg = tres.cfg;
-    printf("===============================================================\n");
-    printf("Config: %s\n", tres.cfg_name);
-    printf("===============================================================\n");
-    printf("%-20s %-10s %-10s\n", "Metric", "Expected", "Actual");
-    printf("%-20s %-10s %-10s\n", "------", "--------", "------");
-    printf("%-20s %-10d %-10d\n", "#Errors", 0, tres.num_errors);
-    printf("%-20s %-10d %-10d \n", "Duration [ms]",
-           cfg.trace_config().duration_ms(), tres.run_time_ms);
-
-    uint32_t exp_threads = cfg.num_processes() * cfg.num_threads();
-    printf("%-20s %-10u %-10u\n", "Num threads", exp_threads, tres.num_threads);
-
-    double dur_s = cfg.trace_config().duration_ms() / 1e3;
-    double exp_per_thread = cfg.steady_state_timings().rate_mean() * dur_s;
-    if (cfg.burst_period_ms()) {
-      double burst_rate = 1.0 * cfg.burst_duration_ms() / cfg.burst_period_ms();
-      exp_per_thread *= 1.0 - burst_rate;
-      exp_per_thread += burst_rate * cfg.burst_timings().rate_mean() * dur_s;
-    }
-    if (cfg.max_events())
-      exp_per_thread = std::min(exp_per_thread, 1.0 * cfg.max_events());
-    double exp_packets = std::round(exp_per_thread * exp_threads);
-    printf("%-20s %-10.0f %-10d\n", "Num packets", exp_packets,
-           tres.num_packets);
-
-    double exp_size_kb = exp_packets * (cfg.nesting() + 1) *
-                         (cfg.steady_state_timings().payload_mean() + 40) /
-                         1000;
-    printf("%-20s ~%-9.0f %-10d\n", "Trace size [KB]", exp_size_kb,
-           tres.trace_size_kb);
-
-    double exp_rss_mb = cfg.trace_config().buffers()[0].size_kb() / 1000;
-    printf("%-20s (max) %-4.0f %-10d\n", "Svc RSS [MB]", exp_rss_mb,
-           tres.svc_rusage.max_rss_kb / 1000);
-    printf("%-20s %-10s %-10d\n", "Svc CPU [ms]", "---",
-           tres.svc_rusage.cpu_time_ms());
-    printf("%-20s %-10s %d / %d\n", "Svc #ctxswitch", "---",
-           tres.svc_rusage.invol_ctx_switch, tres.svc_rusage.vol_ctx_switch);
-
-    printf("%-20s %-10s %-10d\n", "Prod RSS [MB]", "---",
-           tres.prod_rusage.max_rss_kb / 1000);
-    printf("%-20s %-10s %-10d\n", "Prod CPU [ms]", "---",
-           tres.prod_rusage.cpu_time_ms());
-    printf("%-20s %-10s %d / %d\n", "Prod #ctxswitch", "---",
-           tres.prod_rusage.invol_ctx_switch, tres.prod_rusage.vol_ctx_switch);
-    printf("\n");
-  }
-}
-
-}  // namespace
-}  // namespace perfetto
-
-int main(int argc, char** argv) {
-  perfetto::StressTestMain(argc, argv);
-}
diff --git a/test/synth_common.py b/test/synth_common.py
index 0cf5fdd..52f033f 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,27 +15,18 @@
 
 import argparse
 
-from collections import namedtuple
-from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool
+from google.protobuf import descriptor, descriptor_pb2, message_factory, reflection
+from google.protobuf.pyext import _message
 
 CLONE_THREAD = 0x00010000
 CLONE_VFORK = 0x00004000
 CLONE_VM = 0x00000100
 
 
-def ms_to_ns(time_in_ms):
-  return int(time_in_ms * 1000000)
-
-
-def s_to_ns(time_in_s):
-  return int(time_in_s * 1000000000)
-
-
 class Trace(object):
 
-  def __init__(self, trace, prototypes):
+  def __init__(self, trace):
     self.trace = trace
-    self.prototypes = prototypes
     self.proc_map = {}
     self.proc_map[0] = 'idle_thread'
 
@@ -196,12 +187,10 @@
       process.uid = uid
     self.proc_map[pid] = cmdline
 
-  def add_thread(self, tid, tgid, cmdline, name=None):
+  def add_thread(self, tid, tgid, cmdline):
     thread = self.packet.process_tree.threads.add()
     thread.tid = tid
     thread.tgid = tgid
-    if name is not None:
-      thread.name = name
     self.proc_map[tid] = cmdline
 
   def add_battery_counters(self, ts, charge_uah, cap_prct, curr_ua,
@@ -255,7 +244,7 @@
     if seq_id is not None:
       packet.trusted_packet_sequence_id = seq_id
     snap = self.packet.clock_snapshot
-    for k, v in clocks.items():
+    for k, v in clocks.iteritems():
       clock = snap.clocks.add()
       clock.clock_id = k
       clock.timestamp = v
@@ -318,7 +307,6 @@
                             context,
                             render_target_handle=None,
                             render_pass_handle=None,
-                            render_subpass_index_mask=None,
                             command_buffer_handle=None,
                             submission_id=None,
                             extra_data={}):
@@ -334,9 +322,6 @@
       render_stage.render_target_handle = render_target_handle
     if render_pass_handle is not None:
       render_stage.render_pass_handle = render_pass_handle
-    if render_subpass_index_mask is not None:
-      for mask in render_subpass_index_mask:
-        render_stage.render_subpass_index_mask.append(mask)
     if command_buffer_handle is not None:
       render_stage.command_buffer_handle = command_buffer_handle
     if submission_id is not None:
@@ -404,341 +389,6 @@
       thread.cpu_freq_indices.append(index)
       thread.cpu_freq_ticks.append(freqs[index])
 
-  def add_gpu_mem_total_ftrace_event(self, pid, ts, size):
-    ftrace = self.__add_ftrace_event(ts, pid)
-    gpu_mem_total_ftrace_event = ftrace.gpu_mem_total
-    gpu_mem_total_ftrace_event.pid = pid
-    gpu_mem_total_ftrace_event.size = size
-
-  def add_gpu_mem_total_event(self, pid, ts, size):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    gpu_mem_total_event = packet.gpu_mem_total_event
-    gpu_mem_total_event.pid = pid
-    gpu_mem_total_event.size = size
-
-  def add_sched_blocked_reason(self, ts, pid, io_wait, unblock_pid):
-    ftrace = self.__add_ftrace_event(ts, unblock_pid)
-    sched_blocked_reason = ftrace.sched_blocked_reason
-    sched_blocked_reason.pid = pid
-    sched_blocked_reason.io_wait = io_wait
-
-  def add_track_event(self,
-                      name=None,
-                      ts=None,
-                      track=None,
-                      trusted_sequence_id=0,
-                      cpu_time=None):
-    packet = self.add_packet(ts=ts)
-    if name is not None:
-      packet.track_event.name = name
-    if track is not None:
-      packet.track_event.track_uuid = track
-    packet.trusted_packet_sequence_id = trusted_sequence_id
-    if cpu_time is not None:
-      packet.track_event.extra_counter_values.append(cpu_time)
-    return packet
-
-  def add_track_descriptor(self, uuid, parent=None):
-    packet = self.add_packet()
-    track_descriptor = packet.track_descriptor
-    if uuid is not None:
-      track_descriptor.uuid = uuid
-    if parent is not None:
-      track_descriptor.parent_uuid = parent
-    return packet
-
-  def add_process_track_descriptor(self, process_track, pid=None):
-    packet = self.add_track_descriptor(process_track)
-    packet.track_descriptor.process.pid = pid
-    return packet
-
-  def add_chrome_process_track_descriptor(
-      self,
-      process_track,
-      pid=None,
-      process_type=None,
-      host_app_package_name="org.chromium.chrome"):
-    if process_type is None:
-      process_type = self.prototypes.ChromeProcessDescriptor \
-        .ProcessType \
-        .PROCESS_RENDERER
-
-    packet = self.add_process_track_descriptor(process_track, pid=pid)
-    chrome_process = packet.track_descriptor.chrome_process
-    chrome_process.process_type = process_type
-    chrome_process.host_app_package_name = host_app_package_name
-    return packet
-
-  def add_thread_track_descriptor(self,
-                                  process_track,
-                                  thread_track,
-                                  trusted_packet_sequence_id=None,
-                                  pid=None,
-                                  tid=None):
-    packet = self.add_track_descriptor(thread_track, parent=process_track)
-    packet.trusted_packet_sequence_id = trusted_packet_sequence_id
-    packet.track_descriptor.thread.pid = pid
-    packet.track_descriptor.thread.tid = tid
-    return packet
-
-  def add_chrome_thread_track_descriptor(self,
-                                         process_track,
-                                         thread_track,
-                                         trusted_packet_sequence_id=None,
-                                         pid=None,
-                                         tid=None,
-                                         thread_type=None):
-    if thread_type is None:
-      thread_type = self.prototypes.ThreadDescriptor \
-        .ChromeThreadType \
-        .CHROME_THREAD_TYPE_UNSPECIFIED
-
-    packet = self.add_thread_track_descriptor(
-        process_track,
-        thread_track,
-        trusted_packet_sequence_id=trusted_packet_sequence_id,
-        pid=pid,
-        tid=tid)
-    packet.track_descriptor.thread.chrome_thread_type = thread_type
-    return packet
-
-  def add_trace_packet_defaults(self,
-                                trusted_packet_sequence_id=None,
-                                thread_track=None,
-                                counter_track=None):
-    packet = self.add_track_descriptor(None)
-    packet.trusted_packet_sequence_id = trusted_packet_sequence_id
-    track_event_defaults = packet.trace_packet_defaults.track_event_defaults
-    track_event_defaults.track_uuid = thread_track
-    track_event_defaults.extra_counter_track_uuids.append(counter_track)
-    return packet
-
-  def add_counter_track_descriptor(self,
-                                   trusted_packet_sequence_id=None,
-                                   thread_track=None,
-                                   counter_track=None):
-    packet = self.add_track_descriptor(counter_track, parent=thread_track)
-    packet.trusted_packet_sequence_id = trusted_packet_sequence_id
-    packet.track_descriptor.counter.type = self.prototypes.CounterDescriptor \
-      .BuiltinCounterType \
-      .COUNTER_THREAD_TIME_NS
-    return packet
-
-  def add_chrome_thread_with_cpu_counter(self,
-                                         process_track,
-                                         thread_track,
-                                         trusted_packet_sequence_id=None,
-                                         counter_track=None,
-                                         pid=None,
-                                         tid=None,
-                                         thread_type=None):
-    self.add_chrome_thread_track_descriptor(
-        process_track,
-        thread_track,
-        trusted_packet_sequence_id=trusted_packet_sequence_id,
-        pid=pid,
-        tid=tid,
-        thread_type=thread_type)
-    self.add_trace_packet_defaults(
-        trusted_packet_sequence_id=trusted_packet_sequence_id,
-        counter_track=counter_track,
-        thread_track=thread_track)
-
-    self.add_counter_track_descriptor(
-        trusted_packet_sequence_id=trusted_packet_sequence_id,
-        counter_track=counter_track,
-        thread_track=thread_track)
-
-  def add_track_event_slice_begin(self,
-                                  name,
-                                  ts,
-                                  track=None,
-                                  trusted_sequence_id=0,
-                                  cpu_time=None):
-    packet = self.add_track_event(
-        name,
-        ts=ts,
-        track=track,
-        trusted_sequence_id=trusted_sequence_id,
-        cpu_time=cpu_time)
-    packet.track_event.type = self.prototypes.TrackEvent.Type.TYPE_SLICE_BEGIN
-    return packet
-
-  def add_track_event_slice_end(self,
-                                ts,
-                                track=None,
-                                trusted_sequence_id=0,
-                                cpu_time=None):
-    packet = self.add_track_event(
-        ts=ts,
-        track=track,
-        trusted_sequence_id=trusted_sequence_id,
-        cpu_time=cpu_time)
-    packet.track_event.type = self.prototypes.TrackEvent.Type.TYPE_SLICE_END
-    return packet
-
-  # Returns the start slice packet.
-  def add_track_event_slice(self,
-                            name,
-                            ts,
-                            dur,
-                            track=None,
-                            trusted_sequence_id=0,
-                            cpu_start=None,
-                            cpu_delta=None):
-
-    packet = self.add_track_event_slice_begin(
-        name,
-        ts,
-        track=track,
-        trusted_sequence_id=trusted_sequence_id,
-        cpu_time=cpu_start)
-
-    if dur >= 0:
-      cpu_end = cpu_start + cpu_delta if cpu_start is not None else None
-      self.add_track_event_slice_end(
-          ts + dur,
-          track=track,
-          trusted_sequence_id=trusted_sequence_id,
-          cpu_time=cpu_end)
-
-    return packet
-
-  def add_rail_mode_slice(self, ts, dur, track, mode):
-    packet = self.add_track_event_slice(
-        "Scheduler.RAILMode", ts=ts, dur=dur, track=track)
-    packet.track_event.chrome_renderer_scheduler_state.rail_mode = mode
-
-  def add_latency_info_flow(self,
-                            ts,
-                            dur,
-                            track=None,
-                            trusted_sequence_id=None,
-                            trace_id=None,
-                            flow_ids=[],
-                            terminating_flow_ids=[]):
-    packet = self.add_track_event_slice(
-        "LatencyInfo.Flow",
-        ts,
-        dur,
-        track=track,
-        trusted_sequence_id=trusted_sequence_id)
-    if trace_id is not None:
-      packet.track_event.chrome_latency_info.trace_id = trace_id
-    for flow_id in flow_ids:
-      packet.track_event.flow_ids.append(flow_id)
-    for flow_id in terminating_flow_ids:
-      packet.track_event.terminating_flow_ids.append(flow_id)
-    return packet
-
-  def add_input_latency_event_slice(self,
-                                    name,
-                                    ts,
-                                    dur,
-                                    track=None,
-                                    trace_id=None,
-                                    gesture_scroll_id=None,
-                                    is_coalesced=None):
-    packet = self.add_track_event_slice(
-        "InputLatency::" + name, ts=ts, dur=dur, track=track)
-    packet.track_event.chrome_latency_info.trace_id = trace_id
-    packet.track_event.chrome_latency_info.gesture_scroll_id = gesture_scroll_id
-    if is_coalesced is not None:
-      packet.track_event.chrome_latency_info.is_coalesced = is_coalesced
-    return packet
-
-  def add_chrome_metadata(self, os_name=None):
-    metadata = self.add_packet().chrome_events.metadata.add()
-    if os_name is not None:
-      metadata.name = "os-name"
-      metadata.string_value = os_name
-
-    return metadata
-
-  def add_expected_display_frame_start_event(self, ts, cookie, token, pid):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    event = packet.frame_timeline_event.expected_display_frame_start
-    if token != -1:
-      event.cookie = cookie
-      event.token = token
-      event.pid = pid
-
-  def add_actual_display_frame_start_event(self, ts, cookie, token, pid,
-                                           present_type, on_time_finish,
-                                           gpu_composition, jank_type, prediction_type):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    event = packet.frame_timeline_event.actual_display_frame_start
-    if token != -1:
-      event.cookie = cookie
-      event.token = token
-      event.pid = pid
-      event.present_type = present_type
-      event.on_time_finish = on_time_finish
-      event.gpu_composition = gpu_composition
-      event.jank_type = jank_type
-      event.prediction_type = prediction_type
-
-  def add_expected_surface_frame_start_event(self, ts, cookie, token,
-                                             display_frame_token, pid,
-                                             layer_name):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    event = packet.frame_timeline_event.expected_surface_frame_start
-    if token != -1 and display_frame_token != -1:
-      event.cookie = cookie
-      event.token = token
-      event.display_frame_token = display_frame_token
-      event.pid = pid
-      event.layer_name = layer_name
-
-  def add_actual_surface_frame_start_event(self, ts, cookie, token,
-                                           display_frame_token, pid, layer_name,
-                                           present_type, on_time_finish,
-                                           gpu_composition, jank_type, prediction_type):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    event = packet.frame_timeline_event.actual_surface_frame_start
-    if token != -1 and display_frame_token != -1:
-      event.cookie = cookie
-      event.token = token
-      event.display_frame_token = display_frame_token
-      event.pid = pid
-      event.layer_name = layer_name
-      event.present_type = present_type
-      event.on_time_finish = on_time_finish
-      event.gpu_composition = gpu_composition
-      event.jank_type = jank_type
-      event.prediction_type = prediction_type
-
-  def add_frame_end_event(self, ts, cookie):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    event = packet.frame_timeline_event.frame_end
-    event.cookie = cookie
-
-
-def read_descriptor(file_name):
-  with open(file_name, 'rb') as f:
-    contents = f.read()
-
-  descriptor = descriptor_pb2.FileDescriptorSet()
-  descriptor.MergeFromString(contents)
-
-  return descriptor
-
-
-def create_pool(args):
-  trace_descriptor = read_descriptor(args.trace_descriptor)
-
-  pool = descriptor_pool.DescriptorPool()
-  for file in trace_descriptor.file:
-    pool.Add(file)
-
-  return pool
-
 
 def create_trace():
   parser = argparse.ArgumentParser()
@@ -746,37 +396,23 @@
       'trace_descriptor', type=str, help='location of trace descriptor')
   args = parser.parse_args()
 
-  pool = create_pool(args)
-  factory = message_factory.MessageFactory(pool)
-  ProtoTrace = factory.GetPrototype(
-      pool.FindMessageTypeByName('perfetto.protos.Trace'))
+  with open(args.trace_descriptor, 'rb') as t:
+    fileContent = t.read()
 
-  class EnumPrototype(object):
+  file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
+  file_desc_set_pb2.MergeFromString(fileContent)
 
-    def from_descriptor(desc):
-      res = EnumPrototype()
-      for desc in desc.values:
-        setattr(res, desc.name, desc.number)
-      return res
+  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)
 
-  Prototypes = namedtuple('Prototypes', [
-      'TrackEvent',
-      'ChromeRAILMode',
-      'ThreadDescriptor',
-      'ChromeProcessDescriptor',
-      'CounterDescriptor',
-  ])
-  prototypes = Prototypes(
-      TrackEvent=factory.GetPrototype(
-          pool.FindMessageTypeByName('perfetto.protos.TrackEvent')),
-      ChromeRAILMode=EnumPrototype.from_descriptor(
-          pool.FindEnumTypeByName('perfetto.protos.ChromeRAILMode')),
-      ThreadDescriptor=factory.GetPrototype(
-          pool.FindMessageTypeByName('perfetto.protos.ThreadDescriptor')),
-      ChromeProcessDescriptor=factory.GetPrototype(
-          pool.FindMessageTypeByName(
-              'perfetto.protos.ChromeProcessDescriptor')),
-      CounterDescriptor=factory.GetPrototype(
-          pool.FindMessageTypeByName('perfetto.protos.CounterDescriptor')),
-  )
-  return Trace(ProtoTrace(), prototypes)
+    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/test_helper.cc b/test/test_helper.cc
index ce03928..f397e8b 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -16,7 +16,7 @@
 
 #include "test/test_helper.h"
 
-#include "perfetto/base/compiler.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/tracing/core/tracing_service_state.h"
@@ -25,51 +25,24 @@
 
 namespace perfetto {
 
-namespace {
-const char* ProducerSocketForMode(TestHelper::Mode mode) {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  base::ignore_result(mode);
-  return ::perfetto::GetProducerSocket();
-#else
-  switch (mode) {
-    case TestHelper::Mode::kStartDaemons:
-      return "/data/local/tmp/traced_producer";
-    case TestHelper::Mode::kUseSystemService:
-      return ::perfetto::GetProducerSocket();
-  }
-#endif
-}
-
-const char* ConsumerSocketForMode(TestHelper::Mode mode) {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  base::ignore_result(mode);
-  return ::perfetto::GetConsumerSocket();
-#else
-  switch (mode) {
-    case TestHelper::Mode::kStartDaemons:
-      return "/data/local/tmp/traced_consumer";
-    case TestHelper::Mode::kUseSystemService:
-      return ::perfetto::GetConsumerSocket();
-  }
-#endif
-}
-}  // namespace
-
 uint64_t TestHelper::next_instance_num_ = 0;
-#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-TestHelper::Mode TestHelper::kDefaultMode = Mode::kStartDaemons;
+
+// If we're building on Android and starting the daemons ourselves,
+// create the sockets in a world-writable location.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+    PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
+#define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
+#define TEST_CONSUMER_SOCK_NAME "/data/local/tmp/traced_consumer"
 #else
-TestHelper::Mode TestHelper::kDefaultMode = Mode::kUseSystemService;
+#define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
+#define TEST_CONSUMER_SOCK_NAME ::perfetto::GetConsumerSocket()
 #endif
 
-TestHelper::TestHelper(base::TestTaskRunner* task_runner, Mode mode)
+TestHelper::TestHelper(base::TestTaskRunner* task_runner)
     : instance_num_(next_instance_num_++),
       task_runner_(task_runner),
-      mode_(mode),
-      producer_socket_(ProducerSocketForMode(mode)),
-      consumer_socket_(ConsumerSocketForMode(mode)),
-      service_thread_(producer_socket_, consumer_socket_),
-      fake_producer_thread_(producer_socket_,
+      service_thread_(TEST_PRODUCER_SOCK_NAME, TEST_CONSUMER_SOCK_NAME),
+      fake_producer_thread_(TEST_PRODUCER_SOCK_NAME,
                             WrapTask(CreateCheckpoint("producer.connect")),
                             WrapTask(CreateCheckpoint("producer.setup")),
                             WrapTask(CreateCheckpoint("producer.enabled"))) {}
@@ -82,17 +55,15 @@
   PERFETTO_FATAL("Consumer unexpectedly disconnected from the service");
 }
 
-void TestHelper::OnTracingDisabled(const std::string& /*error*/) {
+void TestHelper::OnTracingDisabled() {
   std::move(on_stop_tracing_callback_)();
-  on_stop_tracing_callback_ = nullptr;
 }
 
-void TestHelper::ReadTraceData(std::vector<TracePacket> packets) {
+void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
   for (auto& encoded_packet : packets) {
     protos::gen::TracePacket packet;
     PERFETTO_CHECK(
         packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
-    full_trace_.push_back(packet);
     if (packet.has_clock_snapshot() || packet.has_trace_config() ||
         packet.has_trace_stats() || !packet.synchronization_marker().empty() ||
         packet.has_system_info() || packet.has_service_event()) {
@@ -101,18 +72,16 @@
     PERFETTO_CHECK(packet.has_trusted_uid());
     trace_.push_back(std::move(packet));
   }
-}
 
-void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
-  ReadTraceData(std::move(packets));
   if (!has_more) {
     std::move(on_packets_finished_callback_)();
   }
 }
 
 void TestHelper::StartServiceIfRequired() {
-  if (mode_ == Mode::kStartDaemons)
-    service_thread_.Start();
+#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
+  service_thread_.Start();
+#endif
 }
 
 FakeProducer* TestHelper::ConnectFakeProducer() {
@@ -127,7 +96,8 @@
   cur_consumer_num_++;
   on_connect_callback_ = CreateCheckpoint("consumer.connected." +
                                           std::to_string(cur_consumer_num_));
-  endpoint_ = ConsumerIPCClient::Connect(consumer_socket_, this, task_runner_);
+  endpoint_ =
+      ConsumerIPCClient::Connect(TEST_CONSUMER_SOCK_NAME, this, task_runner_);
 }
 
 void TestHelper::DetachConsumer(const std::string& key) {
@@ -149,18 +119,6 @@
   return success;
 }
 
-bool TestHelper::SaveTraceForBugreportAndWait() {
-  bool success = false;
-  auto checkpoint = CreateCheckpoint("bugreport");
-  auto callback = [&success, checkpoint](bool s, const std::string&) {
-    success = s;
-    checkpoint();
-  };
-  endpoint_->SaveTraceForBugreport(callback);
-  RunUntilCheckpoint("bugreport");
-  return success;
-}
-
 void TestHelper::CreateProducerProvidedSmb() {
   fake_producer_thread_.CreateProducerProvidedSmb();
 }
@@ -179,10 +137,8 @@
 
 void TestHelper::StartTracing(const TraceConfig& config,
                               base::ScopedFile file) {
-  PERFETTO_CHECK(!on_stop_tracing_callback_);
   trace_.clear();
-  on_stop_tracing_callback_ =
-      CreateCheckpoint("stop.tracing" + std::to_string(++trace_count_));
+  on_stop_tracing_callback_ = CreateCheckpoint("stop.tracing");
   endpoint_->EnableTracing(config, std::move(file));
 }
 
@@ -204,10 +160,6 @@
   endpoint_->ReadBuffers();
 }
 
-void TestHelper::FreeBuffers() {
-  endpoint_->FreeBuffers();
-}
-
 void TestHelper::WaitForConsumerConnect() {
   RunUntilCheckpoint("consumer.connected." + std::to_string(cur_consumer_num_));
 }
@@ -221,8 +173,7 @@
 }
 
 void TestHelper::WaitForTracingDisabled(uint32_t timeout_ms) {
-  RunUntilCheckpoint(std::string("stop.tracing") + std::to_string(trace_count_),
-                     timeout_ms);
+  RunUntilCheckpoint("stop.tracing", timeout_ms);
 }
 
 void TestHelper::WaitForReadData(uint32_t read_count, uint32_t timeout_ms) {
@@ -271,13 +222,13 @@
 void TestHelper::OnObservableEvents(const ObservableEvents&) {}
 
 // static
-const char* TestHelper::GetDefaultModeConsumerSocketName() {
-  return ConsumerSocketForMode(TestHelper::kDefaultMode);
+const char* TestHelper::GetConsumerSocketName() {
+  return TEST_CONSUMER_SOCK_NAME;
 }
 
 // static
-const char* TestHelper::GetDefaultModeProducerSocketName() {
-  return ProducerSocketForMode(TestHelper::kDefaultMode);
+const char* TestHelper::GetProducerSocketName() {
+  return TEST_PRODUCER_SOCK_NAME;
 }
 
 }  // namespace perfetto
diff --git a/test/test_helper.h b/test/test_helper.h
index 4ac4c46..0e1cc62 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -17,13 +17,8 @@
 #ifndef TEST_TEST_HELPER_H_
 #define TEST_TEST_HELPER_H_
 
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/thread_task_runner.h"
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/consumer.h"
 #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
@@ -31,25 +26,14 @@
 #include "perfetto/ext/tracing/ipc/service_ipc_host.h"
 #include "perfetto/tracing/core/trace_config.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/fake_producer.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// TODO(primiano): uncomment in next CL.
-// #include "src/tracing/ipc/shared_memory_windows.h"
-#else
 #include "src/traced/probes/probes_producer.h"
 #include "src/tracing/ipc/posix_shared_memory.h"
-#endif
+#include "test/fake_producer.h"
 
 #include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 
-// This value has been bumped to 10s in Oct 2020 because the x86 cuttlefish
-// emulator is sensibly slower (up to 10x) than real hw and caused flakes.
-// See bugs duped against b/171771440.
-constexpr uint32_t kDefaultTestTimeoutMs = 10000;
-
 // This is used only in daemon starting integrations tests.
 class ServiceThread {
  public:
@@ -67,22 +51,12 @@
     runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.svc");
     runner_->PostTaskAndWaitForTesting([this]() {
       svc_ = ServiceIPCHost::CreateInstance(runner_->get());
-      if (remove(producer_socket_.c_str()) == -1) {
-        if (errno != ENOENT)
-          PERFETTO_FATAL("Failed to remove %s", producer_socket_.c_str());
-      }
-      if (remove(consumer_socket_.c_str()) == -1) {
-        if (errno != ENOENT)
-          PERFETTO_FATAL("Failed to remove %s", consumer_socket_.c_str());
-      }
-      base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket_);
-      base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket_);
+      unlink(producer_socket_.c_str());
+      unlink(consumer_socket_.c_str());
+
       bool res =
           svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
-      if (!res) {
-        PERFETTO_FATAL("Failed to start service listening on %s and %s",
-                       producer_socket_.c_str(), consumer_socket_.c_str());
-      }
+      PERFETTO_CHECK(res);
     });
   }
 
@@ -97,15 +71,6 @@
 };
 
 // This is used only in daemon starting integrations tests.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// On Windows we don't have any traced_probes, make this a no-op to avoid
-// propagating #ifdefs to the outer test.
-class ProbesProducerThread {
- public:
-  ProbesProducerThread(const std::string& /*producer_socket*/) {}
-  void Connect() {}
-};
-#else
 class ProbesProducerThread {
  public:
   ProbesProducerThread(const std::string& producer_socket)
@@ -131,7 +96,6 @@
   std::string producer_socket_;
   std::unique_ptr<ProbesProducer> producer_;
 };
-#endif  // !OS_WIN
 
 class FakeProducerThread {
  public:
@@ -167,13 +131,10 @@
   FakeProducer* producer() { return producer_.get(); }
 
   void CreateProducerProvidedSmb() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    // TODO(primiano): in next CLs introduce SharedMemoryWindows.
-#else
     PosixSharedMemory::Factory factory;
     shm_ = factory.CreateSharedMemory(1024 * 1024);
-    shm_arbiter_ = SharedMemoryArbiter::CreateUnboundInstance(shm_.get(), 4096);
-#endif
+    shm_arbiter_ =
+        SharedMemoryArbiter::CreateUnboundInstance(shm_.get(), base::kPageSize);
   }
 
   void ProduceStartupEventBatch(const protos::gen::TestConfig& config,
@@ -196,32 +157,21 @@
 
 class TestHelper : public Consumer {
  public:
-  enum class Mode {
-    kStartDaemons,
-    kUseSystemService,
-  };
-  static Mode kDefaultMode;
+  static const char* GetConsumerSocketName();
+  static const char* GetProducerSocketName();
 
-  static const char* GetDefaultModeConsumerSocketName();
-  static const char* GetDefaultModeProducerSocketName();
-
-  explicit TestHelper(base::TestTaskRunner* task_runner)
-      : TestHelper(task_runner, kDefaultMode) {}
-
-  explicit TestHelper(base::TestTaskRunner* task_runner, Mode mode);
+  explicit TestHelper(base::TestTaskRunner* task_runner);
 
   // Consumer implementation.
   void OnConnect() override;
   void OnDisconnect() override;
-  void OnTracingDisabled(const std::string& error) override;
-  virtual void ReadTraceData(std::vector<TracePacket> packets);
+  void OnTracingDisabled() override;
   void OnTraceData(std::vector<TracePacket> packets, bool has_more) override;
   void OnDetach(bool) override;
   void OnAttach(bool, const TraceConfig&) override;
   void OnTraceStats(bool, const TraceStats&) override;
   void OnObservableEvents(const ObservableEvents&) override;
 
-  // Starts the tracing service if in kStartDaemons mode.
   void StartServiceIfRequired();
 
   // Connects the producer and waits that the service has seen the
@@ -234,10 +184,8 @@
   void DisableTracing();
   void FlushAndWait(uint32_t timeout_ms);
   void ReadData(uint32_t read_count = 0);
-  void FreeBuffers();
   void DetachConsumer(const std::string& key);
   bool AttachConsumer(const std::string& key);
-  bool SaveTraceForBugreportAndWait();
   void CreateProducerProvidedSmb();
   bool IsShmemProvidedByProducer();
   void ProduceStartupEventBatch(const protos::gen::TestConfig& config);
@@ -245,9 +193,8 @@
   void WaitForConsumerConnect();
   void WaitForProducerSetup();
   void WaitForProducerEnabled();
-  void WaitForTracingDisabled(uint32_t timeout_ms = kDefaultTestTimeoutMs);
-  void WaitForReadData(uint32_t read_count = 0,
-                       uint32_t timeout_ms = kDefaultTestTimeoutMs);
+  void WaitForTracingDisabled(uint32_t timeout_ms = 5000);
+  void WaitForReadData(uint32_t read_count = 0, uint32_t timeout_ms = 5000);
   void SyncAndWaitProducer();
   TracingServiceState QueryServiceStateAndWait();
 
@@ -260,7 +207,7 @@
   }
 
   void RunUntilCheckpoint(const std::string& checkpoint,
-                          uint32_t timeout_ms = kDefaultTestTimeoutMs) {
+                          uint32_t timeout_ms = 5000) {
     return task_runner_->RunUntilCheckpoint(AddID(checkpoint), timeout_ms);
   }
 
@@ -270,9 +217,6 @@
   base::ThreadTaskRunner* producer_thread() {
     return fake_producer_thread_.runner();
   }
-  const std::vector<protos::gen::TracePacket>& full_trace() {
-    return full_trace_;
-  }
   const std::vector<protos::gen::TracePacket>& trace() { return trace_; }
 
  private:
@@ -280,7 +224,6 @@
   uint64_t instance_num_;
   base::TestTaskRunner* task_runner_ = nullptr;
   int cur_consumer_num_ = 0;
-  uint64_t trace_count_ = 0;
 
   std::function<void()> on_connect_callback_;
   std::function<void()> on_packets_finished_callback_;
@@ -288,12 +231,8 @@
   std::function<void()> on_detach_callback_;
   std::function<void(bool)> on_attach_callback_;
 
-  std::vector<protos::gen::TracePacket> full_trace_;
   std::vector<protos::gen::TracePacket> trace_;
 
-  Mode mode_;
-  const char* producer_socket_;
-  const char* consumer_socket_;
   ServiceThread service_thread_;
   FakeProducerThread fake_producer_thread_;
 
diff --git a/test/trace_processor/parsing/android_async_slice.textproto b/test/trace_processor/android_async_slice.textproto
similarity index 100%
rename from test/trace_processor/parsing/android_async_slice.textproto
rename to test/trace_processor/android_async_slice.textproto
diff --git a/test/trace_processor/parsing/android_log_counts.out b/test/trace_processor/android_log_counts.out
similarity index 100%
rename from test/trace_processor/parsing/android_log_counts.out
rename to test/trace_processor/android_log_counts.out
diff --git a/test/trace_processor/parsing/android_log_counts.sql b/test/trace_processor/android_log_counts.sql
similarity index 100%
rename from test/trace_processor/parsing/android_log_counts.sql
rename to test/trace_processor/android_log_counts.sql
diff --git a/test/trace_processor/parsing/android_log_msgs.out b/test/trace_processor/android_log_msgs.out
similarity index 100%
rename from test/trace_processor/parsing/android_log_msgs.out
rename to test/trace_processor/android_log_msgs.out
diff --git a/test/trace_processor/parsing/android_log_msgs.sql b/test/trace_processor/android_log_msgs.sql
similarity index 100%
rename from test/trace_processor/parsing/android_log_msgs.sql
rename to test/trace_processor/android_log_msgs.sql
diff --git a/test/trace_processor/parsing/android_log_ring_buffer_mode.out b/test/trace_processor/android_log_ring_buffer_mode.out
similarity index 100%
rename from test/trace_processor/parsing/android_log_ring_buffer_mode.out
rename to test/trace_processor/android_log_ring_buffer_mode.out
diff --git a/test/trace_processor/parsing/android_log_ring_buffer_mode.sql b/test/trace_processor/android_log_ring_buffer_mode.sql
similarity index 100%
rename from test/trace_processor/parsing/android_log_ring_buffer_mode.sql
rename to test/trace_processor/android_log_ring_buffer_mode.sql
diff --git a/test/trace_processor/tables/android_sched_and_ps_b119301023.out b/test/trace_processor/android_sched_and_ps_b119301023.out
similarity index 100%
rename from test/trace_processor/tables/android_sched_and_ps_b119301023.out
rename to test/trace_processor/android_sched_and_ps_b119301023.out
diff --git a/test/trace_processor/tables/android_sched_and_ps_b119496959.out b/test/trace_processor/android_sched_and_ps_b119496959.out
similarity index 100%
rename from test/trace_processor/tables/android_sched_and_ps_b119496959.out
rename to test/trace_processor/android_sched_and_ps_b119496959.out
diff --git a/test/trace_processor/parsing/android_sched_and_ps_end_reason_eq.out b/test/trace_processor/android_sched_and_ps_end_reason_eq.out
similarity index 100%
rename from test/trace_processor/parsing/android_sched_and_ps_end_reason_eq.out
rename to test/trace_processor/android_sched_and_ps_end_reason_eq.out
diff --git a/test/trace_processor/android_sched_and_ps_end_reason_match.out b/test/trace_processor/android_sched_and_ps_end_reason_match.out
new file mode 100644
index 0000000..6bc98a7
--- /dev/null
+++ b/test/trace_processor/android_sched_and_ps_end_reason_match.out
@@ -0,0 +1,3 @@
+"end_state","count(*)"
+"D",10503
+"DK",30
diff --git a/test/trace_processor/parsing/android_sched_and_ps_end_reason_neq.out b/test/trace_processor/android_sched_and_ps_end_reason_neq.out
similarity index 100%
rename from test/trace_processor/parsing/android_sched_and_ps_end_reason_neq.out
rename to test/trace_processor/android_sched_and_ps_end_reason_neq.out
diff --git a/test/trace_processor/span_join/android_sched_and_ps_slice_span_join_b118665515.out b/test/trace_processor/android_sched_and_ps_slice_span_join_b118665515.out
similarity index 100%
rename from test/trace_processor/span_join/android_sched_and_ps_slice_span_join_b118665515.out
rename to test/trace_processor/android_sched_and_ps_slice_span_join_b118665515.out
diff --git a/test/trace_processor/smoke/android_sched_and_ps_smoke.out b/test/trace_processor/android_sched_and_ps_smoke.out
similarity index 100%
rename from test/trace_processor/smoke/android_sched_and_ps_smoke.out
rename to test/trace_processor/android_sched_and_ps_smoke.out
diff --git a/test/trace_processor/tables/android_sched_and_ps_smoke_window.out b/test/trace_processor/android_sched_and_ps_smoke_window.out
similarity index 100%
rename from test/trace_processor/tables/android_sched_and_ps_smoke_window.out
rename to test/trace_processor/android_sched_and_ps_smoke_window.out
diff --git a/test/trace_processor/android_sched_and_ps_stats.out b/test/trace_processor/android_sched_and_ps_stats.out
new file mode 100644
index 0000000..609c875
--- /dev/null
+++ b/test/trace_processor/android_sched_and_ps_stats.out
@@ -0,0 +1,147 @@
+"name","idx","severity","source","value"
+"ftrace_cpu_bytes_read_begin",0,"info","trace",232
+"ftrace_cpu_bytes_read_begin",1,"info","trace",232
+"ftrace_cpu_bytes_read_begin",2,"info","trace",1548
+"ftrace_cpu_bytes_read_begin",3,"info","trace",176
+"ftrace_cpu_bytes_read_begin",4,"info","trace",0
+"ftrace_cpu_bytes_read_begin",5,"info","trace",0
+"ftrace_cpu_bytes_read_begin",6,"info","trace",0
+"ftrace_cpu_bytes_read_begin",7,"info","trace",0
+"ftrace_cpu_bytes_read_end",0,"info","trace",20468
+"ftrace_cpu_bytes_read_end",1,"info","trace",11612
+"ftrace_cpu_bytes_read_end",2,"info","trace",13884
+"ftrace_cpu_bytes_read_end",3,"info","trace",6412
+"ftrace_cpu_bytes_read_end",4,"info","trace",2676
+"ftrace_cpu_bytes_read_end",5,"info","trace",1188
+"ftrace_cpu_bytes_read_end",6,"info","trace",1576
+"ftrace_cpu_bytes_read_end",7,"info","trace",3264
+"ftrace_cpu_commit_overrun_begin",0,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",1,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",2,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",3,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",4,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",5,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",6,"error","trace",0
+"ftrace_cpu_commit_overrun_begin",7,"error","trace",0
+"ftrace_cpu_commit_overrun_end",0,"error","trace",0
+"ftrace_cpu_commit_overrun_end",1,"error","trace",0
+"ftrace_cpu_commit_overrun_end",2,"error","trace",0
+"ftrace_cpu_commit_overrun_end",3,"error","trace",0
+"ftrace_cpu_commit_overrun_end",4,"error","trace",0
+"ftrace_cpu_commit_overrun_end",5,"error","trace",0
+"ftrace_cpu_commit_overrun_end",6,"error","trace",0
+"ftrace_cpu_commit_overrun_end",7,"error","trace",0
+"ftrace_cpu_dropped_events_begin",0,"error","trace",0
+"ftrace_cpu_dropped_events_begin",1,"error","trace",0
+"ftrace_cpu_dropped_events_begin",2,"error","trace",0
+"ftrace_cpu_dropped_events_begin",3,"error","trace",0
+"ftrace_cpu_dropped_events_begin",4,"error","trace",0
+"ftrace_cpu_dropped_events_begin",5,"error","trace",0
+"ftrace_cpu_dropped_events_begin",6,"error","trace",0
+"ftrace_cpu_dropped_events_begin",7,"error","trace",0
+"ftrace_cpu_dropped_events_end",0,"error","trace",0
+"ftrace_cpu_dropped_events_end",1,"error","trace",0
+"ftrace_cpu_dropped_events_end",2,"error","trace",0
+"ftrace_cpu_dropped_events_end",3,"error","trace",0
+"ftrace_cpu_dropped_events_end",4,"error","trace",0
+"ftrace_cpu_dropped_events_end",5,"error","trace",0
+"ftrace_cpu_dropped_events_end",6,"error","trace",0
+"ftrace_cpu_dropped_events_end",7,"error","trace",0
+"ftrace_cpu_entries_begin",0,"info","trace",4
+"ftrace_cpu_entries_begin",1,"info","trace",4
+"ftrace_cpu_entries_begin",2,"info","trace",23
+"ftrace_cpu_entries_begin",3,"info","trace",4
+"ftrace_cpu_entries_begin",4,"info","trace",0
+"ftrace_cpu_entries_begin",5,"info","trace",0
+"ftrace_cpu_entries_begin",6,"info","trace",0
+"ftrace_cpu_entries_begin",7,"info","trace",0
+"ftrace_cpu_entries_end",0,"info","trace",341
+"ftrace_cpu_entries_end",1,"info","trace",195
+"ftrace_cpu_entries_end",2,"info","trace",225
+"ftrace_cpu_entries_end",3,"info","trace",111
+"ftrace_cpu_entries_end",4,"info","trace",45
+"ftrace_cpu_entries_end",5,"info","trace",21
+"ftrace_cpu_entries_end",6,"info","trace",26
+"ftrace_cpu_entries_end",7,"info","trace",54
+"ftrace_cpu_now_ts_begin",0,"info","trace",81473010735000
+"ftrace_cpu_now_ts_begin",1,"info","trace",81473010800000
+"ftrace_cpu_now_ts_begin",2,"info","trace",81473010839000
+"ftrace_cpu_now_ts_begin",3,"info","trace",81473010879000
+"ftrace_cpu_now_ts_begin",4,"info","trace",81473010921000
+"ftrace_cpu_now_ts_begin",5,"info","trace",81473010961000
+"ftrace_cpu_now_ts_begin",6,"info","trace",81473011000000
+"ftrace_cpu_now_ts_begin",7,"info","trace",81473011038000
+"ftrace_cpu_now_ts_end",0,"info","trace",81492876420000
+"ftrace_cpu_now_ts_end",1,"info","trace",81492876502000
+"ftrace_cpu_now_ts_end",2,"info","trace",81492876565000
+"ftrace_cpu_now_ts_end",3,"info","trace",81492876626000
+"ftrace_cpu_now_ts_end",4,"info","trace",81492876685000
+"ftrace_cpu_now_ts_end",5,"info","trace",81492876744000
+"ftrace_cpu_now_ts_end",6,"info","trace",81492876804000
+"ftrace_cpu_now_ts_end",7,"info","trace",81492876865000
+"ftrace_cpu_oldest_event_ts_begin",0,"info","trace",81473010620000
+"ftrace_cpu_oldest_event_ts_begin",1,"info","trace",81473009948000
+"ftrace_cpu_oldest_event_ts_begin",2,"info","trace",81473010031000
+"ftrace_cpu_oldest_event_ts_begin",3,"info","trace",81473010606000
+"ftrace_cpu_oldest_event_ts_begin",4,"info","trace",81400098010000
+"ftrace_cpu_oldest_event_ts_begin",5,"info","trace",0
+"ftrace_cpu_oldest_event_ts_begin",6,"info","trace",81400081638000
+"ftrace_cpu_oldest_event_ts_begin",7,"info","trace",81399773896000
+"ftrace_cpu_oldest_event_ts_end",0,"info","trace",81492812444000
+"ftrace_cpu_oldest_event_ts_end",1,"info","trace",81492812907000
+"ftrace_cpu_oldest_event_ts_end",2,"info","trace",81492800730000
+"ftrace_cpu_oldest_event_ts_end",3,"info","trace",81492838810000
+"ftrace_cpu_oldest_event_ts_end",4,"info","trace",81492423749000
+"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_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
+"ftrace_cpu_read_events_begin",3,"info","trace",0
+"ftrace_cpu_read_events_begin",4,"info","trace",0
+"ftrace_cpu_read_events_begin",5,"info","trace",0
+"ftrace_cpu_read_events_begin",6,"info","trace",0
+"ftrace_cpu_read_events_begin",7,"info","trace",0
+"ftrace_cpu_read_events_end",0,"info","trace",62303
+"ftrace_cpu_read_events_end",1,"info","trace",54916
+"ftrace_cpu_read_events_end",2,"info","trace",55882
+"ftrace_cpu_read_events_end",3,"info","trace",47953
+"ftrace_cpu_read_events_end",4,"info","trace",31345
+"ftrace_cpu_read_events_end",5,"info","trace",23232
+"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,"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,"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
+"traced_buf_chunks_committed_out_of_order",0,"info","trace",0
+"traced_buf_padding_bytes_cleared",0,"info","trace",0
+"traced_buf_padding_bytes_written",0,"info","trace",0
+"traced_buf_patches_failed",0,"info","trace",0
+"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/parsing/android_sched_and_ps_trace_size.out b/test/trace_processor/android_sched_and_ps_trace_size.out
similarity index 100%
rename from test/trace_processor/parsing/android_sched_and_ps_trace_size.out
rename to test/trace_processor/android_sched_and_ps_trace_size.out
diff --git a/test/trace_processor/parsing/args_string_filter_null.sql b/test/trace_processor/args_string_filter_null.sql
similarity index 100%
rename from test/trace_processor/parsing/args_string_filter_null.sql
rename to test/trace_processor/args_string_filter_null.sql
diff --git a/test/trace_processor/parsing/args_string_is_not_null.sql b/test/trace_processor/args_string_is_not_null.sql
similarity index 100%
rename from test/trace_processor/parsing/args_string_is_not_null.sql
rename to test/trace_processor/args_string_is_not_null.sql
diff --git a/test/trace_processor/parsing/args_string_is_null.sql b/test/trace_processor/args_string_is_null.sql
similarity index 100%
rename from test/trace_processor/parsing/args_string_is_null.sql
rename to test/trace_processor/args_string_is_null.sql
diff --git a/test/trace_processor/tables/b119301023.sql b/test/trace_processor/b119301023.sql
similarity index 100%
rename from test/trace_processor/tables/b119301023.sql
rename to test/trace_processor/b119301023.sql
diff --git a/test/trace_processor/tables/b119496959.sql b/test/trace_processor/b119496959.sql
similarity index 100%
rename from test/trace_processor/tables/b119496959.sql
rename to test/trace_processor/b119496959.sql
diff --git a/test/trace_processor/tables/b120278869_neg_ts_end.sql b/test/trace_processor/b120278869_neg_ts_end.sql
similarity index 100%
rename from test/trace_processor/tables/b120278869_neg_ts_end.sql
rename to test/trace_processor/b120278869_neg_ts_end.sql
diff --git a/test/trace_processor/parsing/b120487929.sql b/test/trace_processor/b120487929.sql
similarity index 100%
rename from test/trace_processor/parsing/b120487929.sql
rename to test/trace_processor/b120487929.sql
diff --git a/test/trace_processor/parsing/b120605557.sql b/test/trace_processor/b120605557.sql
similarity index 100%
rename from test/trace_processor/parsing/b120605557.sql
rename to test/trace_processor/b120605557.sql
diff --git a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.out b/test/trace_processor/chrome/actual_power_by_combined_rail_mode.out
deleted file mode 100644
index 6c6e08c..0000000
--- a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.out
+++ /dev/null
@@ -1,12 +0,0 @@
-
-"id","ts","dur","rail_mode","subsystem","joules","drain_w"
-1,0,10000000,"response","cellular",0.000000,0.000000
-1,0,10000000,"response","cpu_little",0.000140,0.014000
-2,10000000,20000000,"animation","cellular",0.000350,0.017500
-2,10000000,20000000,"animation","cpu_little",0.000140,0.007000
-3,30000000,5000000,"background","cellular",0.000018,0.003500
-3,30000000,5000000,"background","cpu_little",0.000007,0.001400
-4,35000000,10000000,"animation","cellular",0.000021,0.002100
-4,35000000,10000000,"animation","cpu_little",0.000070,0.007000
-5,45000000,10000000,"background","cellular",0.000003,0.000350
-5,45000000,10000000,"background","cpu_little",0.000070,0.007000
diff --git a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.py b/test/trace_processor/chrome/actual_power_by_combined_rail_mode.py
deleted file mode 100644
index 92beabc..0000000
--- a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-from synth_common import ms_to_ns
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-packet = trace.add_packet()
-packet = trace.add_power_rails_desc(0, "PPVAR_VPH_PWR_RF")
-packet = trace.add_power_rails_desc(1, "PPVAR_VPH_PWR_S1C")
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(20),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(30),
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_track_event_slice(
-    "task",
-    0,
-    ms_to_ns(10),
-    trusted_sequence_id=seq2,
-    cpu_start=0,
-    cpu_delta=ms_to_ns(10))
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(25),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(35),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(45),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-packet = trace.add_packet()
-
-# cellular
-packet = trace.add_power_rails_data(0, 0, 0)
-packet = trace.add_power_rails_data(10, 0, 0)
-packet = trace.add_power_rails_data(20, 0, 30)
-packet = trace.add_power_rails_data(30, 0, 50)
-packet = trace.add_power_rails_data(40, 0, 55)
-packet = trace.add_power_rails_data(50, 0, 56)
-packet = trace.add_power_rails_data(55, 0, 56)
-
-# cpu little cores
-packet = trace.add_power_rails_data(0, 1, 0)
-packet = trace.add_power_rails_data(10, 1, 20)
-packet = trace.add_power_rails_data(20, 1, 30)
-packet = trace.add_power_rails_data(30, 1, 40)
-packet = trace.add_power_rails_data(40, 1, 42)
-packet = trace.add_power_rails_data(50, 1, 60)
-packet = trace.add_power_rails_data(55, 1, 61)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.sql b/test/trace_processor/chrome/actual_power_by_combined_rail_mode.sql
deleted file mode 100644
index 9690f17..0000000
--- a/test/trace_processor/chrome/actual_power_by_combined_rail_mode.sql
+++ /dev/null
@@ -1,17 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_processes.sql') AS suppress_query_output;
--- SELECT * FROM cpu_time_by_rail_mode;
-SELECT RUN_METRIC('chrome/actual_power_by_rail_mode.sql') AS suppress_query_output;
-SELECT * FROM real_power_by_rail_mode;
diff --git a/test/trace_processor/chrome/chrome_processes.out b/test/trace_processor/chrome/chrome_processes.out
deleted file mode 100644
index 31cd59e..0000000
--- a/test/trace_processor/chrome/chrome_processes.out
+++ /dev/null
@@ -1,6 +0,0 @@
-
-"pid","name","process_type"
-18250,"Renderer","Renderer"
-17547,"Browser","Browser"
-18277,"GPU Process","Gpu"
-17578,"Browser","Browser"
diff --git a/test/trace_processor/chrome/chrome_processes.sql b/test/trace_processor/chrome/chrome_processes.sql
deleted file mode 100644
index 5ca4ded..0000000
--- a/test/trace_processor/chrome/chrome_processes.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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('chrome/chrome_processes.sql') AS suppress_query_output;
-SELECT pid, name, process_type FROM chrome_process;
diff --git a/test/trace_processor/chrome/chrome_processes_android_systrace.out b/test/trace_processor/chrome/chrome_processes_android_systrace.out
deleted file mode 100644
index 32a0f64..0000000
--- a/test/trace_processor/chrome/chrome_processes_android_systrace.out
+++ /dev/null
@@ -1,17 +0,0 @@
-
-"pid","name","process_type"
-13315,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:7","Renderer"
-10090,"com.android.chrome","Browser"
-9523,"org.chromium.chrome","Browser"
-10168,"com.android.chrome:privileged_process0","Gpu"
-8982,"com.chrome.dev","Browser"
-9065,"com.chrome.dev_zygote","Zygote"
-9102,"com.chrome.dev:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0","Renderer"
-9119,"com.chrome.dev:privileged_process0","Gpu"
-9267,"com.chrome.dev:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:1","Renderer"
-9564,"org.chromium.chrome_zygote","Zygote"
-9592,"org.chromium.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0","Renderer"
-9597,"org.chromium.chrome:privileged_process0","Privileged"
-27524,"com.android.chrome_zygote","Zygote"
-13698,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:12","Renderer"
-13736,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:13","Renderer"
diff --git a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.out b/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.out
deleted file mode 100644
index 92b2a6d..0000000
--- a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.out
+++ /dev/null
@@ -1,7 +0,0 @@
-
-"trace_id","dur","start_cpu_time","end_cpu_time","slice_cpu_time"
-2734,2000,3192921000.000000,3192923000.000000,2000.000000
-2734,258000,3192951000.000000,3193122000.000000,171000.000000
-2734,1000,3193009000.000000,3193010000.000000,1000.000000
-2734,25000,1579266000.000000,1579291000.000000,25000.000000
-2734,1000,1579284000.000000,1579286000.000000,2000.000000
diff --git a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.sql b/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.sql
deleted file mode 100644
index 10857de..0000000
--- a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time.sql
+++ /dev/null
@@ -1,29 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_thread_slice_with_cpu_time.sql')
-    AS suppress_query_output;
-
-SELECT
-  EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
-  dur,
-  start_cpu_time,
-  end_cpu_time,
-  slice_cpu_time
-FROM chrome_thread_slice_with_cpu_time
-WHERE
-  name = 'LatencyInfo.Flow' AND
-  EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') = 2734;
diff --git a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.out b/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.out
deleted file mode 100644
index 0794b25..0000000
--- a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.out
+++ /dev/null
@@ -1,9 +0,0 @@
-
-"name","ts","dur","start_cpu_time","end_cpu_time","slice_cpu_time"
-"event1_on_t1",1000,100,1000000.000000,1010000.000000,10000.000000
-"event2_on_t1",2000,200,2000000.000000,2030000.000000,30000.000000
-"event3_on_t1",2000,200,2000000.000000,2030000.000000,30000.000000
-"event4_on_t1",4000,0,2040000.000000,2040000.000000,0.000000
-"float_counter_on_t1",4300,0,"[NULL]","[NULL]","[NULL]"
-"float_counter_on_t1",4500,0,"[NULL]","[NULL]","[NULL]"
-"event1_on_t3",4000,100,10000.000000,15000.000000,5000.000000
diff --git a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.sql b/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.sql
deleted file mode 100644
index 4702b55..0000000
--- a/test/trace_processor/chrome/chrome_thread_slice_with_cpu_time_repeated.sql
+++ /dev/null
@@ -1,27 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_thread_slice_with_cpu_time.sql')
-    AS suppress_query_output;
-
-SELECT
-  name,
-  ts,
-  dur,
-  start_cpu_time,
-  end_cpu_time,
-  slice_cpu_time
-FROM chrome_thread_slice_with_cpu_time
diff --git a/test/trace_processor/chrome/chrome_threads.out b/test/trace_processor/chrome/chrome_threads.out
deleted file mode 100644
index 23e62c8..0000000
--- a/test/trace_processor/chrome/chrome_threads.out
+++ /dev/null
@@ -1,61 +0,0 @@
-
-"tid","name","is_main_thread","canonical_name"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"swapper",0,"swapper"
-17547,"CrBrowserMain",1,"CrProcessMain"
-17578,"CrBrowserMain",1,"CrProcessMain"
-18245,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18246,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18247,"Chrome_IOThread",0,"Chrome_IOThread"
-18248,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18249,"MemoryInfra",0,"MemoryInfra"
-18250,"[NULL]",1,"Unknown"
-18255,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18256,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18259,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18261,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18265,"AudioThread",0,"AudioThread"
-18273,"BrowserWatchdog",0,"BrowserWatchdog"
-18274,"NetworkService",0,"NetworkService"
-18275,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18277,"[NULL]",1,"Unknown"
-18283,"CrRendererMain",0,"CrProcessMain"
-18304,"CrGpuMain",0,"CrProcessMain"
-18305,"CompositorTileWorker1",0,"CompositorTileWorker1"
-18306,"GpuWatchdog",0,"GpuWatchdog"
-18307,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18308,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18309,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-18310,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18311,"VizCompositorThread",0,"VizCompositorThread"
-18312,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18313,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18314,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-18315,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18316,"GpuMemoryThread",0,"GpuMemoryThread"
-18317,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18318,"Compositor",0,"Compositor"
-18319,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18320,"CompositorTileWorker1",0,"CompositorTileWorker1"
-18322,"ThreadPoolSingleThreadForegroundBlocking1",0,"ThreadPoolSingleThreadForegroundBlocking1"
-18339,"Chrome_DevToolsHandlerThread",0,"Chrome_DevToolsHandlerThread"
-18483,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18508,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18509,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18510,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18511,"Chrome_IOThread",0,"Chrome_IOThread"
-18512,"MemoryInfra",0,"MemoryInfra"
-18513,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18514,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18515,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18516,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18517,"AudioThread",0,"AudioThread"
-18518,"BrowserWatchdog",0,"BrowserWatchdog"
-18519,"NetworkService",0,"NetworkService"
-18520,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18521,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18523,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18524,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18525,"ThreadPoolSingleThreadForegroundBlocking1",0,"ThreadPoolSingleThreadForegroundBlocking1"
diff --git a/test/trace_processor/chrome/chrome_threads.sql b/test/trace_processor/chrome/chrome_threads.sql
deleted file mode 100644
index 8fb2839..0000000
--- a/test/trace_processor/chrome/chrome_threads.sql
+++ /dev/null
@@ -1,17 +0,0 @@
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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('chrome/chrome_processes.sql') AS suppress_query_output;
-SELECT tid, name, is_main_thread, canonical_name
-FROM chrome_thread
-ORDER BY tid, name;
diff --git a/test/trace_processor/chrome/chrome_threads_android_systrace.out b/test/trace_processor/chrome/chrome_threads_android_systrace.out
deleted file mode 100644
index ab31779..0000000
--- a/test/trace_processor/chrome/chrome_threads_android_systrace.out
+++ /dev/null
@@ -1,410 +0,0 @@
-
-"tid","name","is_main_thread","canonical_name"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"swapper",0,"swapper"
-8982,"com.chrome.dev",1,"com.chrome.dev"
-8991,"[NULL]",0,"Unknown"
-8992,"[NULL]",0,"Unknown"
-8993,"[NULL]",0,"Unknown"
-8994,"[NULL]",0,"Unknown"
-8995,"[NULL]",0,"Unknown"
-8996,"[NULL]",0,"Unknown"
-8997,"[NULL]",0,"Unknown"
-8998,"[NULL]",0,"Unknown"
-9001,"[NULL]",0,"Unknown"
-9002,"Binder:8982_2",0,"Binder:8982_2"
-9006,"[NULL]",0,"Unknown"
-9030,"[NULL]",0,"Unknown"
-9032,"[NULL]",0,"Unknown"
-9037,"[NULL]",0,"Unknown"
-9057,"GoogleApiHandle",0,"GoogleApiHandle"
-9063,"[NULL]",0,"Unknown"
-9064,"[NULL]",0,"Unknown"
-9065,"[NULL]",1,"Unknown"
-9076,"HangWatcher",0,"HangWatcher"
-9077,"ThreadPoolServi",0,"ThreadPoolServi"
-9079,"[NULL]",0,"Unknown"
-9080,"[NULL]",0,"Unknown"
-9081,"[NULL]",0,"Unknown"
-9082,"Chrome_IOThread",0,"Chrome_IOThread"
-9084,"MemoryInfra",0,"MemoryInfra"
-9085,"[NULL]",0,"Unknown"
-9086,"PCScan",0,"PCScan"
-9089,"[NULL]",0,"Unknown"
-9092,"[NULL]",0,"Unknown"
-9093,"[NULL]",0,"Unknown"
-9094,"NetworkService",0,"NetworkService"
-9095,"[NULL]",0,"Unknown"
-9096,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9101,"[NULL]",0,"Unknown"
-9102,"[NULL]",1,"Unknown"
-9107,"[NULL]",0,"Unknown"
-9108,"[NULL]",0,"Unknown"
-9109,"[NULL]",0,"Unknown"
-9110,"[NULL]",0,"Unknown"
-9111,"[NULL]",0,"Unknown"
-9112,"[NULL]",0,"Unknown"
-9114,"[NULL]",0,"Unknown"
-9115,"[NULL]",0,"Unknown"
-9116,"[NULL]",0,"Unknown"
-9117,"[NULL]",0,"Unknown"
-9118,"[NULL]",0,"Unknown"
-9119,"[NULL]",1,"Unknown"
-9121,"[NULL]",0,"Unknown"
-9124,"[NULL]",0,"Unknown"
-9132,"[NULL]",0,"Unknown"
-9133,"[NULL]",0,"Unknown"
-9134,"[NULL]",0,"Unknown"
-9135,"[NULL]",0,"Unknown"
-9136,"[NULL]",0,"Unknown"
-9139,"[NULL]",0,"Unknown"
-9140,"[NULL]",0,"Unknown"
-9141,"[NULL]",0,"Unknown"
-9142,"[NULL]",0,"Unknown"
-9143,"[NULL]",0,"Unknown"
-9144,"[NULL]",0,"Unknown"
-9145,"[NULL]",0,"Unknown"
-9146,"[NULL]",0,"Unknown"
-9147,"SAFE_BROWSING_U",0,"SAFE_BROWSING_U"
-9148,"CrGpuMain",0,"CrProcessMain"
-9149,"CrRendererMain",0,"CrProcessMain"
-9150,"[NULL]",0,"Unknown"
-9155,"ThreadPoolServi",0,"ThreadPoolServi"
-9156,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9157,"[NULL]",0,"Unknown"
-9159,"[NULL]",0,"Unknown"
-9160,"ThreadPoolServi",0,"ThreadPoolServi"
-9161,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9162,"ThreadPoolBackg",0,"ThreadPoolBackg"
-9165,"Chrome_ChildIOT",0,"Chrome_ChildIOT"
-9166,"[NULL]",0,"Unknown"
-9167,"Chrome_ChildIOT",0,"Chrome_ChildIOT"
-9168,"[NULL]",0,"Unknown"
-9169,"[NULL]",0,"Unknown"
-9171,"[NULL]",0,"Unknown"
-9172,"[NULL]",0,"Unknown"
-9173,"[NULL]",0,"Unknown"
-9174,"[NULL]",0,"Unknown"
-9175,"[NULL]",0,"Unknown"
-9176,"StackSamplingPr",0,"StackSamplingPr"
-9177,"StackSamplingPr",0,"StackSamplingPr"
-9181,"StackSamplingPr",0,"StackSamplingPr"
-9184,"[NULL]",0,"Unknown"
-9185,"[NULL]",0,"Unknown"
-9204,"[NULL]",0,"Unknown"
-9221,"Database thread",0,"Database thread"
-9239,"[NULL]",0,"Unknown"
-9240,"[NULL]",0,"Unknown"
-9241,"[NULL]",0,"Unknown"
-9242,"[NULL]",0,"Unknown"
-9243,"[NULL]",0,"Unknown"
-9267,"[NULL]",1,"Unknown"
-9272,"[NULL]",0,"Unknown"
-9273,"[NULL]",0,"Unknown"
-9274,"[NULL]",0,"Unknown"
-9275,"[NULL]",0,"Unknown"
-9276,"[NULL]",0,"Unknown"
-9277,"[NULL]",0,"Unknown"
-9278,"[NULL]",0,"Unknown"
-9279,"[NULL]",0,"Unknown"
-9280,"[NULL]",0,"Unknown"
-9281,"[NULL]",0,"Unknown"
-9282,"[NULL]",0,"Unknown"
-9283,"[NULL]",0,"Unknown"
-9284,"[NULL]",0,"Unknown"
-9285,"[NULL]",0,"Unknown"
-9287,"CrRendererMain",0,"CrProcessMain"
-9289,"StackSamplingPr",0,"StackSamplingPr"
-9290,"ThreadPoolServi",0,"ThreadPoolServi"
-9291,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9292,"[NULL]",0,"Unknown"
-9293,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9295,"Chrome_ChildIOT",0,"Chrome_ChildIOT"
-9296,"[NULL]",0,"Unknown"
-9297,"[NULL]",0,"Unknown"
-9298,"[NULL]",0,"Unknown"
-9299,"[NULL]",0,"Unknown"
-9300,"[NULL]",0,"Unknown"
-9301,"ThreadPoolForeg",0,"ThreadPoolForeg"
-9302,"[NULL]",0,"Unknown"
-9303,"[NULL]",0,"Unknown"
-9523,"CrBrowserMain",1,"CrProcessMain"
-9533,"[NULL]",0,"Unknown"
-9534,"[NULL]",0,"Unknown"
-9535,"[NULL]",0,"Unknown"
-9536,"[NULL]",0,"Unknown"
-9537,"[NULL]",0,"Unknown"
-9538,"[NULL]",0,"Unknown"
-9539,"[NULL]",0,"Unknown"
-9540,"[NULL]",0,"Unknown"
-9542,"[NULL]",0,"Unknown"
-9543,"[NULL]",0,"Unknown"
-9544,"[NULL]",0,"Unknown"
-9545,"[NULL]",0,"Unknown"
-9551,"[NULL]",0,"Unknown"
-9558,"[NULL]",0,"Unknown"
-9559,"[NULL]",0,"Unknown"
-9562,"[NULL]",0,"Unknown"
-9563,"[NULL]",0,"Unknown"
-9564,"[NULL]",1,"Unknown"
-9574,"HangWatcher",0,"HangWatcher"
-9575,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9576,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-9579,"Chrome_IOThread",0,"Chrome_IOThread"
-9580,"[NULL]",0,"Unknown"
-9581,"[NULL]",0,"Unknown"
-9584,"[NULL]",0,"Unknown"
-9585,"[NULL]",0,"Unknown"
-9587,"NetworkService",0,"NetworkService"
-9588,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-9591,"[NULL]",0,"Unknown"
-9592,"[NULL]",1,"Unknown"
-9597,"[NULL]",1,"Unknown"
-9600,"[NULL]",0,"Unknown"
-9601,"[NULL]",0,"Unknown"
-9603,"[NULL]",0,"Unknown"
-9604,"[NULL]",0,"Unknown"
-9605,"[NULL]",0,"Unknown"
-9611,"[NULL]",0,"Unknown"
-9612,"[NULL]",0,"Unknown"
-9613,"[NULL]",0,"Unknown"
-9614,"[NULL]",0,"Unknown"
-9615,"[NULL]",0,"Unknown"
-9616,"[NULL]",0,"Unknown"
-9621,"[NULL]",0,"Unknown"
-9622,"[NULL]",0,"Unknown"
-9623,"[NULL]",0,"Unknown"
-9624,"[NULL]",0,"Unknown"
-9625,"[NULL]",0,"Unknown"
-9627,"[NULL]",0,"Unknown"
-9630,"[NULL]",0,"Unknown"
-9637,"[NULL]",0,"Unknown"
-9638,"[NULL]",0,"Unknown"
-9639,"[NULL]",0,"Unknown"
-9641,"[NULL]",0,"Unknown"
-9642,"[NULL]",0,"Unknown"
-9643,"[NULL]",0,"Unknown"
-9645,"[NULL]",0,"Unknown"
-9646,"[NULL]",0,"Unknown"
-9647,"CrRendererMain",0,"CrProcessMain"
-9654,"[NULL]",0,"Unknown"
-9655,"[NULL]",0,"Unknown"
-9666,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9667,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-9668,"[NULL]",0,"Unknown"
-9670,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-9672,"[NULL]",0,"Unknown"
-9675,"[NULL]",0,"Unknown"
-9699,"[NULL]",0,"Unknown"
-9700,"[NULL]",0,"Unknown"
-9702,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9706,"[NULL]",0,"Unknown"
-9707,"[NULL]",0,"Unknown"
-9708,"[NULL]",0,"Unknown"
-9709,"[NULL]",0,"Unknown"
-9710,"[NULL]",0,"Unknown"
-9711,"[NULL]",0,"Unknown"
-9712,"[NULL]",0,"Unknown"
-9713,"[NULL]",0,"Unknown"
-9761,"[NULL]",0,"Unknown"
-9934,"[NULL]",0,"Unknown"
-9990,"[NULL]",0,"Unknown"
-9994,"[NULL]",0,"Unknown"
-10016,"[NULL]",0,"Unknown"
-10070,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10090,"CrBrowserMain",1,"CrProcessMain"
-10099,"[NULL]",0,"Unknown"
-10100,"[NULL]",0,"Unknown"
-10101,"[NULL]",0,"Unknown"
-10102,"Jit thread pool",0,"Jit thread pool"
-10104,"HeapTaskDaemon",0,"HeapTaskDaemon"
-10105,"[NULL]",0,"Unknown"
-10106,"[NULL]",0,"Unknown"
-10107,"FinalizerWatchd",0,"FinalizerWatchd"
-10108,"[NULL]",0,"Unknown"
-10109,"Binder:10090_2",0,"Binder:10090_2"
-10110,"[NULL]",0,"Unknown"
-10111,"Profile Saver",0,"Profile Saver"
-10123,"queued-work-loo",0,"queued-work-loo"
-10124,"GoogleApiHandle",0,"GoogleApiHandle"
-10125,"RenderThread",0,"RenderThread"
-10126,"Chrome_ProcessL",0,"Chrome_ProcessL"
-10134,"[NULL]",0,"Unknown"
-10150,"GPU completion",0,"GPU completion"
-10152,"HangWatcher",0,"HangWatcher"
-10153,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-10154,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10156,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10157,"Chrome_IOThread",0,"Chrome_IOThread"
-10158,"MemoryInfra",0,"MemoryInfra"
-10159,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10161,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10162,"AudioThread",0,"AudioThread"
-10163,"BrowserWatchdog",0,"BrowserWatchdog"
-10164,"NetworkService",0,"NetworkService"
-10165,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-10168,"[NULL]",1,"Unknown"
-10178,"[NULL]",0,"Unknown"
-10179,"[NULL]",0,"Unknown"
-10180,"[NULL]",0,"Unknown"
-10181,"[NULL]",0,"Unknown"
-10182,"[NULL]",0,"Unknown"
-10183,"[NULL]",0,"Unknown"
-10184,"[NULL]",0,"Unknown"
-10185,"[NULL]",0,"Unknown"
-10186,"[NULL]",0,"Unknown"
-10187,"[NULL]",0,"Unknown"
-10188,"[NULL]",0,"Unknown"
-10189,"Binder:10168_3",0,"Binder:10168_3"
-10199,"[NULL]",0,"Unknown"
-10212,"CrGpuMain",0,"CrProcessMain"
-10213,"SAFE_BROWSING_U",0,"SAFE_BROWSING_U"
-10221,"GpuWatchdog",0,"GpuWatchdog"
-10230,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-10231,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10233,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10235,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-10236,"VizCompositorThread",0,"VizCompositorThread"
-10239,"[NULL]",0,"Unknown"
-10245,"[NULL]",0,"Unknown"
-10246,"[NULL]",0,"Unknown"
-10255,"[NULL]",0,"Unknown"
-10837,"[NULL]",0,"Unknown"
-10838,"[NULL]",0,"Unknown"
-10839,"[NULL]",0,"Unknown"
-10840,"[NULL]",0,"Unknown"
-11045,"[NULL]",0,"Unknown"
-11134,"[NULL]",0,"Unknown"
-11354,"[NULL]",0,"Unknown"
-11355,"[NULL]",0,"Unknown"
-11661,"[NULL]",0,"Unknown"
-11662,"[NULL]",0,"Unknown"
-11663,"[NULL]",0,"Unknown"
-11664,"[NULL]",0,"Unknown"
-11897,"[NULL]",0,"Unknown"
-11910,"MemoryInfra",0,"MemoryInfra"
-11911,"MemoryInfra",0,"MemoryInfra"
-11912,"MemoryInfra",0,"MemoryInfra"
-12527,"Binder:10090_4",0,"Binder:10090_4"
-12529,"[NULL]",0,"Unknown"
-12534,"Binder:10090_5",0,"Binder:10090_5"
-12535,"[NULL]",0,"Unknown"
-12548,"ThreadPoolForeg",0,"ThreadPoolForeg"
-13212,"[NULL]",0,"Unknown"
-13213,"[NULL]",0,"Unknown"
-13248,"[NULL]",0,"Unknown"
-13299,"[NULL]",0,"Unknown"
-13315,"ocessService0:7",1,"ocessService0:7"
-13326,"Runtime worker ",0,"Runtime worker "
-13327,"Runtime worker ",0,"Runtime worker "
-13328,"Runtime worker ",0,"Runtime worker "
-13329,"Runtime worker ",0,"Runtime worker "
-13331,"Signal Catcher",0,"Signal Catcher"
-13332,"perfetto_hprof_",0,"perfetto_hprof_"
-13333,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13334,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13335,"ReferenceQueueD",0,"ReferenceQueueD"
-13336,"FinalizerDaemon",0,"FinalizerDaemon"
-13337,"FinalizerWatchd",0,"FinalizerWatchd"
-13339,"Binder:13315_1",0,"Binder:13315_1"
-13340,"Binder:13315_2",0,"Binder:13315_2"
-13341,"Binder:13315_3",0,"Binder:13315_3"
-13342,"CrRendererMain",0,"CrProcessMain"
-13343,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13344,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13345,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13346,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13347,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13348,"GpuMemoryThread",0,"GpuMemoryThread"
-13349,"Compositor",0,"Compositor"
-13350,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13351,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13353,"CompositorTileWorkerBackground",0,"CompositorTileWorkerBackground"
-13371,"[NULL]",0,"Unknown"
-13517,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13518,"ReferenceQueueD",0,"ReferenceQueueD"
-13519,"FinalizerDaemon",0,"FinalizerDaemon"
-13520,"FinalizerWatchd",0,"FinalizerWatchd"
-13634,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13643,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13644,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13651,"ServiceWorker thread",0,"ServiceWorker thread"
-13655,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13669,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13670,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13671,"[NULL]",0,"Unknown"
-13672,"[NULL]",0,"Unknown"
-13673,"[NULL]",0,"Unknown"
-13696,"ThreadPoolForeg",0,"ThreadPoolForeg"
-13697,"CrGpuMain",0,"CrProcessMain"
-13698,"cessService0:12",1,"cessService0:12"
-13699,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13700,"ReferenceQueueD",0,"ReferenceQueueD"
-13701,"FinalizerDaemon",0,"FinalizerDaemon"
-13702,"FinalizerWatchd",0,"FinalizerWatchd"
-13703,"Runtime worker ",0,"Runtime worker "
-13704,"Runtime worker ",0,"Runtime worker "
-13705,"Runtime worker ",0,"Runtime worker "
-13706,"Runtime worker ",0,"Runtime worker "
-13707,"Signal Catcher",0,"Signal Catcher"
-13708,"perfetto_hprof_",0,"perfetto_hprof_"
-13709,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13710,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13711,"ReferenceQueueD",0,"ReferenceQueueD"
-13712,"FinalizerDaemon",0,"FinalizerDaemon"
-13713,"FinalizerWatchd",0,"FinalizerWatchd"
-13714,"Binder:13698_1",0,"Binder:13698_1"
-13715,"Binder:13698_2",0,"Binder:13698_2"
-13716,"Binder:13698_3",0,"Binder:13698_3"
-13717,"CrRendererMain",0,"CrProcessMain"
-13718,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13720,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13721,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13722,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13723,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13724,"GpuMemoryThread",0,"GpuMemoryThread"
-13725,"Compositor",0,"Compositor"
-13726,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13727,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13728,"CompositorTileW",0,"CompositorTileW"
-13729,"ThreadPoolForeg",0,"ThreadPoolForeg"
-13736,"cessService0:13",1,"cessService0:13"
-13737,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13738,"ReferenceQueueD",0,"ReferenceQueueD"
-13739,"FinalizerDaemon",0,"FinalizerDaemon"
-13740,"FinalizerWatchd",0,"FinalizerWatchd"
-13741,"Runtime worker ",0,"Runtime worker "
-13742,"Runtime worker ",0,"Runtime worker "
-13743,"Runtime worker ",0,"Runtime worker "
-13744,"Runtime worker ",0,"Runtime worker "
-13745,"Signal Catcher",0,"Signal Catcher"
-13746,"perfetto_hprof_",0,"perfetto_hprof_"
-13747,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13748,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13749,"ReferenceQueueD",0,"ReferenceQueueD"
-13750,"FinalizerDaemon",0,"FinalizerDaemon"
-13751,"FinalizerWatchd",0,"FinalizerWatchd"
-13752,"Binder:13736_1",0,"Binder:13736_1"
-13753,"Binder:13736_2",0,"Binder:13736_2"
-13754,"Binder:13736_3",0,"Binder:13736_3"
-13755,"CrRendererMain",0,"CrProcessMain"
-13756,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13757,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13758,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13759,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13760,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13761,"GpuMemoryThread",0,"GpuMemoryThread"
-13763,"Compositor",0,"Compositor"
-13765,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13766,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13767,"CompositorTileWorkerBackground",0,"CompositorTileWorkerBackground"
-13781,"CrGpuMain",0,"CrProcessMain"
-13795,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13796,"ThreadPoolForeg",0,"ThreadPoolForeg"
-27524,"d.chrome_zygote",1,"d.chrome_zygote"
diff --git a/test/trace_processor/chrome/combined_rail_modes.out b/test/trace_processor/chrome/combined_rail_modes.out
deleted file mode 100644
index b1b6a29..0000000
--- a/test/trace_processor/chrome/combined_rail_modes.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"id","ts","dur","rail_mode"
-1,0,10000,"response"
-2,10000,25000,"animation"
-3,35000,10000,"background"
diff --git a/test/trace_processor/chrome/combined_rail_modes.py b/test/trace_processor/chrome/combined_rail_modes.py
deleted file mode 100644
index 565b97c..0000000
--- a/test/trace_processor/chrome/combined_rail_modes.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-track1 = 1234
-track2 = 4567
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=20000,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=30000,
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=25000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=25000,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=35000,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/combined_rail_modes.sql b/test/trace_processor/chrome/combined_rail_modes.sql
deleted file mode 100644
index 5b49749..0000000
--- a/test/trace_processor/chrome/combined_rail_modes.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql') AS suppress_query_output;
-SELECT * FROM combined_overall_rail_slices;
diff --git a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.out b/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.out
deleted file mode 100644
index 3c55cf3..0000000
--- a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.out
+++ /dev/null
@@ -1,7 +0,0 @@
-
-"id","ts","dur","rail_mode","cpu_dur"
-1,0,10000,"response",26000
-2,10000,20000,"animation",20000
-3,30000,5000,"background",8000
-4,35000,10000,"animation",21000
-5,45000,10000,"background",1000
diff --git a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.py b/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.py
deleted file mode 100644
index f7a6051..0000000
--- a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_track_event_slice(
-    "task", 0, 5000, trusted_sequence_id=seq1, cpu_start=0, cpu_delta=10000)
-trace.add_track_event_slice(
-    "task",
-    5000,
-    5000,
-    trusted_sequence_id=seq1,
-    cpu_start=12000,
-    cpu_delta=4000)
-
-trace.add_track_event_slice(
-    "task",
-    10000,
-    6000,
-    trusted_sequence_id=seq1,
-    cpu_start=18000,
-    cpu_delta=2000)
-trace.add_track_event_slice(
-    "task",
-    16000,
-    4000,
-    trusted_sequence_id=seq1,
-    cpu_start=20000,
-    cpu_delta=7000)
-
-trace.add_track_event_slice(
-    "task",
-    30000,
-    10000,
-    trusted_sequence_id=seq1,
-    cpu_start=30000,
-    cpu_delta=1000)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=20000,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=30000,
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_track_event_slice(
-    "task", 0, 10000, trusted_sequence_id=seq2, cpu_start=0, cpu_delta=10000)
-
-trace.add_track_event_slice(
-    "task",
-    10000,
-    15000,
-    trusted_sequence_id=seq2,
-    cpu_start=12000,
-    cpu_delta=1000)
-
-trace.add_track_event_slice(
-    "task",
-    35000,
-    10000,
-    trusted_sequence_id=seq2,
-    cpu_start=20000,
-    cpu_delta=20000)
-
-trace.add_track_event_slice(
-    "task",
-    45000,
-    10000,
-    trusted_sequence_id=seq2,
-    cpu_start=40000,
-    cpu_delta=1000)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=25000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=35000,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=45000,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.sql b/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.sql
deleted file mode 100644
index b66726a..0000000
--- a/test/trace_processor/chrome/cpu_time_by_combined_rail_mode.sql
+++ /dev/null
@@ -1,17 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_processes.sql') AS suppress_query_output;
--- SELECT * FROM cpu_time_by_rail_mode;
-SELECT RUN_METRIC('chrome/cpu_time_by_rail_mode.sql') AS suppress_query_output;
-SELECT * FROM cpu_time_by_rail_mode;
diff --git a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.out b/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.out
deleted file mode 100644
index ebb8e23..0000000
--- a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.out
+++ /dev/null
@@ -1,7 +0,0 @@
-
-"id","ts","dur","rail_mode","mas","ma"
-1,0,10000000,"response",0.554275,55.427500
-2,10000000,20000000,"animation",0.284850,14.242500
-3,30000000,5000000,"background",0.076233,15.246667
-4,35000000,10000000,"animation",0.536850,53.685000
-5,45000000,10000000,"background",0.071580,7.158000
diff --git a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.py b/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.py
deleted file mode 100644
index 30aea45..0000000
--- a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-from synth_common import ms_to_ns
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-packet = trace.add_packet()
-packet.system_info.android_build_fingerprint = "google/sargo/foo"
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(20),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(30),
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(25),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(35),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(45),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# Create process tree
-trace.add_packet()
-trace.add_process(1, 0, "init")
-trace.add_process(thread_tid1, 1, "Renderer")
-trace.add_process(thread_tid2, 1, "Renderer")
-
-packet = trace.add_packet()
-
-# Add scheduling and cpu frequency data
-trace.add_ftrace_packet(cpu=0)
-trace.add_sched(ts=0, prev_pid=0, next_pid=thread_tid1)
-trace.add_cpufreq(ts=ms_to_ns(0), freq=1708800, cpu=0)
-trace.add_cpufreq(ts=ms_to_ns(5), freq=1324800, cpu=0)
-trace.add_sched(ts=ms_to_ns(20), prev_pid=thread_tid1, next_pid=0)
-trace.add_sched(ts=ms_to_ns(30), prev_pid=0, next_pid=thread_tid1)
-trace.add_cpufreq(ts=ms_to_ns(30), freq=300000, cpu=0)
-trace.add_cpufreq(ts=ms_to_ns(35), freq=1708800, cpu=0)
-trace.add_sched(ts=ms_to_ns(40), prev_pid=thread_tid1, next_pid=0)
-
-trace.add_ftrace_packet(cpu=1)
-trace.add_sched(ts=0, prev_pid=0, next_pid=thread_tid2)
-trace.add_cpufreq(ts=ms_to_ns(0), freq=998400, cpu=1)
-trace.add_sched(ts=ms_to_ns(10), prev_pid=thread_tid2, next_pid=0)
-trace.add_sched(ts=ms_to_ns(35), prev_pid=0, next_pid=thread_tid2)
-trace.add_cpufreq(ts=ms_to_ns(35), freq=1708800, cpu=1)
-trace.add_sched(ts=ms_to_ns(47), prev_pid=thread_tid2, next_pid=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.sql b/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.sql
deleted file mode 100644
index 7aab878..0000000
--- a/test/trace_processor/chrome/estimated_power_by_combined_rail_mode.sql
+++ /dev/null
@@ -1,17 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/chrome_processes.sql') AS suppress_query_output;
--- SELECT * FROM cpu_time_by_rail_mode;
-SELECT RUN_METRIC('chrome/estimated_power_by_rail_mode.sql') AS suppress_query_output;
-SELECT * FROM power_by_rail_mode;
diff --git a/test/trace_processor/chrome/frame_times_metric.out b/test/trace_processor/chrome/frame_times_metric.out
deleted file mode 100644
index 3ae3370..0000000
--- a/test/trace_processor/chrome/frame_times_metric.out
+++ /dev/null
@@ -1,1210 +0,0 @@
-[perfetto.protos.frame_times] {
-  frame_time: 16.816
-  frame_time: 16.791
-  frame_time: 16.677
-  frame_time: 16.875
-  frame_time: 16.555
-  frame_time: 16.571
-  frame_time: 17.015
-  frame_time: 16.379
-  frame_time: 16.659
-  frame_time: 16.87
-  frame_time: 16.667
-  frame_time: 16.609
-  frame_time: 17.019
-  frame_time: 16.684
-  frame_time: 16.691
-  frame_time: 16.598
-  frame_time: 16.605
-  frame_time: 16.675
-  frame_time: 16.895
-  frame_time: 16.614
-  frame_time: 16.856
-  frame_time: 16.664
-  frame_time: 16.636
-  frame_time: 16.83
-  frame_time: 16.313
-  frame_time: 17.04
-  frame_time: 16.695
-  frame_time: 16.699
-  frame_time: 16.481
-  frame_time: 16.954
-  frame_time: 16.633
-  frame_time: 16.783
-  frame_time: 16.655
-  frame_time: 16.764
-  frame_time: 16.5
-  frame_time: 16.791
-  frame_time: 16.991
-  frame_time: 16.617
-  frame_time: 16.668
-  frame_time: 16.374
-  frame_time: 16.941
-  frame_time: 16.429
-  frame_time: 16.921
-  frame_time: 16.654
-  frame_time: 16.966
-  frame_time: 16.184
-  frame_time: 17.212
-  frame_time: 16.545
-  frame_time: 16.838
-  frame_time: 16.511
-  frame_time: 16.678
-  frame_time: 16.706
-  frame_time: 16.651
-  frame_time: 16.831
-  frame_time: 16.662
-  frame_time: 16.72
-  frame_time: 16.523
-  frame_time: 17.072
-  frame_time: 16.732
-  frame_time: 16.783
-  frame_time: 16.492
-  frame_time: 16.958
-  frame_time: 16.805
-  frame_time: 16.433
-  frame_time: 16.697
-  frame_time: 16.412
-  frame_time: 16.708
-  frame_time: 16.912
-  frame_time: 16.799
-  frame_time: 16.692
-  frame_time: 16.642
-  frame_time: 16.679
-  frame_time: 16.39
-  frame_time: 16.762
-  frame_time: 17.136
-  frame_time: 16.536
-  frame_time: 16.652
-  frame_time: 16.746
-  frame_time: 16.632
-  frame_time: 16.626
-  frame_time: 17.139
-  frame_time: 16.886
-  frame_time: 16.464
-  frame_time: 16.167
-  frame_time: 16.664
-  frame_time: 17.122
-  frame_time: 16.706
-  frame_time: 16.859
-  frame_time: 16.543
-  frame_time: 16.319
-  frame_time: 17.227
-  frame_time: 16.758
-  frame_time: 16.36
-  frame_time: 16.834
-  frame_time: 16.757
-  frame_time: 16.409
-  frame_time: 16.908
-  frame_time: 16.785
-  frame_time: 16.691
-  frame_time: 16.399
-  frame_time: 17.055
-  frame_time: 16.348
-  frame_time: 16.668
-  frame_time: 16.957
-  frame_time: 16.605
-  frame_time: 16.552
-  frame_time: 16.696
-  frame_time: 16.946
-  frame_time: 16.893
-  frame_time: 16.659
-  frame_time: 16.674
-  frame_time: 16.608
-  frame_time: 16.82
-  frame_time: 16.6
-  frame_time: 16.743
-  frame_time: 16.512
-  frame_time: 16.647
-  frame_time: 16.613
-  frame_time: 16.793
-  frame_time: 16.574
-  frame_time: 16.775
-  frame_time: 17.215
-  frame_time: 16.306
-  frame_time: 16.604
-  frame_time: 16.847
-  frame_time: 16.899
-  frame_time: 16.561
-  frame_time: 16.659
-  frame_time: 16.548
-  frame_time: 16.716
-  frame_time: 16.819
-  frame_time: 16.85
-  frame_time: 16.724
-  frame_time: 16.653
-  frame_time: 16.553
-  frame_time: 16.783
-  frame_time: 16.543
-  frame_time: 16.627
-  frame_time: 16.817
-  frame_time: 16.629
-  frame_time: 16.898
-  frame_time: 16.592
-  frame_time: 17.033
-  frame_time: 16.702
-  frame_time: 16.35
-  frame_time: 17.052
-  frame_time: 16.568
-  frame_time: 16.785
-  frame_time: 16.673
-  frame_time: 16.798
-  frame_time: 16.743
-  frame_time: 17.166
-  frame_time: 16.409
-  frame_time: 16.375
-  frame_time: 16.804
-  frame_time: 16.692
-  frame_time: 16.802
-  frame_time: 16.62
-  frame_time: 16.787
-  frame_time: 16.581
-  frame_time: 17.26
-  frame_time: 16.346
-  frame_time: 16.654
-  frame_time: 16.579
-  frame_time: 16.41
-  frame_time: 16.968
-  frame_time: 16.769
-  frame_time: 16.728
-  frame_time: 16.647
-  frame_time: 16.651
-  frame_time: 16.603
-  frame_time: 16.706
-  frame_time: 16.705
-  frame_time: 16.754
-  frame_time: 16.449
-  frame_time: 16.954
-  frame_time: 16.947
-  frame_time: 16.438
-  frame_time: 16.679
-  frame_time: 17.492
-  frame_time: 16.044
-  frame_time: 16.551
-  frame_time: 17.175
-  frame_time: 16.198
-  frame_time: 17.152
-  frame_time: 16.512
-  frame_time: 16.718
-  frame_time: 16.699
-  frame_time: 16.864
-  frame_time: 16.736
-  frame_time: 16.606
-  frame_time: 16.829
-  frame_time: 16.336
-  frame_time: 16.866
-  frame_time: 16.901
-  frame_time: 16.654
-  frame_time: 16.73
-  frame_time: 16.366
-  frame_time: 17.021
-  frame_time: 16.516
-  frame_time: 16.742
-  frame_time: 16.85
-  frame_time: 16.417
-  frame_time: 17.11
-  frame_time: 16.588
-  frame_time: 16.727
-  frame_time: 16.625
-  frame_time: 16.684
-  frame_time: 16.774
-  frame_time: 16.638
-  frame_time: 16.866
-  frame_time: 16.518
-  frame_time: 16.688
-  frame_time: 16.844
-  frame_time: 16.808
-  frame_time: 16.666
-  frame_time: 16.568
-  frame_time: 16.775
-  frame_time: 16.763
-  frame_time: 16.223
-  frame_time: 16.976
-  frame_time: 16.563
-  frame_time: 16.994
-  frame_time: 16.944
-  frame_time: 16.422
-  frame_time: 16.783
-  frame_time: 16.535
-  frame_time: 17.022
-  frame_time: 16.245
-  frame_time: 16.989
-  frame_time: 17.11
-  frame_time: 16.091
-  frame_time: 16.61
-  frame_time: 17.223
-  frame_time: 16.588
-  frame_time: 16.377
-  frame_time: 16.882
-  frame_time: 16.478
-  frame_time: 17.064
-  frame_time: 17.023
-  frame_time: 16.327
-  frame_time: 16.745
-  frame_time: 16.572
-  frame_time: 16.719
-  frame_time: 16.717
-  frame_time: 16.675
-  frame_time: 16.952
-  frame_time: 16.283
-  frame_time: 17.076
-  frame_time: 16.438
-  frame_time: 16.656
-  frame_time: 16.627
-  frame_time: 17.149
-  frame_time: 16.507
-  frame_time: 16.695
-  frame_time: 16.852
-  frame_time: 16.669
-  frame_time: 16.708
-  frame_time: 16.799
-  frame_time: 16.752
-  frame_time: 16.703
-  frame_time: 16.602
-  frame_time: 16.711
-  frame_time: 16.54
-  frame_time: 16.713
-  frame_time: 16.731
-  frame_time: 16.636
-  frame_time: 17.09
-  frame_time: 16.538
-  frame_time: 16.848
-  frame_time: 16.704
-  frame_time: 16.302
-  frame_time: 16.737
-  frame_time: 16.878
-  frame_time: 16.522
-  frame_time: 16.824
-  frame_time: 16.872
-  frame_time: 16.782
-  frame_time: 16.419
-  frame_time: 16.847
-  frame_time: 16.815
-  frame_time: 16.338
-  frame_time: 16.848
-  frame_time: 16.687
-  frame_time: 17.042
-  frame_time: 16.313
-  frame_time: 16.989
-  frame_time: 16.843
-  frame_time: 16.23
-  frame_time: 16.831
-  frame_time: 17.174
-  frame_time: 16.227
-  frame_time: 16.587
-  frame_time: 17.134
-  frame_time: 16.654
-  frame_time: 16.682
-  frame_time: 16.757
-  frame_time: 16.732
-  frame_time: 16.685
-  frame_time: 16.774
-  frame_time: 16.678
-  frame_time: 16.473
-  frame_time: 16.796
-  frame_time: 16.73
-  frame_time: 16.758
-  frame_time: 16.684
-  frame_time: 16.692
-  frame_time: 16.709
-  frame_time: 17.045
-  frame_time: 16.552
-  frame_time: 16.712
-  frame_time: 16.375
-  frame_time: 16.875
-  frame_time: 16.762
-  frame_time: 16.639
-  frame_time: 16.594
-  frame_time: 16.857
-  frame_time: 16.422
-  frame_time: 16.914
-  frame_time: 16.667
-  frame_time: 16.801
-  frame_time: 17.196
-  frame_time: 16.229
-  frame_time: 17.002
-  frame_time: 16.421
-  frame_time: 16.579
-  frame_time: 16.731
-  frame_time: 16.6
-  frame_time: 16.913
-  frame_time: 16.596
-  frame_time: 16.674
-  frame_time: 16.706
-  frame_time: 16.723
-  frame_time: 16.78
-  frame_time: 16.675
-  frame_time: 16.651
-  frame_time: 16.851
-  frame_time: 16.59
-  frame_time: 17.057
-  frame_time: 16.716
-  frame_time: 16.226
-  frame_time: 16.918
-  frame_time: 16.755
-  frame_time: 16.688
-  frame_time: 16.717
-  frame_time: 16.388
-  frame_time: 17.128
-  frame_time: 16.519
-  frame_time: 16.711
-  frame_time: 16.725
-  frame_time: 16.679
-  frame_time: 16.573
-  frame_time: 16.892
-  frame_time: 16.668
-  frame_time: 16.729
-  frame_time: 16.737
-  frame_time: 16.695
-  frame_time: 16.702
-  frame_time: 16.677
-  frame_time: 16.852
-  frame_time: 16.512
-  frame_time: 16.757
-  frame_time: 16.657
-  frame_time: 16.607
-  frame_time: 17.096
-  frame_time: 16.607
-  frame_time: 16.598
-  frame_time: 16.505
-  frame_time: 16.722
-  frame_time: 16.811
-  frame_time: 16.664
-  frame_time: 16.738
-  frame_time: 16.816
-  frame_time: 16.597
-  frame_time: 16.762
-  frame_time: 16.416
-  frame_time: 17.049
-  frame_time: 16.651
-  frame_time: 16.683
-  frame_time: 16.463
-  frame_time: 16.896
-  frame_time: 16.457
-  frame_time: 17.091
-  frame_time: 16.534
-  frame_time: 16.787
-  frame_time: 16.659
-  frame_time: 16.611
-  frame_time: 16.741
-  frame_time: 16.785
-  frame_time: 16.45
-  frame_time: 17.021
-  frame_time: 16.722
-  frame_time: 16.633
-  frame_time: 16.838
-  frame_time: 16.241
-  frame_time: 16.974
-  frame_time: 16.708
-  frame_time: 16.745
-  frame_time: 16.674
-  frame_time: 16.621
-  frame_time: 16.71
-  frame_time: 16.741
-  frame_time: 16.744
-  frame_time: 16.709
-  frame_time: 16.707
-  frame_time: 16.603
-  frame_time: 16.84
-  frame_time: 16.42
-  frame_time: 16.976
-  frame_time: 16.808
-  frame_time: 16.369
-  frame_time: 16.832
-  frame_time: 16.767
-  frame_time: 16.548
-  frame_time: 16.878
-  frame_time: 16.865
-  frame_time: 16.918
-  frame_time: 16.611
-  frame_time: 16.686
-  frame_time: 16.49
-  frame_time: 16.694
-  frame_time: 16.477
-  frame_time: 17.31
-  frame_time: 15.995
-  frame_time: 17.086
-  frame_time: 16.789
-  frame_time: 16.613
-  frame_time: 16.801
-  frame_time: 16.556
-  frame_time: 16.769
-  frame_time: 16.664
-  frame_time: 16.524
-  frame_time: 16.949
-  frame_time: 16.66
-  frame_time: 16.835
-  frame_time: 16.232
-  frame_time: 17.075
-  frame_time: 16.694
-  frame_time: 16.632
-  frame_time: 16.672
-  frame_time: 16.773
-  frame_time: 16.761
-  frame_time: 16.593
-  frame_time: 16.707
-  frame_time: 16.903
-  frame_time: 16.464
-  frame_time: 16.8
-  frame_time: 16.725
-  frame_time: 16.63
-  frame_time: 16.612
-  frame_time: 16.86
-  frame_time: 16.7
-  frame_time: 16.746
-  frame_time: 16.409
-  frame_time: 16.962
-  frame_time: 16.764
-  frame_time: 16.618
-  frame_time: 16.781
-  frame_time: 16.788
-  frame_time: 16.488
-  frame_time: 16.755
-  frame_time: 16.686
-  frame_time: 16.701
-  frame_time: 16.778
-  frame_time: 16.693
-  frame_time: 16.505
-  frame_time: 17.008
-  frame_time: 16.531
-  frame_time: 16.513
-  frame_time: 16.912
-  frame_time: 16.58
-  frame_time: 16.685
-  frame_time: 16.849
-  frame_time: 16.69
-  frame_time: 16.555
-  frame_time: 16.82
-  frame_time: 16.65
-  frame_time: 16.78
-  frame_time: 16.679
-  frame_time: 16.729
-  frame_time: 16.183
-  frame_time: 17.318
-  frame_time: 16.648
-  frame_time: 16.75
-  frame_time: 16.794
-  frame_time: 16.309
-  frame_time: 16.929
-  frame_time: 16.588
-  frame_time: 16.665
-  frame_time: 16.914
-  frame_time: 16.708
-  frame_time: 16.681
-  frame_time: 16.678
-  frame_time: 16.368
-  frame_time: 17.4
-  frame_time: 16.317
-  frame_time: 16.951
-  frame_time: 16.584
-  frame_time: 16.687
-  frame_time: 16.966
-  frame_time: 16.413
-  frame_time: 16.456
-  frame_time: 16.73
-  frame_time: 16.963
-  frame_time: 16.3
-  frame_time: 17.323
-  frame_time: 16.507
-  frame_time: 16.506
-  frame_time: 16.765
-  frame_time: 16.757
-  frame_time: 16.653
-  frame_time: 16.67
-  frame_time: 16.866
-  frame_time: 16.406
-  frame_time: 16.91
-  frame_time: 16.49
-  frame_time: 17.009
-  frame_time: 16.714
-  frame_time: 16.358
-  frame_time: 17.015
-  frame_time: 16.713
-  frame_time: 16.651
-  frame_time: 16.708
-  frame_time: 16.73
-  frame_time: 16.642
-  frame_time: 16.456
-  frame_time: 16.911
-  frame_time: 16.459
-  frame_time: 16.923
-  frame_time: 16.544
-  frame_time: 16.767
-  frame_time: 16.396
-  frame_time: 17.106
-  frame_time: 16.402
-  frame_time: 16.976
-  frame_time: 16.651
-  frame_time: 16.44
-  frame_time: 16.703
-  frame_time: 17.053
-  frame_time: 16.376
-  frame_time: 17.105
-  frame_time: 16.565
-  frame_time: 16.766
-  frame_time: 16.388
-  frame_time: 17.04
-  frame_time: 16.915
-  frame_time: 16.68
-  frame_time: 16.399
-  frame_time: 16.897
-  frame_time: 16.333
-  frame_time: 17.182
-  frame_time: 16.515
-  frame_time: 16.735
-  frame_time: 16.674
-  frame_time: 16.441
-  frame_time: 17.002
-  frame_time: 16.753
-  frame_time: 16.604
-  frame_time: 16.68
-  frame_time: 16.711
-  frame_time: 16.672
-  frame_time: 16.308
-  frame_time: 17.04
-  frame_time: 16.376
-  frame_time: 17.349
-  frame_time: 16.463
-  frame_time: 16.547
-  frame_time: 16.836
-  frame_time: 16.71
-  frame_time: 16.639
-  frame_time: 16.651
-  frame_time: 16.711
-  frame_time: 16.906
-  frame_time: 16.845
-  frame_time: 16.457
-  frame_time: 16.424
-  frame_time: 17.067
-  frame_time: 16.14
-  frame_time: 17.189
-  frame_time: 16.63
-  frame_time: 16.717
-  frame_time: 16.771
-  frame_time: 16.639
-  frame_time: 16.733
-  frame_time: 16.796
-  frame_time: 16.578
-  frame_time: 16.678
-  frame_time: 16.908
-  frame_time: 16.515
-  frame_time: 16.712
-  frame_time: 16.506
-  frame_time: 16.933
-  frame_time: 16.377
-  frame_time: 17.083
-  frame_time: 16.637
-  frame_time: 16.626
-  frame_time: 16.682
-  frame_time: 16.677
-  frame_time: 16.7
-  frame_time: 16.786
-  frame_time: 16.798
-  frame_time: 16.583
-  frame_time: 16.859
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.791
-  exp_frame_time: 16.695
-  exp_frame_time: 16.895
-  exp_frame_time: 16.504
-  exp_frame_time: 16.723
-  exp_frame_time: 16.698
-  exp_frame_time: 16.703
-  exp_frame_time: 16.701
-  exp_frame_time: 16.626
-  exp_frame_time: 16.78
-  exp_frame_time: 16.702
-  exp_frame_time: 16.741
-  exp_frame_time: 16.673
-  exp_frame_time: 16.707
-  exp_frame_time: 16.703
-  exp_frame_time: 16.691
-  exp_frame_time: 16.707
-  exp_frame_time: 16.705
-  exp_frame_time: 16.716
-  exp_frame_time: 16.736
-  exp_frame_time: 16.673
-  exp_frame_time: 16.624
-  exp_frame_time: 16.789
-  exp_frame_time: 16.72
-  exp_frame_time: 16.695
-  exp_frame_time: 16.723
-  exp_frame_time: 16.693
-  exp_frame_time: 16.704
-  exp_frame_time: 16.716
-  exp_frame_time: 16.699
-  exp_frame_time: 16.71
-  exp_frame_time: 16.731
-  exp_frame_time: 16.692
-  exp_frame_time: 16.711
-  exp_frame_time: 16.701
-  exp_frame_time: 16.707
-  exp_frame_time: 16.708
-  exp_frame_time: 16.708
-  exp_frame_time: 16.717
-  exp_frame_time: 16.686
-  exp_frame_time: 16.709
-  exp_frame_time: 16.702
-  exp_frame_time: 16.71
-  exp_frame_time: 16.694
-  exp_frame_time: 16.711
-  exp_frame_time: 16.683
-  exp_frame_time: 16.724
-  exp_frame_time: 16.705
-  exp_frame_time: 16.713
-  exp_frame_time: 16.685
-  exp_frame_time: 16.708
-  exp_frame_time: 16.702
-  exp_frame_time: 16.714
-  exp_frame_time: 16.889
-  exp_frame_time: 16.519
-  exp_frame_time: 16.711
-  exp_frame_time: 16.712
-  exp_frame_time: 16.692
-  exp_frame_time: 16.706
-  exp_frame_time: 16.702
-  exp_frame_time: 16.699
-  exp_frame_time: 16.713
-  exp_frame_time: 16.726
-  exp_frame_time: 16.937
-  exp_frame_time: 16.441
-  exp_frame_time: 16.714
-  exp_frame_time: 16.619
-  exp_frame_time: 16.707
-  exp_frame_time: 16.702
-  exp_frame_time: 16.783
-  exp_frame_time: 16.61
-  exp_frame_time: 16.703
-  exp_frame_time: 16.722
-  exp_frame_time: 16.781
-  exp_frame_time: 16.627
-  exp_frame_time: 16.782
-  exp_frame_time: 16.682
-  exp_frame_time: 16.712
-  exp_frame_time: 16.714
-  exp_frame_time: 16.615
-  exp_frame_time: 16.793
-  exp_frame_time: 16.697
-  exp_frame_time: 16.707
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.707
-  exp_frame_time: 16.698
-  exp_frame_time: 16.722
-  exp_frame_time: 16.716
-  exp_frame_time: 16.68
-  exp_frame_time: 16.703
-  exp_frame_time: 16.696
-  exp_frame_time: 16.708
-  exp_frame_time: 16.697
-  exp_frame_time: 16.627
-  exp_frame_time: 16.785
-  exp_frame_time: 16.716
-  exp_frame_time: 16.686
-  exp_frame_time: 16.7
-  exp_frame_time: 16.705
-  exp_frame_time: 16.706
-  exp_frame_time: 16.709
-  exp_frame_time: 16.699
-  exp_frame_time: 16.703
-  exp_frame_time: 16.718
-  exp_frame_time: 16.712
-  exp_frame_time: 16.705
-  exp_frame_time: 16.694
-  exp_frame_time: 16.708
-  exp_frame_time: 16.706
-  exp_frame_time: 16.717
-  exp_frame_time: 16.696
-  exp_frame_time: 16.699
-  exp_frame_time: 16.722
-  exp_frame_time: 16.685
-  exp_frame_time: 16.706
-  exp_frame_time: 16.712
-  exp_frame_time: 16.69
-  exp_frame_time: 16.725
-  exp_frame_time: 16.716
-  exp_frame_time: 16.683
-  exp_frame_time: 16.698
-  exp_frame_time: 16.691
-  exp_frame_time: 16.64
-  exp_frame_time: 16.776
-  exp_frame_time: 16.706
-  exp_frame_time: 16.716
-  exp_frame_time: 16.787
-  exp_frame_time: 16.63
-  exp_frame_time: 16.599
-  exp_frame_time: 16.724
-  exp_frame_time: 16.778
-  exp_frame_time: 16.63
-  exp_frame_time: 16.703
-  exp_frame_time: 16.787
-  exp_frame_time: 16.688
-  exp_frame_time: 16.73
-  exp_frame_time: 16.701
-  exp_frame_time: 16.695
-  exp_frame_time: 16.701
-  exp_frame_time: 16.714
-  exp_frame_time: 16.697
-  exp_frame_time: 16.706
-  exp_frame_time: 16.725
-  exp_frame_time: 16.705
-  exp_frame_time: 16.721
-  exp_frame_time: 16.663
-  exp_frame_time: 16.739
-  exp_frame_time: 16.717
-  exp_frame_time: 16.623
-  exp_frame_time: 16.804
-  exp_frame_time: 16.7
-  exp_frame_time: 16.697
-  exp_frame_time: 16.727
-  exp_frame_time: 16.714
-  exp_frame_time: 16.714
-  exp_frame_time: 16.689
-  exp_frame_time: 16.713
-  exp_frame_time: 16.708
-  exp_frame_time: 16.616
-  exp_frame_time: 16.722
-  exp_frame_time: 16.684
-  exp_frame_time: 16.718
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.788
-  exp_frame_time: 16.627
-  exp_frame_time: 16.686
-  exp_frame_time: 16.717
-  exp_frame_time: 16.785
-  exp_frame_time: 16.702
-  exp_frame_time: 16.636
-  exp_frame_time: 17.081
-  exp_frame_time: 16.332
-  exp_frame_time: 16.703
-  exp_frame_time: 16.784
-  exp_frame_time: 16.712
-  exp_frame_time: 16.711
-  exp_frame_time: 16.797
-  exp_frame_time: 16.622
-  exp_frame_time: 16.717
-  exp_frame_time: 16.703
-  exp_frame_time: 16.704
-  exp_frame_time: 16.712
-  exp_frame_time: 16.691
-  exp_frame_time: 16.732
-  exp_frame_time: 16.702
-  exp_frame_time: 16.714
-  exp_frame_time: 16.708
-  exp_frame_time: 16.718
-  exp_frame_time: 16.704
-  exp_frame_time: 16.698
-  exp_frame_time: 16.706
-  exp_frame_time: 16.632
-  exp_frame_time: 16.786
-  exp_frame_time: 16.697
-  exp_frame_time: 16.722
-  exp_frame_time: 16.709
-  exp_frame_time: 16.711
-  exp_frame_time: 16.712
-  exp_frame_time: 16.711
-  exp_frame_time: 16.711
-  exp_frame_time: 16.7
-  exp_frame_time: 16.713
-  exp_frame_time: 16.712
-  exp_frame_time: 16.703
-  exp_frame_time: 16.74
-  exp_frame_time: 16.673
-  exp_frame_time: 16.704
-  exp_frame_time: 16.721
-  exp_frame_time: 16.723
-  exp_frame_time: 16.685
-  exp_frame_time: 16.707
-  exp_frame_time: 16.703
-  exp_frame_time: 16.714
-  exp_frame_time: 16.715
-  exp_frame_time: 16.7
-  exp_frame_time: 16.714
-  exp_frame_time: 16.717
-  exp_frame_time: 16.702
-  exp_frame_time: 16.711
-  exp_frame_time: 16.71
-  exp_frame_time: 16.631
-  exp_frame_time: 16.894
-  exp_frame_time: 16.599
-  exp_frame_time: 16.702
-  exp_frame_time: 16.633
-  exp_frame_time: 16.787
-  exp_frame_time: 16.631
-  exp_frame_time: 16.705
-  exp_frame_time: 16.774
-  exp_frame_time: 16.636
-  exp_frame_time: 16.775
-  exp_frame_time: 16.705
-  exp_frame_time: 16.628
-  exp_frame_time: 16.788
-  exp_frame_time: 16.693
-  exp_frame_time: 16.643
-  exp_frame_time: 16.702
-  exp_frame_time: 16.776
-  exp_frame_time: 16.71
-  exp_frame_time: 16.704
-  exp_frame_time: 16.637
-  exp_frame_time: 16.78
-  exp_frame_time: 16.632
-  exp_frame_time: 16.778
-  exp_frame_time: 16.705
-  exp_frame_time: 16.744
-  exp_frame_time: 16.678
-  exp_frame_time: 16.71
-  exp_frame_time: 16.637
-  exp_frame_time: 16.79
-  exp_frame_time: 16.699
-  exp_frame_time: 16.721
-  exp_frame_time: 16.701
-  exp_frame_time: 16.722
-  exp_frame_time: 16.702
-  exp_frame_time: 16.685
-  exp_frame_time: 16.741
-  exp_frame_time: 16.676
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.71
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.717
-  exp_frame_time: 16.695
-  exp_frame_time: 16.709
-  exp_frame_time: 16.713
-  exp_frame_time: 16.705
-  exp_frame_time: 16.715
-  exp_frame_time: 16.629
-  exp_frame_time: 16.797
-  exp_frame_time: 16.698
-  exp_frame_time: 16.735
-  exp_frame_time: 16.699
-  exp_frame_time: 16.702
-  exp_frame_time: 16.703
-  exp_frame_time: 16.706
-  exp_frame_time: 16.709
-  exp_frame_time: 16.684
-  exp_frame_time: 16.732
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.711
-  exp_frame_time: 16.713
-  exp_frame_time: 16.713
-  exp_frame_time: 16.691
-  exp_frame_time: 16.714
-  exp_frame_time: 16.729
-  exp_frame_time: 16.702
-  exp_frame_time: 16.703
-  exp_frame_time: 16.709
-  exp_frame_time: 16.709
-  exp_frame_time: 16.723
-  exp_frame_time: 16.693
-  exp_frame_time: 16.71
-  exp_frame_time: 16.694
-  exp_frame_time: 16.739
-  exp_frame_time: 16.696
-  exp_frame_time: 16.695
-  exp_frame_time: 16.713
-  exp_frame_time: 16.7
-  exp_frame_time: 16.731
-  exp_frame_time: 16.715
-  exp_frame_time: 16.712
-  exp_frame_time: 16.694
-  exp_frame_time: 16.643
-  exp_frame_time: 16.767
-  exp_frame_time: 16.649
-  exp_frame_time: 16.785
-  exp_frame_time: 16.705
-  exp_frame_time: 16.637
-  exp_frame_time: 16.708
-  exp_frame_time: 16.783
-  exp_frame_time: 16.629
-  exp_frame_time: 16.708
-  exp_frame_time: 16.71
-  exp_frame_time: 16.714
-  exp_frame_time: 16.685
-  exp_frame_time: 16.718
-  exp_frame_time: 16.723
-  exp_frame_time: 16.701
-  exp_frame_time: 16.701
-  exp_frame_time: 16.707
-  exp_frame_time: 16.687
-  exp_frame_time: 16.805
-  exp_frame_time: 16.705
-  exp_frame_time: 16.706
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.633
-  exp_frame_time: 16.711
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.708
-  exp_frame_time: 16.694
-  exp_frame_time: 16.845
-  exp_frame_time: 16.662
-  exp_frame_time: 16.708
-  exp_frame_time: 16.706
-  exp_frame_time: 16.717
-  exp_frame_time: 16.615
-  exp_frame_time: 16.71
-  exp_frame_time: 16.715
-  exp_frame_time: 16.709
-  exp_frame_time: 16.709
-  exp_frame_time: 16.712
-  exp_frame_time: 16.702
-  exp_frame_time: 16.712
-  exp_frame_time: 16.78
-  exp_frame_time: 16.706
-  exp_frame_time: 16.631
-  exp_frame_time: 16.689
-  exp_frame_time: 16.731
-  exp_frame_time: 16.703
-  exp_frame_time: 16.778
-  exp_frame_time: 16.704
-  exp_frame_time: 16.701
-  exp_frame_time: 16.609
-  exp_frame_time: 16.703
-  exp_frame_time: 16.803
-  exp_frame_time: 16.628
-  exp_frame_time: 16.767
-  exp_frame_time: 16.631
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.781
-  exp_frame_time: 16.626
-  exp_frame_time: 16.69
-  exp_frame_time: 16.795
-  exp_frame_time: 16.738
-  exp_frame_time: 16.668
-  exp_frame_time: 16.728
-  exp_frame_time: 16.666
-  exp_frame_time: 16.604
-  exp_frame_time: 16.722
-  exp_frame_time: 16.698
-  exp_frame_time: 16.708
-  exp_frame_time: 16.702
-  exp_frame_time: 16.712
-  exp_frame_time: 16.781
-  exp_frame_time: 16.7
-  exp_frame_time: 16.704
-  exp_frame_time: 16.707
-  exp_frame_time: 16.625
-  exp_frame_time: 16.731
-  exp_frame_time: 16.744
-  exp_frame_time: 16.706
-  exp_frame_time: 16.637
-  exp_frame_time: 16.687
-  exp_frame_time: 16.722
-  exp_frame_time: 16.702
-  exp_frame_time: 16.708
-  exp_frame_time: 16.783
-  exp_frame_time: 16.637
-  exp_frame_time: 16.775
-  exp_frame_time: 16.71
-  exp_frame_time: 16.625
-  exp_frame_time: 16.708
-  exp_frame_time: 16.786
-  exp_frame_time: 16.633
-  exp_frame_time: 16.703
-  exp_frame_time: 16.723
-  exp_frame_time: 16.697
-  exp_frame_time: 16.711
-  exp_frame_time: 16.706
-  exp_frame_time: 16.79
-  exp_frame_time: 16.705
-  exp_frame_time: 16.627
-  exp_frame_time: 16.706
-  exp_frame_time: 16.7
-  exp_frame_time: 16.705
-  exp_frame_time: 16.695
-  exp_frame_time: 16.719
-  exp_frame_time: 16.782
-  exp_frame_time: 16.69
-  exp_frame_time: 16.709
-  exp_frame_time: 16.698
-  exp_frame_time: 16.71
-  exp_frame_time: 16.608
-  exp_frame_time: 16.798
-  exp_frame_time: 16.694
-  exp_frame_time: 16.709
-  exp_frame_time: 16.702
-  exp_frame_time: 16.702
-  exp_frame_time: 16.752
-  exp_frame_time: 16.636
-  exp_frame_time: 16.706
-  exp_frame_time: 16.697
-  exp_frame_time: 16.697
-  exp_frame_time: 16.71
-  exp_frame_time: 16.681
-  exp_frame_time: 16.718
-  exp_frame_time: 16.71
-  exp_frame_time: 16.624
-  exp_frame_time: 16.793
-  exp_frame_time: 16.687
-  exp_frame_time: 16.714
-  exp_frame_time: 16.625
-  exp_frame_time: 16.781
-  exp_frame_time: 16.705
-  exp_frame_time: 16.727
-  exp_frame_time: 16.661
-  exp_frame_time: 16.776
-  exp_frame_time: 16.58
-  exp_frame_time: 16.778
-  exp_frame_time: 16.693
-  exp_frame_time: 16.707
-  exp_frame_time: 16.792
-  exp_frame_time: 16.613
-  exp_frame_time: 16.71
-  exp_frame_time: 16.705
-  exp_frame_time: 16.703
-  exp_frame_time: 16.699
-  exp_frame_time: 16.718
-  exp_frame_time: 16.7
-  exp_frame_time: 16.693
-  exp_frame_time: 16.706
-  exp_frame_time: 16.629
-  exp_frame_time: 16.919
-  exp_frame_time: 16.563
-  exp_frame_time: 16.637
-  exp_frame_time: 16.769
-  exp_frame_time: 16.71
-  exp_frame_time: 16.734
-  exp_frame_time: 16.656
-  exp_frame_time: 16.716
-  exp_frame_time: 16.626
-  exp_frame_time: 16.783
-  exp_frame_time: 16.699
-  exp_frame_time: 16.696
-  exp_frame_time: 16.632
-  exp_frame_time: 16.782
-  exp_frame_time: 16.704
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.645
-  exp_frame_time: 16.774
-  exp_frame_time: 16.704
-  exp_frame_time: 16.63
-  exp_frame_time: 16.703
-  exp_frame_time: 16.713
-  exp_frame_time: 16.778
-  exp_frame_time: 16.709
-  exp_frame_time: 16.701
-  exp_frame_time: 16.697
-  exp_frame_time: 16.638
-  exp_frame_time: 16.705
-  exp_frame_time: 16.702
-  exp_frame_time: 16.698
-  exp_frame_time: 16.862
-  exp_frame_time: 16.635
-  exp_frame_time: 16.691
-  exp_frame_time: 16.734
-  exp_frame_time: 16.603
-  exp_frame_time: 16.794
-  exp_frame_time: 16.706
-  exp_frame_time: 16.712
-  exp_frame_time: 16.689
-  exp_frame_time: 16.71
-  exp_frame_time: 16.703
-  exp_frame_time: 16.621
-  exp_frame_time: 16.772
-  exp_frame_time: 16.694
-  exp_frame_time: 16.705
-  exp_frame_time: 16.694
-  exp_frame_time: 16.708
-  exp_frame_time: 16.695
-  exp_frame_time: 16.708
-  exp_frame_time: 16.992
-  exp_frame_time: 16.403
-  exp_frame_time: 16.703
-  exp_frame_time: 16.713
-  exp_frame_time: 16.693
-  exp_frame_time: 16.691
-  exp_frame_time: 16.687
-  exp_frame_time: 16.717
-  exp_frame_time: 16.633
-  exp_frame_time: 16.766
-  exp_frame_time: 16.69
-  exp_frame_time: 16.7
-  exp_frame_time: 16.699
-  exp_frame_time: 16.637
-  exp_frame_time: 16.704
-  exp_frame_time: 16.775
-  exp_frame_time: 16.707
-  exp_frame_time: 16.636
-  exp_frame_time: 16.785
-  exp_frame_time: 16.633
-  exp_frame_time: 16.702
-  exp_frame_time: 16.772
-  exp_frame_time: 16.709
-  exp_frame_time: 16.841
-  exp_frame_time: 16.556
-  exp_frame_time: 16.703
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.71
-  exp_frame_time: 16.748
-  exp_frame_time: 16.652
-  exp_frame_time: 16.722
-  exp_frame_time: 16.686
-  exp_frame_time: 16.697
-  exp_frame_time: 16.691
-  exp_frame_time: 16.691
-  exp_frame_time: 16.709
-  exp_frame_time: 16.698
-  exp_frame_time: 16.703
-  exp_frame_time: 16.714
-  exp_frame_time: 16.861
-  exp_frame_time: 16.535
-  exp_frame_time: 16.737
-  exp_frame_time: 16.671
-  exp_frame_time: 16.693
-  exp_frame_time: 16.701
-  exp_frame_time: 16.614
-  exp_frame_time: 16.711
-  exp_frame_time: 16.77
-  exp_frame_time: 16.632
-  exp_frame_time: 16.689
-  exp_frame_time: 16.789
-  exp_frame_time: 16.711
-  exp_frame_time: 16.689
-  exp_frame_time: 16.696
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.686
-  exp_frame_time: 16.64
-  exp_frame_time: 16.701
-  exp_frame_time: 16.794
-  exp_frame_time: 16.704
-  exp_frame_time: 16.714
-  exp_frame_time: 16.728
-  exp_frame_time: 16.664
-  exp_frame_time: 16.71
-  exp_frame_time: 16.631
-  exp_frame_time: 16.781
-  exp_frame_time: 16.628
-  exp_frame_time: 16.703
-  exp_frame_time: 16.773
-  exp_frame_time: 16.712
-  exp_frame_time: 16.699
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.64
-  exp_frame_time: 16.702
-  exp_frame_time: 16.705
-  exp_frame_time: 16.809
-  exp_frame_time: 16.671
-  exp_frame_time: 16.614
-  exp_frame_time: 16.721
-  exp_frame_time: 16.701
-  exp_frame_time: 16.701
-  exp_frame_time: 16.776
-  exp_frame_time: 16.63
-  exp_frame_time: 16.787
-  exp_frame_time: 16.623
-  exp_frame_time: 16.707
-  avg_surface_fps: 59.86008821173197
-  exp_avg_surface_fps: 59.861591661151287
-}
diff --git a/test/trace_processor/chrome/frame_times_metric.sql b/test/trace_processor/chrome/frame_times_metric.sql
deleted file mode 100644
index 28c0c42..0000000
--- a/test/trace_processor/chrome/frame_times_metric.sql
+++ /dev/null
@@ -1,18 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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('experimental/frame_times.sql') AS suppress_query_output;
-
-SELECT * FROM AvgSurfaceFps;
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
deleted file mode 100644
index 5466346..0000000
--- a/test/trace_processor/chrome/index
+++ /dev/null
@@ -1,42 +0,0 @@
-# Tests related to Chrome's use of Perfetto.
-
-# Chrome metrics (found in the trace_processor/chrome directory).
-../../data/chrome_scroll_without_vsync.pftrace scroll_jank_general_validation.sql scroll_jank_general_validation.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_jank.sql scroll_jank.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_flow_event.sql scroll_flow_event.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_flow_event_general_validation.sql scroll_flow_event_general_validation.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_jank_cause.sql scroll_jank_cause.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_flow_event_queuing_delay.sql scroll_flow_event_queuing_delay.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_flow_event_queuing_delay_general_validation.sql scroll_flow_event_general_validation.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_jank_cause_queuing_delay.sql scroll_jank_cause_queuing_delay.out
-../../data/chrome_scroll_without_vsync.pftrace scroll_jank_cause_queuing_delay_general_validation.sql scroll_jank_cause_queuing_delay_general_validation.out
-../../data/chrome_scroll_without_vsync.pftrace chrome_thread_slice_with_cpu_time.sql chrome_thread_slice_with_cpu_time.out
-../track_event/track_event_counters.textproto chrome_thread_slice_with_cpu_time_repeated.sql chrome_thread_slice_with_cpu_time_repeated.out
-../../data/chrome_rendering_desktop.pftrace frame_times frame_times_metric.out
-scroll_jank_mojo_simple_watcher.py scroll_jank_mojo_simple_watcher.sql scroll_jank_mojo_simple_watcher.out
-
-# Chrome memory snapshots.
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_general_validation.sql memory_snapshot_general_validation.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_os_dump_events.sql memory_snapshot_os_dump_events.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_chrome_dump_events.sql memory_snapshot_chrome_dump_events.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_nodes.sql memory_snapshot_nodes.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_edges.sql memory_snapshot_edges.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_node_args.sql memory_snapshot_node_args.out
-../../data/chrome_memory_snapshot.pftrace memory_snapshot_smaps.sql memory_snapshot_smaps.out
-
-# RAIL modes.
-combined_rail_modes.py combined_rail_modes.sql combined_rail_modes.out
-cpu_time_by_combined_rail_mode.py cpu_time_by_combined_rail_mode.sql cpu_time_by_combined_rail_mode.out
-actual_power_by_combined_rail_mode.py actual_power_by_combined_rail_mode.sql actual_power_by_combined_rail_mode.out
-estimated_power_by_combined_rail_mode.py estimated_power_by_combined_rail_mode.sql estimated_power_by_combined_rail_mode.out
-modified_rail_modes.py modified_rail_modes.sql modified_rail_modes.out
-modified_rail_modes_no_vsyncs.py modified_rail_modes.sql modified_rail_modes_no_vsyncs.out
-modified_rail_modes_with_input.py modified_rail_modes_with_input.sql modified_rail_modes_with_input.out
-modified_rail_modes_long.py modified_rail_modes.sql modified_rail_modes_long.out
-modified_rail_modes_extra_long.py modified_rail_modes.sql modified_rail_modes_extra_long.out
-
-# Chrome processes.
-../../data/chrome_scroll_without_vsync.pftrace chrome_processes.sql chrome_processes.out
-../../data/chrome_android_systrace.pftrace chrome_processes.sql chrome_processes_android_systrace.out
-../../data/chrome_scroll_without_vsync.pftrace chrome_threads.sql chrome_threads.out
-../../data/chrome_android_systrace.pftrace chrome_threads.sql chrome_threads_android_systrace.out
diff --git a/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.out b/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.out
deleted file mode 100644
index aea49aa..0000000
--- a/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"process_snapshot_id","upid","snapshot_id","timestamp","detail_level"
-0,1,0,111027205123000,"detailed"
-1,2,0,111027205123000,"detailed"
-2,3,0,111027205123000,"detailed"
-3,5,0,111027205123000,"detailed"
-4,4,0,111027205123000,"detailed"
-5,8,0,111027205123000,"detailed"
-6,6,0,111027205123000,"detailed"
-7,7,0,111027205123000,"detailed"
-8,0,0,111027205123000,"detailed"
-9,1,1,111037187565000,"detailed"
-10,2,1,111037187565000,"detailed"
-11,3,1,111037187565000,"detailed"
-12,5,1,111037187565000,"detailed"
-13,4,1,111037187565000,"detailed"
-14,8,1,111037187565000,"detailed"
-15,6,1,111037187565000,"detailed"
-16,7,1,111037187565000,"detailed"
-17,0,1,111037187565000,"detailed"
diff --git a/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.sql b/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.sql
deleted file mode 100644
index 67fbf86..0000000
--- a/test/trace_processor/chrome/memory_snapshot_chrome_dump_events.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  pms.id AS process_snapshot_id,
-  upid,
-  snapshot_id,
-  timestamp,
-  detail_level
-FROM memory_snapshot ms
-LEFT JOIN process_memory_snapshot pms
-  ON ms.id = pms.snapshot_id
diff --git a/test/trace_processor/chrome/memory_snapshot_edges.out b/test/trace_processor/chrome/memory_snapshot_edges.out
deleted file mode 100644
index 15bb371..0000000
--- a/test/trace_processor/chrome/memory_snapshot_edges.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"id","source_node_id","target_node_id","importance"
-0,1734,1863,0
-1,1728,1839,0
-2,1732,1772,0
-3,1729,1786,0
-4,1730,1805,0
-5,1735,1859,0
-6,1733,1844,0
-7,1727,1840,0
-8,1731,1850,0
-9,1726,1849,0
-10,1636,1639,0
-11,1681,1846,0
-12,1683,1744,0
-13,1680,1849,0
-14,1682,1859,0
-15,1707,1621,0
-16,1634,1638,0
-17,1399,1193,0
-18,1083,1795,2
-19,1358,1846,0
diff --git a/test/trace_processor/chrome/memory_snapshot_edges.sql b/test/trace_processor/chrome/memory_snapshot_edges.sql
deleted file mode 100644
index 63307ad..0000000
--- a/test/trace_processor/chrome/memory_snapshot_edges.sql
+++ /dev/null
@@ -1,23 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  id,
-  source_node_id,
-  target_node_id,
-  importance
-FROM memory_snapshot_edge
-LIMIT 20
diff --git a/test/trace_processor/chrome/memory_snapshot_general_validation.out b/test/trace_processor/chrome/memory_snapshot_general_validation.out
deleted file mode 100644
index cb203ee..0000000
--- a/test/trace_processor/chrome/memory_snapshot_general_validation.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"total_snapshots","total_processes","total_process_snapshots","total_nodes","total_edges","total_node_args","total_smaps"
-2,9,18,3584,788,5014,33979
diff --git a/test/trace_processor/chrome/memory_snapshot_general_validation.sql b/test/trace_processor/chrome/memory_snapshot_general_validation.sql
deleted file mode 100644
index 4075041..0000000
--- a/test/trace_processor/chrome/memory_snapshot_general_validation.sql
+++ /dev/null
@@ -1,41 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  (
-    SELECT COUNT(*) FROM memory_snapshot
-  ) AS total_snapshots,
-  (
-    SELECT COUNT(*) FROM process
-  ) AS total_processes,
-  (
-    SELECT COUNT(*) FROM process_memory_snapshot
-  ) AS total_process_snapshots,
-  (
-    SELECT COUNT(*) FROM memory_snapshot_node
-  ) AS total_nodes,
-  (
-    SELECT COUNT(*) FROM memory_snapshot_edge
-  ) AS total_edges,
-  (
-    SELECT COUNT(DISTINCT args.id)
-    FROM args
-    INNER JOIN memory_snapshot_node
-    ON args.arg_set_id = memory_snapshot_node.arg_set_id
-  ) AS total_node_args,
-  (
-    SELECT COUNT(*) FROM profiler_smaps
-    INNER JOIN memory_snapshot ON timestamp = ts
-  ) AS total_smaps
diff --git a/test/trace_processor/chrome/memory_snapshot_node_args.out b/test/trace_processor/chrome/memory_snapshot_node_args.out
deleted file mode 100644
index c6adffe..0000000
--- a/test/trace_processor/chrome/memory_snapshot_node_args.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"node_id","key","value_type","int_value","string_value"
-20,"id.value","string","[NULL]","C7BC3FD59A40689345EB9CB08570641B"
-20,"locked_size.value","int",0,"[NULL]"
-20,"locked_size.unit","string","[NULL]","bytes"
-20,"virtual_size.value","int",961,"[NULL]"
-20,"virtual_size.unit","string","[NULL]","bytes"
-21,"id.value","string","[NULL]","AF621E3BE175B9B618BAADF9138E5598"
-21,"locked_size.value","int",0,"[NULL]"
-21,"locked_size.unit","string","[NULL]","bytes"
-21,"virtual_size.value","int",529,"[NULL]"
-21,"virtual_size.unit","string","[NULL]","bytes"
-30,"free_size.value","int",1048576,"[NULL]"
-30,"free_size.unit","string","[NULL]","bytes"
-32,"free_size.value","int",65472,"[NULL]"
-32,"free_size.unit","string","[NULL]","bytes"
-54,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Site Characteristics Database"
-57,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Sync Data/LevelDB"
-60,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/shared_proto_db/metadata"
-63,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/GCM Store/Encryption"
-66,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Service Worker/Database"
-69,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Extension Rules"
diff --git a/test/trace_processor/chrome/memory_snapshot_node_args.sql b/test/trace_processor/chrome/memory_snapshot_node_args.sql
deleted file mode 100644
index 03df9e9..0000000
--- a/test/trace_processor/chrome/memory_snapshot_node_args.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  node.id AS node_id,
-  key,
-  value_type,
-  int_value,
-  string_value
-FROM memory_snapshot_node node
-INNER JOIN args ON node.arg_set_id = args.arg_set_id
-LIMIT 20
diff --git a/test/trace_processor/chrome/memory_snapshot_nodes.out b/test/trace_processor/chrome/memory_snapshot_nodes.out
deleted file mode 100644
index 39a8108..0000000
--- a/test/trace_processor/chrome/memory_snapshot_nodes.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"id","process_snapshot_id","parent_node_id","path","size","effective_size"
-0,0,"[NULL]","cc",2899968,2899968
-1,0,0,"cc/tile_memory",2899968,2899968
-2,0,1,"cc/tile_memory/provider_0",2899968,2899968
-3,0,2,"cc/tile_memory/provider_0/resource_10",262144,262144
-4,0,2,"cc/tile_memory/provider_0/resource_11",131072,131072
-5,0,2,"cc/tile_memory/provider_0/resource_14",262144,262144
-6,0,2,"cc/tile_memory/provider_0/resource_15",131072,131072
-7,0,2,"cc/tile_memory/provider_0/resource_21",262144,262144
-8,0,2,"cc/tile_memory/provider_0/resource_23",262144,262144
-9,0,2,"cc/tile_memory/provider_0/resource_26",131072,131072
-10,0,2,"cc/tile_memory/provider_0/resource_3",262144,262144
-11,0,2,"cc/tile_memory/provider_0/resource_31",131072,131072
-12,0,2,"cc/tile_memory/provider_0/resource_36",262144,262144
-13,0,2,"cc/tile_memory/provider_0/resource_4",131072,131072
-14,0,2,"cc/tile_memory/provider_0/resource_41",16384,16384
-15,0,2,"cc/tile_memory/provider_0/resource_42",262144,262144
-16,0,2,"cc/tile_memory/provider_0/resource_7",262144,262144
-17,0,2,"cc/tile_memory/provider_0/resource_8",131072,131072
-18,0,"[NULL]","discardable",16384,16384
-19,0,18,"discardable/process_ffffffff",16384,16384
diff --git a/test/trace_processor/chrome/memory_snapshot_nodes.sql b/test/trace_processor/chrome/memory_snapshot_nodes.sql
deleted file mode 100644
index 0c014d3..0000000
--- a/test/trace_processor/chrome/memory_snapshot_nodes.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  id,
-  process_snapshot_id,
-  parent_node_id,
-  path,
-  size,
-  effective_size
-FROM memory_snapshot_node
-LIMIT 20
diff --git a/test/trace_processor/chrome/memory_snapshot_os_dump_events.out b/test/trace_processor/chrome/memory_snapshot_os_dump_events.out
deleted file mode 100644
index f1ce018..0000000
--- a/test/trace_processor/chrome/memory_snapshot_os_dump_events.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"upid","pid","name","timestamp","detail_level","private_footprint_kb","peak_resident_set_kb","is_peak_rss_resettable"
-0,0,"[NULL]",111027205123000,"detailed","[NULL]","[NULL]","[NULL]"
-1,29694,"Browser",111027205123000,"detailed",76656640.000000,479354880.000000,1
-2,29725,"GPU Process",111027205123000,"detailed",62836736.000000,280952832.000000,1
-3,29728,"Service: network.mojom.NetworkService",111027205123000,"detailed",35360768.000000,229261312.000000,1
-4,29764,"Service: data_decoder.mojom.DataDecoderService",111027205123000,"detailed",30576640.000000,201347072.000000,1
-5,29737,"Service: storage.mojom.StorageService",111027205123000,"detailed",30617600.000000,207138816.000000,1
-6,29833,"Renderer",111027205123000,"detailed",36802560.000000,264036352.000000,1
-7,29877,"Service: tracing.mojom.TracingService",111027205123000,"detailed",31002624.000000,199208960.000000,1
-8,29807,"Renderer",111027205123000,"detailed",87248896.000000,451424256.000000,1
-0,0,"[NULL]",111037187565000,"detailed","[NULL]","[NULL]","[NULL]"
-1,29694,"Browser",111037187565000,"detailed",85942272.000000,491671552.000000,1
-2,29725,"GPU Process",111037187565000,"detailed",62754816.000000,275906560.000000,1
-3,29728,"Service: network.mojom.NetworkService",111037187565000,"detailed",35495936.000000,229351424.000000,1
-4,29764,"Service: data_decoder.mojom.DataDecoderService",111037187565000,"detailed",30679040.000000,201424896.000000,1
-5,29737,"Service: storage.mojom.StorageService",111037187565000,"detailed",30650368.000000,205791232.000000,1
-6,29833,"Renderer",111037187565000,"detailed",36950016.000000,264843264.000000,1
-7,29877,"Service: tracing.mojom.TracingService",111037187565000,"detailed",33386496.000000,204554240.000000,1
-8,29807,"Renderer",111037187565000,"detailed",76832768.000000,445292544.000000,1
diff --git a/test/trace_processor/chrome/memory_snapshot_os_dump_events.sql b/test/trace_processor/chrome/memory_snapshot_os_dump_events.sql
deleted file mode 100644
index b266773..0000000
--- a/test/trace_processor/chrome/memory_snapshot_os_dump_events.sql
+++ /dev/null
@@ -1,42 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  p.upid,
-  pid,
-  p.name,
-  timestamp,
-  detail_level,
-  pf.value AS private_footprint_kb,
-  prs.value AS peak_resident_set_kb,
-  EXTRACT_ARG(p.arg_set_id, 'is_peak_rss_resettable') AS is_peak_rss_resettable
-FROM process p
-LEFT JOIN memory_snapshot
-LEFT JOIN (
-  SELECT id, upid
-  FROM process_counter_track
-  WHERE name IS 'chrome.private_footprint_kb'
-  ) AS pct_pf
-  ON p.upid = pct_pf.upid
-LEFT JOIN counter pf ON timestamp = pf.ts AND pct_pf.id = pf.track_id
-LEFT JOIN (
-  SELECT id, upid
-  FROM process_counter_track
-  WHERE name IS 'chrome.peak_resident_set_kb'
-  ) AS pct_prs
-  ON p.upid = pct_prs.upid
-LEFT JOIN counter prs ON timestamp = prs.ts AND pct_prs.id = prs.track_id
-ORDER BY timestamp
diff --git a/test/trace_processor/chrome/memory_snapshot_smaps.out b/test/trace_processor/chrome/memory_snapshot_smaps.out
deleted file mode 100644
index 255526d..0000000
--- a/test/trace_processor/chrome/memory_snapshot_smaps.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"upid","name","ts","path","size_kb","private_dirty_kb","swap_kb","file_name","start_address","module_timestamp","module_debugid","module_debug_path","protection_flags","private_clean_resident_kb","shared_dirty_resident_kb","shared_clean_resident_kb","locked_kb","proportional_resident_kb"
-1,"Browser",111027205123000,"[NULL]",4,0,0,"",14051238432768,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",40956,40464,0,"",14051238436864,0,"[NULL]","[NULL]",6,0,0,0,0,40464
-1,"Browser",111027205123000,"[NULL]",4,0,0,"",14051280375808,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",11860,8620,0,"",14051280379904,0,"[NULL]","[NULL]",6,0,0,0,0,8620
-1,"Browser",111027205123000,"[NULL]",67896,4,0,"/home/toki/chromium/src/out/Default/chrome",94168098267136,0,"[NULL]","[NULL]",4,6824,0,14812,0,8788
-1,"Browser",111027205123000,"[NULL]",123784,4,0,"/home/toki/chromium/src/out/Default/chrome",94168167792640,0,"[NULL]","[NULL]",5,62584,0,28044,0,70896
-1,"Browser",111027205123000,"[NULL]",3036,3036,0,"/home/toki/chromium/src/out/Default/chrome",94168294547456,0,"[NULL]","[NULL]",4,0,0,0,0,3036
-1,"Browser",111027205123000,"[NULL]",148,136,0,"/home/toki/chromium/src/out/Default/chrome",94168297656320,0,"[NULL]","[NULL]",6,0,0,12,0,137
-1,"Browser",111027205123000,"[NULL]",404,240,0,"",94168297807872,0,"[NULL]","[NULL]",6,0,0,0,0,240
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/dev/shm/.org.chromium.Chromium.Doo3XC (deleted)",140632555954176,0,"[NULL]","[NULL]",134,0,4,0,0,2
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/dev/shm/.org.chromium.Chromium.PxFFQm (deleted)",140632558575616,0,"[NULL]","[NULL]",134,0,4,0,0,2
-1,"Browser",111027205123000,"[NULL]",428,0,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632563163136,0,"[NULL]","[NULL]",5,128,0,136,0,196
-1,"Browser",111027205123000,"[NULL]",2044,0,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632563601408,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",68,68,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632565694464,0,"[NULL]","[NULL]",4,0,0,0,0,68
-1,"Browser",111027205123000,"[NULL]",40,40,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632565764096,0,"[NULL]","[NULL]",6,0,0,0,0,40
-1,"Browser",111027205123000,"[NULL]",668,0,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632565805056,0,"[NULL]","[NULL]",5,340,0,16,0,344
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632566489088,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",8,8,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632568586240,0,"[NULL]","[NULL]",4,0,0,0,0,8
-1,"Browser",111027205123000,"[NULL]",4,4,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632568594432,0,"[NULL]","[NULL]",6,0,0,0,0,4
-1,"Browser",111027205123000,"[NULL]",16,16,0,"",140632568598528,0,"[NULL]","[NULL]",6,0,0,0,0,16
diff --git a/test/trace_processor/chrome/memory_snapshot_smaps.sql b/test/trace_processor/chrome/memory_snapshot_smaps.sql
deleted file mode 100644
index dfd1fce..0000000
--- a/test/trace_processor/chrome/memory_snapshot_smaps.sql
+++ /dev/null
@@ -1,39 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  process.upid,
-  process.name,
-  smap.ts,
-  path,
-  size_kb,
-  private_dirty_kb,
-  swap_kb,
-  file_name,
-  start_address,
-  module_timestamp,
-  module_debugid,
-  module_debug_path,
-  protection_flags,
-  private_clean_resident_kb,
-  shared_dirty_resident_kb,
-  shared_clean_resident_kb,
-  locked_kb,
-  proportional_resident_kb
-FROM process
-INNER JOIN profiler_smaps smap ON process.upid = smap.upid
-INNER JOIN memory_snapshot ms ON ms.timestamp = smap.ts
-LIMIT 20
diff --git a/test/trace_processor/chrome/modified_rail_modes.out b/test/trace_processor/chrome/modified_rail_modes.out
deleted file mode 100644
index 688609b..0000000
--- a/test/trace_processor/chrome/modified_rail_modes.out
+++ /dev/null
@@ -1,7 +0,0 @@
-
-"id","ts","dur","mode"
-2,0,1000000000,"response"
-3,1000000000,1950000000,"foreground_idle"
-4,2950000000,333333324,"animation"
-5,3283333324,216666676,"foreground_idle"
-6,3500000000,1000000000,"background"
diff --git a/test/trace_processor/chrome/modified_rail_modes.py b/test/trace_processor/chrome/modified_rail_modes.py
deleted file mode 100644
index 2369059..0000000
--- a/test/trace_processor/chrome/modified_rail_modes.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-frame_period = s_to_ns(1.0 / 60)
-
-trace.add_track_event_slice("VSync", ts=s_to_ns(3), dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period, dur=10, track=gpu_track)
-# Frame skipped, but modified rail mode won't go back to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 3, dur=10, track=gpu_track)
-# Larger gap now when mode will go to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 12, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 13, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 14, dur=10, track=gpu_track)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/modified_rail_modes.sql b/test/trace_processor/chrome/modified_rail_modes.sql
deleted file mode 100644
index 053aca8..0000000
--- a/test/trace_processor/chrome/modified_rail_modes.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql') AS suppress_query_output;
-SELECT * FROM modified_rail_slices;
diff --git a/test/trace_processor/chrome/modified_rail_modes_extra_long.out b/test/trace_processor/chrome/modified_rail_modes_extra_long.out
deleted file mode 100644
index 9223cac..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_extra_long.out
+++ /dev/null
@@ -1,2 +0,0 @@
-
-"id","ts","dur","mode"
diff --git a/test/trace_processor/chrome/modified_rail_modes_extra_long.py b/test/trace_processor/chrome/modified_rail_modes_extra_long.py
deleted file mode 100644
index da6731f..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_extra_long.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# ceased to ensure that the RAIL mode is extended to the end of the process
-# rather than the end of the trace itself.
-# Generate an extra long trace event making the trace longer than 10 minutes
-# causing the trace to be completely excluded.
-trace.add_track_event_slice("VSync", ts=s_to_ns(1000), dur=10, track=gpu_track)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/modified_rail_modes_long.out b/test/trace_processor/chrome/modified_rail_modes_long.out
deleted file mode 100644
index 5b9f13a..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_long.out
+++ /dev/null
@@ -1,4 +0,0 @@
-
-"id","ts","dur","mode"
-2,0,1000000000,"response"
-3,1000000000,1,"background"
diff --git a/test/trace_processor/chrome/modified_rail_modes_long.py b/test/trace_processor/chrome/modified_rail_modes_long.py
deleted file mode 100644
index a0b4f67..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_long.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# Generate an extra trace event long after events on the renderer process have
-# ceased to ensure that the RAIL mode is extended to the end of the process
-# rather than the end of the trace itself.
-trace.add_track_event_slice("VSync", ts=s_to_ns(25), dur=10, track=gpu_track)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.out b/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.out
deleted file mode 100644
index 70b920c..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"id","ts","dur","mode"
-2,0,1000000000,"response"
-3,1000000000,2500000000,"foreground_idle"
-4,3500000000,1000000000,"background"
diff --git a/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.py b/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.py
deleted file mode 100644
index 1c363dd..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_no_vsyncs.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/modified_rail_modes_with_input.out b/test/trace_processor/chrome/modified_rail_modes_with_input.out
deleted file mode 100644
index 66af894..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_with_input.out
+++ /dev/null
@@ -1,9 +0,0 @@
-
-"id","ts","dur","mode"
-2,0,1000000000,"response"
-3,1000000000,1950000000,"foreground_idle"
-4,2950000000,50000000,"animation"
-5,3000000000,66666674,"response"
-6,3066666674,216666650,"animation"
-7,3283333324,216666676,"foreground_idle"
-8,3500000000,1000000000,"background"
diff --git a/test/trace_processor/chrome/modified_rail_modes_with_input.py b/test/trace_processor/chrome/modified_rail_modes_with_input.py
deleted file mode 100644
index e7b612e..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_with_input.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-frame_period = s_to_ns(1.0 / 60)
-
-trace.add_track_event_slice("VSync", ts=s_to_ns(3), dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period, dur=10, track=gpu_track)
-# Frame skipped, but modified rail mode won't go back to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 3, dur=10, track=gpu_track)
-# Larger gap now when mode will go to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 12, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 13, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 14, dur=10, track=gpu_track)
-
-trace.add_track_event_slice(
-    "InputLatency::GestureScrollBegin", ts=s_to_ns(3), dur=10)
-trace.add_track_event_slice(
-    "InputLatency::GestureScrollEnd", ts=s_to_ns(3) + frame_period * 4, dur=10)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/modified_rail_modes_with_input.sql b/test/trace_processor/chrome/modified_rail_modes_with_input.sql
deleted file mode 100644
index 053aca8..0000000
--- a/test/trace_processor/chrome/modified_rail_modes_with_input.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/rail_modes.sql') AS suppress_query_output;
-SELECT * FROM modified_rail_slices;
diff --git a/test/trace_processor/chrome/scroll_flow_event.out b/test/trace_processor/chrome/scroll_flow_event.out
deleted file mode 100644
index 569ae86..0000000
--- a/test/trace_processor/chrome/scroll_flow_event.out
+++ /dev/null
@@ -1,1114 +0,0 @@
-
-"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
-2709,544958000403,19009426,0,"AsyncBegin",544958000403,544959793403,544960259403,2709,"Begin"
-2709,544960259403,2000,0,"Begin",544960452403,544959793403,544960408403,2709,"STEP_SEND_INPUT_EVENT_UI"
-2709,544960408403,33000,0,"STEP_SEND_INPUT_EVENT_UI",544960452403,544960696611,544960702611,2709,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2709,544960702611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544960714611,544965468611,544965475611,2709,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2709,544965475611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544965507611,544966414611,544966414611,2709,"STEP_SWAP_BUFFERS"
-2709,544966414611,1000,0,"STEP_SWAP_BUFFERS",544966415611,544967888829,544967888829,2709,"STEP_DRAW_AND_SWAP"
-2709,544967888829,2000,0,"STEP_DRAW_AND_SWAP",544967890829,544977012829,544977012829,2709,"End"
-2709,544977012829,1000,0,"End",544977013829,"[NULL]",544966000403,2711,"AsyncBegin"
-2711,544966000403,22609426,0,"AsyncBegin",544966000403,544967825403,544967961403,2711,"Begin"
-2711,544967961403,2000,0,"Begin",544968036403,544967825403,544967991403,2711,"STEP_SEND_INPUT_EVENT_UI"
-2711,544967991403,33000,0,"STEP_SEND_INPUT_EVENT_UI",544968036403,544968345611,544968348611,2711,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2711,544968348611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544968359611,544976665611,544976668611,2711,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2711,544976668611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544976702611,544977398611,544977398611,2711,"STEP_SWAP_BUFFERS"
-2711,544977398611,5000,0,"STEP_SWAP_BUFFERS",544977403611,544978840829,544978840829,2711,"STEP_DRAW_AND_SWAP"
-2711,544978840829,8000,0,"STEP_DRAW_AND_SWAP",544978848829,544988619829,544988619829,2711,"End"
-2711,544988619829,2000,0,"End",544988621829,"[NULL]",544983000403,2715,"AsyncBegin"
-2715,544983000403,28089426,0,"AsyncBegin",544983000403,544984070403,544984265403,2715,"Begin"
-2715,544984265403,2000,0,"Begin",544984392403,544984070403,544984299403,2715,"STEP_SEND_INPUT_EVENT_UI"
-2715,544984299403,39000,0,"STEP_SEND_INPUT_EVENT_UI",544984392403,544984409611,544984412611,2715,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2715,544984412611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544984423611,544988228611,544988232611,2715,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2715,544988232611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544988268611,544989548611,544989548611,2715,"STEP_SWAP_BUFFERS"
-2715,544989548611,6000,0,"STEP_SWAP_BUFFERS",544989554611,545001087829,545001087829,2715,"STEP_DRAW_AND_SWAP"
-2715,545001087829,8000,0,"STEP_DRAW_AND_SWAP",545001095829,545011097829,545011097829,2715,"End"
-2715,545011097829,2000,0,"End",545011099829,"[NULL]",544991000403,2717,"AsyncBegin"
-2717,544991000403,30714426,0,"AsyncBegin",544991000403,544992452403,544992612403,2717,"Begin"
-2717,544992612403,2000,0,"Begin",544992695403,544992452403,544992644403,2717,"STEP_SEND_INPUT_EVENT_UI"
-2717,544992644403,36000,0,"STEP_SEND_INPUT_EVENT_UI",544992695403,544992755611,544992757611,2717,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2717,544992757611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544992767611,544999304611,544999309611,2717,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2717,544999309611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544999349611,545000565611,545000565611,2717,"STEP_SWAP_BUFFERS"
-2717,545000565611,7000,0,"STEP_SWAP_BUFFERS",545000572611,545011641829,545011641829,2717,"STEP_DRAW_AND_SWAP"
-2717,545011641829,5000,0,"STEP_DRAW_AND_SWAP",545011646829,545021756829,545021756829,2717,"End"
-2717,545021756829,9000,0,"End",545021765829,"[NULL]",544999000403,2719,"AsyncBegin"
-2719,544999000403,34740426,0,"AsyncBegin",544999000403,545000581403,545000721403,2719,"Begin"
-2719,545000721403,1000,0,"Begin",545000923403,545000581403,545000748403,2719,"STEP_SEND_INPUT_EVENT_UI"
-2719,545000748403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545000923403,545000825611,545000827611,2719,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2719,545000827611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545000836611,545010457611,545010461611,2719,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2719,545010461611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545010555611,545011228611,545011228611,2719,"STEP_SWAP_BUFFERS"
-2719,545011228611,7000,0,"STEP_SWAP_BUFFERS",545011235611,545023105829,545023105829,2719,"STEP_DRAW_AND_SWAP"
-2719,545023105829,8000,0,"STEP_DRAW_AND_SWAP",545023113829,545033749829,545033749829,2719,"End"
-2719,545033749829,2000,0,"End",545033751829,"[NULL]",545007000403,2721,"AsyncBegin"
-2721,545007000403,37462426,0,"AsyncBegin",545007000403,545010006403,545010187403,2721,"Begin"
-2721,545010187403,1000,0,"Begin",545010323403,545010006403,545010267403,2721,"STEP_SEND_INPUT_EVENT_UI"
-2721,545010267403,41000,0,"STEP_SEND_INPUT_EVENT_UI",545010323403,545010685611,545010687611,2721,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2721,545010687611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545010695611,545021699611,545021703611,2721,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2721,545021703611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545021748611,545022454611,545022454611,2721,"STEP_SWAP_BUFFERS"
-2721,545022454611,5000,0,"STEP_SWAP_BUFFERS",545022459611,545034641829,545034641829,2721,"STEP_DRAW_AND_SWAP"
-2721,545034641829,5000,0,"STEP_DRAW_AND_SWAP",545034646829,545044471829,545044471829,2721,"End"
-2721,545044471829,3000,0,"End",545044474829,"[NULL]",545024000403,2725,"AsyncBegin"
-2725,545024000403,31889426,1,"AsyncBegin",545024000403,545025279403,545025586403,2725,"Begin"
-2725,545025586403,2000,1,"Begin",545025746403,545025279403,545025615403,2725,"STEP_SEND_INPUT_EVENT_UI"
-2725,545025615403,117000,1,"STEP_SEND_INPUT_EVENT_UI",545025746403,545025698611,545025703611,2725,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2725,545025703611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",545025713611,545033251611,545033256611,2725,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2725,545033256611,3000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545033344611,545034007611,545034007611,2725,"STEP_SWAP_BUFFERS"
-2725,545034007611,5000,1,"STEP_SWAP_BUFFERS",545034012611,545047703829,545047703829,2725,"STEP_DRAW_AND_SWAP"
-2725,545047703829,1000,1,"STEP_DRAW_AND_SWAP",545047704829,545055892829,545055892829,2725,"End"
-2725,545055892829,1000,1,"End",545055893829,"[NULL]",545032000403,2727,"AsyncBegin"
-2727,545032000403,23876426,0,"AsyncBegin",545032000403,545033878403,545034017403,2727,"Begin"
-2727,545034017403,1000,0,"Begin",545034128403,545033878403,545034048403,2727,"STEP_SEND_INPUT_EVENT_UI"
-2727,545034048403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545034128403,545034224611,545034228611,2727,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2727,545034228611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545034237611,545044106611,545044111611,2727,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2727,545044111611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545044160611,545046053611,545046053611,2727,"STEP_SWAP_BUFFERS"
-2727,545046053611,8000,0,"STEP_SWAP_BUFFERS",545046061611,545047694829,545047694829,2727,"STEP_DRAW_AND_SWAP"
-2727,545047694829,7000,0,"STEP_DRAW_AND_SWAP",545047701829,545055884829,545055884829,2727,"End"
-2727,545055884829,2000,0,"End",545055886829,"[NULL]",545040000403,2729,"AsyncBegin"
-2729,545040000403,28316426,0,"AsyncBegin",545040000403,545047588403,545047706403,2729,"Begin"
-2729,545047706403,2000,0,"Begin",545047774403,545047588403,545047731403,2729,"STEP_SEND_INPUT_EVENT_UI"
-2729,545047731403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545047774403,545047812611,545047814611,2729,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2729,545047814611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545047825611,545055643611,545055671611,2729,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2729,545055671611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545055758611,545057874611,545057874611,2729,"STEP_SWAP_BUFFERS"
-2729,545057874611,10000,0,"STEP_SWAP_BUFFERS",545057884611,545059449829,545059449829,2729,"STEP_DRAW_AND_SWAP"
-2729,545059449829,9000,0,"STEP_DRAW_AND_SWAP",545059458829,545068323829,545068323829,2729,"End"
-2729,545068323829,2000,0,"End",545068325829,"[NULL]",545056000403,2733,"AsyncBegin"
-2733,545056000403,22620426,0,"AsyncBegin",545056000403,545059559403,545059690403,2733,"Begin"
-2733,545059690403,2000,0,"Begin",545059790403,545059559403,545059716403,2733,"STEP_SEND_INPUT_EVENT_UI"
-2733,545059716403,61000,0,"STEP_SEND_INPUT_EVENT_UI",545059790403,545059828611,545059831611,2733,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2733,545059831611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545059841611,545066118611,545066123611,2733,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2733,545066123611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545066163611,545068329611,545068329611,2733,"STEP_SWAP_BUFFERS"
-2733,545068329611,6000,0,"STEP_SWAP_BUFFERS",545068335611,545068802829,545068802829,2733,"STEP_DRAW_AND_SWAP"
-2733,545068802829,5000,0,"STEP_DRAW_AND_SWAP",545068807829,545078626829,545078626829,2733,"End"
-2733,545078626829,3000,0,"End",545078629829,"[NULL]",545065000403,2735,"AsyncBegin"
-2735,545065000403,23642426,0,"AsyncBegin",545065000403,545066840403,545067063403,2735,"Begin"
-2735,545067063403,3000,0,"Begin",545067143403,545066840403,545067095403,2735,"STEP_SEND_INPUT_EVENT_UI"
-2735,545067095403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545067143403,545067180611,545067186611,2735,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2735,545067186611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545067198611,545077803611,545077807611,2735,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2735,545077807611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545077844611,545079568611,545079568611,2735,"STEP_SWAP_BUFFERS"
-2735,545079568611,6000,0,"STEP_SWAP_BUFFERS",545079574611,545079993829,545079993829,2735,"STEP_DRAW_AND_SWAP"
-2735,545079993829,6000,0,"STEP_DRAW_AND_SWAP",545079999829,545088650829,545088650829,2735,"End"
-2735,545088650829,1000,0,"End",545088651829,"[NULL]",545081000403,2739,"AsyncBegin"
-2739,545081000403,19016426,0,"AsyncBegin",545081000403,545082897403,545083178403,2739,"Begin"
-2739,545083178403,1000,0,"Begin",545083448403,545082897403,545083322403,2739,"STEP_SEND_INPUT_EVENT_UI"
-2739,545083322403,113000,0,"STEP_SEND_INPUT_EVENT_UI",545083448403,545083401611,545083406611,2739,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2739,545083406611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545083416611,545088483611,545088487611,2739,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2739,545088487611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545088525611,545090577611,545090577611,2739,"STEP_SWAP_BUFFERS"
-2739,545090577611,7000,0,"STEP_SWAP_BUFFERS",545090584611,545091220829,545091220829,2739,"STEP_DRAW_AND_SWAP"
-2739,545091220829,6000,0,"STEP_DRAW_AND_SWAP",545091226829,545100025829,545100025829,2739,"End"
-2739,545100025829,2000,0,"End",545100027829,"[NULL]",545089000403,2741,"AsyncBegin"
-2741,545089000403,22491426,0,"AsyncBegin",545089000403,545090893403,545091180403,2741,"Begin"
-2741,545091180403,1000,0,"Begin",545091246403,545090893403,545091206403,2741,"STEP_SEND_INPUT_EVENT_UI"
-2741,545091206403,30000,0,"STEP_SEND_INPUT_EVENT_UI",545091246403,545091279611,545091284611,2741,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2741,545091284611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545091293611,545099726611,545099730611,2741,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2741,545099730611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545099774611,545101547611,545101547611,2741,"STEP_SWAP_BUFFERS"
-2741,545101547611,6000,0,"STEP_SWAP_BUFFERS",545101553611,545101957829,545101957829,2741,"STEP_DRAW_AND_SWAP"
-2741,545101957829,7000,0,"STEP_DRAW_AND_SWAP",545101964829,545111499829,545111499829,2741,"End"
-2741,545111499829,2000,0,"End",545111501829,"[NULL]",545098000403,2743,"AsyncBegin"
-2743,545098000403,24940426,0,"AsyncBegin",545098000403,545100311403,545100585403,2743,"Begin"
-2743,545100585403,1000,0,"Begin",545100658403,545100311403,545100613403,2743,"STEP_SEND_INPUT_EVENT_UI"
-2743,545100613403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545100658403,545100699611,545100704611,2743,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2743,545100704611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545100714611,545111157611,545111161611,2743,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2743,545111161611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545111274611,545113480611,545113480611,2743,"STEP_SWAP_BUFFERS"
-2743,545113480611,31000,0,"STEP_SWAP_BUFFERS",545113511611,545113945829,545113945829,2743,"STEP_DRAW_AND_SWAP"
-2743,545113945829,7000,0,"STEP_DRAW_AND_SWAP",545113952829,545122947829,545122947829,2743,"End"
-2743,545122947829,2000,0,"End",545122949829,"[NULL]",545114000403,2747,"AsyncBegin"
-2747,545114000403,19365426,0,"AsyncBegin",545114000403,545115387403,545115531403,2747,"Begin"
-2747,545115531403,1000,0,"Begin",545115601403,545115387403,545115557403,2747,"STEP_SEND_INPUT_EVENT_UI"
-2747,545115557403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545115601403,545115631611,545115633611,2747,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2747,545115633611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545115642611,545122513611,545122517611,2747,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2747,545122517611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545122556611,545124871611,545124871611,2747,"STEP_SWAP_BUFFERS"
-2747,545124871611,5000,0,"STEP_SWAP_BUFFERS",545124876611,545125297829,545125297829,2747,"STEP_DRAW_AND_SWAP"
-2747,545125297829,7000,0,"STEP_DRAW_AND_SWAP",545125304829,545133372829,545133372829,2747,"End"
-2747,545133372829,2000,0,"End",545133374829,"[NULL]",545122000403,2749,"AsyncBegin"
-2749,545122000403,22629426,0,"AsyncBegin",545122000403,545123889403,545124022403,2749,"Begin"
-2749,545124022403,1000,0,"Begin",545124095403,545123889403,545124047403,2749,"STEP_SEND_INPUT_EVENT_UI"
-2749,545124047403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545124095403,545124128611,545124131611,2749,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2749,545124131611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545124141611,545133176611,545133180611,2749,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2749,545133180611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545133220611,545135346611,545135346611,2749,"STEP_SWAP_BUFFERS"
-2749,545135346611,6000,0,"STEP_SWAP_BUFFERS",545135352611,545135871829,545135871829,2749,"STEP_DRAW_AND_SWAP"
-2749,545135871829,6000,0,"STEP_DRAW_AND_SWAP",545135877829,545144636829,545144636829,2749,"End"
-2749,545144636829,2000,0,"End",545144638829,"[NULL]",545139000403,2753,"AsyncBegin"
-2753,545139000403,17669426,0,"AsyncBegin",545139000403,545140415403,545140565403,2753,"Begin"
-2753,545140565403,1000,0,"Begin",545140662403,545140415403,545140591403,2753,"STEP_SEND_INPUT_EVENT_UI"
-2753,545140591403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545140662403,545140700611,545140702611,2753,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2753,545140702611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545140712611,545144685611,545144689611,2753,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2753,545144689611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545144727611,545146432611,545146432611,2753,"STEP_SWAP_BUFFERS"
-2753,545146432611,6000,0,"STEP_SWAP_BUFFERS",545146438611,545146884829,545146884829,2753,"STEP_DRAW_AND_SWAP"
-2753,545146884829,7000,0,"STEP_DRAW_AND_SWAP",545146891829,545156677829,545156677829,2753,"End"
-2753,545156677829,6000,0,"End",545156683829,"[NULL]",545147000403,2755,"AsyncBegin"
-2755,545147000403,20941426,0,"AsyncBegin",545147000403,545148122403,545148260403,2755,"Begin"
-2755,545148260403,1000,0,"Begin",545148331403,545148122403,545148285403,2755,"STEP_SEND_INPUT_EVENT_UI"
-2755,545148285403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545148331403,545148361611,545148363611,2755,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2755,545148363611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545148372611,545156212611,545156217611,2755,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2755,545156217611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545156278611,545158108611,545158108611,2755,"STEP_SWAP_BUFFERS"
-2755,545158108611,8000,0,"STEP_SWAP_BUFFERS",545158116611,545158576829,545158576829,2755,"STEP_DRAW_AND_SWAP"
-2755,545158576829,7000,0,"STEP_DRAW_AND_SWAP",545158583829,545167947829,545167947829,2755,"End"
-2755,545167947829,2000,0,"End",545167949829,"[NULL]",545155000403,2757,"AsyncBegin"
-2757,545155000403,23321426,0,"AsyncBegin",545155000403,545156464403,545156600403,2757,"Begin"
-2757,545156600403,1000,0,"Begin",545156744403,545156464403,545156676403,2757,"STEP_SEND_INPUT_EVENT_UI"
-2757,545156676403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545156744403,545156762611,545156766611,2757,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2757,545156766611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545156774611,545167101611,545167104611,2757,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2757,545167104611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545167206611,545168969611,545168969611,2757,"STEP_SWAP_BUFFERS"
-2757,545168969611,7000,0,"STEP_SWAP_BUFFERS",545168976611,545169358829,545169358829,2757,"STEP_DRAW_AND_SWAP"
-2757,545169358829,6000,0,"STEP_DRAW_AND_SWAP",545169364829,545178356829,545178356829,2757,"End"
-2757,545178356829,8000,0,"End",545178364829,"[NULL]",545172000403,2761,"AsyncBegin"
-2761,545172000403,18585426,0,"AsyncBegin",545172000403,545173174403,545173356403,2761,"Begin"
-2761,545173356403,1000,0,"Begin",545173435403,545173174403,545173385403,2761,"STEP_SEND_INPUT_EVENT_UI"
-2761,545173385403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545173435403,545173472611,545173475611,2761,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2761,545173475611,14000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545173490611,545178084611,545178088611,2761,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2761,545178088611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545178129611,545179809611,545179809611,2761,"STEP_SWAP_BUFFERS"
-2761,545179809611,7000,0,"STEP_SWAP_BUFFERS",545179816611,545180237829,545180237829,2761,"STEP_DRAW_AND_SWAP"
-2761,545180237829,6000,0,"STEP_DRAW_AND_SWAP",545180243829,545190593829,545190593829,2761,"End"
-2761,545190593829,2000,0,"End",545190595829,"[NULL]",545180000403,2763,"AsyncBegin"
-2763,545180000403,22430426,0,"AsyncBegin",545180000403,545181243403,545181398403,2763,"Begin"
-2763,545181398403,2000,0,"Begin",545181468403,545181243403,545181425403,2763,"STEP_SEND_INPUT_EVENT_UI"
-2763,545181425403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545181468403,545181531611,545181536611,2763,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2763,545181536611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545181548611,545189118611,545189123611,2763,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2763,545189123611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545189173611,545191077611,545191077611,2763,"STEP_SWAP_BUFFERS"
-2763,545191077611,7000,0,"STEP_SWAP_BUFFERS",545191084611,545191465829,545191465829,2763,"STEP_DRAW_AND_SWAP"
-2763,545191465829,6000,0,"STEP_DRAW_AND_SWAP",545191471829,545202437829,545202437829,2763,"End"
-2763,545202437829,3000,0,"End",545202440829,"[NULL]",545188000403,2765,"AsyncBegin"
-2765,545188000403,23545426,0,"AsyncBegin",545188000403,545189976403,545190209403,2765,"Begin"
-2765,545190209403,1000,0,"Begin",545190322403,545189976403,545190240403,2765,"STEP_SEND_INPUT_EVENT_UI"
-2765,545190240403,67000,0,"STEP_SEND_INPUT_EVENT_UI",545190322403,545190513611,545190516611,2765,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2765,545190516611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545190526611,545200643611,545200646611,2765,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2765,545200646611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545200689611,545202604611,545202604611,2765,"STEP_SWAP_BUFFERS"
-2765,545202604611,8000,0,"STEP_SWAP_BUFFERS",545202612611,545202995829,545202995829,2765,"STEP_DRAW_AND_SWAP"
-2765,545202995829,5000,0,"STEP_DRAW_AND_SWAP",545203000829,545211553829,545211553829,2765,"End"
-2765,545211553829,2000,0,"End",545211555829,"[NULL]",545204000403,2769,"AsyncBegin"
-2769,545204000403,19115426,0,"AsyncBegin",545204000403,545206091403,545206301403,2769,"Begin"
-2769,545206301403,1000,0,"Begin",545206390403,545206091403,545206338403,2769,"STEP_SEND_INPUT_EVENT_UI"
-2769,545206338403,38000,0,"STEP_SEND_INPUT_EVENT_UI",545206390403,545206465611,545206467611,2769,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2769,545206467611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545206478611,545211411611,545211415611,2769,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2769,545211415611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545211456611,545213184611,545213184611,2769,"STEP_SWAP_BUFFERS"
-2769,545213184611,7000,0,"STEP_SWAP_BUFFERS",545213191611,545213608829,545213608829,2769,"STEP_DRAW_AND_SWAP"
-2769,545213608829,6000,0,"STEP_DRAW_AND_SWAP",545213614829,545223124829,545223124829,2769,"End"
-2769,545223124829,2000,0,"End",545223126829,"[NULL]",545213000403,2771,"AsyncBegin"
-2771,545213000403,21107426,0,"AsyncBegin",545213000403,545214147403,545214275403,2771,"Begin"
-2771,545214275403,1000,0,"Begin",545214340403,545214147403,545214299403,2771,"STEP_SEND_INPUT_EVENT_UI"
-2771,545214299403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545214340403,545214374611,545214377611,2771,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2771,545214377611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545214385611,545222860611,545222864611,2771,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2771,545222864611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545222909611,545225019611,545225019611,2771,"STEP_SWAP_BUFFERS"
-2771,545225019611,9000,0,"STEP_SWAP_BUFFERS",545225028611,545225484829,545225484829,2771,"STEP_DRAW_AND_SWAP"
-2771,545225484829,9000,0,"STEP_DRAW_AND_SWAP",545225493829,545234115829,545234115829,2771,"End"
-2771,545234115829,2000,0,"End",545234117829,"[NULL]",545221000403,2773,"AsyncBegin"
-2773,545221000403,25065426,0,"AsyncBegin",545221000403,545226434403,545226563403,2773,"Begin"
-2773,545226563403,1000,0,"Begin",545226655403,545226434403,545226589403,2773,"STEP_SEND_INPUT_EVENT_UI"
-2773,545226589403,54000,0,"STEP_SEND_INPUT_EVENT_UI",545226655403,545226702611,545226704611,2773,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2773,545226704611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545226713611,545233818611,545233822611,2773,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2773,545233822611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545233859611,545237110611,545237110611,2773,"STEP_SWAP_BUFFERS"
-2773,545237110611,9000,0,"STEP_SWAP_BUFFERS",545237119611,545237603829,545237603829,2773,"STEP_DRAW_AND_SWAP"
-2773,545237603829,8000,0,"STEP_DRAW_AND_SWAP",545237611829,545246072829,545246072829,2773,"End"
-2773,545246072829,2000,0,"End",545246074829,"[NULL]",545237000403,2777,"AsyncBegin"
-2777,545237000403,20064426,0,"AsyncBegin",545237000403,545238907403,545239218403,2777,"Begin"
-2777,545239218403,1000,0,"Begin",545239371403,545238907403,545239246403,2777,"STEP_SEND_INPUT_EVENT_UI"
-2777,545239246403,112000,0,"STEP_SEND_INPUT_EVENT_UI",545239371403,545239325611,545239329611,2777,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2777,545239329611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545239339611,545244945611,545244948611,2777,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2777,545244948611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545244985611,545247198611,545247198611,2777,"STEP_SWAP_BUFFERS"
-2777,545247198611,6000,0,"STEP_SWAP_BUFFERS",545247204611,545247607829,545247607829,2777,"STEP_DRAW_AND_SWAP"
-2777,545247607829,7000,0,"STEP_DRAW_AND_SWAP",545247614829,545257072829,545257072829,2777,"End"
-2777,545257072829,2000,0,"End",545257074829,"[NULL]",545246000403,2779,"AsyncBegin"
-2779,545246000403,22190426,0,"AsyncBegin",545246000403,545247150403,545247287403,2779,"Begin"
-2779,545247287403,1000,0,"Begin",545247359403,545247150403,545247310403,2779,"STEP_SEND_INPUT_EVENT_UI"
-2779,545247310403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545247359403,545247400611,545247403611,2779,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2779,545247403611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545247411611,545256043611,545256046611,2779,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2779,545256046611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545256079611,545258338611,545258338611,2779,"STEP_SWAP_BUFFERS"
-2779,545258338611,7000,0,"STEP_SWAP_BUFFERS",545258345611,545258748829,545258748829,2779,"STEP_DRAW_AND_SWAP"
-2779,545258748829,6000,0,"STEP_DRAW_AND_SWAP",545258754829,545268197829,545268197829,2779,"End"
-2779,545268197829,2000,0,"End",545268199829,"[NULL]",545262000403,2783,"AsyncBegin"
-2783,545262000403,16635426,0,"AsyncBegin",545262000403,545263402403,545263579403,2783,"Begin"
-2783,545263579403,1000,0,"Begin",545263654403,545263402403,545263606403,2783,"STEP_SEND_INPUT_EVENT_UI"
-2783,545263606403,35000,0,"STEP_SEND_INPUT_EVENT_UI",545263654403,545263695611,545263698611,2783,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2783,545263698611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545263707611,545267807611,545267811611,2783,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2783,545267811611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545267849611,545269500611,545269500611,2783,"STEP_SWAP_BUFFERS"
-2783,545269500611,7000,0,"STEP_SWAP_BUFFERS",545269507611,545269887829,545269887829,2783,"STEP_DRAW_AND_SWAP"
-2783,545269887829,6000,0,"STEP_DRAW_AND_SWAP",545269893829,545278645829,545278645829,2783,"End"
-2783,545278645829,1000,0,"End",545278646829,"[NULL]",545270000403,2785,"AsyncBegin"
-2785,545270000403,19926426,0,"AsyncBegin",545270000403,545271631403,545271774403,2785,"Begin"
-2785,545271774403,1000,0,"Begin",545271847403,545271631403,545271799403,2785,"STEP_SEND_INPUT_EVENT_UI"
-2785,545271799403,35000,0,"STEP_SEND_INPUT_EVENT_UI",545271847403,545271884611,545271887611,2785,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2785,545271887611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545271897611,545278776611,545278780611,2785,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2785,545278780611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545278814611,545282047611,545282047611,2785,"STEP_SWAP_BUFFERS"
-2785,545282047611,7000,0,"STEP_SWAP_BUFFERS",545282054611,545282493829,545282493829,2785,"STEP_DRAW_AND_SWAP"
-2785,545282493829,7000,0,"STEP_DRAW_AND_SWAP",545282500829,545289934829,545289934829,2785,"End"
-2785,545289934829,3000,0,"End",545289937829,"[NULL]",545278000403,2787,"AsyncBegin"
-2787,545278000403,23003426,0,"AsyncBegin",545278000403,545279835403,545280350403,2787,"Begin"
-2787,545280350403,1000,0,"Begin",545280508403,545279835403,545280379403,2787,"STEP_SEND_INPUT_EVENT_UI"
-2787,545280379403,114000,0,"STEP_SEND_INPUT_EVENT_UI",545280508403,545280459611,545280463611,2787,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2787,545280463611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545280474611,545289598611,545289602611,2787,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2787,545289602611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545289638611,545291851611,545291851611,2787,"STEP_SWAP_BUFFERS"
-2787,545291851611,7000,0,"STEP_SWAP_BUFFERS",545291858611,545292308829,545292308829,2787,"STEP_DRAW_AND_SWAP"
-2787,545292308829,6000,0,"STEP_DRAW_AND_SWAP",545292314829,545301010829,545301010829,2787,"End"
-2787,545301010829,3000,0,"End",545301013829,"[NULL]",545295000403,2791,"AsyncBegin"
-2791,545295000403,17169426,0,"AsyncBegin",545295000403,545296719403,545296876403,2791,"Begin"
-2791,545296876403,2000,0,"Begin",545296947403,545296719403,545296903403,2791,"STEP_SEND_INPUT_EVENT_UI"
-2791,545296903403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545296947403,545296994611,545296996611,2791,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2791,545296996611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545297005611,545300799611,545300803611,2791,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2791,545300803611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545300842611,545303115611,545303115611,2791,"STEP_SWAP_BUFFERS"
-2791,545303115611,8000,0,"STEP_SWAP_BUFFERS",545303123611,545303582829,545303582829,2791,"STEP_DRAW_AND_SWAP"
-2791,545303582829,6000,0,"STEP_DRAW_AND_SWAP",545303588829,545312177829,545312177829,2791,"End"
-2791,545312177829,3000,0,"End",545312180829,"[NULL]",545303000403,2793,"AsyncBegin"
-2793,545303000403,20626426,0,"AsyncBegin",545303000403,545304395403,545304562403,2793,"Begin"
-2793,545304562403,2000,0,"Begin",545304626403,545304395403,545304589403,2793,"STEP_SEND_INPUT_EVENT_UI"
-2793,545304589403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545304626403,545304897611,545304899611,2793,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2793,545304899611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545304909611,545311974611,545311978611,2793,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2793,545311978611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545312021611,545314631611,545314631611,2793,"STEP_SWAP_BUFFERS"
-2793,545314631611,7000,0,"STEP_SWAP_BUFFERS",545314638611,545315150829,545315150829,2793,"STEP_DRAW_AND_SWAP"
-2793,545315150829,9000,0,"STEP_DRAW_AND_SWAP",545315159829,545323633829,545323633829,2793,"End"
-2793,545323633829,2000,0,"End",545323635829,"[NULL]",545311000403,2795,"AsyncBegin"
-2795,545311000403,23560426,0,"AsyncBegin",545311000403,545312582403,545312703403,2795,"Begin"
-2795,545312703403,1000,0,"Begin",545312768403,545312582403,545312729403,2795,"STEP_SEND_INPUT_EVENT_UI"
-2795,545312729403,28000,0,"STEP_SEND_INPUT_EVENT_UI",545312768403,545312811611,545312813611,2795,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2795,545312813611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545312823611,545323089611,545323093611,2795,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2795,545323093611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545323131611,545325014611,545325014611,2795,"STEP_SWAP_BUFFERS"
-2795,545325014611,6000,0,"STEP_SWAP_BUFFERS",545325020611,545325412829,545325412829,2795,"STEP_DRAW_AND_SWAP"
-2795,545325412829,6000,0,"STEP_DRAW_AND_SWAP",545325418829,545334569829,545334569829,2795,"End"
-2795,545334569829,2000,0,"End",545334571829,"[NULL]",545328000403,2799,"AsyncBegin"
-2799,545328000403,18191426,0,"AsyncBegin",545328000403,545329466403,545329632403,2799,"Begin"
-2799,545329632403,1000,0,"Begin",545329713403,545329466403,545329664403,2799,"STEP_SEND_INPUT_EVENT_UI"
-2799,545329664403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545329713403,545329815611,545329818611,2799,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2799,545329818611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545329830611,545334454611,545334458611,2799,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2799,545334458611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545334499611,545336543611,545336543611,2799,"STEP_SWAP_BUFFERS"
-2799,545336543611,7000,0,"STEP_SWAP_BUFFERS",545336550611,545336987829,545336987829,2799,"STEP_DRAW_AND_SWAP"
-2799,545336987829,8000,0,"STEP_DRAW_AND_SWAP",545336995829,545346227829,545346227829,2799,"End"
-2799,545346227829,8000,0,"End",545346235829,"[NULL]",545336000403,2801,"AsyncBegin"
-2801,545336000403,20911426,0,"AsyncBegin",545336000403,545337538403,545337677403,2801,"Begin"
-2801,545337677403,1000,0,"Begin",545337747403,545337538403,545337702403,2801,"STEP_SEND_INPUT_EVENT_UI"
-2801,545337702403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545337747403,545337769611,545337771611,2801,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2801,545337771611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545337780611,545345503611,545345508611,2801,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2801,545345508611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545345552611,545347962611,545347962611,2801,"STEP_SWAP_BUFFERS"
-2801,545347962611,7000,0,"STEP_SWAP_BUFFERS",545347969611,545348403829,545348403829,2801,"STEP_DRAW_AND_SWAP"
-2801,545348403829,6000,0,"STEP_DRAW_AND_SWAP",545348409829,545356918829,545356918829,2801,"End"
-2801,545356918829,2000,0,"End",545356920829,"[NULL]",545344000403,2803,"AsyncBegin"
-2803,545344000403,24228426,0,"AsyncBegin",545344000403,545345599403,545345731403,2803,"Begin"
-2803,545345731403,1000,0,"Begin",545345793403,545345599403,545345757403,2803,"STEP_SEND_INPUT_EVENT_UI"
-2803,545345757403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545345793403,545345808611,545345810611,2803,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2803,545345810611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545345818611,545356727611,545356732611,2803,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2803,545356732611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545356870611,545359100611,545359100611,2803,"STEP_SWAP_BUFFERS"
-2803,545359100611,8000,0,"STEP_SWAP_BUFFERS",545359108611,545359582829,545359582829,2803,"STEP_DRAW_AND_SWAP"
-2803,545359582829,8000,0,"STEP_DRAW_AND_SWAP",545359590829,545368235829,545368235829,2803,"End"
-2803,545368235829,2000,0,"End",545368237829,"[NULL]",545361000403,2807,"AsyncBegin"
-2807,545361000403,18189426,0,"AsyncBegin",545361000403,545362126403,545362271403,2807,"Begin"
-2807,545362271403,2000,0,"Begin",545362343403,545362126403,545362297403,2807,"STEP_SEND_INPUT_EVENT_UI"
-2807,545362297403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545362343403,545362382611,545362384611,2807,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2807,545362384611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545362394611,545367793611,545367796611,2807,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2807,545367796611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545367837611,545370187611,545370187611,2807,"STEP_SWAP_BUFFERS"
-2807,545370187611,7000,0,"STEP_SWAP_BUFFERS",545370194611,545370654829,545370654829,2807,"STEP_DRAW_AND_SWAP"
-2807,545370654829,7000,0,"STEP_DRAW_AND_SWAP",545370661829,545379195829,545379195829,2807,"End"
-2807,545379195829,2000,0,"End",545379197829,"[NULL]",545369000403,2809,"AsyncBegin"
-2809,545369000403,21379426,0,"AsyncBegin",545369000403,545370539403,545370671403,2809,"Begin"
-2809,545370671403,1000,0,"Begin",545370733403,545370539403,545370696403,2809,"STEP_SEND_INPUT_EVENT_UI"
-2809,545370696403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545370733403,545370891611,545370894611,2809,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2809,545370894611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545370901611,545379191611,545379195611,2809,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2809,545379195611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545379232611,545381354611,545381354611,2809,"STEP_SWAP_BUFFERS"
-2809,545381354611,7000,0,"STEP_SWAP_BUFFERS",545381361611,545381908829,545381908829,2809,"STEP_DRAW_AND_SWAP"
-2809,545381908829,8000,0,"STEP_DRAW_AND_SWAP",545381916829,545390387829,545390387829,2809,"End"
-2809,545390387829,2000,0,"End",545390389829,"[NULL]",545377000403,2811,"AsyncBegin"
-2811,545377000403,24913426,0,"AsyncBegin",545377000403,545378570403,545378746403,2811,"Begin"
-2811,545378746403,2000,0,"Begin",545378810403,545378570403,545378773403,2811,"STEP_SEND_INPUT_EVENT_UI"
-2811,545378773403,25000,0,"STEP_SEND_INPUT_EVENT_UI",545378810403,545379369611,545379371611,2811,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2811,545379371611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545379379611,545390128611,545390130611,2811,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2811,545390130611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545390169611,545391924611,545391924611,2811,"STEP_SWAP_BUFFERS"
-2811,545391924611,8000,0,"STEP_SWAP_BUFFERS",545391932611,545392344829,545392344829,2811,"STEP_DRAW_AND_SWAP"
-2811,545392344829,6000,0,"STEP_DRAW_AND_SWAP",545392350829,545401921829,545401921829,2811,"End"
-2811,545401921829,3000,0,"End",545401924829,"[NULL]",545394000403,2815,"AsyncBegin"
-2815,545394000403,18671426,0,"AsyncBegin",545394000403,545395127403,545395267403,2815,"Begin"
-2815,545395267403,1000,0,"Begin",545395366403,545395127403,545395293403,2815,"STEP_SEND_INPUT_EVENT_UI"
-2815,545395293403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545395366403,545395369611,545395371611,2815,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2815,545395371611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545395381611,545401928611,545401932611,2815,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2815,545401932611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545401973611,545403806611,545403806611,2815,"STEP_SWAP_BUFFERS"
-2815,545403806611,5000,0,"STEP_SWAP_BUFFERS",545403811611,545404248829,545404248829,2815,"STEP_DRAW_AND_SWAP"
-2815,545404248829,7000,0,"STEP_DRAW_AND_SWAP",545404255829,545412677829,545412677829,2815,"End"
-2815,545412677829,2000,0,"End",545412679829,"[NULL]",545402000403,2817,"AsyncBegin"
-2817,545402000403,21928426,0,"AsyncBegin",545402000403,545403261403,545403464403,2817,"Begin"
-2817,545403464403,2000,0,"Begin",545403612403,545403261403,545403500403,2817,"STEP_SEND_INPUT_EVENT_UI"
-2817,545403500403,94000,0,"STEP_SEND_INPUT_EVENT_UI",545403612403,545403638611,545403640611,2817,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2817,545403640611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545403649611,545412460611,545412464611,2817,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2817,545412464611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545412499611,545414635611,545414635611,2817,"STEP_SWAP_BUFFERS"
-2817,545414635611,7000,0,"STEP_SWAP_BUFFERS",545414642611,545415059829,545415059829,2817,"STEP_DRAW_AND_SWAP"
-2817,545415059829,8000,0,"STEP_DRAW_AND_SWAP",545415067829,545423937829,545423937829,2817,"End"
-2817,545423937829,2000,0,"End",545423939829,"[NULL]",545418000403,2821,"AsyncBegin"
-2821,545418000403,17254426,0,"AsyncBegin",545418000403,545419737403,545419886403,2821,"Begin"
-2821,545419886403,1000,0,"Begin",545420035403,545419737403,545419912403,2821,"STEP_SEND_INPUT_EVENT_UI"
-2821,545419912403,82000,0,"STEP_SEND_INPUT_EVENT_UI",545420035403,545420065611,545420068611,2821,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2821,545420068611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545420077611,545424059611,545424063611,2821,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2821,545424063611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545424099611,545425917611,545425917611,2821,"STEP_SWAP_BUFFERS"
-2821,545425917611,8000,0,"STEP_SWAP_BUFFERS",545425925611,545426405829,545426405829,2821,"STEP_DRAW_AND_SWAP"
-2821,545426405829,8000,0,"STEP_DRAW_AND_SWAP",545426413829,545435262829,545435262829,2821,"End"
-2821,545435262829,2000,0,"End",545435264829,"[NULL]",545426000403,2823,"AsyncBegin"
-2823,545426000403,20407426,0,"AsyncBegin",545426000403,545427922403,545428064403,2823,"Begin"
-2823,545428064403,1000,0,"Begin",545428132403,545427922403,545428090403,2823,"STEP_SEND_INPUT_EVENT_UI"
-2823,545428090403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545428132403,545428176611,545428179611,2823,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2823,545428179611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545428188611,545435214611,545435218611,2823,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2823,545435218611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545435259611,545437410611,545437410611,2823,"STEP_SWAP_BUFFERS"
-2823,545437410611,6000,0,"STEP_SWAP_BUFFERS",545437416611,545437842829,545437842829,2823,"STEP_DRAW_AND_SWAP"
-2823,545437842829,8000,0,"STEP_DRAW_AND_SWAP",545437850829,545446415829,545446415829,2823,"End"
-2823,545446415829,2000,0,"End",545446417829,"[NULL]",545435000403,2825,"AsyncBegin"
-2825,545435000403,22633426,0,"AsyncBegin",545435000403,545435980403,545436098403,2825,"Begin"
-2825,545436098403,2000,0,"Begin",545436165403,545435980403,545436123403,2825,"STEP_SEND_INPUT_EVENT_UI"
-2825,545436123403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545436165403,545436192611,545436194611,2825,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2825,545436194611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545436203611,545446061611,545446064611,2825,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2825,545446064611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545446102611,545447864611,545447864611,2825,"STEP_SWAP_BUFFERS"
-2825,545447864611,9000,0,"STEP_SWAP_BUFFERS",545447873611,545448362829,545448362829,2825,"STEP_DRAW_AND_SWAP"
-2825,545448362829,6000,0,"STEP_DRAW_AND_SWAP",545448368829,545457639829,545457639829,2825,"End"
-2825,545457639829,2000,0,"End",545457641829,"[NULL]",545443000403,2827,"AsyncBegin"
-2827,545443000403,27179426,0,"AsyncBegin",545443000403,545445387403,545445525403,2827,"Begin"
-2827,545445525403,1000,0,"Begin",545445588403,545445387403,545445550403,2827,"STEP_SEND_INPUT_EVENT_UI"
-2827,545445550403,27000,0,"STEP_SEND_INPUT_EVENT_UI",545445588403,545446153611,545446157611,2827,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2827,545446157611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545446171611,545457190611,545457194611,2827,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2827,545457194611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545457236611,545458991611,545458991611,2827,"STEP_SWAP_BUFFERS"
-2827,545458991611,7000,0,"STEP_SWAP_BUFFERS",545458998611,545459400829,545459400829,2827,"STEP_DRAW_AND_SWAP"
-2827,545459400829,6000,0,"STEP_DRAW_AND_SWAP",545459406829,545470185829,545470185829,2827,"End"
-2827,545470185829,3000,0,"End",545470188829,"[NULL]",545459000403,2831,"AsyncBegin"
-2831,545459000403,20575426,0,"AsyncBegin",545459000403,545460996403,545461134403,2831,"Begin"
-2831,545461134403,1000,0,"Begin",545461206403,545460996403,545461161403,2831,"STEP_SEND_INPUT_EVENT_UI"
-2831,545461161403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545461206403,545461254611,545461257611,2831,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2831,545461257611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545461266611,545468705611,545468709611,2831,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2831,545468709611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545468753611,545470512611,545470512611,2831,"STEP_SWAP_BUFFERS"
-2831,545470512611,7000,0,"STEP_SWAP_BUFFERS",545470519611,545470980829,545470980829,2831,"STEP_DRAW_AND_SWAP"
-2831,545470980829,6000,0,"STEP_DRAW_AND_SWAP",545470986829,545479583829,545479583829,2831,"End"
-2831,545479583829,2000,0,"End",545479585829,"[NULL]",545468000403,2833,"AsyncBegin"
-2833,545468000403,23489426,0,"AsyncBegin",545468000403,545469430403,545469546403,2833,"Begin"
-2833,545469546403,2000,0,"Begin",545469638403,545469430403,545469572403,2833,"STEP_SEND_INPUT_EVENT_UI"
-2833,545469572403,55000,0,"STEP_SEND_INPUT_EVENT_UI",545469638403,545469916611,545469918611,2833,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2833,545469918611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545469927611,545479511611,545479515611,2833,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2833,545479515611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545479552611,545481211611,545481211611,2833,"STEP_SWAP_BUFFERS"
-2833,545481211611,6000,0,"STEP_SWAP_BUFFERS",545481217611,545481612829,545481612829,2833,"STEP_DRAW_AND_SWAP"
-2833,545481612829,7000,0,"STEP_DRAW_AND_SWAP",545481619829,545491497829,545491497829,2833,"End"
-2833,545491497829,2000,0,"End",545491499829,"[NULL]",545484000403,2837,"AsyncBegin"
-2837,545484000403,18277426,0,"AsyncBegin",545484000403,545485501403,545485672403,2837,"Begin"
-2837,545485672403,2000,0,"Begin",545485752403,545485501403,545485703403,2837,"STEP_SEND_INPUT_EVENT_UI"
-2837,545485703403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545485752403,545485821611,545485824611,2837,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2837,545485824611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545485835611,545491127611,545491131611,2837,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2837,545491131611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545491175611,545493207611,545493207611,2837,"STEP_SWAP_BUFFERS"
-2837,545493207611,7000,0,"STEP_SWAP_BUFFERS",545493214611,545493655829,545493655829,2837,"STEP_DRAW_AND_SWAP"
-2837,545493655829,8000,0,"STEP_DRAW_AND_SWAP",545493663829,545502285829,545502285829,2837,"End"
-2837,545502285829,2000,0,"End",545502287829,"[NULL]",545492000403,2839,"AsyncBegin"
-2839,545492000403,21649426,0,"AsyncBegin",545492000403,545493813403,545494062403,2839,"Begin"
-2839,545494062403,1000,0,"Begin",545494175403,545493813403,545494122403,2839,"STEP_SEND_INPUT_EVENT_UI"
-2839,545494122403,38000,0,"STEP_SEND_INPUT_EVENT_UI",545494175403,545494238611,545494243611,2839,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2839,545494243611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545494254611,545502007611,545502011611,2839,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2839,545502011611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545502056611,545504796611,545504796611,2839,"STEP_SWAP_BUFFERS"
-2839,545504796611,6000,0,"STEP_SWAP_BUFFERS",545504802611,545505248829,545505248829,2839,"STEP_DRAW_AND_SWAP"
-2839,545505248829,8000,0,"STEP_DRAW_AND_SWAP",545505256829,545513681829,545513681829,2839,"End"
-2839,545513681829,7000,0,"End",545513688829,"[NULL]",545500000403,2841,"AsyncBegin"
-2841,545500000403,24734426,0,"AsyncBegin",545500000403,545502616403,545502751403,2841,"Begin"
-2841,545502751403,2000,0,"Begin",545502821403,545502616403,545502779403,2841,"STEP_SEND_INPUT_EVENT_UI"
-2841,545502779403,30000,0,"STEP_SEND_INPUT_EVENT_UI",545502821403,545502846611,545502849611,2841,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2841,545502849611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545502858611,545513030611,545513059611,2841,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2841,545513059611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545513101611,545515481611,545515481611,2841,"STEP_SWAP_BUFFERS"
-2841,545515481611,8000,0,"STEP_SWAP_BUFFERS",545515489611,545515917829,545515917829,2841,"STEP_DRAW_AND_SWAP"
-2841,545515917829,6000,0,"STEP_DRAW_AND_SWAP",545515923829,545524742829,545524742829,2841,"End"
-2841,545524742829,2000,0,"End",545524744829,"[NULL]",545517000403,2845,"AsyncBegin"
-2845,545517000403,18824426,0,"AsyncBegin",545517000403,545518318403,545518468403,2845,"Begin"
-2845,545518468403,1000,0,"Begin",545518586403,545518318403,545518528403,2845,"STEP_SEND_INPUT_EVENT_UI"
-2845,545518528403,44000,0,"STEP_SEND_INPUT_EVENT_UI",545518586403,545518636611,545518639611,2845,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2845,545518639611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545518649611,545524570611,545524575611,2845,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2845,545524575611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545524628611,545526711611,545526711611,2845,"STEP_SWAP_BUFFERS"
-2845,545526711611,7000,0,"STEP_SWAP_BUFFERS",545526718611,545527190829,545527190829,2845,"STEP_DRAW_AND_SWAP"
-2845,545527190829,7000,0,"STEP_DRAW_AND_SWAP",545527197829,545535831829,545535831829,2845,"End"
-2845,545535831829,2000,0,"End",545535833829,"[NULL]",545525000403,2847,"AsyncBegin"
-2847,545525000403,22343426,0,"AsyncBegin",545525000403,545526525403,545526694403,2847,"Begin"
-2847,545526694403,1000,0,"Begin",545526776403,545526525403,545526724403,2847,"STEP_SEND_INPUT_EVENT_UI"
-2847,545526724403,40000,0,"STEP_SEND_INPUT_EVENT_UI",545526776403,545526918611,545526920611,2847,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2847,545526920611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545526928611,545535499611,545535502611,2847,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2847,545535502611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545535536611,545537200611,545537200611,2847,"STEP_SWAP_BUFFERS"
-2847,545537200611,7000,0,"STEP_SWAP_BUFFERS",545537207611,545537622829,545537622829,2847,"STEP_DRAW_AND_SWAP"
-2847,545537622829,7000,0,"STEP_DRAW_AND_SWAP",545537629829,545547352829,545547352829,2847,"End"
-2847,545547352829,6000,0,"End",545547358829,"[NULL]",545533000403,2849,"AsyncBegin"
-2849,545533000403,25222426,0,"AsyncBegin",545533000403,545534953403,545535099403,2849,"Begin"
-2849,545535099403,1000,0,"Begin",545535160403,545534953403,545535125403,2849,"STEP_SEND_INPUT_EVENT_UI"
-2849,545535125403,24000,0,"STEP_SEND_INPUT_EVENT_UI",545535160403,545535588611,545535592611,2849,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2849,545535592611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545535601611,545546698611,545546704611,2849,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2849,545546704611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545546740611,545548503611,545548503611,2849,"STEP_SWAP_BUFFERS"
-2849,545548503611,9000,0,"STEP_SWAP_BUFFERS",545548512611,545548920829,545548920829,2849,"STEP_DRAW_AND_SWAP"
-2849,545548920829,5000,0,"STEP_DRAW_AND_SWAP",545548925829,545558230829,545558230829,2849,"End"
-2849,545558230829,3000,0,"End",545558233829,"[NULL]",545550000403,2853,"AsyncBegin"
-2853,545550000403,19151426,0,"AsyncBegin",545550000403,545551042403,545551389403,2853,"Begin"
-2853,545551389403,2000,0,"Begin",545551573403,545551042403,545551421403,2853,"STEP_SEND_INPUT_EVENT_UI"
-2853,545551421403,136000,0,"STEP_SEND_INPUT_EVENT_UI",545551573403,545551517611,545551522611,2853,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2853,545551522611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545551534611,545558062611,545558067611,2853,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2853,545558067611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545558111611,545560260611,545560260611,2853,"STEP_SWAP_BUFFERS"
-2853,545560260611,6000,0,"STEP_SWAP_BUFFERS",545560266611,545560689829,545560689829,2853,"STEP_DRAW_AND_SWAP"
-2853,545560689829,8000,0,"STEP_DRAW_AND_SWAP",545560697829,545569158829,545569158829,2853,"End"
-2853,545569158829,1000,0,"End",545569159829,"[NULL]",545558000403,2855,"AsyncBegin"
-2855,545558000403,22660426,0,"AsyncBegin",545558000403,545559432403,545559561403,2855,"Begin"
-2855,545559561403,1000,0,"Begin",545559633403,545559432403,545559587403,2855,"STEP_SEND_INPUT_EVENT_UI"
-2855,545559587403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545559633403,545559679611,545559682611,2855,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2855,545559682611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545559692611,545568903611,545568906611,2855,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2855,545568906611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545569011611,545571019611,545571019611,2855,"STEP_SWAP_BUFFERS"
-2855,545571019611,7000,0,"STEP_SWAP_BUFFERS",545571026611,545571437829,545571437829,2855,"STEP_DRAW_AND_SWAP"
-2855,545571437829,7000,0,"STEP_DRAW_AND_SWAP",545571444829,545580670829,545580670829,2855,"End"
-2855,545580670829,2000,0,"End",545580672829,"[NULL]",545574000403,2859,"AsyncBegin"
-2859,545574000403,17603426,0,"AsyncBegin",545574000403,545575964403,545576109403,2859,"Begin"
-2859,545576109403,1000,0,"Begin",545576180403,545575964403,545576135403,2859,"STEP_SEND_INPUT_EVENT_UI"
-2859,545576135403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545576180403,545576217611,545576219611,2859,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2859,545576219611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545576228611,545581056611,545581062611,2859,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2859,545581062611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545581108611,545582986611,545582986611,2859,"STEP_SWAP_BUFFERS"
-2859,545582986611,7000,0,"STEP_SWAP_BUFFERS",545582993611,545583484829,545583484829,2859,"STEP_DRAW_AND_SWAP"
-2859,545583484829,7000,0,"STEP_DRAW_AND_SWAP",545583491829,545591611829,545591611829,2859,"End"
-2859,545591611829,2000,0,"End",545591613829,"[NULL]",545583000403,2861,"AsyncBegin"
-2861,545583000403,19608426,0,"AsyncBegin",545583000403,545584292403,545584432403,2861,"Begin"
-2861,545584432403,1000,0,"Begin",545584503403,545584292403,545584458403,2861,"STEP_SEND_INPUT_EVENT_UI"
-2861,545584458403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545584503403,545584525611,545584527611,2861,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2861,545584527611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545584537611,545591605611,545591609611,2861,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2861,545591609611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545591652611,545594008611,545594008611,2861,"STEP_SWAP_BUFFERS"
-2861,545594008611,6000,0,"STEP_SWAP_BUFFERS",545594014611,545594448829,545594448829,2861,"STEP_DRAW_AND_SWAP"
-2861,545594448829,8000,0,"STEP_DRAW_AND_SWAP",545594456829,545602616829,545602616829,2861,"End"
-2861,545602616829,2000,0,"End",545602618829,"[NULL]",545591000403,2863,"AsyncBegin"
-2863,545591000403,22822426,0,"AsyncBegin",545591000403,545592149403,545592267403,2863,"Begin"
-2863,545592267403,28000,0,"Begin",545592370403,545592149403,545592323403,2863,"STEP_SEND_INPUT_EVENT_UI"
-2863,545592323403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545592370403,545592608611,545592613611,2863,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2863,545592613611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545592645611,545603135611,545603139611,2863,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2863,545603139611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545603221611,545605222611,545605222611,2863,"STEP_SWAP_BUFFERS"
-2863,545605222611,7000,0,"STEP_SWAP_BUFFERS",545605229611,545605636829,545605636829,2863,"STEP_DRAW_AND_SWAP"
-2863,545605636829,6000,0,"STEP_DRAW_AND_SWAP",545605642829,545613831829,545613831829,2863,"End"
-2863,545613831829,2000,0,"End",545613833829,"[NULL]",545607000403,2867,"AsyncBegin"
-2867,545607000403,18005426,0,"AsyncBegin",545607000403,545608899403,545609050403,2867,"Begin"
-2867,545609050403,2000,0,"Begin",545609125403,545608899403,545609081403,2867,"STEP_SEND_INPUT_EVENT_UI"
-2867,545609081403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545609125403,545609151611,545609153611,2867,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2867,545609153611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545609162611,545614173611,545614177611,2867,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2867,545614177611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545614211611,545615903611,545615903611,2867,"STEP_SWAP_BUFFERS"
-2867,545615903611,7000,0,"STEP_SWAP_BUFFERS",545615910611,545616332829,545616332829,2867,"STEP_DRAW_AND_SWAP"
-2867,545616332829,7000,0,"STEP_DRAW_AND_SWAP",545616339829,545625013829,545625013829,2867,"End"
-2867,545625013829,2000,0,"End",545625015829,"[NULL]",545615000403,2869,"AsyncBegin"
-2869,545615000403,21063426,0,"AsyncBegin",545615000403,545617943403,545618417403,2869,"Begin"
-2869,545618417403,2000,0,"Begin",545618492403,545617943403,545618446403,2869,"STEP_SEND_INPUT_EVENT_UI"
-2869,545618446403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545618492403,545618582611,545618589611,2869,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2869,545618589611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545618600611,545624819611,545624822611,2869,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2869,545624822611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545624863611,545626738611,545626738611,2869,"STEP_SWAP_BUFFERS"
-2869,545626738611,6000,0,"STEP_SWAP_BUFFERS",545626744611,545627143829,545627143829,2869,"STEP_DRAW_AND_SWAP"
-2869,545627143829,7000,0,"STEP_DRAW_AND_SWAP",545627150829,545636070829,545636070829,2869,"End"
-2869,545636070829,1000,0,"End",545636071829,"[NULL]",545624000403,2871,"AsyncBegin"
-2871,545624000403,23894426,0,"AsyncBegin",545624000403,545625078403,545625201403,2871,"Begin"
-2871,545625201403,2000,0,"Begin",545625268403,545625078403,545625227403,2871,"STEP_SEND_INPUT_EVENT_UI"
-2871,545625227403,29000,0,"STEP_SEND_INPUT_EVENT_UI",545625268403,545625287611,545625289611,2871,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2871,545625289611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545625297611,545635894611,545635898611,2871,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2871,545635898611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545635933611,545637871611,545637871611,2871,"STEP_SWAP_BUFFERS"
-2871,545637871611,7000,0,"STEP_SWAP_BUFFERS",545637878611,545638300829,545638300829,2871,"STEP_DRAW_AND_SWAP"
-2871,545638300829,7000,0,"STEP_DRAW_AND_SWAP",545638307829,545647901829,545647901829,2871,"End"
-2871,545647901829,2000,0,"End",545647903829,"[NULL]",545640000403,2875,"AsyncBegin"
-2875,545640000403,18611426,0,"AsyncBegin",545640000403,545641559403,545641729403,2875,"Begin"
-2875,545641729403,1000,0,"Begin",545641805403,545641559403,545641755403,2875,"STEP_SEND_INPUT_EVENT_UI"
-2875,545641755403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545641805403,545641850611,545641854611,2875,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2875,545641854611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545641869611,545647619611,545647653611,2875,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2875,545647653611,7000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545647700611,545649619611,545649619611,2875,"STEP_SWAP_BUFFERS"
-2875,545649619611,9000,0,"STEP_SWAP_BUFFERS",545649628611,545650133829,545650133829,2875,"STEP_DRAW_AND_SWAP"
-2875,545650133829,7000,0,"STEP_DRAW_AND_SWAP",545650140829,545658618829,545658618829,2875,"End"
-2875,545658618829,2000,0,"End",545658620829,"[NULL]",545648000403,2877,"AsyncBegin"
-2877,545648000403,21759426,0,"AsyncBegin",545648000403,545649858403,545650030403,2877,"Begin"
-2877,545650030403,2000,0,"Begin",545650114403,545649858403,545650064403,2877,"STEP_SEND_INPUT_EVENT_UI"
-2877,545650064403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545650114403,545650134611,545650137611,2877,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2877,545650137611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545650146611,545658312611,545658316611,2877,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2877,545658316611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545658354611,545660121611,545660121611,2877,"STEP_SWAP_BUFFERS"
-2877,545660121611,7000,0,"STEP_SWAP_BUFFERS",545660128611,545660549829,545660549829,2877,"STEP_DRAW_AND_SWAP"
-2877,545660549829,7000,0,"STEP_DRAW_AND_SWAP",545660556829,545669767829,545669767829,2877,"End"
-2877,545669767829,2000,0,"End",545669769829,"[NULL]",545656000403,2879,"AsyncBegin"
-2879,545656000403,25004426,0,"AsyncBegin",545656000403,545657848403,545657990403,2879,"Begin"
-2879,545657990403,1000,0,"Begin",545658050403,545657848403,545658015403,2879,"STEP_SEND_INPUT_EVENT_UI"
-2879,545658015403,24000,0,"STEP_SEND_INPUT_EVENT_UI",545658050403,545658466611,545658469611,2879,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2879,545658469611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545658477611,545669774611,545669778611,2879,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2879,545669778611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545669828611,545672231611,545672231611,2879,"STEP_SWAP_BUFFERS"
-2879,545672231611,7000,0,"STEP_SWAP_BUFFERS",545672238611,545672662829,545672662829,2879,"STEP_DRAW_AND_SWAP"
-2879,545672662829,7000,0,"STEP_DRAW_AND_SWAP",545672669829,545681056829,545681056829,2879,"End"
-2879,545681056829,8000,0,"End",545681064829,"[NULL]",545671000403,2881,"AsyncBegin"
-2881,545671000403,32742426,0,"AsyncBegin",545671000403,545673069403,545673257403,2881,"Begin"
-2881,545673257403,1000,0,"Begin",545673352403,545673069403,545673304403,2881,"STEP_SEND_INPUT_EVENT_UI"
-2881,545673304403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545673352403,545673613611,545673616611,2881,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2881,545673616611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545673626611,545681144611,545681149611,2881,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2881,545681149611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545681185611,545687519611,545687519611,2881,"STEP_SWAP_BUFFERS"
-2881,545687519611,6000,0,"STEP_SWAP_BUFFERS",545687525611,545688029829,545688029829,2881,"STEP_DRAW_AND_SWAP"
-2881,545688029829,7000,0,"STEP_DRAW_AND_SWAP",545688036829,545703750829,545703750829,2881,"End"
-2881,545703750829,3000,0,"End",545703753829,"[NULL]",545681794403,2884,"AsyncBegin"
-2884,545681794403,32652426,0,"AsyncBegin",545681794403,545681614403,545681805403,2884,"Begin"
-2884,545681805403,1000,0,"Begin",545681983403,545681614403,545681829403,2884,"STEP_SEND_INPUT_EVENT_UI"
-2884,545681829403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545681983403,545681903611,545681906611,2884,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2884,545681906611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545681916611,545691798611,545691802611,2884,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2884,545691802611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545691839611,545693521611,545693521611,2884,"STEP_SWAP_BUFFERS"
-2884,545693521611,7000,0,"STEP_SWAP_BUFFERS",545693528611,545693969829,545693969829,2884,"STEP_DRAW_AND_SWAP"
-2884,545693969829,8000,0,"STEP_DRAW_AND_SWAP",545693977829,545714454829,545714454829,2884,"End"
-2884,545714454829,2000,0,"End",545714456829,"[NULL]",545691182403,2885,"AsyncBegin"
-2885,545691182403,34488426,0,"AsyncBegin",545691182403,545691819403,545691834403,2885,"Begin"
-2885,545691834403,2000,0,"Begin",545691925403,545691819403,545691874403,2885,"STEP_SEND_INPUT_EVENT_UI"
-2885,545691874403,47000,0,"STEP_SEND_INPUT_EVENT_UI",545691925403,545692055611,545692061611,2885,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2885,545692061611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545692073611,545703179611,545703184611,2885,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2885,545703184611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545703220611,545705806611,545705806611,2885,"STEP_SWAP_BUFFERS"
-2885,545705806611,7000,0,"STEP_SWAP_BUFFERS",545705813611,545706252829,545706252829,2885,"STEP_DRAW_AND_SWAP"
-2885,545706252829,7000,0,"STEP_DRAW_AND_SWAP",545706259829,545725677829,545725677829,2885,"End"
-2885,545725677829,2000,0,"End",545725679829,"[NULL]",545702355403,2886,"AsyncBegin"
-2886,545702355403,34887426,0,"AsyncBegin",545702355403,545703039403,545703056403,2886,"Begin"
-2886,545703056403,2000,0,"Begin",545703154403,545703039403,545703097403,2886,"STEP_SEND_INPUT_EVENT_UI"
-2886,545703097403,52000,0,"STEP_SEND_INPUT_EVENT_UI",545703154403,545703276611,545703300611,2886,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2886,545703300611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545703312611,545714437611,545714440611,2886,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2886,545714440611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545714481611,545716787611,545716787611,2886,"STEP_SWAP_BUFFERS"
-2886,545716787611,8000,0,"STEP_SWAP_BUFFERS",545716795611,545717228829,545717228829,2886,"STEP_DRAW_AND_SWAP"
-2886,545717228829,8000,0,"STEP_DRAW_AND_SWAP",545717236829,545737251829,545737251829,2886,"End"
-2886,545737251829,2000,0,"End",545737253829,"[NULL]",545713526403,2887,"AsyncBegin"
-2887,545713526403,34615426,0,"AsyncBegin",545713526403,545714310403,545714329403,2887,"Begin"
-2887,545714329403,3000,0,"Begin",545714583403,545714310403,545714375403,2887,"STEP_SEND_INPUT_EVENT_UI"
-2887,545714375403,201000,0,"STEP_SEND_INPUT_EVENT_UI",545714583403,545714639611,545714645611,2887,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2887,545714645611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545714657611,545726201611,545726206611,2887,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2887,545726206611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545726246611,545728218611,545728218611,2887,"STEP_SWAP_BUFFERS"
-2887,545728218611,8000,0,"STEP_SWAP_BUFFERS",545728226611,545728661829,545728661829,2887,"STEP_DRAW_AND_SWAP"
-2887,545728661829,8000,0,"STEP_DRAW_AND_SWAP",545728669829,545748149829,545748149829,2887,"End"
-2887,545748149829,2000,0,"End",545748151829,"[NULL]",545724697403,2888,"AsyncBegin"
-2888,545724697403,36799426,0,"AsyncBegin",545724697403,545725536403,545725554403,2888,"Begin"
-2888,545725554403,2000,0,"Begin",545725655403,545725536403,545725595403,2888,"STEP_SEND_INPUT_EVENT_UI"
-2888,545725595403,55000,0,"STEP_SEND_INPUT_EVENT_UI",545725655403,545726300611,545726305611,2888,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2888,545726305611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545726317611,545737740611,545737744611,2888,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2888,545737744611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545737782611,545739404611,545739404611,2888,"STEP_SWAP_BUFFERS"
-2888,545739404611,6000,0,"STEP_SWAP_BUFFERS",545739410611,545739832829,545739832829,2888,"STEP_DRAW_AND_SWAP"
-2888,545739832829,7000,0,"STEP_DRAW_AND_SWAP",545739839829,545761508829,545761508829,2888,"End"
-2888,545761508829,3000,0,"End",545761511829,"[NULL]",545735867403,2889,"AsyncBegin"
-2889,545735867403,35326426,0,"AsyncBegin",545735867403,545736697403,545736718403,2889,"Begin"
-2889,545736718403,2000,0,"Begin",545736833403,545736697403,545736765403,2889,"STEP_SEND_INPUT_EVENT_UI"
-2889,545736765403,62000,0,"STEP_SEND_INPUT_EVENT_UI",545736833403,545737847611,545737851611,2889,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2889,545737851611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545737864611,545747896611,545747901611,2889,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2889,545747901611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545747945611,545749570611,545749570611,2889,"STEP_SWAP_BUFFERS"
-2889,545749570611,6000,0,"STEP_SWAP_BUFFERS",545749576611,545749997829,545749997829,2889,"STEP_DRAW_AND_SWAP"
-2889,545749997829,6000,0,"STEP_DRAW_AND_SWAP",545750003829,545771200829,545771200829,2889,"End"
-2889,545771200829,2000,0,"End",545771202829,"[NULL]",545747040403,2890,"AsyncBegin"
-2890,545747040403,35047426,0,"AsyncBegin",545747040403,545748874403,545748889403,2890,"Begin"
-2890,545748889403,1000,0,"Begin",545749091403,545748874403,545748968403,2890,"STEP_SEND_INPUT_EVENT_UI"
-2890,545748968403,116000,0,"STEP_SEND_INPUT_EVENT_UI",545749091403,545749100611,545749108611,2890,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2890,545749108611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545749123611,545759989611,545759993611,2890,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2890,545759993611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545760037611,545762422611,545762422611,2890,"STEP_SWAP_BUFFERS"
-2890,545762422611,7000,0,"STEP_SWAP_BUFFERS",545762429611,545762851829,545762851829,2890,"STEP_DRAW_AND_SWAP"
-2890,545762851829,6000,0,"STEP_DRAW_AND_SWAP",545762857829,545782095829,545782095829,2890,"End"
-2890,545782095829,3000,0,"End",545782098829,"[NULL]",545758211403,2891,"AsyncBegin"
-2891,545758211403,34990426,0,"AsyncBegin",545758211403,545759258403,545759276403,2891,"Begin"
-2891,545759276403,2000,0,"Begin",545759384403,545759258403,545759321403,2891,"STEP_SEND_INPUT_EVENT_UI"
-2891,545759321403,57000,0,"STEP_SEND_INPUT_EVENT_UI",545759384403,545760216611,545760222611,2891,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2891,545760222611,38000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545760266611,545770425611,545770429611,2891,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2891,545770429611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545770469611,545772129611,545772129611,2891,"STEP_SWAP_BUFFERS"
-2891,545772129611,6000,0,"STEP_SWAP_BUFFERS",545772135611,545772543829,545772543829,2891,"STEP_DRAW_AND_SWAP"
-2891,545772543829,6000,0,"STEP_DRAW_AND_SWAP",545772549829,545793208829,545793208829,2891,"End"
-2891,545793208829,2000,0,"End",545793210829,"[NULL]",545769381403,2892,"AsyncBegin"
-2892,545769381403,39529426,0,"AsyncBegin",545769381403,545770375403,545770396403,2892,"Begin"
-2892,545770396403,3000,0,"Begin",545770528403,545770375403,545770451403,2892,"STEP_SEND_INPUT_EVENT_UI"
-2892,545770451403,69000,0,"STEP_SEND_INPUT_EVENT_UI",545770528403,545771055611,545771063611,2892,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2892,545771063611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545771077611,545781663611,545781667611,2892,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2892,545781667611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545781703611,545783314611,545783314611,2892,"STEP_SWAP_BUFFERS"
-2892,545783314611,6000,0,"STEP_SWAP_BUFFERS",545783320611,545783690829,545783690829,2892,"STEP_DRAW_AND_SWAP"
-2892,545783690829,6000,0,"STEP_DRAW_AND_SWAP",545783696829,545808924829,545808924829,2892,"End"
-2892,545808924829,3000,0,"End",545808927829,"[NULL]",545780550403,2893,"AsyncBegin"
-2893,545780550403,35967426,0,"AsyncBegin",545780550403,545782203403,545782218403,2893,"Begin"
-2893,545782218403,2000,0,"Begin",545782309403,545782203403,545782255403,2893,"STEP_SEND_INPUT_EVENT_UI"
-2893,545782255403,49000,0,"STEP_SEND_INPUT_EVENT_UI",545782309403,545782382611,545782389611,2893,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2893,545782389611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545782404611,545792786611,545792790611,2893,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2893,545792790611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545792829611,545795262611,545795262611,2893,"STEP_SWAP_BUFFERS"
-2893,545795262611,7000,0,"STEP_SWAP_BUFFERS",545795269611,545796104829,545796104829,2893,"STEP_DRAW_AND_SWAP"
-2893,545796104829,9000,0,"STEP_DRAW_AND_SWAP",545796113829,545816526829,545816526829,2893,"End"
-2893,545816526829,2000,0,"End",545816528829,"[NULL]",545791721403,2894,"AsyncBegin"
-2894,545791721403,45468426,1,"AsyncBegin",545791721403,545792514403,545792536403,2894,"Begin"
-2894,545792536403,2000,1,"Begin",545792648403,545792514403,545792584403,2894,"STEP_SEND_INPUT_EVENT_UI"
-2894,545792584403,58000,1,"STEP_SEND_INPUT_EVENT_UI",545792648403,545792895611,545792900611,2894,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2894,545792900611,11000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",545792913611,545803896611,545803900611,2894,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2894,545803900611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545803940611,545817301611,545817301611,2894,"STEP_SWAP_BUFFERS"
-2894,545817301611,16000,1,"STEP_SWAP_BUFFERS",545817317611,545819176829,545819176829,2894,"STEP_DRAW_AND_SWAP"
-2894,545819176829,8000,1,"STEP_DRAW_AND_SWAP",545819184829,545837200829,545837200829,2894,"End"
-2894,545837200829,3000,1,"End",545837203829,"[NULL]",545802892403,2895,"AsyncBegin"
-2895,545802892403,45651426,1,"AsyncBegin",545802892403,545804221403,545804270403,2895,"Begin"
-2895,545804270403,2000,1,"Begin",545804390403,545804221403,545804322403,2895,"STEP_SEND_INPUT_EVENT_UI"
-2895,545804322403,61000,1,"STEP_SEND_INPUT_EVENT_UI",545804390403,545804452611,545804458611,2895,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2895,545804458611,11000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",545804470611,545817484611,545817486611,2895,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2895,545817486611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545817519611,545819202611,545819202611,2895,"STEP_SWAP_BUFFERS"
-2895,545819202611,6000,1,"STEP_SWAP_BUFFERS",545819208611,545826817829,545826817829,2895,"STEP_DRAW_AND_SWAP"
-2895,545826817829,7000,1,"STEP_DRAW_AND_SWAP",545826824829,545848551829,545848551829,2895,"End"
-2895,545848551829,2000,1,"End",545848553829,"[NULL]",545825234403,2897,"AsyncBegin"
-2897,545825234403,34662426,0,"AsyncBegin",545825234403,545826095403,545826110403,2897,"Begin"
-2897,545826110403,3000,0,"Begin",545826202403,545826095403,545826149403,2897,"STEP_SEND_INPUT_EVENT_UI"
-2897,545826149403,48000,0,"STEP_SEND_INPUT_EVENT_UI",545826202403,545826273611,545826281611,2897,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2897,545826281611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545826294611,545842124611,545842129611,2897,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2897,545842129611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545842170611,545844671611,545844671611,2897,"STEP_SWAP_BUFFERS"
-2897,545844671611,8000,0,"STEP_SWAP_BUFFERS",545844679611,545845554829,545845554829,2897,"STEP_DRAW_AND_SWAP"
-2897,545845554829,8000,0,"STEP_DRAW_AND_SWAP",545845562829,545859905829,545859905829,2897,"End"
-2897,545859905829,2000,0,"End",545859907829,"[NULL]",546027000403,2918,"AsyncBegin"
-2918,546027000403,24672426,0,"AsyncBegin",546027000403,546030704403,546031041403,2918,"Begin"
-2918,546031041403,2000,0,"Begin",546031129403,546030704403,546031099403,2918,"STEP_SEND_INPUT_EVENT_UI"
-2918,546031099403,22000,0,"STEP_SEND_INPUT_EVENT_UI",546031129403,546031763611,546031767611,2918,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2918,546031767611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546031780611,546032545611,546032548611,2918,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2918,546032548611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546032578611,546033504611,546033504611,2918,"STEP_SWAP_BUFFERS"
-2918,546033504611,7000,0,"STEP_SWAP_BUFFERS",546033511611,546036368829,546036368829,2918,"STEP_DRAW_AND_SWAP"
-2918,546036368829,9000,0,"STEP_DRAW_AND_SWAP",546036377829,546051706829,546051706829,2918,"End"
-2918,546051706829,8000,0,"End",546051714829,"[NULL]",546035000403,2920,"AsyncBegin"
-2920,546035000403,27274426,0,"AsyncBegin",546035000403,546036805403,546036957403,2920,"Begin"
-2920,546036957403,2000,0,"Begin",546037226403,546036805403,546037157403,2920,"STEP_SEND_INPUT_EVENT_UI"
-2920,546037157403,52000,0,"STEP_SEND_INPUT_EVENT_UI",546037226403,546037290611,546037297611,2920,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2920,546037297611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546037312611,546038471611,546038475611,2920,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2920,546038475611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546038513611,546039413611,546039413611,2920,"STEP_SWAP_BUFFERS"
-2920,546039413611,7000,0,"STEP_SWAP_BUFFERS",546039420611,546041499829,546041499829,2920,"STEP_DRAW_AND_SWAP"
-2920,546041499829,10000,0,"STEP_DRAW_AND_SWAP",546041509829,546062279829,546062279829,2920,"End"
-2920,546062279829,2000,0,"End",546062281829,"[NULL]",546044000403,2922,"AsyncBegin"
-2922,546044000403,28587426,0,"AsyncBegin",546044000403,546045602403,546045753403,2922,"Begin"
-2922,546045753403,1000,0,"Begin",546045828403,546045602403,546045780403,2922,"STEP_SEND_INPUT_EVENT_UI"
-2922,546045780403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546045828403,546045909611,546045911611,2922,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2922,546045911611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546045924611,546049062611,546049066611,2922,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2922,546049066611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546049103611,546050028611,546050028611,2922,"STEP_SWAP_BUFFERS"
-2922,546050028611,7000,0,"STEP_SWAP_BUFFERS",546050035611,546056565829,546056565829,2922,"STEP_DRAW_AND_SWAP"
-2922,546056565829,10000,0,"STEP_DRAW_AND_SWAP",546056575829,546072594829,546072594829,2922,"End"
-2922,546072594829,2000,0,"End",546072596829,"[NULL]",546052000403,2924,"AsyncBegin"
-2924,546052000403,41821426,1,"AsyncBegin",546052000403,546057257403,546057389403,2924,"Begin"
-2924,546057389403,1000,1,"Begin",546057503403,546057257403,546057417403,2924,"STEP_SEND_INPUT_EVENT_UI"
-2924,546057417403,71000,1,"STEP_SEND_INPUT_EVENT_UI",546057503403,546057521611,546057523611,2924,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2924,546057523611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546057532611,546060136611,546060140611,2924,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2924,546060140611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546060176611,546060788611,546060788611,2924,"STEP_SWAP_BUFFERS"
-2924,546060788611,6000,1,"STEP_SWAP_BUFFERS",546060794611,546072983829,546072983829,2924,"STEP_DRAW_AND_SWAP"
-2924,546072983829,5000,1,"STEP_DRAW_AND_SWAP",546072988829,546093831829,546093831829,2924,"End"
-2924,546093831829,2000,1,"End",546093833829,"[NULL]",546060000403,2926,"AsyncBegin"
-2926,546060000403,44914426,1,"AsyncBegin",546060000403,546061893403,546062009403,2926,"Begin"
-2926,546062009403,1000,1,"Begin",546062077403,546061893403,546062034403,2926,"STEP_SEND_INPUT_EVENT_UI"
-2926,546062034403,32000,1,"STEP_SEND_INPUT_EVENT_UI",546062077403,546062104611,546062106611,2926,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2926,546062106611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546062116611,546071407611,546071410611,2926,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2926,546071410611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546071441611,546072109611,546072109611,2926,"STEP_SWAP_BUFFERS"
-2926,546072109611,6000,1,"STEP_SWAP_BUFFERS",546072115611,546084900829,546084900829,2926,"STEP_DRAW_AND_SWAP"
-2926,546084900829,2000,1,"STEP_DRAW_AND_SWAP",546084902829,546104917829,546104917829,2926,"End"
-2926,546104917829,1000,1,"End",546104918829,"[NULL]",546076000403,2930,"AsyncBegin"
-2930,546076000403,28902426,0,"AsyncBegin",546076000403,546078271403,546078414403,2930,"Begin"
-2930,546078414403,1000,0,"Begin",546078488403,546078271403,546078440403,2930,"STEP_SEND_INPUT_EVENT_UI"
-2930,546078440403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546078488403,546078555611,546078558611,2930,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2930,546078558611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546078569611,546082555611,546082558611,2930,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2930,546082558611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546082596611,546083318611,546083318611,2930,"STEP_SWAP_BUFFERS"
-2930,546083318611,7000,0,"STEP_SWAP_BUFFERS",546083325611,546084891829,546084891829,2930,"STEP_DRAW_AND_SWAP"
-2930,546084891829,8000,0,"STEP_DRAW_AND_SWAP",546084899829,546104909829,546104909829,2930,"End"
-2930,546104909829,2000,0,"End",546104911829,"[NULL]",546085000403,2932,"AsyncBegin"
-2932,546085000403,31881426,0,"AsyncBegin",546085000403,546086197403,546086329403,2932,"Begin"
-2932,546086329403,1000,0,"Begin",546086403403,546086197403,546086356403,2932,"STEP_SEND_INPUT_EVENT_UI"
-2932,546086356403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546086403403,546086444611,546086446611,2932,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2932,546086446611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546086456611,546094099611,546094103611,2932,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2932,546094103611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546094140611,546094733611,546094733611,2932,"STEP_SWAP_BUFFERS"
-2932,546094733611,6000,0,"STEP_SWAP_BUFFERS",546094739611,546096093829,546096093829,2932,"STEP_DRAW_AND_SWAP"
-2932,546096093829,8000,0,"STEP_DRAW_AND_SWAP",546096101829,546116889829,546116889829,2932,"End"
-2932,546116889829,2000,0,"End",546116891829,"[NULL]",546093000403,2934,"AsyncBegin"
-2934,546093000403,34989426,0,"AsyncBegin",546093000403,546094650403,546094776403,2934,"Begin"
-2934,546094776403,1000,0,"Begin",546094846403,546094650403,546094801403,2934,"STEP_SEND_INPUT_EVENT_UI"
-2934,546094801403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546094846403,546095114611,546095119611,2934,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2934,546095119611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546095128611,546104611611,546104616611,2934,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2934,546104616611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546104651611,546105363611,546105363611,2934,"STEP_SWAP_BUFFERS"
-2934,546105363611,5000,0,"STEP_SWAP_BUFFERS",546105368611,546107001829,546107001829,2934,"STEP_DRAW_AND_SWAP"
-2934,546107001829,6000,0,"STEP_DRAW_AND_SWAP",546107007829,546127998829,546127998829,2934,"End"
-2934,546127998829,2000,0,"End",546128000829,"[NULL]",546109000403,2938,"AsyncBegin"
-2938,546109000403,41953426,1,"AsyncBegin",546109000403,546110931403,546111071403,2938,"Begin"
-2938,546111071403,1000,1,"Begin",546111154403,546110931403,546111100403,2938,"STEP_SEND_INPUT_EVENT_UI"
-2938,546111100403,40000,1,"STEP_SEND_INPUT_EVENT_UI",546111154403,546111216611,546111218611,2938,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2938,546111218611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546111227611,546116794611,546116798611,2938,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2938,546116798611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546116835611,546117666611,546117666611,2938,"STEP_SWAP_BUFFERS"
-2938,546117666611,6000,1,"STEP_SWAP_BUFFERS",546117672611,546130112829,546130112829,2938,"STEP_DRAW_AND_SWAP"
-2938,546130112829,1000,1,"STEP_DRAW_AND_SWAP",546130113829,546150956829,546150956829,2938,"End"
-2938,546150956829,1000,1,"End",546150957829,"[NULL]",546118000403,2940,"AsyncBegin"
-2940,546118000403,32872426,0,"AsyncBegin",546118000403,546119096403,546119389403,2940,"Begin"
-2940,546119389403,1000,0,"Begin",546119656403,546119096403,546119418403,2940,"STEP_SEND_INPUT_EVENT_UI"
-2940,546119418403,120000,0,"STEP_SEND_INPUT_EVENT_UI",546119656403,546119504611,546119508611,2940,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2940,546119508611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546119518611,546127524611,546127527611,2940,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2940,546127527611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546127561611,546128489611,546128489611,2940,"STEP_SWAP_BUFFERS"
-2940,546128489611,27000,0,"STEP_SWAP_BUFFERS",546128516611,546130104829,546130104829,2940,"STEP_DRAW_AND_SWAP"
-2940,546130104829,7000,0,"STEP_DRAW_AND_SWAP",546130111829,546150880829,546150880829,2940,"End"
-2940,546150880829,69000,0,"End",546150949829,"[NULL]",546126000403,2942,"AsyncBegin"
-2942,546126000403,35348426,0,"AsyncBegin",546126000403,546126954403,546128468403,2942,"Begin"
-2942,546128468403,1000,0,"Begin",546128599403,546126954403,546128503403,2942,"STEP_SEND_INPUT_EVENT_UI"
-2942,546128503403,78000,0,"STEP_SEND_INPUT_EVENT_UI",546128599403,546128618611,546128623611,2942,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2942,546128623611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546128633611,546139155611,546139160611,2942,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2942,546139160611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546139210611,546140019611,546140019611,2942,"STEP_SWAP_BUFFERS"
-2942,546140019611,5000,0,"STEP_SWAP_BUFFERS",546140024611,546141380829,546141380829,2942,"STEP_DRAW_AND_SWAP"
-2942,546141380829,9000,0,"STEP_DRAW_AND_SWAP",546141389829,546161356829,546161356829,2942,"End"
-2942,546161356829,2000,0,"End",546161358829,"[NULL]",546142000403,2946,"AsyncBegin"
-2946,546142000403,42106426,0,"AsyncBegin",546142000403,546143640403,546143776403,2946,"Begin"
-2946,546143776403,1000,0,"Begin",546143885403,546143640403,546143802403,2946,"STEP_SEND_INPUT_EVENT_UI"
-2946,546143802403,64000,0,"STEP_SEND_INPUT_EVENT_UI",546143885403,546143952611,546143956611,2946,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2946,546143956611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546143968611,546150338611,546150343611,2946,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2946,546150343611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546150382611,546152014611,546152014611,2946,"STEP_SWAP_BUFFERS"
-2946,546152014611,7000,0,"STEP_SWAP_BUFFERS",546152021611,546162653829,546162653829,2946,"STEP_DRAW_AND_SWAP"
-2946,546162653829,8000,0,"STEP_DRAW_AND_SWAP",546162661829,546184114829,546184114829,2946,"End"
-2946,546184114829,2000,0,"End",546184116829,"[NULL]",546150000403,2948,"AsyncBegin"
-2948,546150000403,45005426,1,"AsyncBegin",546150000403,546151950403,546152147403,2948,"Begin"
-2948,546152147403,1000,1,"Begin",546152222403,546151950403,546152174403,2948,"STEP_SEND_INPUT_EVENT_UI"
-2948,546152174403,36000,1,"STEP_SEND_INPUT_EVENT_UI",546152222403,546152273611,546152278611,2948,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2948,546152278611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546152288611,546161082611,546161087611,2948,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2948,546161087611,3000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546161130611,546162213611,546162213611,2948,"STEP_SWAP_BUFFERS"
-2948,546162213611,7000,1,"STEP_SWAP_BUFFERS",546162220611,546175298829,546175298829,2948,"STEP_DRAW_AND_SWAP"
-2948,546175298829,1000,1,"STEP_DRAW_AND_SWAP",546175299829,546195008829,546195008829,2948,"End"
-2948,546195008829,2000,1,"End",546195010829,"[NULL]",546159000403,2950,"AsyncBegin"
-2950,546159000403,35994426,0,"AsyncBegin",546159000403,546161262403,546161396403,2950,"Begin"
-2950,546161396403,1000,0,"Begin",546161473403,546161262403,546161423403,2950,"STEP_SEND_INPUT_EVENT_UI"
-2950,546161423403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546161473403,546161629611,546161632611,2950,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2950,546161632611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546161641611,546172303611,546172307611,2950,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2950,546172307611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546172429611,546173523611,546173523611,2950,"STEP_SWAP_BUFFERS"
-2950,546173523611,8000,0,"STEP_SWAP_BUFFERS",546173531611,546175282829,546175282829,2950,"STEP_DRAW_AND_SWAP"
-2950,546175282829,15000,0,"STEP_DRAW_AND_SWAP",546175297829,546195000829,546195000829,2950,"End"
-2950,546195000829,3000,0,"End",546195003829,"[NULL]",546175000403,2954,"AsyncBegin"
-2954,546175000403,30970426,0,"AsyncBegin",546175000403,546176663403,546176812403,2954,"Begin"
-2954,546176812403,1000,0,"Begin",546176884403,546176663403,546176838403,2954,"STEP_SEND_INPUT_EVENT_UI"
-2954,546176838403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546176884403,546176948611,546176951611,2954,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2954,546176951611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546176961611,546183503611,546183508611,2954,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2954,546183508611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546183547611,546184802611,546184802611,2954,"STEP_SWAP_BUFFERS"
-2954,546184802611,7000,0,"STEP_SWAP_BUFFERS",546184809611,546186327829,546186327829,2954,"STEP_DRAW_AND_SWAP"
-2954,546186327829,8000,0,"STEP_DRAW_AND_SWAP",546186335829,546205976829,546205976829,2954,"End"
-2954,546205976829,2000,0,"End",546205978829,"[NULL]",546183000403,2956,"AsyncBegin"
-2956,546183000403,45256426,1,"AsyncBegin",546183000403,546186878403,546186997403,2956,"Begin"
-2956,546186997403,1000,1,"Begin",546187103403,546186878403,546187022403,2956,"STEP_SEND_INPUT_EVENT_UI"
-2956,546187022403,66000,1,"STEP_SEND_INPUT_EVENT_UI",546187103403,546187138611,546187140611,2956,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2956,546187140611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546187149611,546194427611,546194430611,2956,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2956,546194430611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546194464611,546195772611,546195772611,2956,"STEP_SWAP_BUFFERS"
-2956,546195772611,6000,1,"STEP_SWAP_BUFFERS",546195778611,546207402829,546207402829,2956,"STEP_DRAW_AND_SWAP"
-2956,546207402829,7000,1,"STEP_DRAW_AND_SWAP",546207409829,546228297829,546228297829,2956,"End"
-2956,546228297829,7000,1,"End",546228304829,"[NULL]",546200000403,2960,"AsyncBegin"
-2960,546200000403,40097426,1,"AsyncBegin",546200000403,546201377403,546201519403,2960,"Begin"
-2960,546201519403,1000,1,"Begin",546201586403,546201377403,546201544403,2960,"STEP_SEND_INPUT_EVENT_UI"
-2960,546201544403,31000,1,"STEP_SEND_INPUT_EVENT_UI",546201586403,546201665611,546201667611,2960,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2960,546201667611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546201677611,546205643611,546205647611,2960,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2960,546205647611,3000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546205696611,546206945611,546206945611,2960,"STEP_SWAP_BUFFERS"
-2960,546206945611,8000,1,"STEP_SWAP_BUFFERS",546206953611,546220078829,546220078829,2960,"STEP_DRAW_AND_SWAP"
-2960,546220078829,1000,1,"STEP_DRAW_AND_SWAP",546220079829,546240099829,546240099829,2960,"End"
-2960,546240099829,1000,1,"End",546240100829,"[NULL]",546208000403,2962,"AsyncBegin"
-2962,546208000403,32086426,0,"AsyncBegin",546208000403,546209350403,546209483403,2962,"Begin"
-2962,546209483403,1000,0,"Begin",546209547403,546209350403,546209508403,2962,"STEP_SEND_INPUT_EVENT_UI"
-2962,546209508403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546209547403,546209595611,546209597611,2962,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2962,546209597611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546209606611,546217074611,546217078611,2962,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2962,546217078611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546217117611,546219522611,546219522611,2962,"STEP_SWAP_BUFFERS"
-2962,546219522611,6000,0,"STEP_SWAP_BUFFERS",546219528611,546220068829,546220068829,2962,"STEP_DRAW_AND_SWAP"
-2962,546220068829,8000,0,"STEP_DRAW_AND_SWAP",546220076829,546240093829,546240093829,2962,"End"
-2962,546240093829,2000,0,"End",546240095829,"[NULL]",546216000403,2964,"AsyncBegin"
-2964,546216000403,34686426,0,"AsyncBegin",546216000403,546217643403,546217768403,2964,"Begin"
-2964,546217768403,1000,0,"Begin",546217868403,546217643403,546217821403,2964,"STEP_SEND_INPUT_EVENT_UI"
-2964,546217821403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546217868403,546217917611,546217920611,2964,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2964,546217920611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546217930611,546228051611,546228054611,2964,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2964,546228054611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546228091611,546230585611,546230585611,2964,"STEP_SWAP_BUFFERS"
-2964,546230585611,9000,0,"STEP_SWAP_BUFFERS",546230594611,546230999829,546230999829,2964,"STEP_DRAW_AND_SWAP"
-2964,546230999829,7000,0,"STEP_DRAW_AND_SWAP",546231006829,546250694829,546250694829,2964,"End"
-2964,546250694829,2000,0,"End",546250696829,"[NULL]",546233000403,2968,"AsyncBegin"
-2968,546233000403,28852426,0,"AsyncBegin",546233000403,546234475403,546234614403,2968,"Begin"
-2968,546234614403,1000,0,"Begin",546234681403,546234475403,546234639403,2968,"STEP_SEND_INPUT_EVENT_UI"
-2968,546234639403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546234681403,546234720611,546234723611,2968,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2968,546234723611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546234734611,546239796611,546239800611,2968,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2968,546239800611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546239846611,546241573611,546241573611,2968,"STEP_SWAP_BUFFERS"
-2968,546241573611,7000,0,"STEP_SWAP_BUFFERS",546241580611,546241964829,546241964829,2968,"STEP_DRAW_AND_SWAP"
-2968,546241964829,7000,0,"STEP_DRAW_AND_SWAP",546241971829,546261861829,546261861829,2968,"End"
-2968,546261861829,2000,0,"End",546261863829,"[NULL]",546241000403,2970,"AsyncBegin"
-2970,546241000403,32494426,0,"AsyncBegin",546241000403,546243029403,546243175403,2970,"Begin"
-2970,546243175403,1000,0,"Begin",546243308403,546243029403,546243234403,2970,"STEP_SEND_INPUT_EVENT_UI"
-2970,546243234403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546243308403,546243388611,546243394611,2970,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2970,546243394611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546243407611,546250667611,546250672611,2970,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2970,546250672611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546250734611,546252948611,546252948611,2970,"STEP_SWAP_BUFFERS"
-2970,546252948611,8000,0,"STEP_SWAP_BUFFERS",546252956611,546253408829,546253408829,2970,"STEP_DRAW_AND_SWAP"
-2970,546253408829,8000,0,"STEP_DRAW_AND_SWAP",546253416829,546273503829,546273503829,2970,"End"
-2970,546273503829,2000,0,"End",546273505829,"[NULL]",546249000403,2972,"AsyncBegin"
-2972,546249000403,37304426,0,"AsyncBegin",546249000403,546250918403,546251050403,2972,"Begin"
-2972,546251050403,1000,0,"Begin",546251118403,546250918403,546251077403,2972,"STEP_SEND_INPUT_EVENT_UI"
-2972,546251077403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546251118403,546251144611,546251146611,2972,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2972,546251146611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546251156611,546262000611,546262004611,2972,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2972,546262004611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546262046611,546263899611,546263899611,2972,"STEP_SWAP_BUFFERS"
-2972,546263899611,8000,0,"STEP_SWAP_BUFFERS",546263907611,546264307829,546264307829,2972,"STEP_DRAW_AND_SWAP"
-2972,546264307829,7000,0,"STEP_DRAW_AND_SWAP",546264314829,546286312829,546286312829,2972,"End"
-2972,546286312829,2000,0,"End",546286314829,"[NULL]",546265000403,2976,"AsyncBegin"
-2976,546265000403,32101426,0,"AsyncBegin",546265000403,546266881403,546267025403,2976,"Begin"
-2976,546267025403,31000,0,"Begin",546267136403,546266881403,546267087403,2976,"STEP_SEND_INPUT_EVENT_UI"
-2976,546267087403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546267136403,546267229611,546267235611,2976,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2976,546267235611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546267248611,546273055611,546273059611,2976,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2976,546273059611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546273180611,546275260611,546275260611,2976,"STEP_SWAP_BUFFERS"
-2976,546275260611,8000,0,"STEP_SWAP_BUFFERS",546275268611,546275663829,546275663829,2976,"STEP_DRAW_AND_SWAP"
-2976,546275663829,8000,0,"STEP_DRAW_AND_SWAP",546275671829,546297108829,546297108829,2976,"End"
-2976,546297108829,3000,0,"End",546297111829,"[NULL]",546273000403,2978,"AsyncBegin"
-2978,546273000403,34156426,0,"AsyncBegin",546273000403,546275484403,546275607403,2978,"Begin"
-2978,546275607403,1000,0,"Begin",546276344403,546275484403,546275633403,2978,"STEP_SEND_INPUT_EVENT_UI"
-2978,546275633403,690000,0,"STEP_SEND_INPUT_EVENT_UI",546276344403,546275715611,546275719611,2978,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2978,546275719611,5000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546275726611,546283860611,546283863611,2978,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2978,546283863611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546283902611,546285767611,546285767611,2978,"STEP_SWAP_BUFFERS"
-2978,546285767611,7000,0,"STEP_SWAP_BUFFERS",546285774611,546286878829,546286878829,2978,"STEP_DRAW_AND_SWAP"
-2978,546286878829,5000,0,"STEP_DRAW_AND_SWAP",546286883829,546307163829,546307163829,2978,"End"
-2978,546307163829,2000,0,"End",546307165829,"[NULL]",546290000403,2982,"AsyncBegin"
-2982,546290000403,27915426,0,"AsyncBegin",546290000403,546291566403,546291911403,2982,"Begin"
-2982,546291911403,2000,0,"Begin",546291983403,546291566403,546291939403,2982,"STEP_SEND_INPUT_EVENT_UI"
-2982,546291939403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546291983403,546292037611,546292042611,2982,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2982,546292042611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546292053611,546295022611,546295026611,2982,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2982,546295026611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546295062611,546296953611,546296953611,2982,"STEP_SWAP_BUFFERS"
-2982,546296953611,7000,0,"STEP_SWAP_BUFFERS",546296960611,546297448829,546297448829,2982,"STEP_DRAW_AND_SWAP"
-2982,546297448829,4000,0,"STEP_DRAW_AND_SWAP",546297452829,546317924829,546317924829,2982,"End"
-2982,546317924829,2000,0,"End",546317926829,"[NULL]",546298000403,2984,"AsyncBegin"
-2984,546298000403,30723426,0,"AsyncBegin",546298000403,546299971403,546300114403,2984,"Begin"
-2984,546300114403,1000,0,"Begin",546300180403,546299971403,546300138403,2984,"STEP_SEND_INPUT_EVENT_UI"
-2984,546300138403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546300180403,546300219611,546300220611,2984,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2984,546300220611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546300230611,546306555611,546306559611,2984,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2984,546306559611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546306598611,546308592611,546308592611,2984,"STEP_SWAP_BUFFERS"
-2984,546308592611,5000,0,"STEP_SWAP_BUFFERS",546308597611,546308994829,546308994829,2984,"STEP_DRAW_AND_SWAP"
-2984,546308994829,7000,0,"STEP_DRAW_AND_SWAP",546309001829,546328731829,546328731829,2984,"End"
-2984,546328731829,2000,0,"End",546328733829,"[NULL]",546307000403,2986,"AsyncBegin"
-2986,546307000403,32918426,0,"AsyncBegin",546307000403,546308149403,546308285403,2986,"Begin"
-2986,546308285403,2000,0,"Begin",546308356403,546308149403,546308311403,2986,"STEP_SEND_INPUT_EVENT_UI"
-2986,546308311403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546308356403,546308444611,546308446611,2986,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2986,546308446611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546308454611,546317470611,546317474611,2986,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2986,546317474611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546317526611,546319206611,546319206611,2986,"STEP_SWAP_BUFFERS"
-2986,546319206611,8000,0,"STEP_SWAP_BUFFERS",546319214611,546319620829,546319620829,2986,"STEP_DRAW_AND_SWAP"
-2986,546319620829,7000,0,"STEP_DRAW_AND_SWAP",546319627829,546339929829,546339929829,2986,"End"
-2986,546339929829,3000,0,"End",546339932829,"[NULL]",546323000403,2990,"AsyncBegin"
-2990,546323000403,29800426,0,"AsyncBegin",546323000403,546324513403,546324666403,2990,"Begin"
-2990,546324666403,2000,0,"Begin",546324737403,546324513403,546324693403,2990,"STEP_SEND_INPUT_EVENT_UI"
-2990,546324693403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546324737403,546324784611,546324786611,2990,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2990,546324786611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546324796611,546328619611,546328624611,2990,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2990,546328624611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546328668611,546330703611,546330703611,2990,"STEP_SWAP_BUFFERS"
-2990,546330703611,33000,0,"STEP_SWAP_BUFFERS",546330736611,546331260829,546331260829,2990,"STEP_DRAW_AND_SWAP"
-2990,546331260829,8000,0,"STEP_DRAW_AND_SWAP",546331268829,546352807829,546352807829,2990,"End"
-2990,546352807829,3000,0,"End",546352810829,"[NULL]",546331000403,2992,"AsyncBegin"
-2992,546331000403,31314426,0,"AsyncBegin",546331000403,546332697403,546333011403,2992,"Begin"
-2992,546333011403,2000,0,"Begin",546333088403,546332697403,546333039403,2992,"STEP_SEND_INPUT_EVENT_UI"
-2992,546333039403,38000,0,"STEP_SEND_INPUT_EVENT_UI",546333088403,546333139611,546333146611,2992,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2992,546333146611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546333158611,546340189611,546340193611,2992,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2992,546340193611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546340229611,546342849611,546342849611,2992,"STEP_SWAP_BUFFERS"
-2992,546342849611,6000,0,"STEP_SWAP_BUFFERS",546342855611,546343276829,546343276829,2992,"STEP_DRAW_AND_SWAP"
-2992,546343276829,25000,0,"STEP_DRAW_AND_SWAP",546343301829,546362325829,546362325829,2992,"End"
-2992,546362325829,2000,0,"End",546362327829,"[NULL]",546339000403,2994,"AsyncBegin"
-2994,546339000403,35092426,0,"AsyncBegin",546339000403,546340778403,546341033403,2994,"Begin"
-2994,546341033403,2000,0,"Begin",546341105403,546340778403,546341060403,2994,"STEP_SEND_INPUT_EVENT_UI"
-2994,546341060403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546341105403,546341145611,546341151611,2994,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2994,546341151611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546341161611,546350884611,546350887611,2994,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2994,546350887611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546350991611,546352902611,546352902611,2994,"STEP_SWAP_BUFFERS"
-2994,546352902611,7000,0,"STEP_SWAP_BUFFERS",546352909611,546353440829,546353440829,2994,"STEP_DRAW_AND_SWAP"
-2994,546353440829,5000,0,"STEP_DRAW_AND_SWAP",546353445829,546374102829,546374102829,2994,"End"
-2994,546374102829,2000,0,"End",546374104829,"[NULL]",546356000403,2998,"AsyncBegin"
-2998,546356000403,28702426,0,"AsyncBegin",546356000403,546357505403,546357671403,2998,"Begin"
-2998,546357671403,2000,0,"Begin",546357755403,546357505403,546357704403,2998,"STEP_SEND_INPUT_EVENT_UI"
-2998,546357704403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546357755403,546357777611,546357779611,2998,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2998,546357779611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546357788611,546362651611,546362655611,2998,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2998,546362655611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546362697611,546364468611,546364468611,2998,"STEP_SWAP_BUFFERS"
-2998,546364468611,9000,0,"STEP_SWAP_BUFFERS",546364477611,546364896829,546364896829,2998,"STEP_DRAW_AND_SWAP"
-2998,546364896829,8000,0,"STEP_DRAW_AND_SWAP",546364904829,546384825829,546384825829,2998,"End"
-2998,546384825829,109000,0,"End",546384934829,"[NULL]",546364000403,3000,"AsyncBegin"
-3000,546364000403,32457426,0,"AsyncBegin",546364000403,546365563403,546365752403,3000,"Begin"
-3000,546365752403,1000,0,"Begin",546365833403,546365563403,546365781403,3000,"STEP_SEND_INPUT_EVENT_UI"
-3000,546365781403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546365833403,546366021611,546366023611,3000,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3000,546366023611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546366034611,546373564611,546373568611,3000,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3000,546373568611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546373614611,546376356611,546376356611,3000,"STEP_SWAP_BUFFERS"
-3000,546376356611,6000,0,"STEP_SWAP_BUFFERS",546376362611,546376832829,546376832829,3000,"STEP_DRAW_AND_SWAP"
-3000,546376832829,7000,0,"STEP_DRAW_AND_SWAP",546376839829,546396465829,546396465829,3000,"End"
-3000,546396465829,3000,0,"End",546396468829,"[NULL]",546372000403,3002,"AsyncBegin"
-3002,546372000403,35043426,0,"AsyncBegin",546372000403,546374588403,546374732403,3002,"Begin"
-3002,546374732403,1000,0,"Begin",546374803403,546374588403,546374760403,3002,"STEP_SEND_INPUT_EVENT_UI"
-3002,546374760403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546374803403,546374837611,546374839611,3002,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3002,546374839611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546374848611,546384434611,546384437611,3002,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3002,546384437611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546384477611,546386153611,546386153611,3002,"STEP_SWAP_BUFFERS"
-3002,546386153611,7000,0,"STEP_SWAP_BUFFERS",546386160611,546386698829,546386698829,3002,"STEP_DRAW_AND_SWAP"
-3002,546386698829,6000,0,"STEP_DRAW_AND_SWAP",546386704829,546407050829,546407050829,3002,"End"
-3002,546407050829,2000,0,"End",546407052829,"[NULL]",546389000403,3006,"AsyncBegin"
-3006,546389000403,29285426,0,"AsyncBegin",546389000403,546390565403,546390760403,3006,"Begin"
-3006,546390760403,2000,0,"Begin",546390845403,546390565403,546390790403,3006,"STEP_SEND_INPUT_EVENT_UI"
-3006,546390790403,40000,0,"STEP_SEND_INPUT_EVENT_UI",546390845403,546390891611,546390894611,3006,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3006,546390894611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546390905611,546396335611,546396340611,3006,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3006,546396340611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546396384611,546398059611,546398059611,3006,"STEP_SWAP_BUFFERS"
-3006,546398059611,7000,0,"STEP_SWAP_BUFFERS",546398066611,546398466829,546398466829,3006,"STEP_DRAW_AND_SWAP"
-3006,546398466829,8000,0,"STEP_DRAW_AND_SWAP",546398474829,546418293829,546418293829,3006,"End"
-3006,546418293829,2000,0,"End",546418295829,"[NULL]",546397000403,3008,"AsyncBegin"
-3008,546397000403,32831426,0,"AsyncBegin",546397000403,546398582403,546398711403,3008,"Begin"
-3008,546398711403,1000,0,"Begin",546398780403,546398582403,546398736403,3008,"STEP_SEND_INPUT_EVENT_UI"
-3008,546398736403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546398780403,546399217611,546399219611,3008,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3008,546399219611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546399228611,546406876611,546406881611,3008,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3008,546406881611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546407869611,546409583611,546409583611,3008,"STEP_SWAP_BUFFERS"
-3008,546409583611,7000,0,"STEP_SWAP_BUFFERS",546409590611,546410078829,546410078829,3008,"STEP_DRAW_AND_SWAP"
-3008,546410078829,7000,0,"STEP_DRAW_AND_SWAP",546410085829,546429839829,546429839829,3008,"End"
-3008,546429839829,3000,0,"End",546429842829,"[NULL]",546405000403,3010,"AsyncBegin"
-3010,546405000403,35630426,0,"AsyncBegin",546405000403,546407326403,546407543403,3010,"Begin"
-3010,546407543403,2000,0,"Begin",546407626403,546407326403,546407575403,3010,"STEP_SEND_INPUT_EVENT_UI"
-3010,546407575403,38000,0,"STEP_SEND_INPUT_EVENT_UI",546407626403,546408025611,546408028611,3010,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3010,546408028611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546408037611,546417901611,546417904611,3010,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3010,546417904611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546417944611,546420009611,546420009611,3010,"STEP_SWAP_BUFFERS"
-3010,546420009611,11000,0,"STEP_SWAP_BUFFERS",546420020611,546420431829,546420431829,3010,"STEP_DRAW_AND_SWAP"
-3010,546420431829,7000,0,"STEP_DRAW_AND_SWAP",546420438829,546440637829,546440637829,3010,"End"
-3010,546440637829,2000,0,"End",546440639829,"[NULL]",546422000403,3014,"AsyncBegin"
-3014,546422000403,30119426,0,"AsyncBegin",546422000403,546423149403,546423316403,3014,"Begin"
-3014,546423316403,2000,0,"Begin",546423392403,546423149403,546423343403,3014,"STEP_SEND_INPUT_EVENT_UI"
-3014,546423343403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546423392403,546423418611,546423420611,3014,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3014,546423420611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546423428611,546429153611,546429158611,3014,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3014,546429158611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546429196611,546431932611,546431932611,3014,"STEP_SWAP_BUFFERS"
-3014,546431932611,6000,0,"STEP_SWAP_BUFFERS",546431938611,546432346829,546432346829,3014,"STEP_DRAW_AND_SWAP"
-3014,546432346829,7000,0,"STEP_DRAW_AND_SWAP",546432353829,546452126829,546452126829,3014,"End"
-3014,546452126829,2000,0,"End",546452128829,"[NULL]",546430000403,3016,"AsyncBegin"
-3016,546430000403,33185426,0,"AsyncBegin",546430000403,546431264403,546431405403,3016,"Begin"
-3016,546431405403,1000,0,"Begin",546431480403,546431264403,546431431403,3016,"STEP_SEND_INPUT_EVENT_UI"
-3016,546431431403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546431480403,546431519611,546431522611,3016,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3016,546431522611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546431533611,546441188611,546441191611,3016,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3016,546441191611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546441224611,546443045611,546443045611,3016,"STEP_SWAP_BUFFERS"
-3016,546443045611,6000,0,"STEP_SWAP_BUFFERS",546443051611,546443544829,546443544829,3016,"STEP_DRAW_AND_SWAP"
-3016,546443544829,7000,0,"STEP_DRAW_AND_SWAP",546443551829,546463194829,546463194829,3016,"End"
-3016,546463194829,2000,0,"End",546463196829,"[NULL]",546446000403,3020,"AsyncBegin"
-3020,546446000403,28386426,0,"AsyncBegin",546446000403,546447951403,546448098403,3020,"Begin"
-3020,546448098403,1000,0,"Begin",546448169403,546447951403,546448124403,3020,"STEP_SEND_INPUT_EVENT_UI"
-3020,546448124403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546448169403,546448219611,546448222611,3020,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3020,546448222611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546448231611,546451329611,546451333611,3020,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3020,546451333611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546451372611,546454220611,546454220611,3020,"STEP_SWAP_BUFFERS"
-3020,546454220611,9000,0,"STEP_SWAP_BUFFERS",546454229611,546454674829,546454674829,3020,"STEP_DRAW_AND_SWAP"
-3020,546454674829,7000,0,"STEP_DRAW_AND_SWAP",546454681829,546474393829,546474393829,3020,"End"
-3020,546474393829,3000,0,"End",546474396829,"[NULL]",546455000403,3022,"AsyncBegin"
-3022,546455000403,30102426,0,"AsyncBegin",546455000403,546456215403,546456359403,3022,"Begin"
-3022,546456359403,1000,0,"Begin",546456428403,546456215403,546456384403,3022,"STEP_SEND_INPUT_EVENT_UI"
-3022,546456384403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546456428403,546456461611,546456463611,3022,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3022,546456463611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546456472611,546462961611,546462965611,3022,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3022,546462965611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546463005611,546465098611,546465098611,3022,"STEP_SWAP_BUFFERS"
-3022,546465098611,6000,0,"STEP_SWAP_BUFFERS",546465104611,546465524829,546465524829,3022,"STEP_DRAW_AND_SWAP"
-3022,546465524829,8000,0,"STEP_DRAW_AND_SWAP",546465532829,546485110829,546485110829,3022,"End"
-3022,546485110829,2000,0,"End",546485112829,"[NULL]",546463000403,3024,"AsyncBegin"
-3024,546463000403,33512426,0,"AsyncBegin",546463000403,546464373403,546464518403,3024,"Begin"
-3024,546464518403,1000,0,"Begin",546464595403,546464373403,546464544403,3024,"STEP_SEND_INPUT_EVENT_UI"
-3024,546464544403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546464595403,546464703611,546464705611,3024,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3024,546464705611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546464715611,546473824611,546473827611,3024,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3024,546473827611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546473862611,546475568611,546475568611,3024,"STEP_SWAP_BUFFERS"
-3024,546475568611,8000,0,"STEP_SWAP_BUFFERS",546475576611,546476008829,546476008829,3024,"STEP_DRAW_AND_SWAP"
-3024,546476008829,8000,0,"STEP_DRAW_AND_SWAP",546476016829,546496519829,546496519829,3024,"End"
-3024,546496519829,2000,0,"End",546496521829,"[NULL]",546479000403,3028,"AsyncBegin"
-3028,546479000403,28455426,0,"AsyncBegin",546479000403,546480721403,546480874403,3028,"Begin"
-3028,546480874403,2000,0,"Begin",546480950403,546480721403,546480902403,3028,"STEP_SEND_INPUT_EVENT_UI"
-3028,546480902403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546480950403,546481026611,546481028611,3028,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3028,546481028611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546481041611,546485007611,546485011611,3028,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3028,546485011611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546485059611,546487385611,546487385611,3028,"STEP_SWAP_BUFFERS"
-3028,546487385611,8000,0,"STEP_SWAP_BUFFERS",546487393611,546487986829,546487986829,3028,"STEP_DRAW_AND_SWAP"
-3028,546487986829,8000,0,"STEP_DRAW_AND_SWAP",546487994829,546507462829,546507462829,3028,"End"
-3028,546507462829,3000,0,"End",546507465829,"[NULL]",546488000403,3030,"AsyncBegin"
-3030,546488000403,30791426,0,"AsyncBegin",546488000403,546489074403,546489211403,3030,"Begin"
-3030,546489211403,2000,0,"Begin",546489275403,546489074403,546489236403,3030,"STEP_SEND_INPUT_EVENT_UI"
-3030,546489236403,28000,0,"STEP_SEND_INPUT_EVENT_UI",546489275403,546489489611,546489491611,3030,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3030,546489491611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546489499611,546496435611,546496440611,3030,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3030,546496440611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546496481611,546498136611,546498136611,3030,"STEP_SWAP_BUFFERS"
-3030,546498136611,5000,0,"STEP_SWAP_BUFFERS",546498141611,546498528829,546498528829,3030,"STEP_DRAW_AND_SWAP"
-3030,546498528829,6000,0,"STEP_DRAW_AND_SWAP",546498534829,546518802829,546518802829,3030,"End"
-3030,546518802829,1000,0,"End",546518803829,"[NULL]",546496000403,3032,"AsyncBegin"
-3032,546496000403,34105426,0,"AsyncBegin",546496000403,546497219403,546497345403,3032,"Begin"
-3032,546497345403,1000,0,"Begin",546497413403,546497219403,546497371403,3032,"STEP_SEND_INPUT_EVENT_UI"
-3032,546497371403,30000,0,"STEP_SEND_INPUT_EVENT_UI",546497413403,546497439611,546497441611,3032,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3032,546497441611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546497450611,546507298611,546507302611,3032,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3032,546507302611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546507342611,546509375611,546509375611,3032,"STEP_SWAP_BUFFERS"
-3032,546509375611,7000,0,"STEP_SWAP_BUFFERS",546509382611,546510189829,546510189829,3032,"STEP_DRAW_AND_SWAP"
-3032,546510189829,9000,0,"STEP_DRAW_AND_SWAP",546510198829,546530114829,546530114829,3032,"End"
-3032,546530114829,2000,0,"End",546530116829,"[NULL]",546512000403,3036,"AsyncBegin"
-3036,546512000403,29329426,0,"AsyncBegin",546512000403,546513858403,546514007403,3036,"Begin"
-3036,546514007403,2000,0,"Begin",546514080403,546513858403,546514036403,3036,"STEP_SEND_INPUT_EVENT_UI"
-3036,546514036403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546514080403,546514160611,546514163611,3036,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3036,546514163611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546514176611,546519116611,546519120611,3036,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3036,546519120611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546519156611,546521220611,546521220611,3036,"STEP_SWAP_BUFFERS"
-3036,546521220611,8000,0,"STEP_SWAP_BUFFERS",546521228611,546521662829,546521662829,3036,"STEP_DRAW_AND_SWAP"
-3036,546521662829,8000,0,"STEP_DRAW_AND_SWAP",546521670829,546541338829,546541338829,3036,"End"
-3036,546541338829,2000,0,"End",546541340829,"[NULL]",546520000403,3038,"AsyncBegin"
-3038,546520000403,32321426,0,"AsyncBegin",546520000403,546522038403,546522186403,3038,"Begin"
-3038,546522186403,2000,0,"Begin",546522274403,546522038403,546522222403,3038,"STEP_SEND_INPUT_EVENT_UI"
-3038,546522222403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546522274403,546522327611,546522330611,3038,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3038,546522330611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546522339611,546529785611,546529790611,3038,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3038,546529790611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546529836611,546532477611,546532477611,3038,"STEP_SWAP_BUFFERS"
-3038,546532477611,8000,0,"STEP_SWAP_BUFFERS",546532485611,546532942829,546532942829,3038,"STEP_DRAW_AND_SWAP"
-3038,546532942829,8000,0,"STEP_DRAW_AND_SWAP",546532950829,546552358829,546552358829,3038,"End"
-3038,546552358829,9000,0,"End",546552367829,"[NULL]",546529000403,3040,"AsyncBegin"
-3040,546529000403,34457426,0,"AsyncBegin",546529000403,546530169403,546530324403,3040,"Begin"
-3040,546530324403,1000,0,"Begin",546530399403,546530169403,546530352403,3040,"STEP_SEND_INPUT_EVENT_UI"
-3040,546530352403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546530399403,546530540611,546530542611,3040,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3040,546530542611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546530557611,546540823611,546540826611,3040,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3040,546540826611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546541737611,546543749611,546543749611,3040,"STEP_SWAP_BUFFERS"
-3040,546543749611,8000,0,"STEP_SWAP_BUFFERS",546543757611,546544204829,546544204829,3040,"STEP_DRAW_AND_SWAP"
-3040,546544204829,8000,0,"STEP_DRAW_AND_SWAP",546544212829,546563463829,546563463829,3040,"End"
-3040,546563463829,3000,0,"End",546563466829,"[NULL]",546545000403,3044,"AsyncBegin"
-3044,546545000403,29668426,0,"AsyncBegin",546545000403,546546602403,546546816403,3044,"Begin"
-3044,546546816403,1000,0,"Begin",546546890403,546546602403,546546844403,3044,"STEP_SEND_INPUT_EVENT_UI"
-3044,546546844403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546546890403,546546951611,546546953611,3044,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3044,546546953611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546546963611,546552344611,546552349611,3044,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3044,546552349611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546552400611,546554385611,546554385611,3044,"STEP_SWAP_BUFFERS"
-3044,546554385611,8000,0,"STEP_SWAP_BUFFERS",546554393611,546555748829,546555748829,3044,"STEP_DRAW_AND_SWAP"
-3044,546555748829,7000,0,"STEP_DRAW_AND_SWAP",546555755829,546574677829,546574677829,3044,"End"
-3044,546574677829,2000,0,"End",546574679829,"[NULL]",546553000403,3046,"AsyncBegin"
-3046,546553000403,32830426,0,"AsyncBegin",546553000403,546554885403,546555031403,3046,"Begin"
-3046,546555031403,2000,0,"Begin",546555128403,546554885403,546555060403,3046,"STEP_SEND_INPUT_EVENT_UI"
-3046,546555060403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546555128403,546555422611,546555425611,3046,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3046,546555425611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546555434611,546563185611,546563189611,3046,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3046,546563189611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546563228611,546565411611,546565411611,3046,"STEP_SWAP_BUFFERS"
-3046,546565411611,8000,0,"STEP_SWAP_BUFFERS",546565419611,546565832829,546565832829,3046,"STEP_DRAW_AND_SWAP"
-3046,546565832829,8000,0,"STEP_DRAW_AND_SWAP",546565840829,546585839829,546585839829,3046,"End"
-3046,546585839829,2000,0,"End",546585841829,"[NULL]",546561000403,3048,"AsyncBegin"
-3048,546561000403,35849426,0,"AsyncBegin",546561000403,546562758403,546562888403,3048,"Begin"
-3048,546562888403,2000,0,"Begin",546562956403,546562758403,546562915403,3048,"STEP_SEND_INPUT_EVENT_UI"
-3048,546562915403,30000,0,"STEP_SEND_INPUT_EVENT_UI",546562956403,546563366611,546563369611,3048,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3048,546563369611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546563376611,546574498611,546574502611,3048,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3048,546574502611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546574540611,546576468611,546576468611,3048,"STEP_SWAP_BUFFERS"
-3048,546576468611,7000,0,"STEP_SWAP_BUFFERS",546576475611,546576952829,546576952829,3048,"STEP_DRAW_AND_SWAP"
-3048,546576952829,7000,0,"STEP_DRAW_AND_SWAP",546576959829,546596855829,546596855829,3048,"End"
-3048,546596855829,2000,0,"End",546596857829,"[NULL]",546578000403,3052,"AsyncBegin"
-3052,546578000403,30365426,0,"AsyncBegin",546578000403,546579536403,546579683403,3052,"Begin"
-3052,546579683403,1000,0,"Begin",546579801403,546579536403,546579740403,3052,"STEP_SEND_INPUT_EVENT_UI"
-3052,546579740403,45000,0,"STEP_SEND_INPUT_EVENT_UI",546579801403,546579837611,546579841611,3052,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3052,546579841611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546579852611,546585857611,546585861611,3052,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3052,546585861611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546585911611,546588384611,546588384611,3052,"STEP_SWAP_BUFFERS"
-3052,546588384611,5000,0,"STEP_SWAP_BUFFERS",546588389611,546588821829,546588821829,3052,"STEP_DRAW_AND_SWAP"
-3052,546588821829,8000,0,"STEP_DRAW_AND_SWAP",546588829829,546608373829,546608373829,3052,"End"
-3052,546608373829,2000,0,"End",546608375829,"[NULL]",546586000403,3054,"AsyncBegin"
-3054,546586000403,33666426,0,"AsyncBegin",546586000403,546587765403,546587909403,3054,"Begin"
-3054,546587909403,2000,0,"Begin",546587983403,546587765403,546587936403,3054,"STEP_SEND_INPUT_EVENT_UI"
-3054,546587936403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546587983403,546588218611,546588223611,3054,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3054,546588223611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546588233611,546597078611,546597082611,3054,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3054,546597082611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546597117611,546599028611,546599028611,3054,"STEP_SWAP_BUFFERS"
-3054,546599028611,7000,0,"STEP_SWAP_BUFFERS",546599035611,546599458829,546599458829,3054,"STEP_DRAW_AND_SWAP"
-3054,546599458829,6000,0,"STEP_DRAW_AND_SWAP",546599464829,546619678829,546619678829,3054,"End"
-3054,546619678829,3000,0,"End",546619681829,"[NULL]",546594000403,3056,"AsyncBegin"
-3056,546594000403,36913426,0,"AsyncBegin",546594000403,546596575403,546596755403,3056,"Begin"
-3056,546596755403,1000,0,"Begin",546596834403,546596575403,546596782403,3056,"STEP_SEND_INPUT_EVENT_UI"
-3056,546596782403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546596834403,546597253611,546597255611,3056,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3056,546597255611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546597263611,546608211611,546608216611,3056,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3056,546608216611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546608259611,546609939611,546609939611,3056,"STEP_SWAP_BUFFERS"
-3056,546609939611,30000,0,"STEP_SWAP_BUFFERS",546609969611,546610374829,546610374829,3056,"STEP_DRAW_AND_SWAP"
-3056,546610374829,14000,0,"STEP_DRAW_AND_SWAP",546610388829,546630922829,546630922829,3056,"End"
-3056,546630922829,2000,0,"End",546630924829,"[NULL]",546611000403,3060,"AsyncBegin"
-3060,546611000403,30855426,0,"AsyncBegin",546611000403,546612047403,546612188403,3060,"Begin"
-3060,546612188403,1000,0,"Begin",546612256403,546612047403,546612214403,3060,"STEP_SEND_INPUT_EVENT_UI"
-3060,546612214403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546612256403,546612302611,546612305611,3060,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3060,546612305611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546612317611,546620167611,546620171611,3060,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3060,546620171611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546620269611,546622281611,546622281611,3060,"STEP_SWAP_BUFFERS"
-3060,546622281611,7000,0,"STEP_SWAP_BUFFERS",546622288611,546622725829,546622725829,3060,"STEP_DRAW_AND_SWAP"
-3060,546622725829,8000,0,"STEP_DRAW_AND_SWAP",546622733829,546641865829,546641865829,3060,"End"
-3060,546641865829,3000,0,"End",546641868829,"[NULL]",546619000403,3062,"AsyncBegin"
-3062,546619000403,33897426,0,"AsyncBegin",546619000403,546620384403,546620518403,3062,"Begin"
-3062,546620518403,1000,0,"Begin",546620591403,546620384403,546620548403,3062,"STEP_SEND_INPUT_EVENT_UI"
-3062,546620548403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546620591403,546620608611,546620611611,3062,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3062,546620611611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546620618611,546630379611,546630384611,3062,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3062,546630384611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546630421611,546632167611,546632167611,3062,"STEP_SWAP_BUFFERS"
-3062,546632167611,8000,0,"STEP_SWAP_BUFFERS",546632175611,546632600829,546632600829,3062,"STEP_DRAW_AND_SWAP"
-3062,546632600829,7000,0,"STEP_DRAW_AND_SWAP",546632607829,546652905829,546652905829,3062,"End"
-3062,546652905829,3000,0,"End",546652908829,"[NULL]",546627000403,3064,"AsyncBegin"
-3064,546627000403,36941426,0,"AsyncBegin",546627000403,546629888403,546630054403,3064,"Begin"
-3064,546630054403,1000,0,"Begin",546630174403,546629888403,546630083403,3064,"STEP_SEND_INPUT_EVENT_UI"
-3064,546630083403,76000,0,"STEP_SEND_INPUT_EVENT_UI",546630174403,546630538611,546630540611,3064,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3064,546630540611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546630548611,546642123611,546642128611,3064,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3064,546642128611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546642161611,546643979611,546643979611,3064,"STEP_SWAP_BUFFERS"
-3064,546643979611,7000,0,"STEP_SWAP_BUFFERS",546643986611,546644451829,546644451829,3064,"STEP_DRAW_AND_SWAP"
-3064,546644451829,7000,0,"STEP_DRAW_AND_SWAP",546644458829,546663948829,546663948829,3064,"End"
-3064,546663948829,2000,0,"End",546663950829,"[NULL]",546644000403,3068,"AsyncBegin"
-3068,546644000403,31194426,0,"AsyncBegin",546644000403,546645017403,546645164403,3068,"Begin"
-3068,546645164403,1000,0,"Begin",546645251403,546645017403,546645192403,3068,"STEP_SEND_INPUT_EVENT_UI"
-3068,546645192403,45000,0,"STEP_SEND_INPUT_EVENT_UI",546645251403,546645343611,546645345611,3068,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3068,546645345611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546645356611,546653047611,546653050611,3068,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3068,546653050611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546653084611,546655933611,546655933611,3068,"STEP_SWAP_BUFFERS"
-3068,546655933611,5000,0,"STEP_SWAP_BUFFERS",546655938611,546656344829,546656344829,3068,"STEP_DRAW_AND_SWAP"
-3068,546656344829,8000,0,"STEP_DRAW_AND_SWAP",546656352829,546675205829,546675205829,3068,"End"
-3068,546675205829,2000,0,"End",546675207829,"[NULL]",546652000403,3070,"AsyncBegin"
-3070,546652000403,34276426,0,"AsyncBegin",546652000403,546653717403,546653856403,3070,"Begin"
-3070,546653856403,2000,0,"Begin",546653957403,546653717403,546653911403,3070,"STEP_SEND_INPUT_EVENT_UI"
-3070,546653911403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546653957403,546654006611,546654013611,3070,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3070,546654013611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546654025611,546663767611,546663770611,3070,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3070,546663770611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546663811611,546666007611,546666007611,3070,"STEP_SWAP_BUFFERS"
-3070,546666007611,8000,0,"STEP_SWAP_BUFFERS",546666015611,546666425829,546666425829,3070,"STEP_DRAW_AND_SWAP"
-3070,546666425829,8000,0,"STEP_DRAW_AND_SWAP",546666433829,546686287829,546686287829,3070,"End"
-3070,546686287829,3000,0,"End",546686290829,"[NULL]",546676000403,3074,"AsyncBegin"
-3074,546676000403,32746426,0,"AsyncBegin",546676000403,546677976403,546678120403,3074,"Begin"
-3074,546678120403,1000,0,"Begin",546678325403,546677976403,546678271403,3074,"STEP_SEND_INPUT_EVENT_UI"
-3074,546678271403,40000,0,"STEP_SEND_INPUT_EVENT_UI",546678325403,546678362611,546678365611,3074,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3074,546678365611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546678377611,546691500611,546691505611,3074,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3074,546691505611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546691548611,546693461611,546693461611,3074,"STEP_SWAP_BUFFERS"
-3074,546693461611,7000,0,"STEP_SWAP_BUFFERS",546693468611,546693912829,546693912829,3074,"STEP_DRAW_AND_SWAP"
-3074,546693912829,7000,0,"STEP_DRAW_AND_SWAP",546693919829,546708755829,546708755829,3074,"End"
-3074,546708755829,3000,0,"End",546708758829,"[NULL]",546701627403,3077,"AsyncBegin"
-3077,546701627403,29680426,0,"AsyncBegin",546701627403,546701412403,546701638403,3077,"Begin"
-3077,546701638403,1000,0,"Begin",546701829403,546701412403,546701662403,3077,"STEP_SEND_INPUT_EVENT_UI"
-3077,546701662403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546701829403,546701751611,546701754611,3077,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3077,546701754611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546701768611,546713886611,546713890611,3077,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3077,546713890611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546713932611,546715795611,546715795611,3077,"STEP_SWAP_BUFFERS"
-3077,546715795611,2000,0,"STEP_SWAP_BUFFERS",546715797611,546716289829,546716289829,3077,"STEP_DRAW_AND_SWAP"
-3077,546716289829,1000,0,"STEP_DRAW_AND_SWAP",546716290829,546731310829,546731310829,3077,"End"
-3077,546731310829,1000,0,"End",546731311829,"[NULL]",546718977403,3079,"AsyncBegin"
-3079,546718977403,34597426,0,"AsyncBegin",546718977403,546720104403,546720121403,3079,"Begin"
-3079,546720121403,2000,0,"Begin",546720221403,546720104403,546720162403,3079,"STEP_SEND_INPUT_EVENT_UI"
-3079,546720162403,55000,0,"STEP_SEND_INPUT_EVENT_UI",546720221403,546720297611,546720307611,3079,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3079,546720307611,15000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546720324611,546735889611,546735893611,3079,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3079,546735893611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546735932611,546736765611,546736765611,3079,"STEP_SWAP_BUFFERS"
-3079,546736765611,6000,0,"STEP_SWAP_BUFFERS",546736771611,546737248829,546737248829,3079,"STEP_DRAW_AND_SWAP"
-3079,546737248829,8000,0,"STEP_DRAW_AND_SWAP",546737256829,546753582829,546753582829,3079,"End"
-3079,546753582829,2000,0,"End",546753584829,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/scroll_flow_event.sql b/test/trace_processor/chrome/scroll_flow_event.sql
deleted file mode 100644
index 00dbba6..0000000
--- a/test/trace_processor/chrome/scroll_flow_event.sql
+++ /dev/null
@@ -1,29 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_flow_event.sql') AS suppress_query_output;
-
-SELECT
-  trace_id,
-  ts,
-  dur,
-  jank,
-  step,
-  ancestor_end,
-  maybe_next_ancestor_ts,
-  next_ts,
-  next_trace_id,
-  next_step
-FROM scroll_flow_event
-ORDER BY gesture_scroll_id, trace_id, ts;
diff --git a/test/trace_processor/chrome/scroll_flow_event_general_validation.out b/test/trace_processor/chrome/scroll_flow_event_general_validation.out
deleted file mode 100644
index 295637e..0000000
--- a/test/trace_processor/chrome/scroll_flow_event_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total_scroll_updates","total_flow_event_steps","total_janky_flow_event_steps","number_of_unique_steps"
-139,1112,72,8
diff --git a/test/trace_processor/chrome/scroll_flow_event_general_validation.sql b/test/trace_processor/chrome/scroll_flow_event_general_validation.sql
deleted file mode 100644
index f6ceab6..0000000
--- a/test/trace_processor/chrome/scroll_flow_event_general_validation.sql
+++ /dev/null
@@ -1,39 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_flow_event.sql') AS suppress_query_output;
-
-SELECT
-  -- Each trace_id (in our example trace not true in general) has 8 steps. There
-  -- are 139 scrolls. So we expect 1112 rows in total 72 of which are janky.
-  (
-    SELECT
-      COUNT(*)
-    FROM (
-      SELECT
-        trace_id,
-        COUNT(*)
-      FROM scroll_flow_event
-      GROUP BY trace_id
-    )
-  ) AS total_scroll_updates,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event
-  ) AS total_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event WHERE jank
-  ) AS total_janky_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM (SELECT step FROM scroll_flow_event GROUP BY step)
-  ) AS number_of_unique_steps;
diff --git a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out b/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out
deleted file mode 100644
index 610f04b..0000000
--- a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.out
+++ /dev/null
@@ -1,26 +0,0 @@
-
-"trace_id","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
-2721,"AsyncBegin","Begin",545007000403,545010006403,3006000
-2721,"Begin","STEP_SEND_INPUT_EVENT_UI",545010323403,545010006403,0
-2721,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",545010323403,545010685611,362208
-2721,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545010695611,545021699611,11004000
-2721,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",545021748611,545022454611,706000
-2721,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",545022459611,545034641829,12182218
-2721,"STEP_DRAW_AND_SWAP","End",545034646829,545044471829,9825000
-2721,"End","AsyncBegin",545044474829,"[NULL]","[NULL]"
-2725,"AsyncBegin","Begin",545024000403,545025279403,1279000
-2725,"Begin","STEP_SEND_INPUT_EVENT_UI",545025746403,545025279403,0
-2725,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",545025746403,545025698611,0
-2725,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545025713611,545033251611,7538000
-2725,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",545033344611,545034007611,663000
-2725,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",545034012611,545047703829,13691218
-2725,"STEP_DRAW_AND_SWAP","End",545047704829,545055892829,8188000
-2725,"End","AsyncBegin",545055893829,"[NULL]","[NULL]"
-2727,"AsyncBegin","Begin",545032000403,545033878403,1878000
-2727,"Begin","STEP_SEND_INPUT_EVENT_UI",545034128403,545033878403,0
-2727,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",545034128403,545034224611,96208
-2727,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545034237611,545044106611,9869000
-2727,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",545044160611,545046053611,1893000
-2727,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",545046061611,545047694829,1633218
-2727,"STEP_DRAW_AND_SWAP","End",545047701829,545055884829,8183000
-2727,"End","AsyncBegin",545055886829,"[NULL]","[NULL]"
diff --git a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.sql b/test/trace_processor/chrome/scroll_flow_event_queuing_delay.sql
deleted file mode 100644
index fdbb40c..0000000
--- a/test/trace_processor/chrome/scroll_flow_event_queuing_delay.sql
+++ /dev/null
@@ -1,30 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_flow_event_queuing_delay.sql')
-  AS suppress_query_output;
-
--- trace 2725 is janky and 2721 and 2727 surround it (both are not janky). We
--- just manually computed these values to ensure the queuing time is correct.
-SELECT
-  trace_id,
-  step,
-  next_step,
-  ancestor_end,
-  maybe_next_ancestor_ts,
-  queuing_time_ns
-FROM scroll_flow_event_queuing_delay
-WHERE trace_id = 2721 OR trace_id = 2725 OR trace_id = 2727
-ORDER BY trace_id, ts;
diff --git a/test/trace_processor/chrome/scroll_flow_event_queuing_delay_general_validation.sql b/test/trace_processor/chrome/scroll_flow_event_queuing_delay_general_validation.sql
deleted file mode 100644
index a8e78bf..0000000
--- a/test/trace_processor/chrome/scroll_flow_event_queuing_delay_general_validation.sql
+++ /dev/null
@@ -1,40 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_flow_event_queuing_delay.sql')
-    AS suppress_query_output;
-
-SELECT
-  -- Each trace_id (in our example trace not true in general) has 8 steps. There
-  -- are 139 scrolls. So we expect 1112 rows in total 72 of which are janky.
-  (
-    SELECT
-      COUNT(*)
-    FROM (
-      SELECT
-        trace_id,
-        COUNT(*)
-      FROM scroll_flow_event_queuing_delay
-      GROUP BY trace_id
-    )
-  ) AS total_scroll_updates,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event_queuing_delay
-  ) AS total_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event_queuing_delay WHERE jank
-  ) AS total_janky_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM (SELECT step FROM scroll_flow_event_queuing_delay GROUP BY step)
-  ) AS number_of_unique_steps;
diff --git a/test/trace_processor/chrome/scroll_jank.out b/test/trace_processor/chrome/scroll_jank.out
deleted file mode 100644
index fb1120f..0000000
--- a/test/trace_processor/chrome/scroll_jank.out
+++ /dev/null
@@ -1,141 +0,0 @@
-
-"gesture_scroll_id","trace_id","jank","ts","dur"
-2708,2709,0,544958000403,19009426
-2708,2711,0,544966000403,22609426
-2708,2715,0,544983000403,28089426
-2708,2717,0,544991000403,30714426
-2708,2719,0,544999000403,34740426
-2708,2721,0,545007000403,37462426
-2708,2725,1,545024000403,31889426
-2708,2727,0,545032000403,23876426
-2708,2729,0,545040000403,28316426
-2708,2733,0,545056000403,22620426
-2708,2735,0,545065000403,23642426
-2708,2739,0,545081000403,19016426
-2708,2741,0,545089000403,22491426
-2708,2743,0,545098000403,24940426
-2708,2747,0,545114000403,19365426
-2708,2749,0,545122000403,22629426
-2708,2753,0,545139000403,17669426
-2708,2755,0,545147000403,20941426
-2708,2757,0,545155000403,23321426
-2708,2761,0,545172000403,18585426
-2708,2763,0,545180000403,22430426
-2708,2765,0,545188000403,23545426
-2708,2769,0,545204000403,19115426
-2708,2771,0,545213000403,21107426
-2708,2773,0,545221000403,25065426
-2708,2777,0,545237000403,20064426
-2708,2779,0,545246000403,22190426
-2708,2783,0,545262000403,16635426
-2708,2785,0,545270000403,19926426
-2708,2787,0,545278000403,23003426
-2708,2791,0,545295000403,17169426
-2708,2793,0,545303000403,20626426
-2708,2795,0,545311000403,23560426
-2708,2799,0,545328000403,18191426
-2708,2801,0,545336000403,20911426
-2708,2803,0,545344000403,24228426
-2708,2807,0,545361000403,18189426
-2708,2809,0,545369000403,21379426
-2708,2811,0,545377000403,24913426
-2708,2815,0,545394000403,18671426
-2708,2817,0,545402000403,21928426
-2708,2821,0,545418000403,17254426
-2708,2823,0,545426000403,20407426
-2708,2825,0,545435000403,22633426
-2708,2827,0,545443000403,27179426
-2708,2831,0,545459000403,20575426
-2708,2833,0,545468000403,23489426
-2708,2837,0,545484000403,18277426
-2708,2839,0,545492000403,21649426
-2708,2841,0,545500000403,24734426
-2708,2845,0,545517000403,18824426
-2708,2847,0,545525000403,22343426
-2708,2849,0,545533000403,25222426
-2708,2853,0,545550000403,19151426
-2708,2855,0,545558000403,22660426
-2708,2859,0,545574000403,17603426
-2708,2861,0,545583000403,19608426
-2708,2863,0,545591000403,22822426
-2708,2867,0,545607000403,18005426
-2708,2869,0,545615000403,21063426
-2708,2871,0,545624000403,23894426
-2708,2875,0,545640000403,18611426
-2708,2877,0,545648000403,21759426
-2708,2879,0,545656000403,25004426
-2708,2881,0,545671000403,32742426
-2708,2884,0,545681794403,32652426
-2708,2885,0,545691182403,34488426
-2708,2886,0,545702355403,34887426
-2708,2887,0,545713526403,34615426
-2708,2888,0,545724697403,36799426
-2708,2889,0,545735867403,35326426
-2708,2890,0,545747040403,35047426
-2708,2891,0,545758211403,34990426
-2708,2892,0,545769381403,39529426
-2708,2893,0,545780550403,35967426
-2708,2894,1,545791721403,45468426
-2708,2895,1,545802892403,45651426
-2708,2897,0,545825234403,34662426
-2917,2918,0,546027000403,24672426
-2917,2920,0,546035000403,27274426
-2917,2922,0,546044000403,28587426
-2917,2924,1,546052000403,41821426
-2917,2926,1,546060000403,44914426
-2917,2930,0,546076000403,28902426
-2917,2932,0,546085000403,31881426
-2917,2934,0,546093000403,34989426
-2917,2938,1,546109000403,41953426
-2917,2940,0,546118000403,32872426
-2917,2942,0,546126000403,35348426
-2917,2946,0,546142000403,42106426
-2917,2948,1,546150000403,45005426
-2917,2950,0,546159000403,35994426
-2917,2954,0,546175000403,30970426
-2917,2956,1,546183000403,45256426
-2917,2960,1,546200000403,40097426
-2917,2962,0,546208000403,32086426
-2917,2964,0,546216000403,34686426
-2917,2968,0,546233000403,28852426
-2917,2970,0,546241000403,32494426
-2917,2972,0,546249000403,37304426
-2917,2976,0,546265000403,32101426
-2917,2978,0,546273000403,34156426
-2917,2982,0,546290000403,27915426
-2917,2984,0,546298000403,30723426
-2917,2986,0,546307000403,32918426
-2917,2990,0,546323000403,29800426
-2917,2992,0,546331000403,31314426
-2917,2994,0,546339000403,35092426
-2917,2998,0,546356000403,28702426
-2917,3000,0,546364000403,32457426
-2917,3002,0,546372000403,35043426
-2917,3006,0,546389000403,29285426
-2917,3008,0,546397000403,32831426
-2917,3010,0,546405000403,35630426
-2917,3014,0,546422000403,30119426
-2917,3016,0,546430000403,33185426
-2917,3020,0,546446000403,28386426
-2917,3022,0,546455000403,30102426
-2917,3024,0,546463000403,33512426
-2917,3028,0,546479000403,28455426
-2917,3030,0,546488000403,30791426
-2917,3032,0,546496000403,34105426
-2917,3036,0,546512000403,29329426
-2917,3038,0,546520000403,32321426
-2917,3040,0,546529000403,34457426
-2917,3044,0,546545000403,29668426
-2917,3046,0,546553000403,32830426
-2917,3048,0,546561000403,35849426
-2917,3052,0,546578000403,30365426
-2917,3054,0,546586000403,33666426
-2917,3056,0,546594000403,36913426
-2917,3060,0,546611000403,30855426
-2917,3062,0,546619000403,33897426
-2917,3064,0,546627000403,36941426
-2917,3068,0,546644000403,31194426
-2917,3070,0,546652000403,34276426
-2917,3074,0,546676000403,32746426
-2917,3077,0,546701627403,29680426
-2917,3079,0,546718977403,34597426
diff --git a/test/trace_processor/chrome/scroll_jank.sql b/test/trace_processor/chrome/scroll_jank.sql
deleted file mode 100644
index 2a502c1..0000000
--- a/test/trace_processor/chrome/scroll_jank.sql
+++ /dev/null
@@ -1,24 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank.sql') AS suppress_query_output;
-
-SELECT
-  gesture_scroll_id,
-  trace_id,
-  jank,
-  ts,
-  dur
-FROM scroll_jank;
diff --git a/test/trace_processor/chrome/scroll_jank_cause.out b/test/trace_processor/chrome/scroll_jank_cause.out
deleted file mode 100644
index 06ced33..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total","total_jank","sum_explained_and_unexplained","error_rows"
-139,9,9,0
diff --git a/test/trace_processor/chrome/scroll_jank_cause.sql b/test/trace_processor/chrome/scroll_jank_cause.sql
deleted file mode 100644
index 658ec22..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause.sql
+++ /dev/null
@@ -1,32 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank_cause.sql') AS suppress_query_output;
-
-SELECT
-  COUNT(*) AS total,
-  SUM(jank) as total_jank,
-  SUM(explained_jank + unexplained_jank) AS sum_explained_and_unexplained,
-  SUM(
-    CASE WHEN explained_jank THEN
-      unexplained_jank
-    ELSE
-      CASE WHEN jank AND NOT unexplained_jank THEN
-        1
-      ELSE
-        0
-      END
-    END
-  ) AS error_rows
-FROM scroll_jank_cause;
diff --git a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.out b/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.out
deleted file mode 100644
index eedf5a2..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.out
+++ /dev/null
@@ -1,21 +0,0 @@
-
-"process_name","thread_name","trace_id","jank","dur_overlapping_ns","metric_name"
-"Browser","CrProcessMain",2918,0,55000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Browser","CrProcessMain",2918,0,433000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.RenderWidgetHostImpl::ForwardTouchEvent-PassthroughTouchEventQueue::QueueEvent-InputRouterImpl::FilterAndSendWebInputEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2918,0,66000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-MainThreadEventQueue::HandleEvent"
-"Renderer","Compositor",2918,0,116000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-LatencyInfo.Flow-InputHandlerProxy::HandleGestureScrollBegin-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor"
-"Renderer","Compositor",2918,0,29000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-MainThreadEventQueue::HandleEvent"
-"Renderer","Compositor",2918,0,7000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2918,0,25000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-DeltaUnits"
-"Renderer","Compositor",2918,0,6000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.LatencyInfo.Flow"
-"Browser","CrProcessMain",2926,1,52000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.InputRouterImpl::GestureEventHandled-GestureEventQueue::ProcessGestureAck"
-"Browser","CrProcessMain",2926,1,17000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Renderer","Compositor",2926,1,1208,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2926,1,38000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2926,1,21000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-LatencyInfo.Flow-EventWithCallback::CoalesceWith"
-"Renderer","Compositor",2926,1,6000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2926,1,30000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-DeltaUnits"
-"Renderer","Compositor",2926,1,14000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,5000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,8000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
diff --git a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.sql b/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.sql
deleted file mode 100644
index 4941383..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay.sql
+++ /dev/null
@@ -1,27 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank_cause_queuing_delay.sql')
-    AS suppress_query_output;
-
-SELECT
-  process_name,
-  thread_name,
-  trace_id,
-  jank,
-  dur_overlapping_ns,
-  metric_name
-FROM scroll_jank_cause_queuing_delay
-WHERE trace_id = 2918 OR trace_id = 2926
-ORDER BY trace_id ASC, ts ASC
diff --git a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.out b/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.out
deleted file mode 100644
index 48fe6de..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total","janky_latency_info_non_jank_avg_dur","non_janky_latency_info_non_jank_avg_dur"
-139,6387.096774,6387.096774
diff --git a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.sql b/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.sql
deleted file mode 100644
index 9441841..0000000
--- a/test/trace_processor/chrome/scroll_jank_cause_queuing_delay_general_validation.sql
+++ /dev/null
@@ -1,41 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the 'License');
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank_cause_queuing_delay.sql')
-    AS suppress_query_output;
-
-SELECT
-  COUNT(*) as total,
-  (
-    SELECT
-      DISTINCT(avg_no_jank_dur_overlapping_ns)
-    FROM scroll_jank_cause_queuing_delay
-    WHERE
-      location = "LatencyInfo.Flow" AND
-      jank
-  ) AS janky_latency_info_non_jank_avg_dur,
-  (
-    SELECT
-      DISTINCT(avg_no_jank_dur_overlapping_ns)
-    FROM scroll_jank_cause_queuing_delay
-    WHERE
-      location = "LatencyInfo.Flow" AND
-      NOT jank
-  ) AS non_janky_latency_info_non_jank_avg_dur
-FROM (
-  SELECT
-    trace_id
-  FROM scroll_jank_cause_queuing_delay
-  GROUP BY trace_id
-);
diff --git a/test/trace_processor/chrome/scroll_jank_general_validation.out b/test/trace_processor/chrome/scroll_jank_general_validation.out
deleted file mode 100644
index d4323b2..0000000
--- a/test/trace_processor/chrome/scroll_jank_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total","scroll_dur","non_coalesced_updates","non_coalesced_dur","non_coalesced_janky_updates","non_coalesced_janky_dur","janky_percentage","avg_vsync_interval"
-2,1628470852,139,3974685214,9,382057834,9,16000000.000000
diff --git a/test/trace_processor/chrome/scroll_jank_general_validation.sql b/test/trace_processor/chrome/scroll_jank_general_validation.sql
deleted file mode 100644
index 4143875..0000000
--- a/test/trace_processor/chrome/scroll_jank_general_validation.sql
+++ /dev/null
@@ -1,82 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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('chrome/scroll_jank.sql') AS suppress_query_output;
-
-SELECT (
-  -- There are only two valid scrolls (one additional scroll is missing a begin
-  -- and the other is missing an end).
-  SELECT COUNT(*) FROM joined_scroll_begin_and_end
-) AS total,
-(
-  -- Of the two valid scrolls
-  -- gesture_scroll_id: 2708
-  --     starts at: 544958000403
-  --     ends at:   545859896829
-  --     adds dur:     901896426 nanoseconds of scrolling.
-  --
-  -- gesture_scroll_id: 2917
-  --     starts at: 546027000403
-  --     ends at:   546753574829
-  --     adds dur:     726574426 nanoseconds of scrolling.
-  -- This means we should have scroll_dur == 1628470852
-  SELECT SUM(scroll_dur) FROM (
-    SELECT
-      gesture_scroll_id, max(maybe_scroll_end) - begin_ts AS scroll_dur
-    FROM scroll_jank
-    GROUP BY gesture_scroll_id
-  )
-) AS scroll_dur,
-(
-  -- This can be verified by the following simple query to ensure the end result
-  -- in scroll_jank table is sane. The result should be 139.
-  -- SELECT
-  --   COUNT(*)
-  -- FROM slice
-  -- WHERE
-  --    name = "InputLatency::GestureScrollUpdate" AND
-  --    NOT EXTRACT_ARG(arg_set_id, 'chrome_latency_info.is_coalesced') AND
-  --    (
-  --    EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') = 2708
-  --    OR
-  --    EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') = 2917
-  --    )
-  SELECT COUNT(*) FROM scroll_jank
-) AS non_coalesced_updates,
-(
-  -- This can be verified by the following simple query as above but replace
-  -- COUNT(*) with SUM(dur). The result should be 3974685214.
-  SELECT SUM(dur) FROM scroll_jank
-) AS non_coalesced_dur,
-(
-  -- This was found by running the previous metric before porting on the
-  -- example trace.
-  SELECT COUNT(*) FROM scroll_jank WHERE jank
-) AS non_coalesced_janky_updates,
-(
-  -- This was found by running the previous metric before porting on the
-  -- example trace, and also manually summing them.
-  SELECT SUM(dur) FROM scroll_jank WHERE jank
-) AS non_coalesced_janky_dur,
-(
-  -- This is floor((non_coalesced_janky_dur/non_coalesced_dur) * 100) in SQLite.
-  SELECT
-    CAST((CAST((SELECT SUM(dur) FROM scroll_jank WHERE jank) AS FLOAT) /
-    CAST((SELECT SUM(dur) FROM scroll_jank) AS FLOAT)) * 100 AS INT)
-) AS janky_percentage,
-(
-  SELECT avg_vsync_interval FROM joined_scroll_begin_and_end
-) as avg_vsync_interval;
-
diff --git a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.out b/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.out
deleted file mode 100644
index 13709b3..0000000
--- a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"trace_id","jank","dur_overlapping_ns","metric_name"
-34577,0,6000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.task-subtask"
-34578,1,29000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.task-subtask"
-34579,0,29000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.task-subtask(foo)"
diff --git a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.py b/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.py
deleted file mode 100644
index 72dfa7d..0000000
--- a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.py
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 is intended to test the handling of simple_watcher style mojo events,
-# which are often missing trace events below them and so are all aggregated
-# together despite them coming into different mojo interfaces.
-
-from os import sys
-
-import synth_common
-
-from synth_common import ms_to_ns
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-
-trace.add_process_track_descriptor(process_track1, pid=0)
-
-process_pid1 = 2345
-
-thread_track1 = 1235
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-
-seq1 = 9876
-
-thread1_counter = 60
-
-scroll_begin_trace_id = 34576
-trace_id1 = scroll_begin_trace_id + 1
-trace_id2 = trace_id1 + 1
-trace_id3 = trace_id2 + 1
-scroll_end_trace_id = trace_id3 + 1
-
-gesture_scroll_id = 87654
-
-flow_id1 = 45678
-flow_id2 = 45679
-flow_id3 = 45680
-
-trace.add_input_latency_event_slice(
-    "GestureScrollBegin",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    track=scroll_begin_trace_id,
-    trace_id=scroll_begin_trace_id,
-    gesture_scroll_id=gesture_scroll_id)
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-# Scroll update 1 - not janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(10),
-    track=trace_id1,
-    trace_id=trace_id1,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    flow_ids=[flow_id1])
-
-# The slices below will block this "not janky" scroll update 1.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(2), dur=ms_to_ns(6), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(3), dur=ms_to_ns(4), trusted_sequence_id=seq1)
-# This ends the blocking slices of "not janky" scroll update 1.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(11),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    terminating_flow_ids=[flow_id1])
-
-# Scroll update 2 - janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(33),
-    track=trace_id2,
-    trace_id=trace_id2,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-# This is a special event that adds a track event that stretches the entire
-# trace. This should not impact our metric (our metric should ignore it).
-# See b/184134310 for details of why we are testing this.
-trace.add_track_event_slice_begin(
-    "ThreadController active", ts=ms_to_ns(16), trusted_sequence_id=seq1)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    flow_ids=[flow_id2])
-
-# The slices below will block this "janky" scroll update 2.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(18), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(19), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-# This ends the blocking slices of "janky" scroll update 2.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(50),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    terminating_flow_ids=[flow_id2])
-
-# Scroll update 3 - janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(33),
-    track=trace_id3,
-    trace_id=trace_id3,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    flow_ids=[flow_id3])
-
-# The slices below will block this "janky" scroll update 3.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(57), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-packet = trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(58), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-
-packet.track_event.chrome_mojo_event_info.watcher_notify_interface_tag = "foo"
-# This ends the blocking slices of "janky" scroll update 3.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(89),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    terminating_flow_ids=[flow_id3])
-
-trace.add_input_latency_event_slice(
-    "GestureScrollEnd",
-    ts=ms_to_ns(90),
-    dur=ms_to_ns(2),
-    track=scroll_end_trace_id,
-    trace_id=scroll_end_trace_id,
-    gesture_scroll_id=gesture_scroll_id)
-
-# This ends the "ThreadController active" event.
-trace.add_track_event_slice_end(ts=ms_to_ns(94), trusted_sequence_id=seq1)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.sql b/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.sql
deleted file mode 100644
index 3b090e6..0000000
--- a/test/trace_processor/chrome/scroll_jank_mojo_simple_watcher.sql
+++ /dev/null
@@ -1,24 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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('chrome/scroll_jank_cause_queuing_delay.sql')
-    AS suppress_query_output;
-
-SELECT
-  trace_id,
-  jank,
-  dur_overlapping_ns,
-  metric_name
-FROM scroll_jank_cause_queuing_delay
-ORDER BY trace_id ASC, ts ASC;
diff --git a/test/trace_processor/graphics/clock_sync.out b/test/trace_processor/clock_sync.out
similarity index 100%
rename from test/trace_processor/graphics/clock_sync.out
rename to test/trace_processor/clock_sync.out
diff --git a/test/trace_processor/clock_sync.py b/test/trace_processor/clock_sync.py
new file mode 100644
index 0000000..e097024
--- /dev/null
+++ b/test/trace_processor/clock_sync.py
@@ -0,0 +1,92 @@
+#!/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=14, 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)
+
+# Set default clock for sequence 2.
+defaults_packet = trace.add_packet()
+defaults_packet.trusted_packet_sequence_id = 2
+defaults_packet.trace_packet_defaults.timestamp_clock_id = SEQ_CLOCK1
+
+# This counter should be translated @ BOOTTIME : 2000 + 10
+trace.add_gpu_counter(ts=10, seq_id=2, counter_id=42, value=12)
+
+# Manually specified clock_id overrides the default clock.
+trace.add_gpu_counter(
+    ts=2013, clock_id=CLOCK_BOOTTIME, seq_id=2, counter_id=42, value=13)
+
+# Other sequence's default clock isn't changed, so this should be in BOOTTIME.
+trace.add_gpu_counter(ts=3010, counter_id=42, value=15, seq_id=3)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/clock_sync.sql b/test/trace_processor/clock_sync.sql
similarity index 100%
rename from test/trace_processor/graphics/clock_sync.sql
rename to test/trace_processor/clock_sync.sql
diff --git a/test/trace_processor/common/synth_1.py b/test/trace_processor/common/synth_1.py
deleted file mode 100644
index 359e2db..0000000
--- a/test/trace_processor/common/synth_1.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, "init")
-trace.add_process(2, 1, "two_thread_process")
-trace.add_process(4, 1, "single_thread_process")
-trace.add_thread(3, 2, "two_thread_process")
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_sched(ts=1, prev_pid=1, next_pid=3)
-trace.add_cpufreq(ts=50, freq=50, cpu=0)
-trace.add_sched(ts=100, prev_pid=3, next_pid=2)
-trace.add_sched(ts=115, prev_pid=2, next_pid=3)
-
-trace.add_ftrace_packet(cpu=1)
-trace.add_sched(ts=50, prev_pid=4, next_pid=1)
-trace.add_sched(ts=120, prev_pid=1, next_pid=2)
-trace.add_sched(ts=170, prev_pid=2, next_pid=0)
-trace.add_sched(ts=250, prev_pid=0, next_pid=2)
-trace.add_sched(ts=390, prev_pid=2, next_pid=4)
-trace.add_cpufreq(ts=400, freq=100, cpu=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/common/to_systrace.sql b/test/trace_processor/common/to_systrace.sql
deleted file mode 100644
index b2b6ed0..0000000
--- a/test/trace_processor/common/to_systrace.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-select to_ftrace(id) as line
-from raw
\ No newline at end of file
diff --git a/test/trace_processor/smoke/compressed_smoke.out b/test/trace_processor/compressed_smoke.out
similarity index 100%
rename from test/trace_processor/smoke/compressed_smoke.out
rename to test/trace_processor/compressed_smoke.out
diff --git a/test/trace_processor/config_metadata.out b/test/trace_processor/config_metadata.out
new file mode 100644
index 0000000..edcba50
--- /dev/null
+++ b/test/trace_processor/config_metadata.out
@@ -0,0 +1,3 @@
+"name","str_value"
+"android_build_fingerprint","the fingerprint"
+"trace_uuid","123e4567-e89b-12d3-a456-426655443322"
diff --git a/test/trace_processor/parsing/config_metadata.textproto b/test/trace_processor/config_metadata.textproto
similarity index 100%
rename from test/trace_processor/parsing/config_metadata.textproto
rename to test/trace_processor/config_metadata.textproto
diff --git a/test/trace_processor/tables/counter_dur.sql b/test/trace_processor/counter_dur.sql
similarity index 100%
rename from test/trace_processor/tables/counter_dur.sql
rename to test/trace_processor/counter_dur.sql
diff --git a/test/trace_processor/tables/counter_dur_example_android_trace_30s.out b/test/trace_processor/counter_dur_example_android_trace_30s.out
similarity index 100%
rename from test/trace_processor/tables/counter_dur_example_android_trace_30s.out
rename to test/trace_processor/counter_dur_example_android_trace_30s.out
diff --git a/test/trace_processor/counters_group_by_freq.py b/test/trace_processor/counters_group_by_freq.py
new file mode 100644
index 0000000..e39b922
--- /dev/null
+++ b/test/trace_processor/counters_group_by_freq.py
@@ -0,0 +1,27 @@
+#!/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_ftrace_packet(cpu=0)
+trace.add_cpufreq(ts=1000, freq=3000, cpu=1)
+trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
+trace.add_cpufreq(ts=1003, freq=3000, cpu=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/tables/counters_group_by_freq.sql b/test/trace_processor/counters_group_by_freq.sql
similarity index 100%
rename from test/trace_processor/tables/counters_group_by_freq.sql
rename to test/trace_processor/counters_group_by_freq.sql
diff --git a/test/trace_processor/tables/counters_group_by_freq_counters_group_by_freq.out b/test/trace_processor/counters_group_by_freq_counters_group_by_freq.out
similarity index 100%
rename from test/trace_processor/tables/counters_group_by_freq_counters_group_by_freq.out
rename to test/trace_processor/counters_group_by_freq_counters_group_by_freq.out
diff --git a/test/trace_processor/counters_where_cpu.py b/test/trace_processor/counters_where_cpu.py
new file mode 100644
index 0000000..0f2b1f5
--- /dev/null
+++ b/test/trace_processor/counters_where_cpu.py
@@ -0,0 +1,27 @@
+#!/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_ftrace_packet(cpu=0)
+trace.add_cpufreq(ts=1000, freq=3000, cpu=1)
+trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
+trace.add_cpufreq(ts=1002, freq=5000, cpu=2)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/tables/counters_where_cpu.sql b/test/trace_processor/counters_where_cpu.sql
similarity index 100%
rename from test/trace_processor/tables/counters_where_cpu.sql
rename to test/trace_processor/counters_where_cpu.sql
diff --git a/test/trace_processor/tables/counters_where_cpu_counters_where_cpu.out b/test/trace_processor/counters_where_cpu_counters_where_cpu.out
similarity index 100%
rename from test/trace_processor/tables/counters_where_cpu_counters_where_cpu.out
rename to test/trace_processor/counters_where_cpu_counters_where_cpu.out
diff --git a/test/trace_processor/parsing/cpu.out b/test/trace_processor/cpu.out
similarity index 100%
rename from test/trace_processor/parsing/cpu.out
rename to test/trace_processor/cpu.out
diff --git a/test/trace_processor/parsing/cpu.sql b/test/trace_processor/cpu.sql
similarity index 100%
rename from test/trace_processor/parsing/cpu.sql
rename to test/trace_processor/cpu.sql
diff --git a/test/trace_processor/parsing/cpu_counters_b120487929.out b/test/trace_processor/cpu_counters_b120487929.out
similarity index 100%
rename from test/trace_processor/parsing/cpu_counters_b120487929.out
rename to test/trace_processor/cpu_counters_b120487929.out
diff --git a/test/trace_processor/parsing/cpu_freq.out b/test/trace_processor/cpu_freq.out
similarity index 100%
rename from test/trace_processor/parsing/cpu_freq.out
rename to test/trace_processor/cpu_freq.out
diff --git a/test/trace_processor/parsing/cpu_freq.sql b/test/trace_processor/cpu_freq.sql
similarity index 100%
rename from test/trace_processor/parsing/cpu_freq.sql
rename to test/trace_processor/cpu_freq.sql
diff --git a/test/trace_processor/parsing/cpu_info.textproto b/test/trace_processor/cpu_info.textproto
similarity index 100%
rename from test/trace_processor/parsing/cpu_info.textproto
rename to test/trace_processor/cpu_info.textproto
diff --git a/test/trace_processor/dynamic/ancestor_slice.out b/test/trace_processor/dynamic/ancestor_slice.out
deleted file mode 100644
index fb01164..0000000
--- a/test/trace_processor/dynamic/ancestor_slice.out
+++ /dev/null
@@ -1,15 +0,0 @@
-"currentSliceName","ancestorSliceName"
-"event1_on_async_no_relationships","[NULL]"
-"event1_on_t1_no_relationships","[NULL]"
-"event1_on_t2_no_relationships","[NULL]"
-"event2_depth_0_on_t1","[NULL]"
-"event2_on_async_depth_0","[NULL]"
-"event2_depth_1_on_t1","event2_depth_0_on_t1"
-"event2_on_async_depth_1","event2_on_async_depth_0"
-"event2_depth_0_on_t2","[NULL]"
-"event2_first_depth_1_on_t2","event2_depth_0_on_t2"
-"event2_first_depth_2_on_t2","event2_depth_0_on_t2"
-"event2_first_depth_2_on_t2","event2_first_depth_1_on_t2"
-"event2_second_depth_1_on_t2","event2_depth_0_on_t2"
-"event2_second_depth_2_on_t2","event2_depth_0_on_t2"
-"event2_second_depth_2_on_t2","event2_second_depth_1_on_t2"
diff --git a/test/trace_processor/dynamic/ancestor_slice.sql b/test/trace_processor/dynamic/ancestor_slice.sql
deleted file mode 100644
index 44ff972..0000000
--- a/test/trace_processor/dynamic/ancestor_slice.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-SELECT slice.name AS currentSliceName, ancestor.name AS ancestorSliceName
-FROM slice LEFT JOIN ancestor_slice(slice.id) AS ancestor
-ORDER BY slice.ts ASC, ancestor.ts ASC, slice.name ASC, ancestor.name ASC;
diff --git a/test/trace_processor/dynamic/annotated_callstack.sql b/test/trace_processor/dynamic/annotated_callstack.sql
deleted file mode 100644
index a23f3cc..0000000
--- a/test/trace_processor/dynamic/annotated_callstack.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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 eac.id, eac.depth, eac.frame_id, eac.annotation,
-       spf.name
-from experimental_annotated_callstack eac
-join perf_sample ps
-  on (eac.start_id == ps.callsite_id)
-join stack_profile_frame spf
-  on (eac.frame_id == spf.id)
-order by eac.start_id asc, eac.depth asc;
-
diff --git a/test/trace_processor/dynamic/connected_flow.out b/test/trace_processor/dynamic/connected_flow.out
deleted file mode 100644
index f647837..0000000
--- a/test/trace_processor/dynamic/connected_flow.out
+++ /dev/null
@@ -1,62 +0,0 @@
-"type","name","start_name","end_name"
-"directly_connected","Flow0_Slice0","Flow0_Slice0","Flow0_Slice1"
-"directly_connected","Flow0_Slice1","Flow0_Slice0","Flow0_Slice1"
-"directly_connected","Flow1_Slice0","Flow1_Slice0","Flow1_Slice1a"
-"directly_connected","Flow1_Slice0","Flow1_Slice0","Flow1_Slice1b"
-"directly_connected","Flow1_Slice1a","Flow1_Slice0","Flow1_Slice1a"
-"directly_connected","Flow1_Slice1b","Flow1_Slice0","Flow1_Slice1b"
-"directly_connected","Flow2_Slice0","Flow2_Slice0","Flow2_Slice1"
-"directly_connected","Flow2_Slice0","Flow2_Slice1","Flow2_Slice2"
-"directly_connected","Flow2_Slice0","Flow2_Slice2","Flow2_Slice3b"
-"directly_connected","Flow2_Slice1","Flow2_Slice0","Flow2_Slice1"
-"directly_connected","Flow2_Slice1","Flow2_Slice1","Flow2_Slice2"
-"directly_connected","Flow2_Slice1","Flow2_Slice2","Flow2_Slice3b"
-"directly_connected","Flow2_Slice2","Flow2_Slice0","Flow2_Slice1"
-"directly_connected","Flow2_Slice2","Flow2_Slice1","Flow2_Slice2"
-"directly_connected","Flow2_Slice2","Flow2_Slice2","Flow2_Slice3b"
-"directly_connected","Flow2_Slice2a","Flow2_Slice2a","Flow2_Slice3a"
-"directly_connected","Flow2_Slice3a","Flow2_Slice2a","Flow2_Slice3a"
-"directly_connected","Flow2_Slice3b","Flow2_Slice0","Flow2_Slice1"
-"directly_connected","Flow2_Slice3b","Flow2_Slice1","Flow2_Slice2"
-"directly_connected","Flow2_Slice3b","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow0_Slice0","Flow0_Slice0","Flow0_Slice1"
-"following","Flow1_Slice0","Flow1_Slice0","Flow1_Slice1a"
-"following","Flow1_Slice0","Flow1_Slice0","Flow1_Slice1b"
-"following","Flow1_Slice0","Flow2_Slice0","Flow2_Slice1"
-"following","Flow1_Slice0","Flow2_Slice1","Flow2_Slice2"
-"following","Flow1_Slice0","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow1_Slice0","Flow2_Slice2a","Flow2_Slice3a"
-"following","Flow1_Slice1a","Flow2_Slice0","Flow2_Slice1"
-"following","Flow1_Slice1a","Flow2_Slice1","Flow2_Slice2"
-"following","Flow1_Slice1a","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow1_Slice1a","Flow2_Slice2a","Flow2_Slice3a"
-"following","Flow2_Slice0","Flow2_Slice0","Flow2_Slice1"
-"following","Flow2_Slice0","Flow2_Slice1","Flow2_Slice2"
-"following","Flow2_Slice0","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow2_Slice0","Flow2_Slice2a","Flow2_Slice3a"
-"following","Flow2_Slice1","Flow2_Slice1","Flow2_Slice2"
-"following","Flow2_Slice1","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow2_Slice1","Flow2_Slice2a","Flow2_Slice3a"
-"following","Flow2_Slice2","Flow2_Slice2","Flow2_Slice3b"
-"following","Flow2_Slice2","Flow2_Slice2a","Flow2_Slice3a"
-"following","Flow2_Slice2a","Flow2_Slice2a","Flow2_Slice3a"
-"preceding","Flow0_Slice1","Flow0_Slice0","Flow0_Slice1"
-"preceding","Flow1_Slice1a","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow1_Slice1b","Flow1_Slice0","Flow1_Slice1b"
-"preceding","Flow2_Slice0","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice1","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice1","Flow2_Slice0","Flow2_Slice1"
-"preceding","Flow2_Slice2","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice2","Flow2_Slice0","Flow2_Slice1"
-"preceding","Flow2_Slice2","Flow2_Slice1","Flow2_Slice2"
-"preceding","Flow2_Slice2a","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice2a","Flow2_Slice0","Flow2_Slice1"
-"preceding","Flow2_Slice2a","Flow2_Slice1","Flow2_Slice2"
-"preceding","Flow2_Slice3a","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice3a","Flow2_Slice0","Flow2_Slice1"
-"preceding","Flow2_Slice3a","Flow2_Slice1","Flow2_Slice2"
-"preceding","Flow2_Slice3a","Flow2_Slice2a","Flow2_Slice3a"
-"preceding","Flow2_Slice3b","Flow1_Slice0","Flow1_Slice1a"
-"preceding","Flow2_Slice3b","Flow2_Slice0","Flow2_Slice1"
-"preceding","Flow2_Slice3b","Flow2_Slice1","Flow2_Slice2"
-"preceding","Flow2_Slice3b","Flow2_Slice2","Flow2_Slice3b"
diff --git a/test/trace_processor/dynamic/connected_flow.sql b/test/trace_processor/dynamic/connected_flow.sql
deleted file mode 100644
index 96f079f..0000000
--- a/test/trace_processor/dynamic/connected_flow.sql
+++ /dev/null
@@ -1,30 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 "directly_connected" as type, s.name, s1.name as start_name, s2.name as end_name  FROM slice s
-JOIN DIRECTLY_CONNECTED_FLOW(s.id) c
-JOIN slice s1 ON s1.id = c.slice_out
-JOIN slice s2 ON s2.id = c.slice_in
-UNION
-SELECT "following" as type, s.name, s1.name as start_name, s2.name as end_name  FROM slice s
-JOIN FOLLOWING_FLOW(s.id) c
-JOIN slice s1 ON s1.id = c.slice_out
-JOIN slice s2 ON s2.id = c.slice_in
-UNION
-SELECT "preceding" as type, s.name, s1.name as start_name, s2.name as end_name  FROM slice s
-JOIN PRECEDING_FLOW(s.id) c
-JOIN slice s1 ON s1.id = c.slice_out
-JOIN slice s2 ON s2.id = c.slice_in
-ORDER BY type, s.name, s1.name, s2.name ASC
diff --git a/test/trace_processor/dynamic/connected_flow_data.json b/test/trace_processor/dynamic/connected_flow_data.json
deleted file mode 100644
index 6068089..0000000
--- a/test/trace_processor/dynamic/connected_flow_data.json
+++ /dev/null
@@ -1,141 +0,0 @@
-{
-    "traceEvents": [
-      {"args":{"name":"MainProcess"},"cat":"__metadata","name":"process_name","ph":"M","pid":100,"tid":0,"ts":0},
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15903,
-        "ts": 420,
-        "ph": "X",
-        "name": "Flow0_Slice0",
-        "args":{},
-        "dur": 150,
-        "bind_id": "0x401",
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15895,
-        "ts": 720,
-        "ph": "X",
-        "name": "Flow0_Slice1",
-        "args":{},
-        "dur": 200,
-        "bind_id": "0x401",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15904,
-        "ts": 400,
-        "ph": "X",
-        "name": "Flow1_Slice0",
-        "args":{},
-        "dur": 600,
-        "bind_id": "0x403",
-        "flow_out": true,
-        "flow_in": false
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15903,
-        "ts": 1300,
-        "ph": "X",
-        "name": "Flow1_Slice1a",
-        "args":{},
-        "dur": 600,
-        "bind_id": "0x403",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15794,
-        "ts": 1100,
-        "ph": "X",
-        "name": "Flow1_Slice1b",
-        "args":{},
-        "dur": 900,
-        "bind_id": "0x403",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15903,
-        "ts": 1351,
-        "ph": "X",
-        "name": "Flow2_Slice0",
-        "args": {},
-        "dur": 500,
-        "bind_id": "0x402",
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15903,
-        "ts": 2002,
-        "ph": "X",
-        "name": "Flow2_Slice1",
-        "args":{},
-        "dur": 350,
-        "bind_id": "0x402",
-        "flow_out": true,
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15794,
-        "ts": 2400,
-        "ph": "X",
-        "name": "Flow2_Slice2",
-        "args": {},
-        "dur": 300,
-        "bind_id": "0x402",
-        "flow_in": true,
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15794,
-        "ts": 2450,
-        "ph": "X",
-        "name": "Flow2_Slice2a",
-        "args": {},
-        "dur": 200,
-        "bind_id": "0x404",
-        "flow_in": false,
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15904,
-        "ts": 3031,
-        "ph": "X",
-        "name": "Flow2_Slice3a",
-        "args": {},
-        "dur": 400,
-        "bind_id": "0x404",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 100,
-        "tid": 15895,
-        "ts": 3333,
-        "ph": "X",
-        "name": "Flow2_Slice3b",
-        "args": {},
-        "dur": 400,
-        "bind_id": "0x402",
-        "flow_in": true
-      }
-    ]
-  }
\ No newline at end of file
diff --git a/test/trace_processor/dynamic/descendant_slice.out b/test/trace_processor/dynamic/descendant_slice.out
deleted file mode 100644
index b5ffa18..0000000
--- a/test/trace_processor/dynamic/descendant_slice.out
+++ /dev/null
@@ -1,16 +0,0 @@
-"currentSliceName","descendantSliceName"
-"event1_on_async_no_relationships","[NULL]"
-"event1_on_t1_no_relationships","[NULL]"
-"event1_on_t2_no_relationships","[NULL]"
-"event2_depth_0_on_t1","event2_depth_1_on_t1"
-"event2_on_async_depth_0","event2_on_async_depth_1"
-"event2_depth_1_on_t1","[NULL]"
-"event2_on_async_depth_1","[NULL]"
-"event2_depth_0_on_t2","event2_first_depth_1_on_t2"
-"event2_depth_0_on_t2","event2_first_depth_2_on_t2"
-"event2_depth_0_on_t2","event2_second_depth_1_on_t2"
-"event2_depth_0_on_t2","event2_second_depth_2_on_t2"
-"event2_first_depth_1_on_t2","event2_first_depth_2_on_t2"
-"event2_first_depth_2_on_t2","[NULL]"
-"event2_second_depth_1_on_t2","event2_second_depth_2_on_t2"
-"event2_second_depth_2_on_t2","[NULL]"
diff --git a/test/trace_processor/dynamic/descendant_slice.sql b/test/trace_processor/dynamic/descendant_slice.sql
deleted file mode 100644
index 918dd38..0000000
--- a/test/trace_processor/dynamic/descendant_slice.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-SELECT slice.name AS currentSliceName, descendant.name AS descendantSliceName
-FROM slice LEFT JOIN descendant_slice(slice.id) AS descendant
-ORDER BY slice.ts ASC, descendant.ts ASC, slice.name ASC, descendant.name ASC;
diff --git a/test/trace_processor/dynamic/index b/test/trace_processor/dynamic/index
deleted file mode 100644
index 3c5953b..0000000
--- a/test/trace_processor/dynamic/index
+++ /dev/null
@@ -1,13 +0,0 @@
-# Tests for custom dynamic tables.
-
-# Ancestor slice table.
-relationship_tables.textproto ancestor_slice.sql ancestor_slice.out
-
-# Descendant slice table.
-relationship_tables.textproto descendant_slice.sql descendant_slice.out
-
-# Connected/Following/Perceeding flow table.
-connected_flow_data.json connected_flow.sql connected_flow.out
-
-# Annotated callstacks.
-../../data/perf_sample_sc.pb annotated_callstack.sql perf_sample_sc_annotated_callstack.out
diff --git a/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out b/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out
deleted file mode 100644
index 633c97e..0000000
--- a/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out
+++ /dev/null
@@ -1,96 +0,0 @@
-"id","depth","frame_id","annotation","name"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
-3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
-4,4,4,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
-5,5,5,"[NULL]","_ZN7android10PoolThread10threadLoopEv"
-6,6,6,"[NULL]","_ZN7android14IPCThreadState14joinThreadPoolEb"
-7,7,7,"[NULL]","_ZN7android14IPCThreadState14executeCommandEi"
-8,8,8,"[NULL]","_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j"
-9,9,9,"[NULL]","_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j"
-10,10,10,"[NULL]","_ZN7_JNIEnv17CallBooleanMethodEP8_jobjectP10_jmethodIDz"
-11,11,11,"[NULL]","_ZN3art3JNIILb0EE18CallBooleanMethodVEP7_JNIEnvP8_jobjectP10_jmethodIDSt9__va_list"
-12,12,12,"[NULL]","_ZN3art35InvokeVirtualOrInterfaceWithVarArgsIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_St9__va_list"
-13,13,13,"[NULL]","art_quick_invoke_stub"
-14,14,14,"aot","android.os.Binder.execTransact"
-15,15,15,"aot","android.os.Binder.execTransactInternal"
-16,16,16,"aot","com.android.server.wm.Session.onTransact"
-17,17,17,"jit","android.view.IWindowSession$Stub.onTransact"
-18,18,18,"aot","com.android.server.wm.Session.sendWallpaperCommand"
-19,19,19,"aot","com.android.server.ThreadPriorityBooster.boost"
-20,20,20,"common-frame","art_jni_trampoline"
-21,21,21,"[NULL]","_Z36android_os_Process_getThreadPriorityP7_JNIEnvP8_jobjecti"
-22,22,22,"[NULL]","getpriority"
-23,23,23,"[NULL]","__getpriority"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
-3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
-24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
-25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-28,8,28,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-29,9,29,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
-30,10,30,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-31,11,31,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-32,12,32,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
-33,13,33,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher29reportTouchEventForStatisticsERKNS0_11MotionEntryE"
-34,14,34,"[NULL]","_ZN7android17LatencyStatistics12shouldReportEv"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
-3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
-4,4,4,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
-35,5,35,"[NULL]","_ZThn32_N7android13SensorService10threadLoopEv"
-36,6,36,"[NULL]","_ZN7android13SensorService10threadLoopEv"
-37,7,37,"[NULL]","_ZN7android12SensorDevice7pollFmqEP15sensors_event_tm"
-38,8,38,"[NULL]","_ZN7android8hardware9EventFlag10waitHelperEjPjl"
-39,9,39,"[NULL]","syscall"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
-3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
-24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
-25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-28,8,28,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-29,9,29,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
-30,10,30,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-31,11,31,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-40,12,40,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
-41,13,41,"[NULL]","_ZN7android15inputdispatcher34verifiedMotionEventFromMotionEntryERKNS0_11MotionEntryE"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
-3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
-24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
-25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-42,8,42,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-43,9,43,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher30findTouchedWindowTargetsLockedElRKNS0_11MotionEntryERNSt3__16vectorINS0_11InputTargetENS5_9allocatorIS7_EEEEPlPb"
-44,10,44,"[NULL]","_ZNK7android15inputdispatcher15InputDispatcher29hasResponsiveConnectionLockedERNS_17InputWindowHandleE"
-45,11,45,"[NULL]","_ZNK7android7RefBase9incStrongEPKv"
-0,0,0,"[NULL]","__start_thread"
-1,1,1,"[NULL]","_ZL15__pthread_startPv"
-46,2,46,"[NULL]","_ZN3art6Thread14CreateCallbackEPv"
-47,3,47,"[NULL]","_ZN3art35InvokeVirtualOrInterfaceWithJValuesIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_PK6jvalue"
-48,4,48,"[NULL]","_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc"
-49,5,13,"[NULL]","art_quick_invoke_stub"
-50,6,49,"aot","com.android.server.UiThread.run"
-51,7,50,"aot","android.os.HandlerThread.run"
-52,8,51,"aot","android.os.Looper.loop"
-53,9,52,"aot","android.os.Looper.loopOnce"
-54,10,53,"aot","android.os.MessageQueue.next"
-55,11,54,"common-frame","art_jni_trampoline"
-56,12,55,"[NULL]","_ZN7androidL38android_os_MessageQueue_nativePollOnceEP7_JNIEnvP8_jobjectli"
-57,13,56,"[NULL]","_ZN7android6Looper8pollOnceEiPiS1_PPv"
-58,14,57,"[NULL]","_ZN7android6Looper9pollInnerEi"
-59,15,58,"[NULL]","_ZN7android24NativeInputEventReceiver11handleEventEiiPv"
-60,16,59,"[NULL]","_ZN7android24NativeInputEventReceiver13consumeEventsEP7_JNIEnvblPb"
-61,17,60,"common-frame","_ZN3art3JNIILb0EE9FindClassEP7_JNIEnvPKc"
-62,18,61,"common-frame","_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE"
-63,19,62,"common-frame",""
diff --git a/test/trace_processor/dynamic/relationship_tables.textproto b/test/trace_processor/dynamic/relationship_tables.textproto
deleted file mode 100644
index 084ce99..0000000
--- a/test/trace_processor/dynamic/relationship_tables.textproto
+++ /dev/null
@@ -1,308 +0,0 @@
-# Sequence 1 defaults to track for "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 10
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-    }
-  }
-}
-# Sequence 2 defaults to track for "t2".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 2
-    parent_uuid: 10
-    thread {
-      pid: 5
-      tid: 2
-      thread_name: "t2"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 2
-    }
-  }
-}
-# Both thread tracks are nested underneath this process track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 10
-    process {
-      pid: 5
-      process_name: "p1"
-    }
-  }
-}
-# And we have an async track underneath the process too.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 11
-    parent_uuid: 10
-    name: "async"
-  }
-}
-
-# ----------------------
-# Slices
-# ----------------------
-
-# First we create an event with no relationships just a single event on a track
-# by it self. For both threads and async track.
-#
-# t1    |----------|
-# ---------------------
-# t2       |-----|
-# --------------------
-# async |-------------|
-
-# Should appear on default track "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t1_no_relationships"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t1_no_relationships"
-    type: 2
-  }
-}
-# Should appear on default track "t2".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t2_no_relationships"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 3000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t2_no_relationships"
-    type: 2
-  }
-}
-# Should appear on async track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event1_on_async_no_relationships"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 5000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event1_on_async_no_relationships"
-    type: 2
-  }
-}
-
-# Next we create stacks of various depths for the different tracks.
-# t1     |--------|
-#           |---|
-# ---------------------------------
-# t2                  |-------------------|
-#                         |---|   |-----|
-#                           |       |-|
-# ---------------------------------
-# async  |----------------------|
-#                 |-----------|
-
-# Should appear on default track "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 6000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_0_on_t1"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 7000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_1_on_t1"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 8000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_1_on_t1"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 9000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_0_on_t1"
-    type: 2
-  }
-}
-
-# Should appear on default track "t2".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 10000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_0_on_t2"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 11000
-  track_event {
-    categories: "cat"
-    name: "event2_first_depth_1_on_t2"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 12000
-  track_event {
-    categories: "cat"
-    name: "event2_first_depth_2_on_t2"
-    type: 3
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 13000
-  track_event {
-    categories: "cat"
-    name: "event2_first_depth_1_on_t2"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 15000
-  track_event {
-    categories: "cat"
-    name: "event2_second_depth_1_on_t2"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 16000
-  track_event {
-    categories: "cat"
-    name: "event2_second_depth_2_on_t2"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 17000
-  track_event {
-    categories: "cat"
-    name: "event2_second_depth_2_on_t2"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 18000
-  track_event {
-    categories: "cat"
-    name: "event2_second_depth_1_on_t2"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 19000
-  track_event {
-    categories: "cat"
-    name: "event2_depth_0_on_t2"
-    type: 2
-  }
-}
-# Should appear on async track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 6000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event2_on_async_depth_0"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 9000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event2_on_async_depth_1"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 13000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event1_on_async_depth_1"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 14000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event2_on_async_depth_0"
-    type: 2
-  }
-}
diff --git a/test/trace_processor/parsing/end_reason_eq.sql b/test/trace_processor/end_reason_eq.sql
similarity index 100%
rename from test/trace_processor/parsing/end_reason_eq.sql
rename to test/trace_processor/end_reason_eq.sql
diff --git a/test/trace_processor/parsing/end_reason_neq.sql b/test/trace_processor/end_reason_neq.sql
similarity index 100%
rename from test/trace_processor/parsing/end_reason_neq.sql
rename to test/trace_processor/end_reason_neq.sql
diff --git a/test/trace_processor/tables/filter_counter.sql b/test/trace_processor/filter_counter.sql
similarity index 100%
rename from test/trace_processor/tables/filter_counter.sql
rename to test/trace_processor/filter_counter.sql
diff --git a/test/trace_processor/tables/filter_row_vector.sql b/test/trace_processor/filter_row_vector.sql
similarity index 100%
rename from test/trace_processor/tables/filter_row_vector.sql
rename to test/trace_processor/filter_row_vector.sql
diff --git a/test/trace_processor/tables/filter_row_vector_example_android_trace_30s.out b/test/trace_processor/filter_row_vector_example_android_trace_30s.out
similarity index 100%
rename from test/trace_processor/tables/filter_row_vector_example_android_trace_30s.out
rename to test/trace_processor/filter_row_vector_example_android_trace_30s.out
diff --git a/test/trace_processor/tables/filter_sched.sql b/test/trace_processor/filter_sched.sql
similarity index 100%
rename from test/trace_processor/tables/filter_sched.sql
rename to test/trace_processor/filter_sched.sql
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_flow.out b/test/trace_processor/fuchsia/fuchsia_smoke_flow.out
deleted file mode 100644
index 6726a35..0000000
--- a/test/trace_processor/fuchsia/fuchsia_smoke_flow.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"id","slice_out","slice_in"
-0,0,1
-1,2,3
-2,4,5
-3,6,7
-4,8,9
-5,10,11
-6,12,13
-7,14,15
-8,16,17
-9,18,19
diff --git a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_args.out b/test/trace_processor/fuchsia/fuchsia_workstation_smoke_args.out
deleted file mode 100644
index 3b83654..0000000
--- a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_args.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"key","COUNT(*)"
-"Dart Arguments",3
-"Escher frame number",33
-"Expected presentation time",17
-"Frame number",33
-"MinikinFontsCount",2
-"Predicted frame duration(ms)",21
-"Render time(ms)",21
-"Timestamp",917
-"Update time(ms)",21
-"Vsync interval",900
diff --git a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out b/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out
deleted file mode 100644
index daab85f..0000000
--- a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out
+++ /dev/null
@@ -1,24 +0,0 @@
-"type","depth","count"
-"process_track",0,85
-"process_track",1,14
-"process_track",2,1
-"thread_track",0,13379
-"thread_track",1,11548
-"thread_track",2,10181
-"thread_track",3,1927
-"thread_track",4,4001
-"thread_track",5,2543
-"thread_track",6,1856
-"thread_track",7,2209
-"thread_track",8,2200
-"thread_track",9,1672
-"thread_track",10,353
-"thread_track",11,331
-"thread_track",12,304
-"thread_track",13,246
-"thread_track",14,207
-"thread_track",15,175
-"thread_track",16,114
-"thread_track",17,38
-"thread_track",18,12
-"thread_track",19,1
diff --git a/test/trace_processor/fuchsia/index b/test/trace_processor/fuchsia/index
deleted file mode 100644
index bb89b30..0000000
--- a/test/trace_processor/fuchsia/index
+++ /dev/null
@@ -1,12 +0,0 @@
-# Contains tests for parsing Fuchsia traces.
-
-# Smoke test a bunch of different event types.
-../../data/fuchsia_trace.fxt ../common/smoke.sql fuchsia_smoke.out
-../../data/fuchsia_trace.fxt ../common/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_trace.fxt smoke_flow.sql fuchsia_smoke_flow.out
-
-# Smoke test a high-CPU trace.
-../../data/fuchsia_workstation.fxt ../common/smoke_slices.sql fuchsia_workstation_smoke_slices.out
-../../data/fuchsia_workstation.fxt smoke_args.sql fuchsia_workstation_smoke_args.out
diff --git a/test/trace_processor/fuchsia/smoke_args.sql b/test/trace_processor/fuchsia/smoke_args.sql
deleted file mode 100644
index 522f538..0000000
--- a/test/trace_processor/fuchsia/smoke_args.sql
+++ /dev/null
@@ -1,21 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  key,
-  COUNT(*)
-from args
-group by key
-limit 10;
diff --git a/test/trace_processor/fuchsia/smoke_flow.sql b/test/trace_processor/fuchsia/smoke_flow.sql
deleted file mode 100644
index e0b8af4..0000000
--- a/test/trace_processor/fuchsia/smoke_flow.sql
+++ /dev/null
@@ -1,21 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  id,
-  slice_out,
-  slice_in
-from flow
-limit 10;
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke.out b/test/trace_processor/fuchsia_smoke.out
similarity index 100%
rename from test/trace_processor/fuchsia/fuchsia_smoke.out
rename to test/trace_processor/fuchsia_smoke.out
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_counters.out b/test/trace_processor/fuchsia_smoke_counters.out
similarity index 100%
rename from test/trace_processor/fuchsia/fuchsia_smoke_counters.out
rename to test/trace_processor/fuchsia_smoke_counters.out
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_instants.out b/test/trace_processor/fuchsia_smoke_instants.out
similarity index 100%
rename from test/trace_processor/fuchsia/fuchsia_smoke_instants.out
rename to test/trace_processor/fuchsia_smoke_instants.out
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_slices.out b/test/trace_processor/fuchsia_smoke_slices.out
similarity index 100%
rename from test/trace_processor/fuchsia/fuchsia_smoke_slices.out
rename to test/trace_processor/fuchsia_smoke_slices.out
diff --git a/test/trace_processor/fuchsia_workstation_smoke_slices.out b/test/trace_processor/fuchsia_workstation_smoke_slices.out
new file mode 100644
index 0000000..2d133e8
--- /dev/null
+++ b/test/trace_processor/fuchsia_workstation_smoke_slices.out
@@ -0,0 +1,24 @@
+"type","depth","count"
+"thread_track",0,13379
+"thread_track",1,11548
+"thread_track",2,10181
+"thread_track",3,1927
+"thread_track",4,4001
+"thread_track",5,2543
+"thread_track",6,1856
+"thread_track",7,2209
+"thread_track",8,2200
+"thread_track",9,1672
+"thread_track",10,353
+"thread_track",11,331
+"thread_track",12,304
+"thread_track",13,246
+"thread_track",14,207
+"thread_track",15,175
+"thread_track",16,114
+"thread_track",17,38
+"thread_track",18,12
+"thread_track",19,1
+"track",0,85
+"track",1,14
+"track",2,1
diff --git a/test/trace_processor/parsing/global_memory_counter.sql b/test/trace_processor/global_memory_counter.sql
similarity index 100%
rename from test/trace_processor/parsing/global_memory_counter.sql
rename to test/trace_processor/global_memory_counter.sql
diff --git a/test/trace_processor/parsing/global_memory_counter_memory_counters.out b/test/trace_processor/global_memory_counter_memory_counters.out
similarity index 100%
rename from test/trace_processor/parsing/global_memory_counter_memory_counters.out
rename to test/trace_processor/global_memory_counter_memory_counters.out
diff --git a/test/trace_processor/graphics/gpu_counter_specs.out b/test/trace_processor/gpu_counter_specs.out
similarity index 100%
rename from test/trace_processor/graphics/gpu_counter_specs.out
rename to test/trace_processor/gpu_counter_specs.out
diff --git a/test/trace_processor/graphics/gpu_counter_specs.sql b/test/trace_processor/gpu_counter_specs.sql
similarity index 100%
rename from test/trace_processor/graphics/gpu_counter_specs.sql
rename to test/trace_processor/gpu_counter_specs.sql
diff --git a/test/trace_processor/graphics/gpu_counter_specs.textproto b/test/trace_processor/gpu_counter_specs.textproto
similarity index 100%
rename from test/trace_processor/graphics/gpu_counter_specs.textproto
rename to test/trace_processor/gpu_counter_specs.textproto
diff --git a/test/trace_processor/graphics/gpu_counters.out b/test/trace_processor/gpu_counters.out
similarity index 100%
rename from test/trace_processor/graphics/gpu_counters.out
rename to test/trace_processor/gpu_counters.out
diff --git a/test/trace_processor/gpu_counters.py b/test/trace_processor/gpu_counters.py
new file mode 100644
index 0000000..4882167
--- /dev/null
+++ b/test/trace_processor/gpu_counters.py
@@ -0,0 +1,70 @@
+#!/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/graphics/gpu_counters.sql b/test/trace_processor/gpu_counters.sql
similarity index 100%
rename from test/trace_processor/graphics/gpu_counters.sql
rename to test/trace_processor/gpu_counters.sql
diff --git a/test/trace_processor/graphics/gpu_log.out b/test/trace_processor/gpu_log.out
similarity index 100%
rename from test/trace_processor/graphics/gpu_log.out
rename to test/trace_processor/gpu_log.out
diff --git a/test/trace_processor/gpu_log.py b/test/trace_processor/gpu_log.py
new file mode 100644
index 0000000..b4b0369
--- /dev/null
+++ b/test/trace_processor/gpu_log.py
@@ -0,0 +1,28 @@
+#!/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/graphics/gpu_log.sql b/test/trace_processor/gpu_log.sql
similarity index 100%
rename from test/trace_processor/graphics/gpu_log.sql
rename to test/trace_processor/gpu_log.sql
diff --git a/test/trace_processor/gpu_render_stages.out b/test/trace_processor/gpu_render_stages.out
new file mode 100644
index 0000000..1485b99
--- /dev/null
+++ b/test/trace_processor/gpu_render_stages.out
@@ -0,0 +1,18 @@
+"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","render_target_name","render_pass","render_pass_name","command_buffer","command_buffer_name","submission_id","hw_queue_id"
+"queue 1","queue desc 1",0,5,"render stage(1)",0,"[NULL]","[NULL]",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1
+"queue 0","queue desc 0",0,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 1","queue desc 1",10,5,"stage 1",0,"description","stage desc 1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1
+"queue 2","[NULL]",20,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,2
+"queue 0","queue desc 0",30,5,"stage 3",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"Unknown GPU Queue 3","[NULL]",40,5,"render stage(4)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,3
+"queue 0","queue desc 0",50,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",60,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",60,5,"stage 0",0,"key2","value2",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",70,5,"stage 0",0,"key1","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",80,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",90,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",32,"[NULL]",48,"[NULL]",0,0
+"queue 0","queue desc 0",100,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"[NULL]",16,"command_buffer",0,0
+"queue 0","queue desc 0",110,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"render_pass",16,"command_buffer",0,0
+"queue 0","queue desc 0",120,5,"stage 0",0,"[NULL]","[NULL]",42,16,"framebuffer",16,"render_pass",16,"command_buffer",0,0
+"queue 0","queue desc 0",130,5,"stage 0",0,"[NULL]","[NULL]",42,16,"renamed_buffer",0,"[NULL]",0,"[NULL]",0,0
+"Unknown GPU Queue ","[NULL]",140,5,"render stage(18446744073709551615)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1024
diff --git a/test/trace_processor/gpu_render_stages.py b/test/trace_processor/gpu_render_stages.py
new file mode 100644
index 0000000..a88fc78
--- /dev/null
+++ b/test/trace_processor/gpu_render_stages.py
@@ -0,0 +1,192 @@
+#!/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()
+
+# Add a slice before any Specification packet is received.
+trace.add_gpu_render_stages(
+    ts=0, event_id=0, duration=5, hw_queue_id=1, stage_id=1, context=0)
+
+trace.add_gpu_render_stages_stage_spec([{
+    'name': 'stage 0'
+}, {
+    'name': 'stage 1',
+    'description': 'stage desc 1'
+}, {
+    'name': 'stage 2'
+}, {
+    'name': 'stage 3'
+}])
+
+trace.add_gpu_render_stages_hw_queue_spec([{
+    'name': 'queue 0',
+    'description': 'queue desc 0'
+}, {
+    'name': 'queue 1',
+    'description': 'queue desc 1'
+}, {
+    'name': 'queue 2',
+}])
+
+# Add some track to make sure Specification works properly
+trace.add_gpu_render_stages(
+    ts=0, event_id=0, duration=5, hw_queue_id=0, stage_id=0, context=42)
+trace.add_gpu_render_stages(
+    ts=10, event_id=1, duration=5, hw_queue_id=1, stage_id=1, context=42)
+trace.add_gpu_render_stages(
+    ts=20, event_id=2, duration=5, hw_queue_id=2, stage_id=2, context=42)
+trace.add_gpu_render_stages(
+    ts=30, event_id=3, duration=5, hw_queue_id=0, stage_id=3, context=42)
+# Add a track without Specification for hw_queue_id/stage_id.
+trace.add_gpu_render_stages(
+    ts=40, event_id=3, duration=5, hw_queue_id=3, stage_id=4, context=42)
+
+# Test extra_data
+# event with single arg.
+trace.add_gpu_render_stages(
+    ts=50,
+    event_id=5,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    extra_data={'key1': 'value1'})
+# event with multiple args.
+trace.add_gpu_render_stages(
+    ts=60,
+    event_id=6,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    extra_data={
+        'key1': 'value1',
+        'key2': 'value2'
+    })
+# event with args that only has key, but no value.
+trace.add_gpu_render_stages(
+    ts=70,
+    event_id=7,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    extra_data={'key1': None})
+
+##############################################
+# Test stage naming with render target handle.
+
+VK_OBJECT_TYPE_COMMAND_BUFFER = 6
+VK_OBJECT_TYPE_RENDER_PASS = 18
+VK_OBJECT_TYPE_FRAMEBUFFER = 24
+
+trace.add_gpu_render_stages(
+    ts=80, event_id=8, duration=5, hw_queue_id=0, stage_id=2, context=42)
+
+# add render stage with render target handle without debug marker.
+trace.add_gpu_render_stages(
+    ts=90,
+    event_id=9,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10,
+    render_pass_handle=0x20,
+    command_buffer_handle=0x30)
+
+# adding a marker with COMMAND_BUFFER and RENDER_PASS should affect only the
+# relevant handles.
+trace.add_vk_debug_marker(
+    ts=91,
+    pid=100,
+    vk_device=1,
+    obj_type=VK_OBJECT_TYPE_COMMAND_BUFFER,
+    obj=0x10,
+    obj_name="command_buffer")
+trace.add_gpu_render_stages(
+    ts=100,
+    event_id=10,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10,
+    render_pass_handle=0x10,
+    command_buffer_handle=0x10)
+
+trace.add_vk_debug_marker(
+    ts=101,
+    pid=100,
+    vk_device=1,
+    obj_type=VK_OBJECT_TYPE_RENDER_PASS,
+    obj=0x10,
+    obj_name="render_pass")
+trace.add_gpu_render_stages(
+    ts=110,
+    event_id=10,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10,
+    render_pass_handle=0x10,
+    command_buffer_handle=0x10)
+
+# adding a marker with FRAMEBUFFER changes the name of the stage as well.
+trace.add_vk_debug_marker(
+    ts=111,
+    pid=100,
+    vk_device=1,
+    obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
+    obj=0x10,
+    obj_name="framebuffer")
+trace.add_gpu_render_stages(
+    ts=120,
+    event_id=10,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10,
+    render_pass_handle=0x10,
+    command_buffer_handle=0x10)
+
+# setting the name again replace the name
+trace.add_vk_debug_marker(
+    ts=121,
+    pid=100,
+    vk_device=1,
+    obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
+    obj=0x10,
+    obj_name="renamed_buffer")
+trace.add_gpu_render_stages(
+    ts=130,
+    event_id=11,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10)
+
+# Check that a hw_queue_id=-1 doesn't blow up.
+trace.add_gpu_render_stages(
+    ts=140, event_id=12, duration=5, hw_queue_id=-1, stage_id=-1, context=42)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_render_stages.sql b/test/trace_processor/gpu_render_stages.sql
new file mode 100644
index 0000000..c85d162
--- /dev/null
+++ b/test/trace_processor/gpu_render_stages.sql
@@ -0,0 +1,24 @@
+--
+-- 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 track.name AS track_name, gpu_track.description AS track_desc, ts, dur,
+    gpu_slice.name AS slice_name, depth, flat_key, string_value,
+    gpu_slice.context_id, render_target, render_target_name, render_pass, render_pass_name,
+    command_buffer, command_buffer_name, 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/actual_frame_timeline_events.out b/test/trace_processor/graphics/actual_frame_timeline_events.out
deleted file mode 100644
index 0eccd74..0000000
--- a/test/trace_processor/graphics/actual_frame_timeline_events.out
+++ /dev/null
@@ -1,15 +0,0 @@
-"ts","dur","pid","display_frame_token","surface_frame_token","layer_name","present_type","on_time_finish","gpu_composition","jank_type","prediction_type","jank_tag"
-20,6,666,2,0,"[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank"
-21,16,1000,4,1,"Layer1","On-time Present",1,0,"None","Valid Prediction","No Jank"
-41,33,1000,6,5,"Layer1","Late Present",0,0,"App Deadline Missed","Valid Prediction","Self Jank"
-42,5,666,4,0,"[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank"
-80,110,1000,17,16,"Layer1","Unknown Present",0,0,"Unknown Jank","Expired Prediction","Self Jank"
-81,7,666,6,0,"[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank"
-90,16,1000,8,7,"Layer1","Early Present",1,0,"SurfaceFlinger Scheduling","Valid Prediction","Other Jank"
-108,4,666,8,0,"[NULL]","Early Present",1,0,"SurfaceFlinger Scheduling","Valid Prediction","Self Jank"
-148,8,666,12,0,"[NULL]","Late Present",0,0,"SurfaceFlinger Scheduling, SurfaceFlinger CPU Deadline Missed","Valid Prediction","Self Jank"
-150,17,1000,15,14,"Layer1","On-time Present",1,0,"None","Valid Prediction","No Jank"
-150,17,1000,15,14,"Layer2","On-time Present",1,0,"None","Valid Prediction","No Jank"
-170,6,666,15,0,"[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank"
-200,6,666,17,0,"[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank"
-245,15,666,18,0,"[NULL]","Late Present",0,0,"SurfaceFlinger Stuffing","Valid Prediction","SurfaceFlinger Stuffing"
diff --git a/test/trace_processor/graphics/actual_frame_timeline_events.sql b/test/trace_processor/graphics/actual_frame_timeline_events.sql
deleted file mode 100644
index 412f4b7..0000000
--- a/test/trace_processor/graphics/actual_frame_timeline_events.sql
+++ /dev/null
@@ -1,24 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 ts, dur, process.pid as pid, display_frame_token, surface_frame_token, layer_name,
-    present_type, on_time_finish, gpu_composition, jank_type, prediction_type, jank_tag
-from
-  (select t.*, process_track.name as track_name from
-    process_track left join actual_frame_timeline_slice t
-    on process_track.id = t.track_id) s
-join process using(upid)
-where s.track_name = 'Actual Timeline'
-order by ts
diff --git a/test/trace_processor/graphics/android_jank.out b/test/trace_processor/graphics/android_jank.out
deleted file mode 100644
index 0bed674..0000000
--- a/test/trace_processor/graphics/android_jank.out
+++ /dev/null
@@ -1,38 +0,0 @@
-android_jank: {
-  warnings {
-    ts: 4000500
-    dur: 4999500
-    process_name: "com.android.systemui"
-    warning_text: "Expensive measure/layout pass"
-  }
-  warnings {
-    ts: 4001000
-    dur: 3499500
-    process_name: "com.android.systemui"
-    warning_text: "Inflation during ListView recycling"
-  }
-  warnings {
-    ts: 8000000
-    dur: 900000
-    process_name: "com.android.systemui"
-    warning_text: "Inflation during ListView recycling"
-  }
-  warnings {
-    ts: 1000000
-    dur: 19000000
-    process_name: "com.android.systemui"
-    warning_text: "Scheduling delay"
-  }
-  warnings {
-    ts: 116000000
-    dur: 1300000
-    process_name: "com.google.android.inputmethod.latin"
-    warning_text: "Expensive rendering with Canvas#saveLayer()"
-  }
-  warnings {
-    ts: 108000000
-    dur: 4000000
-    process_name: "com.google.android.inputmethod.latin"
-    warning_text: "Expensive Bitmap uploads"
-  }
-}
diff --git a/test/trace_processor/graphics/android_jank.py b/test/trace_processor/graphics/android_jank.py
deleted file mode 100644
index ba6a628..0000000
--- a/test/trace_processor/graphics/android_jank.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-
-def add_main_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=PID, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=PID, pid=PID)
-
-
-def add_render_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=RTID, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=RTID, pid=PID)
-
-
-trace = synth_common.create_trace()
-
-trace.add_packet()
-trace.add_package_list(
-    ts=0, name="com.android.systemui", uid=10001, version_code=1)
-trace.add_package_list(
-    ts=0,
-    name="com.google.android.inputmethod.latin",
-    uid=10002,
-    version_code=1)
-
-trace.add_process(pid=1000, ppid=1, cmdline="com.android.systemui", uid=10001)
-trace.add_thread(
-    tid=1001, tgid=1000, cmdline="RenderThread", name="RenderThread")
-trace.add_process(
-    pid=2000, ppid=1, cmdline="com.google.android.inputmethod.latin", uid=10002)
-trace.add_thread(
-    tid=2001, tgid=2000, cmdline="RenderThread", name="RenderThread")
-
-trace.add_ftrace_packet(cpu=0)
-
-# com.android.systemui
-
-trace.add_atrace_begin(
-    ts=1_000_000, tid=1000, pid=1000, buf='Choreographer#doFrame')
-trace.add_atrace_begin(ts=1_000_100, tid=1000, pid=1000, buf='traversal')
-trace.add_atrace_begin(ts=1_000_500, tid=1000, pid=1000, buf='measure')
-trace.add_atrace_end(ts=4_000_000, tid=1000, pid=1000)
-trace.add_atrace_begin(ts=4_000_500, tid=1000, pid=1000, buf='layout')
-trace.add_atrace_begin(ts=4_001_000, tid=1000, pid=1000, buf='setupListItem')
-trace.add_atrace_begin(ts=4_500_000, tid=1000, pid=1000, buf='inflate')
-trace.add_atrace_end(ts=5_500_000, tid=1000, pid=1000)
-trace.add_atrace_begin(ts=6_500_000, tid=1000, pid=1000, buf='inflate')
-trace.add_atrace_end(ts=7_500_000, tid=1000, pid=1000)
-trace.add_atrace_end(ts=7_500_500, tid=1000, pid=1000)
-trace.add_atrace_begin(ts=8_000_000, tid=1000, pid=1000, buf='obtainView')
-trace.add_atrace_begin(ts=8_000_100, tid=1000, pid=1000, buf='inflate')
-trace.add_atrace_end(ts=8_500_000, tid=1000, pid=1000)
-trace.add_atrace_end(ts=8_900_000, tid=1000, pid=1000)
-trace.add_atrace_end(ts=9_000_000, tid=1000, pid=1000)
-trace.add_atrace_end(ts=9_000_000, tid=1000, pid=1000)
-trace.add_atrace_end(ts=20_000_000, tid=1000, pid=1000)
-
-trace.add_sched(ts=1_000_000, prev_pid=0, next_pid=1000)
-trace.add_sched(ts=10_000_000, prev_pid=1000, next_pid=0, prev_state='R')
-trace.add_sched(ts=10_500_000, prev_pid=0, next_pid=0)
-trace.add_sched(ts=19_500_000, prev_pid=0, next_pid=1000)
-trace.add_sched(ts=20_500_000, prev_pid=1000, next_pid=0, prev_state='R')
-
-# com.google.android.inputmethod.latin
-
-trace.add_atrace_begin(
-    ts=101_000_000, tid=2000, pid=2000, buf='Choreographer#doFrame')
-trace.add_atrace_begin(ts=101_000_100, tid=2000, pid=2000, buf='traversal')
-trace.add_atrace_begin(ts=101_000_500, tid=2000, pid=2000, buf='measure')
-trace.add_atrace_end(ts=104_000_000, tid=2000, pid=2000)
-trace.add_atrace_begin(ts=104_000_500, tid=2000, pid=2000, buf='layout')
-trace.add_atrace_end(ts=105_000_000, tid=2000, pid=2000)
-trace.add_atrace_end(ts=105_000_000, tid=2000, pid=2000)
-trace.add_atrace_begin(ts=105_000_000, tid=2000, pid=2000, buf='draw')
-trace.add_atrace_end(ts=119_000_000, tid=2000, pid=2000)
-trace.add_atrace_end(ts=120_000_000, tid=2000, pid=2000)
-
-trace.add_atrace_begin(ts=105_000_000, tid=2001, pid=2000, buf='DrawFrames 3')
-trace.add_atrace_begin(
-    ts=108_000_000, tid=2001, pid=2000, buf='Upload 300x300 Texture')
-trace.add_atrace_end(ts=112_000_000, tid=2001, pid=2000)
-trace.add_atrace_begin(
-    ts=116_000_000,
-    tid=2001,
-    pid=2000,
-    buf='alpha caused unclipped saveLayer 201x319')
-trace.add_atrace_end(ts=117_300_000, tid=2001, pid=2000)
-trace.add_atrace_end(ts=118_000_000, tid=2001, pid=2000)
-
-trace.add_sched(ts=101_000_000, prev_pid=0, next_pid=2000)
-trace.add_sched(ts=120_000_000, prev_pid=2000, next_pid=0, prev_state='R')
-trace.add_sched(ts=120_500_000, prev_pid=0, next_pid=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/android_sysui_cuj.out b/test/trace_processor/graphics/android_sysui_cuj.out
deleted file mode 100644
index 1cdea90..0000000
--- a/test/trace_processor/graphics/android_sysui_cuj.out
+++ /dev/null
@@ -1,68 +0,0 @@
-android_sysui_cuj {
- cuj_name: "SHADE_ROW_EXPAND"
-  cuj_start: 0
-  cuj_dur: 1000000000
-  process {
-    name: "com.android.systemui"
-    uid: 10001
- }
- frames {
-   number: 1
-   ts: 0
-   dur: 15000000
-   vsync: 10
- }
- frames {
-   number: 2
-   ts: 8000000
-   dur: 27000000
-   jank_cause: "MainThread - binder transaction time"
-   jank_cause: "SurfaceFlinger Scheduling"
-   vsync: 20
- }
- frames {
-   number: 3
-   ts: 30000000
-   dur: 22000000
-   jank_cause: "RenderThread - long flush layers"
-   jank_cause: "MainThread - binder calls count"
-   vsync: 30
- }
- frames {
-   number: 4
-   ts: 40000000
-   dur: 38000000
-   jank_cause: "GPU completion - long completion time"
-   jank_cause: "Long running time"
-   jank_cause: "JIT compiling"
-   vsync: 40
- }
- frames {
-   number: 5
-   ts: 70000000
-   dur: 18000000
-   jank_cause: "RenderThread - scheduler"
-   vsync: 60
- }
-  frames {
-    number: 6
-    ts: 100000000
-    dur: 22000000
-    jank_cause: "GPU completion - long completion time"
-    vsync: 90
-  }
-  frames {
-    number: 7
-    ts: 200000000
-    dur: 10000000
-    jank_cause: "SurfaceFlinger GPU Deadline Missed"
-    jank_cause: "SurfaceFlinger Scheduling"
-    vsync: 100
-  }
-  frames {
-    number: 8
-    ts: 400000000
-    dur: 10000000
-    vsync: 120
-  }
-}
diff --git a/test/trace_processor/graphics/android_sysui_cuj.py b/test/trace_processor/graphics/android_sysui_cuj.py
deleted file mode 100644
index dcbbf9b..0000000
--- a/test/trace_processor/graphics/android_sysui_cuj.py
+++ /dev/null
@@ -1,328 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-PID = 1000
-RTID = 1555
-JITID = 1777
-LAYER = "TX - NotificationShade#0"
-
-
-def add_main_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=PID, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=PID, pid=PID)
-
-
-def add_render_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=RTID, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=RTID, pid=PID)
-
-
-def add_gpu_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=1666, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=1666, pid=PID)
-
-
-def add_jit_thread_atrace(trace, ts, ts_end, buf):
-  trace.add_atrace_begin(ts=ts, tid=JITID, pid=PID, buf=buf)
-  trace.add_atrace_end(ts=ts_end, tid=JITID, pid=PID)
-
-
-def add_frame(trace, vsync, ts_do_frame, ts_end_do_frame, ts_draw_frame,
-              ts_end_draw_frame, ts_gpu, ts_end_gpu):
-  add_main_thread_atrace(trace, ts_do_frame, ts_end_do_frame,
-                         "Choreographer#doFrame %d" % vsync)
-  add_render_thread_atrace(trace, ts_draw_frame, ts_end_draw_frame,
-                           "DrawFrames %d" % vsync)
-  add_gpu_thread_atrace(trace, ts_gpu, ts_end_gpu,
-                        "waiting for GPU completion 123")
-
-
-def add_display_frame_events(ts,
-                             dur,
-                             token_start,
-                             jank=None,
-                             on_time_finish_override=None):
-  jank_type = jank if jank is not None else 1
-  present_type = 2 if jank is not None else 1
-  if on_time_finish_override is None:
-    on_time_finish = 1 if jank is None else 0
-  else:
-    on_time_finish = on_time_finish_override
-  trace.add_expected_display_frame_start_event(
-      ts=ts, cookie=token_start, token=token_start, pid=PID)
-  trace.add_frame_end_event(ts=ts + 20_500_000, cookie=token_start)
-  trace.add_actual_display_frame_start_event(
-      ts=ts,
-      cookie=token_start + 1,
-      token=token_start,
-      pid=PID,
-      present_type=present_type,
-      on_time_finish=on_time_finish,
-      gpu_composition=0,
-      jank_type=jank_type,
-      prediction_type=3)
-  trace.add_frame_end_event(ts=ts + dur, cookie=token_start + 1)
-  trace.add_expected_surface_frame_start_event(
-      ts=ts,
-      cookie=token_start + 2,
-      token=token_start,
-      display_frame_token=token_start,
-      pid=PID,
-      layer_name=LAYER)
-  trace.add_frame_end_event(ts=ts + 20_500_000, cookie=token_start + 2)
-  trace.add_actual_surface_frame_start_event(
-      ts=ts,
-      cookie=token_start + 3,
-      token=token_start,
-      display_frame_token=token_start,
-      pid=PID,
-      layer_name=LAYER,
-      present_type=present_type,
-      on_time_finish=on_time_finish,
-      gpu_composition=0,
-      jank_type=jank_type,
-      prediction_type=3)
-  trace.add_frame_end_event(ts=ts + dur, cookie=token_start + 3)
-
-
-trace = synth_common.create_trace()
-
-trace.add_packet()
-trace.add_package_list(
-    ts=0, name="com.android.systemui", uid=10001, version_code=1)
-
-trace.add_process(pid=PID, ppid=1, cmdline="com.android.systemui", uid=10001)
-trace.add_thread(
-    tid=RTID, tgid=PID, cmdline="RenderThread", name="RenderThread")
-trace.add_thread(
-    tid=1666, tgid=PID, cmdline="GPU completion", name="GPU completion")
-trace.add_thread(
-    tid=JITID, tgid=PID, cmdline="Jit thread pool", name="Jit thread pool")
-trace.add_ftrace_packet(cpu=0)
-trace.add_atrace_async_begin(ts=0, tid=PID, pid=PID, buf="J<SHADE_ROW_EXPAND>")
-trace.add_atrace_async_end(
-    ts=1_000_000_000, tid=PID, pid=PID, buf="J<SHADE_ROW_EXPAND>")
-
-add_frame(
-    trace,
-    vsync=10,
-    ts_do_frame=0,
-    ts_end_do_frame=5_000_000,
-    ts_draw_frame=4_000_000,
-    ts_end_draw_frame=5_000_000,
-    ts_gpu=10_000_000,
-    ts_end_gpu=15_000_000)
-add_main_thread_atrace(
-    trace, ts=1_500_000, ts_end=2_000_000, buf="binder transaction")
-add_render_thread_atrace(
-    trace, ts=4_500_000, ts_end=4_800_000, buf="flush layers")
-
-
-add_frame(
-    trace,
-    vsync=20,
-    ts_do_frame=8_000_000,
-    ts_end_do_frame=23_000_000,
-    ts_draw_frame=22_000_000,
-    ts_end_draw_frame=26_000_000,
-    ts_gpu=27_500_000,
-    ts_end_gpu=35_000_000)
-add_main_thread_atrace(
-    trace, ts=9_000_000, ts_end=20_000_000, buf="binder transaction")
-add_render_thread_atrace(
-    trace, ts=24_000_000, ts_end=25_000_000, buf="flush layers")
-
-add_frame(
-    trace,
-    vsync=30,
-    ts_do_frame=30_000_000,
-    ts_end_do_frame=33_000_000,
-    ts_draw_frame=31_000_000,
-    ts_end_draw_frame=50_000_000,
-    ts_gpu=51_500_000,
-    ts_end_gpu=52_000_000)
-add_main_thread_atrace(
-    trace, ts=31_000_000, ts_end=31_050_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_100_000, ts_end=31_150_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_200_000, ts_end=31_250_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_300_000, ts_end=31_350_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_400_000, ts_end=31_450_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_500_000, ts_end=31_550_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_600_000, ts_end=31_650_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_700_000, ts_end=31_750_000, buf="binder transaction")
-add_main_thread_atrace(
-    trace, ts=31_800_000, ts_end=31_850_000, buf="binder transaction")
-add_render_thread_atrace(
-    trace, ts=38_000_000, ts_end=50_000_000, buf="flush layers")
-
-add_frame(
-    trace,
-    vsync=40,
-    ts_do_frame=40_000_000,
-    ts_end_do_frame=53_000_000,
-    ts_draw_frame=52_000_000,
-    ts_end_draw_frame=59_000_000,
-    ts_gpu=66_500_000,
-    ts_end_gpu=78_000_000)
-
-add_jit_thread_atrace(
-    trace,
-    ts=39_000_000,
-    ts_end=45_000_000,
-    buf="JIT compiling void aa.aa(java.lang.Object, bb) (kind=Baseline)")
-add_jit_thread_atrace(
-    trace,
-    ts=46_000_000,
-    ts_end=47_000_000,
-    buf="Lock contention on Jit code cache (owner tid: 12345)")
-add_jit_thread_atrace(
-    trace,
-    ts=52_500_000,
-    ts_end=54_000_000,
-    buf="JIT compiling void cc.bb(java.lang.Object, bb) (kind=Osr)")
-add_jit_thread_atrace(
-    trace,
-    ts=56_500_000,
-    ts_end=60_000_000,
-    buf="JIT compiling void ff.zz(java.lang.Object, bb) (kind=Baseline)")
-
-# Main thread Running for 14 millis
-trace.add_sched(ts=39_000_000, prev_pid=0, next_pid=PID)
-trace.add_sched(ts=53_000_000, prev_pid=PID, next_pid=0, prev_state='R')
-
-# RenderThread Running for 5 millis
-trace.add_sched(ts=54_000_000, prev_pid=0, next_pid=RTID)
-trace.add_sched(ts=59_000_000, prev_pid=RTID, next_pid=0, prev_state='R')
-
-add_frame(
-    trace,
-    vsync=60,
-    ts_do_frame=70_000_000,
-    ts_end_do_frame=80_000_000,
-    ts_draw_frame=78_000_000,
-    ts_end_draw_frame=87_000_000,
-    ts_gpu=86_500_000,
-    ts_end_gpu=88_000_000)
-
-# Main thread Running for 1 millis
-trace.add_sched(ts=70_000_000, prev_pid=0, next_pid=PID)
-trace.add_sched(ts=71_000_000, prev_pid=PID, next_pid=0, prev_state='R')
-
-# RenderThread Running for 1 millis and R for 9.5 millis
-trace.add_sched(ts=78_000_000, prev_pid=0, next_pid=RTID)
-trace.add_sched(ts=78_500_000, prev_pid=RTID, next_pid=0, prev_state='R')
-trace.add_sched(ts=78_500_000, prev_pid=0, next_pid=0)
-trace.add_sched(ts=88_000_000, prev_pid=0, next_pid=RTID)
-trace.add_sched(ts=88_500_000, prev_pid=RTID, next_pid=0, prev_state='R')
-
-add_frame(
-    trace,
-    vsync=90,
-    ts_do_frame=100_000_000,
-    ts_end_do_frame=115_000_000,
-    ts_draw_frame=102_000_000,
-    ts_end_draw_frame=104_000_000,
-    ts_gpu=108_000_000,
-    ts_end_gpu=115_600_000)
-
-add_render_thread_atrace(
-    trace, ts=108_000_000, ts_end=114_000_000, buf="DrawFrames 90")
-add_gpu_thread_atrace(
-    trace,
-    ts=121_500_000,
-    ts_end=122_000_000,
-    buf="waiting for GPU completion 123")
-
-add_frame(
-    trace,
-    vsync=100,
-    ts_do_frame=200_000_000,
-    ts_end_do_frame=215_000_000,
-    ts_draw_frame=202_000_000,
-    ts_end_draw_frame=204_000_000,
-    ts_gpu=208_000_000,
-    ts_end_gpu=210_000_000)
-
-add_render_thread_atrace(
-    trace, ts=208_000_000, ts_end=214_000_000, buf="DrawFrames 100")
-
-add_frame(
-    trace,
-    vsync=110,
-    ts_do_frame=300_000_000,
-    ts_end_do_frame=315_000_000,
-    ts_draw_frame=302_000_000,
-    ts_end_draw_frame=304_000_000,
-    ts_gpu=308_000_000,
-    ts_end_gpu=310_000_000)
-
-add_render_thread_atrace(
-    trace, ts=305_000_000, ts_end=308_000_000, buf="dispatchFrameCallbacks")
-
-add_frame(
-    trace,
-    vsync=120,
-    ts_do_frame=400_000_000,
-    ts_end_do_frame=415_000_000,
-    ts_draw_frame=402_000_000,
-    ts_end_draw_frame=404_000_000,
-    ts_gpu=408_000_000,
-    ts_end_gpu=410_000_000)
-
-add_render_thread_atrace(
-    trace, ts=415_000_000, ts_end=418_000_000, buf="dispatchFrameCallbacks")
-
-# One more frame after the CUJ is finished
-add_frame(
-    trace,
-    vsync=130,
-    ts_do_frame=1_100_000_000,
-    ts_end_do_frame=1_200_000_000,
-    ts_draw_frame=1_150_000_000,
-    ts_end_draw_frame=1_300_000_000,
-    ts_gpu=1_400_000_000,
-    ts_end_gpu=1_500_000_000)
-
-add_display_frame_events(ts=1, dur=16_000_000, token_start=10)
-add_display_frame_events(ts=8_000_000, dur=28_000_000, token_start=20, jank=66)
-add_display_frame_events(ts=30_000_000, dur=25_000_000, token_start=30, jank=64)
-add_display_frame_events(ts=40_000_000, dur=40_000_000, token_start=40, jank=64)
-add_display_frame_events(ts=70_000_000, dur=20_000_000, token_start=60, jank=64)
-add_display_frame_events(
-    ts=100_000_000, dur=23_000_000, token_start=90, jank=64)
-add_display_frame_events(
-    ts=200_000_000, dur=22_000_000, token_start=100, jank=34)
-add_display_frame_events(ts=300_000_000, dur=61_000_000, token_start=110)
-add_display_frame_events(
-    ts=400_000_000,
-    dur=61_000_000,
-    token_start=120,
-    jank=128,
-    on_time_finish_override=1)
-add_display_frame_events(
-    ts=1_100_000_000, dur=500_000_000, token_start=130, jank=64)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/android_sysui_cuj_event.out b/test/trace_processor/graphics/android_sysui_cuj_event.out
deleted file mode 100644
index 4519815..0000000
--- a/test/trace_processor/graphics/android_sysui_cuj_event.out
+++ /dev/null
@@ -1,8 +0,0 @@
-
-"track_type","track_name","ts","dur","slice_name"
-"slice","SHADE_ROW_EXPAND - jank cause",8000000,15000000,"MainThread - binder transaction time,SurfaceFlinger Scheduling"
-"slice","SHADE_ROW_EXPAND - jank cause",30000000,3000000,"MainThread - binder calls count,RenderThread - long flush layers"
-"slice","SHADE_ROW_EXPAND - jank cause",40000000,13000000,"GPU completion - long completion time,JIT compiling,Long running time"
-"slice","SHADE_ROW_EXPAND - jank cause",70000000,10000000,"RenderThread - scheduler"
-"slice","SHADE_ROW_EXPAND - jank cause",100000000,15000000,"GPU completion - long completion time"
-"slice","SHADE_ROW_EXPAND - jank cause",200000000,15000000,"SurfaceFlinger GPU Deadline Missed,SurfaceFlinger Scheduling"
diff --git a/test/trace_processor/graphics/android_sysui_cuj_event.sql b/test/trace_processor/graphics/android_sysui_cuj_event.sql
deleted file mode 100644
index e1d1271..0000000
--- a/test/trace_processor/graphics/android_sysui_cuj_event.sql
+++ /dev/null
@@ -1,18 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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/android_sysui_cuj.sql') AS suppress_query_output;
-
-SELECT * FROM android_sysui_cuj_event;
\ No newline at end of file
diff --git a/test/trace_processor/graphics/clock_sync.py b/test/trace_processor/graphics/clock_sync.py
deleted file mode 100644
index 690c736..0000000
--- a/test/trace_processor/graphics/clock_sync.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-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=14, 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)
-
-# Set default clock for sequence 2.
-defaults_packet = trace.add_packet()
-defaults_packet.trusted_packet_sequence_id = 2
-defaults_packet.trace_packet_defaults.timestamp_clock_id = SEQ_CLOCK1
-
-# This counter should be translated @ BOOTTIME : 2000 + 10
-trace.add_gpu_counter(ts=10, seq_id=2, counter_id=42, value=12)
-
-# Manually specified clock_id overrides the default clock.
-trace.add_gpu_counter(
-    ts=2013, clock_id=CLOCK_BOOTTIME, seq_id=2, counter_id=42, value=13)
-
-# Other sequence's default clock isn't changed, so this should be in BOOTTIME.
-trace.add_gpu_counter(ts=3010, counter_id=42, value=15, seq_id=3)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/composer_execution.out b/test/trace_processor/graphics/composer_execution.out
deleted file mode 100644
index 1ec79a8..0000000
--- a/test/trace_processor/graphics/composer_execution.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"validation_type","count","total"
-"separated_validation",1,200
-"skipped_validation",2,200
-"unskipped_validation",1,200
diff --git a/test/trace_processor/graphics/composer_execution.py b/test/trace_processor/graphics/composer_execution.py
deleted file mode 100644
index 7ff5524..0000000
--- a/test/trace_processor/graphics/composer_execution.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(10335, 10, "child_process")
-
-trace.add_ftrace_packet(1)
-
-# unskipped validation
-trace.add_atrace_begin(ts=100, tid=10335, pid=10335, buf="onMessageRefresh")
-trace.add_atrace_begin(ts=200, tid=10335, pid=10335, buf="HwcPresentOrValidateDisplay")
-trace.add_atrace_end(ts=300, tid=10335, pid=10335)
-trace.add_atrace_begin(ts=400, tid=10335, pid=10335, buf="HwcPresentDisplay")
-trace.add_atrace_end(ts=500, tid=10335, pid=10335)
-trace.add_atrace_end(ts=600, tid=10335, pid=10335)
-
-# skipped validation
-trace.add_atrace_begin(ts=1_100, tid=10335, pid=10335, buf="onMessageRefresh")
-trace.add_atrace_begin(ts=1_200, tid=10335, pid=10335, buf="HwcPresentOrValidateDisplay")
-trace.add_atrace_end(ts=1_300, tid=10335, pid=10335)
-trace.add_atrace_end(ts=1_400, tid=10335, pid=10335)
-
-# separated validation
-trace.add_atrace_begin(ts=2_100, tid=10335, pid=10335, buf="onMessageRefresh")
-trace.add_atrace_begin(ts=2_200, tid=10335, pid=10335, buf="otherFunction")
-trace.add_atrace_begin(ts=2_300, tid=10335, pid=10335, buf="HwcValidateDisplay")
-trace.add_atrace_end(ts=2_400, tid=10335, pid=10335)
-trace.add_atrace_end(ts=2_500, tid=10335, pid=10335)
-trace.add_atrace_begin(ts=2_600, tid=10335, pid=10335, buf="HwcPresentDisplay")
-trace.add_atrace_end(ts=2_700, tid=10335, pid=10335)
-trace.add_atrace_end(ts=2_800, tid=10335, pid=10335)
-
-# skipped validation
-trace.add_atrace_begin(ts=3_100, tid=10335, pid=10335, buf="AnotherFunction")
-trace.add_atrace_begin(ts=3_200, tid=10335, pid=10335, buf="onMessageRefresh")
-trace.add_atrace_begin(ts=3_300, tid=10335, pid=10335, buf="HwcPresentOrValidateDisplay")
-trace.add_atrace_end(ts=3_400, tid=10335, pid=10335)
-trace.add_atrace_end(ts=3_500, tid=10335, pid=10335)
-trace.add_atrace_end(ts=3_600, tid=10335, pid=10335)
-
-# incomplete (ignored)
-trace.add_atrace_begin(ts=4_100, tid=10335, pid=10335, buf="onMessageRefresh")
-trace.add_atrace_begin(ts=4_200, tid=10335, pid=10335, buf="HwcPresentOrValidateDisplay")
-trace.add_atrace_end(ts=4_300, tid=10335, pid=10335)
-trace.add_atrace_begin(ts=4_400, tid=10335, pid=10335, buf="HwcPresentDisplay")
-
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/composer_execution.sql b/test/trace_processor/graphics/composer_execution.sql
deleted file mode 100644
index 874e12b..0000000
--- a/test/trace_processor/graphics/composer_execution.sql
+++ /dev/null
@@ -1,25 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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/composer_execution.sql',
-  'output', 'hwc_execution_spans') AS suppress_query_output;
-
-SELECT
-  validation_type,
-  COUNT(*) as count,
-  SUM(execution_time_ns) as total
-FROM hwc_execution_spans
-GROUP BY validation_type
-ORDER BY validation_type;
diff --git a/test/trace_processor/graphics/composition_layer.py b/test/trace_processor/graphics/composition_layer.py
deleted file mode 100644
index f25aec6..0000000
--- a/test/trace_processor/graphics/composition_layer.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(11, 10, "child_process")
-
-trace.add_ftrace_packet(1)
-
-trace.add_print(ts=99, tid=11, buf='C|10|HWComposer: Total Layer|7')
-trace.add_print(ts=100, tid=11, buf='C|10|HWComposer: Total Layer|5')
-trace.add_print(ts=101, tid=11, buf='C|10|HWComposer: Total Layer|6')
-trace.add_print(ts=102, tid=11, buf='C|10|HWComposer: Total Layer|0')
-trace.add_print(ts=103, tid=11, buf='C|10|HWComposer: Total Layer|4')
-trace.add_print(ts=104, tid=11, buf='C|10|HWComposer: Total Layer|6')
-trace.add_print(ts=105, tid=11, buf='C|10|HWComposer: Total Layer|0')
-trace.add_print(ts=106, tid=11, buf='C|10|HWComposer: Total Layer|4')
-trace.add_print(ts=107, tid=11, buf='C|10|HWComposer: Total Layer|5')
-trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|0')
-trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|3')
-trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|0')
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/composition_layer_count.out b/test/trace_processor/graphics/composition_layer_count.out
deleted file mode 100644
index 6c47b9e..0000000
--- a/test/trace_processor/graphics/composition_layer_count.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"AVG(value)"
-3.000000
diff --git a/test/trace_processor/graphics/composition_layer_count.sql b/test/trace_processor/graphics/composition_layer_count.sql
deleted file mode 100644
index 30a92e6..0000000
--- a/test/trace_processor/graphics/composition_layer_count.sql
+++ /dev/null
@@ -1,19 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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/android_hwcomposer.sql') AS suppress_query_output;
-
-SELECT AVG(value)
-FROM total_layers;
diff --git a/test/trace_processor/graphics/expected_frame_timeline_events.out b/test/trace_processor/graphics/expected_frame_timeline_events.out
deleted file mode 100644
index bbfb5bd..0000000
--- a/test/trace_processor/graphics/expected_frame_timeline_events.out
+++ /dev/null
@@ -1,13 +0,0 @@
-"ts","dur","pid","display_frame_token","surface_frame_token","layer_name"
-20,6,666,2,0,"[NULL]"
-21,15,1000,4,1,"Layer1"
-40,6,666,4,0,"[NULL]"
-41,15,1000,6,5,"Layer1"
-80,6,666,6,0,"[NULL]"
-90,16,1000,8,7,"Layer1"
-120,6,666,8,0,"[NULL]"
-140,6,666,12,0,"[NULL]"
-150,20,1000,15,14,"Layer1"
-170,6,666,15,0,"[NULL]"
-200,6,666,17,0,"[NULL]"
-220,10,666,18,0,"[NULL]"
diff --git a/test/trace_processor/graphics/expected_frame_timeline_events.sql b/test/trace_processor/graphics/expected_frame_timeline_events.sql
deleted file mode 100644
index 31669c2..0000000
--- a/test/trace_processor/graphics/expected_frame_timeline_events.sql
+++ /dev/null
@@ -1,23 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 ts, dur, process.pid as pid, display_frame_token, surface_frame_token, layer_name
-from
-  (select t.*, process_track.name as track_name from
-    process_track left join expected_frame_timeline_slice t
-    on process_track.id = t.track_id) s
-join process using(upid)
-where s.track_name = 'Expected Timeline'
-order by ts
diff --git a/test/trace_processor/graphics/frame_missed.py b/test/trace_processor/graphics/frame_missed.py
deleted file mode 100644
index d08191d..0000000
--- a/test/trace_processor/graphics/frame_missed.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This synthetic trace tests handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(11, 10, "child_process")
-
-trace.add_ftrace_packet(1)
-
-trace.add_print(ts=99, tid=11, buf='C|10|PrevFrameMissed|0')
-trace.add_print(ts=100, tid=11, buf='C|10|PrevFrameMissed|0')
-trace.add_print(ts=101, tid=11, buf='C|10|PrevFrameMissed|1')
-trace.add_print(ts=102, tid=11, buf='C|10|PrevFrameMissed|0')
-trace.add_print(ts=103, tid=11, buf='C|10|PrevFrameMissed|1')
-trace.add_print(ts=104, tid=11, buf='C|10|PrevFrameMissed|1')
-trace.add_print(ts=105, tid=11, buf='C|10|PrevFrameMissed|0')
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/frame_missed_event.sql b/test/trace_processor/graphics/frame_missed_event.sql
deleted file mode 100644
index 4e79c51..0000000
--- a/test/trace_processor/graphics/frame_missed_event.sql
+++ /dev/null
@@ -1,19 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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/android_surfaceflinger.sql') AS suppress_query_output;
-
-SELECT ts, dur
-FROM android_surfaceflinger_event;
\ No newline at end of file
diff --git a/test/trace_processor/graphics/frame_missed_event_frame_missed.out b/test/trace_processor/graphics/frame_missed_event_frame_missed.out
deleted file mode 100644
index 03bdcb3..0000000
--- a/test/trace_processor/graphics/frame_missed_event_frame_missed.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"ts","dur"
-100,1
-102,1
-103,1
diff --git a/test/trace_processor/graphics/frame_missed_metrics.out b/test/trace_processor/graphics/frame_missed_metrics.out
deleted file mode 100644
index ec59e69..0000000
--- a/test/trace_processor/graphics/frame_missed_metrics.out
+++ /dev/null
@@ -1,6 +0,0 @@
-android_surfaceflinger {
-  missed_frames: 3
-  missed_hwc_frames: 0
-  missed_gpu_frames: 0
-  missed_frame_rate: 0.42857142857142855 # = 3/7
-}
diff --git a/test/trace_processor/graphics/frame_timeline_events.py b/test/trace_processor/graphics/frame_timeline_events.py
deleted file mode 100644
index 0dcba8a..0000000
--- a/test/trace_processor/graphics/frame_timeline_events.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-class JankType:
-  JANK_UNSPECIFIED = 0;
-  JANK_NONE = 1;
-  JANK_SF_SCHEDULING = 2;
-  JANK_PREDICTION_ERROR = 4;
-  JANK_DISPLAY_HAL = 8;
-  JANK_SF_CPU_DEADLINE_MISSED = 16;
-  JANK_SF_GPU_DEADLINE_MISSED = 32;
-  JANK_APP_DEADLINE_MISSED = 64;
-  JANK_BUFFER_STUFFING = 128;
-  JANK_UNKNOWN = 256;
-  JANK_SF_STUFFING = 512;
-
-class PresentType:
-  PRESENT_UNSPECIFIED = 0;
-  PRESENT_ON_TIME = 1;
-  PRESENT_LATE = 2;
-  PRESENT_EARLY = 3;
-  PRESENT_DROPPED = 4;
-  PRESENT_UNKNOWN = 5;
-
-class PredictionType:
-  PREDICTION_UNSPECIFIED = 0;
-  PREDICTION_VALID = 1;
-  PREDICTION_EXPIRED = 2;
-  PREDICTION_UNKNOWN = 3;
-
-trace = synth_common.create_trace()
-
-# DisplayFrame without a SurfaceFrame
-trace.add_expected_display_frame_start_event(ts=20, cookie=1, token=2, pid=666)
-trace.add_frame_end_event(ts=26, cookie=1)
-trace.add_actual_display_frame_start_event(ts=20, cookie=2, token=2, pid=666, present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=26, cookie=2)
-
-# DisplayFrame with a SurfaceFrame
-trace.add_expected_display_frame_start_event(ts=40, cookie=3, token=4, pid=666)
-trace.add_frame_end_event(ts=46, cookie=3)
-trace.add_actual_display_frame_start_event(ts=42, cookie=4, token=4, pid=666, present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=47, cookie=4)
-trace.add_expected_surface_frame_start_event(ts=21, cookie=5, token=1, display_frame_token=4, pid=1000, layer_name="Layer1")
-trace.add_frame_end_event(ts=36, cookie=5)
-trace.add_actual_surface_frame_start_event(ts=21, cookie=6, token=1, display_frame_token=4, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=37, cookie=6)
-
-
-# DisplayFrame with a janky SurfaceFrame
-trace.add_expected_display_frame_start_event(ts=80, cookie=7, token=6, pid=666)
-trace.add_frame_end_event(ts=86, cookie=7)
-trace.add_actual_display_frame_start_event(ts=81, cookie=8, token=6, pid=666, present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=88, cookie=8)
-trace.add_expected_surface_frame_start_event(ts=41, cookie=9, token=5, display_frame_token=6, pid=1000, layer_name="Layer1")
-trace.add_frame_end_event(ts=56, cookie=9)
-trace.add_actual_surface_frame_start_event(ts=41, cookie=10, token=5, display_frame_token=6, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_LATE, on_time_finish=0, gpu_composition=0, jank_type=JankType.JANK_APP_DEADLINE_MISSED, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=74, cookie=10)
-
-
-# Janky DisplayFrame with a SurfaceFrame
-trace.add_expected_display_frame_start_event(ts=120, cookie=11, token=8, pid=666)
-trace.add_frame_end_event(ts=126, cookie=11)
-trace.add_actual_display_frame_start_event(ts=108, cookie=12, token=8, pid=666, present_type=PresentType.PRESENT_EARLY, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_SF_SCHEDULING, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=112, cookie=12)
-trace.add_expected_surface_frame_start_event(ts=90, cookie=13, token=7, display_frame_token=8, pid=1000, layer_name="Layer1")
-trace.add_frame_end_event(ts=106, cookie=13)
-trace.add_actual_surface_frame_start_event(ts=90, cookie=14, token=7, display_frame_token=8, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_EARLY, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_SF_SCHEDULING, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=106, cookie=14)
-
-# DisplayFrame with multiple jank reasons
-trace.add_expected_display_frame_start_event(ts=140, cookie=15, token=12, pid=666)
-trace.add_frame_end_event(ts=146, cookie=15)
-trace.add_actual_display_frame_start_event(ts=148, cookie=16, token=12, pid=666, present_type=PresentType.PRESENT_LATE, on_time_finish=0, gpu_composition=0, jank_type=JankType.JANK_SF_CPU_DEADLINE_MISSED | JankType.JANK_SF_SCHEDULING, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=156, cookie=16)
-
-# Two SurfaceFrames with same token
-trace.add_expected_display_frame_start_event(ts=170, cookie=17, token=15, pid=666)
-trace.add_frame_end_event(ts=176, cookie=17)
-trace.add_actual_display_frame_start_event(ts=170, cookie=18, token=15, pid=666, present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=176, cookie=18)
-trace.add_expected_surface_frame_start_event(ts=150, cookie=19, token=14, display_frame_token=15, pid=1000, layer_name="Layer1")
-trace.add_frame_end_event(ts=170, cookie=19)
-trace.add_actual_surface_frame_start_event(ts=150, cookie=20, token=14, display_frame_token=15, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=167, cookie=20)
-trace.add_expected_surface_frame_start_event(ts=150, cookie=21, token=14, display_frame_token=15, pid=1000, layer_name="Layer2")
-trace.add_frame_end_event(ts=170, cookie=21)
-trace.add_actual_surface_frame_start_event(ts=150, cookie=22, token=14, display_frame_token=15, pid=1000, layer_name="Layer2", present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=167, cookie=22)
-
-# SurfaceFrame with prediction expired (no expected timeline packet)
-trace.add_expected_display_frame_start_event(ts=200, cookie=23, token=17, pid=666)
-trace.add_frame_end_event(ts=206, cookie=23)
-trace.add_actual_display_frame_start_event(ts=200, cookie=24, token=17, pid=666, present_type=PresentType.PRESENT_ON_TIME, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_NONE, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=206, cookie=24)
-trace.add_actual_surface_frame_start_event(ts=80, cookie=25, token=16, display_frame_token=17, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_UNKNOWN, on_time_finish=0, gpu_composition=0, jank_type=JankType.JANK_UNKNOWN, prediction_type=PredictionType.PREDICTION_EXPIRED)
-trace.add_frame_end_event(ts=190, cookie=25)
-
-# DisplayFrame with SF Stuffing jank
-trace.add_expected_display_frame_start_event(ts=220, cookie=26, token=18, pid=666)
-trace.add_frame_end_event(ts=230, cookie=26)
-trace.add_actual_display_frame_start_event(ts=245, cookie=27, token=18, pid=666, present_type=PresentType.PRESENT_LATE, on_time_finish=0, gpu_composition=0, jank_type=JankType.JANK_SF_STUFFING, prediction_type=PredictionType.PREDICTION_VALID)
-trace.add_frame_end_event(ts=260, cookie=27)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/g2d_metrics.out b/test/trace_processor/graphics/g2d_metrics.out
deleted file mode 100644
index a28e4fd..0000000
--- a/test/trace_processor/graphics/g2d_metrics.out
+++ /dev/null
@@ -1,40 +0,0 @@
-g2d {
-    g2d_hw {
-        instances {
-            name: "g2d_frame_hw#10"
-            max_dur_ns: 20
-            min_dur_ns: 20
-            avg_dur_ns: 20
-            frame_count: 1
-            error_count: 0
-        }
-        max_dur_ns: 20
-        min_dur_ns: 20
-        avg_dur_ns: 20
-        frame_count: 1
-        error_count: 0
-    }
-    g2d_sw {
-        instances {
-            name: "g2d_frame_sw#10"
-            max_dur_ns: 40
-            min_dur_ns: 20
-            avg_dur_ns: 30
-            frame_count: 2
-            error_count: 0
-        }
-        instances {
-            name: "g2d_frame_sw#11"
-            max_dur_ns: 40
-            min_dur_ns: 40
-            avg_dur_ns: 40
-            frame_count: 1
-            error_count: 2
-        }
-        max_dur_ns: 40
-        min_dur_ns: 20
-        avg_dur_ns: 33
-        frame_count: 3
-        error_count: 2
-    }
-}
diff --git a/test/trace_processor/graphics/g2d_metrics.textproto b/test/trace_processor/graphics/g2d_metrics.textproto
deleted file mode 100644
index 9ed87bf..0000000
--- a/test/trace_processor/graphics/g2d_metrics.textproto
+++ /dev/null
@@ -1,127 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 1000
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1003
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1005
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 1010
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#10"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 1020
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 1030
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#10"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1040
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#10"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 1050
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#10"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 1060
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1070
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#10"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1080
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#10"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 1085
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#11"
-        type: 67
-        value: 1
-      }
-    }
-  }
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 3
-}
\ No newline at end of file
diff --git a/test/trace_processor/graphics/gpu_counters.py b/test/trace_processor/graphics/gpu_counters.py
deleted file mode 100644
index 00ded78..0000000
--- a/test/trace_processor/graphics/gpu_counters.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_log.py b/test/trace_processor/graphics/gpu_log.py
deleted file mode 100644
index f064173..0000000
--- a/test/trace_processor/graphics/gpu_log.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-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")
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_mem_total.out b/test/trace_processor/graphics/gpu_mem_total.out
deleted file mode 100644
index e39c9a0..0000000
--- a/test/trace_processor/graphics/gpu_mem_total.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"name","unit","description","ts","pid","value"
-"GPU Memory","7","Total GPU memory used by the entire system",0,"[NULL]",123
-"GPU Memory","7","Total GPU memory used by this process",0,1,100
-"GPU Memory","7","Total GPU memory used by the entire system",5,"[NULL]",256
-"GPU Memory","7","Total GPU memory used by this process",5,1,233
-"GPU Memory","7","Total GPU memory used by the entire system",10,"[NULL]",123
-"GPU Memory","7","Total GPU memory used by this process",10,1,0
diff --git a/test/trace_processor/graphics/gpu_mem_total.py b/test/trace_processor/graphics/gpu_mem_total.py
deleted file mode 100755
index e21d8a8..0000000
--- a/test/trace_processor/graphics/gpu_mem_total.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-
-# Global gpu_mem_total initial counter event
-trace.add_gpu_mem_total_event(pid=0, ts=0, size=123)
-
-# Global gpu_mem_total ftrace event
-trace.add_ftrace_packet(cpu=0)
-trace.add_gpu_mem_total_ftrace_event(pid=0, ts=5, size=256)
-trace.add_gpu_mem_total_ftrace_event(pid=0, ts=10, size=123)
-
-# gpu_mem_total initial counter event for pid = 1
-trace.add_gpu_mem_total_event(pid=1, ts=0, size=100)
-
-# gpu_mem_total ftrace event for pid = 1
-trace.add_ftrace_packet(cpu=1)
-trace.add_gpu_mem_total_ftrace_event(pid=1, ts=5, size=233)
-trace.add_gpu_mem_total_ftrace_event(pid=1, ts=10, size=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_mem_total.sql b/test/trace_processor/graphics/gpu_mem_total.sql
deleted file mode 100644
index be985aa..0000000
--- a/test/trace_processor/graphics/gpu_mem_total.sql
+++ /dev/null
@@ -1,6 +0,0 @@
-SELECT ct.name, ct.unit, ct.description, c.ts, p.pid, CAST(c.value as INT) as value
-FROM counter_track ct
-LEFT JOIN process_counter_track pct USING (id)
-LEFT JOIN process p USING (upid)
-LEFT JOIN counter c ON c.track_id = ct.id
-ORDER BY ts
diff --git a/test/trace_processor/graphics/gpu_metric.out b/test/trace_processor/graphics/gpu_metric.out
deleted file mode 100644
index d0ca395..0000000
--- a/test/trace_processor/graphics/gpu_metric.out
+++ /dev/null
@@ -1,17 +0,0 @@
-android_gpu {
-  processes {
-    name: "app_1"
-    mem_max: 8
-    mem_min: 2
-    mem_avg: 3
-  }
-  processes {
-    name: "app_2"
-    mem_max: 10
-    mem_min: 6
-    mem_avg: 8
-  }
-  mem_max: 4
-  mem_min: 1
-  mem_avg: 2
-}
diff --git a/test/trace_processor/graphics/gpu_metric.py b/test/trace_processor/graphics/gpu_metric.py
deleted file mode 100644
index 8179d08..0000000
--- a/test/trace_processor/graphics/gpu_metric.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, "app_1")
-trace.add_process(2, 0, "app_2")
-trace.add_process(3, 0, "app_2")
-
-trace.add_ftrace_packet(cpu=0)
-
-# max=4, min=1, avg=(2*1+5*2+(10-9)*4)/(10-2)=2
-trace.add_gpu_mem_total_ftrace_event(pid=0, ts=2, size=1)
-trace.add_gpu_mem_total_ftrace_event(pid=0, ts=4, size=2)
-trace.add_gpu_mem_total_ftrace_event(pid=0, ts=9, size=4)
-
-# max=8, min=2, avg=(5*2+(10-9)*8)/(10-4)=3
-trace.add_gpu_mem_total_ftrace_event(pid=1, ts=4, size=2)
-trace.add_gpu_mem_total_ftrace_event(pid=1, ts=9, size=8)
-
-# max=8, min=6, avgxdur=2*6+(10-4)*8=60, dur=2+(10-4)=8
-trace.add_gpu_mem_total_ftrace_event(pid=2, ts=2, size=6)
-trace.add_gpu_mem_total_ftrace_event(pid=2, ts=4, size=8)
-
-# max=10, min=7, avgxdur=1*7+(10-7)*10=37, dur=1+(10-7)=4
-trace.add_gpu_mem_total_ftrace_event(pid=3, ts=6, size=7)
-trace.add_gpu_mem_total_ftrace_event(pid=3, ts=7, size=10)
-
-# app_2 will be aggregated
-# max=10, min=6, avg=(60+37)/(8+4)=8
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_render_stages.out b/test/trace_processor/graphics/gpu_render_stages.out
deleted file mode 100644
index da72f32..0000000
--- a/test/trace_processor/graphics/gpu_render_stages.out
+++ /dev/null
@@ -1,22 +0,0 @@
-"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","render_target_name","render_pass","render_pass_name","command_buffer","command_buffer_name","submission_id","hw_queue_id","render_subpasses"
-"queue 1","queue desc 1",0,5,"render stage(1)",0,"[NULL]","[NULL]",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1,"[NULL]"
-"queue 0","queue desc 0",0,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 1","queue desc 1",10,5,"stage 1",0,"description","stage desc 1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1,"[NULL]"
-"queue 2","[NULL]",20,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,2,"[NULL]"
-"queue 0","queue desc 0",30,5,"stage 3",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"Unknown GPU Queue 3","[NULL]",40,5,"render stage(4)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,3,"[NULL]"
-"queue 0","queue desc 0",50,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",60,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",60,5,"stage 0",0,"key2","value2",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",70,5,"stage 0",0,"key1","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",80,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",90,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",32,"[NULL]",48,"[NULL]",0,0,"[NULL]"
-"queue 0","queue desc 0",100,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"[NULL]",16,"command_buffer",0,0,"[NULL]"
-"queue 0","queue desc 0",110,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"render_pass",16,"command_buffer",0,0,"[NULL]"
-"queue 0","queue desc 0",120,5,"stage 0",0,"[NULL]","[NULL]",42,16,"framebuffer",16,"render_pass",16,"command_buffer",0,0,"[NULL]"
-"queue 0","queue desc 0",130,5,"stage 0",0,"[NULL]","[NULL]",42,16,"renamed_buffer",0,"[NULL]",0,"[NULL]",0,0,"[NULL]"
-"Unknown GPU Queue ","[NULL]",140,5,"render stage(18446744073709551615)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1024,"[NULL]"
-"queue 0","queue desc 0",150,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"0"
-"queue 0","queue desc 0",160,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"63,64"
-"queue 0","queue desc 0",170,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"64"
-"queue 0","queue desc 0",180,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0,"3,68,69,70,71"
diff --git a/test/trace_processor/graphics/gpu_render_stages.py b/test/trace_processor/graphics/gpu_render_stages.py
deleted file mode 100644
index b2fc239..0000000
--- a/test/trace_processor/graphics/gpu_render_stages.py
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Add a slice before any Specification packet is received.
-trace.add_gpu_render_stages(
-    ts=0, event_id=0, duration=5, hw_queue_id=1, stage_id=1, context=0)
-
-trace.add_gpu_render_stages_stage_spec([{
-    'name': 'stage 0'
-}, {
-    'name': 'stage 1',
-    'description': 'stage desc 1'
-}, {
-    'name': 'stage 2'
-}, {
-    'name': 'stage 3'
-}])
-
-trace.add_gpu_render_stages_hw_queue_spec([{
-    'name': 'queue 0',
-    'description': 'queue desc 0'
-}, {
-    'name': 'queue 1',
-    'description': 'queue desc 1'
-}, {
-    'name': 'queue 2',
-}])
-
-# Add some track to make sure Specification works properly
-trace.add_gpu_render_stages(
-    ts=0, event_id=0, duration=5, hw_queue_id=0, stage_id=0, context=42)
-trace.add_gpu_render_stages(
-    ts=10, event_id=1, duration=5, hw_queue_id=1, stage_id=1, context=42)
-trace.add_gpu_render_stages(
-    ts=20, event_id=2, duration=5, hw_queue_id=2, stage_id=2, context=42)
-trace.add_gpu_render_stages(
-    ts=30, event_id=3, duration=5, hw_queue_id=0, stage_id=3, context=42)
-# Add a track without Specification for hw_queue_id/stage_id.
-trace.add_gpu_render_stages(
-    ts=40, event_id=3, duration=5, hw_queue_id=3, stage_id=4, context=42)
-
-# Test extra_data
-# event with single arg.
-trace.add_gpu_render_stages(
-    ts=50,
-    event_id=5,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    extra_data={'key1': 'value1'})
-# event with multiple args.
-trace.add_gpu_render_stages(
-    ts=60,
-    event_id=6,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    extra_data={
-        'key1': 'value1',
-        'key2': 'value2'
-    })
-# event with args that only has key, but no value.
-trace.add_gpu_render_stages(
-    ts=70,
-    event_id=7,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    extra_data={'key1': None})
-
-##############################################
-# Test stage naming with render target handle.
-
-VK_OBJECT_TYPE_COMMAND_BUFFER = 6
-VK_OBJECT_TYPE_RENDER_PASS = 18
-VK_OBJECT_TYPE_FRAMEBUFFER = 24
-
-trace.add_gpu_render_stages(
-    ts=80, event_id=8, duration=5, hw_queue_id=0, stage_id=2, context=42)
-
-# add render stage with render target handle without debug marker.
-trace.add_gpu_render_stages(
-    ts=90,
-    event_id=9,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_target_handle=0x10,
-    render_pass_handle=0x20,
-    command_buffer_handle=0x30)
-
-# adding a marker with COMMAND_BUFFER and RENDER_PASS should affect only the
-# relevant handles.
-trace.add_vk_debug_marker(
-    ts=91,
-    pid=100,
-    vk_device=1,
-    obj_type=VK_OBJECT_TYPE_COMMAND_BUFFER,
-    obj=0x10,
-    obj_name="command_buffer")
-trace.add_gpu_render_stages(
-    ts=100,
-    event_id=10,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_target_handle=0x10,
-    render_pass_handle=0x10,
-    command_buffer_handle=0x10)
-
-trace.add_vk_debug_marker(
-    ts=101,
-    pid=100,
-    vk_device=1,
-    obj_type=VK_OBJECT_TYPE_RENDER_PASS,
-    obj=0x10,
-    obj_name="render_pass")
-trace.add_gpu_render_stages(
-    ts=110,
-    event_id=10,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_target_handle=0x10,
-    render_pass_handle=0x10,
-    command_buffer_handle=0x10)
-
-# adding a marker with FRAMEBUFFER changes the name of the stage as well.
-trace.add_vk_debug_marker(
-    ts=111,
-    pid=100,
-    vk_device=1,
-    obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
-    obj=0x10,
-    obj_name="framebuffer")
-trace.add_gpu_render_stages(
-    ts=120,
-    event_id=10,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_target_handle=0x10,
-    render_pass_handle=0x10,
-    command_buffer_handle=0x10)
-
-# setting the name again replace the name
-trace.add_vk_debug_marker(
-    ts=121,
-    pid=100,
-    vk_device=1,
-    obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
-    obj=0x10,
-    obj_name="renamed_buffer")
-trace.add_gpu_render_stages(
-    ts=130,
-    event_id=11,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_target_handle=0x10)
-
-# Check that a hw_queue_id=-1 doesn't blow up.
-trace.add_gpu_render_stages(
-    ts=140, event_id=12, duration=5, hw_queue_id=-1, stage_id=-1, context=42)
-
-# test render_subpass_index_mask
-trace.add_gpu_render_stages(
-    ts=150,
-    event_id=12,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_subpass_index_mask=[0x01])
-trace.add_gpu_render_stages(
-    ts=160,
-    event_id=13,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_subpass_index_mask=[0x8000000000000000, 0x01])
-trace.add_gpu_render_stages(
-    ts=170,
-    event_id=14,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_subpass_index_mask=[0, 0x1])
-trace.add_gpu_render_stages(
-    ts=180,
-    event_id=14,
-    duration=5,
-    hw_queue_id=0,
-    stage_id=0,
-    context=42,
-    render_subpass_index_mask=[0x08, 0xF0])
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_render_stages.sql b/test/trace_processor/graphics/gpu_render_stages.sql
deleted file mode 100644
index 50b887c..0000000
--- a/test/trace_processor/graphics/gpu_render_stages.sql
+++ /dev/null
@@ -1,24 +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 track.name AS track_name, gpu_track.description AS track_desc, ts, dur,
-    gpu_slice.name AS slice_name, depth, flat_key, string_value,
-    gpu_slice.context_id, render_target, render_target_name, render_pass, render_pass_name,
-    command_buffer, command_buffer_name, submission_id, hw_queue_id, render_subpasses
-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/gpu_render_stages_interned_spec.out b/test/trace_processor/graphics/gpu_render_stages_interned_spec.out
deleted file mode 100644
index 05afa4d..0000000
--- a/test/trace_processor/graphics/gpu_render_stages_interned_spec.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","render_target_name","render_pass","render_pass_name","command_buffer","command_buffer_name","submission_id","hw_queue_id","render_subpasses"
-"vertex","vertex queue",100,10,"binning",0,"description","binning graphics",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1,"[NULL]"
-"fragment","fragment queue",200,10,"render",0,"description","render graphics",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,2,"[NULL]"
-"queue2","queue2 description",300,10,"render",0,"description","render graphics",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1,"[NULL]"
diff --git a/test/trace_processor/graphics/gpu_render_stages_interned_spec.textproto b/test/trace_processor/graphics/gpu_render_stages_interned_spec.textproto
deleted file mode 100644
index 08c2e41..0000000
--- a/test/trace_processor/graphics/gpu_render_stages_interned_spec.textproto
+++ /dev/null
@@ -1,126 +0,0 @@
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  interned_data {
-    graphics_contexts {
-      iid: 0
-      pid: 42
-      api: VULKAN
-    }
-  }
-  sequence_flags: 1  # SEQ_INCREMENTAL_STATE_CLEARED
-}
-
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  interned_data {
-    gpu_specifications {
-      iid: 1
-      name: "vertex"
-      description: "vertex queue"
-      category: GRAPHICS
-    }
-    gpu_specifications {
-      iid: 2
-      name: "fragment"
-      description: "fragment queue"
-      category: GRAPHICS
-    }
-  }
-}
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  interned_data {
-    gpu_specifications {
-      iid: 3
-      name: "binning"
-      description: "binning graphics"
-      category: GRAPHICS
-    }
-    gpu_specifications {
-      iid: 4
-      name: "render"
-      description: "render graphics"
-      category: GRAPHICS
-    }
-  }
-}
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 2
-  timestamp: 300
-  interned_data {
-    gpu_specifications {
-      iid: 1
-      name: "queue2"
-      description: "queue2 description"
-      category: COMPUTE
-    }
-    gpu_specifications {
-      iid: 2
-      name: "render"
-      description: "render graphics"
-      category: GRAPHICS
-    }
-  }
-  sequence_flags: 1  # SEQ_INCREMENTAL_STATE_CLEARED
-}
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 1
-  timestamp: 100
-  gpu_render_stage_event {
-    event_id: 0
-    duration: 10
-    hw_queue_iid: 1
-    stage_iid: 3
-    context: 0
-  }
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-}
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 1
-  timestamp: 200
-  gpu_render_stage_event {
-    event_id: 0
-    duration: 10
-    hw_queue_iid: 2
-    stage_iid: 4
-    context: 0
-  }
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-}
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 2
-  timestamp: 300
-  gpu_render_stage_event {
-    event_id: 0
-    duration: 10
-    hw_queue_iid: 1
-    stage_iid: 2
-    context: 0
-  }
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-}
-
-# Test packet with invalid hw_queue_iid is ignore.
-packet {
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 2
-  timestamp: 300
-  gpu_render_stage_event {
-    event_id: 0
-    duration: 10
-    hw_queue_iid: 3
-    stage_iid: 2
-    context: 0
-  }
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-}
diff --git a/test/trace_processor/graphics/graphics_frame_events.out b/test/trace_processor/graphics/graphics_frame_events.out
deleted file mode 100644
index be781b8..0000000
--- a/test/trace_processor/graphics/graphics_frame_events.out
+++ /dev/null
@@ -1,50 +0,0 @@
-"ts","track_name","dur","slice_name","frame_number","layer_name"
-1,"Buffer: 1 layer1",0,"Dequeue",11,"layer1"
-1,"APP_1 layer1",3,"11",11,"layer1"
-4,"Buffer: 1 layer1",0,"Queue",11,"layer1"
-4,"GPU_1 layer1",2,"11",11,"layer1"
-6,"Buffer: 1 layer1",0,"AcquireFenceSignaled",11,"layer1"
-6,"Buffer: 2 layer2",0,"Dequeue",12,"layer2"
-6,"APP_2 layer2",3,"12",12,"layer2"
-7,"Buffer: 7 layer7",0,"unknown_event",15,"layer7"
-8,"Buffer: 1 layer1",0,"Latch",11,"layer1"
-8,"Buffer: 2 layer2",0,"AcquireFenceSignaled",12,"layer2"
-8,"SF_1 layer1",6,"11",11,"layer1"
-9,"Buffer: 2 layer2",0,"Queue",12,"layer2"
-11,"Buffer: 2 layer2",0,"Latch",12,"layer2"
-11,"SF_2 layer2",5,"12",12,"layer2"
-14,"Buffer: 1 layer1",0,"PresentFenceSignaled",11,"layer1"
-14,"Display_layer1",10,"11",11,"layer1"
-16,"Buffer: 2 layer2",0,"PresentFenceSignaled",12,"layer2"
-16,"Display_layer2",-1,"12",12,"layer2"
-24,"Buffer: 1 layer1",0,"PresentFenceSignaled",13,"layer1"
-24,"Display_layer1",-1,"13",13,"layer1"
-31,"Buffer: 1 layer1",0,"Dequeue",21,"layer1"
-31,"APP_1 layer1",3,"21",21,"layer1"
-34,"Buffer: 1 layer1",0,"Queue",21,"layer1"
-34,"GPU_1 layer1",-1,"21",21,"layer1"
-37,"Buffer: 1 layer1",0,"Dequeue",22,"layer1"
-37,"APP_1 layer1",4,"22",22,"layer1"
-41,"Buffer: 1 layer1",0,"Queue",22,"layer1"
-41,"GPU_1 layer1",5,"22",22,"layer1"
-46,"Buffer: 1 layer1",0,"AcquireFenceSignaled",22,"layer1"
-53,"Buffer: 2 layer2",0,"Dequeue",24,"layer2"
-53,"APP_2 layer2",-1,"0",0,"layer2"
-59,"Buffer: 2 layer2",0,"AcquireFenceSignaled",24,"layer2"
-61,"Buffer: 2 layer2",0,"Latch",24,"layer2"
-61,"SF_2 layer2",-1,"24",24,"layer2"
-63,"Buffer: 1 layer1",0,"Dequeue",25,"layer1"
-63,"APP_1 layer1",-1,"0",0,"layer1"
-73,"Buffer: 1 layer1",0,"Dequeue",26,"layer1"
-73,"APP_1 layer1",2,"26",26,"layer1"
-75,"Buffer: 1 layer1",0,"Queue",26,"layer1"
-75,"GPU_1 layer1",4,"26",26,"layer1"
-79,"Buffer: 1 layer1",0,"AcquireFenceSignaled",26,"layer1"
-81,"Buffer: 1 layer1",0,"Dequeue",30,"layer1"
-81,"APP_1 layer1",2,"30",30,"layer1"
-83,"Buffer: 1 layer1",0,"Queue",30,"layer1"
-83,"GPU_1 layer1",-1,"30",30,"layer1"
-90,"Buffer: 1 layer2",0,"Dequeue",35,"layer2"
-90,"APP_1 layer2",2,"35",35,"layer2"
-92,"Buffer: 1 layer2",0,"Queue",35,"layer2"
-92,"GPU_1 layer2",-1,"35",35,"layer2"
diff --git a/test/trace_processor/graphics/graphics_frame_events.py b/test/trace_processor/graphics/graphics_frame_events.py
deleted file mode 100755
index 1344c3f..0000000
--- a/test/trace_processor/graphics/graphics_frame_events.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-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()
-# Layer 1
-trace.add_buffer_event_packet(ts=1, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=4, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=6, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
-trace.add_buffer_event_packet(ts=8, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.LATCH, duration=0)
-trace.add_buffer_event_packet(ts=14, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.PRESENT_FENCE, duration=0)
-# Layer 2
-trace.add_buffer_event_packet(ts=6, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=8, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
-trace.add_buffer_event_packet(ts=9, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=11, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.LATCH, duration=0)
-trace.add_buffer_event_packet(ts=16, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.PRESENT_FENCE, duration=0)
-# Next Present of layer 1
-trace.add_buffer_event_packet(ts=24, buffer_id=1, layer_name="layer1", frame_number=13, event_type=BufferEvent.PRESENT_FENCE, duration=0)
-# Missing id.
-trace.add_buffer_event_packet(ts=6, buffer_id=-1, layer_name="layer6", frame_number=14, event_type=BufferEvent.HWC_COMPOSITION_QUEUED, duration=0)
-# Missing type.
-trace.add_buffer_event_packet(ts=7, buffer_id=7, layer_name="layer7", frame_number=15, event_type=-1, duration=0)
-# Missing Acquire
-trace.add_buffer_event_packet(ts=31, buffer_id=1, layer_name="layer1", frame_number=21, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=34, buffer_id=1, layer_name="layer1", frame_number=21, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=37, buffer_id=1, layer_name="layer1", frame_number=22, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=41, buffer_id=1, layer_name="layer1", frame_number=22, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=46, buffer_id=1, layer_name="layer1", frame_number=22, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
-# Missing queue with acquire
-trace.add_buffer_event_packet(ts=53, buffer_id=2, layer_name="layer2", frame_number=24, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=59, buffer_id=2, layer_name="layer2", frame_number=24, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
-trace.add_buffer_event_packet(ts=61, buffer_id=2, layer_name="layer2", frame_number=24, event_type=BufferEvent.LATCH, duration=0)
-# Missing queue without acquire
-trace.add_buffer_event_packet(ts=63, buffer_id=1, layer_name="layer1", frame_number=25, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=73, buffer_id=1, layer_name="layer1", frame_number=26, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=75, buffer_id=1, layer_name="layer1", frame_number=26, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=79, buffer_id=1, layer_name="layer1", frame_number=26, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
-# Same buffer in multiple layers
-trace.add_buffer_event_packet(ts=81, buffer_id=1, layer_name="layer1", frame_number=30, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=83, buffer_id=1, layer_name="layer1", frame_number=30, event_type=BufferEvent.QUEUE, duration=0)
-trace.add_buffer_event_packet(ts=90, buffer_id=1, layer_name="layer2", frame_number=35, event_type=BufferEvent.DEQUEUE, duration=0)
-trace.add_buffer_event_packet(ts=92, buffer_id=1, layer_name="layer2", frame_number=35, event_type=BufferEvent.QUEUE, duration=0)
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/index b/test/trace_processor/graphics/index
deleted file mode 100644
index c479dea..0000000
--- a/test/trace_processor/graphics/index
+++ /dev/null
@@ -1,48 +0,0 @@
-# Contains tests for graphics related events and tables.
-
-# GPU trace tests.
-gpu_counters.py gpu_counters.sql gpu_counters.out
-gpu_counter_specs.textproto gpu_counter_specs.sql gpu_counter_specs.out
-gpu_render_stages.py gpu_render_stages.sql gpu_render_stages.out
-gpu_render_stages_interned_spec.textproto gpu_render_stages.sql gpu_render_stages_interned_spec.out
-vulkan_api_events.py vulkan_api_events.sql vulkan_api_events.out
-gpu_log.py gpu_log.sql gpu_log.out
-
-# Graphics frame event trace tests.
-graphics_frame_events.py graphics_frame_events.sql graphics_frame_events.out
-
-# GPU Memory ftrace packets
-gpu_mem_total.py gpu_mem_total.sql gpu_mem_total.out
-
-# Clock sync
-clock_sync.py clock_sync.sql clock_sync.out
-
-# Missed frames
-frame_missed.py frame_missed_event.sql frame_missed_event_frame_missed.out
-frame_missed.py android_surfaceflinger frame_missed_metrics.out
-
-# GPU metrics
-gpu_metric.py android_gpu gpu_metric.out
-
-# Android SysUI CUJs metrics
-android_sysui_cuj.py android_sysui_cuj android_sysui_cuj.out
-android_sysui_cuj.py android_sysui_cuj_event.sql android_sysui_cuj_event.out
-
-# Frame Timeline event trace tests
-frame_timeline_events.py expected_frame_timeline_events.sql expected_frame_timeline_events.out
-frame_timeline_events.py actual_frame_timeline_events.sql actual_frame_timeline_events.out
-
-# Composition layer
-composition_layer.py composition_layer_count.sql composition_layer_count.out
-
-# Android Jank metrics
-android_jank.py android_jank android_jank.out
-
-# G2D metrics
-g2d_metrics.textproto g2d g2d_metrics.out
-
-# Composer execution
-composer_execution.py composer_execution.sql composer_execution.out
-
-# Display metrics
-panel_fps.py display_metrics panel_fps.out
diff --git a/test/trace_processor/graphics/panel_fps.out b/test/trace_processor/graphics/panel_fps.out
deleted file mode 100644
index c4e06d9..0000000
--- a/test/trace_processor/graphics/panel_fps.out
+++ /dev/null
@@ -1,24 +0,0 @@
-display_metrics {
-  total_duplicate_frames: 0
-  duplicate_frames_logged: 0
-  total_dpu_underrun_count: 0
-  refresh_rate_switches: 5
-  refresh_rate_stats {
-    refresh_rate_fps: 60
-    count: 2
-    total_dur_ms: 2
-    avg_dur_ms: 1
-  }
-  refresh_rate_stats {
-    refresh_rate_fps: 90
-    count: 2
-    total_dur_ms: 2
-    avg_dur_ms: 1
-  }
-  refresh_rate_stats {
-    refresh_rate_fps: 120
-    count: 1
-    total_dur_ms: 2
-    avg_dur_ms: 2
-  }
-}
diff --git a/test/trace_processor/graphics/panel_fps.py b/test/trace_processor/graphics/panel_fps.py
deleted file mode 100644
index 0c9e293..0000000
--- a/test/trace_processor/graphics/panel_fps.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This synthetic trace tests handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(11, 10, "child_process")
-
-trace.add_ftrace_packet(1)
-
-trace.add_print(ts=99_000_000, tid=11, buf='C|10|panel_fps|60')
-trace.add_print(ts=100_000_000, tid=11, buf='C|10|panel_fps|90')
-trace.add_print(ts=101_000_000, tid=11, buf='C|10|panel_fps|60')
-trace.add_print(ts=102_000_000, tid=11, buf='C|10|panel_fps|120')
-
-# The duplicated fps will be ignored
-trace.add_print(ts=103_000_000, tid=11, buf='C|10|panel_fps|120')
-
-trace.add_print(ts=104_000_000, tid=11, buf='C|10|panel_fps|90')
-
-# The last fps and its following duplicates will be ignored, and will
-# only be used for the calculation of duration of the previous fps
-trace.add_print(ts=105_000_000, tid=11, buf='C|10|panel_fps|24')
-trace.add_print(ts=106_000_000, tid=11, buf='C|10|panel_fps|24')
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/vulkan_api_events.py b/test/trace_processor/graphics/vulkan_api_events.py
deleted file mode 100644
index 0fe4ef0..0000000
--- a/test/trace_processor/graphics/vulkan_api_events.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_vk_queue_submit(
-    ts=10,
-    dur=2,
-    pid=42,
-    tid=43,
-    vk_queue=10,
-    vk_command_buffers=[100],
-    submission_id=1)
-
-trace.add_vk_queue_submit(
-    ts=20,
-    dur=2,
-    pid=44,
-    tid=45,
-    vk_queue=11,
-    vk_command_buffers=[200, 300, 400],
-    submission_id=2)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics_frame_events.out b/test/trace_processor/graphics_frame_events.out
new file mode 100644
index 0000000..8aca540
--- /dev/null
+++ b/test/trace_processor/graphics_frame_events.out
@@ -0,0 +1,21 @@
+"ts","track_name","dur","slice_name","frame_number","layer_name"
+1,"Buffer: 1",0,"Dequeue",11,"layer1"
+1,"APP_1",3,"11",11,"layer1"
+4,"Buffer: 1",0,"Queue",11,"layer1"
+4,"GPU_1",2,"11",11,"layer1"
+6,"Buffer: 1",0,"AcquireFenceSignaled",11,"layer1"
+6,"Buffer: 2",0,"Dequeue",12,"layer2"
+6,"APP_2",3,"12",12,"layer2"
+7,"Buffer: 7",0,"unknown_event",15,"layer7"
+8,"Buffer: 1",0,"Latch",11,"layer1"
+8,"Buffer: 2",0,"AcquireFenceSignaled",12,"layer2"
+8,"SF_1",6,"11",11,"layer1"
+9,"Buffer: 2",0,"Queue",12,"layer2"
+11,"Buffer: 2",0,"Latch",12,"layer2"
+11,"SF_2",5,"12",12,"layer2"
+14,"Buffer: 1",0,"PresentFenceSignaled",11,"layer1"
+14,"Display_layer1",10,"11",11,"layer1"
+16,"Buffer: 2",0,"PresentFenceSignaled",12,"layer2"
+16,"Display_layer2",-1,"12",12,"layer2"
+24,"Buffer: 1",0,"PresentFenceSignaled",13,"layer1"
+24,"Display_layer1",-1,"13",13,"layer1"
diff --git a/test/trace_processor/graphics_frame_events.py b/test/trace_processor/graphics_frame_events.py
new file mode 100755
index 0000000..beaf23a
--- /dev/null
+++ b/test/trace_processor/graphics_frame_events.py
@@ -0,0 +1,55 @@
+#!/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()
+# Layer 1
+trace.add_buffer_event_packet(ts=1, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.DEQUEUE, duration=0)
+trace.add_buffer_event_packet(ts=4, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.QUEUE, duration=0)
+trace.add_buffer_event_packet(ts=6, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
+trace.add_buffer_event_packet(ts=8, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.LATCH, duration=0)
+trace.add_buffer_event_packet(ts=14, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.PRESENT_FENCE, duration=0)
+# Layer 2
+trace.add_buffer_event_packet(ts=6, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.DEQUEUE, duration=0)
+trace.add_buffer_event_packet(ts=8, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.ACQUIRE_FENCE, duration=0)
+trace.add_buffer_event_packet(ts=9, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.QUEUE, duration=0)
+trace.add_buffer_event_packet(ts=11, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.LATCH, duration=0)
+trace.add_buffer_event_packet(ts=16, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.PRESENT_FENCE, duration=0)
+# Next Present of layer 1
+trace.add_buffer_event_packet(ts=24, buffer_id=1, layer_name="layer1", frame_number=13, event_type=BufferEvent.PRESENT_FENCE, duration=0)
+# Missing id.
+trace.add_buffer_event_packet(ts=6, buffer_id=-1, layer_name="layer6", frame_number=14, event_type=BufferEvent.HWC_COMPOSITION_QUEUED, duration=0)
+# Missing type.
+trace.add_buffer_event_packet(ts=7, buffer_id=7, layer_name="layer7", frame_number=15, event_type=-1, duration=0)
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/graphics_frame_events.sql b/test/trace_processor/graphics_frame_events.sql
similarity index 100%
rename from test/trace_processor/graphics/graphics_frame_events.sql
rename to test/trace_processor/graphics_frame_events.sql
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
new file mode 100644
index 0000000..b0a304d
--- /dev/null
+++ b/test/trace_processor/heap_graph.textproto
@@ -0,0 +1,155 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+packet {
+  timestamp: 1
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 0
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  timestamp: 10
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 3000
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+      object_ids: 0x05
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+      reference_field_id: 1
+      reference_object_id: 0x02
+      reference_field_id: 3
+      reference_object_id: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    objects {
+      id: 0x05
+      type_id: 4
+      self_size: 256
+    }
+    objects {
+      id: 0x06
+      type_id: 5
+      self_size: 256
+    }
+    continued: true
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    location_names {
+      iid: 1
+      str: "/data/app/ASDFG/invalid.test.android-SDASD/test.apk"
+    }
+    types {
+      id: 1
+      class_name: "FactoryProducerDelegateImplActor"
+      location_id: 1
+    }
+    types {
+      id: 2
+      class_name: "Foo"
+      location_id: 1
+    }
+    types {
+      id: 3
+      class_name: "a"
+      location_id: 1
+    }
+    types {
+      id: 4
+      class_name: "a[]"
+      location_id: 1
+    }
+    types {
+      id: 5
+      class_name: "java.lang.Class<a[]>"
+      location_id: 1
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "int a.a"
+    }
+    field_names {
+      iid: 3
+      str: "a.b"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.test.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+      obfuscated_members {
+        obfuscated_name: "b"
+        deobfuscated_name: "Other.deobfuscatedA"
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/heap_graph_baseapk.textproto b/test/trace_processor/heap_graph_baseapk.textproto
new file mode 100644
index 0000000..e0ea8e9
--- /dev/null
+++ b/test/trace_processor/heap_graph_baseapk.textproto
@@ -0,0 +1,155 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+packet {
+  timestamp: 1
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 0
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  timestamp: 10
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 3000
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+      object_ids: 0x05
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+      reference_field_id: 1
+      reference_object_id: 0x02
+      reference_field_id: 3
+      reference_object_id: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    objects {
+      id: 0x05
+      type_id: 4
+      self_size: 256
+    }
+    objects {
+      id: 0x06
+      type_id: 5
+      self_size: 256
+    }
+    continued: true
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    location_names {
+      iid: 1
+      str: "base.apk!classes.dex"
+    }
+    types {
+      id: 1
+      class_name: "FactoryProducerDelegateImplActor"
+      location_id: 1
+    }
+    types {
+      id: 2
+      class_name: "Foo"
+      location_id: 1
+    }
+    types {
+      id: 3
+      class_name: "a"
+      location_id: 1
+    }
+    types {
+      id: 4
+      class_name: "a[]"
+      location_id: 1
+    }
+    types {
+      id: 5
+      class_name: "java.lang.Class<a[]>"
+      location_id: 1
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "int a.a"
+    }
+    field_names {
+      iid: 3
+      str: "a.b"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.test.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+      obfuscated_members {
+        obfuscated_name: "b"
+        deobfuscated_name: "Other.deobfuscatedA"
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/heap_graph_branching.textproto b/test/trace_processor/heap_graph_branching.textproto
new file mode 100644
index 0000000..d876fd0
--- /dev/null
+++ b/test/trace_processor/heap_graph_branching.textproto
@@ -0,0 +1,95 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+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: 100
+      reference_field_id: 1
+      reference_object_id: 0x02
+      reference_field_id: 1
+      reference_object_id: 0x04
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 200
+      reference_field_id: 1
+      reference_object_id: 0x03
+    }
+    objects {
+      id: 0x03
+      type_id: 3
+      self_size: 400
+    }
+    objects {
+      id: 0x04
+      type_id: 4
+      self_size: 800
+      reference_field_id: 1
+      reference_object_id: 0x05
+    }
+    objects {
+      id: 0x05
+      type_id: 5
+      self_size: 1600
+    }
+    continued: true
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  heap_graph {
+    pid: 2
+    type_names {
+      iid: 1
+      str: "RootNode"
+    }
+    type_names {
+      iid: 2
+      str: "LeftChild0"
+    }
+    type_names {
+      iid: 3
+      str: "LeftChild1"
+    }
+    type_names {
+      iid: 4
+      str: "RightChild0"
+    }
+    type_names {
+      iid: 5
+      str: "RightChild1"
+    }
+    field_names {
+      iid: 1
+      str: "Node.next"
+    }
+    continued: false
+    index: 1
+  }
+}
+
diff --git a/test/trace_processor/heap_graph_flamegraph.out b/test/trace_processor/heap_graph_flamegraph.out
new file mode 100644
index 0000000..8ee3f57
--- /dev/null
+++ b/test/trace_processor/heap_graph_flamegraph.out
@@ -0,0 +1,4 @@
+"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
+0,0,"FactoryProducerDelegateImplActor","JAVA",1,2,64,96,"[NULL]"
+1,1,"Foo","JAVA",1,1,32,32,0
+2,0,"DeobfuscatedA[]","JAVA",1,1,256,256,"[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_flamegraph.sql b/test/trace_processor/heap_graph_flamegraph.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_flamegraph.sql
rename to test/trace_processor/heap_graph_flamegraph.sql
diff --git a/test/trace_processor/heap_graph_flamegraph_focused.out b/test/trace_processor/heap_graph_flamegraph_focused.out
new file mode 100644
index 0000000..bb26353
--- /dev/null
+++ b/test/trace_processor/heap_graph_flamegraph_focused.out
@@ -0,0 +1,4 @@
+"id","depth","name","count","cumulative_count","size","cumulative_size","parent_id"
+0,0,"RootNode",1,3,100,700,"[NULL]"
+1,1,"LeftChild0",1,2,200,600,0
+2,2,"LeftChild1",1,1,400,400,1
diff --git a/test/trace_processor/profiling/heap_graph_flamegraph_focused.sql b/test/trace_processor/heap_graph_flamegraph_focused.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_flamegraph_focused.sql
rename to test/trace_processor/heap_graph_flamegraph_focused.sql
diff --git a/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out b/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out
new file mode 100644
index 0000000..8f822d1
--- /dev/null
+++ b/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out
@@ -0,0 +1,11 @@
+"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
+0,0,"java.lang.Class<boolean>","JAVA",2,4,240,276,"[NULL]"
+1,1,"java.lang.Object[]","JAVA",1,1,12,12,0
+2,1,"java.lang.String","JAVA",1,1,24,24,0
+3,0,"java.lang.Class<byte>","JAVA",3,4,360,384,"[NULL]"
+4,1,"java.lang.String","JAVA",1,1,24,24,3
+5,0,"java.lang.Class<short>","JAVA",2,3,240,264,"[NULL]"
+6,1,"java.lang.String","JAVA",1,1,24,24,5
+7,0,"java.lang.Class<char>","JAVA",2,3,240,264,"[NULL]"
+8,1,"java.lang.String","JAVA",1,1,24,24,7
+9,0,"java.lang.Class<int>","JAVA",2,3,240,264,"[NULL]"
diff --git a/test/trace_processor/heap_graph_interleaved.textproto b/test/trace_processor/heap_graph_interleaved.textproto
new file mode 100644
index 0000000..fa736a4
--- /dev/null
+++ b/test/trace_processor/heap_graph_interleaved.textproto
@@ -0,0 +1,128 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+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: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    continued: true
+    index: 1
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 10
+  heap_graph {
+    pid: 3
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+    }
+    location_names {
+      iid: 1
+      str: "TEST:TEST"
+    }
+    types {
+      id: 1
+      class_name: "FactoryProducerDelegateImplActor"
+      location_id: 1
+    }
+    continued: false
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  heap_graph {
+    pid: 2
+    location_names {
+      iid: 1
+      str: "/data/app/ASDFG/invalid.test.android-SDASD/test.apk"
+    }
+    types {
+      id: 1
+      class_name: "FactoryProducerDelegateImplActor"
+      location_id: 1
+    }
+    types {
+      id: 2
+      class_name: "Foo"
+      location_id: 1
+    }
+    types {
+      id: 3
+      class_name: "a"
+      location_id: 1
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "a.a"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.test.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/heap_graph_interleaved_object.out b/test/trace_processor/heap_graph_interleaved_object.out
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_interleaved_object.out
rename to test/trace_processor/heap_graph_interleaved_object.out
diff --git a/test/trace_processor/profiling/heap_graph_interleaved_reference.out b/test/trace_processor/heap_graph_interleaved_reference.out
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_interleaved_reference.out
rename to test/trace_processor/heap_graph_interleaved_reference.out
diff --git a/test/trace_processor/heap_graph_legacy.textproto b/test/trace_processor/heap_graph_legacy.textproto
new file mode 100644
index 0000000..13fc018
--- /dev/null
+++ b/test/trace_processor/heap_graph_legacy.textproto
@@ -0,0 +1,146 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+packet {
+  timestamp: 1
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 0
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  timestamp: 10
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 3000
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+      object_ids: 0x05
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+      reference_field_id: 1
+      reference_object_id: 0x02
+      reference_field_id: 3
+      reference_object_id: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    objects {
+      id: 0x05
+      type_id: 4
+      self_size: 256
+    }
+    objects {
+      id: 0x06
+      type_id: 5
+      self_size: 256
+    }
+    continued: true
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    type_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor"
+    }
+    type_names {
+      iid: 2
+      str: "Foo"
+    }
+    type_names {
+      iid: 3
+      str: "a"
+    }
+    type_names {
+      iid: 4
+      str: "a[]"
+    }
+    type_names {
+      iid: 5
+      str: "java.lang.Class<a[]>"
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "int a.a"
+    }
+    field_names {
+      iid: 3
+      str: "a.b"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.example.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+      obfuscated_members {
+        obfuscated_name: "b"
+        deobfuscated_name: "Other.deobfuscatedA"
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
new file mode 100644
index 0000000..215755e
--- /dev/null
+++ b/test/trace_processor/heap_graph_object.out
@@ -0,0 +1,7 @@
+"id","type","upid","graph_sample_ts","self_size","reference_set_id","reachable","type_name","deobfuscated_type_name","root_type"
+0,"heap_graph_object",2,10,64,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,32,"[NULL]",1,"Foo","[NULL]","[NULL]"
+2,"heap_graph_object",2,10,128,"[NULL]",0,"Foo","[NULL]","[NULL]"
+3,"heap_graph_object",2,10,256,2,0,"a","DeobfuscatedA","[NULL]"
+4,"heap_graph_object",2,10,256,"[NULL]",1,"a[]","DeobfuscatedA[]","ROOT_JAVA_FRAME"
+5,"heap_graph_object",2,10,256,"[NULL]",0,"java.lang.Class<a[]>","java.lang.Class<DeobfuscatedA[]>","[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_object.sql b/test/trace_processor/heap_graph_object.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_object.sql
rename to test/trace_processor/heap_graph_object.sql
diff --git a/test/trace_processor/heap_graph_reference.out b/test/trace_processor/heap_graph_reference.out
new file mode 100644
index 0000000..a166b39
--- /dev/null
+++ b/test/trace_processor/heap_graph_reference.out
@@ -0,0 +1,4 @@
+"id","type","reference_set_id","owner_id","owned_id","field_name","field_type_name","deobfuscated_field_name"
+0,"heap_graph_reference",0,0,1,"FactoryProducerDelegateImplActor.foo","[NULL]","[NULL]"
+1,"heap_graph_reference",0,0,1,"a.b","[NULL]","Other.deobfuscatedA"
+2,"heap_graph_reference",2,3,0,"a.a","int","DeobfuscatedA.deobfuscatedA"
diff --git a/test/trace_processor/profiling/heap_graph_reference.sql b/test/trace_processor/heap_graph_reference.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_reference.sql
rename to test/trace_processor/heap_graph_reference.sql
diff --git a/test/trace_processor/profiling/heap_graph_two_locations.out b/test/trace_processor/heap_graph_two_locations.out
similarity index 100%
rename from test/trace_processor/profiling/heap_graph_two_locations.out
rename to test/trace_processor/heap_graph_two_locations.out
diff --git a/test/trace_processor/heap_graph_two_locations.textproto b/test/trace_processor/heap_graph_two_locations.textproto
new file mode 100644
index 0000000..e70e525
--- /dev/null
+++ b/test/trace_processor/heap_graph_two_locations.textproto
@@ -0,0 +1,168 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+packet {
+  timestamp: 1
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 0
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  timestamp: 10
+  process_stats {
+    processes {
+      pid: 2
+      rss_anon_kb: 1000
+      vm_swap_kb: 3000
+      oom_score_adj: 0
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+      object_ids: 0x05
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+      reference_field_id: 1
+      reference_object_id: 0x02
+      reference_field_id: 3
+      reference_object_id: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    objects {
+      id: 0x05
+      type_id: 4
+      self_size: 256
+    }
+    objects {
+      id: 0x06
+      type_id: 5
+      self_size: 256
+    }
+    continued: true
+    index: 0
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    location_names {
+      iid: 1
+      str: "/data/app/ASDFG/invalid.test.android-SDASD/test.apk"
+    }
+    location_names {
+      iid: 2
+      str: "/data/app/ASDFG/invalid.test2.android-SDASD/test.apk"
+    }
+    types {
+      id: 1
+      class_name: "FactoryProducerDelegateImplActor"
+      location_id: 1
+    }
+    types {
+      id: 2
+      class_name: "a"
+      location_id: 2
+    }
+    types {
+      id: 3
+      class_name: "a"
+      location_id: 1
+    }
+    types {
+      id: 4
+      class_name: "a[]"
+      location_id: 1
+    }
+    types {
+      id: 5
+      class_name: "java.lang.Class<a[]>"
+      location_id: 1
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "int a.a"
+    }
+    field_names {
+      iid: 3
+      str: "a.b"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.test.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+      obfuscated_members {
+        obfuscated_name: "b"
+        deobfuscated_name: "Other.deobfuscatedA"
+      }
+    }
+  }
+}
+packet {
+  deobfuscation_mapping {
+    package_name: "invalid.test2.android"
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "Foo"
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/heap_profile_flamegraph.sql b/test/trace_processor/heap_profile_flamegraph.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_flamegraph.sql
rename to test/trace_processor/heap_profile_flamegraph.sql
diff --git a/test/trace_processor/profiling/heap_profile_flamegraph_system-server-native-profile.out b/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_flamegraph_system-server-native-profile.out
rename to test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
diff --git a/test/trace_processor/profiling/heap_profile_frames.sql b/test/trace_processor/heap_profile_frames.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_frames.sql
rename to test/trace_processor/heap_profile_frames.sql
diff --git a/test/trace_processor/profiling/heap_profile_jit.out b/test/trace_processor/heap_profile_jit.out
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_jit.out
rename to test/trace_processor/heap_profile_jit.out
diff --git a/test/trace_processor/profiling/heap_profile_jit.textproto b/test/trace_processor/heap_profile_jit.textproto
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_jit.textproto
rename to test/trace_processor/heap_profile_jit.textproto
diff --git a/test/trace_processor/heap_profile_tracker_new_stack.out b/test/trace_processor/heap_profile_tracker_new_stack.out
new file mode 100644
index 0000000..205768d
--- /dev/null
+++ b/test/trace_processor/heap_profile_tracker_new_stack.out
@@ -0,0 +1,5 @@
+"id","type","ts","upid","callsite_id","count","size"
+0,"heap_profile_allocation",0,0,0,1,1
+1,"heap_profile_allocation",0,0,0,-1,-1
+2,"heap_profile_allocation",1,0,0,1,1
+3,"heap_profile_allocation",1,0,0,-1,-1
diff --git a/test/trace_processor/profiling/heap_profile_tracker_new_stack.sql b/test/trace_processor/heap_profile_tracker_new_stack.sql
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_tracker_new_stack.sql
rename to test/trace_processor/heap_profile_tracker_new_stack.sql
diff --git a/test/trace_processor/profiling/heap_profile_tracker_new_stack.textproto b/test/trace_processor/heap_profile_tracker_new_stack.textproto
similarity index 100%
rename from test/trace_processor/profiling/heap_profile_tracker_new_stack.textproto
rename to test/trace_processor/heap_profile_tracker_new_stack.textproto
diff --git a/test/trace_processor/include_index b/test/trace_processor/include_index
deleted file mode 100644
index b07a07f..0000000
--- a/test/trace_processor/include_index
+++ /dev/null
@@ -1,14 +0,0 @@
-chrome/index
-dynamic/index
-fuchsia/index
-graphics/index
-memory/index
-parsing/index
-power/index
-process_tracking/index
-profiling/index
-smoke/index
-span_join/index
-startup/index
-tables/index
-track_event/index
diff --git a/test/trace_processor/index b/test/trace_processor/index
new file mode 100644
index 0000000..139569b
--- /dev/null
+++ b/test/trace_processor/index
@@ -0,0 +1,226 @@
+# Smoke tests
+../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
+synth_process_tracking.py process_tracking_uid.sql process_tracking_uid.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
+reused_thread_print.py process_tracking.sql process_tracking_reused_thread_print.out
+sde_tracing_mark_write.textproto slice_with_pid.sql slice_with_pid_sde_tracing_mark_write.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
+
+
+# The below tests check the storage backed tables in the trace processor.
+# Sched
+../data/android_sched_and_ps.pb ts_desc_filter.sql ts_desc_filter_android_sched_and_ps.out
+
+# Sched reason
+../data/android_sched_and_ps.pb end_reason_eq.sql android_sched_and_ps_end_reason_eq.out
+../data/android_sched_and_ps.pb end_reason_neq.sql android_sched_and_ps_end_reason_neq.out
+
+# Sched wakeup
+../data/android_sched_and_ps.pb sched_wakeup.sql sched_wakeup_android_sched_and_ps.out
+
+# CPU Frequency
+../data/cpu_counters.pb b120487929.sql cpu_counters_b120487929.out
+
+# Logcat
+../data/android_log.pb android_log_counts.sql android_log_counts.out
+../data/android_log.pb android_log_msgs.sql android_log_msgs.out
+../data/android_log_ring_buffer_mode.pb android_log_ring_buffer_mode.sql android_log_ring_buffer_mode.out
+
+# Mm Event
+../data/mm_event.pb mm_event.sql mm_event.out
+
+# Oom Score
+synth_oom.py oom_query.sql synth_oom_oom_query.out
+../data/process_stats_poll.pb oom_score_poll.sql process_stats_poll_oom_score.out
+
+# LMK handling
+kernel_lmk.py lmk.sql lmk_kernel_lmk.out
+../data/lmk_userspace.pb lmk.sql lmk_userspace_lmk.out
+oom_kill.textproto oom_kill.sql oom_kill.out
+
+# Rss stats
+rss_stat_mm_id.py rss_stat.sql rss_stat_mm_id.out
+rss_stat_mm_id_clone.py rss_stat.sql rss_stat_mm_id_clone.out
+rss_stat_mm_id_reuse.py rss_stat.sql rss_stat_mm_id_reuse.out
+rss_stat_legacy.py rss_stat.sql rss_stat_legacy.out
+rss_stat_after_free.py rss_stat_after_free.sql rss_stat_after_free.out
+
+# Memory counters
+../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
+../data/memory_counters.pb b120605557.sql memory_counters_b120605557.out
+../data/memory_counters.pb global_memory_counter.sql global_memory_counter_memory_counters.out
+ion_stat.textproto ion_stat.sql ion_stat.out
+
+# Stats
+../data/android_sched_and_ps.pb stats.sql android_sched_and_ps_stats.out
+
+# Syscalls
+syscall.py sys.sql sys_syscall.out
+
+# Power rails
+../data/power_rails.pb power_rails.sql power_rails_power_rails.out
+power_rails_custom_clock.textproto power_rails_event.sql power_rails_event_power_rails_custom_clock.out
+power_rails.textproto power_rails_timestamp_sort.sql power_rails_timestamp_sort.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.
+# Span join
+../data/android_sched_and_ps.pb slice_span_join_b118665515.sql android_sched_and_ps_slice_span_join_b118665515.out
+synth_1.py span_join_unordered_cols.sql span_join_unordered_cols_synth_1.out
+synth_1.py span_join_unordered_cols_reverse.sql span_join_unordered_cols_synth_1.out
+../data/android_sched_and_ps.pb span_left_join.sql span_left_join.out
+../data/android_sched_and_ps.pb span_left_join_unpartitioned.sql span_left_join_unpartitioned.out
+../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
+../data/android_sched_and_ps.pb span_join_zero_negative_dur.sql span_join_zero_negative_dur.out
+../data/android_sched_and_ps.pb span_outer_join_empty.sql span_outer_join_empty_android_sched_and_ps.out
+../data/android_sched_and_ps.pb span_left_join_unordered.sql span_left_join_unordered_android_sched_and_ps.out
+../data/android_sched_and_ps.pb span_join_unpartitioned_empty.sql span_join_unpartitioned_empty.out
+
+# Window table
+../data/android_sched_and_ps.pb smoke_window.sql android_sched_and_ps_smoke_window.out
+
+
+# The below tests check the lower level layers of the trace processor (i.e.
+# fitering and printing code).
+# Sched table
+synth_1.py filter_sched.sql synth_1_filter_sched.out
+../data/android_sched_and_ps.pb b119496959.sql android_sched_and_ps_b119496959.out
+../data/android_sched_and_ps.pb b119301023.sql android_sched_and_ps_b119301023.out
+
+# Counters table
+synth_1.py filter_counter.sql synth_1_filter_counter.out
+../data/memory_counters.pb b120278869_neg_ts_end.sql memory_counters_b120278869_neg_ts_end.out
+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
+../data/example_android_trace_30s.pb filter_row_vector.sql filter_row_vector_example_android_trace_30s.out
+../data/example_android_trace_30s.pb counter_dur.sql counter_dur_example_android_trace_30s.out
+
+# Null printing
+synth_1.py nulls.sql nulls.out
+
+
+# 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
+gpu_counter_specs.textproto gpu_counter_specs.sql gpu_counter_specs.out
+gpu_render_stages.py gpu_render_stages.sql gpu_render_stages.out
+vulkan_api_events.py vulkan_api_events.sql vulkan_api_events.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
+
+profiler_smaps.textproto profiler_smaps.sql profiler_smaps.out
+
+heap_graph_baseapk.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
+heap_graph_baseapk.textproto heap_graph_object.sql heap_graph_object.out
+heap_graph_baseapk.textproto heap_graph_reference.sql heap_graph_reference.out
+
+heap_graph.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
+heap_graph.textproto heap_graph_object.sql heap_graph_object.out
+heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
+heap_graph_two_locations.textproto heap_graph_object.sql heap_graph_two_locations.out
+# TODO(b/153552977): Stop supporting legacy heap graphs. These never made
+#                    it into a public release, so we should eventually stop
+#                    supporting workarounds for them.
+heap_graph_legacy.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
+heap_graph_legacy.textproto heap_graph_object.sql heap_graph_object.out
+heap_graph_legacy.textproto heap_graph_reference.sql heap_graph_reference.out
+heap_graph_interleaved.textproto heap_graph_object.sql heap_graph_interleaved_object.out
+heap_graph_interleaved.textproto heap_graph_reference.sql heap_graph_interleaved_reference.out
+../data/system-server-heap-graph.pftrace heap_graph_flamegraph.sql heap_graph_flamegraph_system-server-heap-graph.out
+../data/system-server-native-profile heap_profile_flamegraph.sql heap_profile_flamegraph_system-server-native-profile.out
+heap_profile_tracker_new_stack.textproto heap_profile_tracker_new_stack.sql heap_profile_tracker_new_stack.out
+heap_graph_branching.textproto heap_graph_flamegraph_focused.sql heap_graph_flamegraph_focused.out
+
+stack_profile_tracker_empty_callstack.textproto stack_profile_tracker_empty_callstack.sql stack_profile_tracker_empty_callstack.out
+
+# TrackEvent tests.
+track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
+track_event_same_tids.textproto track_event_slices.sql track_event_same_tids_slices.out
+track_event_typed_args.textproto track_event_slices.sql track_event_typed_args_slices.out
+track_event_typed_args.textproto track_event_args.sql track_event_typed_args_args.out
+track_event_tracks.textproto track_event_slices.sql track_event_tracks_slices.out
+track_event_with_atrace.textproto track_event_slices.sql track_event_with_atrace.out
+track_event_merged_debug_annotations.textproto track_event_args.sql track_event_merged_debug_annotations_args.out
+track_event_counters.textproto track_event_slices.sql track_event_counters_slices.out
+track_event_counters.textproto track_event_counters.sql track_event_counters_counters.out
+track_event_monotonic_trace_clock.textproto track_event_slices.sql track_event_monotonic_trace_clock_slices.out
+
+# Parsing systrace files
+../data/systrace.html systrace_html.sql systrace_html.out
+../data/trailing_empty.systrace sched_smoke.sql sched_smoke_trailing_empty.out
+
+# Config & metadata
+config_metadata.textproto metadata.sql config_metadata.out
+trigger_packet_trace.textproto triggers_packets.sql triggers_packets_trigger_packet_trace.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
+
+# Ensures process -> package matching works as expected.
+process_metadata_matching.textproto process_metadata_matching.sql process_metadata_matching.out
+
+# Trace size
+../data/android_sched_and_ps.pb trace_size.sql android_sched_and_ps_trace_size.out
+
+# Thread time_in_state
+thread_time_in_state.textproto thread_time_in_state.sql thread_time_in_state.out
+thread_time_in_state_annotations.py thread_time_in_state_annotations.sql thread_time_in_state_annotations.out
+
+# Initial display state
+initial_display_state.textproto initial_display_state.sql initial_display_state.out
+
+# CPU info
+cpu_info.textproto cpu.sql cpu.out
+cpu_info.textproto cpu_freq.sql cpu_freq.out
+
+# Thread table
+thread_main_thread.textproto thread_main_thread.sql thread_main_thread.out
diff --git a/test/trace_processor/parsing/initial_display_state.out b/test/trace_processor/initial_display_state.out
similarity index 100%
rename from test/trace_processor/parsing/initial_display_state.out
rename to test/trace_processor/initial_display_state.out
diff --git a/test/trace_processor/parsing/initial_display_state.sql b/test/trace_processor/initial_display_state.sql
similarity index 100%
rename from test/trace_processor/parsing/initial_display_state.sql
rename to test/trace_processor/initial_display_state.sql
diff --git a/test/trace_processor/parsing/initial_display_state.textproto b/test/trace_processor/initial_display_state.textproto
similarity index 100%
rename from test/trace_processor/parsing/initial_display_state.textproto
rename to test/trace_processor/initial_display_state.textproto
diff --git a/test/trace_processor/parsing/ion_stat.out b/test/trace_processor/ion_stat.out
similarity index 100%
rename from test/trace_processor/parsing/ion_stat.out
rename to test/trace_processor/ion_stat.out
diff --git a/test/trace_processor/parsing/ion_stat.sql b/test/trace_processor/ion_stat.sql
similarity index 100%
rename from test/trace_processor/parsing/ion_stat.sql
rename to test/trace_processor/ion_stat.sql
diff --git a/test/trace_processor/parsing/ion_stat.textproto b/test/trace_processor/ion_stat.textproto
similarity index 100%
rename from test/trace_processor/parsing/ion_stat.textproto
rename to test/trace_processor/ion_stat.textproto
diff --git a/test/trace_processor/kernel_lmk.py b/test/trace_processor/kernel_lmk.py
new file mode 100644
index 0000000..e653950
--- /dev/null
+++ b/test/trace_processor/kernel_lmk.py
@@ -0,0 +1,36 @@
+#!/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()
+trace.add_process(pid=1, ppid=0, cmdline="init")
+trace.add_process(pid=2, ppid=1, cmdline="two_thread_process")
+trace.add_process(pid=4, ppid=1, cmdline="single_thread_process")
+
+trace.add_process(pid=1000, ppid=1, cmdline="padding_process")
+trace.add_thread(tid=1301, tgid=1000, cmdline="padding_process_thread_1")
+trace.add_thread(tid=1302, tgid=1000, cmdline="padding_process_thread_2")
+
+trace.add_thread(tid=300, tgid=2, cmdline="two_thread_process")
+
+trace.add_ftrace_packet(0)
+trace.add_kernel_lmk(ts=100, tid=300)
+trace.add_kernel_lmk(ts=101, tid=4)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/lmk.sql b/test/trace_processor/lmk.sql
similarity index 100%
rename from test/trace_processor/parsing/lmk.sql
rename to test/trace_processor/lmk.sql
diff --git a/test/trace_processor/parsing/lmk_kernel_lmk.out b/test/trace_processor/lmk_kernel_lmk.out
similarity index 100%
rename from test/trace_processor/parsing/lmk_kernel_lmk.out
rename to test/trace_processor/lmk_kernel_lmk.out
diff --git a/test/trace_processor/parsing/lmk_userspace_lmk.out b/test/trace_processor/lmk_userspace_lmk.out
similarity index 100%
rename from test/trace_processor/parsing/lmk_userspace_lmk.out
rename to test/trace_processor/lmk_userspace_lmk.out
diff --git a/test/trace_processor/memory/android_dma_buffer_tracks.out b/test/trace_processor/memory/android_dma_buffer_tracks.out
deleted file mode 100644
index 39463cd..0000000
--- a/test/trace_processor/memory/android_dma_buffer_tracks.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"name","ts","dur","name"
-"mem.dma_buffer",100,100,"1 kB"
diff --git a/test/trace_processor/memory/android_dma_heap_stat.out b/test/trace_processor/memory/android_dma_heap_stat.out
deleted file mode 100644
index 71b8f40..0000000
--- a/test/trace_processor/memory/android_dma_heap_stat.out
+++ /dev/null
@@ -1,6 +0,0 @@
-android_dma_heap {
-    avg_size_bytes: 2048.0
-    min_size_bytes: 1024.0
-    max_size_bytes: 2048.0
-    total_alloc_size_bytes: 1024.0
-}
diff --git a/test/trace_processor/memory/android_dma_heap_stat.textproto b/test/trace_processor/memory/android_dma_heap_stat.textproto
deleted file mode 100644
index 6c091aa..0000000
--- a/test/trace_processor/memory/android_dma_heap_stat.textproto
+++ /dev/null
@@ -1,28 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 0
-    event {
-      timestamp: 100
-      pid: 1
-      dma_heap_stat {
-        inode: 123
-        len: 1024
-        total_allocated: 2048
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 0
-    event {
-      timestamp: 200
-      pid: 1
-      dma_heap_stat {
-        inode: 123
-        len: -1024
-        total_allocated: 1024
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/memory/android_fastrpc_dma_stat.out b/test/trace_processor/memory/android_fastrpc_dma_stat.out
deleted file mode 100644
index c16f833..0000000
--- a/test/trace_processor/memory/android_fastrpc_dma_stat.out
+++ /dev/null
@@ -1,9 +0,0 @@
-android_fastrpc {
-  subsystem {
-    name: "MDSP"
-    avg_size_bytes: 2000.0
-    min_size_bytes: 1000.0
-    max_size_bytes: 2000.0
-    total_alloc_size_bytes: 1000.0
-  }
-}
diff --git a/test/trace_processor/memory/android_fastrpc_dma_stat.textproto b/test/trace_processor/memory/android_fastrpc_dma_stat.textproto
deleted file mode 100644
index 9157736..0000000
--- a/test/trace_processor/memory/android_fastrpc_dma_stat.textproto
+++ /dev/null
@@ -1,28 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 0
-    event {
-      timestamp: 100
-      pid: 1
-      fastrpc_dma_stat {
-        cid: 1
-        len: 1000
-        total_allocated: 2000
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 0
-    event {
-      timestamp: 200
-      pid: 1
-      fastrpc_dma_stat {
-        cid: 1
-        len: -1000
-        total_allocated: 1000
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/memory/android_ion.out b/test/trace_processor/memory/android_ion.out
deleted file mode 100644
index 5116e55..0000000
--- a/test/trace_processor/memory/android_ion.out
+++ /dev/null
@@ -1,16 +0,0 @@
-android_ion {
-  buffer {
-    name: "adsp"
-    avg_size_bytes: 1000.0
-    min_size_bytes: 1000.0
-    max_size_bytes: 1100.0
-    total_alloc_size_bytes: 1100.0
-  }
-  buffer {
-    name: "system"
-    avg_size_bytes: 1497.4874371859296
-    min_size_bytes: 1000.0
-    max_size_bytes: 2000.0
-    total_alloc_size_bytes: 2000.0
-  }
-}
diff --git a/test/trace_processor/memory/android_ion.py b/test/trace_processor/memory/android_ion.py
deleted file mode 100644
index 9618460..0000000
--- a/test/trace_processor/memory/android_ion.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_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', len=1000)
-trace.add_ion_event(ts=150, tid=3, heap_name='adsp', len=1000)
-trace.add_ion_event(ts=200, tid=3, heap_name='system', size=1000, len=1000)
-trace.add_ion_event(ts=299, tid=3, heap_name='adsp', size=1000, len=100)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_lmk.py b/test/trace_processor/memory/android_lmk.py
deleted file mode 100644
index eaf9a3e..0000000
--- a/test/trace_processor/memory/android_lmk.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_lmk_reason.py b/test/trace_processor/memory/android_lmk_reason.py
deleted file mode 100644
index f5841f3..0000000
--- a/test/trace_processor/memory/android_lmk_reason.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-anon_member = 1
-swap_member = 2
-
-trace = synth_common.create_trace()
-
-trace.add_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'lmk_victim:no_data:ignored')
-trace.add_process(4, 1, 'lmk_victim:no_ion')
-trace.add_process(5, 1, 'lmk_victim:with_ion')
-trace.add_process(6, 1, 'process')
-trace.add_process(7, 1, 'lmk_victim:with_process')
-trace.add_process(8, 1, 'app:ui', 10001)
-trace.add_process(9, 1, 'lmk_victim:with_app')
-
-trace.add_package_list(ts=1, name="app", uid=10001, version_code=123)
-trace.add_package_list(ts=1, name="shared_uid_app", uid=10001, version_code=345)
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_kernel_lmk(ts=101, tid=3)
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_oom_score_update(ts=201, oom_score_adj=0, pid=4)
-trace.add_kernel_lmk(ts=202, tid=4)
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_ion_event(ts=301, tid=5, heap_name='system', len=1000)
-trace.add_oom_score_update(ts=302, oom_score_adj=100, pid=5)
-trace.add_kernel_lmk(ts=303, tid=5)
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_oom_score_update(ts=401, oom_score_adj=0, pid=6)
-trace.add_oom_score_update(ts=402, oom_score_adj=200, pid=7)
-trace.add_rss_stat(ts=403, tid=6, member=anon_member, size=2000)
-trace.add_kernel_lmk(ts=404, tid=7)
-trace.add_process_free(ts=405, tid=6, comm='', prio=0)
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_oom_score_update(ts=501, oom_score_adj=0, pid=8)
-trace.add_oom_score_update(ts=502, oom_score_adj=100, pid=9)
-trace.add_rss_stat(ts=503, tid=8, member=anon_member, size=2500)
-trace.add_rss_stat(ts=503, tid=8, member=swap_member, size=2500)
-trace.add_kernel_lmk(ts=504, tid=9)
-
-# Dummy trace event to ensure the trace does not end on an LMK.
-trace.add_ftrace_packet(cpu=0)
-trace.add_oom_score_update(ts=1001, oom_score_adj=-800, pid=2)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/android_mem_by_priority.py b/test/trace_processor/memory/android_mem_by_priority.py
deleted file mode 100644
index 685af43..0000000
--- a/test/trace_processor/memory/android_mem_by_priority.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-file_member = 0
-anon_member = 1
-swap_member = 2
-
-trace = synth_common.create_trace()
-trace.add_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/memory/dma_buffer_tracks.sql b/test/trace_processor/memory/dma_buffer_tracks.sql
deleted file mode 100644
index 9815ce5..0000000
--- a/test/trace_processor/memory/dma_buffer_tracks.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-SELECT track.name, slice.ts, slice.dur, slice.name
-FROM slice JOIN track ON slice.track_id = track.id
-WHERE track.name = 'mem.dma_buffer';
diff --git a/test/trace_processor/memory/index b/test/trace_processor/memory/index
deleted file mode 100644
index 683d4f1..0000000
--- a/test/trace_processor/memory/index
+++ /dev/null
@@ -1,20 +0,0 @@
-# Contains test for Android memory metrics.
-
-# Memory metric
-../../data/memory_counters.pb android_mem android_mem_counters.out
-../../data/memory_counters.pb trace_metadata trace_metadata.out
-android_mem_by_priority.py android_mem android_mem_by_priority.out
-android_lmk.py android_lmk android_mem_lmk.out
-android_lmk_reason.py android_lmk_reason android_lmk_reason.out
-../common/oom_kill.textproto android_lmk android_lmk_oom.out
-
-# ION metric
-android_ion.py android_ion android_ion.out
-android_ion_stat.textproto android_ion android_ion_stat.out
-
-# DMA-BUF heap Metric
-android_dma_heap_stat.textproto android_dma_heap android_dma_heap_stat.out
-android_dma_heap_stat.textproto dma_buffer_tracks.sql android_dma_buffer_tracks.out
-
-# fastrpc metric
-android_fastrpc_dma_stat.textproto android_fastrpc android_fastrpc_dma_stat.out
diff --git a/test/trace_processor/memory/trace_metadata.out b/test/trace_processor/memory/trace_metadata.out
deleted file mode 100644
index b66bf1a..0000000
--- a/test/trace_processor/memory/trace_metadata.out
+++ /dev/null
@@ -1,6 +0,0 @@
-trace_metadata {
-  trace_duration_ns: 9519159074,
-  trace_size_bytes: 6365447
-  trace_config_pbtxt: "buffers: {\n  size_kb: 32768\n  fill_policy: UNSPECIFIED\n}\ndata_sources: {\n  config: {\n    name: \"linux.ftrace\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      ftrace_events: \"print\"\n      ftrace_events: \"sched_switch\"\n      ftrace_events: \"rss_stat\"\n      ftrace_events: \"ion_heap_shrink\"\n      ftrace_events: \"ion_heap_grow\"\n      atrace_categories: \"am\"\n      atrace_categories: \"dalvik\"\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 0\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 0\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\ndata_sources: {\n  config: {\n    name: \"linux.process_stats\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 100\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 0\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\ndata_sources: {\n  config: {\n    name: \"linux.sys_stats\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 0\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 50\n      meminfo_counters: MEMINFO_MEM_AVAILABLE\n      meminfo_counters: MEMINFO_SWAP_CACHED\n      meminfo_counters: MEMINFO_ACTIVE\n      meminfo_counters: MEMINFO_INACTIVE\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\nduration_ms: 10000\nenable_extra_guardrails: false\nlockdown_mode: LOCKDOWN_UNCHANGED\nstatsd_metadata: {\n  triggering_alert_id: 0\n  triggering_config_uid: 0\n  triggering_config_id: 0\n}\nwrite_into_file: false\nfile_write_period_ms: 0\nmax_file_size_bytes: 0\nguardrail_overrides: {\n  max_upload_per_day_bytes: 0\n}\ndeferred_start: false",
-  sched_duration_ns: 9452761359
-}
diff --git a/test/trace_processor/parsing/memory_counters_args_string_filter_null.out b/test/trace_processor/memory_counters_args_string_filter_null.out
similarity index 100%
rename from test/trace_processor/parsing/memory_counters_args_string_filter_null.out
rename to test/trace_processor/memory_counters_args_string_filter_null.out
diff --git a/test/trace_processor/parsing/memory_counters_args_string_is_not_null.out b/test/trace_processor/memory_counters_args_string_is_not_null.out
similarity index 100%
rename from test/trace_processor/parsing/memory_counters_args_string_is_not_null.out
rename to test/trace_processor/memory_counters_args_string_is_not_null.out
diff --git a/test/trace_processor/parsing/memory_counters_args_string_is_null.out b/test/trace_processor/memory_counters_args_string_is_null.out
similarity index 100%
rename from test/trace_processor/parsing/memory_counters_args_string_is_null.out
rename to test/trace_processor/memory_counters_args_string_is_null.out
diff --git a/test/trace_processor/tables/memory_counters_b120278869_neg_ts_end.out b/test/trace_processor/memory_counters_b120278869_neg_ts_end.out
similarity index 100%
rename from test/trace_processor/tables/memory_counters_b120278869_neg_ts_end.out
rename to test/trace_processor/memory_counters_b120278869_neg_ts_end.out
diff --git a/test/trace_processor/parsing/memory_counters_b120605557.out b/test/trace_processor/memory_counters_b120605557.out
similarity index 100%
rename from test/trace_processor/parsing/memory_counters_b120605557.out
rename to test/trace_processor/memory_counters_b120605557.out
diff --git a/test/trace_processor/parsing/metadata.sql b/test/trace_processor/metadata.sql
similarity index 100%
rename from test/trace_processor/parsing/metadata.sql
rename to test/trace_processor/metadata.sql
diff --git a/test/trace_processor/parsing/mm_event.out b/test/trace_processor/mm_event.out
similarity index 100%
rename from test/trace_processor/parsing/mm_event.out
rename to test/trace_processor/mm_event.out
diff --git a/test/trace_processor/parsing/mm_event.sql b/test/trace_processor/mm_event.sql
similarity index 100%
rename from test/trace_processor/parsing/mm_event.sql
rename to test/trace_processor/mm_event.sql
diff --git a/test/trace_processor/tables/nulls.out b/test/trace_processor/nulls.out
similarity index 100%
rename from test/trace_processor/tables/nulls.out
rename to test/trace_processor/nulls.out
diff --git a/test/trace_processor/tables/nulls.sql b/test/trace_processor/nulls.sql
similarity index 100%
rename from test/trace_processor/tables/nulls.sql
rename to test/trace_processor/nulls.sql
diff --git a/test/trace_processor/parsing/oom_kill.out b/test/trace_processor/oom_kill.out
similarity index 100%
rename from test/trace_processor/parsing/oom_kill.out
rename to test/trace_processor/oom_kill.out
diff --git a/test/trace_processor/parsing/oom_kill.sql b/test/trace_processor/oom_kill.sql
similarity index 100%
rename from test/trace_processor/parsing/oom_kill.sql
rename to test/trace_processor/oom_kill.sql
diff --git a/test/trace_processor/common/oom_kill.textproto b/test/trace_processor/oom_kill.textproto
similarity index 100%
rename from test/trace_processor/common/oom_kill.textproto
rename to test/trace_processor/oom_kill.textproto
diff --git a/test/trace_processor/parsing/oom_query.sql b/test/trace_processor/oom_query.sql
similarity index 100%
rename from test/trace_processor/parsing/oom_query.sql
rename to test/trace_processor/oom_query.sql
diff --git a/test/trace_processor/parsing/oom_score_poll.sql b/test/trace_processor/oom_score_poll.sql
similarity index 100%
rename from test/trace_processor/parsing/oom_score_poll.sql
rename to test/trace_processor/oom_score_poll.sql
diff --git a/test/trace_processor/parsing/android_b2b_async_begin.textproto b/test/trace_processor/parsing/android_b2b_async_begin.textproto
deleted file mode 100644
index 121dfe1..0000000
--- a/test/trace_processor/parsing/android_b2b_async_begin.textproto
+++ /dev/null
@@ -1,69 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 3
-    event {
-      timestamp: 1000
-      pid: 4064
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1010
-      pid: 1257
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1015
-      pid: 1257
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|multistart|10\n"
-      }
-    }
-    event {
-      timestamp: 1020
-      pid: 1240
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1030
-      pid: 4293
-      print {
-        ip: 18446743562018522420
-        buf: "F|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1030
-      pid: 1240
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1050
-      pid: 4293
-      print {
-        ip: 18446743562018522420
-        buf: "F|1204|multistart|0\n"
-      }
-    }
-    event {
-      timestamp: 1060
-      pid: 4009
-      print {
-        ip: 18446743562018522420
-        buf: "F|1204|multistart|10\n"
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/android_b2b_async_begin_list_slices.out b/test/trace_processor/parsing/android_b2b_async_begin_list_slices.out
deleted file mode 100644
index a11b96c..0000000
--- a/test/trace_processor/parsing/android_b2b_async_begin_list_slices.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"ts","dur","name"
-1000,30,"multistart"
-1015,45,"multistart"
-1030,20,"multistart"
diff --git a/test/trace_processor/parsing/android_package_list.py b/test/trace_processor/parsing/android_package_list.py
deleted file mode 100644
index 95ebb44..0000000
--- a/test/trace_processor/parsing/android_package_list.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_package_list(1, 'com.my.pkg', 123, 456000)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/android_sched_and_ps_stats.out b/test/trace_processor/parsing/android_sched_and_ps_stats.out
deleted file mode 100644
index 4ff60f7..0000000
--- a/test/trace_processor/parsing/android_sched_and_ps_stats.out
+++ /dev/null
@@ -1,147 +0,0 @@
-"name","idx","severity","source","value"
-"ftrace_cpu_bytes_read_begin",0,"info","trace",232
-"ftrace_cpu_bytes_read_begin",1,"info","trace",232
-"ftrace_cpu_bytes_read_begin",2,"info","trace",1548
-"ftrace_cpu_bytes_read_begin",3,"info","trace",176
-"ftrace_cpu_bytes_read_begin",4,"info","trace",0
-"ftrace_cpu_bytes_read_begin",5,"info","trace",0
-"ftrace_cpu_bytes_read_begin",6,"info","trace",0
-"ftrace_cpu_bytes_read_begin",7,"info","trace",0
-"ftrace_cpu_bytes_read_end",0,"info","trace",20468
-"ftrace_cpu_bytes_read_end",1,"info","trace",11612
-"ftrace_cpu_bytes_read_end",2,"info","trace",13884
-"ftrace_cpu_bytes_read_end",3,"info","trace",6412
-"ftrace_cpu_bytes_read_end",4,"info","trace",2676
-"ftrace_cpu_bytes_read_end",5,"info","trace",1188
-"ftrace_cpu_bytes_read_end",6,"info","trace",1576
-"ftrace_cpu_bytes_read_end",7,"info","trace",3264
-"ftrace_cpu_commit_overrun_begin",0,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",1,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",2,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",3,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",4,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",5,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",6,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",7,"error","trace",0
-"ftrace_cpu_commit_overrun_end",0,"error","trace",0
-"ftrace_cpu_commit_overrun_end",1,"error","trace",0
-"ftrace_cpu_commit_overrun_end",2,"error","trace",0
-"ftrace_cpu_commit_overrun_end",3,"error","trace",0
-"ftrace_cpu_commit_overrun_end",4,"error","trace",0
-"ftrace_cpu_commit_overrun_end",5,"error","trace",0
-"ftrace_cpu_commit_overrun_end",6,"error","trace",0
-"ftrace_cpu_commit_overrun_end",7,"error","trace",0
-"ftrace_cpu_dropped_events_begin",0,"error","trace",0
-"ftrace_cpu_dropped_events_begin",1,"error","trace",0
-"ftrace_cpu_dropped_events_begin",2,"error","trace",0
-"ftrace_cpu_dropped_events_begin",3,"error","trace",0
-"ftrace_cpu_dropped_events_begin",4,"error","trace",0
-"ftrace_cpu_dropped_events_begin",5,"error","trace",0
-"ftrace_cpu_dropped_events_begin",6,"error","trace",0
-"ftrace_cpu_dropped_events_begin",7,"error","trace",0
-"ftrace_cpu_dropped_events_end",0,"error","trace",0
-"ftrace_cpu_dropped_events_end",1,"error","trace",0
-"ftrace_cpu_dropped_events_end",2,"error","trace",0
-"ftrace_cpu_dropped_events_end",3,"error","trace",0
-"ftrace_cpu_dropped_events_end",4,"error","trace",0
-"ftrace_cpu_dropped_events_end",5,"error","trace",0
-"ftrace_cpu_dropped_events_end",6,"error","trace",0
-"ftrace_cpu_dropped_events_end",7,"error","trace",0
-"ftrace_cpu_entries_begin",0,"info","trace",4
-"ftrace_cpu_entries_begin",1,"info","trace",4
-"ftrace_cpu_entries_begin",2,"info","trace",23
-"ftrace_cpu_entries_begin",3,"info","trace",4
-"ftrace_cpu_entries_begin",4,"info","trace",0
-"ftrace_cpu_entries_begin",5,"info","trace",0
-"ftrace_cpu_entries_begin",6,"info","trace",0
-"ftrace_cpu_entries_begin",7,"info","trace",0
-"ftrace_cpu_entries_end",0,"info","trace",341
-"ftrace_cpu_entries_end",1,"info","trace",195
-"ftrace_cpu_entries_end",2,"info","trace",225
-"ftrace_cpu_entries_end",3,"info","trace",111
-"ftrace_cpu_entries_end",4,"info","trace",45
-"ftrace_cpu_entries_end",5,"info","trace",21
-"ftrace_cpu_entries_end",6,"info","trace",26
-"ftrace_cpu_entries_end",7,"info","trace",54
-"ftrace_cpu_now_ts_begin",0,"info","trace",81473010735000
-"ftrace_cpu_now_ts_begin",1,"info","trace",81473010800000
-"ftrace_cpu_now_ts_begin",2,"info","trace",81473010839000
-"ftrace_cpu_now_ts_begin",3,"info","trace",81473010879000
-"ftrace_cpu_now_ts_begin",4,"info","trace",81473010921000
-"ftrace_cpu_now_ts_begin",5,"info","trace",81473010961000
-"ftrace_cpu_now_ts_begin",6,"info","trace",81473011000000
-"ftrace_cpu_now_ts_begin",7,"info","trace",81473011038000
-"ftrace_cpu_now_ts_end",0,"info","trace",81492876420000
-"ftrace_cpu_now_ts_end",1,"info","trace",81492876502000
-"ftrace_cpu_now_ts_end",2,"info","trace",81492876565000
-"ftrace_cpu_now_ts_end",3,"info","trace",81492876626000
-"ftrace_cpu_now_ts_end",4,"info","trace",81492876685000
-"ftrace_cpu_now_ts_end",5,"info","trace",81492876744000
-"ftrace_cpu_now_ts_end",6,"info","trace",81492876804000
-"ftrace_cpu_now_ts_end",7,"info","trace",81492876865000
-"ftrace_cpu_oldest_event_ts_begin",0,"info","trace",81473010620000
-"ftrace_cpu_oldest_event_ts_begin",1,"info","trace",81473009948000
-"ftrace_cpu_oldest_event_ts_begin",2,"info","trace",81473010031000
-"ftrace_cpu_oldest_event_ts_begin",3,"info","trace",81473010606000
-"ftrace_cpu_oldest_event_ts_begin",4,"info","trace",81400098010000
-"ftrace_cpu_oldest_event_ts_begin",5,"info","trace",0
-"ftrace_cpu_oldest_event_ts_begin",6,"info","trace",81400081638000
-"ftrace_cpu_oldest_event_ts_begin",7,"info","trace",81399773896000
-"ftrace_cpu_oldest_event_ts_end",0,"info","trace",81492812444000
-"ftrace_cpu_oldest_event_ts_end",1,"info","trace",81492812907000
-"ftrace_cpu_oldest_event_ts_end",2,"info","trace",81492800730000
-"ftrace_cpu_oldest_event_ts_end",3,"info","trace",81492838810000
-"ftrace_cpu_oldest_event_ts_end",4,"info","trace",81492423749000
-"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_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
-"ftrace_cpu_read_events_begin",3,"info","trace",0
-"ftrace_cpu_read_events_begin",4,"info","trace",0
-"ftrace_cpu_read_events_begin",5,"info","trace",0
-"ftrace_cpu_read_events_begin",6,"info","trace",0
-"ftrace_cpu_read_events_begin",7,"info","trace",0
-"ftrace_cpu_read_events_end",0,"info","trace",62303
-"ftrace_cpu_read_events_end",1,"info","trace",54916
-"ftrace_cpu_read_events_end",2,"info","trace",55882
-"ftrace_cpu_read_events_end",3,"info","trace",47953
-"ftrace_cpu_read_events_end",4,"info","trace",31345
-"ftrace_cpu_read_events_end",5,"info","trace",23232
-"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,"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,"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
-"traced_buf_chunks_committed_out_of_order",0,"info","trace",0
-"traced_buf_padding_bytes_cleared",0,"info","trace",0
-"traced_buf_padding_bytes_written",0,"info","trace",0
-"traced_buf_patches_failed",0,"data_loss","trace",0
-"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,"data_loss","trace",0
-"traced_buf_write_wrap_count",0,"info","trace",0
diff --git a/test/trace_processor/parsing/android_thread_time_in_state.out b/test/trace_processor/parsing/android_thread_time_in_state.out
deleted file mode 100644
index 7878ba5..0000000
--- a/test/trace_processor/parsing/android_thread_time_in_state.out
+++ /dev/null
@@ -1,73 +0,0 @@
-android_thread_time_in_state {
-  processes {
-    metadata {
-      name: "com.google.pid5"
-    }
-    metrics_by_core_type {
-      time_in_state_cpu: 0
-      core_type: "little"
-      runtime_ms: 20
-      mcycles: 3
-    }
-    threads {
-      main_thread: true
-      metrics_by_core_type {
-        time_in_state_cpu: 0
-        core_type: "little"
-        runtime_ms: 20
-        mcycles: 3
-      }
-    }
-  }
-  processes {
-    metadata {
-      name: "com.google.pid11"
-    }
-    metrics_by_core_type {
-      time_in_state_cpu: 2
-      core_type: "little"
-      runtime_ms: 20
-      mcycles: 40
-    }
-    threads {
-      name: "tid11"
-      main_thread: true
-      metrics_by_core_type {
-        time_in_state_cpu: 2
-        core_type: "little"
-        runtime_ms: 10
-        mcycles: 20
-      }
-    }
-    threads {
-      name: "tid12"
-      main_thread: false
-      metrics_by_core_type {
-        time_in_state_cpu: 2
-        core_type: "little"
-        runtime_ms: 10
-        mcycles: 20
-      }
-    }
-  }
-  processes {
-    metadata {
-      name: "com.google.pid17"
-    }
-    metrics_by_core_type {
-      time_in_state_cpu: 0
-      core_type: "little"
-      runtime_ms: 10
-      mcycles: 1
-    }
-    threads {
-      main_thread: true
-      metrics_by_core_type {
-        time_in_state_cpu: 0
-        core_type: "little"
-        runtime_ms: 10
-        mcycles: 1
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/parsing/android_thread_time_in_state_unknown.out b/test/trace_processor/parsing/android_thread_time_in_state_unknown.out
deleted file mode 100644
index 1c7c1c5..0000000
--- a/test/trace_processor/parsing/android_thread_time_in_state_unknown.out
+++ /dev/null
@@ -1,22 +0,0 @@
-android_thread_time_in_state {
-  processes {
-    metadata {
-      name: "com.google.pid5"
-    }
-    metrics_by_core_type {
-      time_in_state_cpu: 0
-      core_type: "unknown"
-      runtime_ms: 20
-      mcycles: 3
-    }
-    threads {
-      main_thread: true
-      metrics_by_core_type {
-        time_in_state_cpu: 0
-        core_type: "unknown"
-        runtime_ms: 20
-        mcycles: 3
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/parsing/bad_print.systrace b/test/trace_processor/parsing/bad_print.systrace
deleted file mode 100644
index cb12780..0000000
--- a/test/trace_processor/parsing/bad_print.systrace
+++ /dev/null
@@ -1,5 +0,0 @@
-           <...>-882   (  882) [003] .... 10852.771186: event: event: abc xyz =0x34 clk id = 019
-some = 000, other = 0x4
-xyz = 0x0 abc = 0x0
-  surfaceflinger-598   (  598) [004] .... 10852.771242: tracing_mark_write: B|598|some event
-  surfaceflinger-598   (  598) [004] .... 10852.771245: tracing_mark_write: E|598
diff --git a/test/trace_processor/parsing/bad_print.textproto b/test/trace_processor/parsing/bad_print.textproto
deleted file mode 100644
index 388946d..0000000
--- a/test/trace_processor/parsing/bad_print.textproto
+++ /dev/null
@@ -1,52 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 3
-    event {
-      timestamp: 74289018336
-      pid: 1
-      print {
-        ip: 18446743562018522420
-        buf: "event: abc xyz =0x34 clk id = 019\n"
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 74662603008
-      pid: 1
-      print {
-        ip: 18446743562018522420
-        buf: "another random print message\n"
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 74662603048
-      pid: 2
-      print {
-        ip: 18446743562018522420
-        buf: "B|2|valid_print\n"
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 74662603050
-      pid: 2
-      print {
-        ip: 18446743562018522420
-        buf: "E|2\n"
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/bad_print_systrace_list_slices.out b/test/trace_processor/parsing/bad_print_systrace_list_slices.out
deleted file mode 100644
index 6b081c8..0000000
--- a/test/trace_processor/parsing/bad_print_systrace_list_slices.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"ts","dur","name"
-10852771242000,3000,"some event"
diff --git a/test/trace_processor/parsing/bad_print_textproto_list_slices.out b/test/trace_processor/parsing/bad_print_textproto_list_slices.out
deleted file mode 100644
index 1f44a90..0000000
--- a/test/trace_processor/parsing/bad_print_textproto_list_slices.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"ts","dur","name"
-74662603048,2,"valid_print"
diff --git a/test/trace_processor/parsing/chrome_metadata.out b/test/trace_processor/parsing/chrome_metadata.out
deleted file mode 100644
index 71e8908..0000000
--- a/test/trace_processor/parsing/chrome_metadata.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"id","type","name","key_type","int_value","str_value"
-0,"metadata","cr-playstore_version_code","single",101,"[NULL]"
-1,"metadata","cr-enabled_categories","single","[NULL]","cat1,cat2,cat3"
-2,"metadata","trace_size_bytes","single",50,"[NULL]"
diff --git a/test/trace_processor/parsing/chrome_metadata.sql b/test/trace_processor/parsing/chrome_metadata.sql
deleted file mode 100644
index 3521cf1..0000000
--- a/test/trace_processor/parsing/chrome_metadata.sql
+++ /dev/null
@@ -1 +0,0 @@
-select * from metadata
diff --git a/test/trace_processor/parsing/chrome_metadata.textproto b/test/trace_processor/parsing/chrome_metadata.textproto
deleted file mode 100644
index f1bcff1..0000000
--- a/test/trace_processor/parsing/chrome_metadata.textproto
+++ /dev/null
@@ -1,18 +0,0 @@
-packet {
-  clock_snapshot {
-    clocks {
-      clock_id: 6
-      timestamp: 101000002
-    }
-  }
-  trusted_packet_sequence_id: 1
-  timestamp: 101000002
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 101000002
-  chrome_metadata {
-    chrome_version_code: 101
-    enabled_categories: "cat1,cat2,cat3"
-  }
-}
diff --git a/test/trace_processor/parsing/config_metadata.out b/test/trace_processor/parsing/config_metadata.out
deleted file mode 100644
index 3a77f45..0000000
--- a/test/trace_processor/parsing/config_metadata.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"name","str_value"
-"android_build_fingerprint","the fingerprint"
-"trace_config_pbtxt","trace_uuid_msb: 1314564453825188563
-trace_uuid_lsb: -6605018796207623390"
-"trace_uuid","123e4567-e89b-12d3-a456-426655443322"
diff --git a/test/trace_processor/parsing/decimal_timestamp_slices.out b/test/trace_processor/parsing/decimal_timestamp_slices.out
deleted file mode 100644
index b64b606..0000000
--- a/test/trace_processor/parsing/decimal_timestamp_slices.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"ts","dur","name"
-5100,500100,"name.exec"
diff --git a/test/trace_processor/parsing/display_time_unit_slices.out b/test/trace_processor/parsing/display_time_unit_slices.out
deleted file mode 100644
index 4343a9e..0000000
--- a/test/trace_processor/parsing/display_time_unit_slices.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"ts","dur","name"
-1597071955492308000,211463000,"add_graph"
diff --git a/test/trace_processor/parsing/flow_events.sql b/test/trace_processor/parsing/flow_events.sql
deleted file mode 100644
index 11ef1a9..0000000
--- a/test/trace_processor/parsing/flow_events.sql
+++ /dev/null
@@ -1,18 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 t1.name as slice_out, t2.name as slice_in from flow t
-join slice t1 on t.slice_out == t1.slice_id
-join slice t2 on t.slice_in == t2.slice_id;
diff --git a/test/trace_processor/parsing/flow_events_json_v1.json b/test/trace_processor/parsing/flow_events_json_v1.json
deleted file mode 100644
index 461aa39..0000000
--- a/test/trace_processor/parsing/flow_events_json_v1.json
+++ /dev/null
@@ -1,123 +0,0 @@
-{
-    "traceEvents": [
-      {
-        "cat": "ipc",
-        "pid": 15902,
-        "tid": 15903,
-        "ts": 3002,
-        "ph": "X",
-        "name": "SenderA",
-        "args":{},
-        "dur": 10
-      },
-      {
-        "cat": "ipc",
-        "pid": 15902,
-        "tid": 15903,
-        "ts": 3002,
-        "ph": "s",
-        "name": "IPC",
-        "args":{},
-        "id":"0x402",
-        "sf": "7"
-      },
-      {
-        "cat": "ipc",
-        "pid": 15903,
-        "tid": 15904,
-        "ts": 0,
-        "ph": "X",
-        "name": "SenderB",
-        "args":{},
-        "dur": 10
-      },
-      {
-        "cat": "ipc",
-        "pid": 15903,
-        "tid": 15904,
-        "ts": 1,
-        "ph": "s",
-        "name": "IPC",
-        "args":{},
-        "id":"0x403"
-      },
-      {
-        "cat": "ipc",
-        "pid": 15875,
-        "tid": 15895,
-        "ts": 1001,
-        "ph": "f",
-        "name": "IPC",
-        "args": {},
-        "id": "0x403"
-      },
-      {
-        "cat": "ipc",
-        "pid": 15875,
-        "tid": 15895,
-        "ts": 1001,
-        "ph": "X",
-        "name": "Blergh",
-        "args": {},
-        "dur": 100
-      },
-      {
-        "cat": "ipc",
-        "pid": 15774,
-        "tid": 15794,
-        "ts": 3200,
-        "ph": "X",
-        "name": "OtherSlice",
-        "args": {},
-        "dur": 500
-      },
-      {
-        "cat": "ipc",
-        "pid": 15774,
-        "tid": 15794,
-        "ts": 3220,
-        "ph": "t",
-        "name": "IPC",
-        "args": {},
-        "id": "0x402",
-        "sf": 8
-      },
-      {
-        "cat": "ipc",
-        "pid": 15874,
-        "tid": 15894,
-        "ts": 3330,
-        "ph": "f",
-        "name": "IPC",
-        "args": {},
-        "id": "0x402",
-        "sf": "1"
-      },
-      {
-        "cat": "ipc",
-        "pid": 15874,
-        "tid": 15894,
-        "ts": 3331,
-        "ph": "X",
-        "name": "SomeSlice",
-        "args": {},
-        "dur": 400
-      }
-    ],
-    "stackFrames": {
-      "1": {
-        "category": "m1",
-        "name": "main"
-      },
-      "7": {
-        "category": "m2",
-        "name": "frame7",
-        "parent": "1"
-      },
-      "8": {
-        "category": "m2",
-        "name": "frame8",
-        "parent": "1"
-      }
-    }
-  }
\ No newline at end of file
diff --git a/test/trace_processor/parsing/flow_events_json_v1.out b/test/trace_processor/parsing/flow_events_json_v1.out
deleted file mode 100644
index 3cef532..0000000
--- a/test/trace_processor/parsing/flow_events_json_v1.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"slice_out","slice_in"
-"SenderB","Blergh"
-"SenderA","OtherSlice"
-"OtherSlice","SomeSlice"
diff --git a/test/trace_processor/parsing/flow_events_json_v2.json b/test/trace_processor/parsing/flow_events_json_v2.json
deleted file mode 100644
index f62e86d..0000000
--- a/test/trace_processor/parsing/flow_events_json_v2.json
+++ /dev/null
@@ -1,86 +0,0 @@
-{
-    "traceEvents": [
-      {
-        "cat": "ipc",
-        "pid": 15902,
-        "tid": 15903,
-        "ts": 3002,
-        "ph": "X",
-        "name": "SenderA",
-        "args":{},
-        "dur": 10,
-        "bind_id": "0x402",
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 15903,
-        "tid": 15904,
-        "ts": 0,
-        "ph": "X",
-        "name": "SenderB",
-        "args":{},
-        "dur": 10,
-        "bind_id": "0x403",
-        "flow_out": true,
-        "flow_in": false
-      },
-      {
-        "cat": "ipc",
-        "pid": 15875,
-        "tid": 15895,
-        "ts": 1001,
-        "ph": "X",
-        "name": "Blergh",
-        "args": {},
-        "dur": 100,
-        "bind_id": "0x403",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 15774,
-        "tid": 15794,
-        "ts": 3200,
-        "ph": "X",
-        "name": "OtherSlice",
-        "args": {},
-        "dur": 500,
-        "bind_id": "0x402",
-        "flow_in": true,
-        "flow_out": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 15874,
-        "tid": 15894,
-        "ts": 3331,
-        "ph": "X",
-        "name": "SomeSlice",
-        "args": {},
-        "dur": 400,
-        "bind_id": "0x402",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 15875,
-        "tid": 15895,
-        "ts": 3333,
-        "ph": "B",
-        "name": "SomeOtherSlice",
-        "args": {},
-        "bind_id": "0x402",
-        "flow_in": true
-      },
-      {
-        "cat": "ipc",
-        "pid": 15875,
-        "tid": 15895,
-        "ts": 4330,
-        "ph": "E",
-        "name": "SomeOtherSlice",
-        "args": {}
-      }
-    ]
-  }
\ No newline at end of file
diff --git a/test/trace_processor/parsing/flow_events_json_v2.out b/test/trace_processor/parsing/flow_events_json_v2.out
deleted file mode 100644
index 3090047..0000000
--- a/test/trace_processor/parsing/flow_events_json_v2.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"slice_out","slice_in"
-"SenderB","Blergh"
-"SenderA","OtherSlice"
-"OtherSlice","SomeSlice"
-"OtherSlice","SomeOtherSlice"
diff --git a/test/trace_processor/parsing/ftrace_with_tracing_start.py b/test/trace_processor/parsing/ftrace_with_tracing_start.py
deleted file mode 100644
index 3ba34f8..0000000
--- a/test/trace_processor/parsing/ftrace_with_tracing_start.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Add a tracing_started packet which should cause all ftrace
-# events before this ts to be dropped.
-packet = trace.add_packet(ts=100)
-packet.service_event.tracing_started = True
-
-# Everything in this packet should be dropped.
-trace.add_ftrace_packet(cpu=0)
-trace.add_sched(ts=50, prev_pid=1, next_pid=2, prev_comm='t1', next_comm='t2')
-trace.add_sched(ts=60, prev_pid=2, next_pid=1, prev_comm='t2', next_comm='t1')
-trace.add_sched(ts=70, prev_pid=1, next_pid=2, prev_comm='t1', next_comm='t2')
-trace.add_sched(
-    ts=80, prev_pid=2, next_pid=0, prev_comm='t2', next_comm='swapper')
-
-# The first 2 slices here should also be dropped but the last one should be
-# retained.
-trace.add_ftrace_packet(cpu=2)
-trace.add_sched(
-    ts=80, prev_pid=0, next_pid=1, prev_comm='swapper', next_comm='t1')
-trace.add_sched(ts=90, prev_pid=1, next_pid=2, prev_comm='t1', next_comm='t2')
-trace.add_sched(ts=100, prev_pid=2, next_pid=1, prev_comm='t2', next_comm='t1')
-trace.add_sched(ts=110, prev_pid=1, next_pid=2, prev_comm='t1', next_comm='t2')
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/ftrace_with_tracing_start_list_sched_slice_spans.out b/test/trace_processor/parsing/ftrace_with_tracing_start_list_sched_slice_spans.out
deleted file mode 100644
index de5e654..0000000
--- a/test/trace_processor/parsing/ftrace_with_tracing_start_list_sched_slice_spans.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"ts","dur","tid"
-100,10,1
-110,0,2
diff --git a/test/trace_processor/parsing/index b/test/trace_processor/parsing/index
deleted file mode 100644
index 4b2ca9a..0000000
--- a/test/trace_processor/parsing/index
+++ /dev/null
@@ -1,144 +0,0 @@
-# Contains tests for parsing events which are applicable to more than one vertical
-# "area". Generally, events here are of high importance (e.g. sched_switch is tested
-# here is and is used by every embedder of trace processor)
-#
-# Note: It's generally *not* advisable to add tests here. Check the guidance provided by
-# http://perfetto/dev/docs/analysis/trace-processor#diff-tests for choosing which folder
-# to add a new test to.
-
-# TODO(lalitm): some tests here should be moved out of here and into the area folders;
-# they are only here because they predate the modularisation of diff tests.
-
-# Sched
-../../data/android_sched_and_ps.pb ts_desc_filter.sql ts_desc_filter_android_sched_and_ps.out
-
-# Sched reason
-../../data/android_sched_and_ps.pb end_reason_eq.sql android_sched_and_ps_end_reason_eq.out
-../../data/android_sched_and_ps.pb end_reason_neq.sql android_sched_and_ps_end_reason_neq.out
-
-# Sched wakeup
-../../data/android_sched_and_ps.pb sched_wakeup.sql sched_wakeup_android_sched_and_ps.out
-
-# CPU Frequency
-../../data/cpu_counters.pb b120487929.sql cpu_counters_b120487929.out
-
-# Test the filtering of ftrace events before tracing_start.
-ftrace_with_tracing_start.py list_sched_slice_spans.sql ftrace_with_tracing_start_list_sched_slice_spans.out
-
-# Rss stats
-rss_stat_mm_id.py rss_stat.sql rss_stat_mm_id.out
-rss_stat_mm_id_clone.py rss_stat.sql rss_stat_mm_id_clone.out
-rss_stat_mm_id_reuse.py rss_stat.sql rss_stat_mm_id_reuse.out
-rss_stat_legacy.py rss_stat.sql rss_stat_legacy.out
-rss_stat_after_free.py rss_stat_after_free.sql rss_stat_after_free.out
-
-# Memory counters
-../../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
-../../data/memory_counters.pb b120605557.sql memory_counters_b120605557.out
-../../data/memory_counters.pb global_memory_counter.sql global_memory_counter_memory_counters.out
-ion_stat.textproto ion_stat.sql ion_stat.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
-
-# 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
-
-# Mm Event
-../../data/mm_event.pb mm_event.sql mm_event.out
-
-# Android userspace async slices
-android_async_slice.textproto process_track_slices.sql process_track_slices_android_async_slice.out
-
-# Check the systrace conversion code in the raw table.
-# Print events
-../../data/lmk_userspace.pb print_systrace.sql print_systrace_lmk_userspace.out
-kernel_tmw_counter.textproto thread_counter_and_track.sql kernel_tmw_counter_thread_counter_and_track.out
-# Unsigned integers
-print_systrace_unsigned.py print_systrace.sql print_systrace_unsigned.out
-
-# Parsing systrace files
-../../data/systrace.html systrace_html.sql systrace_html.out
-../../data/trailing_empty.systrace sched_smoke.sql sched_smoke_trailing_empty.out
-
-# Check error handling when parsing print events.
-bad_print.textproto list_slices.sql bad_print_textproto_list_slices.out
-bad_print.systrace list_slices.sql bad_print_systrace_list_slices.out
-
-# Match legacy Catapult behaviour when we see multiple S events b2b with the same cookie
-# name and upid.
-android_b2b_async_begin.textproto list_slices.sql android_b2b_async_begin_list_slices.out
-
-# LMK handling
-kernel_lmk.py lmk.sql lmk_kernel_lmk.out
-../../data/lmk_userspace.pb lmk.sql lmk_userspace_lmk.out
-../common/oom_kill.textproto oom_kill.sql oom_kill.out
-
-# Logcat
-../../data/android_log.pb android_log_counts.sql android_log_counts.out
-../../data/android_log.pb android_log_msgs.sql android_log_msgs.out
-../../data/android_log_ring_buffer_mode.pb android_log_ring_buffer_mode.sql android_log_ring_buffer_mode.out
-
-# Oom Score
-synth_oom.py oom_query.sql synth_oom_oom_query.out
-../../data/process_stats_poll.pb oom_score_poll.sql process_stats_poll_oom_score.out
-
-# Stats
-../../data/android_sched_and_ps.pb stats.sql android_sched_and_ps_stats.out
-
-# Syscalls
-syscall.py sys.sql sys_syscall.out
-
-# Thread time_in_state
-thread_time_in_state.textproto thread_time_in_state.sql thread_time_in_state.out
-thread_time_in_state_event.py thread_time_in_state_event.sql thread_time_in_state_event.out
-thread_time_in_state.textproto android_thread_time_in_state android_thread_time_in_state.out
-thread_time_in_state_unknown.textproto android_thread_time_in_state android_thread_time_in_state_unknown.out
-
-# Initial display state
-initial_display_state.textproto initial_display_state.sql initial_display_state.out
-
-# Config & metadata
-config_metadata.textproto metadata.sql config_metadata.out
-trigger_packet_trace.textproto triggers_packets.sql triggers_packets_trigger_packet_trace.out
-chrome_metadata.textproto chrome_metadata.sql chrome_metadata.out
-
-# CPU info
-cpu_info.textproto cpu.sql cpu.out
-cpu_info.textproto cpu_freq.sql cpu_freq.out
-
-# Trace size
-../../data/android_sched_and_ps.pb trace_size.sql android_sched_and_ps_trace_size.out
-
-# Package list handling
-android_package_list.py android_package_list android_package_list.out
-
-# Ensures process -> package matching works as expected.
-process_metadata_matching.textproto process_metadata_matching.sql process_metadata_matching.out
-
-# Flow events importing from json
-flow_events_json_v1.json flow_events.sql flow_events_json_v1.out
-flow_events_json_v2.json flow_events.sql flow_events_json_v2.out
-
-# Importing displayTimeUnit
-../../data/display_time_unit.json slices.sql display_time_unit_slices.out
-
-# Parsing sched_blocked_reason
-sched_blocked_proto.py sched_blocked_reason.sql sched_blocked_proto_sched_blocked_reason.out
-sched_blocked_systrace.systrace sched_blocked_reason.sql sched_blocked_systrace_sched_blocked_reason.out
-
-# Kernel symbolization
-sched_blocked_reason_symbolized.textproto sched_blocked_reason_function.sql sched_blocked_reason_symbolized_sched_blocked_reason_function.out
-sched_blocked_reason_symbolized.textproto ../common/to_systrace.sql sched_blocked_reason_symbolized_to_systrace.out
-
-# Floating point numbers
-../../data/decimal_timestamp.json slices.sql decimal_timestamp_slices.out
diff --git a/test/trace_processor/parsing/kernel_lmk.py b/test/trace_processor/parsing/kernel_lmk.py
deleted file mode 100644
index 9b26d4f..0000000
--- a/test/trace_processor/parsing/kernel_lmk.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(pid=1, ppid=0, cmdline="init")
-trace.add_process(pid=2, ppid=1, cmdline="two_thread_process")
-trace.add_process(pid=4, ppid=1, cmdline="single_thread_process")
-
-trace.add_process(pid=1000, ppid=1, cmdline="padding_process")
-trace.add_thread(tid=1301, tgid=1000, cmdline="padding_process_thread_1")
-trace.add_thread(tid=1302, tgid=1000, cmdline="padding_process_thread_2")
-
-trace.add_thread(tid=300, tgid=2, cmdline="two_thread_process")
-
-trace.add_ftrace_packet(0)
-trace.add_kernel_lmk(ts=100, tid=300)
-trace.add_kernel_lmk(ts=101, tid=4)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/kernel_tmw_counter.textproto b/test/trace_processor/parsing/kernel_tmw_counter.textproto
deleted file mode 100644
index 101f953..0000000
--- a/test/trace_processor/parsing/kernel_tmw_counter.textproto
+++ /dev/null
@@ -1,77 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 795572805481
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#15"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 795572870504
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#15"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 795620516581
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#15"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 795620943421
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#15"
-        type: 67
-        value: 1
-      }
-    }
-    event {
-      timestamp: 795623633810
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#15"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 795623633810
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_hw#15"
-        type: 67
-        value: 0
-      }
-    }
-    event {
-      timestamp: 795623739848
-      pid: 237
-      g2d_tracing_mark_write {
-        pid: 237
-        name: "g2d_frame_sw#15"
-        type: 67
-        value: 0
-      }
-    }
-  }
-  trusted_uid: 9999
-  trusted_packet_sequence_id: 3
-}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/kernel_tmw_counter_thread_counter_and_track.out b/test/trace_processor/parsing/kernel_tmw_counter_thread_counter_and_track.out
deleted file mode 100644
index a2037b9..0000000
--- a/test/trace_processor/parsing/kernel_tmw_counter_thread_counter_and_track.out
+++ /dev/null
@@ -1,8 +0,0 @@
-"ts","name","value","tid"
-795572805481,"g2d_frame_hw#15",0.000000,237
-795572870504,"g2d_frame_sw#15",0.000000,237
-795620516581,"g2d_frame_sw#15",1.000000,237
-795620943421,"g2d_frame_hw#15",1.000000,237
-795623633810,"g2d_frame_hw#15",0.000000,237
-795623633810,"g2d_frame_hw#15",0.000000,237
-795623739848,"g2d_frame_sw#15",0.000000,237
diff --git a/test/trace_processor/parsing/list_sched_slice_spans.sql b/test/trace_processor/parsing/list_sched_slice_spans.sql
deleted file mode 100644
index e5122e9..0000000
--- a/test/trace_processor/parsing/list_sched_slice_spans.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-select ts, dur, tid
-from sched
-join thread using(utid)
-order by ts
\ No newline at end of file
diff --git a/test/trace_processor/parsing/list_slices.sql b/test/trace_processor/parsing/list_slices.sql
deleted file mode 100644
index 211ae89..0000000
--- a/test/trace_processor/parsing/list_slices.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-SELECT ts, dur, name
-FROM slice
\ No newline at end of file
diff --git a/test/trace_processor/parsing/print_systrace_unsigned.py b/test/trace_processor/parsing/print_systrace_unsigned.py
deleted file mode 100644
index c63ce57..0000000
--- a/test/trace_processor/parsing/print_systrace_unsigned.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-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_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_after_free.py b/test/trace_processor/parsing/rss_stat_after_free.py
deleted file mode 100644
index ef00a73..0000000
--- a/test/trace_processor/parsing/rss_stat_after_free.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(11, 1, "other_process")
-
-trace.add_ftrace_packet(1)
-
-# Emit an event on an irrelevant thread.
-trace.add_rss_stat(90, tid=11, member=0, size=20, mm_id=0x5678, curr=1)
-
-# Emit an event for the process.
-trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
-
-# Now kill the process.
-trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
-
-# Emit an event on another thread which reuses the struct after free.
-trace.add_rss_stat(103, tid=11, member=0, size=10, mm_id=0x1234, curr=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_legacy.py b/test/trace_processor/parsing/rss_stat_legacy.py
deleted file mode 100644
index 1eeb6c7..0000000
--- a/test/trace_processor/parsing/rss_stat_legacy.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 legacy rss_stat events on old kernels which
-# do not have the mm_id change and thus we cannot accurately track
-# rss changes when one process changes another's mm struct.
-
-from os import sys, path
-
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 0, "process")
-
-trace.add_ftrace_packet(0)
-
-# Create a new child process (treated internally as a thread) of kthreadd.
-trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
-
-# Add an event on tid 3 which affects its own rss.
-trace.add_rss_stat(ts=90, tid=3, member=0, size=9)
-
-# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
-# where kthreadd is cleaning up the mm struct of another process.
-trace.add_rss_stat(ts=91, tid=3, member=0, size=900)
-
-# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
-# where a process reaches into another process' mm struct.
-trace.add_rss_stat(ts=99, tid=10, member=0, size=10)
-
-# Add an event on tid 10 which affects its own rss.
-trace.add_rss_stat(ts=100, tid=10, member=0, size=1000)
-
-# Add an event on tid 10 from tid 3.
-trace.add_rss_stat(ts=101, tid=3, member=0, size=900)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id.py b/test/trace_processor/parsing/rss_stat_mm_id.py
deleted file mode 100644
index b48dab9..0000000
--- a/test/trace_processor/parsing/rss_stat_mm_id.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event.
-
-from os import sys, path
-
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 0, "process")
-
-trace.add_ftrace_packet(0)
-
-# Create a new child process (treated internally as a thread) of kthreadd.
-trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
-
-# Add an event on tid 3 which affects its own rss.
-trace.add_rss_stat(ts=90, tid=3, member=0, size=9, mm_id=4321, curr=True)
-
-# Try to add an event for tid 10. However, as we've not seen an event
-# with curr == True for tid == 10, this event will be dropped.
-trace.add_rss_stat(ts=91, tid=3, member=0, size=900, mm_id=1234, curr=False)
-
-# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
-# where a process reaches into another process' mm struct.
-trace.add_rss_stat(ts=99, tid=10, member=0, size=10, mm_id=4321, curr=False)
-
-# Add an event on tid 10 which affects its own rss.
-trace.add_rss_stat(ts=100, tid=10, member=0, size=1000, mm_id=1234, curr=True)
-
-# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
-# where kthreadd is cleaning up the mm struct of another process.
-trace.add_rss_stat(ts=101, tid=3, member=0, size=900, mm_id=1234, curr=False)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id_clone.py b/test/trace_processor/parsing/rss_stat_mm_id_clone.py
deleted file mode 100644
index 3b36d88..0000000
--- a/test/trace_processor/parsing/rss_stat_mm_id_clone.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event during clone events which have various flag combinations set.
-
-from os import sys, path
-
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-trace.add_process(3, 2, "kernel_thread")
-
-# In this packet, check what happens to userspace processes with different
-# clone flags.
-trace.add_ftrace_packet(1)
-
-# Emit an rss stat event for the main thread of the process to associate it
-# with an mm_id.
-trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
-
-# Create a newtask event emulating vfork/posix_spawn (i.e. CLONE_VM and
-# CLONE_VFORK set).
-trace.add_newtask(
-    101,
-    tid=10,
-    new_tid=11,
-    new_comm="child_process",
-    flags=synth_common.CLONE_VFORK | synth_common.CLONE_VM)
-
-# The child process will now change its own (and parent's) VM space with
-# |curr| set to 1 (emulating cleaning up some memory in parent).
-trace.add_rss_stat(102, tid=11, member=0, size=90, mm_id=0x1234, curr=1)
-
-# At this point, the child process will obtain a new mm struct. From this
-# point on, all mm_ids from the child should be different from the parent.
-
-# The child process will now change its parents VM space with curr set to
-# 0 (emulating e.g. cleaning up its stack).
-trace.add_rss_stat(103, tid=11, member=0, size=85, mm_id=0x1234, curr=0)
-
-# Now the child process should exec another process.
-
-# The child can now change its own memory.
-trace.add_rss_stat(104, tid=11, member=0, size=10, mm_id=0x5678, curr=1)
-
-# The parent can now resume execution and may emit another rss event.
-trace.add_rss_stat(105, tid=10, member=0, size=95, mm_id=0x1234, curr=1)
-
-# The parent can now go ahead and start a new thread.
-trace.add_newtask(
-    106,
-    tid=10,
-    new_tid=12,
-    new_comm="parent_thread",
-    flags=synth_common.CLONE_VM | synth_common.CLONE_THREAD)
-
-# Since this thread shares mm space with the parent, it should have the
-# same mm id and have curr set to 1.
-trace.add_rss_stat(107, tid=12, member=0, size=105, mm_id=0x1234, curr=1)
-
-# The parent can also emit events with the same mm struct at the same time.
-trace.add_rss_stat(108, tid=10, member=0, size=110, mm_id=0x1234, curr=1)
-
-# In this packet, we check what happens to kernel threads in RSS stat.
-trace.add_ftrace_packet(1)
-
-# Emit an rss stat event for the the existing kernel thread.
-trace.add_rss_stat(100, tid=3, member=0, size=10, mm_id=0x2345, curr=1)
-
-# Start a new kernel thread.
-trace.add_newtask(
-    101,
-    tid=2,
-    new_tid=4,
-    new_comm="kernel_thread2",
-    flags=synth_common.CLONE_VM)
-
-# Emit a rss stat for the new kernel thread.
-trace.add_rss_stat(102, tid=4, member=0, size=20, mm_id=0x2345, curr=1)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id_reuse.py b/test/trace_processor/parsing/rss_stat_mm_id_reuse.py
deleted file mode 100644
index 479ed94..0000000
--- a/test/trace_processor/parsing/rss_stat_mm_id_reuse.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 handling of the mm_id field in the rss_stat
-# event when mm_structs are reused on process death.
-
-from os import sys, path
-
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_packet(ts=1)
-trace.add_process(10, 1, "parent_process")
-
-trace.add_ftrace_packet(1)
-
-# Emit an event for the process.
-trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
-
-# Now kill the process.
-trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
-
-# Create a new thread which reuses the pid and mm struct.
-trace.add_newtask(102, tid=1, new_tid=10, new_comm="new_process", flags=0)
-
-# Emit an event for the new thread.
-trace.add_rss_stat(103, tid=10, member=0, size=10, mm_id=0x1234, curr=1)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/sched_blocked_proto.py b/test/trace_processor/parsing/sched_blocked_proto.py
deleted file mode 100644
index a6589f8..0000000
--- a/test/trace_processor/parsing/sched_blocked_proto.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-file_member = 0
-anon_member = 1
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, "init")
-trace.add_process(2, 0, "init2")
-trace.add_process(3, 0, "unblocker")
-
-trace.add_ftrace_packet(0)
-trace.add_sched_blocked_reason(ts=100, pid=1, io_wait=0, unblock_pid=3)
-trace.add_sched_blocked_reason(ts=110, pid=2, io_wait=1, unblock_pid=3)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/sched_blocked_proto_sched_blocked_reason.out b/test/trace_processor/parsing/sched_blocked_proto_sched_blocked_reason.out
deleted file mode 100644
index 910c51c..0000000
--- a/test/trace_processor/parsing/sched_blocked_proto_sched_blocked_reason.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"ts","tid","io_wait"
-100,1,0
-110,2,1
diff --git a/test/trace_processor/parsing/sched_blocked_reason.sql b/test/trace_processor/parsing/sched_blocked_reason.sql
deleted file mode 100644
index 59e26e6..0000000
--- a/test/trace_processor/parsing/sched_blocked_reason.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-select ts, tid, EXTRACT_ARG(arg_set_id, 'io_wait') as io_wait
-from instants
-join thread on instants.ref = thread.utid
-where instants.name = 'sched_blocked_reason'
\ No newline at end of file
diff --git a/test/trace_processor/parsing/sched_blocked_reason_function.sql b/test/trace_processor/parsing/sched_blocked_reason_function.sql
deleted file mode 100644
index 1344d9b..0000000
--- a/test/trace_processor/parsing/sched_blocked_reason_function.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-select
-  ts,
-  thread.tid as pid,
-  EXTRACT_ARG(arg_set_id, 'function') as func
-from instant
-join thread on instant.ref = thread.utid
-where instant.name = 'sched_blocked_reason';
\ No newline at end of file
diff --git a/test/trace_processor/parsing/sched_blocked_reason_symbolized.textproto b/test/trace_processor/parsing/sched_blocked_reason_symbolized.textproto
deleted file mode 100644
index 6b26df0..0000000
--- a/test/trace_processor/parsing/sched_blocked_reason_symbolized.textproto
+++ /dev/null
@@ -1,112 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 1
-    event {
-      timestamp: 1000000
-      pid: 0
-      sched_blocked_reason {
-        pid: 100
-        caller: 1
-        io_wait: 0
-      }
-    }
-    event {
-      timestamp: 1001000
-      pid: 0
-      sched_blocked_reason {
-        pid: 101
-        caller: 2
-        io_wait: 0
-      }
-    }
-  }
-  trusted_uid: 0
-  trusted_packet_sequence_id: 2
-  interned_data {
-    kernel_symbols {
-      iid: 1
-      str: "filemap_fault"
-    }
-  }
-  sequence_flags: 1
-  previous_packet_dropped: true
-}
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 999000
-      pid: 0
-      sched_blocked_reason {
-        pid: 102
-        caller: 1
-        io_wait: 1
-      }
-    }
-    event {
-      timestamp: 1002000
-      pid: 0
-      sched_blocked_reason {
-        pid: 103
-        caller: 2
-        io_wait: 1
-      }
-    }
-    event {
-      timestamp: 1005000
-      pid: 0
-      sched_blocked_reason {
-        pid: 104
-        caller: 1
-        io_wait: 1
-      }
-    }
-  }
-  trusted_uid: 0
-  trusted_packet_sequence_id: 2
-}
-packet {
-  ftrace_events {
-    cpu: 3
-    event {
-      timestamp: 999000
-      pid: 0
-      sched_blocked_reason {
-        pid: 105
-        caller: 3
-        io_wait: 1
-      }
-    }
-  }
-  trusted_uid: 0
-  trusted_packet_sequence_id: 2
-  interned_data {
-    kernel_symbols {
-      iid: 3
-      str: "some_fn"
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 1
-    event {
-      timestamp: 1003000
-      pid: 0
-      sched_blocked_reason {
-        pid: 100
-        caller: 1
-        io_wait: 1
-      }
-    }
-  }
-  trusted_uid: 0
-  trusted_packet_sequence_id: 2
-  interned_data {
-    kernel_symbols {
-      iid: 1
-      str: "some_other_fn"
-    }
-  }
-  sequence_flags: 1
-}
\ No newline at end of file
diff --git a/test/trace_processor/parsing/sched_blocked_reason_symbolized_sched_blocked_reason_function.out b/test/trace_processor/parsing/sched_blocked_reason_symbolized_sched_blocked_reason_function.out
deleted file mode 100644
index 26bf1ac..0000000
--- a/test/trace_processor/parsing/sched_blocked_reason_symbolized_sched_blocked_reason_function.out
+++ /dev/null
@@ -1,8 +0,0 @@
-"ts","pid","func"
-999000,102,"filemap_fault"
-999000,105,"some_fn"
-1000000,100,"filemap_fault"
-1001000,101,"[NULL]"
-1002000,103,"[NULL]"
-1003000,100,"some_other_fn"
-1005000,104,"filemap_fault"
diff --git a/test/trace_processor/parsing/sched_blocked_reason_symbolized_to_systrace.out b/test/trace_processor/parsing/sched_blocked_reason_symbolized_to_systrace.out
deleted file mode 100644
index ea78ae5..0000000
--- a/test/trace_processor/parsing/sched_blocked_reason_symbolized_to_systrace.out
+++ /dev/null
@@ -1,8 +0,0 @@
-"line"
-"          <idle>-0     (-----) [002] .... 0.000999: sched_blocked_reason: pid=102 io_wait=1 caller=filemap_fault"
-"          <idle>-0     (-----) [003] .... 0.000999: sched_blocked_reason: pid=105 io_wait=1 caller=some_fn"
-"          <idle>-0     (-----) [001] .... 0.001000: sched_blocked_reason: pid=100 io_wait=0 caller=filemap_fault"
-"          <idle>-0     (-----) [001] .... 0.001001: sched_blocked_reason: pid=101 io_wait=0 caller=2"
-"          <idle>-0     (-----) [002] .... 0.001002: sched_blocked_reason: pid=103 io_wait=1 caller=2"
-"          <idle>-0     (-----) [001] .... 0.001003: sched_blocked_reason: pid=100 io_wait=1 caller=some_other_fn"
-"          <idle>-0     (-----) [002] .... 0.001005: sched_blocked_reason: pid=104 io_wait=1 caller=filemap_fault"
diff --git a/test/trace_processor/parsing/sched_blocked_systrace.systrace b/test/trace_processor/parsing/sched_blocked_systrace.systrace
deleted file mode 100644
index 81046bf..0000000
--- a/test/trace_processor/parsing/sched_blocked_systrace.systrace
+++ /dev/null
@@ -1,2 +0,0 @@
-           <...>-3694  ( 3694) [006] d..3    20.258854: sched_blocked_reason: pid=269 iowait=0 caller=worker_thread+0x534/0x820
-          <idle>-0     (-----) [000] d.s4    21.123838: sched_blocked_reason: pid=2172 iowait=1 caller=__filemap_fdatawait_range+0x134/0x150
diff --git a/test/trace_processor/parsing/sched_blocked_systrace_sched_blocked_reason.out b/test/trace_processor/parsing/sched_blocked_systrace_sched_blocked_reason.out
deleted file mode 100644
index 87f718c..0000000
--- a/test/trace_processor/parsing/sched_blocked_systrace_sched_blocked_reason.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"ts","tid","io_wait"
-20258854000,269,0
-21123838000,2172,1
diff --git a/test/trace_processor/parsing/sched_slices_sched_switch_compact.out b/test/trace_processor/parsing/sched_slices_sched_switch_compact.out
deleted file mode 100644
index c2f2e7c..0000000
--- a/test/trace_processor/parsing/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"
-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"
-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"
-807082879059487,0,120052,807082879179539,"S",120,22367,"kworker/u16:9"
-807082879179539,0,68398757,807082947578296,"R",120,0,"swapper"
-807082947578296,0,49271,807082947627567,"S",120,28673,"kworker/0:0"
-807082947627567,0,11515782,807082959143349,"R",120,0,"swapper"
-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"
-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"
-807082863150944,1,42760,807082863193704,"S",49,4454,"irq/80-1436400."
-807082863193704,1,1931823,807082865125527,"R",120,0,"swapper"
-807082865125527,1,159532,807082865285059,"D",49,4458,"irq/81-114a000."
-807082865285059,1,34375,807082865319434,"R",120,0,"swapper"
-807082865319434,1,38333,807082865357767,"S",49,4458,"irq/81-114a000."
-807082865357767,1,82176415,807082947534182,"R",120,0,"swapper"
-807082947534182,1,56875,807082947591057,"S",120,28610,"kworker/1:0"
-807082947591057,1,15142918,807082962733975,"R",120,0,"swapper"
-807082962733975,1,77448,807082962811423,"S",120,18,"ksoftirqd/1"
-807082962811423,1,5196563,807082968007986,"R",120,0,"swapper"
-807082968007986,1,268437,807082968276423,"S",98,4009,"bluetooth@1.0-s"
-807082968276423,1,134688,807082968411111,"R",120,0,"swapper"
-807082968411111,1,116718,807082968527829,"S",120,22367,"kworker/u16:9"
-807082968527829,1,62510684,807083031038513,"R",120,0,"swapper"
-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"
-807083032698617,1,276146,807083032974763,"D",120,22367,"kworker/u16:9"
-807083032974763,1,62396,807083033037159,"R",120,0,"swapper"
-807083033037159,1,43437,807083033080596,"S",120,22367,"kworker/u16:9"
-807083033080596,1,0,807083033080596,"R",120,0,"swapper"
-807082865061361,2,399583,807082865460944,"D",120,22367,"kworker/u16:9"
-807082865460944,2,46771,807082865507715,"R",120,0,"swapper"
-807082865507715,2,30312,807082865538027,"S",120,22367,"kworker/u16:9"
-807082865538027,2,2811459,807082868349486,"R",120,0,"swapper"
-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"
-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"
-807082948649130,2,185052,807082948834182,"D",120,22367,"kworker/u16:9"
-807082948834182,2,357239,807082949191421,"R",120,0,"swapper"
-807082949191421,2,55677,807082949247098,"S",120,22367,"kworker/u16:9"
-807082949247098,2,83833498,807083033080596,"R",120,0,"swapper"
-807082947555119,3,37083,807082947592202,"R",120,0,"swapper"
-807082947592202,3,38177,807082947630379,"S",120,7,"rcu_preempt"
-807082947630379,3,4172813,807082951803192,"R",120,0,"swapper"
-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"
-807082862976152,4,14792,807082862990944,"S",120,29207,"traced_probes"
-807082862990944,4,83901102,807082946892046,"R",120,0,"swapper"
-807082946892046,4,327500,807082947219546,"S",120,29207,"traced_probes"
-807082947219546,4,15052,807082947234598,"R",120,0,"swapper"
-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"
-807083030695961,4,104895,807083030800856,"S",120,42,"ksoftirqd/4"
-807083030800856,4,2279740,807083033080596,"R",120,0,"swapper"
-807082952627307,7,1534375,807082954161682,"R",120,0,"swapper"
-807082954161682,7,43490,807082954205172,"S",49,628,"sugov:4"
-807082954205172,7,78875424,807083033080596,"R",120,0,"swapper"
diff --git a/test/trace_processor/parsing/sched_slices_sched_switch_original.out b/test/trace_processor/parsing/sched_slices_sched_switch_original.out
deleted file mode 100644
index 404a588..0000000
--- a/test/trace_processor/parsing/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"
-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"
-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"
-807082879059487,0,120052,807082879179539,"S",120,22367,"kworker/u16:9"
-807082879179539,0,68398757,807082947578296,"R",120,0,"swapper"
-807082947578296,0,49271,807082947627567,"S",120,28673,"kworker/0:0"
-807082947627567,0,11515782,807082959143349,"R",120,0,"swapper"
-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"
-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"
-807082863150944,1,42760,807082863193704,"S",49,4454,"irq/80-1436400."
-807082863193704,1,1931823,807082865125527,"R",120,0,"swapper"
-807082865125527,1,159532,807082865285059,"D",49,4458,"irq/81-114a000."
-807082865285059,1,34375,807082865319434,"R",120,0,"swapper"
-807082865319434,1,38333,807082865357767,"S",49,4458,"irq/81-114a000."
-807082865357767,1,82176415,807082947534182,"R",120,0,"swapper"
-807082947534182,1,56875,807082947591057,"S",120,28610,"kworker/1:0"
-807082947591057,1,15142918,807082962733975,"R",120,0,"swapper"
-807082962733975,1,77448,807082962811423,"S",120,18,"ksoftirqd/1"
-807082962811423,1,5196563,807082968007986,"R",120,0,"swapper"
-807082968007986,1,268437,807082968276423,"S",98,4009,"bluetooth@1.0-s"
-807082968276423,1,134688,807082968411111,"R",120,0,"swapper"
-807082968411111,1,116718,807082968527829,"S",120,22367,"kworker/u16:9"
-807082968527829,1,62510684,807083031038513,"R",120,0,"swapper"
-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"
-807083032698617,1,276146,807083032974763,"D",120,22367,"kworker/u16:9"
-807083032974763,1,62396,807083033037159,"R",120,0,"swapper"
-807083033037159,1,43437,807083033080596,"S",120,22367,"kworker/u16:9"
-807083033080596,1,0,807083033080596,"R",120,0,"swapper"
-807082862645371,2,2415990,807082865061361,"R",120,0,"swapper"
-807082865061361,2,399583,807082865460944,"D",120,22367,"kworker/u16:9"
-807082865460944,2,46771,807082865507715,"R",120,0,"swapper"
-807082865507715,2,30312,807082865538027,"S",120,22367,"kworker/u16:9"
-807082865538027,2,2811459,807082868349486,"R",120,0,"swapper"
-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"
-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"
-807082948649130,2,185052,807082948834182,"D",120,22367,"kworker/u16:9"
-807082948834182,2,357239,807082949191421,"R",120,0,"swapper"
-807082949191421,2,55677,807082949247098,"S",120,22367,"kworker/u16:9"
-807082949247098,2,83833498,807083033080596,"R",120,0,"swapper"
-807082947493504,3,61615,807082947555119,"S",120,28905,"kworker/3:0"
-807082947555119,3,37083,807082947592202,"R",120,0,"swapper"
-807082947592202,3,38177,807082947630379,"S",120,7,"rcu_preempt"
-807082947630379,3,4172813,807082951803192,"R",120,0,"swapper"
-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"
-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"
-807082946892046,4,327500,807082947219546,"S",120,29207,"traced_probes"
-807082947219546,4,15052,807082947234598,"R",120,0,"swapper"
-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"
-807083030695961,4,104895,807083030800856,"S",120,42,"ksoftirqd/4"
-807083030800856,4,2279740,807083033080596,"R",120,0,"swapper"
-807082952486057,7,141250,807082952627307,"D",49,628,"sugov:4"
-807082952627307,7,1534375,807082954161682,"R",120,0,"swapper"
-807082954161682,7,43490,807082954205172,"S",49,628,"sugov:4"
-807082954205172,7,78875424,807083033080596,"R",120,0,"swapper"
diff --git a/test/trace_processor/parsing/slices.sql b/test/trace_processor/parsing/slices.sql
deleted file mode 100644
index d41bd3b..0000000
--- a/test/trace_processor/parsing/slices.sql
+++ /dev/null
@@ -1,17 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 ts, dur, name from slice order by ts desc;
-
diff --git a/test/trace_processor/parsing/stats.sql b/test/trace_processor/parsing/stats.sql
deleted file mode 100644
index d68b28f..0000000
--- a/test/trace_processor/parsing/stats.sql
+++ /dev/null
@@ -1,17 +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 name, idx, severity, source, value
-from stats where name like 'ftrace_cpu_%' or name like 'traced_buf_%';
\ No newline at end of file
diff --git a/test/trace_processor/parsing/synth_oom.py b/test/trace_processor/parsing/synth_oom.py
deleted file mode 100644
index 973835e..0000000
--- a/test/trace_processor/parsing/synth_oom.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-file_member = 0
-anon_member = 1
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, "init")
-trace.add_process(2, 1, "process_a")
-trace.add_process(3, 1, "process_b")
-
-trace.add_ftrace_packet(0)
-trace.add_rss_stat(100, 2, file_member, 100)
-trace.add_rss_stat(100, 2, anon_member, 200)
-trace.add_oom_score_update(100, 1000, 2)
-trace.add_rss_stat(105, 2, file_member, 50)
-trace.add_oom_score_update(107, -300, 2)
-trace.add_rss_stat(110, 2, anon_member, 100)
-trace.add_rss_stat(120, 2, anon_member, 75)
-trace.add_rss_stat(121, 2, file_member, 95)
-trace.add_oom_score_update(122, 300, 2)
-trace.add_rss_stat(123, 2, anon_member, 200)
-trace.add_rss_stat(124, 2, file_member, 75)
-trace.add_rss_stat(125, 2, file_member, 35)
-trace.add_oom_score_update(126, 0, 2)
-trace.add_rss_stat(126, 2, file_member, 0)
-trace.add_rss_stat(126, 2, anon_member, 0)
-
-trace.add_ftrace_packet(0)
-trace.add_rss_stat(104, 3, file_member, 400)
-trace.add_rss_stat(107, 3, anon_member, 300)
-trace.add_oom_score_update(110, 0, 3)
-trace.add_rss_stat(113, 3, file_member, 75)
-trace.add_rss_stat(114, 3, anon_member, 800)
-trace.add_oom_score_update(115, 600, 3)
-trace.add_rss_stat(117, 3, file_member, 25)
-trace.add_rss_stat(118, 3, file_member, 80)
-trace.add_oom_score_update(118, -500, 3)
-trace.add_rss_stat(123, 3, file_member, 85)
-trace.add_rss_stat(126, 3, anon_member, 600)
-trace.add_rss_stat(129, 3, file_member, 90)
-trace.add_oom_score_update(130, 200, 3)
-trace.add_rss_stat(130, 2, file_member, 0)
-trace.add_rss_stat(130, 2, anon_member, 0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/syscall.py b/test/trace_processor/parsing/syscall.py
deleted file mode 100644
index 84ec946..0000000
--- a/test/trace_processor/parsing/syscall.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_system_info(arch='aarch64')
-
-trace.add_packet()
-trace.add_process(pid=1, ppid=0, cmdline="init")
-trace.add_process(pid=2, ppid=1, cmdline="two_thread_process")
-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)
-trace.add_sys_exit(ts=106, tid=1, id=0, ret=0)
-trace.add_sys_exit(ts=110, tid=2, id=1, ret=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/systrace_html.out b/test/trace_processor/parsing/systrace_html.out
deleted file mode 100644
index fccba89..0000000
--- a/test/trace_processor/parsing/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,630,"S",100,630,"kworker/u17:1",1134
-6824711826519000,6,69000,6824711826588000,669,"S",120,669,"kworker/6:1",14833
-6824711826574000,2,133000,6824711826707000,2487,"S",120,739,"UsbFfs-worker",20308
-6824711826588000,6,32000,6824711826620000,5,"S",120,5,"rcu_preempt",7
-6824711826620000,6,72000,6824711826692000,38,"S",120,38,"rcuop/4",44
-6824711826692000,6,16000,6824711826708000,6,"S",120,6,"rcu_sched",8
-6824711826707000,2,81000,6824711826788000,52,"S",120,52,"rcuop/6",60
-6824711826708000,6,352000,6824711827060000,0,"R",120,"[NULL]","swapper",0
-6824711826730000,0,80000,6824711826810000,8,"S",120,8,"rcuop/0",10
-6824711826788000,2,81000,6824711826869000,45,"S",120,45,"rcuop/5",52
-6824711826810000,0,15054000,6824711841864000,0,"R",120,"[NULL]","swapper",0
-6824711826820000,3,33000,6824711826853000,9,"S",120,9,"rcuos/0",11
-6824711826853000,3,54000,6824711826907000,17,"S",120,17,"rcuop/1",20
-6824711826869000,2,165000,6824711827034000,739,"S",120,739,"adbd",20305
-6824711826907000,3,380000,6824711827287000,0,"R",120,"[NULL]","swapper",0
-6824711826997000,1,21000,6824711827018000,18,"S",120,18,"rcuos/1",21
-6824711827018000,1,27430000,6824711854448000,0,"R",120,"[NULL]","swapper",0
-6824711827034000,2,51000,6824711827085000,59,"S",120,59,"rcuop/7",68
-6824711827060000,6,8000,6824711827068000,702,"S",120,702,"kworker/u16:7",19422
-6824711827068000,6,32000,6824711827100000,0,"R",120,"[NULL]","swapper",0
-6824711827085000,2,1808000,6824711828893000,0,"R",120,"[NULL]","swapper",0
-6824711827100000,6,4000,6824711827104000,702,"S",120,702,"kworker/u16:7",19422
-6824711827104000,6,9000,6824711827113000,0,"R",120,"[NULL]","swapper",0
-6824711827113000,6,31000,6824711827144000,702,"S",120,702,"kworker/u16:7",19422
-6824711827138000,7,5000,6824711827143000,711,"S",120,711,"kworker/u16:2",19725
-6824711827143000,7,13961000,6824711841104000,0,"R",120,"[NULL]","swapper",0
-6824711827144000,6,1680000,6824711828824000,0,"R",120,"[NULL]","swapper",0
-6824711827183000,4,899199000,6824712726382000,0,"R",120,"[NULL]","swapper",0
-6824711827287000,3,999000,6824711828286000,2731,"I",120,760,"sh",20447
-6824711828286000,3,281000,6824711828567000,2732,"I",120,739,"shell",20448
-6824711828567000,3,8000,6824711828575000,25,"S",120,25,"rcuos/2",29
-6824711828575000,3,250000,6824711828825000,739,"S",120,739,"adbd",20305
-6824711828824000,6,43000,6824711828867000,630,"S",100,630,"kworker/u17:1",1134
-6824711828825000,3,15722000,6824711844547000,0,"R",120,"[NULL]","swapper",0
-6824711828867000,6,19000,6824711828886000,669,"S",120,669,"kworker/6:1",14833
-6824711828886000,6,64000,6824711828950000,0,"R",120,"[NULL]","swapper",0
-6824711828893000,2,28000,6824711828921000,2487,"S",120,739,"UsbFfs-worker",20308
-6824711828921000,2,72000,6824711828993000,0,"R",120,"[NULL]","swapper",0
-6824711828950000,6,14000,6824711828964000,630,"S",100,630,"kworker/u17:1",1134
-6824711828964000,6,21000,6824711828985000,669,"S",120,669,"kworker/6:1",14833
-6824711828985000,6,4000,6824711828989000,0,"R",120,"[NULL]","swapper",0
-6824711828989000,6,9000,6824711828998000,630,"S",100,630,"kworker/u17:1",1134
-6824711828993000,2,26000,6824711829019000,2487,"S",120,739,"UsbFfs-worker",20308
-6824711828998000,6,102000,6824711829100000,0,"R",120,"[NULL]","swapper",0
-6824711829019000,2,208000,6824711829227000,0,"R",120,"[NULL]","swapper",0
-6824711829100000,6,34000,6824711829134000,630,"S",100,630,"kworker/u17:1",1134
-6824711829134000,6,38000,6824711829172000,0,"R",120,"[NULL]","swapper",0
-6824711829172000,6,16000,6824711829188000,630,"S",100,630,"kworker/u17:1",1134
-6824711829188000,6,23000,6824711829211000,669,"S",120,669,"kworker/6:1",14833
-6824711829211000,6,11000,6824711829222000,0,"R",120,"[NULL]","swapper",0
-6824711829222000,6,33000,6824711829255000,630,"S",100,630,"kworker/u17:1",1134
-6824711829227000,2,70000,6824711829297000,2487,"S",120,739,"UsbFfs-worker",20308
-6824711829255000,6,40000,6824711829295000,0,"R",120,"[NULL]","swapper",0
-6824711829295000,6,13000,6824711829308000,630,"S",100,630,"kworker/u17:1",1134
-6824711829297000,2,153000,6824711829450000,739,"S",120,739,"adbd",20305
-6824711829308000,6,19000,6824711829327000,669,"S",120,669,"kworker/6:1",14833
-6824711829327000,6,75000,6824711829402000,0,"R",120,"[NULL]","swapper",0
-6824711829402000,6,12000,6824711829414000,630,"S",100,630,"kworker/u17:1",1134
-6824711829414000,6,7000,6824711829421000,669,"S",120,669,"kworker/6:1",14833
-6824711829421000,6,16000,6824711829437000,0,"R",120,"[NULL]","swapper",0
-6824711829437000,6,7000,6824711829444000,630,"S",100,630,"kworker/u17:1",1134
-6824711829444000,6,452000,6824711829896000,0,"R",120,"[NULL]","swapper",0
-6824711829450000,2,41000,6824711829491000,2487,"S",120,739,"UsbFfs-worker",20308
-6824711829491000,2,68000,6824711829559000,739,"S",120,739,"adbd",20305
-6824711829559000,2,4671000,6824711834230000,0,"R",120,"[NULL]","swapper",0
-6824711829896000,6,16000,6824711829912000,669,"S",120,669,"kworker/6:1",14833
-6824711829912000,6,3511000,6824711833423000,0,"R",120,"[NULL]","swapper",0
-6824711833250000,5,36000,6824711833286000,483,"S",49,483,"sugov:4",606
-6824711833286000,5,153000,6824711833439000,113,"R+",120,113,"kswapd0",150
-6824711833423000,6,19000,6824711833442000,5,"S",120,5,"rcu_preempt",7
-6824711833439000,5,74000,6824711833513000,24,"S",120,24,"rcuop/2",28
-6824711833442000,6,8000,6824711833450000,6,"S",120,6,"rcu_sched",8
-6824711833450000,6,7442000,6824711840892000,0,"R",120,"[NULL]","swapper",0
-6824711833513000,5,994000,6824711834507000,113,"S",120,113,"kswapd0",150
-6824711834230000,2,26000,6824711834256000,31,"S",120,31,"rcuop/3",36
-6824711834256000,2,5778000,6824711840034000,0,"R",120,"[NULL]","swapper",0
-6824711834507000,5,6564000,6824711841071000,0,"R",120,"[NULL]","swapper",0
-6824711840034000,2,108000,6824711840142000,482,"S",49,482,"sugov:0",605
-6824711840142000,2,74000,6824711840216000,22,"S",120,22,"ksoftirqd/2",25
-6824711840216000,2,1649000,6824711841865000,0,"R",120,"[NULL]","swapper",0
-6824711840892000,6,39000,6824711840931000,5,"S",120,5,"rcu_preempt",7
-6824711840931000,6,24000,6824711840955000,6,"S",120,6,"rcu_sched",8
-6824711840955000,6,143000,6824711841098000,38,"S",120,38,"rcuop/4",44
-6824711841071000,5,11000,6824711841082000,39,"S",120,39,"rcuos/4",45
-6824711841082000,5,5691000,6824711846773000,0,"R",120,"[NULL]","swapper",0
-6824711841098000,6,3082000,6824711844180000,0,"R",120,"[NULL]","swapper",0
-6824711841104000,7,11000,6824711841115000,53,"S",120,53,"rcuos/6",61
-6824711841115000,7,12000,6824711841127000,60,"S",120,60,"rcuos/7",69
-6824711841127000,7,10000,6824711841137000,668,"S",120,668,"kworker/7:2",14813
-6824711841137000,7,290852000,6824712131989000,0,"R",120,"[NULL]","swapper",0
-6824711841864000,0,161000,6824711842025000,8,"S",120,8,"rcuop/0",10
-6824711841865000,2,1300000,6824711843165000,45,"S",120,45,"rcuop/5",52
-6824711842025000,0,12144000,6824711854169000,0,"R",120,"[NULL]","swapper",0
-6824711843165000,2,225000,6824711843390000,52,"R",120,52,"rcuop/6",60
-6824711843390000,2,108000,6824711843498000,482,"S",49,482,"sugov:0",605
-6824711843498000,2,131000,6824711843629000,17,"S",120,17,"rcuop/1",20
-6824711843629000,2,152000,6824711843781000,52,"S",120,52,"rcuop/6",60
-6824711843781000,2,441000,6824711844222000,59,"S",120,59,"rcuop/7",68
-6824711844180000,6,95000,6824711844275000,702,"D",120,702,"kworker/u16:7",19422
-6824711844222000,2,48000,6824711844270000,694,"S",120,694,"kworker/2:0",18823
-6824711844270000,2,2752000,6824711847022000,0,"R",120,"[NULL]","swapper",0
-6824711844275000,6,572000,6824711844847000,0,"R",120,"[NULL]","swapper",0
-6824711844547000,3,172000,6824711844719000,77,"S",120,77,"smem_native_rpm",87
-6824711844719000,3,2190000,6824711846909000,0,"R",120,"[NULL]","swapper",0
-6824711844847000,6,13000,6824711844860000,702,"S",120,702,"kworker/u16:7",19422
-6824711844860000,6,1757000,6824711846617000,0,"R",120,"[NULL]","swapper",0
-6824711846617000,6,22000,6824711846639000,5,"S",120,5,"rcu_preempt",7
-6824711846639000,6,16000,6824711846655000,6,"S",120,6,"rcu_sched",8
-6824711846655000,6,11000,6824711846666000,669,"S",120,669,"kworker/6:1",14833
-6824711846666000,6,149000,6824711846815000,702,"S",120,702,"kworker/u16:7",19422
-6824711846773000,5,35000,6824711846808000,24,"S",120,24,"rcuop/2",28
-6824711846808000,5,88282000,6824711935090000,0,"R",120,"[NULL]","swapper",0
-6824711846815000,6,7290000,6824711854105000,0,"R",120,"[NULL]","swapper",0
-6824711846909000,3,64000,6824711846973000,25,"S",120,25,"rcuos/2",29
-6824711846973000,3,63000,6824711847036000,32,"S",120,32,"rcuos/3",37
-6824711847022000,2,328000,6824711847350000,31,"S",120,31,"rcuop/3",36
-6824711847036000,3,3496000,6824711850532000,0,"R",120,"[NULL]","swapper",0
-6824711847350000,2,8611000,6824711855961000,0,"R",120,"[NULL]","swapper",0
-6824711850532000,3,50000,6824711850582000,29,"S",120,29,"ksoftirqd/3",33
-6824711850582000,3,24018000,6824711874600000,0,"R",120,"[NULL]","swapper",0
-6824711854105000,6,13000,6824711854118000,5,"S",120,5,"rcu_preempt",7
-6824711854118000,6,7000,6824711854125000,6,"S",120,6,"rcu_sched",8
-6824711854125000,6,6654000,6824711860779000,0,"R",120,"[NULL]","swapper",0
-6824711854169000,0,120000,6824711854289000,743,"S",120,743,"kworker/0:5",20371
-6824711854289000,0,462000,6824711854751000,0,"R",120,"[NULL]","swapper",0
-6824711854448000,1,404000,6824711854852000,786,"S",111,494,"SDM_EventThread",685
-6824711854751000,0,327000,6824711855078000,777,"S",120,493,"HwBinder:640_1",721
-6824711854852000,1,326000,6824711855178000,0,"R",120,"[NULL]","swapper",0
-6824711855078000,0,471000,6824711855549000,0,"R",120,"[NULL]","swapper",0
-6824711855178000,1,179000,6824711855357000,771,"S",97,493,"DispSync",676
-6824711855357000,1,545000,6824711855902000,0,"R",120,"[NULL]","swapper",0
-6824711855549000,0,272000,6824711855821000,773,"S",97,493,"app",678
-6824711855821000,0,1794000,6824711857615000,0,"R",120,"[NULL]","swapper",0
-6824711855902000,1,1771000,6824711857673000,644,"S",120,644,"ndroid.systemui",1664
-6824711855961000,2,72000,6824711856033000,771,"S",97,493,"DispSync",676
-6824711856033000,2,5351000,6824711861384000,0,"R",120,"[NULL]","swapper",0
-6824711857615000,0,250000,6824711857865000,770,"S",120,493,"Binder:640_2",675
-6824711857673000,1,347000,6824711858020000,0,"R",120,"[NULL]","swapper",0
-6824711857865000,0,426000,6824711858291000,0,"R",120,"[NULL]","swapper",0
-6824711858020000,1,151000,6824711858171000,773,"S",97,493,"app",678
-6824711858171000,1,29595000,6824711887766000,0,"R",120,"[NULL]","swapper",0
-6824711858291000,0,79000,6824711858370000,771,"S",97,493,"DispSync",676
-6824711858370000,0,1693000,6824711860063000,0,"R",120,"[NULL]","swapper",0
-6824711860063000,0,48000,6824711860111000,3,"S",120,3,"ksoftirqd/0",3
-6824711860111000,0,5836000,6824711865947000,0,"R",120,"[NULL]","swapper",0
-6824711860779000,6,128000,6824711860907000,483,"S",49,483,"sugov:4",606
-6824711860907000,6,78000,6824711860985000,5,"S",120,5,"rcu_preempt",7
-6824711860985000,6,67000,6824711861052000,6,"S",120,6,"rcu_sched",8
-6824711861052000,6,50000,6824711861102000,39,"S",120,39,"rcuos/4",45
-6824711861102000,6,168000,6824711861270000,38,"S",120,38,"rcuop/4",44
-6824711861270000,6,32000,6824711861302000,52,"S",120,52,"rcuop/6",60
-6824711861302000,6,12006000,6824711873308000,0,"R",120,"[NULL]","swapper",0
-6824711861384000,2,457000,6824711861841000,45,"S",120,45,"rcuop/5",52
-6824711861841000,2,27907000,6824711889748000,0,"R",120,"[NULL]","swapper",0
-6824711865947000,0,139000,6824711866086000,482,"S",49,482,"sugov:0",605
-6824711866086000,0,46000,6824711866132000,3,"S",120,3,"ksoftirqd/0",3
-6824711866132000,0,889000,6824711867021000,0,"R",120,"[NULL]","swapper",0
-6824711867021000,0,47000,6824711867068000,3,"S",120,3,"ksoftirqd/0",3
-6824711867068000,0,702000,6824711867770000,0,"R",120,"[NULL]","swapper",0
-6824711867770000,0,70000,6824711867840000,5,"S",120,5,"rcu_preempt",7
-6824711867840000,0,4623000,6824711872463000,0,"R",120,"[NULL]","swapper",0
-6824711872463000,0,52000,6824711872515000,3,"S",120,3,"ksoftirqd/0",3
-6824711872515000,0,868000,6824711873383000,0,"R",120,"[NULL]","swapper",0
-6824711873308000,6,68000,6824711873376000,702,"D",120,702,"kworker/u16:7",19422
-6824711873376000,6,665000,6824711874041000,0,"R",120,"[NULL]","swapper",0
-6824711873383000,0,136000,6824711873519000,5,"S",120,5,"rcu_preempt",7
-6824711873519000,0,76000,6824711873595000,24,"S",120,24,"rcuop/2",28
-6824711873595000,0,115000,6824711873710000,743,"S",120,743,"kworker/0:5",20371
-6824711873710000,0,46000,6824711873756000,8,"S",120,8,"rcuop/0",10
-6824711873756000,0,6329000,6824711880085000,0,"R",120,"[NULL]","swapper",0
-6824711874041000,6,477000,6824711874518000,702,"D",120,702,"kworker/u16:7",19422
-6824711874518000,6,672000,6824711875190000,0,"R",120,"[NULL]","swapper",0
-6824711874600000,3,138000,6824711874738000,77,"S",120,77,"smem_native_rpm",87
-6824711874738000,3,920000,6824711875658000,0,"R",120,"[NULL]","swapper",0
-6824711875190000,6,207000,6824711875397000,702,"D",120,702,"kworker/u16:7",19422
-6824711875397000,6,667000,6824711876064000,0,"R",120,"[NULL]","swapper",0
-6824711875658000,3,86000,6824711875744000,77,"S",120,77,"smem_native_rpm",87
-6824711875744000,3,729000,6824711876473000,0,"R",120,"[NULL]","swapper",0
-6824711876064000,6,202000,6824711876266000,702,"D",120,702,"kworker/u16:7",19422
-6824711876266000,6,110000,6824711876376000,0,"R",120,"[NULL]","swapper",0
-6824711876376000,6,96000,6824711876472000,702,"D",120,702,"kworker/u16:7",19422
-6824711876472000,6,704000,6824711877176000,0,"R",120,"[NULL]","swapper",0
-6824711876473000,3,71000,6824711876544000,77,"S",120,77,"smem_native_rpm",87
-6824711876544000,3,783000,6824711877327000,0,"R",120,"[NULL]","swapper",0
-6824711877176000,6,125000,6824711877301000,702,"D",120,702,"kworker/u16:7",19422
-6824711877301000,6,678000,6824711877979000,0,"R",120,"[NULL]","swapper",0
-6824711877327000,3,143000,6824711877470000,77,"S",120,77,"smem_native_rpm",87
-6824711877470000,3,716000,6824711878186000,0,"R",120,"[NULL]","swapper",0
-6824711877979000,6,198000,6824711878177000,702,"D",120,702,"kworker/u16:7",19422
-6824711878177000,6,472000,6824711878649000,0,"R",120,"[NULL]","swapper",0
-6824711878186000,3,193000,6824711878379000,77,"S",120,77,"smem_native_rpm",87
-6824711878379000,3,469000,6824711878848000,0,"R",120,"[NULL]","swapper",0
-6824711878649000,6,182000,6824711878831000,702,"D",120,702,"kworker/u16:7",19422
-6824711878831000,6,446000,6824711879277000,0,"R",120,"[NULL]","swapper",0
-6824711878848000,3,140000,6824711878988000,77,"S",120,77,"smem_native_rpm",87
-6824711878988000,3,666000,6824711879654000,0,"R",120,"[NULL]","swapper",0
-6824711879277000,6,161000,6824711879438000,702,"D",120,702,"kworker/u16:7",19422
-6824711879438000,6,112000,6824711879550000,0,"R",120,"[NULL]","swapper",0
-6824711879550000,6,82000,6824711879632000,702,"D",120,702,"kworker/u16:7",19422
-6824711879632000,6,169000,6824711879801000,0,"R",120,"[NULL]","swapper",0
-6824711879654000,3,182000,6824711879836000,77,"S",120,77,"smem_native_rpm",87
-6824711879801000,6,192000,6824711879993000,702,"D",120,702,"kworker/u16:7",19422
-6824711879836000,3,398000,6824711880234000,0,"R",120,"[NULL]","swapper",0
-6824711879993000,6,231000,6824711880224000,0,"R",120,"[NULL]","swapper",0
-6824711880085000,0,155000,6824711880240000,3,"S",120,3,"ksoftirqd/0",3
-6824711880224000,6,143000,6824711880367000,702,"D",120,702,"kworker/u16:7",19422
-6824711880234000,3,64000,6824711880298000,77,"S",120,77,"smem_native_rpm",87
-6824711880240000,0,57000,6824711880297000,5,"S",120,5,"rcu_preempt",7
-6824711880297000,0,6382000,6824711886679000,0,"R",120,"[NULL]","swapper",0
-6824711880298000,3,94000,6824711880392000,0,"R",120,"[NULL]","swapper",0
-6824711880367000,6,186000,6824711880553000,0,"R",120,"[NULL]","swapper",0
-6824711880392000,3,202000,6824711880594000,77,"S",120,77,"smem_native_rpm",87
-6824711880553000,6,58000,6824711880611000,702,"S",120,702,"kworker/u16:7",19422
-6824711880594000,3,14276000,6824711894870000,0,"R",120,"[NULL]","swapper",0
-6824711880611000,6,5024000,6824711885635000,0,"R",120,"[NULL]","swapper",0
-6824711885635000,6,44000,6824711885679000,50,"S",120,50,"ksoftirqd/6",57
-6824711885679000,6,8649000,6824711894328000,0,"R",120,"[NULL]","swapper",0
-6824711886679000,0,139000,6824711886818000,5,"S",120,5,"rcu_preempt",7
-6824711886818000,0,59000,6824711886877000,52,"S",120,52,"rcuop/6",60
-6824711886877000,0,585000,6824711887462000,0,"R",120,"[NULL]","swapper",0
-6824711887462000,0,118000,6824711887580000,743,"S",120,743,"kworker/0:5",20371
-6824711887580000,0,455000,6824711888035000,0,"R",120,"[NULL]","swapper",0
-6824711887766000,1,377000,6824711888143000,786,"S",111,494,"SDM_EventThread",685
-6824711888035000,0,327000,6824711888362000,777,"S",120,493,"HwBinder:640_1",721
-6824711888143000,1,88000,6824711888231000,0,"R",120,"[NULL]","swapper",0
-6824711888231000,1,85000,6824711888316000,771,"S",97,493,"DispSync",676
-6824711888316000,1,979000,6824711889295000,0,"R",120,"[NULL]","swapper",0
-6824711888362000,0,604000,6824711888966000,0,"R",120,"[NULL]","swapper",0
-6824711888966000,0,178000,6824711889144000,771,"S",97,493,"DispSync",676
-6824711889144000,0,532000,6824711889676000,0,"R",120,"[NULL]","swapper",0
-6824711889295000,1,275000,6824711889570000,773,"S",97,493,"app",678
-6824711889570000,1,1823000,6824711891393000,0,"R",120,"[NULL]","swapper",0
-6824711889676000,0,1753000,6824711891429000,644,"S",120,644,"ndroid.systemui",1664
-6824711889748000,2,86000,6824711889834000,771,"S",97,493,"DispSync",676
-6824711889834000,2,34646000,6824711924480000,0,"R",120,"[NULL]","swapper",0
-6824711891393000,1,280000,6824711891673000,770,"S",120,493,"Binder:640_2",675
-6824711891429000,0,393000,6824711891822000,0,"R",120,"[NULL]","swapper",0
-6824711891673000,1,472000,6824711892145000,0,"R",120,"[NULL]","swapper",0
-6824711891822000,0,178000,6824711892000000,773,"S",97,493,"app",678
-6824711892000000,0,1451000,6824711893451000,0,"R",120,"[NULL]","swapper",0
-6824711892145000,1,95000,6824711892240000,771,"S",97,493,"DispSync",676
-6824711892240000,1,12180000,6824711904420000,0,"R",120,"[NULL]","swapper",0
-6824711893451000,0,109000,6824711893560000,5,"S",120,5,"rcu_preempt",7
-6824711893560000,0,38000,6824711893598000,24,"S",120,24,"rcuop/2",28
-6824711893598000,0,52000,6824711893650000,8,"S",120,8,"rcuop/0",10
-6824711893650000,0,78000,6824711893728000,743,"D",120,743,"kworker/0:5",20371
-6824711893728000,0,65000,6824711893793000,705,"S",120,705,"kworker/0:1",19511
-6824711893793000,0,59000,6824711893852000,743,"S",120,743,"kworker/0:5",20371
-6824711893852000,0,27555000,6824711921407000,0,"R",120,"[NULL]","swapper",0
-6824711894328000,6,300000,6824711894628000,702,"D",120,702,"kworker/u16:7",19422
-6824711894628000,6,2368000,6824711896996000,0,"R",120,"[NULL]","swapper",0
-6824711894870000,3,77000,6824711894947000,77,"S",120,77,"smem_native_rpm",87
-6824711894947000,3,4289000,6824711899236000,0,"R",120,"[NULL]","swapper",0
-6824711896996000,6,306000,6824711897302000,702,"D",120,702,"kworker/u16:7",19422
-6824711897302000,6,48000,6824711897350000,0,"R",120,"[NULL]","swapper",0
-6824711897350000,6,43000,6824711897393000,50,"S",120,50,"ksoftirqd/6",57
-6824711897393000,6,3585000,6824711900978000,0,"R",120,"[NULL]","swapper",0
-6824711899236000,3,257000,6824711899493000,77,"S",120,77,"smem_native_rpm",87
-6824711899493000,3,4694000,6824711904187000,0,"R",120,"[NULL]","swapper",0
-6824711900978000,6,122000,6824711901100000,702,"S",120,702,"kworker/u16:7",19422
-6824711901100000,6,50000,6824711901150000,0,"R",120,"[NULL]","swapper",0
-6824711901150000,6,40000,6824711901190000,50,"S",120,50,"ksoftirqd/6",57
-6824711901190000,6,826872000,6824712728062000,0,"R",120,"[NULL]","swapper",0
-6824711904187000,3,212000,6824711904399000,77,"S",120,77,"smem_native_rpm",87
-6824711904399000,3,55334000,6824711959733000,0,"R",120,"[NULL]","swapper",0
-6824711904420000,1,72000,6824711904492000,15,"S",120,15,"ksoftirqd/1",17
-6824711904492000,1,14769000,6824711919261000,0,"R",120,"[NULL]","swapper",0
-6824711919261000,1,145000,6824711919406000,15,"S",120,15,"ksoftirqd/1",17
-6824711919406000,1,3219000,6824711922625000,0,"R",120,"[NULL]","swapper",0
-6824711921407000,0,185000,6824711921592000,743,"S",120,743,"kworker/0:5",20371
-6824711921592000,0,726000,6824711922318000,786,"S",111,494,"SDM_EventThread",685
-6824711922318000,0,65000,6824711922383000,0,"R",120,"[NULL]","swapper",0
-6824711922383000,0,57000,6824711922440000,3,"S",120,3,"ksoftirqd/0",3
-6824711922440000,0,585000,6824711923025000,0,"R",120,"[NULL]","swapper",0
-6824711922625000,1,477000,6824711923102000,777,"S",120,493,"HwBinder:640_1",721
-6824711923025000,0,239000,6824711923264000,771,"S",97,493,"DispSync",676
-6824711923102000,1,584000,6824711923686000,0,"R",120,"[NULL]","swapper",0
-6824711923264000,0,1073000,6824711924337000,0,"R",120,"[NULL]","swapper",0
-6824711923686000,1,409000,6824711924095000,773,"S",97,493,"app",678
-6824711924095000,1,2591000,6824711926686000,0,"R",120,"[NULL]","swapper",0
-6824711924337000,0,2416000,6824711926753000,644,"S",120,644,"ndroid.systemui",1664
-6824711924480000,2,93000,6824711924573000,771,"S",97,493,"DispSync",676
-6824711924573000,2,34369000,6824711958942000,0,"R",120,"[NULL]","swapper",0
-6824711926686000,1,341000,6824711927027000,770,"S",120,493,"Binder:640_2",675
-6824711926753000,0,601000,6824711927354000,0,"R",120,"[NULL]","swapper",0
-6824711927027000,1,795000,6824711927822000,0,"R",120,"[NULL]","swapper",0
-6824711927354000,0,186000,6824711927540000,773,"S",97,493,"app",678
-6824711927540000,0,30747000,6824711958287000,0,"R",120,"[NULL]","swapper",0
-6824711927822000,1,86000,6824711927908000,771,"S",97,493,"DispSync",676
-6824711927908000,1,30404000,6824711958312000,0,"R",120,"[NULL]","swapper",0
-6824711935090000,5,59000,6824711935149000,113,"S",120,113,"kswapd0",150
-6824711935149000,5,791709000,6824712726858000,0,"R",120,"[NULL]","swapper",0
-6824711958287000,0,325000,6824711958612000,771,"S",97,493,"DispSync",676
-6824711958312000,1,275000,6824711958587000,15,"S",120,15,"ksoftirqd/1",17
-6824711958587000,1,120000,6824711958707000,693,"S",120,693,"kworker/1:1",18800
-6824711958612000,0,107000,6824711958719000,743,"S",120,743,"kworker/0:5",20371
-6824711958707000,1,827000,6824711959534000,0,"R",120,"[NULL]","swapper",0
-6824711958719000,0,580000,6824711959299000,786,"S",111,494,"SDM_EventThread",685
-6824711958942000,2,402000,6824711959344000,773,"S",97,493,"app",678
-6824711959299000,0,1274000,6824711960573000,702,"R+",120,702,"kworker/u16:7",19422
-6824711959344000,2,862000,6824711960206000,0,"R",120,"[NULL]","swapper",0
-6824711959534000,1,579000,6824711960113000,777,"S",120,493,"HwBinder:640_1",721
-6824711959733000,3,66000,6824711959799000,771,"S",97,493,"DispSync",676
-6824711959799000,3,2784000,6824711962583000,644,"S",120,644,"ndroid.systemui",1664
-6824711960113000,1,3163000,6824711963276000,0,"R",120,"[NULL]","swapper",0
-6824711960206000,2,86000,6824711960292000,771,"S",97,493,"DispSync",676
-6824711960292000,2,31867000,6824711992159000,0,"R",120,"[NULL]","swapper",0
-6824711960573000,0,54000,6824711960627000,77,"S",120,77,"smem_native_rpm",87
-6824711960627000,0,52000,6824711960679000,702,"D",120,702,"kworker/u16:7",19422
-6824711960679000,0,1939000,6824711962618000,0,"R",120,"[NULL]","swapper",0
-6824711962583000,3,212000,6824711962795000,702,"D",120,702,"kworker/u16:7",19422
-6824711962618000,0,399000,6824711963017000,770,"S",120,493,"Binder:640_2",675
-6824711962795000,3,29662000,6824711992457000,0,"R",120,"[NULL]","swapper",0
-6824711963017000,0,225000,6824711963242000,77,"S",120,77,"smem_native_rpm",87
-6824711963242000,0,720000,6824711963962000,0,"R",120,"[NULL]","swapper",0
-6824711963276000,1,193000,6824711963469000,773,"S",97,493,"app",678
-6824711963469000,1,75000,6824711963544000,702,"S",120,702,"kworker/u16:7",19422
-6824711963544000,1,27817000,6824711991361000,0,"R",120,"[NULL]","swapper",0
-6824711963962000,0,93000,6824711964055000,771,"S",97,493,"DispSync",676
-6824711964055000,0,26981000,6824711991036000,0,"R",120,"[NULL]","swapper",0
-6824711991036000,0,265000,6824711991301000,743,"S",120,743,"kworker/0:5",20371
-6824711991301000,0,902000,6824711992203000,786,"S",111,494,"SDM_EventThread",685
-6824711991361000,1,512000,6824711991873000,771,"S",97,493,"DispSync",676
-6824711991873000,1,90000,6824711991963000,0,"R",120,"[NULL]","swapper",0
-6824711991963000,1,86000,6824711992049000,15,"S",120,15,"ksoftirqd/1",17
-6824711992049000,1,1109000,6824711993158000,0,"R",120,"[NULL]","swapper",0
-6824711992159000,2,539000,6824711992698000,773,"S",97,493,"app",678
-6824711992203000,0,811000,6824711993014000,0,"R",120,"[NULL]","swapper",0
-6824711992457000,3,561000,6824711993018000,777,"S",120,493,"HwBinder:640_1",721
-6824711992698000,2,31632000,6824712024330000,0,"R",120,"[NULL]","swapper",0
-6824711993014000,0,3047000,6824711996061000,644,"S",120,644,"ndroid.systemui",1664
-6824711993018000,3,29607000,6824712022625000,0,"R",120,"[NULL]","swapper",0
-6824711993158000,1,88000,6824711993246000,771,"S",97,493,"DispSync",676
-6824711993246000,1,2846000,6824711996092000,0,"R",120,"[NULL]","swapper",0
-6824711996061000,0,723000,6824711996784000,0,"R",120,"[NULL]","swapper",0
-6824711996092000,1,399000,6824711996491000,770,"S",120,493,"Binder:640_2",675
-6824711996491000,1,795000,6824711997286000,0,"R",120,"[NULL]","swapper",0
-6824711996784000,0,206000,6824711996990000,773,"S",97,493,"app",678
-6824711996990000,0,72000,6824711997062000,0,"R",120,"[NULL]","swapper",0
-6824711997062000,0,65000,6824711997127000,3,"S",120,3,"ksoftirqd/0",3
-6824711997127000,0,25255000,6824712022382000,0,"R",120,"[NULL]","swapper",0
-6824711997286000,1,89000,6824711997375000,771,"S",97,493,"DispSync",676
-6824711997375000,1,26567000,6824712023942000,0,"R",120,"[NULL]","swapper",0
-6824712022382000,0,182000,6824712022564000,743,"S",120,743,"kworker/0:5",20371
-6824712022564000,0,1155000,6824712023719000,786,"S",111,494,"SDM_EventThread",685
-6824712022625000,3,91000,6824712022716000,686,"S",120,686,"kworker/3:1",17791
-6824712022716000,3,37690000,6824712060406000,0,"R",120,"[NULL]","swapper",0
-6824712023719000,0,311000,6824712024030000,702,"S",120,702,"kworker/u16:7",19422
-6824712023942000,1,639000,6824712024581000,777,"S",120,493,"HwBinder:640_1",721
-6824712024030000,0,921000,6824712024951000,0,"R",120,"[NULL]","swapper",0
-6824712024330000,2,324000,6824712024654000,771,"S",97,493,"DispSync",676
-6824712024581000,1,1190000,6824712025771000,0,"R",120,"[NULL]","swapper",0
-6824712024654000,2,1208000,6824712025862000,0,"R",120,"[NULL]","swapper",0
-6824712024951000,0,531000,6824712025482000,773,"S",97,493,"app",678
-6824712025482000,0,3497000,6824712028979000,0,"R",120,"[NULL]","swapper",0
-6824712025771000,1,3163000,6824712028934000,644,"S",120,644,"ndroid.systemui",1664
-6824712025862000,2,83000,6824712025945000,771,"S",97,493,"DispSync",676
-6824712025945000,2,34179000,6824712060124000,0,"R",120,"[NULL]","swapper",0
-6824712028934000,1,717000,6824712029651000,0,"R",120,"[NULL]","swapper",0
-6824712028979000,0,393000,6824712029372000,770,"S",120,493,"Binder:640_2",675
-6824712029372000,0,798000,6824712030170000,0,"R",120,"[NULL]","swapper",0
-6824712029651000,1,204000,6824712029855000,773,"S",97,493,"app",678
-6824712029855000,1,29454000,6824712059309000,0,"R",120,"[NULL]","swapper",0
-6824712030170000,0,89000,6824712030259000,771,"S",97,493,"DispSync",676
-6824712030259000,0,70000,6824712030329000,0,"R",120,"[NULL]","swapper",0
-6824712030329000,0,70000,6824712030399000,3,"S",120,3,"ksoftirqd/0",3
-6824712030399000,0,28593000,6824712058992000,0,"R",120,"[NULL]","swapper",0
-6824712058992000,0,265000,6824712059257000,743,"S",120,743,"kworker/0:5",20371
-6824712059257000,0,1001000,6824712060258000,786,"S",111,494,"SDM_EventThread",685
-6824712059309000,1,519000,6824712059828000,771,"S",97,493,"DispSync",676
-6824712059828000,1,364000,6824712060192000,0,"R",120,"[NULL]","swapper",0
-6824712060124000,2,513000,6824712060637000,773,"S",97,493,"app",678
-6824712060192000,1,37000,6824712060229000,15,"S",120,15,"ksoftirqd/1",17
-6824712060229000,1,111000,6824712060340000,693,"S",120,693,"kworker/1:1",18800
-6824712060258000,0,735000,6824712060993000,702,"R+",120,702,"kworker/u16:7",19422
-6824712060340000,1,928000,6824712061268000,0,"R",120,"[NULL]","swapper",0
-6824712060406000,3,546000,6824712060952000,777,"S",120,493,"HwBinder:640_1",721
-6824712060637000,2,31702000,6824712092339000,0,"R",120,"[NULL]","swapper",0
-6824712060952000,3,31540000,6824712092492000,0,"R",120,"[NULL]","swapper",0
-6824712060993000,0,65000,6824712061058000,771,"S",97,493,"DispSync",676
-6824712061058000,0,280000,6824712061338000,702,"S",120,702,"kworker/u16:7",19422
-6824712061268000,1,3172000,6824712064440000,644,"S",120,644,"ndroid.systemui",1664
-6824712061338000,0,3134000,6824712064472000,0,"R",120,"[NULL]","swapper",0
-6824712064440000,1,710000,6824712065150000,0,"R",120,"[NULL]","swapper",0
-6824712064472000,0,400000,6824712064872000,770,"S",120,493,"Binder:640_2",675
-6824712064872000,0,780000,6824712065652000,0,"R",120,"[NULL]","swapper",0
-6824712065150000,1,201000,6824712065351000,773,"S",97,493,"app",678
-6824712065351000,1,10437000,6824712075788000,0,"R",120,"[NULL]","swapper",0
-6824712065652000,0,89000,6824712065741000,771,"S",97,493,"DispSync",676
-6824712065741000,0,24857000,6824712090598000,0,"R",120,"[NULL]","swapper",0
-6824712075788000,1,292000,6824712076080000,1919,"S",120,667,"Executor-7",14762
-6824712076080000,1,88000,6824712076168000,0,"R",120,"[NULL]","swapper",0
-6824712076168000,1,225000,6824712076393000,15,"S",120,15,"ksoftirqd/1",17
-6824712076393000,1,162000,6824712076555000,702,"S",120,702,"kworker/u16:7",19422
-6824712076555000,1,15181000,6824712091736000,0,"R",120,"[NULL]","swapper",0
-6824712090598000,0,224000,6824712090822000,743,"S",120,743,"kworker/0:5",20371
-6824712090822000,0,1321000,6824712092143000,786,"S",111,494,"SDM_EventThread",685
-6824712091736000,1,410000,6824712092146000,771,"S",97,493,"DispSync",676
-6824712092143000,0,90000,6824712092233000,0,"R",120,"[NULL]","swapper",0
-6824712092146000,1,1144000,6824712093290000,0,"R",120,"[NULL]","swapper",0
-6824712092233000,0,79000,6824712092312000,3,"S",120,3,"ksoftirqd/0",3
-6824712092312000,0,820000,6824712093132000,0,"R",120,"[NULL]","swapper",0
-6824712092339000,2,602000,6824712092941000,777,"S",120,493,"HwBinder:640_1",721
-6824712092492000,3,487000,6824712092979000,773,"S",97,493,"app",678
-6824712092941000,2,4352000,6824712097293000,0,"R",120,"[NULL]","swapper",0
-6824712092979000,3,33505000,6824712126484000,0,"R",120,"[NULL]","swapper",0
-6824712093132000,0,90000,6824712093222000,771,"S",97,493,"DispSync",676
-6824712093222000,0,3125000,6824712096347000,0,"R",120,"[NULL]","swapper",0
-6824712093290000,1,3028000,6824712096318000,644,"S",120,644,"ndroid.systemui",1664
-6824712096318000,1,443000,6824712096761000,0,"R",120,"[NULL]","swapper",0
-6824712096347000,0,516000,6824712096863000,770,"S",120,493,"Binder:640_2",675
-6824712096761000,1,208000,6824712096969000,773,"S",97,493,"app",678
-6824712096863000,0,27799000,6824712124662000,0,"R",120,"[NULL]","swapper",0
-6824712096969000,1,28547000,6824712125516000,0,"R",120,"[NULL]","swapper",0
-6824712097293000,2,94000,6824712097387000,771,"S",97,493,"DispSync",676
-6824712097387000,2,27295000,6824712124682000,0,"R",120,"[NULL]","swapper",0
-6824712124662000,0,474000,6824712125136000,771,"S",97,493,"DispSync",676
-6824712124682000,2,304000,6824712124986000,22,"S",120,22,"ksoftirqd/2",25
-6824712124986000,2,1342000,6824712126328000,0,"R",120,"[NULL]","swapper",0
-6824712125136000,0,150000,6824712125286000,743,"S",120,743,"kworker/0:5",20371
-6824712125286000,0,705000,6824712125991000,786,"R+",111,494,"SDM_EventThread",685
-6824712125516000,1,532000,6824712126048000,773,"S",97,493,"app",678
-6824712125991000,0,50000,6824712126041000,771,"S",97,493,"DispSync",676
-6824712126041000,0,199000,6824712126240000,786,"S",111,494,"SDM_EventThread",685
-6824712126048000,1,3632000,6824712129680000,0,"R",120,"[NULL]","swapper",0
-6824712126240000,0,149000,6824712126389000,702,"S",120,702,"kworker/u16:7",19422
-6824712126328000,2,2927000,6824712129255000,644,"S",120,644,"ndroid.systemui",1664
-6824712126389000,0,970000,6824712127359000,0,"R",120,"[NULL]","swapper",0
-6824712126484000,3,712000,6824712127196000,777,"S",120,493,"HwBinder:640_1",721
-6824712127196000,3,32061000,6824712159257000,0,"R",120,"[NULL]","swapper",0
-6824712127359000,0,84000,6824712127443000,771,"S",97,493,"DispSync",676
-6824712127443000,0,1769000,6824712129212000,0,"R",120,"[NULL]","swapper",0
-6824712129212000,0,299000,6824712129511000,770,"S",120,493,"Binder:640_2",675
-6824712129255000,2,29843000,6824712159098000,0,"R",120,"[NULL]","swapper",0
-6824712129511000,0,530000,6824712130041000,0,"R",120,"[NULL]","swapper",0
-6824712129680000,1,177000,6824712129857000,773,"S",97,493,"app",678
-6824712129857000,1,28493000,6824712158350000,0,"R",120,"[NULL]","swapper",0
-6824712130041000,0,88000,6824712130129000,771,"S",97,493,"DispSync",676
-6824712130129000,0,64000,6824712130193000,0,"R",120,"[NULL]","swapper",0
-6824712130193000,0,56000,6824712130249000,3,"S",120,3,"ksoftirqd/0",3
-6824712130249000,0,496000,6824712130745000,0,"R",120,"[NULL]","swapper",0
-6824712130745000,0,331000,6824712131076000,702,"R+",120,702,"kworker/u16:7",19422
-6824712131076000,0,202000,6824712131278000,1199,"D",120,611,"rild",1339
-6824712131278000,0,65000,6824712131343000,702,"R+",120,702,"kworker/u16:7",19422
-6824712131343000,0,671000,6824712132014000,1199,"S",120,611,"rild",1339
-6824712131989000,7,56000,6824712132045000,711,"S",120,711,"kworker/u16:2",19725
-6824712132014000,0,442000,6824712132456000,1187,"S",120,611,"rild",1260
-6824712132045000,7,62353000,6824712194398000,0,"R",120,"[NULL]","swapper",0
-6824712132456000,0,749000,6824712133205000,543,"S",120,543,"suspend@1.0-ser",796
-6824712133205000,0,1823000,6824712135028000,1187,"S",120,611,"rild",1260
-6824712135028000,0,81000,6824712135109000,8,"S",120,8,"rcuop/0",10
-6824712135109000,0,37000,6824712135146000,5,"S",120,5,"rcu_preempt",7
-6824712135146000,0,240000,6824712135386000,543,"S",120,543,"suspend@1.0-ser",796
-6824712135386000,0,65000,6824712135451000,702,"S",120,702,"kworker/u16:7",19422
-6824712135451000,0,5153000,6824712140604000,0,"R",120,"[NULL]","swapper",0
-6824712140604000,0,103000,6824712140707000,5,"S",120,5,"rcu_preempt",7
-6824712140707000,0,133000,6824712140840000,8,"S",120,8,"rcuop/0",10
-6824712140840000,0,16732000,6824712157572000,0,"R",120,"[NULL]","swapper",0
-6824712157572000,0,451000,6824712158023000,743,"S",120,743,"kworker/0:5",20371
-6824712158023000,0,992000,6824712159015000,786,"S",111,494,"SDM_EventThread",685
-6824712158350000,1,452000,6824712158802000,771,"S",97,493,"DispSync",676
-6824712158802000,1,87000,6824712158889000,0,"R",120,"[NULL]","swapper",0
-6824712158889000,1,87000,6824712158976000,15,"S",120,15,"ksoftirqd/1",17
-6824712158976000,1,981000,6824712159957000,0,"R",120,"[NULL]","swapper",0
-6824712159015000,0,478000,6824712159493000,0,"R",120,"[NULL]","swapper",0
-6824712159098000,2,521000,6824712159619000,773,"S",97,493,"app",678
-6824712159257000,3,559000,6824712159816000,777,"S",120,493,"HwBinder:640_1",721
-6824712159493000,0,708000,6824712160201000,644,"R",120,644,"ndroid.systemui",1664
-6824712159619000,2,33324000,6824712192943000,0,"R",120,"[NULL]","swapper",0
-6824712159816000,3,33271000,6824712193087000,0,"R",120,"[NULL]","swapper",0
-6824712159957000,1,87000,6824712160044000,771,"S",97,493,"DispSync",676
-6824712160044000,1,3767000,6824712163811000,0,"R",120,"[NULL]","swapper",0
-6824712160201000,0,878000,6824712161079000,702,"S",120,702,"kworker/u16:7",19422
-6824712161079000,0,86000,6824712161165000,743,"S",120,743,"kworker/0:5",20371
-6824712161165000,0,2618000,6824712163783000,644,"S",120,644,"ndroid.systemui",1664
-6824712163783000,0,718000,6824712164501000,0,"R",120,"[NULL]","swapper",0
-6824712163811000,1,405000,6824712164216000,770,"S",120,493,"Binder:640_2",675
-6824712164216000,1,792000,6824712165008000,0,"R",120,"[NULL]","swapper",0
-6824712164501000,0,203000,6824712164704000,773,"S",97,493,"app",678
-6824712164704000,0,26926000,6824712191630000,0,"R",120,"[NULL]","swapper",0
-6824712165008000,1,88000,6824712165096000,771,"S",97,493,"DispSync",676
-6824712165096000,1,26545000,6824712191641000,0,"R",120,"[NULL]","swapper",0
-6824712191630000,0,479000,6824712192109000,771,"S",97,493,"DispSync",676
-6824712191641000,1,258000,6824712191899000,15,"S",120,15,"ksoftirqd/1",17
-6824712191899000,1,160000,6824712192059000,0,"R",120,"[NULL]","swapper",0
-6824712192059000,1,615000,6824712192674000,773,"S",97,493,"app",678
-6824712192109000,0,139000,6824712192248000,743,"S",120,743,"kworker/0:5",20371
-6824712192248000,0,299000,6824712192547000,702,"S",120,702,"kworker/u16:7",19422
-6824712192547000,0,966000,6824712193513000,786,"S",111,494,"SDM_EventThread",685
-6824712192674000,1,1433000,6824712194107000,0,"R",120,"[NULL]","swapper",0
-6824712192943000,2,3173000,6824712196116000,644,"S",120,644,"ndroid.systemui",1664
-6824712193087000,3,109000,6824712193196000,771,"S",97,493,"DispSync",676
-6824712193196000,3,33652000,6824712226848000,0,"R",120,"[NULL]","swapper",0
-6824712193513000,0,1329000,6824712194842000,0,"R",120,"[NULL]","swapper",0
-6824712194107000,1,556000,6824712194663000,777,"S",120,493,"HwBinder:640_1",721
-6824712194398000,7,72000,6824712194470000,711,"S",120,711,"kworker/u16:2",19725
-6824712194470000,7,52792000,6824712247262000,0,"R",120,"[NULL]","swapper",0
-6824712194663000,1,2149000,6824712196812000,0,"R",120,"[NULL]","swapper",0
-6824712194842000,0,89000,6824712194931000,771,"S",97,493,"DispSync",676
-6824712194931000,0,1217000,6824712196148000,0,"R",120,"[NULL]","swapper",0
-6824712196116000,2,30414000,6824712226530000,0,"R",120,"[NULL]","swapper",0
-6824712196148000,0,385000,6824712196533000,770,"S",120,493,"Binder:640_2",675
-6824712196533000,0,781000,6824712197314000,0,"R",120,"[NULL]","swapper",0
-6824712196812000,1,200000,6824712197012000,773,"S",97,493,"app",678
-6824712197012000,1,28707000,6824712225719000,0,"R",120,"[NULL]","swapper",0
-6824712197314000,0,88000,6824712197402000,771,"S",97,493,"DispSync",676
-6824712197402000,0,28073000,6824712225475000,0,"R",120,"[NULL]","swapper",0
-6824712225475000,0,204000,6824712225679000,743,"S",120,743,"kworker/0:5",20371
-6824712225679000,0,916000,6824712226595000,786,"S",111,494,"SDM_EventThread",685
-6824712225719000,1,521000,6824712226240000,771,"S",97,493,"DispSync",676
-6824712226240000,1,81000,6824712226321000,0,"R",120,"[NULL]","swapper",0
-6824712226321000,1,87000,6824712226408000,15,"S",120,15,"ksoftirqd/1",17
-6824712226408000,1,1183000,6824712227591000,0,"R",120,"[NULL]","swapper",0
-6824712226530000,2,669000,6824712227199000,773,"S",97,493,"app",678
-6824712226595000,0,894000,6824712227489000,0,"R",120,"[NULL]","swapper",0
-6824712226848000,3,546000,6824712227394000,777,"S",120,493,"HwBinder:640_1",721
-6824712227199000,2,32486000,6824712259685000,0,"R",120,"[NULL]","swapper",0
-6824712227394000,3,101387000,6824712328781000,0,"R",120,"[NULL]","swapper",0
-6824712227489000,0,3161000,6824712230650000,644,"S",120,644,"ndroid.systemui",1664
-6824712227591000,1,88000,6824712227679000,771,"S",97,493,"DispSync",676
-6824712227679000,1,3014000,6824712230693000,0,"R",120,"[NULL]","swapper",0
-6824712230650000,0,717000,6824712231367000,0,"R",120,"[NULL]","swapper",0
-6824712230693000,1,394000,6824712231087000,770,"S",120,493,"Binder:640_2",675
-6824712231087000,1,782000,6824712231869000,0,"R",120,"[NULL]","swapper",0
-6824712231367000,0,200000,6824712231567000,773,"S",97,493,"app",678
-6824712231567000,0,13149000,6824712244716000,0,"R",120,"[NULL]","swapper",0
-6824712231869000,1,87000,6824712231956000,771,"S",97,493,"DispSync",676
-6824712231956000,1,12891000,6824712244847000,0,"R",120,"[NULL]","swapper",0
-6824712244716000,0,324000,6824712245040000,1808,"S",120,663,"ogle.android.as",15167
-6824712244847000,1,193000,6824712245040000,1807,"S",120,663,"ogle.android.as",15166
-6824712245040000,0,87000,6824712245127000,0,"R",120,"[NULL]","swapper",0
-6824712245040000,1,14256000,6824712259296000,0,"R",120,"[NULL]","swapper",0
-6824712245127000,0,258000,6824712245385000,3,"S",120,3,"ksoftirqd/0",3
-6824712245385000,0,12652000,6824712258037000,0,"R",120,"[NULL]","swapper",0
-6824712247262000,7,203000,6824712247465000,711,"S",120,711,"kworker/u16:2",19725
-6824712247465000,7,71000,6824712247536000,0,"R",120,"[NULL]","swapper",0
-6824712247536000,7,62000,6824712247598000,57,"S",120,57,"ksoftirqd/7",65
-6824712247598000,7,14402000,6824712262000000,0,"R",120,"[NULL]","swapper",0
-6824712258037000,0,225000,6824712258262000,743,"S",120,743,"kworker/0:5",20371
-6824712258262000,0,1133000,6824712259395000,786,"S",111,494,"SDM_EventThread",685
-6824712259296000,1,626000,6824712259922000,777,"S",120,493,"HwBinder:640_1",721
-6824712259395000,0,83000,6824712259478000,0,"R",120,"[NULL]","swapper",0
-6824712259478000,0,86000,6824712259564000,3,"S",120,3,"ksoftirqd/0",3
-6824712259564000,0,904000,6824712260468000,0,"R",120,"[NULL]","swapper",0
-6824712259685000,2,648000,6824712260333000,771,"S",97,493,"DispSync",676
-6824712259922000,1,1420000,6824712261342000,0,"R",120,"[NULL]","swapper",0
-6824712260333000,2,128000,6824712260461000,694,"S",120,694,"kworker/2:0",18823
-6824712260461000,2,979000,6824712261440000,0,"R",120,"[NULL]","swapper",0
-6824712260468000,0,523000,6824712260991000,773,"S",97,493,"app",678
-6824712260991000,0,3489000,6824712264480000,0,"R",120,"[NULL]","swapper",0
-6824712261342000,1,3074000,6824712264416000,644,"S",120,644,"ndroid.systemui",1664
-6824712261440000,2,98000,6824712261538000,771,"S",97,493,"DispSync",676
-6824712261538000,2,31144000,6824712292682000,0,"R",120,"[NULL]","swapper",0
-6824712262000000,7,773000,6824712262773000,711,"S",120,711,"kworker/u16:2",19725
-6824712262773000,7,467225000,6824712729998000,0,"R",120,"[NULL]","swapper",0
-6824712264416000,1,745000,6824712265161000,0,"R",120,"[NULL]","swapper",0
-6824712264480000,0,399000,6824712264879000,770,"S",120,493,"Binder:640_2",675
-6824712264879000,0,791000,6824712265670000,0,"R",120,"[NULL]","swapper",0
-6824712265161000,1,209000,6824712265370000,773,"S",97,493,"app",678
-6824712265370000,1,26002000,6824712291372000,0,"R",120,"[NULL]","swapper",0
-6824712265670000,0,96000,6824712265766000,771,"S",97,493,"DispSync",676
-6824712265766000,0,19023000,6824712284789000,0,"R",120,"[NULL]","swapper",0
-6824712284789000,0,487000,6824712285276000,1694,"D",100,660,"thermal-engine",2490
-6824712285276000,0,89000,6824712285365000,0,"R",120,"[NULL]","swapper",0
-6824712285365000,0,85000,6824712285450000,3,"S",120,3,"ksoftirqd/0",3
-6824712285450000,0,2460000,6824712287910000,0,"R",120,"[NULL]","swapper",0
-6824712287910000,0,209000,6824712288119000,743,"R+",120,743,"kworker/0:5",20371
-6824712288119000,0,555000,6824712288674000,1694,"S",100,660,"thermal-engine",2490
-6824712288674000,0,111000,6824712288785000,743,"S",120,743,"kworker/0:5",20371
-6824712288785000,0,83000,6824712288868000,0,"R",120,"[NULL]","swapper",0
-6824712288868000,0,79000,6824712288947000,3,"S",120,3,"ksoftirqd/0",3
-6824712288947000,0,1078000,6824712290025000,0,"R",120,"[NULL]","swapper",0
-6824712290025000,0,115000,6824712290140000,743,"S",120,743,"kworker/0:5",20371
-6824712290140000,0,986000,6824712291126000,786,"S",111,494,"SDM_EventThread",685
-6824712291126000,0,55000,6824712291181000,0,"R",120,"[NULL]","swapper",0
-6824712291181000,0,48000,6824712291229000,3,"S",120,3,"ksoftirqd/0",3
-6824712291229000,0,733000,6824712291962000,0,"R",120,"[NULL]","swapper",0
-6824712291372000,1,758000,6824712292130000,777,"S",120,493,"HwBinder:640_1",721
-6824712291962000,0,316000,6824712292278000,771,"S",97,493,"DispSync",676
-6824712292130000,1,1482000,6824712293612000,0,"R",120,"[NULL]","swapper",0
-6824712292278000,0,1237000,6824712293515000,0,"R",120,"[NULL]","swapper",0
-6824712292682000,2,555000,6824712293237000,773,"S",97,493,"app",678
-6824712293237000,2,4208000,6824712297445000,0,"R",120,"[NULL]","swapper",0
-6824712293515000,0,3069000,6824712296584000,644,"S",120,644,"ndroid.systemui",1664
-6824712293612000,1,83000,6824712293695000,771,"S",97,493,"DispSync",676
-6824712293695000,1,2925000,6824712296620000,0,"R",120,"[NULL]","swapper",0
-6824712296584000,0,315000,6824712296899000,0,"R",120,"[NULL]","swapper",0
-6824712296620000,1,373000,6824712296993000,770,"S",120,493,"Binder:640_2",675
-6824712296899000,0,235000,6824712297134000,773,"S",97,493,"app",678
-6824712296993000,1,153000,6824712297146000,711,"S",120,711,"kworker/u16:2",19725
-6824712297134000,0,29796000,6824712326930000,0,"R",120,"[NULL]","swapper",0
-6824712297146000,1,30662000,6824712327808000,0,"R",120,"[NULL]","swapper",0
-6824712297445000,2,91000,6824712297536000,771,"S",97,493,"DispSync",676
-6824712297536000,2,29403000,6824712326939000,0,"R",120,"[NULL]","swapper",0
-6824712326930000,0,479000,6824712327409000,771,"S",97,493,"DispSync",676
-6824712326939000,2,165000,6824712327104000,22,"S",120,22,"ksoftirqd/2",25
-6824712327104000,2,1506000,6824712328610000,0,"R",120,"[NULL]","swapper",0
-6824712327409000,0,171000,6824712327580000,743,"S",120,743,"kworker/0:5",20371
-6824712327580000,0,701000,6824712328281000,786,"R+",111,494,"SDM_EventThread",685
-6824712327808000,1,528000,6824712328336000,773,"S",97,493,"app",678
-6824712328281000,0,52000,6824712328333000,771,"S",97,493,"DispSync",676
-6824712328333000,0,226000,6824712328559000,786,"S",111,494,"SDM_EventThread",685
-6824712328336000,1,4173000,6824712332509000,0,"R",120,"[NULL]","swapper",0
-6824712328559000,0,938000,6824712329497000,0,"R",120,"[NULL]","swapper",0
-6824712328610000,2,3183000,6824712331793000,644,"S",120,644,"ndroid.systemui",1664
-6824712328781000,3,574000,6824712329355000,777,"S",120,493,"HwBinder:640_1",721
-6824712329355000,3,32279000,6824712361634000,0,"R",120,"[NULL]","swapper",0
-6824712329497000,0,87000,6824712329584000,771,"S",97,493,"DispSync",676
-6824712329584000,0,2242000,6824712331826000,0,"R",120,"[NULL]","swapper",0
-6824712331793000,2,29260000,6824712361053000,0,"R",120,"[NULL]","swapper",0
-6824712331826000,0,394000,6824712332220000,770,"S",120,493,"Binder:640_2",675
-6824712332220000,0,790000,6824712333010000,0,"R",120,"[NULL]","swapper",0
-6824712332509000,1,202000,6824712332711000,773,"S",97,493,"app",678
-6824712332711000,1,27609000,6824712360320000,0,"R",120,"[NULL]","swapper",0
-6824712333010000,0,85000,6824712333095000,771,"S",97,493,"DispSync",676
-6824712333095000,0,26074000,6824712359169000,0,"R",120,"[NULL]","swapper",0
-6824712359169000,0,225000,6824712359394000,743,"S",120,743,"kworker/0:5",20371
-6824712359394000,0,1615000,6824712361009000,786,"S",111,494,"SDM_EventThread",685
-6824712360320000,1,440000,6824712360760000,771,"S",97,493,"DispSync",676
-6824712360760000,1,80000,6824712360840000,0,"R",120,"[NULL]","swapper",0
-6824712360840000,1,552000,6824712361392000,777,"S",120,493,"HwBinder:640_1",721
-6824712361009000,0,85000,6824712361094000,743,"S",120,743,"kworker/0:5",20371
-6824712361053000,2,490000,6824712361543000,773,"S",97,493,"app",678
-6824712361094000,0,1024000,6824712362118000,711,"S",120,711,"kworker/u16:2",19725
-6824712361392000,1,52000,6824712361444000,0,"R",120,"[NULL]","swapper",0
-6824712361444000,1,3028000,6824712364472000,644,"S",120,644,"ndroid.systemui",1664
-6824712361543000,2,32596000,6824712394139000,0,"R",120,"[NULL]","swapper",0
-6824712361634000,3,102000,6824712361736000,771,"S",97,493,"DispSync",676
-6824712361736000,3,33366000,6824712395102000,0,"R",120,"[NULL]","swapper",0
-6824712362118000,0,2398000,6824712364516000,0,"R",120,"[NULL]","swapper",0
-6824712364472000,1,724000,6824712365196000,0,"R",120,"[NULL]","swapper",0
-6824712364516000,0,394000,6824712364910000,770,"S",120,493,"Binder:640_2",675
-6824712364910000,0,797000,6824712365707000,0,"R",120,"[NULL]","swapper",0
-6824712365196000,1,209000,6824712365405000,773,"S",97,493,"app",678
-6824712365405000,1,27749000,6824712393154000,0,"R",120,"[NULL]","swapper",0
-6824712365707000,0,88000,6824712365795000,771,"S",97,493,"DispSync",676
-6824712365795000,0,27098000,6824712392893000,0,"R",120,"[NULL]","swapper",0
-6824712392893000,0,266000,6824712393159000,743,"S",120,743,"kworker/0:5",20371
-6824712393154000,1,677000,6824712393831000,771,"S",97,493,"DispSync",676
-6824712393159000,0,1045000,6824712394204000,786,"S",111,494,"SDM_EventThread",685
-6824712393831000,1,936000,6824712394767000,0,"R",120,"[NULL]","swapper",0
-6824712394139000,2,561000,6824712394700000,773,"S",97,493,"app",678
-6824712394204000,0,745000,6824712394949000,0,"R",120,"[NULL]","swapper",0
-6824712394700000,2,32976000,6824712427676000,0,"R",120,"[NULL]","swapper",0
-6824712394767000,1,525000,6824712395292000,777,"S",120,493,"HwBinder:640_1",721
-6824712394949000,0,3133000,6824712398082000,644,"S",120,644,"ndroid.systemui",1664
-6824712395102000,3,102000,6824712395204000,771,"S",97,493,"DispSync",676
-6824712395204000,3,33047000,6824712428251000,0,"R",120,"[NULL]","swapper",0
-6824712395292000,1,2827000,6824712398119000,0,"R",120,"[NULL]","swapper",0
-6824712398082000,0,723000,6824712398805000,0,"R",120,"[NULL]","swapper",0
-6824712398119000,1,404000,6824712398523000,770,"S",120,493,"Binder:640_2",675
-6824712398523000,1,782000,6824712399305000,0,"R",120,"[NULL]","swapper",0
-6824712398805000,0,206000,6824712399011000,773,"S",97,493,"app",678
-6824712399011000,0,27138000,6824712426149000,0,"R",120,"[NULL]","swapper",0
-6824712399305000,1,88000,6824712399393000,771,"S",97,493,"DispSync",676
-6824712399393000,1,27547000,6824712426940000,0,"R",120,"[NULL]","swapper",0
-6824712426149000,0,223000,6824712426372000,743,"S",120,743,"kworker/0:5",20371
-6824712426372000,0,1235000,6824712427607000,786,"S",111,494,"SDM_EventThread",685
-6824712426940000,1,447000,6824712427387000,771,"S",97,493,"DispSync",676
-6824712427387000,1,62000,6824712427449000,0,"R",120,"[NULL]","swapper",0
-6824712427449000,1,556000,6824712428005000,777,"S",120,493,"HwBinder:640_1",721
-6824712427607000,0,142000,6824712427749000,711,"S",120,711,"kworker/u16:2",19725
-6824712427676000,2,485000,6824712428161000,773,"S",97,493,"app",678
-6824712427749000,0,1055000,6824712428804000,0,"R",120,"[NULL]","swapper",0
-6824712428005000,1,3964000,6824712431969000,0,"R",120,"[NULL]","swapper",0
-6824712428161000,2,33130000,6824712461291000,0,"R",120,"[NULL]","swapper",0
-6824712428251000,3,103000,6824712428354000,771,"S",97,493,"DispSync",676
-6824712428354000,3,33090000,6824712461444000,0,"R",120,"[NULL]","swapper",0
-6824712428804000,0,3132000,6824712431936000,644,"S",120,644,"ndroid.systemui",1664
-6824712431936000,0,704000,6824712432640000,0,"R",120,"[NULL]","swapper",0
-6824712431969000,1,397000,6824712432366000,770,"S",120,493,"Binder:640_2",675
-6824712432366000,1,792000,6824712433158000,0,"R",120,"[NULL]","swapper",0
-6824712432640000,0,216000,6824712432856000,773,"S",97,493,"app",678
-6824712432856000,0,26763000,6824712459619000,0,"R",120,"[NULL]","swapper",0
-6824712433158000,1,88000,6824712433246000,771,"S",97,493,"DispSync",676
-6824712433246000,1,27279000,6824712460525000,0,"R",120,"[NULL]","swapper",0
-6824712459619000,0,225000,6824712459844000,743,"S",120,743,"kworker/0:5",20371
-6824712459844000,0,1326000,6824712461170000,786,"S",111,494,"SDM_EventThread",685
-6824712460525000,1,447000,6824712460972000,771,"S",97,493,"DispSync",676
-6824712460972000,1,1100000,6824712462072000,0,"R",120,"[NULL]","swapper",0
-6824712461170000,0,668000,6824712461838000,711,"R+",120,711,"kworker/u16:2",19725
-6824712461291000,2,529000,6824712461820000,773,"S",97,493,"app",678
-6824712461444000,3,570000,6824712462014000,777,"S",120,493,"HwBinder:640_1",721
-6824712461820000,2,32964000,6824712494784000,0,"R",120,"[NULL]","swapper",0
-6824712461838000,0,60000,6824712461898000,771,"S",97,493,"DispSync",676
-6824712461898000,0,133000,6824712462031000,743,"S",120,743,"kworker/0:5",20371
-6824712462014000,3,33363000,6824712495377000,0,"R",120,"[NULL]","swapper",0
-6824712462031000,0,281000,6824712462312000,711,"S",120,711,"kworker/u16:2",19725
-6824712462072000,1,3236000,6824712465308000,644,"S",120,644,"ndroid.systemui",1664
-6824712462312000,0,3049000,6824712465361000,0,"R",120,"[NULL]","swapper",0
-6824712465308000,1,737000,6824712466045000,0,"R",120,"[NULL]","swapper",0
-6824712465361000,0,404000,6824712465765000,770,"S",120,493,"Binder:640_2",675
-6824712465765000,0,787000,6824712466552000,0,"R",120,"[NULL]","swapper",0
-6824712466045000,1,204000,6824712466249000,773,"S",97,493,"app",678
-6824712466249000,1,27754000,6824712494003000,0,"R",120,"[NULL]","swapper",0
-6824712466552000,0,174000,6824712466726000,771,"S",97,493,"DispSync",676
-6824712466726000,0,26386000,6824712493112000,0,"R",120,"[NULL]","swapper",0
-6824712493112000,0,746000,6824712493858000,743,"S",120,743,"kworker/0:5",20371
-6824712493858000,0,917000,6824712494775000,786,"S",111,494,"SDM_EventThread",685
-6824712494003000,1,505000,6824712494508000,771,"S",97,493,"DispSync",676
-6824712494508000,1,79000,6824712494587000,0,"R",120,"[NULL]","swapper",0
-6824712494587000,1,558000,6824712495145000,777,"S",120,493,"HwBinder:640_1",721
-6824712494775000,0,149000,6824712494924000,711,"S",120,711,"kworker/u16:2",19725
-6824712494784000,2,486000,6824712495270000,773,"S",97,493,"app",678
-6824712494924000,0,989000,6824712495913000,0,"R",120,"[NULL]","swapper",0
-6824712495145000,1,3951000,6824712499096000,0,"R",120,"[NULL]","swapper",0
-6824712495270000,2,33176000,6824712528446000,0,"R",120,"[NULL]","swapper",0
-6824712495377000,3,105000,6824712495482000,771,"S",97,493,"DispSync",676
-6824712495482000,3,33062000,6824712528544000,0,"R",120,"[NULL]","swapper",0
-6824712495913000,0,3157000,6824712499070000,644,"S",120,644,"ndroid.systemui",1664
-6824712499070000,0,712000,6824712499782000,0,"R",120,"[NULL]","swapper",0
-6824712499096000,1,408000,6824712499504000,770,"S",120,493,"Binder:640_2",675
-6824712499504000,1,790000,6824712500294000,0,"R",120,"[NULL]","swapper",0
-6824712499782000,0,306000,6824712500088000,773,"S",97,493,"app",678
-6824712500088000,0,26796000,6824712526884000,0,"R",120,"[NULL]","swapper",0
-6824712500294000,1,92000,6824712500386000,771,"S",97,493,"DispSync",676
-6824712500386000,1,27266000,6824712527652000,0,"R",120,"[NULL]","swapper",0
-6824712526884000,0,181000,6824712527065000,743,"S",120,743,"kworker/0:5",20371
-6824712527065000,0,125000,6824712527190000,711,"S",120,711,"kworker/u16:2",19725
-6824712527190000,0,978000,6824712528168000,786,"S",111,494,"SDM_EventThread",685
-6824712527652000,1,437000,6824712528089000,771,"S",97,493,"DispSync",676
-6824712528089000,1,1245000,6824712529334000,0,"R",120,"[NULL]","swapper",0
-6824712528168000,0,70000,6824712528238000,702,"S",120,702,"kworker/u16:7",19422
-6824712528238000,0,994000,6824712529232000,0,"R",120,"[NULL]","swapper",0
-6824712528446000,2,487000,6824712528933000,773,"S",97,493,"app",678
-6824712528544000,3,620000,6824712529164000,777,"S",120,493,"HwBinder:640_1",721
-6824712528933000,2,52000,6824712528985000,0,"R",120,"[NULL]","swapper",0
-6824712528985000,2,78000,6824712529063000,773,"S",97,493,"app",678
-6824712529063000,2,32595000,6824712561658000,0,"R",120,"[NULL]","swapper",0
-6824712529164000,3,33240000,6824712562404000,0,"R",120,"[NULL]","swapper",0
-6824712529232000,0,835000,6824712530067000,644,"R",120,644,"ndroid.systemui",1664
-6824712529334000,1,86000,6824712529420000,771,"S",97,493,"DispSync",676
-6824712529420000,1,3171000,6824712532591000,0,"R",120,"[NULL]","swapper",0
-6824712530067000,0,157000,6824712530224000,1920,"S",120,667,"Executor-7",14763
-6824712530224000,0,2349000,6824712532573000,644,"S",120,644,"ndroid.systemui",1664
-6824712532573000,0,701000,6824712533274000,0,"R",120,"[NULL]","swapper",0
-6824712532591000,1,395000,6824712532986000,770,"S",120,493,"Binder:640_2",675
-6824712532986000,1,786000,6824712533772000,0,"R",120,"[NULL]","swapper",0
-6824712533274000,0,198000,6824712533472000,773,"S",97,493,"app",678
-6824712533472000,0,70000,6824712533542000,0,"R",120,"[NULL]","swapper",0
-6824712533542000,0,67000,6824712533609000,3,"S",120,3,"ksoftirqd/0",3
-6824712533609000,0,26476000,6824712560085000,0,"R",120,"[NULL]","swapper",0
-6824712533772000,1,89000,6824712533861000,771,"S",97,493,"DispSync",676
-6824712533861000,1,27413000,6824712561274000,0,"R",120,"[NULL]","swapper",0
-6824712560085000,0,224000,6824712560309000,743,"S",120,743,"kworker/0:5",20371
-6824712560309000,0,1129000,6824712561438000,786,"S",111,494,"SDM_EventThread",685
-6824712561274000,1,622000,6824712561896000,777,"S",120,493,"HwBinder:640_1",721
-6824712561438000,0,79000,6824712561517000,0,"R",120,"[NULL]","swapper",0
-6824712561517000,0,189000,6824712561706000,3,"S",120,3,"ksoftirqd/0",3
-6824712561658000,2,329000,6824712561987000,771,"S",97,493,"DispSync",676
-6824712561706000,0,1079000,6824712562785000,702,"S",120,702,"kworker/u16:7",19422
-6824712561896000,1,1355000,6824712563251000,0,"R",120,"[NULL]","swapper",0
-6824712561987000,2,1400000,6824712563387000,0,"R",120,"[NULL]","swapper",0
-6824712562404000,3,576000,6824712562980000,773,"S",97,493,"app",678
-6824712562785000,0,106000,6824712562891000,743,"S",120,743,"kworker/0:5",20371
-6824712562891000,0,3455000,6824712566346000,0,"R",120,"[NULL]","swapper",0
-6824712562980000,3,66067000,6824712629047000,0,"R",120,"[NULL]","swapper",0
-6824712563251000,1,3044000,6824712566295000,644,"S",120,644,"ndroid.systemui",1664
-6824712563387000,2,84000,6824712563471000,771,"S",97,493,"DispSync",676
-6824712563471000,2,66000,6824712563537000,0,"R",120,"[NULL]","swapper",0
-6824712563537000,2,61000,6824712563598000,22,"S",120,22,"ksoftirqd/2",25
-6824712563598000,2,28176000,6824712591774000,0,"R",120,"[NULL]","swapper",0
-6824712566295000,1,912000,6824712567207000,0,"R",120,"[NULL]","swapper",0
-6824712566346000,0,580000,6824712566926000,770,"S",120,493,"Binder:640_2",675
-6824712566926000,0,798000,6824712567724000,0,"R",120,"[NULL]","swapper",0
-6824712567207000,1,209000,6824712567416000,773,"S",97,493,"app",678
-6824712567416000,1,25855000,6824712593271000,0,"R",120,"[NULL]","swapper",0
-6824712567724000,0,90000,6824712567814000,771,"S",97,493,"DispSync",676
-6824712567814000,0,23951000,6824712591765000,0,"R",120,"[NULL]","swapper",0
-6824712591765000,0,69000,6824712591834000,3,"S",120,3,"ksoftirqd/0",3
-6824712591774000,2,643000,6824712592417000,479,"S",120,479,"hwservicemanage",602
-6824712591834000,0,141000,6824712591975000,743,"S",120,743,"kworker/0:5",20371
-6824712591975000,0,943000,6824712592918000,786,"S",111,494,"SDM_EventThread",685
-6824712592417000,2,1974000,6824712594391000,0,"R",120,"[NULL]","swapper",0
-6824712592918000,0,855000,6824712593773000,0,"R",120,"[NULL]","swapper",0
-6824712593271000,1,748000,6824712594019000,777,"S",120,493,"HwBinder:640_1",721
-6824712593773000,0,313000,6824712594086000,771,"S",97,493,"DispSync",676
-6824712594019000,1,75000,6824712594094000,0,"R",120,"[NULL]","swapper",0
-6824712594086000,0,1123000,6824712595209000,0,"R",120,"[NULL]","swapper",0
-6824712594094000,1,73000,6824712594167000,15,"S",120,15,"ksoftirqd/1",17
-6824712594167000,1,1145000,6824712595312000,0,"R",120,"[NULL]","swapper",0
-6824712594391000,2,543000,6824712594934000,773,"S",97,493,"app",678
-6824712594934000,2,33189000,6824712628123000,0,"R",120,"[NULL]","swapper",0
-6824712595209000,0,3193000,6824712598402000,644,"S",120,644,"ndroid.systemui",1664
-6824712595312000,1,84000,6824712595396000,771,"S",97,493,"DispSync",676
-6824712595396000,1,3046000,6824712598442000,0,"R",120,"[NULL]","swapper",0
-6824712598402000,0,638000,6824712599040000,0,"R",120,"[NULL]","swapper",0
-6824712598442000,1,395000,6824712598837000,770,"S",120,493,"Binder:640_2",675
-6824712598837000,1,566000,6824712599403000,0,"R",120,"[NULL]","swapper",0
-6824712599040000,0,182000,6824712599222000,773,"S",97,493,"app",678
-6824712599222000,0,27826000,6824712627048000,0,"R",120,"[NULL]","swapper",0
-6824712599403000,1,87000,6824712599490000,771,"S",97,493,"DispSync",676
-6824712599490000,1,27821000,6824712627311000,0,"R",120,"[NULL]","swapper",0
-6824712627048000,0,215000,6824712627263000,743,"S",120,743,"kworker/0:5",20371
-6824712627263000,0,865000,6824712628128000,786,"S",111,494,"SDM_EventThread",685
-6824712627311000,1,535000,6824712627846000,771,"S",97,493,"DispSync",676
-6824712627846000,1,97000,6824712627943000,0,"R",120,"[NULL]","swapper",0
-6824712627943000,1,143000,6824712628086000,15,"S",120,15,"ksoftirqd/1",17
-6824712628086000,1,559000,6824712628645000,777,"S",120,493,"HwBinder:640_1",721
-6824712628123000,2,487000,6824712628610000,773,"S",97,493,"app",678
-6824712628128000,0,134000,6824712628262000,702,"S",120,702,"kworker/u16:7",19422
-6824712628262000,0,1140000,6824712629402000,0,"R",120,"[NULL]","swapper",0
-6824712628610000,2,29797000,6824712658407000,0,"R",120,"[NULL]","swapper",0
-6824712628645000,1,4458000,6824712633103000,0,"R",120,"[NULL]","swapper",0
-6824712629047000,3,3339000,6824712632386000,644,"S",120,644,"ndroid.systemui",1664
-6824712629402000,0,86000,6824712629488000,771,"S",97,493,"DispSync",676
-6824712629488000,0,2932000,6824712632420000,0,"R",120,"[NULL]","swapper",0
-6824712632386000,3,20618000,6824712653004000,0,"R",120,"[NULL]","swapper",0
-6824712632420000,0,405000,6824712632825000,770,"S",120,493,"Binder:640_2",675
-6824712632825000,0,777000,6824712633602000,0,"R",120,"[NULL]","swapper",0
-6824712633103000,1,300000,6824712633403000,773,"S",97,493,"app",678
-6824712633403000,1,24713000,6824712658116000,0,"R",120,"[NULL]","swapper",0
-6824712633602000,0,89000,6824712633691000,771,"S",97,493,"DispSync",676
-6824712633691000,0,8761000,6824712642452000,0,"R",120,"[NULL]","swapper",0
-6824712642452000,0,1867000,6824712644319000,702,"R+",120,702,"kworker/u16:7",19422
-6824712644319000,0,91000,6824712644410000,458,"S",100,458,"kworker/0:1H",558
-6824712644410000,0,777000,6824712645187000,711,"D",120,711,"kworker/u16:2",19725
-6824712645187000,0,70000,6824712645257000,77,"S",120,77,"smem_native_rpm",87
-6824712645257000,0,107000,6824712645364000,702,"S",120,702,"kworker/u16:7",19422
-6824712645364000,0,605000,6824712645969000,0,"R",120,"[NULL]","swapper",0
-6824712645969000,0,204000,6824712646173000,711,"D",120,711,"kworker/u16:2",19725
-6824712646173000,0,123000,6824712646296000,77,"S",120,77,"smem_native_rpm",87
-6824712646296000,0,140000,6824712646436000,711,"D",120,711,"kworker/u16:2",19725
-6824712646436000,0,48000,6824712646484000,77,"S",120,77,"smem_native_rpm",87
-6824712646484000,0,171000,6824712646655000,0,"R",120,"[NULL]","swapper",0
-6824712646655000,0,46000,6824712646701000,458,"S",100,458,"kworker/0:1H",558
-6824712646701000,0,144000,6824712646845000,711,"D",120,711,"kworker/u16:2",19725
-6824712646845000,0,124000,6824712646969000,77,"S",120,77,"smem_native_rpm",87
-6824712646969000,0,167000,6824712647136000,711,"D",120,711,"kworker/u16:2",19725
-6824712647136000,0,49000,6824712647185000,77,"S",120,77,"smem_native_rpm",87
-6824712647185000,0,104000,6824712647289000,0,"R",120,"[NULL]","swapper",0
-6824712647289000,0,146000,6824712647435000,711,"D",120,711,"kworker/u16:2",19725
-6824712647435000,0,48000,6824712647483000,77,"S",120,77,"smem_native_rpm",87
-6824712647483000,0,945000,6824712648428000,0,"R",120,"[NULL]","swapper",0
-6824712648428000,0,169000,6824712648597000,711,"D",120,711,"kworker/u16:2",19725
-6824712648597000,0,119000,6824712648716000,77,"S",120,77,"smem_native_rpm",87
-6824712648716000,0,149000,6824712648865000,711,"D",120,711,"kworker/u16:2",19725
-6824712648865000,0,54000,6824712648919000,77,"S",120,77,"smem_native_rpm",87
-6824712648919000,0,62000,6824712648981000,0,"R",120,"[NULL]","swapper",0
-6824712648981000,0,150000,6824712649131000,711,"D",120,711,"kworker/u16:2",19725
-6824712649131000,0,113000,6824712649244000,77,"S",120,77,"smem_native_rpm",87
-6824712649244000,0,139000,6824712649383000,711,"D",120,711,"kworker/u16:2",19725
-6824712649383000,0,48000,6824712649431000,77,"S",120,77,"smem_native_rpm",87
-6824712649431000,0,72000,6824712649503000,0,"R",120,"[NULL]","swapper",0
-6824712649503000,0,130000,6824712649633000,711,"R+",120,711,"kworker/u16:2",19725
-6824712649633000,0,28000,6824712649661000,77,"S",120,77,"smem_native_rpm",87
-6824712649661000,0,41000,6824712649702000,711,"D",120,711,"kworker/u16:2",19725
-6824712649702000,0,58000,6824712649760000,0,"R",120,"[NULL]","swapper",0
-6824712649760000,0,262000,6824712650022000,711,"R+",120,711,"kworker/u16:2",19725
-6824712650022000,0,45000,6824712650067000,458,"S",100,458,"kworker/0:1H",558
-6824712650067000,0,34000,6824712650101000,77,"S",120,77,"smem_native_rpm",87
-6824712650101000,0,134000,6824712650235000,711,"R+",120,711,"kworker/u16:2",19725
-6824712650235000,0,27000,6824712650262000,77,"S",120,77,"smem_native_rpm",87
-6824712650262000,0,42000,6824712650304000,711,"D",120,711,"kworker/u16:2",19725
-6824712650304000,0,91000,6824712650395000,0,"R",120,"[NULL]","swapper",0
-6824712650395000,0,177000,6824712650572000,711,"R+",120,711,"kworker/u16:2",19725
-6824712650572000,0,63000,6824712650635000,77,"S",120,77,"smem_native_rpm",87
-6824712650635000,0,222000,6824712650857000,711,"D",120,711,"kworker/u16:2",19725
-6824712650857000,0,1177000,6824712652034000,0,"R",120,"[NULL]","swapper",0
-6824712652034000,0,108000,6824712652142000,711,"R+",120,711,"kworker/u16:2",19725
-6824712652142000,0,349000,6824712652491000,702,"S",120,702,"kworker/u16:7",19422
-6824712652491000,0,379000,6824712652870000,711,"S",120,711,"kworker/u16:2",19725
-6824712652870000,0,45000,6824712652915000,702,"S",120,702,"kworker/u16:7",19422
-6824712652915000,0,447000,6824712653362000,0,"R",120,"[NULL]","swapper",0
-6824712653004000,3,59000,6824712653063000,469,"S",100,469,"kworker/3:1H",578
-6824712653063000,3,70763000,6824712723826000,0,"R",120,"[NULL]","swapper",0
-6824712653362000,0,46000,6824712653408000,458,"S",100,458,"kworker/0:1H",558
-6824712653408000,0,4244000,6824712657652000,0,"R",120,"[NULL]","swapper",0
-6824712657652000,0,93000,6824712657745000,743,"S",120,743,"kworker/0:5",20371
-6824712657745000,0,488000,6824712658233000,786,"S",111,494,"SDM_EventThread",685
-6824712658116000,1,447000,6824712658563000,777,"S",120,493,"HwBinder:640_1",721
-6824712658233000,0,57000,6824712658290000,0,"R",120,"[NULL]","swapper",0
-6824712658290000,0,53000,6824712658343000,3,"S",120,3,"ksoftirqd/0",3
-6824712658343000,0,1697000,6824712660040000,0,"R",120,"[NULL]","swapper",0
-6824712658407000,2,117000,6824712658524000,771,"S",97,493,"DispSync",676
-6824712658524000,2,2025000,6824712660549000,0,"R",120,"[NULL]","swapper",0
-6824712658563000,1,1537000,6824712660100000,0,"R",120,"[NULL]","swapper",0
-6824712660040000,0,97000,6824712660137000,743,"S",120,743,"kworker/0:5",20371
-6824712660100000,1,184000,6824712660284000,771,"S",97,493,"DispSync",676
-6824712660137000,0,391000,6824712660528000,702,"S",120,702,"kworker/u16:7",19422
-6824712660284000,1,748000,6824712661032000,0,"R",120,"[NULL]","swapper",0
-6824712660528000,0,434000,6824712660962000,0,"R",120,"[NULL]","swapper",0
-6824712660549000,2,334000,6824712660883000,773,"S",97,493,"app",678
-6824712660883000,2,33798000,6824712694681000,0,"R",120,"[NULL]","swapper",0
-6824712660962000,0,1928000,6824712662890000,644,"S",120,644,"ndroid.systemui",1664
-6824712661032000,1,82000,6824712661114000,771,"S",97,493,"DispSync",676
-6824712661114000,1,1692000,6824712662806000,0,"R",120,"[NULL]","swapper",0
-6824712662806000,1,304000,6824712663110000,770,"S",120,493,"Binder:640_2",675
-6824712662890000,0,402000,6824712663292000,0,"R",120,"[NULL]","swapper",0
-6824712663110000,1,497000,6824712663607000,0,"R",120,"[NULL]","swapper",0
-6824712663292000,0,190000,6824712663482000,773,"S",97,493,"app",678
-6824712663482000,0,57000,6824712663539000,0,"R",120,"[NULL]","swapper",0
-6824712663539000,0,53000,6824712663592000,3,"S",120,3,"ksoftirqd/0",3
-6824712663592000,0,2553000,6824712666145000,0,"R",120,"[NULL]","swapper",0
-6824712663607000,1,90000,6824712663697000,771,"S",97,493,"DispSync",676
-6824712663697000,1,25560000,6824712689257000,0,"R",120,"[NULL]","swapper",0
-6824712666145000,0,109000,6824712666254000,77,"S",120,77,"smem_native_rpm",87
-6824712666254000,0,23413000,6824712689667000,0,"R",120,"[NULL]","swapper",0
-6824712689257000,1,201000,6824712689458000,15,"S",120,15,"ksoftirqd/1",17
-6824712689458000,1,81000,6824712689539000,693,"D",120,693,"kworker/1:1",18800
-6824712689539000,1,2472000,6824712692011000,0,"R",120,"[NULL]","swapper",0
-6824712689667000,0,99000,6824712689766000,702,"S",120,702,"kworker/u16:7",19422
-6824712689766000,0,1565000,6824712691331000,0,"R",120,"[NULL]","swapper",0
-6824712691331000,0,95000,6824712691426000,743,"S",120,743,"kworker/0:5",20371
-6824712691426000,0,518000,6824712691944000,786,"S",111,494,"SDM_EventThread",685
-6824712691944000,0,66000,6824712692010000,0,"R",120,"[NULL]","swapper",0
-6824712692010000,0,52000,6824712692062000,3,"S",120,3,"ksoftirqd/0",3
-6824712692011000,1,436000,6824712692447000,777,"S",120,493,"HwBinder:640_1",721
-6824712692062000,0,412000,6824712692474000,0,"R",120,"[NULL]","swapper",0
-6824712692447000,1,1171000,6824712693618000,0,"R",120,"[NULL]","swapper",0
-6824712692474000,0,113000,6824712692587000,771,"S",97,493,"DispSync",676
-6824712692587000,0,1292000,6824712693879000,0,"R",120,"[NULL]","swapper",0
-6824712693618000,1,43000,6824712693661000,15,"S",120,15,"ksoftirqd/1",17
-6824712693661000,1,535000,6824712694196000,0,"R",120,"[NULL]","swapper",0
-6824712693879000,0,175000,6824712694054000,771,"S",97,493,"DispSync",676
-6824712694054000,0,541000,6824712694595000,0,"R",120,"[NULL]","swapper",0
-6824712694196000,1,322000,6824712694518000,773,"S",97,493,"app",678
-6824712694518000,1,1868000,6824712696386000,0,"R",120,"[NULL]","swapper",0
-6824712694595000,0,1875000,6824712696470000,644,"S",120,644,"ndroid.systemui",1664
-6824712694681000,2,92000,6824712694773000,771,"S",97,493,"DispSync",676
-6824712694773000,2,2264000,6824712697037000,0,"R",120,"[NULL]","swapper",0
-6824712696386000,1,443000,6824712696829000,770,"S",120,493,"Binder:640_2",675
-6824712696470000,0,141000,6824712696611000,0,"R",120,"[NULL]","swapper",0
-6824712696611000,0,78000,6824712696689000,773,"S",97,493,"app",678
-6824712696689000,0,44000,6824712696733000,0,"R",120,"[NULL]","swapper",0
-6824712696733000,0,164000,6824712696897000,773,"S",97,493,"app",678
-6824712696829000,1,10308000,6824712707137000,0,"R",120,"[NULL]","swapper",0
-6824712696897000,0,6225000,6824712703122000,0,"R",120,"[NULL]","swapper",0
-6824712697037000,2,91000,6824712697128000,771,"S",97,493,"DispSync",676
-6824712697128000,2,25635000,6824712722763000,0,"R",120,"[NULL]","swapper",0
-6824712703122000,0,62000,6824712703184000,702,"D",120,702,"kworker/u16:7",19422
-6824712703184000,0,133000,6824712703317000,0,"R",120,"[NULL]","swapper",0
-6824712703317000,0,21000,6824712703338000,3,"S",120,3,"ksoftirqd/0",3
-6824712703338000,0,51000,6824712703389000,743,"D",120,743,"kworker/0:5",20371
-6824712703389000,0,49000,6824712703438000,0,"R",120,"[NULL]","swapper",0
-6824712703438000,0,613000,6824712704051000,702,"D",120,702,"kworker/u16:7",19422
-6824712704051000,0,129000,6824712704180000,77,"S",120,77,"smem_native_rpm",87
-6824712704180000,0,129000,6824712704309000,702,"D",120,702,"kworker/u16:7",19422
-6824712704309000,0,114000,6824712704423000,77,"S",120,77,"smem_native_rpm",87
-6824712704423000,0,123000,6824712704546000,702,"D",120,702,"kworker/u16:7",19422
-6824712704546000,0,107000,6824712704653000,77,"S",120,77,"smem_native_rpm",87
-6824712704653000,0,136000,6824712704789000,702,"D",120,702,"kworker/u16:7",19422
-6824712704789000,0,50000,6824712704839000,77,"S",120,77,"smem_native_rpm",87
-6824712704839000,0,628000,6824712705467000,0,"R",120,"[NULL]","swapper",0
-6824712705467000,0,160000,6824712705627000,702,"D",120,702,"kworker/u16:7",19422
-6824712705627000,0,121000,6824712705748000,77,"S",120,77,"smem_native_rpm",87
-6824712705748000,0,124000,6824712705872000,702,"D",120,702,"kworker/u16:7",19422
-6824712705872000,0,136000,6824712706008000,77,"S",120,77,"smem_native_rpm",87
-6824712706008000,0,152000,6824712706160000,702,"D",120,702,"kworker/u16:7",19422
-6824712706160000,0,114000,6824712706274000,77,"S",120,77,"smem_native_rpm",87
-6824712706274000,0,125000,6824712706399000,702,"D",120,702,"kworker/u16:7",19422
-6824712706399000,0,48000,6824712706447000,77,"S",120,77,"smem_native_rpm",87
-6824712706447000,0,873000,6824712707320000,0,"R",120,"[NULL]","swapper",0
-6824712707137000,1,57000,6824712707194000,15,"S",120,15,"ksoftirqd/1",17
-6824712707194000,1,15412000,6824712722606000,0,"R",120,"[NULL]","swapper",0
-6824712707320000,0,162000,6824712707482000,702,"D",120,702,"kworker/u16:7",19422
-6824712707482000,0,105000,6824712707587000,77,"S",120,77,"smem_native_rpm",87
-6824712707587000,0,128000,6824712707715000,702,"D",120,702,"kworker/u16:7",19422
-6824712707715000,0,115000,6824712707830000,77,"S",120,77,"smem_native_rpm",87
-6824712707830000,0,124000,6824712707954000,702,"D",120,702,"kworker/u16:7",19422
-6824712707954000,0,110000,6824712708064000,77,"S",120,77,"smem_native_rpm",87
-6824712708064000,0,140000,6824712708204000,702,"D",120,702,"kworker/u16:7",19422
-6824712708204000,0,114000,6824712708318000,77,"S",120,77,"smem_native_rpm",87
-6824712708318000,0,82000,6824712708400000,702,"S",120,702,"kworker/u16:7",19422
-6824712708400000,0,15285000,6824712723685000,0,"R",120,"[NULL]","swapper",0
-6824712722606000,1,109000,6824712722715000,13,"S",0,13,"watchdog/1",15
-6824712722715000,1,79000,6824712722794000,0,"R",120,"[NULL]","swapper",0
-6824712722763000,2,73000,6824712722836000,20,"S",0,20,"watchdog/2",23
-6824712722794000,1,64000,6824712722858000,15,"S",120,15,"ksoftirqd/1",17
-6824712722836000,2,5437000,6824712728273000,0,"R",120,"[NULL]","swapper",0
-6824712722858000,1,2789000,6824712725647000,0,"R",120,"[NULL]","swapper",0
-6824712723685000,0,148000,6824712723833000,705,"D",120,705,"kworker/0:1",19511
-6824712723826000,3,72000,6824712723898000,27,"S",0,27,"watchdog/3",31
-6824712723833000,0,828000,6824712724661000,0,"R",120,"[NULL]","swapper",0
-6824712723898000,3,34414000,6824712758312000,0,"R",120,"[NULL]","swapper",0
-6824712724661000,0,78000,6824712724739000,701,"S",120,701,"kworker/0:3",19397
-6824712724739000,0,236000,6824712724975000,705,"R+",120,705,"kworker/0:1",19511
-6824712724975000,0,544000,6824712725519000,786,"S",111,494,"SDM_EventThread",685
-6824712725519000,0,64000,6824712725583000,705,"S",120,705,"kworker/0:1",19511
-6824712725583000,0,365000,6824712725948000,0,"R",120,"[NULL]","swapper",0
-6824712725647000,1,483000,6824712726130000,777,"S",120,493,"HwBinder:640_1",721
-6824712725948000,0,129000,6824712726077000,771,"S",97,493,"DispSync",676
-6824712726077000,0,1250000,6824712727327000,0,"R",120,"[NULL]","swapper",0
-6824712726130000,1,1587000,6824712727717000,0,"R",120,"[NULL]","swapper",0
-6824712726382000,4,67000,6824712726449000,34,"S",0,34,"watchdog/4",39
-6824712726449000,4,657913000,6824713384362000,0,"R",120,"[NULL]","swapper",0
-6824712726858000,5,46000,6824712726904000,41,"S",0,41,"watchdog/5",47
-6824712726904000,5,48000,6824712726952000,0,"R",120,"[NULL]","swapper",0
-6824712726952000,5,38000,6824712726990000,43,"S",120,43,"ksoftirqd/5",49
-6824712726990000,5,678798000,6824713405788000,0,"R",120,"[NULL]","swapper",0
-6824712727327000,0,178000,6824712727505000,771,"S",97,493,"DispSync",676
-6824712727505000,0,702000,6824712728207000,0,"R",120,"[NULL]","swapper",0
-6824712727717000,1,350000,6824712728067000,773,"S",97,493,"app",678
-6824712728062000,6,48000,6824712728110000,48,"S",0,48,"watchdog/6",55
-6824712728067000,1,2263000,6824712730330000,0,"R",120,"[NULL]","swapper",0
-6824712728110000,6,110547000,6824712838657000,0,"R",120,"[NULL]","swapper",0
-6824712728207000,0,2150000,6824712730357000,644,"S",120,644,"ndroid.systemui",1664
-6824712728273000,2,88000,6824712728361000,771,"S",97,493,"DispSync",676
-6824712728361000,2,33537000,6824712761898000,0,"R",120,"[NULL]","swapper",0
-6824712729998000,7,46000,6824712730044000,55,"S",0,55,"watchdog/7",63
-6824712730044000,7,136266000,6824712866310000,0,"R",120,"[NULL]","swapper",0
-6824712730330000,1,314000,6824712730644000,770,"S",120,493,"Binder:640_2",675
-6824712730357000,0,484000,6824712730841000,0,"R",120,"[NULL]","swapper",0
-6824712730644000,1,567000,6824712731211000,0,"R",120,"[NULL]","swapper",0
-6824712730841000,0,182000,6824712731023000,773,"S",97,493,"app",678
-6824712731023000,0,2119000,6824712733142000,0,"R",120,"[NULL]","swapper",0
-6824712731211000,1,95000,6824712731306000,771,"S",97,493,"DispSync",676
-6824712731306000,1,27902000,6824712759208000,0,"R",120,"[NULL]","swapper",0
-6824712733142000,0,190000,6824712733332000,77,"S",120,77,"smem_native_rpm",87
-6824712733332000,0,25059000,6824712758391000,0,"R",120,"[NULL]","swapper",0
-6824712758312000,3,37000,6824712758349000,29,"S",120,29,"ksoftirqd/3",33
-6824712758349000,3,119000,6824712758468000,702,"S",120,702,"kworker/u16:7",19422
-6824712758391000,0,96000,6824712758487000,705,"S",120,705,"kworker/0:1",19511
-6824712758468000,3,38802000,6824712797270000,0,"R",120,"[NULL]","swapper",0
-6824712758487000,0,574000,6824712759061000,786,"S",111,494,"SDM_EventThread",685
-6824712759061000,0,699000,6824712759760000,0,"R",120,"[NULL]","swapper",0
-6824712759208000,1,489000,6824712759697000,777,"S",120,493,"HwBinder:640_1",721
-6824712759697000,1,1610000,6824712761307000,0,"R",120,"[NULL]","swapper",0
-6824712759760000,0,131000,6824712759891000,771,"S",97,493,"DispSync",676
-6824712759891000,0,227000,6824712760118000,0,"R",120,"[NULL]","swapper",0
-6824712760118000,0,54000,6824712760172000,705,"S",120,705,"kworker/0:1",19511
-6824712760172000,0,509000,6824712760681000,702,"S",120,702,"kworker/u16:7",19422
-6824712760681000,0,231000,6824712760912000,0,"R",120,"[NULL]","swapper",0
-6824712760912000,0,182000,6824712761094000,771,"S",97,493,"DispSync",676
-6824712761094000,0,708000,6824712761802000,0,"R",120,"[NULL]","swapper",0
-6824712761307000,1,363000,6824712761670000,773,"S",97,493,"app",678
-6824712761670000,1,2291000,6824712763961000,0,"R",120,"[NULL]","swapper",0
-6824712761802000,0,2190000,6824712763992000,644,"S",120,644,"ndroid.systemui",1664
-6824712761898000,2,92000,6824712761990000,771,"S",97,493,"DispSync",676
-6824712761990000,2,35024000,6824712797014000,0,"R",120,"[NULL]","swapper",0
-6824712763961000,1,312000,6824712764273000,770,"S",120,493,"Binder:640_2",675
-6824712763992000,0,457000,6824712764449000,0,"R",120,"[NULL]","swapper",0
-6824712764273000,1,539000,6824712764812000,0,"R",120,"[NULL]","swapper",0
-6824712764449000,0,182000,6824712764631000,773,"S",97,493,"app",678
-6824712764631000,0,30567000,6824712795198000,0,"R",120,"[NULL]","swapper",0
-6824712764812000,1,95000,6824712764907000,771,"S",97,493,"DispSync",676
-6824712764907000,1,30302000,6824712795209000,0,"R",120,"[NULL]","swapper",0
-6824712795198000,0,480000,6824712795678000,771,"S",97,493,"DispSync",676
-6824712795209000,1,163000,6824712795372000,15,"S",120,15,"ksoftirqd/1",17
-6824712795372000,1,877000,6824712796249000,0,"R",120,"[NULL]","swapper",0
-6824712795678000,0,171000,6824712795849000,705,"S",120,705,"kworker/0:1",19511
-6824712795849000,0,1068000,6824712796917000,786,"S",111,494,"SDM_EventThread",685
-6824712796249000,1,683000,6824712796932000,773,"S",97,493,"app",678
-6824712796917000,0,862000,6824712797779000,0,"R",120,"[NULL]","swapper",0
-6824712796932000,1,4294000,6824712801226000,0,"R",120,"[NULL]","swapper",0
-6824712797014000,2,615000,6824712797629000,777,"S",120,493,"HwBinder:640_1",721
-6824712797270000,3,69000,6824712797339000,771,"S",97,493,"DispSync",676
-6824712797339000,3,3182000,6824712800521000,644,"S",120,644,"ndroid.systemui",1664
-6824712797629000,2,32555000,6824712830184000,0,"R",120,"[NULL]","swapper",0
-6824712797779000,0,87000,6824712797866000,771,"S",97,493,"DispSync",676
-6824712797866000,0,2676000,6824712800542000,0,"R",120,"[NULL]","swapper",0
-6824712800521000,3,61041000,6824712861562000,0,"R",120,"[NULL]","swapper",0
-6824712800542000,0,397000,6824712800939000,770,"S",120,493,"Binder:640_2",675
-6824712800939000,0,790000,6824712801729000,0,"R",120,"[NULL]","swapper",0
-6824712801226000,1,203000,6824712801429000,773,"S",97,493,"app",678
-6824712801429000,1,28175000,6824712829604000,0,"R",120,"[NULL]","swapper",0
-6824712801729000,0,88000,6824712801817000,771,"S",97,493,"DispSync",676
-6824712801817000,0,26133000,6824712827950000,0,"R",120,"[NULL]","swapper",0
-6824712827950000,0,303000,6824712828253000,705,"S",120,705,"kworker/0:1",19511
-6824712828253000,0,1174000,6824712829427000,786,"S",111,494,"SDM_EventThread",685
-6824712829427000,0,87000,6824712829514000,0,"R",120,"[NULL]","swapper",0
-6824712829514000,0,249000,6824712829763000,3,"S",120,3,"ksoftirqd/0",3
-6824712829604000,1,771000,6824712830375000,777,"S",120,493,"HwBinder:640_1",721
-6824712829763000,0,134000,6824712829897000,702,"S",120,702,"kworker/u16:7",19422
-6824712829897000,0,1050000,6824712830947000,0,"R",120,"[NULL]","swapper",0
-6824712830184000,2,302000,6824712830486000,771,"S",97,493,"DispSync",676
-6824712830375000,1,1386000,6824712831761000,0,"R",120,"[NULL]","swapper",0
-6824712830486000,2,1407000,6824712831893000,0,"R",120,"[NULL]","swapper",0
-6824712830947000,0,531000,6824712831478000,773,"S",97,493,"app",678
-6824712831478000,0,3444000,6824712834922000,0,"R",120,"[NULL]","swapper",0
-6824712831761000,1,3128000,6824712834889000,644,"S",120,644,"ndroid.systemui",1664
-6824712831893000,2,86000,6824712831979000,771,"S",97,493,"DispSync",676
-6824712831979000,2,9415000,6824712841394000,0,"R",120,"[NULL]","swapper",0
-6824712834889000,1,707000,6824712835596000,0,"R",120,"[NULL]","swapper",0
-6824712834922000,0,398000,6824712835320000,770,"S",120,493,"Binder:640_2",675
-6824712835320000,0,775000,6824712836095000,0,"R",120,"[NULL]","swapper",0
-6824712835596000,1,201000,6824712835797000,773,"S",97,493,"app",678
-6824712835797000,1,24848000,6824712860645000,0,"R",120,"[NULL]","swapper",0
-6824712836095000,0,93000,6824712836188000,771,"S",97,493,"DispSync",676
-6824712836188000,0,23047000,6824712859235000,0,"R",120,"[NULL]","swapper",0
-6824712838657000,6,193000,6824712838850000,630,"S",100,630,"kworker/u17:1",1134
-6824712838850000,6,70000,6824712838920000,0,"R",120,"[NULL]","swapper",0
-6824712838920000,6,49000,6824712838969000,50,"S",120,50,"ksoftirqd/6",57
-6824712838969000,6,3751000,6824712842720000,0,"R",120,"[NULL]","swapper",0
-6824712841394000,2,165000,6824712841559000,22,"S",120,22,"ksoftirqd/2",25
-6824712841559000,2,3497000,6824712845056000,0,"R",120,"[NULL]","swapper",0
-6824712842720000,6,303000,6824712843023000,630,"S",100,630,"kworker/u17:1",1134
-6824712843023000,6,564000,6824712843587000,669,"S",120,669,"kworker/6:1",14833
-6824712843587000,6,2780000,6824712846367000,0,"R",120,"[NULL]","swapper",0
-6824712845056000,2,686000,6824712845742000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712845742000,2,3405000,6824712849147000,0,"R",120,"[NULL]","swapper",0
-6824712846367000,6,406000,6824712846773000,630,"S",100,630,"kworker/u17:1",1134
-6824712846773000,6,355000,6824712847128000,669,"S",120,669,"kworker/6:1",14833
-6824712847128000,6,206037000,6824713053165000,0,"R",120,"[NULL]","swapper",0
-6824712849147000,2,1203000,6824712850350000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712850350000,2,3128000,6824712853478000,739,"R+",120,739,"adbd",20305
-6824712853478000,2,128000,6824712853606000,24,"S",120,24,"rcuop/2",28
-6824712853606000,2,62000,6824712853668000,5,"S",120,5,"rcu_preempt",7
-6824712853668000,2,3944000,6824712857612000,739,"S",120,739,"adbd",20305
-6824712857612000,2,2594000,6824712860206000,2733,"R+",120,761,"sh",20457
-6824712859235000,0,137000,6824712859372000,705,"S",120,705,"kworker/0:1",19511
-6824712859372000,0,965000,6824712860337000,786,"S",111,494,"SDM_EventThread",685
-6824712860206000,2,85000,6824712860291000,694,"S",120,694,"kworker/2:0",18823
-6824712860291000,2,57000,6824712860348000,5,"S",120,5,"rcu_preempt",7
-6824712860337000,0,922000,6824712861259000,702,"S",120,702,"kworker/u16:7",19422
-6824712860348000,2,3024000,6824712863372000,2733,"R+",120,761,"sh",20457
-6824712860645000,1,709000,6824712861354000,777,"S",120,493,"HwBinder:640_1",721
-6824712861259000,0,553000,6824712861812000,0,"R",120,"[NULL]","swapper",0
-6824712861354000,1,1038000,6824712862392000,0,"R",120,"[NULL]","swapper",0
-6824712861562000,3,169000,6824712861731000,771,"S",97,493,"DispSync",676
-6824712861731000,3,1521000,6824712863252000,0,"R",120,"[NULL]","swapper",0
-6824712861812000,0,223000,6824712862035000,771,"S",97,493,"DispSync",676
-6824712862035000,0,716000,6824712862751000,0,"R",120,"[NULL]","swapper",0
-6824712862392000,1,491000,6824712862883000,773,"S",97,493,"app",678
-6824712862751000,0,3243000,6824712865994000,644,"S",120,644,"ndroid.systemui",1664
-6824712862883000,1,3367000,6824712866250000,0,"R",120,"[NULL]","swapper",0
-6824712863252000,3,63000,6824712863315000,771,"S",97,493,"DispSync",676
-6824712863315000,3,230000,6824712863545000,25,"S",120,25,"rcuos/2",29
-6824712863372000,2,95000,6824712863467000,5,"S",120,5,"rcu_preempt",7
-6824712863467000,2,80000,6824712863547000,24,"S",120,24,"rcuop/2",28
-6824712863545000,3,13874000,6824712877419000,0,"R",120,"[NULL]","swapper",0
-6824712863547000,2,40000,6824712863587000,6,"S",120,6,"rcu_sched",8
-6824712863587000,2,24000,6824712863611000,5,"S",120,5,"rcu_preempt",7
-6824712863611000,2,1548000,6824712865159000,2733,"R+",120,761,"sh",20457
-6824712865159000,2,3064000,6824712868223000,739,"R+",120,739,"adbd",20305
-6824712865994000,0,1047000,6824712867041000,0,"R",120,"[NULL]","swapper",0
-6824712866250000,1,587000,6824712866837000,770,"S",120,493,"Binder:640_2",675
-6824712866310000,7,74000,6824712866384000,145,"S",120,145,"hwrng",215
-6824712866384000,7,6718000,6824712873102000,0,"R",120,"[NULL]","swapper",0
-6824712866837000,1,771000,6824712867608000,0,"R",120,"[NULL]","swapper",0
-6824712867041000,0,285000,6824712867326000,773,"S",97,493,"app",678
-6824712867326000,0,9974000,6824712877300000,0,"R",120,"[NULL]","swapper",0
-6824712867608000,1,76000,6824712867684000,771,"S",97,493,"DispSync",676
-6824712867684000,1,110000,6824712867794000,630,"S",100,630,"kworker/u17:1",1134
-6824712867794000,1,62000,6824712867856000,0,"R",120,"[NULL]","swapper",0
-6824712867856000,1,140000,6824712867996000,630,"S",100,630,"kworker/u17:1",1134
-6824712867996000,1,60000,6824712868056000,698,"R+",120,698,"kworker/1:0",19220
-6824712868056000,1,59000,6824712868115000,630,"S",100,630,"kworker/u17:1",1134
-6824712868115000,1,111000,6824712868226000,698,"R+",120,698,"kworker/1:0",19220
-6824712868223000,2,292000,6824712868515000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712868226000,1,78000,6824712868304000,630,"S",100,630,"kworker/u17:1",1134
-6824712868304000,1,48000,6824712868352000,698,"R+",120,698,"kworker/1:0",19220
-6824712868352000,1,57000,6824712868409000,630,"S",100,630,"kworker/u17:1",1134
-6824712868409000,1,45000,6824712868454000,698,"R+",120,698,"kworker/1:0",19220
-6824712868454000,1,72000,6824712868526000,630,"S",100,630,"kworker/u17:1",1134
-6824712868515000,2,145000,6824712868660000,739,"S",120,739,"adbd",20305
-6824712868526000,1,257000,6824712868783000,698,"S",120,698,"kworker/1:0",19220
-6824712868660000,2,454000,6824712869114000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712868783000,1,1322000,6824712870105000,0,"R",120,"[NULL]","swapper",0
-6824712869114000,2,770000,6824712869884000,739,"S",120,739,"adbd",20305
-6824712869884000,2,197000,6824712870081000,2733,"R+",120,761,"sh",20457
-6824712870081000,2,56000,6824712870137000,5,"S",120,5,"rcu_preempt",7
-6824712870105000,1,117000,6824712870222000,630,"S",100,630,"kworker/u17:1",1134
-6824712870137000,2,41000,6824712870178000,6,"S",120,6,"rcu_sched",8
-6824712870178000,2,153000,6824712870331000,2733,"R+",120,761,"sh",20457
-6824712870222000,1,113000,6824712870335000,698,"R+",120,698,"kworker/1:0",19220
-6824712870331000,2,69000,6824712870400000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712870335000,1,43000,6824712870378000,630,"S",100,630,"kworker/u17:1",1134
-6824712870378000,1,66000,6824712870444000,698,"S",120,698,"kworker/1:0",19220
-6824712870400000,2,6436000,6824712876836000,2733,"R+",120,761,"sh",20457
-6824712870444000,1,20085000,6824712890529000,0,"R",120,"[NULL]","swapper",0
-6824712873102000,7,72000,6824712873174000,145,"S",120,145,"hwrng",215
-6824712873174000,7,5793000,6824712878967000,0,"R",120,"[NULL]","swapper",0
-6824712876836000,2,146000,6824712876982000,6,"S",120,6,"rcu_sched",8
-6824712876982000,2,88000,6824712877070000,5,"S",120,5,"rcu_preempt",7
-6824712877070000,2,86000,6824712877156000,24,"S",120,24,"rcuop/2",28
-6824712877156000,2,40000,6824712877196000,5,"S",120,5,"rcu_preempt",7
-6824712877196000,2,374000,6824712877570000,2734,"R",120,739,"shell",20458
-6824712877300000,0,156000,6824712877456000,702,"S",120,702,"kworker/u16:7",19422
-6824712877419000,3,189000,6824712877608000,25,"S",120,25,"rcuos/2",29
-6824712877456000,0,6419000,6824712883875000,0,"R",120,"[NULL]","swapper",0
-6824712877570000,2,32000,6824712877602000,6,"S",120,6,"rcu_sched",8
-6824712877602000,2,441000,6824712878043000,2734,"S",120,739,"shell",20458
-6824712877608000,3,13785000,6824712891393000,0,"R",120,"[NULL]","swapper",0
-6824712878043000,2,5493000,6824712883536000,2733,"R+",120,761,"sh",20457
-6824712878967000,7,74000,6824712879041000,145,"S",120,145,"hwrng",215
-6824712879041000,7,22599000,6824712901640000,0,"R",120,"[NULL]","swapper",0
-6824712883536000,2,224000,6824712883760000,482,"S",49,482,"sugov:0",605
-6824712883760000,2,7130000,6824712890890000,2733,"R",120,761,"sh",20457
-6824712883875000,0,37000,6824712883912000,6,"S",120,6,"rcu_sched",8
-6824712883912000,0,38000,6824712883950000,5,"S",120,5,"rcu_preempt",7
-6824712883950000,0,6876000,6824712890826000,0,"R",120,"[NULL]","swapper",0
-6824712890529000,1,61000,6824712890590000,693,"S",120,693,"kworker/1:1",18800
-6824712890590000,1,2884000,6824712893474000,0,"R",120,"[NULL]","swapper",0
-6824712890826000,0,72000,6824712890898000,5,"S",120,5,"rcu_preempt",7
-6824712890890000,2,188000,6824712891078000,24,"S",120,24,"rcuop/2",28
-6824712890898000,0,80000,6824712890978000,6,"S",120,6,"rcu_sched",8
-6824712890978000,0,595000,6824712891573000,0,"R",120,"[NULL]","swapper",0
-6824712891078000,2,5651000,6824712896729000,2733,"R",120,761,"sh",20457
-6824712891393000,3,58000,6824712891451000,25,"S",120,25,"rcuos/2",29
-6824712891451000,3,4407000,6824712895858000,0,"R",120,"[NULL]","swapper",0
-6824712891573000,0,40000,6824712891613000,5,"S",120,5,"rcu_preempt",7
-6824712891613000,0,803000,6824712892416000,0,"R",120,"[NULL]","swapper",0
-6824712892416000,0,105000,6824712892521000,705,"S",120,705,"kworker/0:1",19511
-6824712892521000,0,800000,6824712893321000,786,"S",111,494,"SDM_EventThread",685
-6824712893321000,0,850000,6824712894171000,0,"R",120,"[NULL]","swapper",0
-6824712893474000,1,566000,6824712894040000,777,"S",120,493,"HwBinder:640_1",721
-6824712894040000,1,1068000,6824712895108000,0,"R",120,"[NULL]","swapper",0
-6824712894171000,0,111000,6824712894282000,771,"S",97,493,"DispSync",676
-6824712894282000,0,714000,6824712894996000,0,"R",120,"[NULL]","swapper",0
-6824712894996000,0,140000,6824712895136000,771,"S",97,493,"DispSync",676
-6824712895108000,1,410000,6824712895518000,773,"S",97,493,"app",678
-6824712895136000,0,301000,6824712895437000,0,"R",120,"[NULL]","swapper",0
-6824712895437000,0,1223000,6824712896660000,644,"R",120,644,"ndroid.systemui",1664
-6824712895518000,1,2511000,6824712898029000,0,"R",120,"[NULL]","swapper",0
-6824712895858000,3,55000,6824712895913000,771,"S",97,493,"DispSync",676
-6824712895913000,3,20866000,6824712916779000,0,"R",120,"[NULL]","swapper",0
-6824712896660000,0,76000,6824712896736000,5,"S",120,5,"rcu_preempt",7
-6824712896729000,2,38000,6824712896767000,24,"S",120,24,"rcuop/2",28
-6824712896736000,0,1181000,6824712897917000,644,"S",120,644,"ndroid.systemui",1664
-6824712896767000,2,3122000,6824712899889000,2733,"R",120,761,"sh",20457
-6824712897917000,0,362000,6824712898279000,0,"R",120,"[NULL]","swapper",0
-6824712898029000,1,330000,6824712898359000,770,"S",120,493,"Binder:640_2",675
-6824712898279000,0,181000,6824712898460000,773,"S",97,493,"app",678
-6824712898359000,1,40000,6824712898399000,0,"R",120,"[NULL]","swapper",0
-6824712898399000,1,53000,6824712898452000,771,"S",97,493,"DispSync",676
-6824712898452000,1,28312000,6824712926764000,0,"R",120,"[NULL]","swapper",0
-6824712898460000,0,1923000,6824712900383000,0,"R",120,"[NULL]","swapper",0
-6824712899889000,2,124000,6824712900013000,24,"S",120,24,"rcuop/2",28
-6824712900013000,2,3333000,6824712903346000,2733,"R",120,761,"sh",20457
-6824712900383000,0,51000,6824712900434000,5,"S",120,5,"rcu_preempt",7
-6824712900434000,0,6845000,6824712907279000,0,"R",120,"[NULL]","swapper",0
-6824712901640000,7,72000,6824712901712000,145,"S",120,145,"hwrng",215
-6824712901712000,7,80781000,6824712982493000,0,"R",120,"[NULL]","swapper",0
-6824712903346000,2,197000,6824712903543000,482,"S",49,482,"sugov:0",605
-6824712903543000,2,3857000,6824712907400000,2733,"R",120,761,"sh",20457
-6824712907279000,0,57000,6824712907336000,743,"S",120,743,"kworker/0:5",20371
-6824712907336000,0,77000,6824712907413000,5,"S",120,5,"rcu_preempt",7
-6824712907400000,2,66000,6824712907466000,24,"S",120,24,"rcuop/2",28
-6824712907413000,0,51000,6824712907464000,0,"R",120,"[NULL]","swapper",0
-6824712907464000,0,27000,6824712907491000,5,"S",120,5,"rcu_preempt",7
-6824712907466000,2,180000,6824712907646000,2733,"R+",120,761,"sh",20457
-6824712907491000,0,6442000,6824712913933000,0,"R",120,"[NULL]","swapper",0
-6824712907646000,2,198000,6824712907844000,2734,"S",120,739,"shell",20458
-6824712907844000,2,962000,6824712908806000,739,"R+",120,739,"adbd",20305
-6824712908806000,2,188000,6824712908994000,630,"S",100,630,"kworker/u17:1",1134
-6824712908994000,2,81000,6824712909075000,694,"S",120,694,"kworker/2:0",18823
-6824712909075000,2,25000,6824712909100000,670,"S",100,670,"kworker/u17:2",14944
-6824712909100000,2,79000,6824712909179000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712909179000,2,99000,6824712909278000,739,"R+",120,739,"adbd",20305
-6824712909278000,2,50000,6824712909328000,670,"S",100,670,"kworker/u17:2",14944
-6824712909328000,2,49000,6824712909377000,694,"R+",120,694,"kworker/2:0",18823
-6824712909377000,2,21000,6824712909398000,670,"S",100,670,"kworker/u17:2",14944
-6824712909398000,2,10000,6824712909408000,694,"S",120,694,"kworker/2:0",18823
-6824712909408000,2,164000,6824712909572000,739,"R+",120,739,"adbd",20305
-6824712909572000,2,42000,6824712909614000,670,"S",100,670,"kworker/u17:2",14944
-6824712909614000,2,53000,6824712909667000,739,"R+",120,739,"adbd",20305
-6824712909667000,2,62000,6824712909729000,670,"S",100,670,"kworker/u17:2",14944
-6824712909729000,2,88000,6824712909817000,739,"S",120,739,"adbd",20305
-6824712909817000,2,183000,6824712910000000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712910000000,2,101000,6824712910101000,694,"S",120,694,"kworker/2:0",18823
-6824712910101000,2,40000,6824712910141000,2487,"R",120,739,"UsbFfs-worker",20308
-6824712910141000,2,36000,6824712910177000,670,"S",100,670,"kworker/u17:2",14944
-6824712910177000,2,35000,6824712910212000,2487,"R",120,739,"UsbFfs-worker",20308
-6824712910212000,2,56000,6824712910268000,670,"S",100,670,"kworker/u17:2",14944
-6824712910268000,2,37000,6824712910305000,694,"R",120,694,"kworker/2:0",18823
-6824712910305000,2,35000,6824712910340000,670,"S",100,670,"kworker/u17:2",14944
-6824712910340000,2,34000,6824712910374000,694,"R",120,694,"kworker/2:0",18823
-6824712910374000,2,46000,6824712910420000,670,"S",100,670,"kworker/u17:2",14944
-6824712910420000,2,78000,6824712910498000,694,"S",120,694,"kworker/2:0",18823
-6824712910498000,2,292000,6824712910790000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712910790000,2,280000,6824712911070000,739,"R+",120,739,"adbd",20305
-6824712911070000,2,92000,6824712911162000,670,"S",100,670,"kworker/u17:2",14944
-6824712911162000,2,10000,6824712911172000,630,"S",100,630,"kworker/u17:1",1134
-6824712911172000,2,47000,6824712911219000,739,"R",120,739,"adbd",20305
-6824712911219000,2,22000,6824712911241000,630,"S",100,630,"kworker/u17:1",1134
-6824712911241000,2,85000,6824712911326000,739,"S",120,739,"adbd",20305
-6824712911326000,2,112000,6824712911438000,2734,"S",120,739,"shell",20458
-6824712911438000,2,42000,6824712911480000,694,"S",120,694,"kworker/2:0",18823
-6824712911480000,2,22000,6824712911502000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712911502000,2,2059000,6824712913561000,2733,"S",120,761,"sh",20457
-6824712913561000,2,431000,6824712913992000,2735,"R+",120,762,"sh",20459
-6824712913933000,0,84000,6824712914017000,5,"S",120,5,"rcu_preempt",7
-6824712913992000,2,65000,6824712914057000,24,"S",120,24,"rcuop/2",28
-6824712914017000,0,1135000,6824712915152000,0,"R",120,"[NULL]","swapper",0
-6824712914057000,2,670000,6824712914727000,2735,"R+",120,762,"sh",20459
-6824712914727000,2,46000,6824712914773000,24,"S",120,24,"rcuop/2",28
-6824712914773000,2,1850000,6824712916623000,2735,"R+",120,762,"sh",20459
-6824712915152000,0,39000,6824712915191000,5,"S",120,5,"rcu_preempt",7
-6824712915191000,0,2005000,6824712917196000,0,"R",120,"[NULL]","swapper",0
-6824712916623000,2,1909000,6824712918532000,2733,"I",120,761,"sh",20457
-6824712916779000,3,89000,6824712916868000,25,"S",120,25,"rcuos/2",29
-6824712916868000,3,6871000,6824712923739000,0,"R",120,"[NULL]","swapper",0
-6824712917196000,0,38000,6824712917234000,6,"S",120,6,"rcu_sched",8
-6824712917234000,0,3105000,6824712920339000,0,"R",120,"[NULL]","swapper",0
-6824712918532000,2,938000,6824712919470000,2734,"I",120,739,"shell",20458
-6824712919470000,2,1271000,6824712920741000,739,"S",120,739,"adbd",20305
-6824712920339000,0,118000,6824712920457000,630,"S",100,630,"kworker/u17:1",1134
-6824712920457000,0,98000,6824712920555000,743,"S",120,743,"kworker/0:5",20371
-6824712920555000,0,67000,6824712920622000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712920622000,0,44000,6824712920666000,630,"S",100,630,"kworker/u17:1",1134
-6824712920666000,0,83000,6824712920749000,5,"S",120,5,"rcu_preempt",7
-6824712920741000,2,90000,6824712920831000,24,"S",120,24,"rcuop/2",28
-6824712920749000,0,63000,6824712920812000,0,"R",120,"[NULL]","swapper",0
-6824712920812000,0,59000,6824712920871000,630,"S",100,630,"kworker/u17:1",1134
-6824712920831000,2,100000,6824712920931000,2735,"R+",120,762,"sh",20459
-6824712920871000,0,56000,6824712920927000,743,"R+",120,743,"kworker/0:5",20371
-6824712920927000,0,28000,6824712920955000,630,"S",100,630,"kworker/u17:1",1134
-6824712920931000,2,327000,6824712921258000,482,"S",49,482,"sugov:0",605
-6824712920955000,0,8000,6824712920963000,743,"S",120,743,"kworker/0:5",20371
-6824712920963000,0,23000,6824712920986000,2487,"R",120,739,"UsbFfs-worker",20308
-6824712920986000,0,40000,6824712921026000,630,"S",100,630,"kworker/u17:1",1134
-6824712921026000,0,41000,6824712921067000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712921067000,0,15000,6824712921082000,5,"R+",120,5,"rcu_preempt",7
-6824712921082000,0,68000,6824712921150000,630,"S",100,630,"kworker/u17:1",1134
-6824712921150000,0,50000,6824712921200000,743,"R+",120,743,"kworker/0:5",20371
-6824712921200000,0,48000,6824712921248000,630,"S",100,630,"kworker/u17:1",1134
-6824712921248000,0,48000,6824712921296000,743,"R+",120,743,"kworker/0:5",20371
-6824712921258000,2,54000,6824712921312000,2735,"I",120,762,"sh",20459
-6824712921296000,0,38000,6824712921334000,630,"S",100,630,"kworker/u17:1",1134
-6824712921312000,2,8350000,6824712929662000,0,"R",120,"[NULL]","swapper",0
-6824712921334000,0,41000,6824712921375000,743,"S",120,743,"kworker/0:5",20371
-6824712921375000,0,204000,6824712921579000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712921579000,0,177000,6824712921756000,739,"S",120,739,"adbd",20305
-6824712921756000,0,15000,6824712921771000,5,"S",120,5,"rcu_preempt",7
-6824712921771000,0,337000,6824712922108000,0,"R",120,"[NULL]","swapper",0
-6824712922108000,0,39000,6824712922147000,630,"S",100,630,"kworker/u17:1",1134
-6824712922147000,0,31000,6824712922178000,743,"S",120,743,"kworker/0:5",20371
-6824712922178000,0,23000,6824712922201000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712922201000,0,1099000,6824712923300000,0,"R",120,"[NULL]","swapper",0
-6824712923300000,0,66000,6824712923366000,6,"S",120,6,"rcu_sched",8
-6824712923366000,0,2472000,6824712925838000,0,"R",120,"[NULL]","swapper",0
-6824712923739000,3,108000,6824712923847000,25,"S",120,25,"rcuos/2",29
-6824712923847000,3,21000,6824712923868000,6,"S",120,6,"rcu_sched",8
-6824712923868000,3,6431000,6824712930299000,0,"R",120,"[NULL]","swapper",0
-6824712925838000,0,33000,6824712925871000,743,"R+",120,743,"kworker/0:5",20371
-6824712925871000,0,645000,6824712926516000,786,"S",111,494,"SDM_EventThread",685
-6824712926516000,0,30000,6824712926546000,743,"S",120,743,"kworker/0:5",20371
-6824712926546000,0,967000,6824712927513000,0,"R",120,"[NULL]","swapper",0
-6824712926764000,1,82000,6824712926846000,702,"S",120,702,"kworker/u16:7",19422
-6824712926846000,1,16000,6824712926862000,5,"S",120,5,"rcu_preempt",7
-6824712926862000,1,489000,6824712927351000,777,"S",120,493,"HwBinder:640_1",721
-6824712927351000,1,1624000,6824712928975000,0,"R",120,"[NULL]","swapper",0
-6824712927513000,0,89000,6824712927602000,771,"S",97,493,"DispSync",676
-6824712927602000,0,969000,6824712928571000,0,"R",120,"[NULL]","swapper",0
-6824712928571000,0,92000,6824712928663000,771,"S",97,493,"DispSync",676
-6824712928663000,0,909000,6824712929572000,0,"R",120,"[NULL]","swapper",0
-6824712928975000,1,295000,6824712929270000,773,"S",97,493,"app",678
-6824712929270000,1,2298000,6824712931568000,0,"R",120,"[NULL]","swapper",0
-6824712929572000,0,1853000,6824712931425000,644,"S",120,644,"ndroid.systemui",1664
-6824712929662000,2,29000,6824712929691000,771,"S",97,493,"DispSync",676
-6824712929691000,2,2432000,6824712932123000,0,"R",120,"[NULL]","swapper",0
-6824712930299000,3,39000,6824712930338000,6,"S",120,6,"rcu_sched",8
-6824712930338000,3,37000,6824712930375000,25,"S",120,25,"rcuos/2",29
-6824712930375000,3,34073000,6824712964448000,0,"R",120,"[NULL]","swapper",0
-6824712931425000,0,319000,6824712931744000,0,"R",120,"[NULL]","swapper",0
-6824712931568000,1,223000,6824712931791000,770,"S",120,493,"Binder:640_2",675
-6824712931744000,0,102000,6824712931846000,773,"S",97,493,"app",678
-6824712931791000,1,1518000,6824712933309000,0,"R",120,"[NULL]","swapper",0
-6824712931846000,0,29956000,6824712961802000,0,"R",120,"[NULL]","swapper",0
-6824712932123000,2,33000,6824712932156000,771,"S",97,493,"DispSync",676
-6824712932156000,2,1529000,6824712933685000,0,"R",120,"[NULL]","swapper",0
-6824712933309000,1,55000,6824712933364000,5,"S",120,5,"rcu_preempt",7
-6824712933364000,1,935000,6824712934299000,0,"R",120,"[NULL]","swapper",0
-6824712933685000,2,248000,6824712933933000,24,"S",120,24,"rcuop/2",28
-6824712933933000,2,27866000,6824712961799000,0,"R",120,"[NULL]","swapper",0
-6824712934299000,1,19000,6824712934318000,5,"S",120,5,"rcu_preempt",7
-6824712934318000,1,7968000,6824712942286000,0,"R",120,"[NULL]","swapper",0
-6824712942286000,1,302000,6824712942588000,482,"S",49,482,"sugov:0",605
-6824712942588000,1,197000,6824712942785000,5,"S",120,5,"rcu_preempt",7
-6824712942785000,1,171000,6824712942956000,24,"S",120,24,"rcuop/2",28
-6824712942956000,1,19657000,6824712962613000,0,"R",120,"[NULL]","swapper",0
-6824712961799000,2,620000,6824712962419000,22,"S",120,22,"ksoftirqd/2",25
-6824712961802000,0,176000,6824712961978000,743,"S",120,743,"kworker/0:5",20371
-6824712961978000,0,108000,6824712962086000,630,"S",100,630,"kworker/u17:1",1134
-6824712962086000,0,239000,6824712962325000,786,"R+",111,494,"SDM_EventThread",685
-6824712962325000,0,174000,6824712962499000,630,"S",100,630,"kworker/u17:1",1134
-6824712962419000,2,165000,6824712962584000,694,"S",120,694,"kworker/2:0",18823
-6824712962499000,0,997000,6824712963496000,702,"S",120,702,"kworker/u16:7",19422
-6824712962584000,2,967000,6824712963551000,0,"R",120,"[NULL]","swapper",0
-6824712962613000,1,435000,6824712963048000,771,"S",97,493,"DispSync",676
-6824712963048000,1,140000,6824712963188000,630,"S",100,630,"kworker/u17:1",1134
-6824712963188000,1,505000,6824712963693000,693,"S",120,693,"kworker/1:1",18800
-6824712963496000,0,688000,6824712964184000,786,"S",111,494,"SDM_EventThread",685
-6824712963551000,2,518000,6824712964069000,773,"S",97,493,"app",678
-6824712963693000,1,156000,6824712963849000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712963849000,1,66000,6824712963915000,0,"R",120,"[NULL]","swapper",0
-6824712963915000,1,403000,6824712964318000,644,"R",120,644,"ndroid.systemui",1664
-6824712964069000,2,11256000,6824712975325000,0,"R",120,"[NULL]","swapper",0
-6824712964184000,0,198000,6824712964382000,743,"S",120,743,"kworker/0:5",20371
-6824712964318000,1,572000,6824712964890000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712964382000,0,882000,6824712965264000,0,"R",120,"[NULL]","swapper",0
-6824712964448000,3,67000,6824712964515000,771,"S",97,493,"DispSync",676
-6824712964515000,3,578000,6824712965093000,777,"S",120,493,"HwBinder:640_1",721
-6824712964890000,1,6507000,6824712971397000,739,"S",120,739,"adbd",20305
-6824712965093000,3,29801000,6824712994894000,0,"R",120,"[NULL]","swapper",0
-6824712965264000,0,98000,6824712965362000,771,"S",97,493,"DispSync",676
-6824712965362000,0,9149000,6824712974511000,0,"R",120,"[NULL]","swapper",0
-6824712971397000,1,2878000,6824712974275000,644,"S",120,644,"ndroid.systemui",1664
-6824712974275000,1,2508000,6824712976783000,2720,"R+",120,755,"sh",20460
-6824712974511000,0,515000,6824712975026000,770,"S",120,493,"Binder:640_2",675
-6824712975026000,0,904000,6824712975930000,0,"R",120,"[NULL]","swapper",0
-6824712975325000,2,324000,6824712975649000,773,"S",97,493,"app",678
-6824712975649000,2,11143000,6824712986792000,0,"R",120,"[NULL]","swapper",0
-6824712975930000,0,113000,6824712976043000,771,"S",97,493,"DispSync",676
-6824712976043000,0,5748000,6824712981791000,0,"R",120,"[NULL]","swapper",0
-6824712976783000,1,140000,6824712976923000,702,"S",120,702,"kworker/u16:7",19422
-6824712976923000,1,2388000,6824712979311000,2720,"R+",120,755,"sh",20460
-6824712979311000,1,127000,6824712979438000,9,"S",120,9,"rcuos/0",11
-6824712979438000,1,54000,6824712979492000,6,"S",120,6,"rcu_sched",8
-6824712979492000,1,1949000,6824712981441000,2720,"R+",120,755,"sh",20460
-6824712981441000,1,88000,6824712981529000,8,"S",120,8,"rcuop/0",10
-6824712981529000,1,40000,6824712981569000,5,"S",120,5,"rcu_preempt",7
-6824712981569000,1,1127000,6824712982696000,2720,"R+",120,755,"sh",20460
-6824712981791000,0,2438000,6824712984229000,739,"S",120,739,"adbd",20305
-6824712982493000,7,74000,6824712982567000,145,"S",120,145,"hwrng",215
-6824712982567000,7,268581000,6824713251148000,0,"R",120,"[NULL]","swapper",0
-6824712982696000,1,31000,6824712982727000,145,"S",120,145,"hwrng",215
-6824712982727000,1,630000,6824712983357000,2720,"R",120,755,"sh",20460
-6824712983357000,1,58000,6824712983415000,6,"S",120,6,"rcu_sched",8
-6824712983415000,1,820000,6824712984235000,2720,"R+",120,755,"sh",20460
-6824712984229000,0,571000,6824712984800000,2728,"S",120,739,"shell",20461
-6824712984235000,1,175000,6824712984410000,630,"S",100,630,"kworker/u17:1",1134
-6824712984410000,1,138000,6824712984548000,693,"S",120,693,"kworker/1:1",18800
-6824712984548000,1,27000,6824712984575000,145,"S",120,145,"hwrng",215
-6824712984575000,1,155000,6824712984730000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712984730000,1,290000,6824712985020000,2720,"R+",120,755,"sh",20460
-6824712984800000,0,3033000,6824712987833000,0,"R",120,"[NULL]","swapper",0
-6824712985020000,1,73000,6824712985093000,630,"S",100,630,"kworker/u17:1",1134
-6824712985093000,1,600000,6824712985693000,2720,"R+",120,755,"sh",20460
-6824712985693000,1,141000,6824712985834000,630,"S",100,630,"kworker/u17:1",1134
-6824712985834000,1,51000,6824712985885000,693,"R+",120,693,"kworker/1:1",18800
-6824712985885000,1,79000,6824712985964000,630,"S",100,630,"kworker/u17:1",1134
-6824712985964000,1,186000,6824712986150000,693,"S",120,693,"kworker/1:1",18800
-6824712986150000,1,639000,6824712986789000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824712986789000,1,238000,6824712987027000,482,"S",49,482,"sugov:0",605
-6824712986792000,2,82000,6824712986874000,5,"S",120,5,"rcu_preempt",7
-6824712986874000,2,6897000,6824712993771000,0,"R",120,"[NULL]","swapper",0
-6824712987027000,1,358000,6824712987385000,739,"S",120,739,"adbd",20305
-6824712987385000,1,192000,6824712987577000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712987577000,1,951000,6824712988528000,2720,"R+",120,755,"sh",20460
-6824712987833000,0,421000,6824712988254000,739,"S",120,739,"adbd",20305
-6824712988254000,0,185000,6824712988439000,2728,"S",120,739,"shell",20461
-6824712988439000,0,4499000,6824712992938000,0,"R",120,"[NULL]","swapper",0
-6824712988528000,1,87000,6824712988615000,630,"S",100,630,"kworker/u17:1",1134
-6824712988615000,1,69000,6824712988684000,693,"S",120,693,"kworker/1:1",18800
-6824712988684000,1,65000,6824712988749000,2487,"S",120,739,"UsbFfs-worker",20308
-6824712988749000,1,1248000,6824712989997000,2720,"R",120,755,"sh",20460
-6824712989997000,1,90000,6824712990087000,6,"S",120,6,"rcu_sched",8
-6824712990087000,1,92000,6824712990179000,9,"S",120,9,"rcuos/0",11
-6824712990179000,1,76000,6824712990255000,18,"S",120,18,"rcuos/1",21
-6824712990255000,1,24000,6824712990279000,6,"S",120,6,"rcu_sched",8
-6824712990279000,1,2760000,6824712993039000,2720,"R+",120,755,"sh",20460
-6824712992938000,0,152000,6824712993090000,743,"S",120,743,"kworker/0:5",20371
-6824712993039000,1,804000,6824712993843000,786,"S",111,494,"SDM_EventThread",685
-6824712993090000,0,998000,6824712994088000,0,"R",120,"[NULL]","swapper",0
-6824712993771000,2,89000,6824712993860000,5,"S",120,5,"rcu_preempt",7
-6824712993843000,1,145000,6824712993988000,8,"S",120,8,"rcuop/0",10
-6824712993860000,2,587000,6824712994447000,0,"R",120,"[NULL]","swapper",0
-6824712993988000,1,34000,6824712994022000,17,"S",120,17,"rcuop/1",20
-6824712994022000,1,2637000,6824712996659000,2720,"R",120,755,"sh",20460
-6824712994088000,0,576000,6824712994664000,777,"S",120,493,"HwBinder:640_1",721
-6824712994447000,2,41000,6824712994488000,5,"S",120,5,"rcu_preempt",7
-6824712994488000,2,1596000,6824712996084000,0,"R",120,"[NULL]","swapper",0
-6824712994664000,0,752000,6824712995416000,0,"R",120,"[NULL]","swapper",0
-6824712994894000,3,230000,6824712995124000,771,"S",97,493,"DispSync",676
-6824712995124000,3,1089000,6824712996213000,0,"R",120,"[NULL]","swapper",0
-6824712995416000,0,388000,6824712995804000,773,"S",97,493,"app",678
-6824712995804000,0,2854000,6824712998658000,0,"R",120,"[NULL]","swapper",0
-6824712996084000,2,2507000,6824712998591000,644,"S",120,644,"ndroid.systemui",1664
-6824712996213000,3,61000,6824712996274000,771,"S",97,493,"DispSync",676
-6824712996274000,3,31193000,6824713027467000,0,"R",120,"[NULL]","swapper",0
-6824712996659000,1,76000,6824712996735000,6,"S",120,6,"rcu_sched",8
-6824712996735000,1,52000,6824712996787000,9,"S",120,9,"rcuos/0",11
-6824712996787000,1,28000,6824712996815000,18,"S",120,18,"rcuos/1",21
-6824712996815000,1,3192000,6824713000007000,2720,"R+",120,755,"sh",20460
-6824712998591000,2,346000,6824712998937000,0,"R",120,"[NULL]","swapper",0
-6824712998658000,0,379000,6824712999037000,770,"S",120,493,"Binder:640_2",675
-6824712998937000,2,202000,6824712999139000,773,"S",97,493,"app",678
-6824712999037000,0,34000,6824712999071000,0,"R",120,"[NULL]","swapper",0
-6824712999071000,0,62000,6824712999133000,771,"S",97,493,"DispSync",676
-6824712999133000,0,22793000,6824713021926000,0,"R",120,"[NULL]","swapper",0
-6824712999139000,2,28073000,6824713027212000,0,"R",120,"[NULL]","swapper",0
-6824713000007000,1,107000,6824713000114000,5,"S",120,5,"rcu_preempt",7
-6824713000114000,1,92000,6824713000206000,8,"S",120,8,"rcuop/0",10
-6824713000206000,1,61000,6824713000267000,17,"S",120,17,"rcuop/1",20
-6824713000267000,1,3074000,6824713003341000,2720,"R",120,755,"sh",20460
-6824713003341000,1,209000,6824713003550000,482,"S",49,482,"sugov:0",605
-6824713003550000,1,7239000,6824713010789000,2720,"R",120,755,"sh",20460
-6824713010789000,1,52000,6824713010841000,8,"S",120,8,"rcuop/0",10
-6824713010841000,1,35000,6824713010876000,5,"S",120,5,"rcu_preempt",7
-6824713010876000,1,95000,6824713010971000,2720,"R+",120,755,"sh",20460
-6824713010971000,1,26000,6824713010997000,145,"S",120,145,"hwrng",215
-6824713010997000,1,5636000,6824713016633000,2720,"R",120,755,"sh",20460
-6824713016633000,1,67000,6824713016700000,5,"S",120,5,"rcu_preempt",7
-6824713016700000,1,66000,6824713016766000,8,"S",120,8,"rcuop/0",10
-6824713016766000,1,36000,6824713016802000,17,"S",120,17,"rcuop/1",20
-6824713016802000,1,12000,6824713016814000,5,"S",120,5,"rcu_preempt",7
-6824713016814000,1,1724000,6824713018538000,2720,"S",120,755,"sh",20460
-6824713018538000,1,2161000,6824713020699000,2721,"R+",120,756,"sh",20462
-6824713020699000,1,225000,6824713020924000,482,"S",49,482,"sugov:0",605
-6824713020924000,1,273000,6824713021197000,2721,"S",120,756,"sh",20462
-6824713021197000,1,5881000,6824713027078000,0,"R",120,"[NULL]","swapper",0
-6824713021926000,0,1729000,6824713023655000,2722,"R+",120,757,"ps",20463
-6824713023655000,0,62000,6824713023717000,9,"S",120,9,"rcuos/0",11
-6824713023717000,0,29000,6824713023746000,6,"S",120,6,"rcu_sched",8
-6824713023746000,0,29000,6824713023775000,2722,"R+",120,757,"ps",20463
-6824713023775000,0,30000,6824713023805000,5,"S",120,5,"rcu_preempt",7
-6824713023805000,0,413000,6824713024218000,2722,"R+",120,757,"ps",20463
-6824713024218000,0,23000,6824713024241000,145,"S",120,145,"hwrng",215
-6824713024241000,0,556000,6824713024797000,2722,"R+",120,757,"ps",20463
-6824713024797000,0,9000,6824713024806000,145,"S",120,145,"hwrng",215
-6824713024806000,0,1217000,6824713026023000,2722,"R+",120,757,"ps",20463
-6824713026023000,0,91000,6824713026114000,743,"S",120,743,"kworker/0:5",20371
-6824713026114000,0,814000,6824713026928000,786,"S",111,494,"SDM_EventThread",685
-6824713026928000,0,45000,6824713026973000,5,"S",120,5,"rcu_preempt",7
-6824713026973000,0,263000,6824713027236000,2722,"R+",120,757,"ps",20463
-6824713027078000,1,93000,6824713027171000,702,"S",120,702,"kworker/u16:7",19422
-6824713027171000,1,67000,6824713027238000,8,"S",120,8,"rcuop/0",10
-6824713027212000,2,447000,6824713027659000,777,"S",120,493,"HwBinder:640_1",721
-6824713027236000,0,14000,6824713027250000,5,"S",120,5,"rcu_preempt",7
-6824713027238000,1,61000,6824713027299000,17,"S",120,17,"rcuop/1",20
-6824713027250000,0,2732000,6824713029982000,2722,"R",120,757,"ps",20463
-6824713027299000,1,655000,6824713027954000,0,"R",120,"[NULL]","swapper",0
-6824713027467000,3,179000,6824713027646000,771,"S",97,493,"DispSync",676
-6824713027646000,3,1029000,6824713028675000,0,"R",120,"[NULL]","swapper",0
-6824713027659000,2,901000,6824713028560000,0,"R",120,"[NULL]","swapper",0
-6824713027954000,1,314000,6824713028268000,773,"S",97,493,"app",678
-6824713028268000,1,2352000,6824713030620000,0,"R",120,"[NULL]","swapper",0
-6824713028560000,2,1914000,6824713030474000,644,"S",120,644,"ndroid.systemui",1664
-6824713028675000,3,34000,6824713028709000,771,"S",97,493,"DispSync",676
-6824713028709000,3,34349000,6824713063058000,0,"R",120,"[NULL]","swapper",0
-6824713029982000,0,33000,6824713030015000,6,"S",120,6,"rcu_sched",8
-6824713030015000,0,3308000,6824713033323000,2722,"R+",120,757,"ps",20463
-6824713030474000,2,705000,6824713031179000,0,"R",120,"[NULL]","swapper",0
-6824713030620000,1,274000,6824713030894000,770,"S",120,493,"Binder:640_2",675
-6824713030894000,1,696000,6824713031590000,0,"R",120,"[NULL]","swapper",0
-6824713031179000,2,137000,6824713031316000,773,"S",97,493,"app",678
-6824713031316000,2,29313000,6824713060629000,0,"R",120,"[NULL]","swapper",0
-6824713031590000,1,43000,6824713031633000,771,"S",97,493,"DispSync",676
-6824713031633000,1,2153000,6824713033786000,0,"R",120,"[NULL]","swapper",0
-6824713033323000,0,89000,6824713033412000,5,"S",120,5,"rcu_preempt",7
-6824713033412000,0,86000,6824713033498000,8,"S",120,8,"rcuop/0",10
-6824713033498000,0,13000,6824713033511000,5,"S",120,5,"rcu_preempt",7
-6824713033511000,0,3137000,6824713036648000,2722,"R",120,757,"ps",20463
-6824713033786000,1,36000,6824713033822000,17,"S",120,17,"rcuop/1",20
-6824713033822000,1,6659000,6824713040481000,0,"R",120,"[NULL]","swapper",0
-6824713036648000,0,56000,6824713036704000,6,"S",120,6,"rcu_sched",8
-6824713036704000,0,54000,6824713036758000,9,"S",120,9,"rcuos/0",11
-6824713036758000,0,10000,6824713036768000,6,"S",120,6,"rcu_sched",8
-6824713036768000,0,6593000,6824713043361000,2722,"R",120,757,"ps",20463
-6824713040481000,1,46000,6824713040527000,5,"S",120,5,"rcu_preempt",7
-6824713040527000,1,3210000,6824713043737000,0,"R",120,"[NULL]","swapper",0
-6824713043361000,0,195000,6824713043556000,482,"S",49,482,"sugov:0",605
-6824713043556000,0,3032000,6824713046588000,2722,"R",120,757,"ps",20463
-6824713043737000,1,36000,6824713043773000,6,"S",120,6,"rcu_sched",8
-6824713043773000,1,3242000,6824713047015000,0,"R",120,"[NULL]","swapper",0
-6824713046588000,0,37000,6824713046625000,482,"S",49,482,"sugov:0",605
-6824713046625000,0,431000,6824713047056000,2722,"R",120,757,"ps",20463
-6824713047015000,1,48000,6824713047063000,5,"S",120,5,"rcu_preempt",7
-6824713047056000,0,43000,6824713047099000,8,"S",120,8,"rcuop/0",10
-6824713047063000,1,3191000,6824713050254000,0,"R",120,"[NULL]","swapper",0
-6824713047099000,0,3188000,6824713050287000,2722,"R",120,757,"ps",20463
-6824713050254000,1,42000,6824713050296000,6,"S",120,6,"rcu_sched",8
-6824713050287000,0,36000,6824713050323000,9,"S",120,9,"rcuos/0",11
-6824713050296000,1,4103000,6824713054399000,0,"R",120,"[NULL]","swapper",0
-6824713050323000,0,3621000,6824713053944000,2722,"R",120,757,"ps",20463
-6824713053165000,6,647000,6824713053812000,650,"S",120,650,"m.android.phone",1702
-6824713053812000,6,196550000,6824713250362000,0,"R",120,"[NULL]","swapper",0
-6824713053944000,0,46000,6824713053990000,8,"S",120,8,"rcuop/0",10
-6824713053990000,0,65000,6824713054055000,2722,"R+",120,757,"ps",20463
-6824713054055000,0,22000,6824713054077000,145,"S",120,145,"hwrng",215
-6824713054077000,0,5450000,6824713059527000,2722,"R",120,757,"ps",20463
-6824713054399000,1,30000,6824713054429000,5,"S",120,5,"rcu_preempt",7
-6824713054429000,1,6141000,6824713060570000,0,"R",120,"[NULL]","swapper",0
-6824713059527000,0,91000,6824713059618000,743,"S",120,743,"kworker/0:5",20371
-6824713059618000,0,735000,6824713060353000,786,"S",111,494,"SDM_EventThread",685
-6824713060353000,0,48000,6824713060401000,743,"S",120,743,"kworker/0:5",20371
-6824713060401000,0,2914000,6824713063315000,2722,"R+",120,757,"ps",20463
-6824713060570000,1,23000,6824713060593000,15,"S",120,15,"ksoftirqd/1",17
-6824713060593000,1,54000,6824713060647000,5,"S",120,5,"rcu_preempt",7
-6824713060629000,2,431000,6824713061060000,777,"S",120,493,"HwBinder:640_1",721
-6824713060647000,1,274000,6824713060921000,0,"R",120,"[NULL]","swapper",0
-6824713060921000,1,103000,6824713061024000,771,"S",97,493,"DispSync",676
-6824713061024000,1,915000,6824713061939000,0,"R",120,"[NULL]","swapper",0
-6824713061060000,2,1313000,6824713062373000,0,"R",120,"[NULL]","swapper",0
-6824713061939000,1,85000,6824713062024000,771,"S",97,493,"DispSync",676
-6824713062024000,1,1073000,6824713063097000,0,"R",120,"[NULL]","swapper",0
-6824713062373000,2,326000,6824713062699000,773,"S",97,493,"app",678
-6824713062699000,2,2701000,6824713065400000,0,"R",120,"[NULL]","swapper",0
-6824713063058000,3,1709000,6824713064767000,644,"S",120,644,"ndroid.systemui",1664
-6824713063097000,1,28000,6824713063125000,771,"S",97,493,"DispSync",676
-6824713063125000,1,518000,6824713063643000,0,"R",120,"[NULL]","swapper",0
-6824713063315000,0,161000,6824713063476000,482,"S",49,482,"sugov:0",605
-6824713063476000,0,29511000,6824713092987000,2722,"R+",120,757,"ps",20463
-6824713063643000,1,682000,6824713064325000,702,"S",120,702,"kworker/u16:7",19422
-6824713064325000,1,588000,6824713064913000,0,"R",120,"[NULL]","swapper",0
-6824713064767000,3,15375000,6824713080142000,0,"R",120,"[NULL]","swapper",0
-6824713064913000,1,237000,6824713065150000,770,"S",120,493,"Binder:640_2",675
-6824713065150000,1,321000,6824713065471000,0,"R",120,"[NULL]","swapper",0
-6824713065400000,2,110000,6824713065510000,773,"S",97,493,"app",678
-6824713065471000,1,26000,6824713065497000,771,"S",97,493,"DispSync",676
-6824713065497000,1,1148000,6824713066645000,0,"R",120,"[NULL]","swapper",0
-6824713065510000,2,1194000,6824713066704000,0,"R",120,"[NULL]","swapper",0
-6824713066645000,1,64000,6824713066709000,5,"S",120,5,"rcu_preempt",7
-6824713066704000,2,53000,6824713066757000,8,"S",120,8,"rcuop/0",10
-6824713066709000,1,41000,6824713066750000,0,"R",120,"[NULL]","swapper",0
-6824713066750000,1,18000,6824713066768000,5,"S",120,5,"rcu_preempt",7
-6824713066757000,2,4703000,6824713071460000,0,"R",120,"[NULL]","swapper",0
-6824713066768000,1,4421000,6824713071189000,0,"R",120,"[NULL]","swapper",0
-6824713071189000,1,109000,6824713071298000,2728,"S",120,739,"shell",20461
-6824713071298000,1,679000,6824713071977000,0,"R",120,"[NULL]","swapper",0
-6824713071460000,2,412000,6824713071872000,739,"S",120,739,"adbd",20305
-6824713071872000,2,322000,6824713072194000,0,"R",120,"[NULL]","swapper",0
-6824713071977000,1,50000,6824713072027000,630,"S",100,630,"kworker/u17:1",1134
-6824713072027000,1,34000,6824713072061000,693,"S",120,693,"kworker/1:1",18800
-6824713072061000,1,129000,6824713072190000,0,"R",120,"[NULL]","swapper",0
-6824713072190000,1,20000,6824713072210000,630,"S",100,630,"kworker/u17:1",1134
-6824713072194000,2,45000,6824713072239000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713072210000,1,337000,6824713072547000,0,"R",120,"[NULL]","swapper",0
-6824713072239000,2,259000,6824713072498000,0,"R",120,"[NULL]","swapper",0
-6824713072498000,2,31000,6824713072529000,630,"S",100,630,"kworker/u17:1",1134
-6824713072529000,2,26000,6824713072555000,694,"S",120,694,"kworker/2:0",18823
-6824713072547000,1,36000,6824713072583000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713072555000,2,85000,6824713072640000,0,"R",120,"[NULL]","swapper",0
-6824713072583000,1,374000,6824713072957000,0,"R",120,"[NULL]","swapper",0
-6824713072640000,2,21000,6824713072661000,630,"S",100,630,"kworker/u17:1",1134
-6824713072661000,2,249000,6824713072910000,0,"R",120,"[NULL]","swapper",0
-6824713072910000,2,25000,6824713072935000,630,"S",100,630,"kworker/u17:1",1134
-6824713072935000,2,32000,6824713072967000,694,"S",120,694,"kworker/2:0",18823
-6824713072957000,1,71000,6824713073028000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713072967000,2,23000,6824713072990000,0,"R",120,"[NULL]","swapper",0
-6824713072990000,2,99000,6824713073089000,739,"S",120,739,"adbd",20305
-6824713073028000,1,235000,6824713073263000,0,"R",120,"[NULL]","swapper",0
-6824713073089000,2,196000,6824713073285000,0,"R",120,"[NULL]","swapper",0
-6824713073263000,1,25000,6824713073288000,5,"S",120,5,"rcu_preempt",7
-6824713073285000,2,117000,6824713073402000,8,"S",120,8,"rcuop/0",10
-6824713073288000,1,270000,6824713073558000,0,"R",120,"[NULL]","swapper",0
-6824713073402000,2,3701000,6824713077103000,0,"R",120,"[NULL]","swapper",0
-6824713073558000,1,15000,6824713073573000,5,"S",120,5,"rcu_preempt",7
-6824713073573000,1,3170000,6824713076743000,0,"R",120,"[NULL]","swapper",0
-6824713076743000,1,148000,6824713076891000,702,"D",120,702,"kworker/u16:7",19422
-6824713076891000,1,199000,6824713077090000,0,"R",120,"[NULL]","swapper",0
-6824713077090000,1,16000,6824713077106000,702,"S",120,702,"kworker/u16:7",19422
-6824713077103000,2,19000,6824713077122000,77,"S",120,77,"smem_native_rpm",87
-6824713077106000,1,2331000,6824713079437000,0,"R",120,"[NULL]","swapper",0
-6824713077122000,2,2542000,6824713079664000,0,"R",120,"[NULL]","swapper",0
-6824713079437000,1,81000,6824713079518000,2728,"S",120,739,"shell",20461
-6824713079518000,1,417000,6824713079935000,0,"R",120,"[NULL]","swapper",0
-6824713079664000,2,293000,6824713079957000,739,"S",120,739,"adbd",20305
-6824713079935000,1,31000,6824713079966000,630,"S",100,630,"kworker/u17:1",1134
-6824713079957000,2,23000,6824713079980000,0,"R",120,"[NULL]","swapper",0
-6824713079966000,1,28000,6824713079994000,693,"S",120,693,"kworker/1:1",18800
-6824713079980000,2,20000,6824713080000000,630,"S",100,630,"kworker/u17:1",1134
-6824713079994000,1,24000,6824713080018000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713080000000,2,320000,6824713080320000,0,"R",120,"[NULL]","swapper",0
-6824713080018000,1,518000,6824713080536000,0,"R",120,"[NULL]","swapper",0
-6824713080142000,3,24000,6824713080166000,5,"S",120,5,"rcu_preempt",7
-6824713080166000,3,419000,6824713080585000,0,"R",120,"[NULL]","swapper",0
-6824713080320000,2,27000,6824713080347000,630,"S",100,630,"kworker/u17:1",1134
-6824713080347000,2,41000,6824713080388000,694,"S",120,694,"kworker/2:0",18823
-6824713080388000,2,452000,6824713080840000,0,"R",120,"[NULL]","swapper",0
-6824713080536000,1,38000,6824713080574000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713080574000,1,488000,6824713081062000,0,"R",120,"[NULL]","swapper",0
-6824713080585000,3,26000,6824713080611000,630,"S",100,630,"kworker/u17:1",1134
-6824713080611000,3,6419000,6824713087030000,0,"R",120,"[NULL]","swapper",0
-6824713080840000,2,23000,6824713080863000,630,"S",100,630,"kworker/u17:1",1134
-6824713080863000,2,43000,6824713080906000,694,"S",120,694,"kworker/2:0",18823
-6824713080906000,2,345000,6824713081251000,0,"R",120,"[NULL]","swapper",0
-6824713081062000,1,72000,6824713081134000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713081134000,1,6852000,6824713087986000,0,"R",120,"[NULL]","swapper",0
-6824713081251000,2,106000,6824713081357000,739,"S",120,739,"adbd",20305
-6824713081357000,2,6049000,6824713087406000,0,"R",120,"[NULL]","swapper",0
-6824713087030000,3,62000,6824713087092000,5,"S",120,5,"rcu_preempt",7
-6824713087092000,3,964000,6824713088056000,0,"R",120,"[NULL]","swapper",0
-6824713087406000,2,284000,6824713087690000,8,"S",120,8,"rcuop/0",10
-6824713087690000,2,783000,6824713088473000,0,"R",120,"[NULL]","swapper",0
-6824713087986000,1,139000,6824713088125000,2728,"S",120,739,"shell",20461
-6824713088056000,3,22000,6824713088078000,5,"S",120,5,"rcu_preempt",7
-6824713088078000,3,36000,6824713088114000,0,"R",120,"[NULL]","swapper",0
-6824713088114000,3,404000,6824713088518000,739,"S",120,739,"adbd",20305
-6824713088125000,1,464000,6824713088589000,0,"R",120,"[NULL]","swapper",0
-6824713088473000,2,53000,6824713088526000,630,"S",100,630,"kworker/u17:1",1134
-6824713088518000,3,43000,6824713088561000,0,"R",120,"[NULL]","swapper",0
-6824713088526000,2,74000,6824713088600000,694,"S",120,694,"kworker/2:0",18823
-6824713088561000,3,34000,6824713088595000,630,"S",100,630,"kworker/u17:1",1134
-6824713088589000,1,37000,6824713088626000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713088595000,3,122000,6824713088717000,0,"R",120,"[NULL]","swapper",0
-6824713088600000,2,1021000,6824713089621000,0,"R",120,"[NULL]","swapper",0
-6824713088626000,1,590000,6824713089216000,0,"R",120,"[NULL]","swapper",0
-6824713088717000,3,48000,6824713088765000,630,"S",100,630,"kworker/u17:1",1134
-6824713088765000,3,41000,6824713088806000,686,"S",120,686,"kworker/3:1",17791
-6824713088806000,3,14000,6824713088820000,0,"R",120,"[NULL]","swapper",0
-6824713088820000,3,17000,6824713088837000,630,"S",100,630,"kworker/u17:1",1134
-6824713088837000,3,135000,6824713088972000,0,"R",120,"[NULL]","swapper",0
-6824713088972000,3,44000,6824713089016000,630,"S",100,630,"kworker/u17:1",1134
-6824713089016000,3,47000,6824713089063000,0,"R",120,"[NULL]","swapper",0
-6824713089063000,3,35000,6824713089098000,630,"S",100,630,"kworker/u17:1",1134
-6824713089098000,3,89000,6824713089187000,686,"S",120,686,"kworker/3:1",17791
-6824713089187000,3,4413000,6824713093600000,0,"R",120,"[NULL]","swapper",0
-6824713089216000,1,154000,6824713089370000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713089370000,1,4023000,6824713093393000,0,"R",120,"[NULL]","swapper",0
-6824713089621000,2,127000,6824713089748000,739,"S",120,739,"adbd",20305
-6824713089748000,2,4425000,6824713094173000,0,"R",120,"[NULL]","swapper",0
-6824713092987000,0,74000,6824713093061000,743,"S",120,743,"kworker/0:5",20371
-6824713093061000,0,3580000,6824713096641000,2722,"R+",120,757,"ps",20463
-6824713093393000,1,580000,6824713093973000,786,"S",111,494,"SDM_EventThread",685
-6824713093600000,3,36000,6824713093636000,5,"S",120,5,"rcu_preempt",7
-6824713093636000,3,1371000,6824713095007000,0,"R",120,"[NULL]","swapper",0
-6824713093973000,1,507000,6824713094480000,0,"R",120,"[NULL]","swapper",0
-6824713094173000,2,367000,6824713094540000,777,"S",120,493,"HwBinder:640_1",721
-6824713094480000,1,99000,6824713094579000,771,"S",97,493,"DispSync",676
-6824713094540000,2,9000,6824713094549000,0,"R",120,"[NULL]","swapper",0
-6824713094549000,2,126000,6824713094675000,777,"S",120,493,"HwBinder:640_1",721
-6824713094579000,1,9000,6824713094588000,0,"R",120,"[NULL]","swapper",0
-6824713094588000,1,74000,6824713094662000,771,"S",97,493,"DispSync",676
-6824713094662000,1,934000,6824713095596000,0,"R",120,"[NULL]","swapper",0
-6824713094675000,2,1004000,6824713095679000,0,"R",120,"[NULL]","swapper",0
-6824713095007000,3,267000,6824713095274000,773,"S",97,493,"app",678
-6824713095274000,3,5029000,6824713100303000,0,"R",120,"[NULL]","swapper",0
-6824713095596000,1,2136000,6824713097732000,644,"S",120,644,"ndroid.systemui",1664
-6824713095679000,2,17000,6824713095696000,771,"S",97,493,"DispSync",676
-6824713095696000,2,2152000,6824713097848000,0,"R",120,"[NULL]","swapper",0
-6824713096641000,0,233000,6824713096874000,482,"S",49,482,"sugov:0",605
-6824713096874000,0,29589000,6824713126463000,2722,"R+",120,757,"ps",20463
-6824713097732000,1,701000,6824713098433000,0,"R",120,"[NULL]","swapper",0
-6824713097848000,2,321000,6824713098169000,770,"S",120,493,"Binder:640_2",675
-6824713098169000,2,724000,6824713098893000,0,"R",120,"[NULL]","swapper",0
-6824713098433000,1,171000,6824713098604000,773,"S",97,493,"app",678
-6824713098604000,1,39000,6824713098643000,0,"R",120,"[NULL]","swapper",0
-6824713098643000,1,113000,6824713098756000,482,"S",49,482,"sugov:0",605
-6824713098756000,1,488000,6824713099244000,0,"R",120,"[NULL]","swapper",0
-6824713098893000,2,25000,6824713098918000,771,"S",97,493,"DispSync",676
-6824713098918000,2,480000,6824713099398000,0,"R",120,"[NULL]","swapper",0
-6824713099244000,1,183000,6824713099427000,2728,"S",120,739,"shell",20461
-6824713099398000,2,1576000,6824713100974000,739,"S",120,739,"adbd",20305
-6824713099427000,1,51000,6824713099478000,0,"R",120,"[NULL]","swapper",0
-6824713099478000,1,65000,6824713099543000,1919,"S",120,667,"Executor-7",14762
-6824713099543000,1,1075000,6824713100618000,0,"R",120,"[NULL]","swapper",0
-6824713100303000,3,67000,6824713100370000,630,"S",100,630,"kworker/u17:1",1134
-6824713100370000,3,9000,6824713100379000,0,"R",120,"[NULL]","swapper",0
-6824713100379000,3,72000,6824713100451000,630,"S",100,630,"kworker/u17:1",1134
-6824713100451000,3,97000,6824713100548000,686,"S",120,686,"kworker/3:1",17791
-6824713100548000,3,59000,6824713100607000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713100607000,3,31000,6824713100638000,630,"S",100,630,"kworker/u17:1",1134
-6824713100618000,1,54000,6824713100672000,5,"S",120,5,"rcu_preempt",7
-6824713100638000,3,17000,6824713100655000,686,"S",120,686,"kworker/3:1",17791
-6824713100655000,3,15000,6824713100670000,2487,"R",120,739,"UsbFfs-worker",20308
-6824713100670000,3,12000,6824713100682000,630,"S",100,630,"kworker/u17:1",1134
-6824713100672000,1,561000,6824713101233000,8,"S",120,8,"rcuop/0",10
-6824713100682000,3,60000,6824713100742000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713100742000,3,513000,6824713101255000,0,"R",120,"[NULL]","swapper",0
-6824713100974000,2,632000,6824713101606000,0,"R",120,"[NULL]","swapper",0
-6824713101233000,1,787000,6824713102020000,0,"R",120,"[NULL]","swapper",0
-6824713101255000,3,47000,6824713101302000,630,"S",100,630,"kworker/u17:1",1134
-6824713101302000,3,605000,6824713101907000,0,"R",120,"[NULL]","swapper",0
-6824713101606000,2,31000,6824713101637000,5,"S",120,5,"rcu_preempt",7
-6824713101637000,2,471000,6824713102108000,0,"R",120,"[NULL]","swapper",0
-6824713101907000,3,54000,6824713101961000,630,"S",100,630,"kworker/u17:1",1134
-6824713101961000,3,73000,6824713102034000,686,"S",120,686,"kworker/3:1",17791
-6824713102020000,1,177000,6824713102197000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713102034000,3,8819000,6824713110853000,0,"R",120,"[NULL]","swapper",0
-6824713102108000,2,177000,6824713102285000,739,"S",120,739,"adbd",20305
-6824713102197000,1,5230000,6824713107427000,0,"R",120,"[NULL]","swapper",0
-6824713102285000,2,4714000,6824713106999000,0,"R",120,"[NULL]","swapper",0
-6824713106999000,2,46000,6824713107045000,5,"S",120,5,"rcu_preempt",7
-6824713107045000,2,1111000,6824713108156000,0,"R",120,"[NULL]","swapper",0
-6824713107427000,1,382000,6824713107809000,8,"S",120,8,"rcuop/0",10
-6824713107809000,1,1784000,6824713109593000,0,"R",120,"[NULL]","swapper",0
-6824713108156000,2,24000,6824713108180000,5,"S",120,5,"rcu_preempt",7
-6824713108180000,2,1871000,6824713110051000,0,"R",120,"[NULL]","swapper",0
-6824713109593000,1,155000,6824713109748000,2728,"S",120,739,"shell",20461
-6824713109748000,1,1604000,6824713111352000,0,"R",120,"[NULL]","swapper",0
-6824713110051000,2,506000,6824713110557000,739,"S",120,739,"adbd",20305
-6824713110557000,2,728000,6824713111285000,0,"R",120,"[NULL]","swapper",0
-6824713110853000,3,66000,6824713110919000,630,"S",100,630,"kworker/u17:1",1134
-6824713110919000,3,54000,6824713110973000,686,"S",120,686,"kworker/3:1",17791
-6824713110973000,3,1252000,6824713112225000,0,"R",120,"[NULL]","swapper",0
-6824713111285000,2,35000,6824713111320000,630,"S",100,630,"kworker/u17:1",1134
-6824713111320000,2,474000,6824713111794000,0,"R",120,"[NULL]","swapper",0
-6824713111352000,1,75000,6824713111427000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713111427000,1,882000,6824713112309000,0,"R",120,"[NULL]","swapper",0
-6824713111794000,2,71000,6824713111865000,630,"S",100,630,"kworker/u17:1",1134
-6824713111865000,2,64000,6824713111929000,694,"S",120,694,"kworker/2:0",18823
-6824713111929000,2,466000,6824713112395000,0,"R",120,"[NULL]","swapper",0
-6824713112225000,3,47000,6824713112272000,630,"S",100,630,"kworker/u17:1",1134
-6824713112272000,3,72000,6824713112344000,686,"S",120,686,"kworker/3:1",17791
-6824713112309000,1,168000,6824713112477000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713112344000,3,10051000,6824713122395000,0,"R",120,"[NULL]","swapper",0
-6824713112395000,2,142000,6824713112537000,739,"S",120,739,"adbd",20305
-6824713112477000,1,4894000,6824713117371000,0,"R",120,"[NULL]","swapper",0
-6824713112537000,2,766000,6824713113303000,0,"R",120,"[NULL]","swapper",0
-6824713113303000,2,30000,6824713113333000,5,"S",120,5,"rcu_preempt",7
-6824713113333000,2,3671000,6824713117004000,0,"R",120,"[NULL]","swapper",0
-6824713117004000,2,42000,6824713117046000,5,"S",120,5,"rcu_preempt",7
-6824713117046000,2,851000,6824713117897000,0,"R",120,"[NULL]","swapper",0
-6824713117371000,1,213000,6824713117584000,8,"S",120,8,"rcuop/0",10
-6824713117584000,1,3602000,6824713121186000,0,"R",120,"[NULL]","swapper",0
-6824713117897000,2,22000,6824713117919000,5,"S",120,5,"rcu_preempt",7
-6824713117919000,2,3713000,6824713121632000,0,"R",120,"[NULL]","swapper",0
-6824713121186000,1,154000,6824713121340000,2728,"S",120,739,"shell",20461
-6824713121340000,1,1525000,6824713122865000,0,"R",120,"[NULL]","swapper",0
-6824713121632000,2,519000,6824713122151000,739,"S",120,739,"adbd",20305
-6824713122151000,2,341000,6824713122492000,0,"R",120,"[NULL]","swapper",0
-6824713122395000,3,74000,6824713122469000,630,"S",100,630,"kworker/u17:1",1134
-6824713122469000,3,51000,6824713122520000,686,"S",120,686,"kworker/3:1",17791
-6824713122492000,2,31000,6824713122523000,630,"S",100,630,"kworker/u17:1",1134
-6824713122520000,3,1113000,6824713123633000,0,"R",120,"[NULL]","swapper",0
-6824713122523000,2,120000,6824713122643000,0,"R",120,"[NULL]","swapper",0
-6824713122643000,2,45000,6824713122688000,630,"S",100,630,"kworker/u17:1",1134
-6824713122688000,2,30000,6824713122718000,694,"S",120,694,"kworker/2:0",18823
-6824713122718000,2,23000,6824713122741000,0,"R",120,"[NULL]","swapper",0
-6824713122741000,2,16000,6824713122757000,630,"S",100,630,"kworker/u17:1",1134
-6824713122757000,2,136000,6824713122893000,0,"R",120,"[NULL]","swapper",0
-6824713122865000,1,95000,6824713122960000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713122893000,2,34000,6824713122927000,630,"S",100,630,"kworker/u17:1",1134
-6824713122927000,2,101000,6824713123028000,0,"R",120,"[NULL]","swapper",0
-6824713122960000,1,168000,6824713123128000,0,"R",120,"[NULL]","swapper",0
-6824713123028000,2,42000,6824713123070000,630,"S",100,630,"kworker/u17:1",1134
-6824713123070000,2,76000,6824713123146000,694,"S",120,694,"kworker/2:0",18823
-6824713123128000,1,152000,6824713123280000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713123146000,2,29000,6824713123175000,0,"R",120,"[NULL]","swapper",0
-6824713123175000,2,190000,6824713123365000,739,"S",120,739,"adbd",20305
-6824713123280000,1,3559000,6824713126839000,0,"R",120,"[NULL]","swapper",0
-6824713123365000,2,3548000,6824713126913000,0,"R",120,"[NULL]","swapper",0
-6824713123633000,3,30000,6824713123663000,5,"S",120,5,"rcu_preempt",7
-6824713123663000,3,3867000,6824713127530000,0,"R",120,"[NULL]","swapper",0
-6824713126463000,0,72000,6824713126535000,743,"S",120,743,"kworker/0:5",20371
-6824713126535000,0,3430000,6824713129965000,2722,"R+",120,757,"ps",20463
-6824713126839000,1,582000,6824713127421000,786,"S",111,494,"SDM_EventThread",685
-6824713126913000,2,467000,6824713127380000,702,"R+",120,702,"kworker/u16:7",19422
-6824713127380000,2,198000,6824713127578000,771,"S",97,493,"DispSync",676
-6824713127421000,1,507000,6824713127928000,0,"R",120,"[NULL]","swapper",0
-6824713127530000,3,44000,6824713127574000,77,"S",120,77,"smem_native_rpm",87
-6824713127574000,3,559000,6824713128133000,0,"R",120,"[NULL]","swapper",0
-6824713127578000,2,33000,6824713127611000,702,"S",120,702,"kworker/u16:7",19422
-6824713127611000,2,338000,6824713127949000,777,"S",120,493,"HwBinder:640_1",721
-6824713127928000,1,258000,6824713128186000,773,"S",97,493,"app",678
-6824713127949000,2,518000,6824713128467000,0,"R",120,"[NULL]","swapper",0
-6824713128133000,3,26000,6824713128159000,771,"S",97,493,"DispSync",676
-6824713128159000,3,8000,6824713128167000,0,"R",120,"[NULL]","swapper",0
-6824713128167000,3,13000,6824713128180000,771,"S",97,493,"DispSync",676
-6824713128180000,3,1804000,6824713129984000,0,"R",120,"[NULL]","swapper",0
-6824713128186000,1,2334000,6824713130520000,0,"R",120,"[NULL]","swapper",0
-6824713128467000,2,1954000,6824713130421000,644,"S",120,644,"ndroid.systemui",1664
-6824713129965000,0,223000,6824713130188000,482,"S",49,482,"sugov:0",605
-6824713129984000,3,64000,6824713130048000,5,"S",120,5,"rcu_preempt",7
-6824713130048000,3,1593000,6824713131641000,0,"R",120,"[NULL]","swapper",0
-6824713130188000,0,29833000,6824713160021000,2722,"R",120,757,"ps",20463
-6824713130421000,2,758000,6824713131179000,0,"R",120,"[NULL]","swapper",0
-6824713130520000,1,356000,6824713130876000,770,"S",120,493,"Binder:640_2",675
-6824713130876000,1,61000,6824713130937000,8,"R",120,8,"rcuop/0",10
-6824713130937000,1,114000,6824713131051000,482,"S",49,482,"sugov:0",605
-6824713131051000,1,355000,6824713131406000,8,"S",120,8,"rcuop/0",10
-6824713131179000,2,114000,6824713131293000,773,"S",97,493,"app",678
-6824713131293000,2,593000,6824713131886000,0,"R",120,"[NULL]","swapper",0
-6824713131406000,1,828000,6824713132234000,0,"R",120,"[NULL]","swapper",0
-6824713131641000,3,30000,6824713131671000,771,"S",97,493,"DispSync",676
-6824713131671000,3,95000,6824713131766000,0,"R",120,"[NULL]","swapper",0
-6824713131766000,3,183000,6824713131949000,2728,"S",120,739,"shell",20461
-6824713131886000,2,26000,6824713131912000,5,"S",120,5,"rcu_preempt",7
-6824713131912000,2,1066000,6824713132978000,0,"R",120,"[NULL]","swapper",0
-6824713131949000,3,1543000,6824713133492000,0,"R",120,"[NULL]","swapper",0
-6824713132234000,1,838000,6824713133072000,739,"S",120,739,"adbd",20305
-6824713132978000,2,164000,6824713133142000,630,"S",100,630,"kworker/u17:1",1134
-6824713133072000,1,496000,6824713133568000,0,"R",120,"[NULL]","swapper",0
-6824713133142000,2,65000,6824713133207000,694,"S",120,694,"kworker/2:0",18823
-6824713133207000,2,70000,6824713133277000,0,"R",120,"[NULL]","swapper",0
-6824713133277000,2,50000,6824713133327000,630,"S",100,630,"kworker/u17:1",1134
-6824713133327000,2,20000,6824713133347000,694,"S",120,694,"kworker/2:0",18823
-6824713133347000,2,160000,6824713133507000,0,"R",120,"[NULL]","swapper",0
-6824713133492000,3,53000,6824713133545000,670,"S",100,670,"kworker/u17:2",14944
-6824713133507000,2,8000,6824713133515000,630,"S",100,630,"kworker/u17:1",1134
-6824713133515000,2,65000,6824713133580000,0,"R",120,"[NULL]","swapper",0
-6824713133545000,3,9733000,6824713143278000,0,"R",120,"[NULL]","swapper",0
-6824713133568000,1,104000,6824713133672000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713133580000,2,40000,6824713133620000,670,"S",100,670,"kworker/u17:2",14944
-6824713133620000,2,86000,6824713133706000,694,"S",120,694,"kworker/2:0",18823
-6824713133672000,1,11000,6824713133683000,0,"R",120,"[NULL]","swapper",0
-6824713133683000,1,142000,6824713133825000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713133706000,2,37000,6824713133743000,0,"R",120,"[NULL]","swapper",0
-6824713133743000,2,140000,6824713133883000,739,"S",120,739,"adbd",20305
-6824713133825000,1,6827000,6824713140652000,0,"R",120,"[NULL]","swapper",0
-6824713133883000,2,3063000,6824713136946000,0,"R",120,"[NULL]","swapper",0
-6824713136946000,2,41000,6824713136987000,5,"S",120,5,"rcu_preempt",7
-6824713136987000,2,3274000,6824713140261000,0,"R",120,"[NULL]","swapper",0
-6824713140261000,2,37000,6824713140298000,5,"S",120,5,"rcu_preempt",7
-6824713140298000,2,1112000,6824713141410000,0,"R",120,"[NULL]","swapper",0
-6824713140652000,1,423000,6824713141075000,8,"S",120,8,"rcuop/0",10
-6824713141075000,1,1022000,6824713142097000,0,"R",120,"[NULL]","swapper",0
-6824713141410000,2,18000,6824713141428000,5,"S",120,5,"rcu_preempt",7
-6824713141428000,2,1111000,6824713142539000,0,"R",120,"[NULL]","swapper",0
-6824713142097000,1,152000,6824713142249000,2728,"S",120,739,"shell",20461
-6824713142249000,1,2185000,6824713144434000,0,"R",120,"[NULL]","swapper",0
-6824713142539000,2,518000,6824713143057000,739,"S",120,739,"adbd",20305
-6824713143057000,2,1528000,6824713144585000,0,"R",120,"[NULL]","swapper",0
-6824713143278000,3,57000,6824713143335000,670,"S",100,670,"kworker/u17:2",14944
-6824713143335000,3,606000,6824713143941000,0,"R",120,"[NULL]","swapper",0
-6824713143941000,3,76000,6824713144017000,670,"S",100,670,"kworker/u17:2",14944
-6824713144017000,3,60000,6824713144077000,686,"S",120,686,"kworker/3:1",17791
-6824713144077000,3,438000,6824713144515000,0,"R",120,"[NULL]","swapper",0
-6824713144434000,1,56000,6824713144490000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713144490000,1,687000,6824713145177000,0,"R",120,"[NULL]","swapper",0
-6824713144515000,3,36000,6824713144551000,670,"S",100,670,"kworker/u17:2",14944
-6824713144551000,3,44000,6824713144595000,686,"S",120,686,"kworker/3:1",17791
-6824713144585000,2,61000,6824713144646000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713144595000,3,37000,6824713144632000,670,"S",100,670,"kworker/u17:2",14944
-6824713144632000,3,139000,6824713144771000,0,"R",120,"[NULL]","swapper",0
-6824713144646000,2,26000,6824713144672000,0,"R",120,"[NULL]","swapper",0
-6824713144672000,2,58000,6824713144730000,670,"S",100,670,"kworker/u17:2",14944
-6824713144730000,2,57000,6824713144787000,694,"S",120,694,"kworker/2:0",18823
-6824713144771000,3,137000,6824713144908000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713144787000,2,2129000,6824713146916000,0,"R",120,"[NULL]","swapper",0
-6824713144908000,3,9292000,6824713154200000,0,"R",120,"[NULL]","swapper",0
-6824713145177000,1,151000,6824713145328000,739,"S",120,739,"adbd",20305
-6824713145328000,1,1971000,6824713147299000,0,"R",120,"[NULL]","swapper",0
-6824713146916000,2,42000,6824713146958000,5,"S",120,5,"rcu_preempt",7
-6824713146958000,2,950000,6824713147908000,0,"R",120,"[NULL]","swapper",0
-6824713147299000,1,265000,6824713147564000,8,"S",120,8,"rcuop/0",10
-6824713147564000,1,6404000,6824713153968000,0,"R",120,"[NULL]","swapper",0
-6824713147908000,2,20000,6824713147928000,5,"S",120,5,"rcu_preempt",7
-6824713147928000,2,5718000,6824713153646000,0,"R",120,"[NULL]","swapper",0
-6824713153646000,2,49000,6824713153695000,5,"S",120,5,"rcu_preempt",7
-6824713153695000,2,724000,6824713154419000,0,"R",120,"[NULL]","swapper",0
-6824713153968000,1,154000,6824713154122000,2728,"S",120,739,"shell",20461
-6824713154122000,1,591000,6824713154713000,0,"R",120,"[NULL]","swapper",0
-6824713154200000,3,176000,6824713154376000,8,"S",120,8,"rcuop/0",10
-6824713154376000,3,873000,6824713155249000,0,"R",120,"[NULL]","swapper",0
-6824713154419000,2,564000,6824713154983000,739,"S",120,739,"adbd",20305
-6824713154713000,1,18000,6824713154731000,5,"S",120,5,"rcu_preempt",7
-6824713154731000,1,1001000,6824713155732000,0,"R",120,"[NULL]","swapper",0
-6824713154983000,2,683000,6824713155666000,0,"R",120,"[NULL]","swapper",0
-6824713155249000,3,83000,6824713155332000,670,"S",100,670,"kworker/u17:2",14944
-6824713155332000,3,55000,6824713155387000,686,"S",120,686,"kworker/3:1",17791
-6824713155387000,3,344000,6824713155731000,0,"R",120,"[NULL]","swapper",0
-6824713155666000,2,78000,6824713155744000,670,"S",100,670,"kworker/u17:2",14944
-6824713155731000,3,19000,6824713155750000,630,"S",100,630,"kworker/u17:1",1134
-6824713155732000,1,85000,6824713155817000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713155744000,2,88000,6824713155832000,0,"R",120,"[NULL]","swapper",0
-6824713155750000,3,177000,6824713155927000,0,"R",120,"[NULL]","swapper",0
-6824713155817000,1,92000,6824713155909000,0,"R",120,"[NULL]","swapper",0
-6824713155832000,2,47000,6824713155879000,630,"S",100,630,"kworker/u17:1",1134
-6824713155879000,2,58000,6824713155937000,694,"S",120,694,"kworker/2:0",18823
-6824713155909000,1,37000,6824713155946000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713155927000,3,16000,6824713155943000,630,"S",100,630,"kworker/u17:1",1134
-6824713155937000,2,171000,6824713156108000,0,"R",120,"[NULL]","swapper",0
-6824713155943000,3,6823000,6824713162766000,0,"R",120,"[NULL]","swapper",0
-6824713155946000,1,615000,6824713156561000,0,"R",120,"[NULL]","swapper",0
-6824713156108000,2,34000,6824713156142000,630,"S",100,630,"kworker/u17:1",1134
-6824713156142000,2,27000,6824713156169000,0,"R",120,"[NULL]","swapper",0
-6824713156169000,2,40000,6824713156209000,630,"S",100,630,"kworker/u17:1",1134
-6824713156209000,2,45000,6824713156254000,694,"S",120,694,"kworker/2:0",18823
-6824713156254000,2,364000,6824713156618000,0,"R",120,"[NULL]","swapper",0
-6824713156561000,1,142000,6824713156703000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713156618000,2,133000,6824713156751000,739,"S",120,739,"adbd",20305
-6824713156703000,1,3760000,6824713160463000,0,"R",120,"[NULL]","swapper",0
-6824713156751000,2,4509000,6824713161260000,0,"R",120,"[NULL]","swapper",0
-6824713160021000,0,109000,6824713160130000,743,"S",120,743,"kworker/0:5",20371
-6824713160130000,0,33314000,6824713193444000,2722,"R+",120,757,"ps",20463
-6824713160463000,1,578000,6824713161041000,786,"S",111,494,"SDM_EventThread",685
-6824713161041000,1,887000,6824713161928000,0,"R",120,"[NULL]","swapper",0
-6824713161260000,2,459000,6824713161719000,777,"S",120,493,"HwBinder:640_1",721
-6824713161719000,2,304000,6824713162023000,0,"R",120,"[NULL]","swapper",0
-6824713161928000,1,140000,6824713162068000,771,"S",97,493,"DispSync",676
-6824713162023000,2,447000,6824713162470000,773,"S",97,493,"app",678
-6824713162068000,1,358000,6824713162426000,0,"R",120,"[NULL]","swapper",0
-6824713162426000,1,1725000,6824713164151000,644,"S",120,644,"ndroid.systemui",1664
-6824713162470000,2,1183000,6824713163653000,0,"R",120,"[NULL]","swapper",0
-6824713162766000,3,32000,6824713162798000,771,"S",97,493,"DispSync",676
-6824713162798000,3,917000,6824713163715000,0,"R",120,"[NULL]","swapper",0
-6824713163653000,2,751000,6824713164404000,702,"S",120,702,"kworker/u16:7",19422
-6824713163715000,3,56000,6824713163771000,5,"S",120,5,"rcu_preempt",7
-6824713163771000,3,581000,6824713164352000,0,"R",120,"[NULL]","swapper",0
-6824713164151000,1,689000,6824713164840000,0,"R",120,"[NULL]","swapper",0
-6824713164352000,3,251000,6824713164603000,770,"S",120,493,"Binder:640_2",675
-6824713164404000,2,820000,6824713165224000,0,"R",120,"[NULL]","swapper",0
-6824713164603000,3,1967000,6824713166570000,0,"R",120,"[NULL]","swapper",0
-6824713164840000,1,120000,6824713164960000,773,"S",97,493,"app",678
-6824713164960000,1,408000,6824713165368000,0,"R",120,"[NULL]","swapper",0
-6824713165224000,2,31000,6824713165255000,771,"S",97,493,"DispSync",676
-6824713165255000,2,581000,6824713165836000,0,"R",120,"[NULL]","swapper",0
-6824713165368000,1,186000,6824713165554000,2728,"S",120,739,"shell",20461
-6824713165554000,1,1573000,6824713167127000,0,"R",120,"[NULL]","swapper",0
-6824713165836000,2,847000,6824713166683000,739,"R+",120,739,"adbd",20305
-6824713166570000,3,92000,6824713166662000,630,"S",100,630,"kworker/u17:1",1134
-6824713166662000,3,58000,6824713166720000,686,"S",120,686,"kworker/3:1",17791
-6824713166683000,2,227000,6824713166910000,482,"S",49,482,"sugov:0",605
-6824713166720000,3,109000,6824713166829000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713166829000,3,636000,6824713167465000,0,"R",120,"[NULL]","swapper",0
-6824713166910000,2,644000,6824713167554000,739,"S",120,739,"adbd",20305
-6824713167127000,1,100000,6824713167227000,630,"S",100,630,"kworker/u17:1",1134
-6824713167227000,1,42000,6824713167269000,0,"R",120,"[NULL]","swapper",0
-6824713167269000,1,51000,6824713167320000,630,"S",100,630,"kworker/u17:1",1134
-6824713167320000,1,35000,6824713167355000,0,"R",120,"[NULL]","swapper",0
-6824713167355000,1,100000,6824713167455000,630,"S",100,630,"kworker/u17:1",1134
-6824713167455000,1,63000,6824713167518000,693,"S",120,693,"kworker/1:1",18800
-6824713167465000,3,195000,6824713167660000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713167518000,1,54000,6824713167572000,630,"S",100,630,"kworker/u17:1",1134
-6824713167554000,2,634000,6824713168188000,0,"R",120,"[NULL]","swapper",0
-6824713167572000,1,42000,6824713167614000,0,"R",120,"[NULL]","swapper",0
-6824713167614000,1,71000,6824713167685000,630,"S",100,630,"kworker/u17:1",1134
-6824713167660000,3,456000,6824713168116000,0,"R",120,"[NULL]","swapper",0
-6824713167685000,1,45000,6824713167730000,0,"R",120,"[NULL]","swapper",0
-6824713167730000,1,100000,6824713167830000,630,"S",100,630,"kworker/u17:1",1134
-6824713167830000,1,52000,6824713167882000,693,"R",120,693,"kworker/1:1",18800
-6824713167882000,1,132000,6824713168014000,482,"S",49,482,"sugov:0",605
-6824713168014000,1,125000,6824713168139000,693,"S",120,693,"kworker/1:1",18800
-6824713168116000,3,145000,6824713168261000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713168139000,1,2254000,6824713170393000,0,"R",120,"[NULL]","swapper",0
-6824713168188000,2,118000,6824713168306000,739,"S",120,739,"adbd",20305
-6824713168261000,3,1720000,6824713169981000,0,"R",120,"[NULL]","swapper",0
-6824713168306000,2,8737000,6824713177043000,0,"R",120,"[NULL]","swapper",0
-6824713169981000,3,63000,6824713170044000,5,"S",120,5,"rcu_preempt",7
-6824713170044000,3,912000,6824713170956000,0,"R",120,"[NULL]","swapper",0
-6824713170393000,1,203000,6824713170596000,8,"S",120,8,"rcuop/0",10
-6824713170596000,1,7765000,6824713178361000,0,"R",120,"[NULL]","swapper",0
-6824713170956000,3,31000,6824713170987000,5,"S",120,5,"rcu_preempt",7
-6824713170987000,3,6024000,6824713177011000,0,"R",120,"[NULL]","swapper",0
-6824713177011000,3,31000,6824713177042000,5,"S",120,5,"rcu_preempt",7
-6824713177042000,3,653000,6824713177695000,0,"R",120,"[NULL]","swapper",0
-6824713177043000,2,352000,6824713177395000,702,"D",120,702,"kworker/u16:7",19422
-6824713177395000,2,498000,6824713177893000,0,"R",120,"[NULL]","swapper",0
-6824713177695000,3,144000,6824713177839000,77,"S",120,77,"smem_native_rpm",87
-6824713177839000,3,5798000,6824713183637000,0,"R",120,"[NULL]","swapper",0
-6824713177893000,2,35000,6824713177928000,702,"S",120,702,"kworker/u16:7",19422
-6824713177928000,2,920000,6824713178848000,0,"R",120,"[NULL]","swapper",0
-6824713178361000,1,204000,6824713178565000,2728,"S",120,739,"shell",20461
-6824713178565000,1,1277000,6824713179842000,0,"R",120,"[NULL]","swapper",0
-6824713178848000,2,801000,6824713179649000,739,"S",120,739,"adbd",20305
-6824713179649000,2,622000,6824713180271000,0,"R",120,"[NULL]","swapper",0
-6824713179842000,1,126000,6824713179968000,630,"S",100,630,"kworker/u17:1",1134
-6824713179968000,1,67000,6824713180035000,693,"S",120,693,"kworker/1:1",18800
-6824713180035000,1,535000,6824713180570000,0,"R",120,"[NULL]","swapper",0
-6824713180271000,2,74000,6824713180345000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713180345000,2,438000,6824713180783000,0,"R",120,"[NULL]","swapper",0
-6824713180570000,1,46000,6824713180616000,630,"S",100,630,"kworker/u17:1",1134
-6824713180616000,1,116000,6824713180732000,0,"R",120,"[NULL]","swapper",0
-6824713180732000,1,31000,6824713180763000,630,"S",100,630,"kworker/u17:1",1134
-6824713180763000,1,28000,6824713180791000,693,"S",120,693,"kworker/1:1",18800
-6824713180783000,2,71000,6824713180854000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713180791000,1,34000,6824713180825000,0,"R",120,"[NULL]","swapper",0
-6824713180825000,1,17000,6824713180842000,630,"S",100,630,"kworker/u17:1",1134
-6824713180842000,1,170000,6824713181012000,0,"R",120,"[NULL]","swapper",0
-6824713180854000,2,1030000,6824713181884000,0,"R",120,"[NULL]","swapper",0
-6824713181012000,1,44000,6824713181056000,630,"S",100,630,"kworker/u17:1",1134
-6824713181056000,1,406000,6824713181462000,0,"R",120,"[NULL]","swapper",0
-6824713181462000,1,39000,6824713181501000,630,"S",100,630,"kworker/u17:1",1134
-6824713181501000,1,44000,6824713181545000,693,"S",120,693,"kworker/1:1",18800
-6824713181545000,1,414000,6824713181959000,0,"R",120,"[NULL]","swapper",0
-6824713181884000,2,150000,6824713182034000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713181959000,1,179000,6824713182138000,739,"S",120,739,"adbd",20305
-6824713182034000,2,6995000,6824713189029000,0,"R",120,"[NULL]","swapper",0
-6824713182138000,1,1920000,6824713184058000,0,"R",120,"[NULL]","swapper",0
-6824713183637000,3,58000,6824713183695000,5,"S",120,5,"rcu_preempt",7
-6824713183695000,3,1423000,6824713185118000,0,"R",120,"[NULL]","swapper",0
-6824713184058000,1,700000,6824713184758000,8,"S",120,8,"rcuop/0",10
-6824713184758000,1,3775000,6824713188533000,0,"R",120,"[NULL]","swapper",0
-6824713185118000,3,22000,6824713185140000,5,"S",120,5,"rcu_preempt",7
-6824713185140000,3,5295000,6824713190435000,0,"R",120,"[NULL]","swapper",0
-6824713188533000,1,169000,6824713188702000,2728,"S",120,739,"shell",20461
-6824713188702000,1,1106000,6824713189808000,0,"R",120,"[NULL]","swapper",0
-6824713189029000,2,560000,6824713189589000,739,"S",120,739,"adbd",20305
-6824713189589000,2,668000,6824713190257000,0,"R",120,"[NULL]","swapper",0
-6824713189808000,1,118000,6824713189926000,630,"S",100,630,"kworker/u17:1",1134
-6824713189926000,1,53000,6824713189979000,693,"S",120,693,"kworker/1:1",18800
-6824713189979000,1,588000,6824713190567000,0,"R",120,"[NULL]","swapper",0
-6824713190257000,2,67000,6824713190324000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713190324000,2,156000,6824713190480000,0,"R",120,"[NULL]","swapper",0
-6824713190435000,3,53000,6824713190488000,5,"S",120,5,"rcu_preempt",7
-6824713190480000,2,615000,6824713191095000,8,"S",120,8,"rcuop/0",10
-6824713190488000,3,904000,6824713191392000,0,"R",120,"[NULL]","swapper",0
-6824713190567000,1,41000,6824713190608000,630,"S",100,630,"kworker/u17:1",1134
-6824713190608000,1,445000,6824713191053000,0,"R",120,"[NULL]","swapper",0
-6824713191053000,1,39000,6824713191092000,630,"S",100,630,"kworker/u17:1",1134
-6824713191092000,1,23000,6824713191115000,693,"R+",120,693,"kworker/1:1",18800
-6824713191095000,2,22000,6824713191117000,0,"R",120,"[NULL]","swapper",0
-6824713191115000,1,33000,6824713191148000,630,"S",100,630,"kworker/u17:1",1134
-6824713191117000,2,95000,6824713191212000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713191148000,1,15000,6824713191163000,693,"S",120,693,"kworker/1:1",18800
-6824713191163000,1,41000,6824713191204000,0,"R",120,"[NULL]","swapper",0
-6824713191204000,1,40000,6824713191244000,630,"S",100,630,"kworker/u17:1",1134
-6824713191212000,2,58000,6824713191270000,0,"R",120,"[NULL]","swapper",0
-6824713191244000,1,41000,6824713191285000,693,"S",120,693,"kworker/1:1",18800
-6824713191270000,2,141000,6824713191411000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713191285000,1,50000,6824713191335000,0,"R",120,"[NULL]","swapper",0
-6824713191335000,1,184000,6824713191519000,739,"S",120,739,"adbd",20305
-6824713191392000,3,26000,6824713191418000,5,"S",120,5,"rcu_preempt",7
-6824713191411000,2,3384000,6824713194795000,0,"R",120,"[NULL]","swapper",0
-6824713191418000,3,4124000,6824713195542000,0,"R",120,"[NULL]","swapper",0
-6824713191519000,1,2312000,6824713193831000,0,"R",120,"[NULL]","swapper",0
-6824713193444000,0,76000,6824713193520000,743,"S",120,743,"kworker/0:5",20371
-6824713193520000,0,3109000,6824713196629000,2722,"R+",120,757,"ps",20463
-6824713193831000,1,657000,6824713194488000,786,"S",111,494,"SDM_EventThread",685
-6824713194488000,1,600000,6824713195088000,0,"R",120,"[NULL]","swapper",0
-6824713194795000,2,411000,6824713195206000,777,"S",120,493,"HwBinder:640_1",721
-6824713195088000,1,141000,6824713195229000,771,"S",97,493,"DispSync",676
-6824713195206000,2,990000,6824713196196000,0,"R",120,"[NULL]","swapper",0
-6824713195229000,1,889000,6824713196118000,0,"R",120,"[NULL]","swapper",0
-6824713195542000,3,272000,6824713195814000,773,"S",97,493,"app",678
-6824713195814000,3,811000,6824713196625000,0,"R",120,"[NULL]","swapper",0
-6824713196118000,1,2042000,6824713198160000,644,"S",120,644,"ndroid.systemui",1664
-6824713196196000,2,19000,6824713196215000,771,"S",97,493,"DispSync",676
-6824713196215000,2,3119000,6824713199334000,0,"R",120,"[NULL]","swapper",0
-6824713196625000,3,44000,6824713196669000,5,"S",120,5,"rcu_preempt",7
-6824713196629000,0,168000,6824713196797000,482,"S",49,482,"sugov:0",605
-6824713196669000,3,1654000,6824713198323000,0,"R",120,"[NULL]","swapper",0
-6824713196797000,0,30115000,6824713226912000,2722,"R+",120,757,"ps",20463
-6824713198160000,1,730000,6824713198890000,0,"R",120,"[NULL]","swapper",0
-6824713198323000,3,309000,6824713198632000,770,"S",120,493,"Binder:640_2",675
-6824713198632000,3,5040000,6824713203672000,0,"R",120,"[NULL]","swapper",0
-6824713198890000,1,161000,6824713199051000,773,"S",97,493,"app",678
-6824713199051000,1,29000,6824713199080000,0,"R",120,"[NULL]","swapper",0
-6824713199080000,1,118000,6824713199198000,482,"S",49,482,"sugov:0",605
-6824713199198000,1,5504000,6824713204702000,0,"R",120,"[NULL]","swapper",0
-6824713199334000,2,29000,6824713199363000,771,"S",97,493,"DispSync",676
-6824713199363000,2,4705000,6824713204068000,0,"R",120,"[NULL]","swapper",0
-6824713203672000,3,74000,6824713203746000,5,"S",120,5,"rcu_preempt",7
-6824713203746000,3,1079000,6824713204825000,0,"R",120,"[NULL]","swapper",0
-6824713204068000,2,436000,6824713204504000,8,"S",120,8,"rcuop/0",10
-6824713204504000,2,743000,6824713205247000,0,"R",120,"[NULL]","swapper",0
-6824713204702000,1,215000,6824713204917000,2728,"S",120,739,"shell",20461
-6824713204825000,3,28000,6824713204853000,5,"S",120,5,"rcu_preempt",7
-6824713204853000,3,1654000,6824713206507000,0,"R",120,"[NULL]","swapper",0
-6824713204917000,1,1067000,6824713205984000,0,"R",120,"[NULL]","swapper",0
-6824713205247000,2,966000,6824713206213000,739,"S",120,739,"adbd",20305
-6824713205984000,1,70000,6824713206054000,630,"S",100,630,"kworker/u17:1",1134
-6824713206054000,1,9000,6824713206063000,0,"R",120,"[NULL]","swapper",0
-6824713206063000,1,59000,6824713206122000,630,"S",100,630,"kworker/u17:1",1134
-6824713206122000,1,57000,6824713206179000,693,"S",120,693,"kworker/1:1",18800
-6824713206179000,1,100000,6824713206279000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713206213000,2,904000,6824713207117000,0,"R",120,"[NULL]","swapper",0
-6824713206279000,1,1131000,6824713207410000,0,"R",120,"[NULL]","swapper",0
-6824713206507000,3,43000,6824713206550000,630,"S",100,630,"kworker/u17:1",1134
-6824713206550000,3,436000,6824713206986000,0,"R",120,"[NULL]","swapper",0
-6824713206986000,3,67000,6824713207053000,630,"S",100,630,"kworker/u17:1",1134
-6824713207053000,3,47000,6824713207100000,686,"S",120,686,"kworker/3:1",17791
-6824713207100000,3,2871000,6824713209971000,0,"R",120,"[NULL]","swapper",0
-6824713207117000,2,57000,6824713207174000,630,"S",100,630,"kworker/u17:1",1134
-6824713207174000,2,56000,6824713207230000,694,"S",120,694,"kworker/2:0",18823
-6824713207230000,2,623000,6824713207853000,0,"R",120,"[NULL]","swapper",0
-6824713207410000,1,204000,6824713207614000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713207614000,1,16701000,6824713224315000,0,"R",120,"[NULL]","swapper",0
-6824713207853000,2,179000,6824713208032000,739,"S",120,739,"adbd",20305
-6824713208032000,2,2366000,6824713210398000,0,"R",120,"[NULL]","swapper",0
-6824713209971000,3,55000,6824713210026000,5,"S",120,5,"rcu_preempt",7
-6824713210026000,3,1318000,6824713211344000,0,"R",120,"[NULL]","swapper",0
-6824713210398000,2,635000,6824713211033000,8,"S",120,8,"rcuop/0",10
-6824713211033000,2,6391000,6824713217424000,0,"R",120,"[NULL]","swapper",0
-6824713211344000,3,26000,6824713211370000,5,"S",120,5,"rcu_preempt",7
-6824713211370000,3,5656000,6824713217026000,0,"R",120,"[NULL]","swapper",0
-6824713217026000,3,51000,6824713217077000,5,"S",120,5,"rcu_preempt",7
-6824713217077000,3,770000,6824713217847000,0,"R",120,"[NULL]","swapper",0
-6824713217424000,2,75000,6824713217499000,8,"S",120,8,"rcuop/0",10
-6824713217499000,2,6882000,6824713224381000,0,"R",120,"[NULL]","swapper",0
-6824713217847000,3,19000,6824713217866000,5,"S",120,5,"rcu_preempt",7
-6824713217866000,3,6087000,6824713223953000,0,"R",120,"[NULL]","swapper",0
-6824713223953000,3,87000,6824713224040000,5,"S",120,5,"rcu_preempt",7
-6824713224040000,3,879000,6824713224919000,0,"R",120,"[NULL]","swapper",0
-6824713224315000,1,256000,6824713224571000,2728,"S",120,739,"shell",20461
-6824713224381000,2,258000,6824713224639000,8,"S",120,8,"rcuop/0",10
-6824713224571000,1,589000,6824713225160000,0,"R",120,"[NULL]","swapper",0
-6824713224639000,2,1469000,6824713226108000,0,"R",120,"[NULL]","swapper",0
-6824713224919000,3,932000,6824713225851000,739,"S",120,739,"adbd",20305
-6824713225160000,1,33000,6824713225193000,5,"S",120,5,"rcu_preempt",7
-6824713225193000,1,2096000,6824713227289000,0,"R",120,"[NULL]","swapper",0
-6824713225851000,3,755000,6824713226606000,0,"R",120,"[NULL]","swapper",0
-6824713226108000,2,128000,6824713226236000,630,"S",100,630,"kworker/u17:1",1134
-6824713226236000,2,76000,6824713226312000,694,"S",120,694,"kworker/2:0",18823
-6824713226312000,2,35000,6824713226347000,0,"R",120,"[NULL]","swapper",0
-6824713226347000,2,23000,6824713226370000,630,"S",100,630,"kworker/u17:1",1134
-6824713226370000,2,20000,6824713226390000,694,"S",120,694,"kworker/2:0",18823
-6824713226390000,2,562000,6824713226952000,0,"R",120,"[NULL]","swapper",0
-6824713226606000,3,144000,6824713226750000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713226750000,3,199000,6824713226949000,0,"R",120,"[NULL]","swapper",0
-6824713226912000,0,65000,6824713226977000,743,"S",120,743,"kworker/0:5",20371
-6824713226949000,3,43000,6824713226992000,630,"S",100,630,"kworker/u17:1",1134
-6824713226952000,2,113000,6824713227065000,702,"S",120,702,"kworker/u16:7",19422
-6824713226977000,0,23808000,6824713250785000,2722,"R",120,757,"ps",20463
-6824713226992000,3,43000,6824713227035000,0,"R",120,"[NULL]","swapper",0
-6824713227035000,3,61000,6824713227096000,630,"S",100,630,"kworker/u17:1",1134
-6824713227065000,2,78000,6824713227143000,0,"R",120,"[NULL]","swapper",0
-6824713227096000,3,66000,6824713227162000,686,"S",120,686,"kworker/3:1",17791
-6824713227143000,2,162000,6824713227305000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713227162000,3,446000,6824713227608000,0,"R",120,"[NULL]","swapper",0
-6824713227289000,1,566000,6824713227855000,786,"S",111,494,"SDM_EventThread",685
-6824713227305000,2,440000,6824713227745000,0,"R",120,"[NULL]","swapper",0
-6824713227608000,3,224000,6824713227832000,739,"S",120,739,"adbd",20305
-6824713227745000,2,443000,6824713228188000,777,"S",120,493,"HwBinder:640_1",721
-6824713227832000,3,1635000,6824713229467000,0,"R",120,"[NULL]","swapper",0
-6824713227855000,1,548000,6824713228403000,0,"R",120,"[NULL]","swapper",0
-6824713228188000,2,681000,6824713228869000,0,"R",120,"[NULL]","swapper",0
-6824713228403000,1,135000,6824713228538000,771,"S",97,493,"DispSync",676
-6824713228538000,1,565000,6824713229103000,0,"R",120,"[NULL]","swapper",0
-6824713228869000,2,274000,6824713229143000,773,"S",97,493,"app",678
-6824713229103000,1,1753000,6824713230856000,644,"S",120,644,"ndroid.systemui",1664
-6824713229143000,2,1167000,6824713230310000,0,"R",120,"[NULL]","swapper",0
-6824713229467000,3,23000,6824713229490000,771,"S",97,493,"DispSync",676
-6824713229490000,3,1513000,6824713231003000,0,"R",120,"[NULL]","swapper",0
-6824713230310000,2,45000,6824713230355000,5,"S",120,5,"rcu_preempt",7
-6824713230355000,2,1542000,6824713231897000,0,"R",120,"[NULL]","swapper",0
-6824713230856000,1,642000,6824713231498000,0,"R",120,"[NULL]","swapper",0
-6824713231003000,3,258000,6824713231261000,770,"S",120,493,"Binder:640_2",675
-6824713231261000,3,5466000,6824713236727000,0,"R",120,"[NULL]","swapper",0
-6824713231498000,1,138000,6824713231636000,773,"S",97,493,"app",678
-6824713231636000,1,6415000,6824713238051000,0,"R",120,"[NULL]","swapper",0
-6824713231897000,2,28000,6824713231925000,771,"S",97,493,"DispSync",676
-6824713231925000,2,4745000,6824713236670000,0,"R",120,"[NULL]","swapper",0
-6824713236670000,2,70000,6824713236740000,5,"S",120,5,"rcu_preempt",7
-6824713236727000,3,267000,6824713236994000,8,"S",120,8,"rcuop/0",10
-6824713236740000,2,246000,6824713236986000,0,"R",120,"[NULL]","swapper",0
-6824713236986000,2,17000,6824713237003000,5,"S",120,5,"rcu_preempt",7
-6824713236994000,3,1550000,6824713238544000,0,"R",120,"[NULL]","swapper",0
-6824713237003000,2,3473000,6824713240476000,0,"R",120,"[NULL]","swapper",0
-6824713238051000,1,210000,6824713238261000,2728,"S",120,739,"shell",20461
-6824713238261000,1,7678000,6824713245939000,0,"R",120,"[NULL]","swapper",0
-6824713238544000,3,824000,6824713239368000,739,"S",120,739,"adbd",20305
-6824713239368000,3,631000,6824713239999000,0,"R",120,"[NULL]","swapper",0
-6824713239999000,3,127000,6824713240126000,630,"S",100,630,"kworker/u17:1",1134
-6824713240126000,3,61000,6824713240187000,686,"S",120,686,"kworker/3:1",17791
-6824713240187000,3,594000,6824713240781000,0,"R",120,"[NULL]","swapper",0
-6824713240476000,2,102000,6824713240578000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713240578000,2,560000,6824713241138000,0,"R",120,"[NULL]","swapper",0
-6824713240781000,3,38000,6824713240819000,630,"S",100,630,"kworker/u17:1",1134
-6824713240819000,3,32000,6824713240851000,686,"S",120,686,"kworker/3:1",17791
-6824713240851000,3,284000,6824713241135000,0,"R",120,"[NULL]","swapper",0
-6824713241135000,3,35000,6824713241170000,630,"S",100,630,"kworker/u17:1",1134
-6824713241138000,2,73000,6824713241211000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713241170000,3,27000,6824713241197000,0,"R",120,"[NULL]","swapper",0
-6824713241197000,3,40000,6824713241237000,630,"S",100,630,"kworker/u17:1",1134
-6824713241211000,2,447000,6824713241658000,0,"R",120,"[NULL]","swapper",0
-6824713241237000,3,43000,6824713241280000,686,"S",120,686,"kworker/3:1",17791
-6824713241280000,3,763000,6824713242043000,0,"R",120,"[NULL]","swapper",0
-6824713241658000,2,183000,6824713241841000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713241841000,2,1454000,6824713243295000,0,"R",120,"[NULL]","swapper",0
-6824713242043000,3,215000,6824713242258000,739,"S",120,739,"adbd",20305
-6824713242258000,3,5163000,6824713247421000,0,"R",120,"[NULL]","swapper",0
-6824713243295000,2,43000,6824713243338000,5,"S",120,5,"rcu_preempt",7
-6824713243338000,2,3652000,6824713246990000,0,"R",120,"[NULL]","swapper",0
-6824713245939000,1,86000,6824713246025000,1807,"S",120,663,"ogle.android.as",15166
-6824713246025000,1,64000,6824713246089000,1808,"S",120,663,"ogle.android.as",15167
-6824713246089000,1,9699000,6824713255788000,0,"R",120,"[NULL]","swapper",0
-6824713246990000,2,51000,6824713247041000,5,"S",120,5,"rcu_preempt",7
-6824713247041000,2,1235000,6824713248276000,0,"R",120,"[NULL]","swapper",0
-6824713247421000,3,487000,6824713247908000,8,"S",120,8,"rcuop/0",10
-6824713247908000,3,4863000,6824713252771000,0,"R",120,"[NULL]","swapper",0
-6824713248276000,2,25000,6824713248301000,5,"S",120,5,"rcu_preempt",7
-6824713248301000,2,4882000,6824713253183000,0,"R",120,"[NULL]","swapper",0
-6824713250362000,6,413000,6824713250775000,2728,"S",120,739,"shell",20461
-6824713250775000,6,72000,6824713250847000,0,"R",120,"[NULL]","swapper",0
-6824713250785000,0,74000,6824713250859000,11,"S",0,11,"migration/0",13
-6824713250847000,6,2556000,6824713253403000,2722,"R",120,757,"ps",20463
-6824713250859000,0,61000,6824713250920000,0,"R",120,"[NULL]","swapper",0
-6824713250920000,0,247000,6824713251167000,482,"S",49,482,"sugov:0",605
-6824713251148000,7,902000,6824713252050000,739,"S",120,739,"adbd",20305
-6824713251167000,0,342000,6824713251509000,0,"R",120,"[NULL]","swapper",0
-6824713251509000,0,58000,6824713251567000,52,"S",120,52,"rcuop/6",60
-6824713251567000,0,7123000,6824713258690000,0,"R",120,"[NULL]","swapper",0
-6824713252050000,7,3110000,6824713255160000,0,"R",120,"[NULL]","swapper",0
-6824713252771000,3,197000,6824713252968000,630,"S",100,630,"kworker/u17:1",1134
-6824713252968000,3,186000,6824713253154000,686,"S",120,686,"kworker/3:1",17791
-6824713253154000,3,188000,6824713253342000,630,"S",100,630,"kworker/u17:1",1134
-6824713253183000,2,568000,6824713253751000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713253342000,3,68000,6824713253410000,686,"S",120,686,"kworker/3:1",17791
-6824713253403000,6,156000,6824713253559000,483,"S",49,483,"sugov:4",606
-6824713253410000,3,69000,6824713253479000,630,"S",100,630,"kworker/u17:1",1134
-6824713253479000,3,642000,6824713254121000,0,"R",120,"[NULL]","swapper",0
-6824713253559000,6,223000,6824713253782000,2722,"R+",120,757,"ps",20463
-6824713253751000,2,72000,6824713253823000,5,"S",120,5,"rcu_preempt",7
-6824713253782000,6,16000,6824713253798000,2728,"S",120,739,"shell",20461
-6824713253798000,6,1208000,6824713255006000,2722,"I",120,757,"ps",20463
-6824713253823000,2,1690000,6824713255513000,0,"R",120,"[NULL]","swapper",0
-6824713254121000,3,94000,6824713254215000,630,"S",100,630,"kworker/u17:1",1134
-6824713254215000,3,534000,6824713254749000,0,"R",120,"[NULL]","swapper",0
-6824713254749000,3,113000,6824713254862000,630,"S",100,630,"kworker/u17:1",1134
-6824713254862000,3,213000,6824713255075000,686,"S",120,686,"kworker/3:1",17791
-6824713255006000,6,74037000,6824713329043000,0,"R",120,"[NULL]","swapper",0
-6824713255075000,3,5496000,6824713260571000,0,"R",120,"[NULL]","swapper",0
-6824713255160000,7,39000,6824713255199000,53,"S",120,53,"rcuos/6",61
-6824713255199000,7,23000,6824713255222000,6,"S",120,6,"rcu_sched",8
-6824713255222000,7,6211000,6824713261433000,0,"R",120,"[NULL]","swapper",0
-6824713255513000,2,403000,6824713255916000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713255788000,1,140000,6824713255928000,482,"S",49,482,"sugov:0",605
-6824713255916000,2,1029000,6824713256945000,739,"R",120,739,"adbd",20305
-6824713255928000,1,733000,6824713256661000,2721,"R+",120,756,"sh",20462
-6824713256661000,1,87000,6824713256748000,482,"S",49,482,"sugov:0",605
-6824713256748000,1,2388000,6824713259136000,2721,"S",120,756,"sh",20462
-6824713256945000,2,173000,6824713257118000,630,"S",100,630,"kworker/u17:1",1134
-6824713257118000,2,59000,6824713257177000,694,"R+",120,694,"kworker/2:0",18823
-6824713257177000,2,41000,6824713257218000,630,"S",100,630,"kworker/u17:1",1134
-6824713257218000,2,23000,6824713257241000,670,"S",100,670,"kworker/u17:2",14944
-6824713257241000,2,60000,6824713257301000,694,"R+",120,694,"kworker/2:0",18823
-6824713257301000,2,26000,6824713257327000,670,"S",100,670,"kworker/u17:2",14944
-6824713257327000,2,72000,6824713257399000,694,"S",120,694,"kworker/2:0",18823
-6824713257399000,2,76000,6824713257475000,2487,"R",120,739,"UsbFfs-worker",20308
-6824713257475000,2,44000,6824713257519000,670,"S",100,670,"kworker/u17:2",14944
-6824713257519000,2,62000,6824713257581000,2487,"R",120,739,"UsbFfs-worker",20308
-6824713257581000,2,65000,6824713257646000,670,"S",100,670,"kworker/u17:2",14944
-6824713257646000,2,44000,6824713257690000,694,"S",120,694,"kworker/2:0",18823
-6824713257690000,2,127000,6824713257817000,739,"S",120,739,"adbd",20305
-6824713257817000,2,122000,6824713257939000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713257939000,2,73000,6824713258012000,482,"S",49,482,"sugov:0",605
-6824713258012000,2,131000,6824713258143000,739,"S",120,739,"adbd",20305
-6824713258143000,2,148000,6824713258291000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713258291000,2,1744000,6824713260035000,0,"R",120,"[NULL]","swapper",0
-6824713258690000,0,164000,6824713258854000,739,"S",120,739,"adbd",20305
-6824713258854000,0,1935000,6824713260789000,0,"R",120,"[NULL]","swapper",0
-6824713259136000,1,895000,6824713260031000,2729,"R+",120,758,"ps",20464
-6824713260031000,1,69000,6824713260100000,693,"S",120,693,"kworker/1:1",18800
-6824713260035000,2,103000,6824713260138000,5,"S",120,5,"rcu_preempt",7
-6824713260100000,1,747000,6824713260847000,2729,"R+",120,758,"ps",20464
-6824713260138000,2,1298000,6824713261436000,0,"R",120,"[NULL]","swapper",0
-6824713260571000,3,513000,6824713261084000,8,"S",120,8,"rcuop/0",10
-6824713260789000,0,106000,6824713260895000,743,"S",120,743,"kworker/0:5",20371
-6824713260847000,1,692000,6824713261539000,786,"S",111,494,"SDM_EventThread",685
-6824713260895000,0,931000,6824713261826000,0,"R",120,"[NULL]","swapper",0
-6824713261084000,3,994000,6824713262078000,0,"R",120,"[NULL]","swapper",0
-6824713261433000,7,52000,6824713261485000,6,"S",120,6,"rcu_sched",8
-6824713261436000,2,254000,6824713261690000,771,"S",97,493,"DispSync",676
-6824713261485000,7,50000,6824713261535000,53,"S",120,53,"rcuos/6",61
-6824713261535000,7,2709000,6824713264244000,0,"R",120,"[NULL]","swapper",0
-6824713261539000,1,1177000,6824713262716000,2729,"R+",120,758,"ps",20464
-6824713261690000,2,748000,6824713262438000,0,"R",120,"[NULL]","swapper",0
-6824713261826000,0,412000,6824713262238000,777,"S",120,493,"HwBinder:640_1",721
-6824713262078000,3,319000,6824713262397000,773,"S",97,493,"app",678
-6824713262238000,0,529000,6824713262767000,0,"R",120,"[NULL]","swapper",0
-6824713262397000,3,11856000,6824713274253000,0,"R",120,"[NULL]","swapper",0
-6824713262438000,2,46000,6824713262484000,771,"S",97,493,"DispSync",676
-6824713262484000,2,2645000,6824713265129000,0,"R",120,"[NULL]","swapper",0
-6824713262716000,1,92000,6824713262808000,9,"S",120,9,"rcuos/0",11
-6824713262767000,0,2217000,6824713264984000,644,"S",120,644,"ndroid.systemui",1664
-6824713262808000,1,549000,6824713263357000,2729,"R+",120,758,"ps",20464
-6824713263357000,1,1008000,6824713264365000,702,"S",120,702,"kworker/u16:7",19422
-6824713264244000,7,55000,6824713264299000,6,"S",120,6,"rcu_sched",8
-6824713264299000,7,7113000,6824713271412000,0,"R",120,"[NULL]","swapper",0
-6824713264365000,1,230000,6824713264595000,2729,"R+",120,758,"ps",20464
-6824713264595000,1,23000,6824713264618000,145,"S",120,145,"hwrng",215
-6824713264618000,1,6871000,6824713271489000,2729,"R+",120,758,"ps",20464
-6824713264984000,0,719000,6824713265703000,0,"R",120,"[NULL]","swapper",0
-6824713265129000,2,305000,6824713265434000,770,"S",120,493,"Binder:640_2",675
-6824713265434000,2,29000,6824713265463000,145,"S",120,145,"hwrng",215
-6824713265463000,2,364000,6824713265827000,0,"R",120,"[NULL]","swapper",0
-6824713265703000,0,185000,6824713265888000,773,"S",97,493,"app",678
-6824713265827000,2,52000,6824713265879000,771,"S",97,493,"DispSync",676
-6824713265879000,2,818000,6824713266697000,0,"R",120,"[NULL]","swapper",0
-6824713265888000,0,23236000,6824713289124000,0,"R",120,"[NULL]","swapper",0
-6824713266697000,2,86000,6824713266783000,5,"R+",120,5,"rcu_preempt",7
-6824713266783000,2,33000,6824713266816000,52,"S",120,52,"rcuop/6",60
-6824713266816000,2,36000,6824713266852000,5,"S",120,5,"rcu_preempt",7
-6824713266852000,2,6898000,6824713273750000,0,"R",120,"[NULL]","swapper",0
-6824713271412000,7,52000,6824713271464000,6,"S",120,6,"rcu_sched",8
-6824713271464000,7,1149000,6824713272613000,0,"R",120,"[NULL]","swapper",0
-6824713271489000,1,125000,6824713271614000,9,"S",120,9,"rcuos/0",11
-6824713271614000,1,43000,6824713271657000,18,"S",120,18,"rcuos/1",21
-6824713271657000,1,2660000,6824713274317000,2729,"R+",120,758,"ps",20464
-6824713272613000,7,50000,6824713272663000,6,"S",120,6,"rcu_sched",8
-6824713272663000,7,4324000,6824713276987000,0,"R",120,"[NULL]","swapper",0
-6824713273750000,2,109000,6824713273859000,5,"R+",120,5,"rcu_preempt",7
-6824713273859000,2,152000,6824713274011000,52,"S",120,52,"rcuop/6",60
-6824713274011000,2,24000,6824713274035000,24,"S",120,24,"rcuop/2",28
-6824713274035000,2,26000,6824713274061000,5,"S",120,5,"rcu_preempt",7
-6824713274061000,2,6571000,6824713280632000,0,"R",120,"[NULL]","swapper",0
-6824713274253000,3,160000,6824713274413000,8,"S",120,8,"rcuop/0",10
-6824713274317000,1,223000,6824713274540000,17,"S",120,17,"rcuop/1",20
-6824713274413000,3,13234000,6824713287647000,0,"R",120,"[NULL]","swapper",0
-6824713274540000,1,2103000,6824713276643000,2729,"R+",120,758,"ps",20464
-6824713276643000,1,103000,6824713276746000,702,"S",120,702,"kworker/u16:7",19422
-6824713276746000,1,294000,6824713277040000,2729,"R+",120,758,"ps",20464
-6824713276987000,7,34000,6824713277021000,6,"S",120,6,"rcu_sched",8
-6824713277021000,7,53046000,6824713330067000,0,"R",120,"[NULL]","swapper",0
-6824713277040000,1,41000,6824713277081000,9,"S",120,9,"rcuos/0",11
-6824713277081000,1,23000,6824713277104000,18,"S",120,18,"rcuos/1",21
-6824713277104000,1,2914000,6824713280018000,2729,"R+",120,758,"ps",20464
-6824713280018000,1,235000,6824713280253000,482,"S",49,482,"sugov:0",605
-6824713280253000,1,7441000,6824713287694000,2729,"R",120,758,"ps",20464
-6824713280632000,2,120000,6824713280752000,482,"S",49,482,"sugov:0",605
-6824713280752000,2,55000,6824713280807000,5,"R+",120,5,"rcu_preempt",7
-6824713280807000,2,27000,6824713280834000,24,"S",120,24,"rcuop/2",28
-6824713280834000,2,20000,6824713280854000,5,"S",120,5,"rcu_preempt",7
-6824713280854000,2,6307000,6824713287161000,0,"R",120,"[NULL]","swapper",0
-6824713287161000,2,80000,6824713287241000,5,"S",120,5,"rcu_preempt",7
-6824713287241000,2,805000,6824713288046000,0,"R",120,"[NULL]","swapper",0
-6824713287647000,3,85000,6824713287732000,8,"S",120,8,"rcuop/0",10
-6824713287694000,1,49000,6824713287743000,17,"S",120,17,"rcuop/1",20
-6824713287732000,3,6253000,6824713293985000,0,"R",120,"[NULL]","swapper",0
-6824713287743000,1,6273000,6824713294016000,2729,"R+",120,758,"ps",20464
-6824713288046000,2,19000,6824713288065000,5,"S",120,5,"rcu_preempt",7
-6824713288065000,2,5544000,6824713293609000,0,"R",120,"[NULL]","swapper",0
-6824713289124000,0,238000,6824713289362000,1694,"D",100,660,"thermal-engine",2490
-6824713289362000,0,803000,6824713290165000,0,"R",120,"[NULL]","swapper",0
-6824713290165000,0,67000,6824713290232000,743,"S",120,743,"kworker/0:5",20371
-6824713290232000,0,256000,6824713290488000,1694,"S",100,660,"thermal-engine",2490
-6824713290488000,0,3702000,6824713294190000,0,"R",120,"[NULL]","swapper",0
-6824713293609000,2,45000,6824713293654000,5,"S",120,5,"rcu_preempt",7
-6824713293654000,2,1390000,6824713295044000,0,"R",120,"[NULL]","swapper",0
-6824713293985000,3,43000,6824713294028000,8,"S",120,8,"rcuop/0",10
-6824713294016000,1,29000,6824713294045000,17,"S",120,17,"rcuop/1",20
-6824713294028000,3,1525000,6824713295553000,0,"R",120,"[NULL]","swapper",0
-6824713294045000,1,182000,6824713294227000,2729,"R",120,758,"ps",20464
-6824713294190000,0,70000,6824713294260000,743,"S",120,743,"kworker/0:5",20371
-6824713294227000,1,650000,6824713294877000,786,"S",111,494,"SDM_EventThread",685
-6824713294260000,0,501000,6824713294761000,0,"R",120,"[NULL]","swapper",0
-6824713294761000,0,350000,6824713295111000,777,"S",120,493,"HwBinder:640_1",721
-6824713294877000,1,8453000,6824713303330000,2729,"R+",120,758,"ps",20464
-6824713295044000,2,186000,6824713295230000,771,"S",97,493,"DispSync",676
-6824713295111000,0,16000,6824713295127000,0,"R",120,"[NULL]","swapper",0
-6824713295127000,0,113000,6824713295240000,777,"S",120,493,"HwBinder:640_1",721
-6824713295230000,2,1013000,6824713296243000,0,"R",120,"[NULL]","swapper",0
-6824713295240000,0,922000,6824713296162000,0,"R",120,"[NULL]","swapper",0
-6824713295553000,3,326000,6824713295879000,773,"S",97,493,"app",678
-6824713295879000,3,4297000,6824713300176000,0,"R",120,"[NULL]","swapper",0
-6824713296162000,0,1958000,6824713298120000,644,"S",120,644,"ndroid.systemui",1664
-6824713296243000,2,31000,6824713296274000,771,"S",97,493,"DispSync",676
-6824713296274000,2,1983000,6824713298257000,0,"R",120,"[NULL]","swapper",0
-6824713298120000,0,672000,6824713298792000,0,"R",120,"[NULL]","swapper",0
-6824713298257000,2,260000,6824713298517000,770,"S",120,493,"Binder:640_2",675
-6824713298517000,2,708000,6824713299225000,0,"R",120,"[NULL]","swapper",0
-6824713298792000,0,153000,6824713298945000,773,"S",97,493,"app",678
-6824713298945000,0,25615000,6824713324560000,0,"R",120,"[NULL]","swapper",0
-6824713299225000,2,37000,6824713299262000,771,"S",97,493,"DispSync",676
-6824713299262000,2,1065000,6824713300327000,0,"R",120,"[NULL]","swapper",0
-6824713300176000,3,48000,6824713300224000,8,"S",120,8,"rcuop/0",10
-6824713300224000,3,7418000,6824713307642000,0,"R",120,"[NULL]","swapper",0
-6824713300327000,2,21000,6824713300348000,145,"S",120,145,"hwrng",215
-6824713300348000,2,36000,6824713300384000,5,"S",120,5,"rcu_preempt",7
-6824713300384000,2,6852000,6824713307236000,0,"R",120,"[NULL]","swapper",0
-6824713303330000,1,176000,6824713303506000,482,"S",49,482,"sugov:0",605
-6824713303506000,1,3115000,6824713306621000,2729,"R+",120,758,"ps",20464
-6824713306621000,1,71000,6824713306692000,482,"S",49,482,"sugov:0",605
-6824713306692000,1,994000,6824713307686000,2729,"R+",120,758,"ps",20464
-6824713307236000,2,69000,6824713307305000,5,"S",120,5,"rcu_preempt",7
-6824713307305000,2,404000,6824713307709000,0,"R",120,"[NULL]","swapper",0
-6824713307642000,3,72000,6824713307714000,8,"S",120,8,"rcuop/0",10
-6824713307686000,1,32000,6824713307718000,17,"S",120,17,"rcuop/1",20
-6824713307709000,2,17000,6824713307726000,5,"S",120,5,"rcu_preempt",7
-6824713307714000,3,9638000,6824713317352000,0,"R",120,"[NULL]","swapper",0
-6824713307718000,1,9664000,6824713317382000,2729,"R+",120,758,"ps",20464
-6824713307726000,2,5944000,6824713313670000,0,"R",120,"[NULL]","swapper",0
-6824713313670000,2,31000,6824713313701000,5,"S",120,5,"rcu_preempt",7
-6824713313701000,2,3234000,6824713316935000,0,"R",120,"[NULL]","swapper",0
-6824713316935000,2,46000,6824713316981000,5,"S",120,5,"rcu_preempt",7
-6824713316981000,2,773000,6824713317754000,0,"R",120,"[NULL]","swapper",0
-6824713317352000,3,56000,6824713317408000,8,"S",120,8,"rcuop/0",10
-6824713317382000,1,116000,6824713317498000,17,"S",120,17,"rcuop/1",20
-6824713317408000,3,6640000,6824713324048000,0,"R",120,"[NULL]","swapper",0
-6824713317498000,1,5825000,6824713323323000,2729,"R+",120,758,"ps",20464
-6824713317754000,2,15000,6824713317769000,5,"S",120,5,"rcu_preempt",7
-6824713317769000,2,5877000,6824713323646000,0,"R",120,"[NULL]","swapper",0
-6824713323323000,1,140000,6824713323463000,482,"S",49,482,"sugov:0",605
-6824713323463000,1,4344000,6824713327807000,2729,"R+",120,758,"ps",20464
-6824713323646000,2,54000,6824713323700000,5,"S",120,5,"rcu_preempt",7
-6824713323700000,2,893000,6824713324593000,0,"R",120,"[NULL]","swapper",0
-6824713324048000,3,59000,6824713324107000,8,"S",120,8,"rcuop/0",10
-6824713324107000,3,3572000,6824713327679000,0,"R",120,"[NULL]","swapper",0
-6824713324560000,0,209000,6824713324769000,17,"S",120,17,"rcuop/1",20
-6824713324593000,2,17000,6824713324610000,5,"S",120,5,"rcu_preempt",7
-6824713324610000,2,2330000,6824713326940000,0,"R",120,"[NULL]","swapper",0
-6824713324769000,0,2944000,6824713327713000,0,"R",120,"[NULL]","swapper",0
-6824713326940000,2,357000,6824713327297000,702,"D",120,702,"kworker/u16:7",19422
-6824713327297000,2,154000,6824713327451000,0,"R",120,"[NULL]","swapper",0
-6824713327451000,2,31000,6824713327482000,702,"S",120,702,"kworker/u16:7",19422
-6824713327482000,2,276000,6824713327758000,0,"R",120,"[NULL]","swapper",0
-6824713327679000,3,43000,6824713327722000,77,"S",120,77,"smem_native_rpm",87
-6824713327713000,0,92000,6824713327805000,743,"S",120,743,"kworker/0:5",20371
-6824713327722000,3,1218000,6824713328940000,0,"R",120,"[NULL]","swapper",0
-6824713327758000,2,602000,6824713328360000,786,"S",111,494,"SDM_EventThread",685
-6824713327805000,0,570000,6824713328375000,0,"R",120,"[NULL]","swapper",0
-6824713327807000,1,48000,6824713327855000,14,"S",0,14,"migration/1",16
-6824713327855000,1,1280000,6824713329135000,0,"R",120,"[NULL]","swapper",0
-6824713328360000,2,884000,6824713329244000,0,"R",120,"[NULL]","swapper",0
-6824713328375000,0,1267000,6824713329642000,2729,"R",120,758,"ps",20464
-6824713328940000,3,397000,6824713329337000,777,"S",120,493,"HwBinder:640_1",721
-6824713329043000,6,147000,6824713329190000,483,"S",49,483,"sugov:4",606
-6824713329135000,1,153000,6824713329288000,771,"S",97,493,"DispSync",676
-6824713329190000,6,433000,6824713329623000,2728,"S",120,739,"shell",20461
-6824713329244000,2,244000,6824713329488000,773,"S",97,493,"app",678
-6824713329288000,1,523000,6824713329811000,0,"R",120,"[NULL]","swapper",0
-6824713329337000,3,722000,6824713330059000,0,"R",120,"[NULL]","swapper",0
-6824713329488000,2,470000,6824713329958000,0,"R",120,"[NULL]","swapper",0
-6824713329623000,6,113000,6824713329736000,0,"R",120,"[NULL]","swapper",0
-6824713329642000,0,49000,6824713329691000,11,"S",0,11,"migration/0",13
-6824713329691000,0,2040000,6824713331731000,0,"R",120,"[NULL]","swapper",0
-6824713329736000,6,3595000,6824713333331000,2729,"R+",120,758,"ps",20464
-6824713329811000,1,17000,6824713329828000,771,"S",97,493,"DispSync",676
-6824713329828000,1,2390000,6824713332218000,0,"R",120,"[NULL]","swapper",0
-6824713329958000,2,20000,6824713329978000,52,"S",120,52,"rcuop/6",60
-6824713329978000,2,29000,6824713330007000,5,"S",120,5,"rcu_preempt",7
-6824713330007000,2,1145000,6824713331152000,0,"R",120,"[NULL]","swapper",0
-6824713330059000,3,1520000,6824713331579000,644,"S",120,644,"ndroid.systemui",1664
-6824713330067000,7,915000,6824713330982000,739,"S",120,739,"adbd",20305
-6824713330982000,7,71506000,6824713402488000,0,"R",120,"[NULL]","swapper",0
-6824713331152000,2,172000,6824713331324000,670,"S",100,670,"kworker/u17:2",14944
-6824713331324000,2,62000,6824713331386000,694,"S",120,694,"kworker/2:0",18823
-6824713331386000,2,66000,6824713331452000,630,"S",100,630,"kworker/u17:1",1134
-6824713331452000,2,4000,6824713331456000,670,"S",100,670,"kworker/u17:2",14944
-6824713331456000,2,12000,6824713331468000,694,"S",120,694,"kworker/2:0",18823
-6824713331468000,2,57000,6824713331525000,2487,"R",120,739,"UsbFfs-worker",20308
-6824713331525000,2,14000,6824713331539000,670,"S",100,670,"kworker/u17:2",14944
-6824713331539000,2,119000,6824713331658000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713331579000,3,5762000,6824713337341000,0,"R",120,"[NULL]","swapper",0
-6824713331658000,2,60000,6824713331718000,0,"R",120,"[NULL]","swapper",0
-6824713331718000,2,33000,6824713331751000,670,"S",100,670,"kworker/u17:2",14944
-6824713331731000,0,215000,6824713331946000,770,"S",120,493,"Binder:640_2",675
-6824713331751000,2,33000,6824713331784000,0,"R",120,"[NULL]","swapper",0
-6824713331784000,2,39000,6824713331823000,670,"S",100,670,"kworker/u17:2",14944
-6824713331823000,2,43000,6824713331866000,694,"S",120,694,"kworker/2:0",18823
-6824713331866000,2,172000,6824713332038000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713331946000,0,667000,6824713332613000,0,"R",120,"[NULL]","swapper",0
-6824713332038000,2,397000,6824713332435000,739,"S",120,739,"adbd",20305
-6824713332218000,1,104000,6824713332322000,773,"S",97,493,"app",678
-6824713332322000,1,30785000,6824713363107000,0,"R",120,"[NULL]","swapper",0
-6824713332435000,2,4516000,6824713336951000,0,"R",120,"[NULL]","swapper",0
-6824713332613000,0,24000,6824713332637000,771,"S",97,493,"DispSync",676
-6824713332637000,0,5094000,6824713337731000,0,"R",120,"[NULL]","swapper",0
-6824713333331000,6,103000,6824713333434000,483,"S",49,483,"sugov:4",606
-6824713333434000,6,9802000,6824713343236000,2729,"R+",120,758,"ps",20464
-6824713336951000,2,72000,6824713337023000,5,"S",120,5,"rcu_preempt",7
-6824713337023000,2,6609000,6824713343632000,0,"R",120,"[NULL]","swapper",0
-6824713337341000,3,53000,6824713337394000,8,"S",120,8,"rcuop/0",10
-6824713337394000,3,14884000,6824713352278000,0,"R",120,"[NULL]","swapper",0
-6824713337731000,0,167000,6824713337898000,17,"S",120,17,"rcuop/1",20
-6824713337898000,0,14895000,6824713352793000,0,"R",120,"[NULL]","swapper",0
-6824713343236000,6,17000,6824713343253000,483,"S",49,483,"sugov:4",606
-6824713343253000,6,797000,6824713344050000,2729,"R+",120,758,"ps",20464
-6824713343632000,2,147000,6824713343779000,482,"S",49,482,"sugov:0",605
-6824713343779000,2,140000,6824713343919000,5,"R+",120,5,"rcu_preempt",7
-6824713343919000,2,29000,6824713343948000,52,"S",120,52,"rcuop/6",60
-6824713343948000,2,28000,6824713343976000,5,"S",120,5,"rcu_preempt",7
-6824713343976000,2,7683000,6824713351659000,0,"R",120,"[NULL]","swapper",0
-6824713344050000,6,47000,6824713344097000,2728,"R+",120,739,"shell",20461
-6824713344097000,6,32000,6824713344129000,483,"S",49,483,"sugov:4",606
-6824713344129000,6,10000,6824713344139000,2728,"S",120,739,"shell",20461
-6824713344139000,6,5756000,6824713349895000,2729,"R+",120,758,"ps",20464
-6824713349895000,6,389000,6824713350284000,739,"S",120,739,"adbd",20305
-6824713350284000,6,1235000,6824713351519000,2729,"R+",120,758,"ps",20464
-6824713351519000,6,22000,6824713351541000,483,"S",49,483,"sugov:4",606
-6824713351541000,6,108000,6824713351649000,670,"S",100,670,"kworker/u17:2",14944
-6824713351649000,6,56000,6824713351705000,669,"S",120,669,"kworker/6:1",14833
-6824713351659000,2,259000,6824713351918000,5,"R+",120,5,"rcu_preempt",7
-6824713351705000,6,212000,6824713351917000,2729,"R+",120,758,"ps",20464
-6824713351917000,6,39000,6824713351956000,670,"S",100,670,"kworker/u17:2",14944
-6824713351918000,2,591000,6824713352509000,52,"S",120,52,"rcuop/6",60
-6824713351956000,6,11000,6824713351967000,669,"S",120,669,"kworker/6:1",14833
-6824713351967000,6,121000,6824713352088000,2729,"R",120,758,"ps",20464
-6824713352088000,6,38000,6824713352126000,670,"S",100,670,"kworker/u17:2",14944
-6824713352126000,6,58000,6824713352184000,2729,"R+",120,758,"ps",20464
-6824713352184000,6,60000,6824713352244000,670,"S",100,670,"kworker/u17:2",14944
-6824713352244000,6,24000,6824713352268000,669,"S",120,669,"kworker/6:1",14833
-6824713352268000,6,6413000,6824713358681000,2729,"R+",120,758,"ps",20464
-6824713352278000,3,219000,6824713352497000,8,"S",120,8,"rcuop/0",10
-6824713352497000,3,11953000,6824713364450000,0,"R",120,"[NULL]","swapper",0
-6824713352509000,2,289000,6824713352798000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713352793000,0,205000,6824713352998000,17,"S",120,17,"rcuop/1",20
-6824713352798000,2,418000,6824713353216000,739,"S",120,739,"adbd",20305
-6824713352998000,0,8273000,6824713361271000,0,"R",120,"[NULL]","swapper",0
-6824713353216000,2,150000,6824713353366000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713353366000,2,154000,6824713353520000,739,"S",120,739,"adbd",20305
-6824713353520000,2,163000,6824713353683000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713353683000,2,57000,6824713353740000,5,"S",120,5,"rcu_preempt",7
-6824713353740000,2,7167000,6824713360907000,0,"R",120,"[NULL]","swapper",0
-6824713358681000,6,60000,6824713358741000,2728,"S",120,739,"shell",20461
-6824713358741000,6,311000,6824713359052000,739,"S",120,739,"adbd",20305
-6824713359052000,6,875000,6824713359927000,2729,"R+",120,758,"ps",20464
-6824713359927000,6,41000,6824713359968000,669,"S",120,669,"kworker/6:1",14833
-6824713359968000,6,3312000,6824713363280000,2729,"R",120,758,"ps",20464
-6824713360907000,2,128000,6824713361035000,5,"R+",120,5,"rcu_preempt",7
-6824713361035000,2,355000,6824713361390000,52,"S",120,52,"rcuop/6",60
-6824713361271000,0,118000,6824713361389000,670,"S",100,670,"kworker/u17:2",14944
-6824713361389000,0,127000,6824713361516000,743,"R+",120,743,"kworker/0:5",20371
-6824713361390000,2,51000,6824713361441000,5,"S",120,5,"rcu_preempt",7
-6824713361441000,2,95000,6824713361536000,0,"R",120,"[NULL]","swapper",0
-6824713361516000,0,44000,6824713361560000,670,"S",100,670,"kworker/u17:2",14944
-6824713361536000,2,952000,6824713362488000,786,"S",111,494,"SDM_EventThread",685
-6824713361560000,0,61000,6824713361621000,743,"R+",120,743,"kworker/0:5",20371
-6824713361621000,0,33000,6824713361654000,670,"S",100,670,"kworker/u17:2",14944
-6824713361654000,0,67000,6824713361721000,743,"S",120,743,"kworker/0:5",20371
-6824713361721000,0,80000,6824713361801000,0,"R",120,"[NULL]","swapper",0
-6824713361801000,0,57000,6824713361858000,670,"S",100,670,"kworker/u17:2",14944
-6824713361858000,0,46000,6824713361904000,0,"R",120,"[NULL]","swapper",0
-6824713361904000,0,39000,6824713361943000,670,"S",100,670,"kworker/u17:2",14944
-6824713361943000,0,43000,6824713361986000,0,"R",120,"[NULL]","swapper",0
-6824713361986000,0,70000,6824713362056000,670,"S",100,670,"kworker/u17:2",14944
-6824713362056000,0,69000,6824713362125000,743,"S",120,743,"kworker/0:5",20371
-6824713362125000,0,232000,6824713362357000,0,"R",120,"[NULL]","swapper",0
-6824713362357000,0,537000,6824713362894000,777,"S",120,493,"HwBinder:640_1",721
-6824713362488000,2,279000,6824713362767000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713362767000,2,401000,6824713363168000,739,"S",120,739,"adbd",20305
-6824713362894000,0,738000,6824713363632000,0,"R",120,"[NULL]","swapper",0
-6824713363107000,1,274000,6824713363381000,771,"S",97,493,"DispSync",676
-6824713363168000,2,157000,6824713363325000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713363280000,6,49000,6824713363329000,483,"S",49,483,"sugov:4",606
-6824713363325000,2,157000,6824713363482000,739,"S",120,739,"adbd",20305
-6824713363329000,6,6630000,6824713369959000,2729,"R+",120,758,"ps",20464
-6824713363381000,1,919000,6824713364300000,0,"R",120,"[NULL]","swapper",0
-6824713363482000,2,776000,6824713364258000,702,"S",120,702,"kworker/u16:7",19422
-6824713363632000,0,355000,6824713363987000,773,"S",97,493,"app",678
-6824713363987000,0,2520000,6824713366507000,0,"R",120,"[NULL]","swapper",0
-6824713364258000,2,164000,6824713364422000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713364300000,1,2117000,6824713366417000,644,"S",120,644,"ndroid.systemui",1664
-6824713364422000,2,2600000,6824713367022000,0,"R",120,"[NULL]","swapper",0
-6824713364450000,3,65000,6824713364515000,771,"S",97,493,"DispSync",676
-6824713364515000,3,13500000,6824713378015000,0,"R",120,"[NULL]","swapper",0
-6824713366417000,1,380000,6824713366797000,0,"R",120,"[NULL]","swapper",0
-6824713366507000,0,360000,6824713366867000,770,"S",120,493,"Binder:640_2",675
-6824713366797000,1,143000,6824713366940000,773,"S",97,493,"app",678
-6824713366867000,0,5605000,6824713372472000,0,"R",120,"[NULL]","swapper",0
-6824713366940000,1,28138000,6824713395078000,0,"R",120,"[NULL]","swapper",0
-6824713367022000,2,33000,6824713367055000,771,"S",97,493,"DispSync",676
-6824713367055000,2,85000,6824713367140000,5,"R+",120,5,"rcu_preempt",7
-6824713367140000,2,409000,6824713367549000,52,"S",120,52,"rcuop/6",60
-6824713367549000,2,34000,6824713367583000,5,"S",120,5,"rcu_preempt",7
-6824713367583000,2,5336000,6824713372919000,0,"R",120,"[NULL]","swapper",0
-6824713369959000,6,65000,6824713370024000,2728,"R+",120,739,"shell",20461
-6824713370024000,6,36000,6824713370060000,483,"S",49,483,"sugov:4",606
-6824713370060000,6,15000,6824713370075000,2728,"S",120,739,"shell",20461
-6824713370075000,6,299000,6824713370374000,739,"S",120,739,"adbd",20305
-6824713370374000,6,10921000,6824713381295000,2729,"R+",120,758,"ps",20464
-6824713372472000,0,237000,6824713372709000,670,"R+",100,670,"kworker/u17:2",14944
-6824713372709000,0,188000,6824713372897000,482,"S",49,482,"sugov:0",605
-6824713372897000,0,74000,6824713372971000,670,"S",100,670,"kworker/u17:2",14944
-6824713372919000,2,89000,6824713373008000,630,"S",100,630,"kworker/u17:1",1134
-6824713372971000,0,177000,6824713373148000,743,"R+",120,743,"kworker/0:5",20371
-6824713373008000,2,144000,6824713373152000,0,"R",120,"[NULL]","swapper",0
-6824713373148000,0,64000,6824713373212000,670,"S",100,670,"kworker/u17:2",14944
-6824713373152000,2,734000,6824713373886000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713373212000,0,142000,6824713373354000,743,"R+",120,743,"kworker/0:5",20371
-6824713373354000,0,79000,6824713373433000,670,"S",100,670,"kworker/u17:2",14944
-6824713373433000,0,170000,6824713373603000,743,"S",120,743,"kworker/0:5",20371
-6824713373603000,0,8922000,6824713382525000,0,"R",120,"[NULL]","swapper",0
-6824713373886000,2,518000,6824713374404000,739,"S",120,739,"adbd",20305
-6824713374404000,2,168000,6824713374572000,5,"R+",120,5,"rcu_preempt",7
-6824713374572000,2,494000,6824713375066000,52,"S",120,52,"rcuop/6",60
-6824713375066000,2,44000,6824713375110000,5,"S",120,5,"rcu_preempt",7
-6824713375110000,2,127000,6824713375237000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713375237000,2,235000,6824713375472000,739,"S",120,739,"adbd",20305
-6824713375472000,2,230000,6824713375702000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713375702000,2,1343000,6824713377045000,0,"R",120,"[NULL]","swapper",0
-6824713377045000,2,741000,6824713377786000,702,"S",120,702,"kworker/u16:7",19422
-6824713377786000,2,2753000,6824713380539000,0,"R",120,"[NULL]","swapper",0
-6824713378015000,3,111000,6824713378126000,77,"S",120,77,"smem_native_rpm",87
-6824713378126000,3,5664000,6824713383790000,0,"R",120,"[NULL]","swapper",0
-6824713380539000,2,133000,6824713380672000,482,"S",49,482,"sugov:0",605
-6824713380672000,2,103000,6824713380775000,5,"R+",120,5,"rcu_preempt",7
-6824713380775000,2,390000,6824713381165000,52,"S",120,52,"rcuop/6",60
-6824713381165000,2,41000,6824713381206000,5,"R+",120,5,"rcu_preempt",7
-6824713381206000,2,75000,6824713381281000,482,"S",49,482,"sugov:0",605
-6824713381281000,2,45000,6824713381326000,5,"S",120,5,"rcu_preempt",7
-6824713381295000,6,45000,6824713381340000,483,"S",49,483,"sugov:4",606
-6824713381326000,2,1876000,6824713383202000,0,"R",120,"[NULL]","swapper",0
-6824713381340000,6,66000,6824713381406000,2728,"S",120,739,"shell",20461
-6824713381406000,6,288000,6824713381694000,739,"S",120,739,"adbd",20305
-6824713381694000,6,1546000,6824713383240000,2729,"R+",120,758,"ps",20464
-6824713382525000,0,114000,6824713382639000,670,"S",100,670,"kworker/u17:2",14944
-6824713382639000,0,173000,6824713382812000,743,"S",120,743,"kworker/0:5",20371
-6824713382812000,0,744000,6824713383556000,0,"R",120,"[NULL]","swapper",0
-6824713383202000,2,136000,6824713383338000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713383240000,6,170000,6824713383410000,483,"D",49,483,"sugov:4",606
-6824713383338000,2,443000,6824713383781000,0,"R",120,"[NULL]","swapper",0
-6824713383410000,6,5051000,6824713388461000,2729,"R+",120,758,"ps",20464
-6824713383556000,0,102000,6824713383658000,670,"S",100,670,"kworker/u17:2",14944
-6824713383658000,0,115000,6824713383773000,743,"R+",120,743,"kworker/0:5",20371
-6824713383773000,0,53000,6824713383826000,670,"S",100,670,"kworker/u17:2",14944
-6824713383781000,2,83000,6824713383864000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713383790000,3,60000,6824713383850000,77,"S",120,77,"smem_native_rpm",87
-6824713383826000,0,167000,6824713383993000,743,"S",120,743,"kworker/0:5",20371
-6824713383850000,3,11312000,6824713395162000,0,"R",120,"[NULL]","swapper",0
-6824713383864000,2,90000,6824713383954000,0,"R",120,"[NULL]","swapper",0
-6824713383954000,2,184000,6824713384138000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713383993000,0,6047000,6824713390040000,0,"R",120,"[NULL]","swapper",0
-6824713384138000,2,253000,6824713384391000,739,"S",120,739,"adbd",20305
-6824713384362000,4,24000,6824713384386000,483,"S",49,483,"sugov:4",606
-6824713384386000,4,18375000,6824713402761000,0,"R",120,"[NULL]","swapper",0
-6824713384391000,2,105000,6824713384496000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713384496000,2,149000,6824713384645000,739,"S",120,739,"adbd",20305
-6824713384645000,2,120000,6824713384765000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713384765000,2,2176000,6824713386941000,0,"R",120,"[NULL]","swapper",0
-6824713386941000,2,96000,6824713387037000,5,"R+",120,5,"rcu_preempt",7
-6824713387037000,2,340000,6824713387377000,52,"S",120,52,"rcuop/6",60
-6824713387377000,2,41000,6824713387418000,5,"S",120,5,"rcu_preempt",7
-6824713387418000,2,3209000,6824713390627000,0,"R",120,"[NULL]","swapper",0
-6824713388461000,6,29000,6824713388490000,2728,"S",120,739,"shell",20461
-6824713388490000,6,145000,6824713388635000,739,"S",120,739,"adbd",20305
-6824713388635000,6,3783000,6824713392418000,2729,"R+",120,758,"ps",20464
-6824713390040000,0,142000,6824713390182000,670,"S",100,670,"kworker/u17:2",14944
-6824713390182000,0,178000,6824713390360000,743,"S",120,743,"kworker/0:5",20371
-6824713390360000,0,476000,6824713390836000,0,"R",120,"[NULL]","swapper",0
-6824713390627000,2,119000,6824713390746000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713390746000,2,516000,6824713391262000,0,"R",120,"[NULL]","swapper",0
-6824713390836000,0,87000,6824713390923000,670,"S",100,670,"kworker/u17:2",14944
-6824713390923000,0,144000,6824713391067000,743,"S",120,743,"kworker/0:5",20371
-6824713391067000,0,424000,6824713391491000,0,"R",120,"[NULL]","swapper",0
-6824713391262000,2,94000,6824713391356000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713391356000,2,737000,6824713392093000,0,"R",120,"[NULL]","swapper",0
-6824713391491000,0,76000,6824713391567000,670,"S",100,670,"kworker/u17:2",14944
-6824713391567000,0,314000,6824713391881000,0,"R",120,"[NULL]","swapper",0
-6824713391881000,0,87000,6824713391968000,670,"S",100,670,"kworker/u17:2",14944
-6824713391968000,0,163000,6824713392131000,743,"S",120,743,"kworker/0:5",20371
-6824713392093000,2,134000,6824713392227000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713392131000,0,1225000,6824713393356000,0,"R",120,"[NULL]","swapper",0
-6824713392227000,2,294000,6824713392521000,739,"S",120,739,"adbd",20305
-6824713392418000,6,21000,6824713392439000,2728,"S",120,739,"shell",20461
-6824713392439000,6,7047000,6824713399486000,2729,"R+",120,758,"ps",20464
-6824713392521000,2,105000,6824713392626000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713392626000,2,812000,6824713393438000,739,"S",120,739,"adbd",20305
-6824713393356000,0,90000,6824713393446000,670,"S",100,670,"kworker/u17:2",14944
-6824713393438000,2,137000,6824713393575000,5,"S",120,5,"rcu_preempt",7
-6824713393446000,0,64000,6824713393510000,743,"S",120,743,"kworker/0:5",20371
-6824713393510000,0,41000,6824713393551000,0,"R",120,"[NULL]","swapper",0
-6824713393551000,0,67000,6824713393618000,670,"S",100,670,"kworker/u17:2",14944
-6824713393575000,2,258000,6824713393833000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713393618000,0,173000,6824713393791000,0,"R",120,"[NULL]","swapper",0
-6824713393791000,0,72000,6824713393863000,670,"S",100,670,"kworker/u17:2",14944
-6824713393833000,2,136000,6824713393969000,0,"R",120,"[NULL]","swapper",0
-6824713393863000,0,110000,6824713393973000,743,"R+",120,743,"kworker/0:5",20371
-6824713393969000,2,167000,6824713394136000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713393973000,0,35000,6824713394008000,670,"S",100,670,"kworker/u17:2",14944
-6824713394008000,0,46000,6824713394054000,743,"S",120,743,"kworker/0:5",20371
-6824713394054000,0,41000,6824713394095000,0,"R",120,"[NULL]","swapper",0
-6824713394095000,0,67000,6824713394162000,670,"S",100,670,"kworker/u17:2",14944
-6824713394136000,2,347000,6824713394483000,0,"R",120,"[NULL]","swapper",0
-6824713394162000,0,179000,6824713394341000,0,"R",120,"[NULL]","swapper",0
-6824713394341000,0,59000,6824713394400000,670,"S",100,670,"kworker/u17:2",14944
-6824713394400000,0,224000,6824713394624000,743,"S",120,743,"kworker/0:5",20371
-6824713394483000,2,486000,6824713394969000,786,"S",111,494,"SDM_EventThread",685
-6824713394624000,0,46000,6824713394670000,0,"R",120,"[NULL]","swapper",0
-6824713394670000,0,199000,6824713394869000,771,"S",97,493,"DispSync",676
-6824713394869000,0,625000,6824713395494000,0,"R",120,"[NULL]","swapper",0
-6824713394969000,2,86000,6824713395055000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713395055000,2,184000,6824713395239000,739,"S",120,739,"adbd",20305
-6824713395078000,1,283000,6824713395361000,773,"S",97,493,"app",678
-6824713395162000,3,322000,6824713395484000,777,"S",120,493,"HwBinder:640_1",721
-6824713395239000,2,104000,6824713395343000,2487,"R+",120,739,"UsbFfs-worker",20308
-6824713395343000,2,155000,6824713395498000,739,"S",120,739,"adbd",20305
-6824713395361000,1,1958000,6824713397319000,0,"R",120,"[NULL]","swapper",0
-6824713395484000,3,8157000,6824713403641000,0,"R",120,"[NULL]","swapper",0
-6824713395494000,0,49000,6824713395543000,771,"S",97,493,"DispSync",676
-6824713395498000,2,120000,6824713395618000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713395543000,0,1769000,6824713397312000,644,"S",120,644,"ndroid.systemui",1664
-6824713395618000,2,7707000,6824713403325000,0,"R",120,"[NULL]","swapper",0
-6824713397312000,0,423000,6824713397735000,0,"R",120,"[NULL]","swapper",0
-6824713397319000,1,268000,6824713397587000,770,"S",120,493,"Binder:640_2",675
-6824713397587000,1,483000,6824713398070000,0,"R",120,"[NULL]","swapper",0
-6824713397735000,0,162000,6824713397897000,773,"S",97,493,"app",678
-6824713397897000,0,2323000,6824713400220000,0,"R",120,"[NULL]","swapper",0
-6824713398070000,1,74000,6824713398144000,771,"S",97,493,"DispSync",676
-6824713398144000,1,3426000,6824713401570000,0,"R",120,"[NULL]","swapper",0
-6824713399486000,6,30000,6824713399516000,2728,"S",120,739,"shell",20461
-6824713399516000,6,162000,6824713399678000,739,"S",120,739,"adbd",20305
-6824713399678000,6,3250000,6824713402928000,2729,"R+",120,758,"ps",20464
-6824713400220000,0,111000,6824713400331000,670,"S",100,670,"kworker/u17:2",14944
-6824713400331000,0,120000,6824713400451000,743,"S",120,743,"kworker/0:5",20371
-6824713400451000,0,43000,6824713400494000,2487,"R",120,739,"UsbFfs-worker",20308
-6824713400494000,0,70000,6824713400564000,670,"S",100,670,"kworker/u17:2",14944
-6824713400564000,0,40000,6824713400604000,743,"R+",120,743,"kworker/0:5",20371
-6824713400604000,0,34000,6824713400638000,670,"S",100,670,"kworker/u17:2",14944
-6824713400638000,0,17000,6824713400655000,743,"S",120,743,"kworker/0:5",20371
-6824713400655000,0,97000,6824713400752000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713400752000,0,71000,6824713400823000,670,"S",100,670,"kworker/u17:2",14944
-6824713400823000,0,363000,6824713401186000,0,"R",120,"[NULL]","swapper",0
-6824713401186000,0,78000,6824713401264000,670,"S",100,670,"kworker/u17:2",14944
-6824713401264000,0,103000,6824713401367000,743,"S",120,743,"kworker/0:5",20371
-6824713401367000,0,329000,6824713401696000,0,"R",120,"[NULL]","swapper",0
-6824713401570000,1,237000,6824713401807000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713401696000,0,372000,6824713402068000,739,"S",120,739,"adbd",20305
-6824713401807000,1,2137000,6824713403944000,0,"R",120,"[NULL]","swapper",0
-6824713402068000,0,1411000,6824713403479000,0,"R",120,"[NULL]","swapper",0
-6824713402488000,7,51000,6824713402539000,2728,"S",120,739,"shell",20461
-6824713402539000,7,4230000,6824713406769000,0,"R",120,"[NULL]","swapper",0
-6824713402761000,4,165000,6824713402926000,739,"S",120,739,"adbd",20305
-6824713402926000,4,350000,6824713403276000,0,"R",120,"[NULL]","swapper",0
-6824713402928000,6,24000,6824713402952000,49,"S",0,49,"migration/6",56
-6824713402952000,6,43000,6824713402995000,483,"S",49,483,"sugov:4",606
-6824713402995000,6,4234000,6824713407229000,0,"R",120,"[NULL]","swapper",0
-6824713403276000,4,53289000,6824713456565000,2729,"R",120,758,"ps",20464
-6824713403325000,2,97000,6824713403422000,22,"S",120,22,"ksoftirqd/2",25
-6824713403422000,2,498000,6824713403920000,0,"R",120,"[NULL]","swapper",0
-6824713403479000,0,104000,6824713403583000,670,"S",100,670,"kworker/u17:2",14944
-6824713403583000,0,99000,6824713403682000,743,"S",120,743,"kworker/0:5",20371
-6824713403641000,3,96000,6824713403737000,5,"S",120,5,"rcu_preempt",7
-6824713403682000,0,507000,6824713404189000,0,"R",120,"[NULL]","swapper",0
-6824713403737000,3,885000,6824713404622000,0,"R",120,"[NULL]","swapper",0
-6824713403920000,2,530000,6824713404450000,52,"S",120,52,"rcuop/6",60
-6824713403944000,1,83000,6824713404027000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713404027000,1,662000,6824713404689000,0,"R",120,"[NULL]","swapper",0
-6824713404189000,0,132000,6824713404321000,670,"R+",100,670,"kworker/u17:2",14944
-6824713404321000,0,140000,6824713404461000,482,"S",49,482,"sugov:0",605
-6824713404450000,2,572000,6824713405022000,0,"R",120,"[NULL]","swapper",0
-6824713404461000,0,55000,6824713404516000,670,"S",100,670,"kworker/u17:2",14944
-6824713404516000,0,125000,6824713404641000,743,"S",120,743,"kworker/0:5",20371
-6824713404622000,3,59000,6824713404681000,630,"S",100,630,"kworker/u17:1",1134
-6824713404641000,0,3779000,6824713408420000,0,"R",120,"[NULL]","swapper",0
-6824713404681000,3,582000,6824713405263000,0,"R",120,"[NULL]","swapper",0
-6824713404689000,1,62000,6824713404751000,5,"S",120,5,"rcu_preempt",7
-6824713404751000,1,4130000,6824713408881000,0,"R",120,"[NULL]","swapper",0
-6824713405022000,2,120000,6824713405142000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713405142000,2,330000,6824713405472000,0,"R",120,"[NULL]","swapper",0
-6824713405263000,3,117000,6824713405380000,630,"S",100,630,"kworker/u17:1",1134
-6824713405380000,3,138000,6824713405518000,686,"S",120,686,"kworker/3:1",17791
-6824713405472000,2,245000,6824713405717000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713405518000,3,2372000,6824713407890000,0,"R",120,"[NULL]","swapper",0
-6824713405717000,2,2451000,6824713408168000,0,"R",120,"[NULL]","swapper",0
-6824713405788000,5,62000,6824713405850000,739,"S",120,739,"adbd",20305
-6824713405850000,5,1152000,6824713407002000,0,"R",120,"[NULL]","swapper",0
-6824713406769000,7,10000,6824713406779000,38,"S",120,38,"rcuop/4",44
-6824713406779000,7,26544000,6824713433323000,0,"R",120,"[NULL]","swapper",0
-6824713407002000,5,29000,6824713407031000,2728,"S",120,739,"shell",20461
-6824713407031000,5,7986000,6824713415017000,0,"R",120,"[NULL]","swapper",0
-6824713407229000,6,96000,6824713407325000,739,"S",120,739,"adbd",20305
-6824713407325000,6,1876000,6824713409201000,0,"R",120,"[NULL]","swapper",0
-6824713407890000,3,127000,6824713408017000,630,"S",100,630,"kworker/u17:1",1134
-6824713408017000,3,114000,6824713408131000,686,"S",120,686,"kworker/3:1",17791
-6824713408131000,3,8216000,6824713416347000,0,"R",120,"[NULL]","swapper",0
-6824713408168000,2,97000,6824713408265000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713408265000,2,326000,6824713408591000,0,"R",120,"[NULL]","swapper",0
-6824713408420000,0,106000,6824713408526000,630,"S",100,630,"kworker/u17:1",1134
-6824713408526000,0,129000,6824713408655000,743,"S",120,743,"kworker/0:5",20371
-6824713408591000,2,198000,6824713408789000,630,"S",100,630,"kworker/u17:1",1134
-6824713408655000,0,53000,6824713408708000,0,"R",120,"[NULL]","swapper",0
-6824713408708000,0,44000,6824713408752000,670,"S",100,670,"kworker/u17:2",14944
-6824713408752000,0,7418000,6824713416170000,0,"R",120,"[NULL]","swapper",0
-6824713408789000,2,105000,6824713408894000,694,"S",120,694,"kworker/2:0",18823
-6824713408881000,1,261000,6824713409142000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713408894000,2,1471000,6824713410365000,0,"R",120,"[NULL]","swapper",0
-6824713409142000,1,888000,6824713410030000,0,"R",120,"[NULL]","swapper",0
-6824713409201000,6,60000,6824713409261000,739,"S",120,739,"adbd",20305
-6824713409261000,6,6003000,6824713415264000,0,"R",120,"[NULL]","swapper",0
-6824713410030000,1,92000,6824713410122000,5,"S",120,5,"rcu_preempt",7
-6824713410122000,1,6146000,6824713416268000,0,"R",120,"[NULL]","swapper",0
-6824713410365000,2,1409000,6824713411774000,52,"S",120,52,"rcuop/6",60
-6824713411774000,2,3953000,6824713415727000,0,"R",120,"[NULL]","swapper",0
-6824713415017000,5,41000,6824713415058000,2728,"S",120,739,"shell",20461
-6824713415058000,5,871000,6824713415929000,0,"R",120,"[NULL]","swapper",0
-6824713415264000,6,114000,6824713415378000,739,"S",120,739,"adbd",20305
-6824713415378000,6,2157000,6824713417535000,0,"R",120,"[NULL]","swapper",0
-6824713415727000,2,177000,6824713415904000,630,"S",100,630,"kworker/u17:1",1134
-6824713415904000,2,176000,6824713416080000,694,"S",120,694,"kworker/2:0",18823
-6824713415929000,5,22000,6824713415951000,2728,"S",120,739,"shell",20461
-6824713415951000,5,4014000,6824713419965000,0,"R",120,"[NULL]","swapper",0
-6824713416080000,2,579000,6824713416659000,0,"R",120,"[NULL]","swapper",0
-6824713416170000,0,101000,6824713416271000,670,"S",100,670,"kworker/u17:2",14944
-6824713416268000,1,135000,6824713416403000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713416271000,0,81000,6824713416352000,743,"S",120,743,"kworker/0:5",20371
-6824713416347000,3,56000,6824713416403000,630,"S",100,630,"kworker/u17:1",1134
-6824713416352000,0,4993000,6824713421345000,0,"R",120,"[NULL]","swapper",0
-6824713416403000,3,2160000,6824713418563000,0,"R",120,"[NULL]","swapper",0
-6824713416403000,1,272000,6824713416675000,0,"R",120,"[NULL]","swapper",0
-6824713416659000,2,84000,6824713416743000,630,"S",100,630,"kworker/u17:1",1134
-6824713416675000,1,57000,6824713416732000,5,"S",120,5,"rcu_preempt",7
-6824713416732000,1,521000,6824713417253000,0,"R",120,"[NULL]","swapper",0
-6824713416743000,2,74000,6824713416817000,0,"R",120,"[NULL]","swapper",0
-6824713416817000,2,91000,6824713416908000,630,"S",100,630,"kworker/u17:1",1134
-6824713416908000,2,119000,6824713417027000,694,"S",120,694,"kworker/2:0",18823
-6824713417027000,2,1013000,6824713418040000,0,"R",120,"[NULL]","swapper",0
-6824713417253000,1,234000,6824713417487000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713417487000,1,1008000,6824713418495000,0,"R",120,"[NULL]","swapper",0
-6824713417535000,6,118000,6824713417653000,739,"S",120,739,"adbd",20305
-6824713417653000,6,1707000,6824713419360000,0,"R",120,"[NULL]","swapper",0
-6824713418040000,2,115000,6824713418155000,630,"S",100,630,"kworker/u17:1",1134
-6824713418155000,2,178000,6824713418333000,694,"S",120,694,"kworker/2:0",18823
-6824713418333000,2,395000,6824713418728000,0,"R",120,"[NULL]","swapper",0
-6824713418495000,1,107000,6824713418602000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713418563000,3,106000,6824713418669000,630,"S",100,630,"kworker/u17:1",1134
-6824713418602000,1,455000,6824713419057000,0,"R",120,"[NULL]","swapper",0
-6824713418669000,3,117000,6824713418786000,686,"S",120,686,"kworker/3:1",17791
-6824713418728000,2,76000,6824713418804000,630,"S",100,630,"kworker/u17:1",1134
-6824713418786000,3,2669000,6824713421455000,0,"R",120,"[NULL]","swapper",0
-6824713418804000,2,62000,6824713418866000,0,"R",120,"[NULL]","swapper",0
-6824713418866000,2,86000,6824713418952000,630,"S",100,630,"kworker/u17:1",1134
-6824713418952000,2,87000,6824713419039000,694,"S",120,694,"kworker/2:0",18823
-6824713419039000,2,1615000,6824713420654000,0,"R",120,"[NULL]","swapper",0
-6824713419057000,1,251000,6824713419308000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713419308000,1,1797000,6824713421105000,0,"R",120,"[NULL]","swapper",0
-6824713419360000,6,50000,6824713419410000,739,"S",120,739,"adbd",20305
-6824713419410000,6,798000,6824713420208000,0,"R",120,"[NULL]","swapper",0
-6824713419965000,5,29000,6824713419994000,2728,"S",120,739,"shell",20461
-6824713419994000,5,3214000,6824713423208000,0,"R",120,"[NULL]","swapper",0
-6824713420208000,6,90000,6824713420298000,739,"S",120,739,"adbd",20305
-6824713420298000,6,1655000,6824713421953000,0,"R",120,"[NULL]","swapper",0
-6824713420654000,2,115000,6824713420769000,630,"S",100,630,"kworker/u17:1",1134
-6824713420769000,2,111000,6824713420880000,694,"S",120,694,"kworker/2:0",18823
-6824713420880000,2,66000,6824713420946000,0,"R",120,"[NULL]","swapper",0
-6824713420946000,2,147000,6824713421093000,630,"S",100,630,"kworker/u17:1",1134
-6824713421093000,2,133000,6824713421226000,694,"S",120,694,"kworker/2:0",18823
-6824713421105000,1,129000,6824713421234000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713421226000,2,3867000,6824713425093000,0,"R",120,"[NULL]","swapper",0
-6824713421234000,1,424000,6824713421658000,0,"R",120,"[NULL]","swapper",0
-6824713421345000,0,93000,6824713421438000,670,"S",100,670,"kworker/u17:2",14944
-6824713421438000,0,49000,6824713421487000,0,"R",120,"[NULL]","swapper",0
-6824713421455000,3,119000,6824713421574000,630,"S",100,630,"kworker/u17:1",1134
-6824713421487000,0,43000,6824713421530000,670,"S",100,670,"kworker/u17:2",14944
-6824713421530000,0,6608000,6824713428138000,0,"R",120,"[NULL]","swapper",0
-6824713421574000,3,130000,6824713421704000,686,"S",120,686,"kworker/3:1",17791
-6824713421658000,1,224000,6824713421882000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713421704000,3,2240000,6824713423944000,0,"R",120,"[NULL]","swapper",0
-6824713421882000,1,1476000,6824713423358000,0,"R",120,"[NULL]","swapper",0
-6824713421953000,6,52000,6824713422005000,739,"S",120,739,"adbd",20305
-6824713422005000,6,1245000,6824713423250000,0,"R",120,"[NULL]","swapper",0
-6824713423208000,5,44000,6824713423252000,2728,"S",120,739,"shell",20461
-6824713423250000,6,81000,6824713423331000,739,"S",120,739,"adbd",20305
-6824713423252000,5,4584000,6824713427836000,0,"R",120,"[NULL]","swapper",0
-6824713423331000,6,90000,6824713423421000,0,"R",120,"[NULL]","swapper",0
-6824713423358000,1,94000,6824713423452000,5,"S",120,5,"rcu_preempt",7
-6824713423421000,6,90000,6824713423511000,38,"S",120,38,"rcuop/4",44
-6824713423452000,1,101000,6824713423553000,0,"R",120,"[NULL]","swapper",0
-6824713423511000,6,2065000,6824713425576000,0,"R",120,"[NULL]","swapper",0
-6824713423553000,1,47000,6824713423600000,5,"S",120,5,"rcu_preempt",7
-6824713423600000,1,800000,6824713424400000,0,"R",120,"[NULL]","swapper",0
-6824713423944000,3,121000,6824713424065000,630,"S",100,630,"kworker/u17:1",1134
-6824713424065000,3,113000,6824713424178000,686,"S",120,686,"kworker/3:1",17791
-6824713424178000,3,631000,6824713424809000,0,"R",120,"[NULL]","swapper",0
-6824713424400000,1,98000,6824713424498000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713424498000,1,773000,6824713425271000,0,"R",120,"[NULL]","swapper",0
-6824713424809000,3,127000,6824713424936000,630,"S",100,630,"kworker/u17:1",1134
-6824713424936000,3,111000,6824713425047000,686,"S",120,686,"kworker/3:1",17791
-6824713425047000,3,3858000,6824713428905000,0,"R",120,"[NULL]","swapper",0
-6824713425093000,2,105000,6824713425198000,630,"S",100,630,"kworker/u17:1",1134
-6824713425198000,2,89000,6824713425287000,694,"S",120,694,"kworker/2:0",18823
-6824713425271000,1,260000,6824713425531000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713425287000,2,1587000,6824713426874000,0,"R",120,"[NULL]","swapper",0
-6824713425531000,1,3451000,6824713428982000,0,"R",120,"[NULL]","swapper",0
-6824713425576000,6,50000,6824713425626000,739,"S",120,739,"adbd",20305
-6824713425626000,6,2459000,6824713428085000,0,"R",120,"[NULL]","swapper",0
-6824713426874000,2,103000,6824713426977000,702,"S",120,702,"kworker/u16:7",19422
-6824713426977000,2,1675000,6824713428652000,0,"R",120,"[NULL]","swapper",0
-6824713427836000,5,29000,6824713427865000,2728,"S",120,739,"shell",20461
-6824713427865000,5,2265000,6824713430130000,0,"R",120,"[NULL]","swapper",0
-6824713428085000,6,99000,6824713428184000,739,"S",120,739,"adbd",20305
-6824713428138000,0,104000,6824713428242000,743,"S",120,743,"kworker/0:5",20371
-6824713428184000,6,2870000,6824713431054000,0,"R",120,"[NULL]","swapper",0
-6824713428242000,0,898000,6824713429140000,0,"R",120,"[NULL]","swapper",0
-6824713428652000,2,437000,6824713429089000,786,"S",111,494,"SDM_EventThread",685
-6824713428905000,3,123000,6824713429028000,630,"S",100,630,"kworker/u17:1",1134
-6824713428982000,1,322000,6824713429304000,777,"S",120,493,"HwBinder:640_1",721
-6824713429028000,3,118000,6824713429146000,686,"S",120,686,"kworker/3:1",17791
-6824713429089000,2,544000,6824713429633000,0,"R",120,"[NULL]","swapper",0
-6824713429140000,0,196000,6824713429336000,771,"S",97,493,"DispSync",676
-6824713429146000,3,734000,6824713429880000,0,"R",120,"[NULL]","swapper",0
-6824713429304000,1,93000,6824713429397000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713429336000,0,735000,6824713430071000,0,"R",120,"[NULL]","swapper",0
-6824713429397000,1,470000,6824713429867000,0,"R",120,"[NULL]","swapper",0
-6824713429633000,2,287000,6824713429920000,773,"S",97,493,"app",678
-6824713429867000,1,193000,6824713430060000,771,"S",97,493,"DispSync",676
-6824713429880000,3,203000,6824713430083000,630,"S",100,630,"kworker/u17:1",1134
-6824713429920000,2,86000,6824713430006000,0,"R",120,"[NULL]","swapper",0
-6824713430006000,2,61000,6824713430067000,5,"S",120,5,"rcu_preempt",7
-6824713430060000,1,492000,6824713430552000,0,"R",120,"[NULL]","swapper",0
-6824713430067000,2,113000,6824713430180000,0,"R",120,"[NULL]","swapper",0
-6824713430071000,0,1790000,6824713431861000,644,"S",120,644,"ndroid.systemui",1664
-6824713430083000,3,143000,6824713430226000,686,"S",120,686,"kworker/3:1",17791
-6824713430130000,5,24000,6824713430154000,2728,"S",120,739,"shell",20461
-6824713430154000,5,3393000,6824713433547000,0,"R",120,"[NULL]","swapper",0
-6824713430180000,2,112000,6824713430292000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713430226000,3,1706000,6824713431932000,0,"R",120,"[NULL]","swapper",0
-6824713430292000,2,469000,6824713430761000,0,"R",120,"[NULL]","swapper",0
-6824713430552000,1,120000,6824713430672000,630,"S",100,630,"kworker/u17:1",1134
-6824713430672000,1,134000,6824713430806000,693,"S",120,693,"kworker/1:1",18800
-6824713430761000,2,222000,6824713430983000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713430806000,1,695000,6824713431501000,0,"R",120,"[NULL]","swapper",0
-6824713430983000,2,607000,6824713431590000,0,"R",120,"[NULL]","swapper",0
-6824713431054000,6,118000,6824713431172000,739,"S",120,739,"adbd",20305
-6824713431172000,6,1852000,6824713433024000,0,"R",120,"[NULL]","swapper",0
-6824713431501000,1,118000,6824713431619000,630,"S",100,630,"kworker/u17:1",1134
-6824713431590000,2,264000,6824713431854000,770,"R+",120,493,"Binder:640_2",675
-6824713431619000,1,101000,6824713431720000,693,"S",120,693,"kworker/1:1",18800
-6824713431720000,1,103000,6824713431823000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713431823000,1,758000,6824713432581000,0,"R",120,"[NULL]","swapper",0
-6824713431854000,2,46000,6824713431900000,773,"S",97,493,"app",678
-6824713431861000,0,492000,6824713432353000,0,"R",120,"[NULL]","swapper",0
-6824713431900000,2,159000,6824713432059000,770,"S",120,493,"Binder:640_2",675
-6824713431932000,3,91000,6824713432023000,630,"S",100,630,"kworker/u17:1",1134
-6824713432023000,3,128000,6824713432151000,0,"R",120,"[NULL]","swapper",0
-6824713432059000,2,655000,6824713432714000,0,"R",120,"[NULL]","swapper",0
-6824713432151000,3,92000,6824713432243000,630,"S",100,630,"kworker/u17:1",1134
-6824713432243000,3,110000,6824713432353000,686,"S",120,686,"kworker/3:1",17791
-6824713432353000,3,349000,6824713432702000,0,"R",120,"[NULL]","swapper",0
-6824713432353000,0,196000,6824713432549000,773,"S",97,493,"app",678
-6824713432549000,0,28791000,6824713461340000,0,"R",120,"[NULL]","swapper",0
-6824713432581000,1,110000,6824713432691000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713432691000,1,29017000,6824713461708000,0,"R",120,"[NULL]","swapper",0
-6824713432702000,3,77000,6824713432779000,630,"S",100,630,"kworker/u17:1",1134
-6824713432714000,2,166000,6824713432880000,771,"S",97,493,"DispSync",676
-6824713432779000,3,31370000,6824713464149000,0,"R",120,"[NULL]","swapper",0
-6824713432880000,2,3801000,6824713436681000,0,"R",120,"[NULL]","swapper",0
-6824713433024000,6,46000,6824713433070000,630,"S",100,630,"kworker/u17:1",1134
-6824713433070000,6,31000,6824713433101000,669,"S",120,669,"kworker/6:1",14833
-6824713433101000,6,1961000,6824713435062000,0,"R",120,"[NULL]","swapper",0
-6824713433323000,7,68000,6824713433391000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713433391000,7,2508000,6824713435899000,0,"R",120,"[NULL]","swapper",0
-6824713433547000,5,47000,6824713433594000,739,"S",120,739,"adbd",20305
-6824713433594000,5,1241000,6824713434835000,0,"R",120,"[NULL]","swapper",0
-6824713434835000,5,30000,6824713434865000,2728,"S",120,739,"shell",20461
-6824713434865000,5,2740000,6824713437605000,0,"R",120,"[NULL]","swapper",0
-6824713435062000,6,101000,6824713435163000,739,"S",120,739,"adbd",20305
-6824713435163000,6,471000,6824713435634000,0,"R",120,"[NULL]","swapper",0
-6824713435634000,6,36000,6824713435670000,630,"S",100,630,"kworker/u17:1",1134
-6824713435670000,6,13000,6824713435683000,669,"S",120,669,"kworker/6:1",14833
-6824713435683000,6,316000,6824713435999000,0,"R",120,"[NULL]","swapper",0
-6824713435899000,7,15000,6824713435914000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713435914000,7,346000,6824713436260000,0,"R",120,"[NULL]","swapper",0
-6824713435999000,6,24000,6824713436023000,630,"S",100,630,"kworker/u17:1",1134
-6824713436023000,6,13000,6824713436036000,669,"S",120,669,"kworker/6:1",14833
-6824713436036000,6,273000,6824713436309000,0,"R",120,"[NULL]","swapper",0
-6824713436260000,7,20000,6824713436280000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713436280000,7,302000,6824713436582000,0,"R",120,"[NULL]","swapper",0
-6824713436309000,6,29000,6824713436338000,630,"S",100,630,"kworker/u17:1",1134
-6824713436338000,6,35000,6824713436373000,0,"R",120,"[NULL]","swapper",0
-6824713436373000,6,29000,6824713436402000,630,"S",100,630,"kworker/u17:1",1134
-6824713436402000,6,14000,6824713436416000,669,"S",120,669,"kworker/6:1",14833
-6824713436416000,6,184000,6824713436600000,0,"R",120,"[NULL]","swapper",0
-6824713436582000,7,40000,6824713436622000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713436600000,6,53000,6824713436653000,739,"S",120,739,"adbd",20305
-6824713436622000,7,1360000,6824713437982000,0,"R",120,"[NULL]","swapper",0
-6824713436653000,6,83000,6824713436736000,0,"R",120,"[NULL]","swapper",0
-6824713436681000,2,89000,6824713436770000,5,"S",120,5,"rcu_preempt",7
-6824713436736000,6,216000,6824713436952000,38,"S",120,38,"rcuop/4",44
-6824713436770000,2,222000,6824713436992000,0,"R",120,"[NULL]","swapper",0
-6824713436952000,6,678000,6824713437630000,0,"R",120,"[NULL]","swapper",0
-6824713436992000,2,48000,6824713437040000,5,"S",120,5,"rcu_preempt",7
-6824713437040000,2,6321000,6824713443361000,0,"R",120,"[NULL]","swapper",0
-6824713437605000,5,30000,6824713437635000,2728,"S",120,739,"shell",20461
-6824713437630000,6,82000,6824713437712000,739,"S",120,739,"adbd",20305
-6824713437635000,5,3002000,6824713440637000,0,"R",120,"[NULL]","swapper",0
-6824713437712000,6,15000,6824713437727000,0,"R",120,"[NULL]","swapper",0
-6824713437727000,6,14000,6824713437741000,630,"S",100,630,"kworker/u17:1",1134
-6824713437741000,6,40000,6824713437781000,0,"R",120,"[NULL]","swapper",0
-6824713437781000,6,19000,6824713437800000,630,"S",100,630,"kworker/u17:1",1134
-6824713437800000,6,9000,6824713437809000,669,"S",120,669,"kworker/6:1",14833
-6824713437809000,6,39000,6824713437848000,0,"R",120,"[NULL]","swapper",0
-6824713437848000,6,25000,6824713437873000,630,"S",100,630,"kworker/u17:1",1134
-6824713437873000,6,136000,6824713438009000,0,"R",120,"[NULL]","swapper",0
-6824713437982000,7,13000,6824713437995000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713437995000,7,43000,6824713438038000,0,"R",120,"[NULL]","swapper",0
-6824713438009000,6,19000,6824713438028000,630,"S",100,630,"kworker/u17:1",1134
-6824713438028000,6,10000,6824713438038000,669,"S",120,669,"kworker/6:1",14833
-6824713438038000,7,7000,6824713438045000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713438038000,6,283000,6824713438321000,0,"R",120,"[NULL]","swapper",0
-6824713438045000,7,470000,6824713438515000,0,"R",120,"[NULL]","swapper",0
-6824713438321000,6,20000,6824713438341000,630,"S",100,630,"kworker/u17:1",1134
-6824713438341000,6,34000,6824713438375000,0,"R",120,"[NULL]","swapper",0
-6824713438375000,6,29000,6824713438404000,630,"S",100,630,"kworker/u17:1",1134
-6824713438404000,6,71000,6824713438475000,0,"R",120,"[NULL]","swapper",0
-6824713438475000,6,29000,6824713438504000,630,"S",100,630,"kworker/u17:1",1134
-6824713438504000,6,14000,6824713438518000,669,"S",120,669,"kworker/6:1",14833
-6824713438515000,7,34000,6824713438549000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713438518000,6,10000,6824713438528000,0,"R",120,"[NULL]","swapper",0
-6824713438528000,6,43000,6824713438571000,739,"S",120,739,"adbd",20305
-6824713438549000,7,3192000,6824713441741000,0,"R",120,"[NULL]","swapper",0
-6824713438571000,6,2294000,6824713440865000,0,"R",120,"[NULL]","swapper",0
-6824713440637000,5,30000,6824713440667000,2728,"S",120,739,"shell",20461
-6824713440667000,5,2936000,6824713443603000,0,"R",120,"[NULL]","swapper",0
-6824713440865000,6,84000,6824713440949000,739,"S",120,739,"adbd",20305
-6824713440949000,6,533000,6824713441482000,0,"R",120,"[NULL]","swapper",0
-6824713441482000,6,36000,6824713441518000,630,"S",100,630,"kworker/u17:1",1134
-6824713441518000,6,12000,6824713441530000,669,"S",120,669,"kworker/6:1",14833
-6824713441530000,6,315000,6824713441845000,0,"R",120,"[NULL]","swapper",0
-6824713441741000,7,12000,6824713441753000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713441753000,7,349000,6824713442102000,0,"R",120,"[NULL]","swapper",0
-6824713441845000,6,22000,6824713441867000,630,"S",100,630,"kworker/u17:1",1134
-6824713441867000,6,11000,6824713441878000,669,"S",120,669,"kworker/6:1",14833
-6824713441878000,6,270000,6824713442148000,0,"R",120,"[NULL]","swapper",0
-6824713442102000,7,15000,6824713442117000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713442117000,7,369000,6824713442486000,0,"R",120,"[NULL]","swapper",0
-6824713442148000,6,16000,6824713442164000,630,"S",100,630,"kworker/u17:1",1134
-6824713442164000,6,35000,6824713442199000,0,"R",120,"[NULL]","swapper",0
-6824713442199000,6,26000,6824713442225000,630,"S",100,630,"kworker/u17:1",1134
-6824713442225000,6,51000,6824713442276000,0,"R",120,"[NULL]","swapper",0
-6824713442276000,6,29000,6824713442305000,630,"S",100,630,"kworker/u17:1",1134
-6824713442305000,6,15000,6824713442320000,669,"S",120,669,"kworker/6:1",14833
-6824713442320000,6,184000,6824713442504000,0,"R",120,"[NULL]","swapper",0
-6824713442486000,7,38000,6824713442524000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713442504000,6,45000,6824713442549000,739,"S",120,739,"adbd",20305
-6824713442524000,7,2361000,6824713444885000,0,"R",120,"[NULL]","swapper",0
-6824713442549000,6,1704000,6824713444253000,0,"R",120,"[NULL]","swapper",0
-6824713443361000,2,92000,6824713443453000,5,"S",120,5,"rcu_preempt",7
-6824713443453000,2,362000,6824713443815000,0,"R",120,"[NULL]","swapper",0
-6824713443603000,5,161000,6824713443764000,38,"S",120,38,"rcuop/4",44
-6824713443764000,5,254000,6824713444018000,0,"R",120,"[NULL]","swapper",0
-6824713443815000,2,49000,6824713443864000,5,"S",120,5,"rcu_preempt",7
-6824713443864000,2,6152000,6824713450016000,0,"R",120,"[NULL]","swapper",0
-6824713444018000,5,29000,6824713444047000,2728,"S",120,739,"shell",20461
-6824713444047000,5,6341000,6824713450388000,0,"R",120,"[NULL]","swapper",0
-6824713444253000,6,82000,6824713444335000,739,"S",120,739,"adbd",20305
-6824713444335000,6,323000,6824713444658000,0,"R",120,"[NULL]","swapper",0
-6824713444658000,6,36000,6824713444694000,630,"S",100,630,"kworker/u17:1",1134
-6824713444694000,6,11000,6824713444705000,669,"S",120,669,"kworker/6:1",14833
-6824713444705000,6,416000,6824713445121000,0,"R",120,"[NULL]","swapper",0
-6824713444885000,7,14000,6824713444899000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713444899000,7,439000,6824713445338000,0,"R",120,"[NULL]","swapper",0
-6824713445121000,6,35000,6824713445156000,630,"S",100,630,"kworker/u17:1",1134
-6824713445156000,6,9000,6824713445165000,669,"S",120,669,"kworker/6:1",14833
-6824713445165000,6,50000,6824713445215000,0,"R",120,"[NULL]","swapper",0
-6824713445215000,6,27000,6824713445242000,630,"S",100,630,"kworker/u17:1",1134
-6824713445242000,6,9000,6824713445251000,669,"S",120,669,"kworker/6:1",14833
-6824713445251000,6,106000,6824713445357000,0,"R",120,"[NULL]","swapper",0
-6824713445338000,7,42000,6824713445380000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713445357000,6,38000,6824713445395000,739,"S",120,739,"adbd",20305
-6824713445380000,7,2465000,6824713447845000,0,"R",120,"[NULL]","swapper",0
-6824713445395000,6,2679000,6824713448074000,0,"R",120,"[NULL]","swapper",0
-6824713447845000,7,24000,6824713447869000,2728,"S",120,739,"shell",20461
-6824713447869000,7,782000,6824713448651000,0,"R",120,"[NULL]","swapper",0
-6824713448074000,6,85000,6824713448159000,739,"S",120,739,"adbd",20305
-6824713448159000,6,279000,6824713448438000,0,"R",120,"[NULL]","swapper",0
-6824713448438000,6,36000,6824713448474000,630,"S",100,630,"kworker/u17:1",1134
-6824713448474000,6,11000,6824713448485000,669,"S",120,669,"kworker/6:1",14833
-6824713448485000,6,380000,6824713448865000,0,"R",120,"[NULL]","swapper",0
-6824713448651000,7,12000,6824713448663000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713448663000,7,456000,6824713449119000,0,"R",120,"[NULL]","swapper",0
-6824713448865000,6,23000,6824713448888000,630,"S",100,630,"kworker/u17:1",1134
-6824713448888000,6,11000,6824713448899000,669,"S",120,669,"kworker/6:1",14833
-6824713448899000,6,269000,6824713449168000,0,"R",120,"[NULL]","swapper",0
-6824713449119000,7,15000,6824713449134000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713449134000,7,353000,6824713449487000,0,"R",120,"[NULL]","swapper",0
-6824713449168000,6,27000,6824713449195000,630,"S",100,630,"kworker/u17:1",1134
-6824713449195000,6,48000,6824713449243000,0,"R",120,"[NULL]","swapper",0
-6824713449243000,6,29000,6824713449272000,630,"S",100,630,"kworker/u17:1",1134
-6824713449272000,6,15000,6824713449287000,669,"S",120,669,"kworker/6:1",14833
-6824713449287000,6,389000,6824713449676000,0,"R",120,"[NULL]","swapper",0
-6824713449487000,7,38000,6824713449525000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713449525000,7,2642000,6824713452167000,0,"R",120,"[NULL]","swapper",0
-6824713449676000,6,51000,6824713449727000,739,"S",120,739,"adbd",20305
-6824713449727000,6,349000,6824713450076000,0,"R",120,"[NULL]","swapper",0
-6824713450016000,2,95000,6824713450111000,5,"S",120,5,"rcu_preempt",7
-6824713450076000,6,87000,6824713450163000,38,"S",120,38,"rcuop/4",44
-6824713450111000,2,11329000,6824713461440000,0,"R",120,"[NULL]","swapper",0
-6824713450163000,6,2199000,6824713452362000,0,"R",120,"[NULL]","swapper",0
-6824713450388000,5,13000,6824713450401000,5,"S",120,5,"rcu_preempt",7
-6824713450401000,5,6481000,6824713456882000,0,"R",120,"[NULL]","swapper",0
-6824713452167000,7,26000,6824713452193000,2728,"S",120,739,"shell",20461
-6824713452193000,7,989000,6824713453182000,0,"R",120,"[NULL]","swapper",0
-6824713452362000,6,87000,6824713452449000,739,"S",120,739,"adbd",20305
-6824713452449000,6,485000,6824713452934000,0,"R",120,"[NULL]","swapper",0
-6824713452934000,6,35000,6824713452969000,630,"S",100,630,"kworker/u17:1",1134
-6824713452969000,6,12000,6824713452981000,669,"S",120,669,"kworker/6:1",14833
-6824713452981000,6,601000,6824713453582000,0,"R",120,"[NULL]","swapper",0
-6824713453182000,7,12000,6824713453194000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713453194000,7,648000,6824713453842000,0,"R",120,"[NULL]","swapper",0
-6824713453582000,6,35000,6824713453617000,630,"S",100,630,"kworker/u17:1",1134
-6824713453617000,6,11000,6824713453628000,669,"S",120,669,"kworker/6:1",14833
-6824713453628000,6,571000,6824713454199000,0,"R",120,"[NULL]","swapper",0
-6824713453842000,7,15000,6824713453857000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713453857000,7,551000,6824713454408000,0,"R",120,"[NULL]","swapper",0
-6824713454199000,6,30000,6824713454229000,630,"S",100,630,"kworker/u17:1",1134
-6824713454229000,6,15000,6824713454244000,669,"S",120,669,"kworker/6:1",14833
-6824713454244000,6,182000,6824713454426000,0,"R",120,"[NULL]","swapper",0
-6824713454408000,7,40000,6824713454448000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713454426000,6,45000,6824713454471000,739,"S",120,739,"adbd",20305
-6824713454448000,7,1495000,6824713455943000,0,"R",120,"[NULL]","swapper",0
-6824713454471000,6,1697000,6824713456168000,0,"R",120,"[NULL]","swapper",0
-6824713455943000,7,21000,6824713455964000,2728,"S",120,739,"shell",20461
-6824713455964000,7,1116000,6824713457080000,0,"R",120,"[NULL]","swapper",0
-6824713456168000,6,83000,6824713456251000,739,"S",120,739,"adbd",20305
-6824713456251000,6,535000,6824713456786000,0,"R",120,"[NULL]","swapper",0
-6824713456565000,4,16000,6824713456581000,716,"S",120,716,"kworker/4:1",19875
-6824713456581000,4,3324000,6824713459905000,2729,"R",120,758,"ps",20464
-6824713456786000,6,36000,6824713456822000,630,"S",100,630,"kworker/u17:1",1134
-6824713456822000,6,11000,6824713456833000,669,"S",120,669,"kworker/6:1",14833
-6824713456833000,6,411000,6824713457244000,0,"R",120,"[NULL]","swapper",0
-6824713456882000,5,15000,6824713456897000,5,"S",120,5,"rcu_preempt",7
-6824713456897000,5,644000,6824713457541000,0,"R",120,"[NULL]","swapper",0
-6824713457080000,7,12000,6824713457092000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713457092000,7,408000,6824713457500000,0,"R",120,"[NULL]","swapper",0
-6824713457244000,6,70000,6824713457314000,38,"S",120,38,"rcuop/4",44
-6824713457314000,6,585000,6824713457899000,0,"R",120,"[NULL]","swapper",0
-6824713457500000,7,44000,6824713457544000,630,"S",100,630,"kworker/u17:1",1134
-6824713457541000,5,8000,6824713457549000,5,"S",120,5,"rcu_preempt",7
-6824713457544000,7,12000,6824713457556000,668,"S",120,668,"kworker/7:2",14813
-6824713457549000,5,2749000,6824713460298000,0,"R",120,"[NULL]","swapper",0
-6824713457556000,7,13000,6824713457569000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713457569000,7,270000,6824713457839000,0,"R",120,"[NULL]","swapper",0
-6824713457839000,7,32000,6824713457871000,630,"S",100,630,"kworker/u17:1",1134
-6824713457871000,7,12000,6824713457883000,668,"S",120,668,"kworker/7:2",14813
-6824713457883000,7,36000,6824713457919000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713457899000,6,46000,6824713457945000,739,"S",120,739,"adbd",20305
-6824713457919000,7,2183000,6824713460102000,0,"R",120,"[NULL]","swapper",0
-6824713457945000,6,5819000,6824713463764000,0,"R",120,"[NULL]","swapper",0
-6824713459905000,4,14000,6824713459919000,716,"S",120,716,"kworker/4:1",19875
-6824713459919000,4,6161000,6824713466080000,2729,"I",120,758,"ps",20464
-6824713460102000,7,30000,6824713460132000,2728,"S",120,739,"shell",20461
-6824713460132000,7,539000,6824713460671000,0,"R",120,"[NULL]","swapper",0
-6824713460298000,5,97000,6824713460395000,739,"S",120,739,"adbd",20305
-6824713460395000,5,1447000,6824713461842000,0,"R",120,"[NULL]","swapper",0
-6824713460671000,7,35000,6824713460706000,630,"S",100,630,"kworker/u17:1",1134
-6824713460706000,7,8000,6824713460714000,668,"S",120,668,"kworker/7:2",14813
-6824713460714000,7,9000,6824713460723000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713460723000,7,306000,6824713461029000,0,"R",120,"[NULL]","swapper",0
-6824713461029000,7,22000,6824713461051000,630,"S",100,630,"kworker/u17:1",1134
-6824713461051000,7,8000,6824713461059000,668,"S",120,668,"kworker/7:2",14813
-6824713461059000,7,11000,6824713461070000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713461070000,7,261000,6824713461331000,0,"R",120,"[NULL]","swapper",0
-6824713461331000,7,30000,6824713461361000,630,"S",100,630,"kworker/u17:1",1134
-6824713461340000,0,109000,6824713461449000,743,"S",120,743,"kworker/0:5",20371
-6824713461361000,7,250000,6824713461611000,0,"R",120,"[NULL]","swapper",0
-6824713461440000,2,373000,6824713461813000,786,"S",111,494,"SDM_EventThread",685
-6824713461449000,0,460000,6824713461909000,0,"R",120,"[NULL]","swapper",0
-6824713461611000,7,30000,6824713461641000,630,"S",100,630,"kworker/u17:1",1134
-6824713461641000,7,13000,6824713461654000,668,"S",120,668,"kworker/7:2",14813
-6824713461654000,7,36000,6824713461690000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713461690000,7,2930000,6824713464620000,0,"R",120,"[NULL]","swapper",0
-6824713461708000,1,421000,6824713462129000,777,"S",120,493,"HwBinder:640_1",721
-6824713461813000,2,364000,6824713462177000,0,"R",120,"[NULL]","swapper",0
-6824713461842000,5,49000,6824713461891000,739,"S",120,739,"adbd",20305
-6824713461891000,5,1341000,6824713463232000,0,"R",120,"[NULL]","swapper",0
-6824713461909000,0,68000,6824713461977000,771,"S",97,493,"DispSync",676
-6824713461977000,0,38000,6824713462015000,0,"R",120,"[NULL]","swapper",0
-6824713462015000,0,162000,6824713462177000,771,"S",97,493,"DispSync",676
-6824713462129000,1,262000,6824713462391000,0,"R",120,"[NULL]","swapper",0
-6824713462177000,2,255000,6824713462432000,773,"S",97,493,"app",678
-6824713462177000,0,142000,6824713462319000,0,"R",120,"[NULL]","swapper",0
-6824713462319000,0,1790000,6824713464109000,644,"S",120,644,"ndroid.systemui",1664
-6824713462391000,1,75000,6824713462466000,771,"S",97,493,"DispSync",676
-6824713462432000,2,1186000,6824713463618000,0,"R",120,"[NULL]","swapper",0
-6824713462466000,1,2550000,6824713465016000,0,"R",120,"[NULL]","swapper",0
-6824713463232000,5,9000,6824713463241000,5,"S",120,5,"rcu_preempt",7
-6824713463241000,5,334000,6824713463575000,0,"R",120,"[NULL]","swapper",0
-6824713463575000,5,14000,6824713463589000,5,"S",120,5,"rcu_preempt",7
-6824713463589000,5,243000,6824713463832000,0,"R",120,"[NULL]","swapper",0
-6824713463618000,2,521000,6824713464139000,702,"S",120,702,"kworker/u16:7",19422
-6824713463764000,6,70000,6824713463834000,38,"S",120,38,"rcuop/4",44
-6824713463832000,5,5000,6824713463837000,5,"S",120,5,"rcu_preempt",7
-6824713463834000,6,2237000,6824713466071000,0,"R",120,"[NULL]","swapper",0
-6824713463837000,5,1034000,6824713464871000,0,"R",120,"[NULL]","swapper",0
-6824713464109000,0,488000,6824713464597000,0,"R",120,"[NULL]","swapper",0
-6824713464139000,2,5608000,6824713469747000,0,"R",120,"[NULL]","swapper",0
-6824713464149000,3,282000,6824713464431000,770,"S",120,493,"Binder:640_2",675
-6824713464431000,3,3478000,6824713467909000,0,"R",120,"[NULL]","swapper",0
-6824713464597000,0,172000,6824713464769000,773,"S",97,493,"app",678
-6824713464620000,7,27000,6824713464647000,2728,"S",120,739,"shell",20461
-6824713464647000,7,582000,6824713465229000,0,"R",120,"[NULL]","swapper",0
-6824713464769000,0,2190000,6824713466959000,0,"R",120,"[NULL]","swapper",0
-6824713464871000,5,85000,6824713464956000,739,"S",120,739,"adbd",20305
-6824713464956000,5,693000,6824713465649000,0,"R",120,"[NULL]","swapper",0
-6824713465016000,1,91000,6824713465107000,771,"S",97,493,"DispSync",676
-6824713465107000,1,1435000,6824713466542000,0,"R",120,"[NULL]","swapper",0
-6824713465229000,7,21000,6824713465250000,630,"S",100,630,"kworker/u17:1",1134
-6824713465250000,7,9000,6824713465259000,668,"S",120,668,"kworker/7:2",14813
-6824713465259000,7,10000,6824713465269000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713465269000,7,284000,6824713465553000,0,"R",120,"[NULL]","swapper",0
-6824713465553000,7,29000,6824713465582000,630,"S",100,630,"kworker/u17:1",1134
-6824713465582000,7,689000,6824713466271000,0,"R",120,"[NULL]","swapper",0
-6824713465649000,5,20000,6824713465669000,2728,"S",120,739,"shell",20461
-6824713465669000,5,418000,6824713466087000,0,"R",120,"[NULL]","swapper",0
-6824713466071000,6,16000,6824713466087000,39,"S",120,39,"rcuos/4",45
-6824713466080000,4,812000,6824713466892000,0,"R",120,"[NULL]","swapper",0
-6824713466087000,6,4893000,6824713470980000,0,"R",120,"[NULL]","swapper",0
-6824713466087000,5,8000,6824713466095000,6,"S",120,6,"rcu_sched",8
-6824713466095000,5,2929000,6824713469024000,0,"R",120,"[NULL]","swapper",0
-6824713466271000,7,37000,6824713466308000,630,"S",100,630,"kworker/u17:1",1134
-6824713466308000,7,8000,6824713466316000,668,"S",120,668,"kworker/7:2",14813
-6824713466316000,7,14000,6824713466330000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713466330000,7,308000,6824713466638000,0,"R",120,"[NULL]","swapper",0
-6824713466542000,1,3584000,6824713470126000,2721,"I",120,756,"sh",20462
-6824713466638000,7,28000,6824713466666000,630,"S",100,630,"kworker/u17:1",1134
-6824713466666000,7,11000,6824713466677000,668,"S",120,668,"kworker/7:2",14813
-6824713466677000,7,39000,6824713466716000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713466716000,7,622000,6824713467338000,0,"R",120,"[NULL]","swapper",0
-6824713466892000,4,113000,6824713467005000,739,"S",120,739,"adbd",20305
-6824713466959000,0,61000,6824713467020000,8,"S",120,8,"rcuop/0",10
-6824713467005000,4,1148000,6824713468153000,0,"R",120,"[NULL]","swapper",0
-6824713467020000,0,1748000,6824713468768000,0,"R",120,"[NULL]","swapper",0
-6824713467338000,7,249000,6824713467587000,483,"D",49,483,"sugov:4",606
-6824713467587000,7,70000,6824713467657000,630,"S",100,630,"kworker/u17:1",1134
-6824713467657000,7,50000,6824713467707000,668,"S",120,668,"kworker/7:2",14813
-6824713467707000,7,60000,6824713467767000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713467767000,7,9375000,6824713477142000,0,"R",120,"[NULL]","swapper",0
-6824713467909000,3,104000,6824713468013000,77,"S",120,77,"smem_native_rpm",87
-6824713468013000,3,1027000,6824713469040000,0,"R",120,"[NULL]","swapper",0
-6824713468153000,4,109000,6824713468262000,630,"R+",100,630,"kworker/u17:1",1134
-6824713468262000,4,82000,6824713468344000,483,"S",49,483,"sugov:4",606
-6824713468344000,4,36000,6824713468380000,716,"R",120,716,"kworker/4:1",19875
-6824713468380000,4,232000,6824713468612000,483,"D",49,483,"sugov:4",606
-6824713468612000,4,48000,6824713468660000,630,"S",100,630,"kworker/u17:1",1134
-6824713468660000,4,23000,6824713468683000,716,"S",120,716,"kworker/4:1",19875
-6824713468683000,4,29000,6824713468712000,0,"R",120,"[NULL]","swapper",0
-6824713468712000,4,53000,6824713468765000,630,"S",100,630,"kworker/u17:1",1134
-6824713468765000,4,18000,6824713468783000,716,"S",120,716,"kworker/4:1",19875
-6824713468768000,0,71000,6824713468839000,670,"S",100,670,"kworker/u17:2",14944
-6824713468783000,4,263000,6824713469046000,0,"R",120,"[NULL]","swapper",0
-6824713468839000,0,3202000,6824713472041000,0,"R",120,"[NULL]","swapper",0
-6824713469024000,5,45000,6824713469069000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713469040000,3,71000,6824713469111000,77,"S",120,77,"smem_native_rpm",87
-6824713469046000,4,43000,6824713469089000,739,"S",120,739,"adbd",20305
-6824713469069000,5,850000,6824713469919000,0,"R",120,"[NULL]","swapper",0
-6824713469089000,4,153000,6824713469242000,0,"R",120,"[NULL]","swapper",0
-6824713469111000,3,1771000,6824713470882000,0,"R",120,"[NULL]","swapper",0
-6824713469242000,4,14000,6824713469256000,483,"S",49,483,"sugov:4",606
-6824713469256000,4,2174000,6824713471430000,0,"R",120,"[NULL]","swapper",0
-6824713469747000,2,68000,6824713469815000,9,"S",120,9,"rcuos/0",11
-6824713469815000,2,281000,6824713470096000,0,"R",120,"[NULL]","swapper",0
-6824713469919000,5,7000,6824713469926000,6,"S",120,6,"rcu_sched",8
-6824713469926000,5,6000,6824713469932000,5,"S",120,5,"rcu_preempt",7
-6824713469932000,5,770000,6824713470702000,0,"R",120,"[NULL]","swapper",0
-6824713470096000,2,3770000,6824713473866000,2720,"I",120,755,"sh",20460
-6824713470126000,1,2368000,6824713472494000,0,"R",120,"[NULL]","swapper",0
-6824713470702000,5,43000,6824713470745000,5,"S",120,5,"rcu_preempt",7
-6824713470745000,5,381000,6824713471126000,0,"R",120,"[NULL]","swapper",0
-6824713470882000,3,62000,6824713470944000,24,"S",120,24,"rcuop/2",28
-6824713470944000,3,15328000,6824713486272000,0,"R",120,"[NULL]","swapper",0
-6824713470980000,6,109000,6824713471089000,38,"S",120,38,"rcuop/4",44
-6824713471089000,6,2971000,6824713474060000,0,"R",120,"[NULL]","swapper",0
-6824713471126000,5,89000,6824713471215000,2728,"S",120,739,"shell",20461
-6824713471215000,5,687000,6824713471902000,0,"R",120,"[NULL]","swapper",0
-6824713471430000,4,246000,6824713471676000,739,"S",120,739,"adbd",20305
-6824713471676000,4,2529000,6824713474205000,0,"R",120,"[NULL]","swapper",0
-6824713471902000,5,68000,6824713471970000,2728,"S",120,739,"shell",20461
-6824713471970000,5,263000,6824713472233000,0,"R",120,"[NULL]","swapper",0
-6824713472041000,0,131000,6824713472172000,670,"S",100,670,"kworker/u17:2",14944
-6824713472172000,0,119000,6824713472291000,743,"S",120,743,"kworker/0:5",20371
-6824713472233000,5,23000,6824713472256000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713472256000,5,537000,6824713472793000,0,"R",120,"[NULL]","swapper",0
-6824713472291000,0,508000,6824713472799000,0,"R",120,"[NULL]","swapper",0
-6824713472494000,1,96000,6824713472590000,670,"S",100,670,"kworker/u17:2",14944
-6824713472590000,1,47000,6824713472637000,0,"R",120,"[NULL]","swapper",0
-6824713472637000,1,100000,6824713472737000,670,"S",100,670,"kworker/u17:2",14944
-6824713472737000,1,105000,6824713472842000,693,"S",120,693,"kworker/1:1",18800
-6824713472793000,5,17000,6824713472810000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713472799000,0,61000,6824713472860000,670,"S",100,670,"kworker/u17:2",14944
-6824713472810000,5,299000,6824713473109000,0,"R",120,"[NULL]","swapper",0
-6824713472842000,1,2946000,6824713475788000,0,"R",120,"[NULL]","swapper",0
-6824713472860000,0,44000,6824713472904000,0,"R",120,"[NULL]","swapper",0
-6824713472904000,0,75000,6824713472979000,670,"S",100,670,"kworker/u17:2",14944
-6824713472979000,0,453000,6824713473432000,0,"R",120,"[NULL]","swapper",0
-6824713473109000,5,8000,6824713473117000,25,"S",120,25,"rcuos/2",29
-6824713473117000,5,861000,6824713473978000,0,"R",120,"[NULL]","swapper",0
-6824713473432000,0,106000,6824713473538000,670,"S",100,670,"kworker/u17:2",14944
-6824713473538000,0,135000,6824713473673000,743,"S",120,743,"kworker/0:5",20371
-6824713473673000,0,946000,6824713474619000,0,"R",120,"[NULL]","swapper",0
-6824713473866000,2,283000,6824713474149000,0,"R",120,"[NULL]","swapper",0
-6824713473978000,5,75000,6824713474053000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713474053000,5,975000,6824713475028000,0,"R",120,"[NULL]","swapper",0
-6824713474060000,6,244000,6824713474304000,2728,"I",120,739,"shell",20461
-6824713474149000,2,49000,6824713474198000,52,"S",120,52,"rcuop/6",60
-6824713474198000,2,596000,6824713474794000,0,"R",120,"[NULL]","swapper",0
-6824713474205000,4,149000,6824713474354000,739,"S",120,739,"adbd",20305
-6824713474304000,6,2488000,6824713476792000,0,"R",120,"[NULL]","swapper",0
-6824713474354000,4,1066000,6824713475420000,0,"R",120,"[NULL]","swapper",0
-6824713474619000,0,108000,6824713474727000,670,"S",100,670,"kworker/u17:2",14944
-6824713474727000,0,110000,6824713474837000,743,"S",120,743,"kworker/0:5",20371
-6824713474794000,2,81000,6824713474875000,670,"S",100,670,"kworker/u17:2",14944
-6824713474837000,0,521000,6824713475358000,0,"R",120,"[NULL]","swapper",0
-6824713474875000,2,189000,6824713475064000,0,"R",120,"[NULL]","swapper",0
-6824713475028000,5,13000,6824713475041000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713475041000,5,348000,6824713475389000,0,"R",120,"[NULL]","swapper",0
-6824713475064000,2,217000,6824713475281000,670,"S",100,670,"kworker/u17:2",14944
-6824713475281000,2,288000,6824713475569000,694,"S",120,694,"kworker/2:0",18823
-6824713475358000,0,96000,6824713475454000,670,"S",100,670,"kworker/u17:2",14944
-6824713475389000,5,10000,6824713475399000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713475399000,5,31000,6824713475430000,0,"R",120,"[NULL]","swapper",0
-6824713475420000,4,11000,6824713475431000,630,"S",100,630,"kworker/u17:1",1134
-6824713475430000,5,7000,6824713475437000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713475431000,4,340000,6824713475771000,0,"R",120,"[NULL]","swapper",0
-6824713475437000,5,75000,6824713475512000,0,"R",120,"[NULL]","swapper",0
-6824713475454000,0,114000,6824713475568000,743,"S",120,743,"kworker/0:5",20371
-6824713475512000,5,39000,6824713475551000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713475551000,5,1067000,6824713476618000,0,"R",120,"[NULL]","swapper",0
-6824713475568000,0,10190000,6824713485758000,0,"R",120,"[NULL]","swapper",0
-6824713475569000,2,10187000,6824713485756000,0,"R",120,"[NULL]","swapper",0
-6824713475771000,4,98000,6824713475869000,739,"S",120,739,"adbd",20305
-6824713475788000,1,89000,6824713475877000,670,"S",100,670,"kworker/u17:2",14944
-6824713475869000,4,1395000,6824713477264000,0,"R",120,"[NULL]","swapper",0
-6824713475877000,1,621000,6824713476498000,0,"R",120,"[NULL]","swapper",0
-6824713476498000,1,200000,6824713476698000,670,"S",100,670,"kworker/u17:2",14944
-6824713476618000,5,8000,6824713476626000,5,"S",120,5,"rcu_preempt",7
-6824713476626000,5,41000,6824713476667000,702,"S",120,702,"kworker/u16:7",19422
-6824713476667000,5,361000,6824713477028000,0,"R",120,"[NULL]","swapper",0
-6824713476698000,1,154000,6824713476852000,693,"S",120,693,"kworker/1:1",18800
-6824713476792000,6,30000,6824713476822000,6,"S",120,6,"rcu_sched",8
-6824713476822000,6,7677000,6824713484499000,0,"R",120,"[NULL]","swapper",0
-6824713476852000,1,9339000,6824713486191000,0,"R",120,"[NULL]","swapper",0
-6824713477028000,5,42000,6824713477070000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713477070000,5,7334000,6824713484404000,0,"R",120,"[NULL]","swapper",0
-6824713477142000,7,19000,6824713477161000,39,"S",120,39,"rcuos/4",45
-6824713477161000,7,61280000,6824713538441000,0,"R",120,"[NULL]","swapper",0
-6824713477264000,4,40000,6824713477304000,739,"S",120,739,"adbd",20305
-6824713477304000,4,31231000,6824713508535000,0,"R",120,"[NULL]","swapper",0
-6824713484404000,5,44000,6824713484448000,5,"S",120,5,"rcu_preempt",7
-6824713484448000,5,365000,6824713484813000,0,"R",120,"[NULL]","swapper",0
-6824713484499000,6,23000,6824713484522000,6,"S",120,6,"rcu_sched",8
-6824713484522000,6,6802000,6824713491324000,0,"R",120,"[NULL]","swapper",0
-6824713484813000,5,36000,6824713484849000,25,"S",120,25,"rcuos/2",29
-6824713484849000,5,6226000,6824713491075000,0,"R",120,"[NULL]","swapper",0
-6824713485756000,2,159000,6824713485915000,9,"S",120,9,"rcuos/0",11
-6824713485758000,0,157000,6824713485915000,8,"S",120,8,"rcuop/0",10
-6824713485915000,2,6523000,6824713492438000,0,"R",120,"[NULL]","swapper",0
-6824713485915000,0,9244000,6824713495159000,0,"R",120,"[NULL]","swapper",0
-6824713486191000,1,100000,6824713486291000,17,"S",120,17,"rcuop/1",20
-6824713486272000,3,94000,6824713486366000,18,"S",120,18,"rcuos/1",21
-6824713486291000,1,9985000,6824713496276000,0,"R",120,"[NULL]","swapper",0
-6824713486366000,3,6074000,6824713492440000,0,"R",120,"[NULL]","swapper",0
-6824713491075000,5,58000,6824713491133000,5,"S",120,5,"rcu_preempt",7
-6824713491133000,5,6463000,6824713497596000,0,"R",120,"[NULL]","swapper",0
-6824713491324000,6,54000,6824713491378000,38,"S",120,38,"rcuop/4",44
-6824713491378000,6,47434000,6824713538812000,0,"R",120,"[NULL]","swapper",0
-6824713492438000,2,218000,6824713492656000,52,"S",120,52,"rcuop/6",60
-6824713492440000,3,215000,6824713492655000,24,"S",120,24,"rcuop/2",28
-6824713492655000,3,6627000,6824713499282000,0,"R",120,"[NULL]","swapper",0
-6824713492656000,2,2845000,6824713495501000,0,"R",120,"[NULL]","swapper",0
-6824713495159000,0,143000,6824713495302000,743,"S",120,743,"kworker/0:5",20371
-6824713495302000,0,61000,6824713495363000,0,"R",120,"[NULL]","swapper",0
-6824713495363000,0,62000,6824713495425000,3,"S",120,3,"ksoftirqd/0",3
-6824713495425000,0,586000,6824713496011000,0,"R",120,"[NULL]","swapper",0
-6824713495501000,2,575000,6824713496076000,786,"S",111,494,"SDM_EventThread",685
-6824713496011000,0,264000,6824713496275000,771,"S",97,493,"DispSync",676
-6824713496076000,2,458000,6824713496534000,0,"R",120,"[NULL]","swapper",0
-6824713496275000,0,505000,6824713496780000,0,"R",120,"[NULL]","swapper",0
-6824713496276000,1,516000,6824713496792000,777,"S",120,493,"HwBinder:640_1",721
-6824713496534000,2,458000,6824713496992000,773,"S",97,493,"app",678
-6824713496780000,0,101000,6824713496881000,771,"S",97,493,"DispSync",676
-6824713496792000,1,472000,6824713497264000,0,"R",120,"[NULL]","swapper",0
-6824713496881000,0,83000,6824713496964000,0,"R",120,"[NULL]","swapper",0
-6824713496964000,0,65000,6824713497029000,771,"S",97,493,"DispSync",676
-6824713496992000,2,10168000,6824713507160000,0,"R",120,"[NULL]","swapper",0
-6824713497029000,0,2730000,6824713499759000,0,"R",120,"[NULL]","swapper",0
-6824713497264000,1,2038000,6824713499302000,644,"S",120,644,"ndroid.systemui",1664
-6824713497596000,5,25000,6824713497621000,5,"S",120,5,"rcu_preempt",7
-6824713497621000,5,6805000,6824713504426000,0,"R",120,"[NULL]","swapper",0
-6824713499282000,3,328000,6824713499610000,770,"S",120,493,"Binder:640_2",675
-6824713499302000,1,572000,6824713499874000,0,"R",120,"[NULL]","swapper",0
-6824713499610000,3,7250000,6824713506860000,0,"R",120,"[NULL]","swapper",0
-6824713499759000,0,267000,6824713500026000,773,"S",97,493,"app",678
-6824713499874000,1,154000,6824713500028000,771,"S",97,493,"DispSync",676
-6824713500026000,0,6835000,6824713506861000,0,"R",120,"[NULL]","swapper",0
-6824713500028000,1,7524000,6824713507552000,0,"R",120,"[NULL]","swapper",0
-6824713504426000,5,314000,6824713504740000,483,"D",49,483,"sugov:4",606
-6824713504740000,5,82000,6824713504822000,5,"S",120,5,"rcu_preempt",7
-6824713504822000,5,26596000,6824713531418000,0,"R",120,"[NULL]","swapper",0
-6824713506860000,3,291000,6824713507151000,77,"S",120,77,"smem_native_rpm",87
-6824713506861000,0,290000,6824713507151000,8,"S",120,8,"rcuop/0",10
-6824713507151000,3,22498000,6824713529649000,0,"R",120,"[NULL]","swapper",0
-6824713507151000,0,1456000,6824713508607000,0,"R",120,"[NULL]","swapper",0
-6824713507160000,2,99000,6824713507259000,22,"S",120,22,"ksoftirqd/2",25
-6824713507259000,2,10658000,6824713517917000,0,"R",120,"[NULL]","swapper",0
-6824713507552000,1,436000,6824713507988000,17,"S",120,17,"rcuop/1",20
-6824713507988000,1,16424000,6824713524412000,0,"R",120,"[NULL]","swapper",0
-6824713508535000,4,250000,6824713508785000,483,"S",49,483,"sugov:4",606
-6824713508607000,0,56000,6824713508663000,8,"S",120,8,"rcuop/0",10
-6824713508663000,0,4135000,6824713512798000,0,"R",120,"[NULL]","swapper",0
-6824713508785000,4,35595000,6824713544380000,0,"R",120,"[NULL]","swapper",0
-6824713512798000,0,237000,6824713513035000,5,"S",120,5,"rcu_preempt",7
-6824713513035000,0,4264000,6824713517299000,0,"R",120,"[NULL]","swapper",0
-6824713517299000,0,410000,6824713517709000,5,"S",120,5,"rcu_preempt",7
-6824713517709000,0,229000,6824713517938000,24,"S",120,24,"rcuop/2",28
-6824713517917000,2,73000,6824713517990000,31,"S",120,31,"rcuop/3",36
-6824713517938000,0,144000,6824713518082000,38,"S",120,38,"rcuop/4",44
-6824713517990000,2,147000,6824713518137000,52,"S",120,52,"rcuop/6",60
-6824713518082000,0,5664000,6824713523746000,0,"R",120,"[NULL]","swapper",0
-6824713518137000,2,83000,6824713518220000,45,"S",120,45,"rcuop/5",52
-6824713518220000,2,10550000,6824713528770000,0,"R",120,"[NULL]","swapper",0
-6824713523746000,0,88000,6824713523834000,5,"S",120,5,"rcu_preempt",7
-6824713523834000,0,154000,6824713523988000,8,"R+",120,8,"rcuop/0",10
-6824713523988000,0,28000,6824713524016000,5,"S",120,5,"rcu_preempt",7
-6824713524016000,0,43000,6824713524059000,8,"S",120,8,"rcuop/0",10
-6824713524059000,0,4757000,6824713528816000,0,"R",120,"[NULL]","swapper",0
-6824713524412000,1,87000,6824713524499000,17,"S",120,17,"rcuop/1",20
-6824713524499000,1,4727000,6824713529226000,0,"R",120,"[NULL]","swapper",0
-6824713528770000,2,179000,6824713528949000,22,"S",120,22,"ksoftirqd/2",25
-6824713528816000,0,175000,6824713528991000,743,"S",120,743,"kworker/0:5",20371
-6824713528949000,2,1466000,6824713530415000,786,"S",111,494,"SDM_EventThread",685
-6824713528991000,0,531000,6824713529522000,702,"R+",120,702,"kworker/u16:7",19422
-6824713529226000,1,134000,6824713529360000,670,"S",100,670,"kworker/u17:2",14944
-6824713529360000,1,961000,6824713530321000,0,"R",120,"[NULL]","swapper",0
-6824713529522000,0,135000,6824713529657000,670,"S",100,670,"kworker/u17:2",14944
-6824713529649000,3,475000,6824713530124000,771,"S",97,493,"DispSync",676
-6824713529657000,0,56000,6824713529713000,743,"R+",120,743,"kworker/0:5",20371
-6824713529713000,0,55000,6824713529768000,670,"S",100,670,"kworker/u17:2",14944
-6824713529768000,0,119000,6824713529887000,743,"R+",120,743,"kworker/0:5",20371
-6824713529887000,0,214000,6824713530101000,670,"S",100,670,"kworker/u17:2",14944
-6824713530101000,0,105000,6824713530206000,743,"S",120,743,"kworker/0:5",20371
-6824713530124000,3,93000,6824713530217000,77,"S",120,77,"smem_native_rpm",87
-6824713530206000,0,40000,6824713530246000,5,"S",120,5,"rcu_preempt",7
-6824713530217000,3,33925000,6824713564142000,0,"R",120,"[NULL]","swapper",0
-6824713530246000,0,81000,6824713530327000,702,"S",120,702,"kworker/u16:7",19422
-6824713530321000,1,505000,6824713530826000,773,"S",97,493,"app",678
-6824713530327000,0,1013000,6824713531340000,0,"R",120,"[NULL]","swapper",0
-6824713530415000,2,1002000,6824713531417000,0,"R",120,"[NULL]","swapper",0
-6824713530826000,1,558000,6824713531384000,777,"S",120,493,"HwBinder:640_1",721
-6824713531340000,0,2759000,6824713534099000,644,"S",120,644,"ndroid.systemui",1664
-6824713531384000,1,2683000,6824713534067000,0,"R",120,"[NULL]","swapper",0
-6824713531417000,2,89000,6824713531506000,771,"S",97,493,"DispSync",676
-6824713531418000,5,849000,6824713532267000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713531506000,2,8373000,6824713539879000,0,"R",120,"[NULL]","swapper",0
-6824713532267000,5,3668000,6824713535935000,739,"S",120,739,"adbd",20305
-6824713534067000,1,310000,6824713534377000,770,"S",120,493,"Binder:640_2",675
-6824713534099000,0,433000,6824713534532000,0,"R",120,"[NULL]","swapper",0
-6824713534377000,1,510000,6824713534887000,0,"R",120,"[NULL]","swapper",0
-6824713534532000,0,188000,6824713534720000,773,"S",97,493,"app",678
-6824713534720000,0,2286000,6824713537006000,0,"R",120,"[NULL]","swapper",0
-6824713534887000,1,85000,6824713534972000,771,"S",97,493,"DispSync",676
-6824713534972000,1,29038000,6824713564010000,0,"R",120,"[NULL]","swapper",0
-6824713535935000,5,3107000,6824713539042000,2736,"R+",120,763,"sh",20465
-6824713537006000,0,74000,6824713537080000,5,"S",120,5,"rcu_preempt",7
-6824713537080000,0,59000,6824713537139000,8,"S",120,8,"rcuop/0",10
-6824713537139000,0,2739000,6824713539878000,0,"R",120,"[NULL]","swapper",0
-6824713538441000,7,113000,6824713538554000,39,"S",120,39,"rcuos/4",45
-6824713538554000,7,5437000,6824713543991000,0,"R",120,"[NULL]","swapper",0
-6824713538812000,6,55000,6824713538867000,6,"S",120,6,"rcu_sched",8
-6824713538867000,6,4782000,6824713543649000,0,"R",120,"[NULL]","swapper",0
-6824713539042000,5,1123000,6824713540165000,739,"S",120,739,"adbd",20305
-6824713539878000,0,278000,6824713540156000,38,"R+",120,38,"rcuop/4",44
-6824713539879000,2,332000,6824713540211000,145,"S",120,145,"hwrng",215
-6824713540156000,0,139000,6824713540295000,670,"S",100,670,"kworker/u17:2",14944
-6824713540165000,5,271000,6824713540436000,2736,"R+",120,763,"sh",20465
-6824713540211000,2,1202000,6824713541413000,0,"R",120,"[NULL]","swapper",0
-6824713540295000,0,37000,6824713540332000,5,"S",120,5,"rcu_preempt",7
-6824713540332000,0,118000,6824713540450000,743,"S",120,743,"kworker/0:5",20371
-6824713540436000,5,70000,6824713540506000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713540450000,0,46000,6824713540496000,38,"S",120,38,"rcuop/4",44
-6824713540496000,0,316000,6824713540812000,0,"R",120,"[NULL]","swapper",0
-6824713540506000,5,886000,6824713541392000,2736,"R",120,763,"sh",20465
-6824713540812000,0,76000,6824713540888000,670,"S",100,670,"kworker/u17:2",14944
-6824713540888000,0,6183000,6824713547071000,0,"R",120,"[NULL]","swapper",0
-6824713541392000,5,115000,6824713541507000,670,"S",100,670,"kworker/u17:2",14944
-6824713541413000,2,46000,6824713541459000,145,"S",120,145,"hwrng",215
-6824713541459000,2,6115000,6824713547574000,0,"R",120,"[NULL]","swapper",0
-6824713541507000,5,68000,6824713541575000,697,"R+",120,697,"kworker/5:2",19092
-6824713541575000,5,59000,6824713541634000,670,"S",100,670,"kworker/u17:2",14944
-6824713541634000,5,105000,6824713541739000,697,"S",120,697,"kworker/5:2",19092
-6824713541739000,5,246000,6824713541985000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713541985000,5,354000,6824713542339000,739,"R+",120,739,"adbd",20305
-6824713542339000,5,29000,6824713542368000,670,"S",100,670,"kworker/u17:2",14944
-6824713542368000,5,84000,6824713542452000,739,"S",120,739,"adbd",20305
-6824713542452000,5,329000,6824713542781000,2736,"R+",120,763,"sh",20465
-6824713542781000,5,61000,6824713542842000,670,"S",100,670,"kworker/u17:2",14944
-6824713542842000,5,68000,6824713542910000,697,"S",120,697,"kworker/5:2",19092
-6824713542910000,5,36000,6824713542946000,2487,"S",120,739,"UsbFfs-worker",20308
-6824713542946000,5,4105000,6824713547051000,2736,"R",120,763,"sh",20465
-6824713543649000,6,83000,6824713543732000,6,"S",120,6,"rcu_sched",8
-6824713543732000,6,730000,6824713544462000,0,"R",120,"[NULL]","swapper",0
-6824713543991000,7,134000,6824713544125000,39,"S",120,39,"rcuos/4",45
-6824713544125000,7,6499000,6824713550624000,0,"R",120,"[NULL]","swapper",0
-6824713544380000,4,97000,6824713544477000,46,"S",120,46,"rcuos/5",53
-6824713544462000,6,45000,6824713544507000,6,"S",120,6,"rcu_sched",8
-6824713544477000,4,6494000,6824713550971000,0,"R",120,"[NULL]","swapper",0
-6824713544507000,6,5784000,6824713550291000,0,"R",120,"[NULL]","swapper",0
-6824713547051000,5,95000,6824713547146000,5,"S",120,5,"rcu_preempt",7
-6824713547071000,0,137000,6824713547208000,1920,"S",120,667,"Executor-7",14763
-6824713547146000,5,228000,6824713547374000,2737,"R",120,739,"shell",20466
-6824713547208000,0,181000,6824713547389000,38,"S",120,38,"rcuop/4",44
-6824713547374000,5,21000,6824713547395000,5,"S",120,5,"rcu_preempt",7
-6824713547389000,0,13607000,6824713560996000,0,"R",120,"[NULL]","swapper",0
-6824713547395000,5,225000,6824713547620000,2737,"S",120,739,"shell",20466
-6824713547574000,2,56000,6824713547630000,45,"S",120,45,"rcuop/5",52
-6824713547620000,5,5690000,6824713553310000,2736,"R",120,763,"sh",20465
-6824713547630000,2,46000,6824713547676000,145,"S",120,145,"hwrng",215
-6824713547676000,2,15043000,6824713562719000,0,"R",120,"[NULL]","swapper",0
-6824713550291000,6,80000,6824713550371000,6,"S",120,6,"rcu_sched",8
-6824713550371000,6,24532000,6824713574903000,0,"R",120,"[NULL]","swapper",0
-6824713550624000,7,88000,6824713550712000,39,"S",120,39,"rcuos/4",45
-6824713550712000,7,23645000,6824713574357000,0,"R",120,"[NULL]","swapper",0
-6824713550971000,4,48000,6824713551019000,46,"S",120,46,"rcuos/5",53
-6824713551019000,4,14066000,6824713565085000,0,"R",120,"[NULL]","swapper",0
-6824713553310000,5,86000,6824713553396000,5,"S",120,5,"rcu_preempt",7
-6824713553396000,5,69000,6824713553465000,38,"S",120,38,"rcuop/4",44
-6824713553465000,5,36000,6824713553501000,45,"S",120,45,"rcuop/5",52
-6824713553501000,5,6486000,6824713559987000,2736,"R",120,763,"sh",20465
-6824713559987000,5,57000,6824713560044000,697,"S",120,697,"kworker/5:2",19092
-6824713560044000,5,2577000,6824713562621000,2736,"R+",120,763,"sh",20465
-6824713560996000,0,1098000,6824713562094000,943,"D",100,563,"FileWatcherThre",908
-6824713562094000,0,235000,6824713562329000,743,"S",120,743,"kworker/0:5",20371
-6824713562329000,0,966000,6824713563295000,0,"R",120,"[NULL]","swapper",0
-6824713562621000,5,180000,6824713562801000,483,"S",49,483,"sugov:4",606
-6824713562719000,2,997000,6824713563716000,786,"S",111,494,"SDM_EventThread",685
-6824713562801000,5,33000,6824713562834000,38,"S",120,38,"rcuop/4",44
-6824713562834000,5,14000,6824713562848000,5,"S",120,5,"rcu_preempt",7
-6824713562848000,5,3776000,6824713566624000,2736,"R",120,763,"sh",20465
-6824713563295000,0,346000,6824713563641000,771,"S",97,493,"DispSync",676
-6824713563641000,0,888000,6824713564529000,702,"S",120,702,"kworker/u16:7",19422
-6824713563716000,2,72000,6824713563788000,145,"S",120,145,"hwrng",215
-6824713563788000,2,972000,6824713564760000,0,"R",120,"[NULL]","swapper",0
-6824713564010000,1,574000,6824713564584000,777,"S",120,493,"HwBinder:640_1",721
-6824713564142000,3,453000,6824713564595000,773,"S",97,493,"app",678
-6824713564529000,0,91000,6824713564620000,743,"S",120,743,"kworker/0:5",20371
-6824713564584000,1,2497000,6824713567081000,0,"R",120,"[NULL]","swapper",0
-6824713564595000,3,3222000,6824713567817000,644,"S",120,644,"ndroid.systemui",1664
-6824713564620000,0,1978000,6824713566598000,0,"R",120,"[NULL]","swapper",0
-6824713564760000,2,90000,6824713564850000,771,"S",97,493,"DispSync",676
-6824713564850000,2,3091000,6824713567941000,0,"R",120,"[NULL]","swapper",0
-6824713565085000,4,514000,6824713565599000,943,"D",100,563,"FileWatcherThre",908
-6824713565599000,4,22373000,6824713587972000,0,"R",120,"[NULL]","swapper",0
-6824713566598000,0,117000,6824713566715000,743,"S",120,743,"kworker/0:5",20371
-6824713566624000,5,23000,6824713566647000,5,"S",120,5,"rcu_preempt",7
-6824713566647000,5,2458000,6824713569105000,2736,"S",120,763,"sh",20465
-6824713566715000,0,1121000,6824713567836000,0,"R",120,"[NULL]","swapper",0
-6824713567081000,1,530000,6824713567611000,943,"S",100,563,"FileWatcherThre",908
-6824713567611000,1,1518000,6824713569129000,0,"R",120,"[NULL]","swapper",0
-6824713567817000,3,13943000,6824713581760000,0,"R",120,"[NULL]","swapper",0
-6824713567836000,0,68000,6824713567904000,8,"S",120,8,"rcuop/0",10
-6824713567904000,0,700000,6824713568604000,0,"R",120,"[NULL]","swapper",0
-6824713567941000,2,390000,6824713568331000,770,"S",120,493,"Binder:640_2",675
-6824713568331000,2,4718000,6824713573049000,0,"R",120,"[NULL]","swapper",0
-6824713568604000,0,218000,6824713568822000,773,"S",97,493,"app",678
-6824713568822000,0,11756000,6824713580578000,0,"R",120,"[NULL]","swapper",0
-6824713569105000,5,4189000,6824713573294000,2738,"R+",120,764,"atrace",20467
-6824713569129000,1,107000,6824713569236000,771,"S",97,493,"DispSync",676
-6824713569236000,1,12634000,6824713581870000,0,"R",120,"[NULL]","swapper",0
-6824713573049000,2,113000,6824713573162000,145,"S",120,145,"hwrng",215
-6824713573162000,2,2555000,6824713575717000,0,"R",120,"[NULL]","swapper",0
-6824713573294000,5,49000,6824713573343000,5,"S",120,5,"rcu_preempt",7
-6824713573343000,5,37000,6824713573380000,38,"S",120,38,"rcuop/4",44
-6824713573380000,5,23000,6824713573403000,45,"S",120,45,"rcuop/5",52
-6824713573403000,5,6607000,6824713580010000,2738,"R+",120,764,"atrace",20467
-6824713574357000,7,104000,6824713574461000,39,"S",120,39,"rcuos/4",45
-6824713574461000,7,12988000,6824713587449000,0,"R",120,"[NULL]","swapper",0
-6824713574903000,6,48000,6824713574951000,6,"S",120,6,"rcu_sched",8
-6824713574951000,6,5495000,6824713580446000,0,"R",120,"[NULL]","swapper",0
-6824713575717000,2,111000,6824713575828000,145,"S",120,145,"hwrng",215
-6824713575828000,2,22002000,6824713597830000,0,"R",120,"[NULL]","swapper",0
-6824713580010000,5,60000,6824713580070000,5,"S",120,5,"rcu_preempt",7
-6824713580070000,5,3250000,6824713583320000,2738,"R+",120,764,"atrace",20467
-6824713580446000,6,32000,6824713580478000,6,"S",120,6,"rcu_sched",8
-6824713580478000,6,6544000,6824713587022000,0,"R",120,"[NULL]","swapper",0
-6824713580578000,0,647000,6824713581225000,702,"D",120,702,"kworker/u16:7",19422
-6824713581225000,0,158000,6824713581383000,8,"S",120,8,"rcuop/0",10
-6824713581383000,0,892000,6824713582275000,0,"R",120,"[NULL]","swapper",0
-6824713581760000,3,187000,6824713581947000,77,"S",120,77,"smem_native_rpm",87
-6824713581870000,1,91000,6824713581961000,17,"S",120,17,"rcuop/1",20
-6824713581947000,3,16557000,6824713598504000,0,"R",120,"[NULL]","swapper",0
-6824713581961000,1,15601000,6824713597562000,0,"R",120,"[NULL]","swapper",0
-6824713582275000,0,89000,6824713582364000,702,"S",120,702,"kworker/u16:7",19422
-6824713582364000,0,14442000,6824713596806000,0,"R",120,"[NULL]","swapper",0
-6824713583320000,5,148000,6824713583468000,483,"S",49,483,"sugov:4",606
-6824713583468000,5,3138000,6824713586606000,2738,"R",120,764,"atrace",20467
-6824713586606000,5,29000,6824713586635000,5,"S",120,5,"rcu_preempt",7
-6824713586635000,5,43000,6824713586678000,38,"S",120,38,"rcuop/4",44
-6824713586678000,5,94000,6824713586772000,45,"S",120,45,"rcuop/5",52
-6824713586772000,5,8000,6824713586780000,5,"S",120,5,"rcu_preempt",7
-6824713586780000,5,6480000,6824713593260000,2738,"R",120,764,"atrace",20467
-6824713587022000,6,46000,6824713587068000,6,"S",120,6,"rcu_sched",8
-6824713587068000,6,1013000,6824713588081000,0,"R",120,"[NULL]","swapper",0
-6824713587449000,7,83000,6824713587532000,39,"S",120,39,"rcuos/4",45
-6824713587532000,7,6610000,6824713594142000,0,"R",120,"[NULL]","swapper",0
-6824713587972000,4,51000,6824713588023000,46,"S",120,46,"rcuos/5",53
-6824713588023000,4,6549000,6824713594572000,0,"R",120,"[NULL]","swapper",0
-6824713588081000,6,24000,6824713588105000,6,"S",120,6,"rcu_sched",8
-6824713588105000,6,5555000,6824713593660000,0,"R",120,"[NULL]","swapper",0
-6824713593260000,5,24000,6824713593284000,5,"S",120,5,"rcu_preempt",7
-6824713593284000,5,18000,6824713593302000,38,"S",120,38,"rcuop/4",44
-6824713593302000,5,19000,6824713593321000,45,"S",120,45,"rcuop/5",52
-6824713593321000,5,9953000,6824713603274000,2738,"R",120,764,"atrace",20467
-6824713593660000,6,42000,6824713593702000,6,"S",120,6,"rcu_sched",8
-6824713593702000,6,41271000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713594142000,7,54000,6824713594196000,39,"S",120,39,"rcuos/4",45
-6824713594196000,7,40777000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713594572000,4,31000,6824713594603000,46,"S",120,46,"rcuos/5",53
-6824713594603000,4,40370000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713596806000,0,434000,6824713597240000,771,"S",97,493,"DispSync",676
-6824713597240000,0,240000,6824713597480000,743,"S",120,743,"kworker/0:5",20371
-6824713597480000,0,864000,6824713598344000,0,"R",120,"[NULL]","swapper",0
-6824713597562000,1,518000,6824713598080000,773,"S",97,493,"app",678
-6824713597830000,2,805000,6824713598635000,786,"S",111,494,"SDM_EventThread",685
-6824713598080000,1,765000,6824713598845000,0,"R",120,"[NULL]","swapper",0
-6824713598344000,0,3217000,6824713601561000,644,"S",120,644,"ndroid.systemui",1664
-6824713598504000,3,105000,6824713598609000,771,"S",97,493,"DispSync",676
-6824713598609000,3,32422000,6824713631031000,0,"R",120,"[NULL]","swapper",0
-6824713598635000,2,932000,6824713599567000,0,"R",120,"[NULL]","swapper",0
-6824713598845000,1,556000,6824713599401000,777,"S",120,493,"HwBinder:640_1",721
-6824713599401000,1,2173000,6824713601574000,0,"R",120,"[NULL]","swapper",0
-6824713599567000,2,90000,6824713599657000,771,"S",97,493,"DispSync",676
-6824713599657000,2,23565000,6824713623222000,0,"R",120,"[NULL]","swapper",0
-6824713601561000,0,678000,6824713602239000,0,"R",120,"[NULL]","swapper",0
-6824713601574000,1,395000,6824713601969000,770,"S",120,493,"Binder:640_2",675
-6824713601969000,1,395000,6824713602364000,0,"R",120,"[NULL]","swapper",0
-6824713602239000,0,209000,6824713602448000,773,"S",97,493,"app",678
-6824713602364000,1,79000,6824713602443000,771,"S",97,493,"DispSync",676
-6824713602443000,1,27933000,6824713630376000,0,"R",120,"[NULL]","swapper",0
-6824713602448000,0,26982000,6824713629430000,0,"R",120,"[NULL]","swapper",0
-6824713603274000,5,115000,6824713603389000,483,"S",49,483,"sugov:4",606
-6824713603389000,5,17861000,6824713621250000,2738,"R+",120,764,"atrace",20467
-6824713621250000,5,138000,6824713621388000,483,"S",49,483,"sugov:4",606
-6824713621388000,5,35000,6824713621423000,38,"S",120,38,"rcuop/4",44
-6824713621423000,5,19000,6824713621442000,5,"S",120,5,"rcu_preempt",7
-6824713621442000,5,5171000,6824713626613000,2738,"R",120,764,"atrace",20467
-6824713623222000,2,232000,6824713623454000,145,"S",120,145,"hwrng",215
-6824713623454000,2,5577000,6824713629031000,0,"R",120,"[NULL]","swapper",0
-6824713626613000,5,45000,6824713626658000,5,"S",120,5,"rcu_preempt",7
-6824713626658000,5,26000,6824713626684000,38,"S",120,38,"rcuop/4",44
-6824713626684000,5,21000,6824713626705000,45,"S",120,45,"rcuop/5",52
-6824713626705000,5,6000,6824713626711000,5,"S",120,5,"rcu_preempt",7
-6824713626711000,5,282000,6824713626993000,2738,"S",120,764,"atrace",20467
-6824713626993000,5,7817000,6824713634810000,0,"R",120,"[NULL]","swapper",0
-6824713629031000,2,2744000,6824713631775000,479,"R+",120,479,"hwservicemanage",602
-6824713629430000,0,258000,6824713629688000,743,"S",120,743,"kworker/0:5",20371
-6824713629688000,0,932000,6824713630620000,786,"R+",111,494,"SDM_EventThread",685
-6824713630376000,1,388000,6824713630764000,771,"S",97,493,"DispSync",676
-6824713630620000,0,466000,6824713631086000,773,"S",97,493,"app",678
-6824713630764000,1,886000,6824713631650000,0,"R",120,"[NULL]","swapper",0
-6824713631031000,3,505000,6824713631536000,777,"S",120,493,"HwBinder:640_1",721
-6824713631086000,0,116000,6824713631202000,702,"S",120,702,"kworker/u16:7",19422
-6824713631202000,0,181000,6824713631383000,786,"S",111,494,"SDM_EventThread",685
-6824713631383000,0,2291000,6824713633674000,0,"R",120,"[NULL]","swapper",0
-6824713631536000,3,3437000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713631650000,1,63000,6824713631713000,771,"S",97,493,"DispSync",676
-6824713631713000,1,1737000,6824713633450000,644,"S",120,644,"ndroid.systemui",1664
-6824713631775000,2,255000,6824713632030000,482,"S",49,482,"sugov:0",605
-6824713632030000,2,108000,6824713632138000,479,"S",120,479,"hwservicemanage",602
-6824713632138000,2,437000,6824713632575000,2738,"R+",120,764,"atrace",20467
-6824713632575000,2,334000,6824713632909000,479,"S",120,479,"hwservicemanage",602
-6824713632909000,2,263000,6824713633172000,2738,"R+",120,764,"atrace",20467
-6824713633172000,2,340000,6824713633512000,489,"S",120,489,"atrace@1.0-serv",635
-6824713633450000,1,1179000,6824713634629000,0,"R",120,"[NULL]","swapper",0
-6824713633512000,2,169000,6824713633681000,2738,"R+",120,764,"atrace",20467
-6824713633674000,0,213000,6824713633887000,770,"S",120,493,"Binder:640_2",675
-6824713633681000,2,75000,6824713633756000,489,"S",120,489,"atrace@1.0-serv",635
-6824713633756000,2,1217000,6824713634973000,2738,"R",120,764,"atrace",20467
-6824713633887000,0,1086000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713634629000,1,131000,6824713634760000,773,"S",97,493,"app",678
-6824713634760000,1,213000,6824713634973000,0,"R",120,"[NULL]","swapper",0
-6824713634810000,5,70000,6824713634880000,5,"S",120,5,"rcu_preempt",7
-6824713634880000,5,39000,6824713634919000,38,"S",120,38,"rcuop/4",44
-6824713634919000,5,54000,6824713634973000,45,"S",120,45,"rcuop/5",52
-6824713634973000,5,0,6824713634973000,0,"R",120,"[NULL]","swapper",0
diff --git a/test/trace_processor/parsing/thread_counter_and_track.sql b/test/trace_processor/parsing/thread_counter_and_track.sql
deleted file mode 100644
index 24f3d81..0000000
--- a/test/trace_processor/parsing/thread_counter_and_track.sql
+++ /dev/null
@@ -1,5 +0,0 @@
-select ts, t.name, value, tid
-from counter c
-join thread_counter_track t on c.track_id = t.id
-join thread using (utid)
-order by ts;
\ No newline at end of file
diff --git a/test/trace_processor/parsing/thread_time_in_state.out b/test/trace_processor/parsing/thread_time_in_state.out
deleted file mode 100644
index 10275e1..0000000
--- a/test/trace_processor/parsing/thread_time_in_state.out
+++ /dev/null
@@ -1,16 +0,0 @@
-"ts","tid","cpu","freq","time_ms"
-2,5,0,100000,10
-2,5,0,200000,10
-3,5,0,100000,20
-3,5,0,200000,10
-3,7,2,1000000,10
-3,11,2,2000000,10
-3,12,2,2000000,10
-4,5,0,200000,20
-4,11,2,2000000,20
-4,12,2,2000000,20
-5,17,0,100000,10
-5,17,0,200000,10
-5,17,2,1000000,0
-5,17,2,2000000,0
-6,17,0,100000,20
diff --git a/test/trace_processor/parsing/thread_time_in_state.sql b/test/trace_processor/parsing/thread_time_in_state.sql
deleted file mode 100644
index 1848149..0000000
--- a/test/trace_processor/parsing/thread_time_in_state.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-SELECT
-  ts,
-  tid,
-  EXTRACT_ARG(counter.arg_set_id, 'time_in_state_cpu_id') AS cpu,
-  EXTRACT_ARG(counter.arg_set_id, 'freq') AS freq,
-  CAST(value AS INT) time_ms
-FROM counter
-JOIN thread_counter_track ON (counter.track_id = thread_counter_track.id)
-JOIN thread USING (utid)
-WHERE thread_counter_track.name = 'time_in_state'
-ORDER BY ts, tid, cpu, freq;
diff --git a/test/trace_processor/parsing/thread_time_in_state.textproto b/test/trace_processor/parsing/thread_time_in_state.textproto
deleted file mode 100644
index f6d4749..0000000
--- a/test/trace_processor/parsing/thread_time_in_state.textproto
+++ /dev/null
@@ -1,181 +0,0 @@
-packet {
-  system_info {
-    # Use bonito CPU core to cluster mapping.
-    android_build_fingerprint: "bonito"
-    hz: 100
-  }
-}
-packet {
-  timestamp: 1
-  process_tree {
-    processes {
-      pid: 5
-      ppid: 1
-      cmdline: "com.google.pid5"
-    }
-    threads {
-      tid: 5
-      tgid: 5
-    }
-    threads {
-      tid: 7
-      tgid: 5
-      name: "tid7"
-    }
-    processes {
-      pid: 11
-      ppid: 1
-      cmdline: "com.google.pid11"
-    }
-    threads {
-      tid: 11
-      tgid: 11
-      name: "tid11"
-    }
-    threads {
-      tid: 12
-      tgid: 11
-      name: "tid12"
-    }
-  }
-}
-packet {
-  timestamp: 2
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 1
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 1
-      }
-    }
-  }
-}
-packet {
-  timestamp: 3
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 2
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 1
-      }
-      threads {
-        tid: 7
-        cpu_freq_indices: 5
-        cpu_freq_ticks: 1
-      }
-    }
-    processes {
-      pid: 11
-      threads {
-        tid: 11
-        cpu_freq_indices: 6
-        cpu_freq_ticks: 1
-      }
-      threads {
-        tid: 12
-        cpu_freq_indices: 6
-        cpu_freq_ticks: 1
-      }
-    }
-  }
-}
-packet {
-  timestamp: 4
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        # cpu_freq_indices: 1 was skipped because it did not change.
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 2
-      }
-    }
-    processes {
-      pid: 11
-      threads {
-        tid: 11
-        cpu_freq_indices: 6
-        cpu_freq_ticks: 2
-      }
-      threads {
-        tid: 12
-        cpu_freq_indices: 6
-        cpu_freq_ticks: 2
-      }
-    }
-  }
-}
-packet {
-  timestamp: 5
-  process_tree {
-    processes {
-      pid: 17
-      ppid: 1
-      cmdline: "com.google.pid17"
-    }
-    threads {
-      tid: 17
-      tgid: 17
-    }
-  }
-}
-packet {
-  timestamp: 5
-  process_stats {
-    processes {
-      pid: 17
-      threads {
-        tid: 17
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 1
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 1
-        cpu_freq_full: true
-      }
-    }
-  }
-}
-packet {
-  timestamp: 6
-  process_stats {
-    processes {
-      pid: 17
-      threads {
-        tid: 17
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 2
-        # cpu_freq_indices: 2 was skipped because it did not change.
-      }
-    }
-  }
-}
-packet {
-  timestamp: 1
-  cpu_info {
-    cpus {
-      frequencies: 100000
-      frequencies: 200000
-    }
-    cpus {
-      frequencies: 100000
-      frequencies: 200000
-    }
-    cpus {
-      frequencies: 1000000
-      frequencies: 2000000
-    }
-    cpus {
-      frequencies: 1000000
-      frequencies: 2000000
-    }
-  }
-}
diff --git a/test/trace_processor/parsing/thread_time_in_state_event.out b/test/trace_processor/parsing/thread_time_in_state_event.out
deleted file mode 100644
index af8192c..0000000
--- a/test/trace_processor/parsing/thread_time_in_state_event.out
+++ /dev/null
@@ -1,13 +0,0 @@
-
-"track_type","track_name","ts","dur","upid","value"
-"counter","Total big core cycles / sec",2000000000,1000000000,0,1000
-"counter","Total little core cycles / sec",2000000000,1000000000,0,100
-"counter","Thread 10 (1) (big core)",2000000000,1000000000,1,1000
-"counter","Thread 10 (1) (little core)",2000000000,1000000000,1,100
-"counter","Total big core cycles / sec",3000000000,1000000000,0,30000
-"counter","Total little core cycles / sec",3000000000,1000000000,0,3100
-"counter","Thread 10 (1) (big core)",3000000000,1000000000,1,20000
-"counter","Thread 10 (1) (little core)",3000000000,1000000000,1,2000
-"counter","Thread 20 (3) (big core)",3000000000,1000000000,2,10000
-"counter","Thread 20 (3) (little core)",3000000000,1000000000,2,1000
-"counter","Thread 40 (7) (little core)",3000000000,1000000000,4,100
diff --git a/test/trace_processor/parsing/thread_time_in_state_event.py b/test/trace_processor/parsing/thread_time_in_state_event.py
deleted file mode 100644
index ab3b7f6..0000000
--- a/test/trace_processor/parsing/thread_time_in_state_event.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-
-import synth_common
-
-# Since we do various time based conversions to build cycles/sec, ensure that
-# the timestamps look a bit realistic so they don't make those results look
-# weird.
-SEC = 1000000000
-
-trace = synth_common.create_trace()
-
-# Use fake fingerprint to simulate big/little cores.
-trace.add_system_info(arch='aarch64', fingerprint='crosshatch')
-trace.packet.system_info.hz = 1
-
-trace.add_packet(1)
-# little cores: cpu0 - cpu3
-trace.add_cpu([100, 200])
-trace.add_cpu([100, 200])
-trace.add_cpu([100, 200])
-trace.add_cpu([100, 200])
-# big cores: cpu4 - cpu5
-trace.add_cpu([1000, 2000])
-trace.add_cpu([1000, 2000])
-
-trace.add_packet(1 * SEC)
-trace.add_process_stats(pid=1, freqs={1: 1, 2: 1, 9: 1, 10: 1})
-trace.add_process_stats(pid=2, freqs={1: 1, 2: 1, 9: 1, 10: 1})
-trace.add_process_stats(pid=3, freqs={1: 1, 2: 1, 9: 1, 10: 1})
-trace.add_process_stats(pid=4, freqs={1: 1, 2: 1, 9: 1, 10: 1})
-
-trace.add_packet(2 * SEC)
-trace.add_process_stats(pid=1, freqs={1: 2, 9: 2})
-# Don't log anything for pid=2 thread, test that the packet at t=3 is based
-# against t=2 anyway.
-
-trace.add_packet(3 * SEC)
-trace.add_process_stats(pid=1, freqs={2: 11, 10: 11})
-trace.add_process_stats(pid=2, freqs={1: 11, 9: 11})
-# pid=3 did not record any change in time_in_state, test that it does not
-# appear in events.
-trace.add_process_stats(pid=3, freqs={1: 1})
-# pid=4 recorded a change only on the little core, test that it shows track for
-# the little core but not the big one.
-trace.add_process_stats(pid=4, freqs={1: 2, 9: 1})
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/thread_time_in_state_event.sql b/test/trace_processor/parsing/thread_time_in_state_event.sql
deleted file mode 100644
index 6b6ae5e..0000000
--- a/test/trace_processor/parsing/thread_time_in_state_event.sql
+++ /dev/null
@@ -1,21 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 so that RUN_METRIC will run without outputting any rows.
-SELECT RUN_METRIC('android/android_thread_time_in_state.sql')
-    AS suppress_query_output;
-
-SELECT * FROM android_thread_time_in_state_event
-ORDER BY ts, upid, track_name;
diff --git a/test/trace_processor/parsing/thread_time_in_state_unknown.textproto b/test/trace_processor/parsing/thread_time_in_state_unknown.textproto
deleted file mode 100644
index a85a462..0000000
--- a/test/trace_processor/parsing/thread_time_in_state_unknown.textproto
+++ /dev/null
@@ -1,96 +0,0 @@
-packet {
-  system_info {
-    # No android_build_fingerprint to test the metric without the CPU core to
-    # cluster mapping.
-    hz: 100
-  }
-}
-packet {
-  timestamp: 1
-  process_tree {
-    processes {
-      pid: 5
-      ppid: 1
-      cmdline: "com.google.pid5"
-    }
-    threads {
-      tid: 5
-      tgid: 5
-    }
-    threads {
-      tid: 7
-      tgid: 5
-      name: "tid7"
-    }
-  }
-}
-packet {
-  timestamp: 2
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 1
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 1
-      }
-    }
-  }
-}
-packet {
-  timestamp: 3
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        cpu_freq_indices: 1
-        cpu_freq_ticks: 2
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 1
-      }
-      threads {
-        tid: 7
-        cpu_freq_indices: 5
-        cpu_freq_ticks: 1
-      }
-    }
-  }
-}
-packet {
-  timestamp: 4
-  process_stats {
-    processes {
-      pid: 5
-      threads {
-        tid: 5
-        # cpu_freq_indices: 1 was skipped because it did not change.
-        cpu_freq_indices: 2
-        cpu_freq_ticks: 2
-      }
-    }
-  }
-}
-packet {
-  timestamp: 1
-  cpu_info {
-    cpus {
-      frequencies: 100000
-      frequencies: 200000
-    }
-    cpus {
-      frequencies: 100000
-      frequencies: 200000
-    }
-    cpus {
-      frequencies: 1000000
-      frequencies: 2000000
-    }
-    cpus {
-      frequencies: 1000000
-      frequencies: 2000000
-    }
-  }
-}
diff --git a/test/trace_processor/power/index b/test/trace_processor/power/index
deleted file mode 100644
index 004f7a3..0000000
--- a/test/trace_processor/power/index
+++ /dev/null
@@ -1,5 +0,0 @@
-# Power rails
-../../data/power_rails.pb power_rails.sql power_rails_power_rails.out
-power_rails_custom_clock.textproto power_rails_event.sql power_rails_event_power_rails_custom_clock.out
-power_rails.textproto power_rails_timestamp_sort.sql power_rails_timestamp_sort.out
-power_rails_well_known.textproto power_rails.sql power_rails_well_known_power_rails.out
diff --git a/test/trace_processor/power/power_rails_well_known.textproto b/test/trace_processor/power/power_rails_well_known.textproto
deleted file mode 100644
index 5129011..0000000
--- a/test/trace_processor/power/power_rails_well_known.textproto
+++ /dev/null
@@ -1,45 +0,0 @@
-packet {
-  power_rails {
-    rail_descriptor {
-      index: 4
-      rail_name: "S3M_VDD_CPUCL1"
-      subsys_name: "cpu"
-      sampling_rate: 1023
-    }
-  }
-}
-packet {
-  timestamp: 3000003
-  power_rails {
-    energy_data {
-      index: 4
-      timestamp_ms: 3
-      energy: 333
-    }
-  }
-}
-packet {
-  timestamp: 3000005
-  power_rails {
-    rail_descriptor {
-      index: 3
-      rail_name: "S2S_VDD_G3D"
-      subsys_name: "gpu"
-      sampling_rate: 1022
-    }
-    energy_data {
-      index: 4
-      timestamp_ms: 5
-      energy: 666
-    }
-    energy_data {
-      index: 3
-      energy: 999
-    }
-    energy_data {
-      index: 4
-      timestamp_ms: 3
-      energy: 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/power/power_rails_well_known_power_rails.out b/test/trace_processor/power/power_rails_well_known_power_rails.out
deleted file mode 100644
index d3c19d6..0000000
--- a/test/trace_processor/power/power_rails_well_known_power_rails.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"name","AVG(value)","COUNT(*)"
-"power.rails.cpu.mid",333.000000,3
-"power.rails.gpu",999.000000,1
diff --git a/test/trace_processor/power/power_rails.sql b/test/trace_processor/power_rails.sql
similarity index 100%
rename from test/trace_processor/power/power_rails.sql
rename to test/trace_processor/power_rails.sql
diff --git a/test/trace_processor/power/power_rails.textproto b/test/trace_processor/power_rails.textproto
similarity index 100%
rename from test/trace_processor/power/power_rails.textproto
rename to test/trace_processor/power_rails.textproto
diff --git a/test/trace_processor/power/power_rails_custom_clock.textproto b/test/trace_processor/power_rails_custom_clock.textproto
similarity index 100%
rename from test/trace_processor/power/power_rails_custom_clock.textproto
rename to test/trace_processor/power_rails_custom_clock.textproto
diff --git a/test/trace_processor/power/power_rails_event.sql b/test/trace_processor/power_rails_event.sql
similarity index 100%
rename from test/trace_processor/power/power_rails_event.sql
rename to test/trace_processor/power_rails_event.sql
diff --git a/test/trace_processor/power/power_rails_event_power_rails_custom_clock.out b/test/trace_processor/power_rails_event_power_rails_custom_clock.out
similarity index 100%
rename from test/trace_processor/power/power_rails_event_power_rails_custom_clock.out
rename to test/trace_processor/power_rails_event_power_rails_custom_clock.out
diff --git a/test/trace_processor/power/power_rails_power_rails.out b/test/trace_processor/power_rails_power_rails.out
similarity index 100%
rename from test/trace_processor/power/power_rails_power_rails.out
rename to test/trace_processor/power_rails_power_rails.out
diff --git a/test/trace_processor/power/power_rails_timestamp_sort.out b/test/trace_processor/power_rails_timestamp_sort.out
similarity index 100%
rename from test/trace_processor/power/power_rails_timestamp_sort.out
rename to test/trace_processor/power_rails_timestamp_sort.out
diff --git a/test/trace_processor/power/power_rails_timestamp_sort.sql b/test/trace_processor/power_rails_timestamp_sort.sql
similarity index 100%
rename from test/trace_processor/power/power_rails_timestamp_sort.sql
rename to test/trace_processor/power_rails_timestamp_sort.sql
diff --git a/test/trace_processor/parsing/print_systrace.sql b/test/trace_processor/print_systrace.sql
similarity index 100%
rename from test/trace_processor/parsing/print_systrace.sql
rename to test/trace_processor/print_systrace.sql
diff --git a/test/trace_processor/parsing/print_systrace_lmk_userspace.out b/test/trace_processor/print_systrace_lmk_userspace.out
similarity index 100%
rename from test/trace_processor/parsing/print_systrace_lmk_userspace.out
rename to test/trace_processor/print_systrace_lmk_userspace.out
diff --git a/test/trace_processor/parsing/print_systrace_unsigned.out b/test/trace_processor/print_systrace_unsigned.out
similarity index 100%
rename from test/trace_processor/parsing/print_systrace_unsigned.out
rename to test/trace_processor/print_systrace_unsigned.out
diff --git a/test/trace_processor/print_systrace_unsigned.py b/test/trace_processor/print_systrace_unsigned.py
new file mode 100644
index 0000000..f058b0e
--- /dev/null
+++ b/test/trace_processor/print_systrace_unsigned.py
@@ -0,0 +1,50 @@
+#!/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_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/parsing/process_metadata_matching.out b/test/trace_processor/process_metadata_matching.out
similarity index 100%
rename from test/trace_processor/parsing/process_metadata_matching.out
rename to test/trace_processor/process_metadata_matching.out
diff --git a/test/trace_processor/parsing/process_metadata_matching.sql b/test/trace_processor/process_metadata_matching.sql
similarity index 100%
rename from test/trace_processor/parsing/process_metadata_matching.sql
rename to test/trace_processor/process_metadata_matching.sql
diff --git a/test/trace_processor/parsing/process_metadata_matching.textproto b/test/trace_processor/process_metadata_matching.textproto
similarity index 100%
rename from test/trace_processor/parsing/process_metadata_matching.textproto
rename to test/trace_processor/process_metadata_matching.textproto
diff --git a/test/trace_processor/process_tracking/process_parent_pid.sql b/test/trace_processor/process_parent_pid.sql
similarity index 100%
rename from test/trace_processor/process_tracking/process_parent_pid.sql
rename to test/trace_processor/process_parent_pid.sql
diff --git a/test/trace_processor/process_tracking/process_parent_pid_process_parent_pid_tracking_1.out b/test/trace_processor/process_parent_pid_process_parent_pid_tracking_1.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_parent_pid_process_parent_pid_tracking_1.out
rename to test/trace_processor/process_parent_pid_process_parent_pid_tracking_1.out
diff --git a/test/trace_processor/process_tracking/process_parent_pid_process_parent_pid_tracking_2.out b/test/trace_processor/process_parent_pid_process_parent_pid_tracking_2.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_parent_pid_process_parent_pid_tracking_2.out
rename to test/trace_processor/process_parent_pid_process_parent_pid_tracking_2.out
diff --git a/test/trace_processor/process_parent_pid_tracking_1.py b/test/trace_processor/process_parent_pid_tracking_1.py
new file mode 100644
index 0000000..6da9547
--- /dev/null
+++ b/test/trace_processor/process_parent_pid_tracking_1.py
@@ -0,0 +1,36 @@
+#!/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_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
new file mode 100644
index 0000000..fb31a99
--- /dev/null
+++ b/test/trace_processor/process_parent_pid_tracking_2.py
@@ -0,0 +1,37 @@
+#!/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_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/parsing/process_stats_poll_oom_score.out b/test/trace_processor/process_stats_poll_oom_score.out
similarity index 100%
rename from test/trace_processor/parsing/process_stats_poll_oom_score.out
rename to test/trace_processor/process_stats_poll_oom_score.out
diff --git a/test/trace_processor/parsing/process_track_slices.sql b/test/trace_processor/process_track_slices.sql
similarity index 100%
rename from test/trace_processor/parsing/process_track_slices.sql
rename to test/trace_processor/process_track_slices.sql
diff --git a/test/trace_processor/parsing/process_track_slices_android_async_slice.out b/test/trace_processor/process_track_slices_android_async_slice.out
similarity index 100%
rename from test/trace_processor/parsing/process_track_slices_android_async_slice.out
rename to test/trace_processor/process_track_slices_android_async_slice.out
diff --git a/test/trace_processor/process_tracking/process_tracking.out b/test/trace_processor/process_tracking.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking.out
rename to test/trace_processor/process_tracking.out
diff --git a/test/trace_processor/common/process_tracking.sql b/test/trace_processor/process_tracking.sql
similarity index 100%
rename from test/trace_processor/common/process_tracking.sql
rename to test/trace_processor/process_tracking.sql
diff --git a/test/trace_processor/process_tracking/index b/test/trace_processor/process_tracking/index
deleted file mode 100644
index 9d08804..0000000
--- a/test/trace_processor/process_tracking/index
+++ /dev/null
@@ -1,24 +0,0 @@
-# Tests for the core process and thread tracking logic.
-
-# Smoke tests
-synth_process_tracking.py ../common/process_tracking.sql process_tracking.out
-
-# Short lived threads/processes
-process_tracking_short_lived_1.py ../common/process_tracking.sql process_tracking_process_tracking_short_lived_1.out
-process_tracking_short_lived_2.py ../common/process_tracking.sql process_tracking_process_tracking_short_lived_2.out
-
-# Process uid handling
-synth_process_tracking.py process_tracking_uid.sql process_tracking_uid.out
-
-# Tracking across execs
-process_tracking_exec.py ../common/process_tracking.sql process_tracking_process_tracking_exec.out
-
-# Tracking parent threads
-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
-
-# Tracking thread reuse
-reused_thread_print.py ../common/process_tracking.sql process_tracking_reused_thread_print.out
-
-# TODO(lalitm): move this out of this folder.
-sde_tracing_mark_write.textproto slice_with_pid.sql slice_with_pid_sde_tracing_mark_write.out
diff --git a/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py b/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py
deleted file mode 100644
index 0018381..0000000
--- a/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py b/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py
deleted file mode 100644
index bbea355..0000000
--- a/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_packet(ts=25)
-trace.add_process(10, 0, "main_thread")
-trace.add_thread(11, 10, "worker_thread")
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_exec.py b/test/trace_processor/process_tracking/process_tracking_exec.py
deleted file mode 100644
index 4fc2290..0000000
--- a/test/trace_processor/process_tracking/process_tracking_exec.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_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_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_packet(ts=30)
-trace.add_process(11, 10, "true_process_name")
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_short_lived_1.py b/test/trace_processor/process_tracking/process_tracking_short_lived_1.py
deleted file mode 100644
index d862335..0000000
--- a/test/trace_processor/process_tracking/process_tracking_short_lived_1.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_short_lived_2.py b/test/trace_processor/process_tracking/process_tracking_short_lived_2.py
deleted file mode 100644
index d8e3837..0000000
--- a/test/trace_processor/process_tracking/process_tracking_short_lived_2.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/reused_thread_print.py b/test/trace_processor/process_tracking/reused_thread_print.py
deleted file mode 100644
index 2429452..0000000
--- a/test/trace_processor/process_tracking/reused_thread_print.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-
-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_packet(ts=1)
-trace.add_process(10, 0, "parent")
-trace.add_process(11, 0, "short_lived")
-
-# Make the short lived thread emit a begin/end pair then exit.
-trace.add_ftrace_packet(0)
-trace.add_atrace_begin(ts=10, tid=11, pid=11, buf='test')
-trace.add_atrace_end(ts=11, tid=11, pid=11)
-trace.add_process_free(ts=12, tid=11, comm='short_lived', prio=0)
-
-# Now, reuse tid 11 and emit a begin on the parent and an end on the child.
-# This is an abuse of sync events (which technically should always be associated
-# with a single thread) but this happens all the time in places like ART so
-# we should support it.
-trace.add_ftrace_packet(0)
-trace.add_newtask(
-    ts=15, tid=10, new_tid=11, new_comm='child', flags=CLONE_THREAD)
-trace.add_rename(
-    ts=17, tid=11, old_comm='child', new_comm='true_name', oom_score_adj=1000)
-trace.add_atrace_begin(ts=18, tid=10, pid=10, buf='test')
-trace.add_atrace_end(ts=19, tid=11, pid=10)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/synth_process_tracking.py b/test/trace_processor/process_tracking/synth_process_tracking.py
deleted file mode 100644
index 68641ad..0000000
--- a/test/trace_processor/process_tracking/synth_process_tracking.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 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
-
-from synth_common import CLONE_THREAD
-import synth_common
-
-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=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
-# SQL level we should be able to tell that p1-t0 and p1-t2 belong to 'process1'
-# but p1-t1 should be left unjoinable.
-trace.add_packet(ts=5)
-trace.add_process(10, 0, "process1", 1001)
-trace.add_thread(12, 10, "p1-t2")
-
-# Now create another process (pid=20) with three threads(tids=20,21,22).
-# This will be slightly more complicated. We'll pretend that tids=20,21 were
-# 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=14, prev_pid=22, next_pid=0, prev_comm='p2-t2')
-
-# From the process tracker viewpoint we pretend we only scraped tids=20,21.
-trace.add_packet(ts=15)
-trace.add_process(20, 0, "process_2", 1002)
-trace.add_thread(21, 20, "p2-t1")
-
-# Finally the very complex case: a third process (pid=30) which spawns threads
-# in the following order (notation: A->B means thread A spawns thread B).
-# 31->32, 31->33, 32->34.
-# Last but not least we spawn a further process (pid=40) which spawns a thread
-# 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_packet(ts=26)
-trace.add_process(30, 0, "process_3")
-trace.add_thread(31, 30, "p3-t1")
-
-# This event pretends that TID=32 forks() a new process 40 (note the absence of
-# 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_packet(ts=29)
-trace.add_process(40, 0, "process_4")
-
-# 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')
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking_exec.py b/test/trace_processor/process_tracking_exec.py
new file mode 100644
index 0000000..1b075fe
--- /dev/null
+++ b/test/trace_processor/process_tracking_exec.py
@@ -0,0 +1,47 @@
+#!/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_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_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_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_process_tracking_exec.out b/test/trace_processor/process_tracking_process_tracking_exec.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_process_tracking_exec.out
rename to test/trace_processor/process_tracking_process_tracking_exec.out
diff --git a/test/trace_processor/process_tracking/process_tracking_process_tracking_short_lived_1.out b/test/trace_processor/process_tracking_process_tracking_short_lived_1.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_process_tracking_short_lived_1.out
rename to test/trace_processor/process_tracking_process_tracking_short_lived_1.out
diff --git a/test/trace_processor/process_tracking/process_tracking_process_tracking_short_lived_2.out b/test/trace_processor/process_tracking_process_tracking_short_lived_2.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_process_tracking_short_lived_2.out
rename to test/trace_processor/process_tracking_process_tracking_short_lived_2.out
diff --git a/test/trace_processor/process_tracking/process_tracking_reused_thread_print.out b/test/trace_processor/process_tracking_reused_thread_print.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_reused_thread_print.out
rename to test/trace_processor/process_tracking_reused_thread_print.out
diff --git a/test/trace_processor/process_tracking_short_lived_1.py b/test/trace_processor/process_tracking_short_lived_1.py
new file mode 100644
index 0000000..7811898
--- /dev/null
+++ b/test/trace_processor/process_tracking_short_lived_1.py
@@ -0,0 +1,37 @@
+#!/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_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
new file mode 100644
index 0000000..3eab4b6
--- /dev/null
+++ b/test/trace_processor/process_tracking_short_lived_2.py
@@ -0,0 +1,39 @@
+#!/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_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/process_tracking/process_tracking_uid.out b/test/trace_processor/process_tracking_uid.out
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_uid.out
rename to test/trace_processor/process_tracking_uid.out
diff --git a/test/trace_processor/process_tracking/process_tracking_uid.sql b/test/trace_processor/process_tracking_uid.sql
similarity index 100%
rename from test/trace_processor/process_tracking/process_tracking_uid.sql
rename to test/trace_processor/process_tracking_uid.sql
diff --git a/test/trace_processor/profiling/profiler_smaps.out b/test/trace_processor/profiler_smaps.out
similarity index 100%
rename from test/trace_processor/profiling/profiler_smaps.out
rename to test/trace_processor/profiler_smaps.out
diff --git a/test/trace_processor/profiling/profiler_smaps.sql b/test/trace_processor/profiler_smaps.sql
similarity index 100%
rename from test/trace_processor/profiling/profiler_smaps.sql
rename to test/trace_processor/profiler_smaps.sql
diff --git a/test/trace_processor/profiling/profiler_smaps.textproto b/test/trace_processor/profiler_smaps.textproto
similarity index 100%
rename from test/trace_processor/profiling/profiler_smaps.textproto
rename to test/trace_processor/profiler_smaps.textproto
diff --git a/test/trace_processor/profiling/heap_graph.textproto b/test/trace_processor/profiling/heap_graph.textproto
deleted file mode 100644
index b4c2037..0000000
--- a/test/trace_processor/profiling/heap_graph.textproto
+++ /dev/null
@@ -1,175 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  timestamp: 1
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 0
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  timestamp: 10
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 3000
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-      object_ids: 0x05
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      reference_object_id: 0x02
-      reference_object_id: 0x00
-      reference_object_id: 0x02
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-    }
-    objects {
-      id_delta: 1
-      type_id: 3
-      reference_field_id: 2
-      reference_object_id: 0x01
-    }
-    objects {
-      id: 0x05
-      type_id: 4
-      self_size: 256
-    }
-    objects {
-      id: 0x06
-      type_id: 5
-      self_size: 256
-    }
-    continued: true
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    location_names {
-      iid: 1
-      str: "/data/app/~~ASDFG==/invalid.test.android-SDASD/test.apk"
-    }
-    types {
-      id: 6
-      class_name: "FactoryProducerDelegateImplActorEmptySuper"
-      location_id: 1
-      object_size: 64
-      superclass_id: 7
-    }
-    types {
-      id: 7
-      class_name: "FactoryProducerDelegateImplActorSuperSuper"
-      location_id: 1
-      object_size: 64
-      reference_field_id: 3
-    }
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-      object_size: 64
-      reference_field_id: 1
-      reference_field_id: 4
-      superclass_id: 6
-    }
-    types {
-      id: 2
-      class_name: "Foo"
-      location_id: 1
-      object_size: 128
-    }
-    types {
-      id: 3
-      class_name: "a"
-      location_id: 1
-      object_size: 256
-    }
-    types {
-      id: 4
-      class_name: "a[]"
-      location_id: 1
-    }
-    types {
-      id: 5
-      class_name: "java.lang.Class<a[]>"
-      location_id: 1
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    field_names {
-      iid: 2
-      str: "int a.a"
-    }
-    field_names {
-      iid: 3
-      str: "a.b"
-    }
-    field_names {
-      iid: 4
-      str: "FactoryProducerDelegateImplActor.setToNULL"
-    }
-    continued: false
-    index: 1
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.test.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "DeobfuscatedA"
-      obfuscated_members {
-        obfuscated_name: "a"
-        deobfuscated_name: "deobfuscatedA"
-      }
-      obfuscated_members {
-        obfuscated_name: "b"
-        deobfuscated_name: "Other.deobfuscatedA"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_baseapk.textproto b/test/trace_processor/profiling/heap_graph_baseapk.textproto
deleted file mode 100644
index 18cae91..0000000
--- a/test/trace_processor/profiling/heap_graph_baseapk.textproto
+++ /dev/null
@@ -1,161 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  timestamp: 1
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 0
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  timestamp: 10
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 3000
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-      object_ids: 0x05
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-      reference_field_id: 1
-      reference_object_id: 0x02
-      reference_field_id: 4
-      reference_object_id: 0x00
-      reference_field_id: 3
-      reference_object_id: 0x02
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-      self_size: 128
-    }
-    objects {
-      id: 0x04
-      type_id: 3
-      self_size: 256
-      reference_field_id: 2
-      reference_object_id: 0x01
-    }
-    objects {
-      id: 0x05
-      type_id: 4
-      self_size: 256
-    }
-    objects {
-      id: 0x06
-      type_id: 5
-      self_size: 256
-    }
-    continued: true
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    location_names {
-      iid: 1
-      str: "base.apk!classes.dex"
-    }
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-    }
-    types {
-      id: 2
-      class_name: "Foo"
-      location_id: 1
-    }
-    types {
-      id: 3
-      class_name: "a"
-      location_id: 1
-    }
-    types {
-      id: 4
-      class_name: "a[]"
-      location_id: 1
-    }
-    types {
-      id: 5
-      class_name: "java.lang.Class<a[]>"
-      location_id: 1
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    field_names {
-      iid: 2
-      str: "int a.a"
-    }
-    field_names {
-      iid: 3
-      str: "a.b"
-    }
-    field_names {
-      iid: 4
-      str: "FactoryProducerDelegateImplActor.setToNULL"
-    }
-    continued: false
-    index: 1
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.test.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "DeobfuscatedA"
-      obfuscated_members {
-        obfuscated_name: "a"
-        deobfuscated_name: "deobfuscatedA"
-      }
-      obfuscated_members {
-        obfuscated_name: "b"
-        deobfuscated_name: "Other.deobfuscatedA"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_branching.textproto b/test/trace_processor/profiling/heap_graph_branching.textproto
deleted file mode 100644
index 7690c77..0000000
--- a/test/trace_processor/profiling/heap_graph_branching.textproto
+++ /dev/null
@@ -1,95 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-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: 100
-      reference_field_id: 1
-      reference_object_id: 0x02
-      reference_field_id: 1
-      reference_object_id: 0x04
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 200
-      reference_field_id: 1
-      reference_object_id: 0x03
-    }
-    objects {
-      id: 0x03
-      type_id: 3
-      self_size: 400
-    }
-    objects {
-      id: 0x04
-      type_id: 4
-      self_size: 800
-      reference_field_id: 1
-      reference_object_id: 0x05
-    }
-    objects {
-      id: 0x05
-      type_id: 5
-      self_size: 1600
-    }
-    continued: true
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  heap_graph {
-    pid: 2
-    types {
-      id: 1
-      class_name: "RootNode"
-    }
-    types {
-      id: 2
-      class_name: "LeftChild0"
-    }
-    types {
-      id: 3
-      class_name: "LeftChild1"
-    }
-    types {
-      id: 4
-      class_name: "RightChild0"
-    }
-    types {
-      id: 5
-      class_name: "RightChild1"
-    }
-    field_names {
-      iid: 1
-      str: "Node.next"
-    }
-    continued: false
-    index: 1
-  }
-}
-
diff --git a/test/trace_processor/profiling/heap_graph_duplicate.textproto b/test/trace_processor/profiling/heap_graph_duplicate.textproto
deleted file mode 100644
index 23194ef..0000000
--- a/test/trace_processor/profiling/heap_graph_duplicate.textproto
+++ /dev/null
@@ -1,45 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  timestamp: 10
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 3000
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-    }
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-      object_ids: 0x01
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-    }
-    continued: false
-    index: 0
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_duplicate_flamegraph.out b/test/trace_processor/profiling/heap_graph_duplicate_flamegraph.out
deleted file mode 100644
index 74094d8..0000000
--- a/test/trace_processor/profiling/heap_graph_duplicate_flamegraph.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
-0,0,"FactoryProducerDelegateImplActor [ROOT_JAVA_FRAME]","JAVA",1,1,64,64,"[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_flamegraph.out b/test/trace_processor/profiling/heap_graph_flamegraph.out
deleted file mode 100644
index f0d87db..0000000
--- a/test/trace_processor/profiling/heap_graph_flamegraph.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
-0,0,"FactoryProducerDelegateImplActor [ROOT_JAVA_FRAME]","JAVA",1,2,64,96,"[NULL]"
-1,1,"Foo","JAVA",1,1,32,32,0
-2,0,"DeobfuscatedA[] [ROOT_JAVA_FRAME]","JAVA",1,1,256,256,"[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_flamegraph_focused.out b/test/trace_processor/profiling/heap_graph_flamegraph_focused.out
deleted file mode 100644
index 85a537d..0000000
--- a/test/trace_processor/profiling/heap_graph_flamegraph_focused.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"id","depth","name","count","cumulative_count","size","cumulative_size","parent_id"
-0,0,"RootNode [ROOT_JAVA_FRAME]",1,3,100,700,"[NULL]"
-1,1,"LeftChild0",1,2,200,600,0
-2,2,"LeftChild1",1,1,400,400,1
diff --git a/test/trace_processor/profiling/heap_graph_flamegraph_system-server-heap-graph.out b/test/trace_processor/profiling/heap_graph_flamegraph_system-server-heap-graph.out
deleted file mode 100644
index 1aa70e7..0000000
--- a/test/trace_processor/profiling/heap_graph_flamegraph_system-server-heap-graph.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
-0,0,"java.lang.Class<java.lang.Object[]> [ROOT_JNI_GLOBAL]","JAVA",1,3,224,292,"[NULL]"
-1,1,"java.lang.Object[]","JAVA",1,1,28,28,0
-2,1,"java.lang.String","JAVA",1,1,40,40,0
-3,0,"java.lang.String [ROOT_INTERNED_STRING]","JAVA",41197,41197,1845640,1845640,"[NULL]"
-4,0,"java.lang.Class<android.content.pm.ApplicationInfo> [ROOT_STICKY_CLASS]","JAVA",1,5,1152,1268,"[NULL]"
-5,1,"java.lang.String","JAVA",1,1,56,56,4
-6,1,"android.content.pm.ApplicationInfo$1","JAVA",1,1,8,8,4
-7,1,"java.lang.Object[]","JAVA",1,2,20,52,4
-8,2,"long[]","JAVA",1,1,32,32,7
-9,0,"java.lang.Class<java.io.File> [ROOT_STICKY_CLASS]","JAVA",1,11,645,997,"[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_interleaved.textproto b/test/trace_processor/profiling/heap_graph_interleaved.textproto
deleted file mode 100644
index 2e2af30..0000000
--- a/test/trace_processor/profiling/heap_graph_interleaved.textproto
+++ /dev/null
@@ -1,128 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-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: 0x02
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-      self_size: 128
-    }
-    objects {
-      id: 0x04
-      type_id: 3
-      self_size: 256
-      reference_field_id: 2
-      reference_object_id: 0x01
-    }
-    continued: true
-    index: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 10
-  heap_graph {
-    pid: 3
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-    }
-    location_names {
-      iid: 1
-      str: "TEST:TEST"
-    }
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-    }
-    continued: false
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  heap_graph {
-    pid: 2
-    location_names {
-      iid: 1
-      str: "/data/app/~~ASDFG==/invalid.test.android-SDASD/test.apk"
-    }
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-    }
-    types {
-      id: 2
-      class_name: "Foo"
-      location_id: 1
-    }
-    types {
-      id: 3
-      class_name: "a"
-      location_id: 1
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    field_names {
-      iid: 2
-      str: "a.a"
-    }
-    continued: false
-    index: 1
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.test.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "DeobfuscatedA"
-      obfuscated_members {
-        obfuscated_name: "a"
-        deobfuscated_name: "deobfuscatedA"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_legacy.textproto b/test/trace_processor/profiling/heap_graph_legacy.textproto
deleted file mode 100644
index 54d19cd..0000000
--- a/test/trace_processor/profiling/heap_graph_legacy.textproto
+++ /dev/null
@@ -1,152 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  timestamp: 1
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 0
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  timestamp: 10
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 3000
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-      object_ids: 0x05
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-      reference_field_id: 1
-      reference_object_id: 0x02
-      reference_field_id: 4
-      reference_object_id: 0x00
-      reference_field_id: 3
-      reference_object_id: 0x02
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-      self_size: 128
-    }
-    objects {
-      id: 0x04
-      type_id: 3
-      self_size: 256
-      reference_field_id: 2
-      reference_object_id: 0x01
-    }
-    objects {
-      id: 0x05
-      type_id: 4
-      self_size: 256
-    }
-    objects {
-      id: 0x06
-      type_id: 5
-      self_size: 256
-    }
-    continued: true
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-    }
-    types {
-      id: 2
-      class_name: "Foo"
-    }
-    types {
-      id: 3
-      class_name: "a"
-    }
-    types {
-      id: 4
-      class_name: "a[]"
-    }
-    types {
-      id: 5
-      class_name: "java.lang.Class<a[]>"
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    field_names {
-      iid: 2
-      str: "int a.a"
-    }
-    field_names {
-      iid: 3
-      str: "a.b"
-    }
-    field_names {
-      iid: 4
-      str: "FactoryProducerDelegateImplActor.setToNULL"
-    }
-    continued: false
-    index: 1
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.example.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "DeobfuscatedA"
-      obfuscated_members {
-        obfuscated_name: "a"
-        deobfuscated_name: "deobfuscatedA"
-      }
-      obfuscated_members {
-        obfuscated_name: "b"
-        deobfuscated_name: "Other.deobfuscatedA"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_object.out b/test/trace_processor/profiling/heap_graph_object.out
deleted file mode 100644
index e4aa0b1..0000000
--- a/test/trace_processor/profiling/heap_graph_object.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"id","type","upid","graph_sample_ts","self_size","reference_set_id","reachable","type_name","deobfuscated_type_name","root_type"
-0,"heap_graph_object",2,10,64,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
-1,"heap_graph_object",2,10,32,"[NULL]",1,"Foo","[NULL]","[NULL]"
-2,"heap_graph_object",2,10,128,"[NULL]",0,"Foo","[NULL]","[NULL]"
-3,"heap_graph_object",2,10,256,3,0,"a","DeobfuscatedA","[NULL]"
-4,"heap_graph_object",2,10,256,"[NULL]",1,"a[]","DeobfuscatedA[]","ROOT_JAVA_FRAME"
-5,"heap_graph_object",2,10,256,"[NULL]",0,"java.lang.Class<a[]>","java.lang.Class<DeobfuscatedA[]>","[NULL]"
diff --git a/test/trace_processor/profiling/heap_graph_reference.out b/test/trace_processor/profiling/heap_graph_reference.out
deleted file mode 100644
index 7fc441a..0000000
--- a/test/trace_processor/profiling/heap_graph_reference.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"id","type","reference_set_id","owner_id","owned_id","field_name","field_type_name","deobfuscated_field_name"
-0,"heap_graph_reference",0,0,1,"FactoryProducerDelegateImplActor.foo","[NULL]","[NULL]"
-1,"heap_graph_reference",0,0,"[NULL]","FactoryProducerDelegateImplActor.setToNULL","[NULL]","[NULL]"
-2,"heap_graph_reference",0,0,1,"a.b","[NULL]","Other.deobfuscatedA"
-3,"heap_graph_reference",3,3,0,"a.a","int","DeobfuscatedA.deobfuscatedA"
diff --git a/test/trace_processor/profiling/heap_graph_superclass.out b/test/trace_processor/profiling/heap_graph_superclass.out
deleted file mode 100644
index 9f31019..0000000
--- a/test/trace_processor/profiling/heap_graph_superclass.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"id","superclass_id","name","superclass_name","location"
-0,"[NULL]","java.lang.Class<java.lang.Object>","[NULL]","l1"
-1,"[NULL]","java.lang.Class<MySuperClass>","[NULL]","l1"
-2,"[NULL]","java.lang.Class<MyChildClass>","[NULL]","l2"
-3,"[NULL]","java.lang.Object","[NULL]","l1"
-4,3,"MySuperClass","java.lang.Object","l1"
-5,4,"MyChildClass","MySuperClass","l2"
diff --git a/test/trace_processor/profiling/heap_graph_superclass.sql b/test/trace_processor/profiling/heap_graph_superclass.sql
deleted file mode 100644
index 6526d28..0000000
--- a/test/trace_processor/profiling/heap_graph_superclass.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-SELECT c.id, c.superclass_id, c.name, s.name superclass_name, c.location
-FROM heap_graph_class c LEFT JOIN heap_graph_class s ON c.superclass_id = s.id;
\ No newline at end of file
diff --git a/test/trace_processor/profiling/heap_graph_superclass.textproto b/test/trace_processor/profiling/heap_graph_superclass.textproto
deleted file mode 100644
index 02c4fbe..0000000
--- a/test/trace_processor/profiling/heap_graph_superclass.textproto
+++ /dev/null
@@ -1,104 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    objects {
-      # Class<Object> type
-      id: 0x01
-      type_id: 1
-      self_size: 40
-    }
-    objects {
-      # Class<MySuperClass> type
-      id: 0x02
-      type_id: 2
-      self_size: 40
-      reference_field_id: 1
-      reference_object_id: 0x01
-    }
-    objects {
-      # Class<MyChildClass> type
-      id: 0x03
-      type_id: 3
-      self_size: 40
-      reference_field_id: 1
-      reference_object_id: 0x02
-    }
-    objects {
-      # Object instance
-      id: 0x04
-      type_id: 4
-      self_size: 128
-    }
-    objects {
-      # MySuperClass instance
-      id: 0x05
-      type_id: 5
-      self_size: 128
-    }
-    objects {
-      # MyChildClass instance
-      id: 0x06
-      type_id: 6
-      self_size: 128
-    }
-
-    types {
-      id: 1
-      location_id: 1
-      class_name: "java.lang.Class<java.lang.Object>"
-    }
-    types {
-      id: 2
-      location_id: 1
-      class_name: "java.lang.Class<MySuperClass>"
-    }
-    types {
-      id: 3
-      location_id: 2
-      class_name: "java.lang.Class<MyChildClass>"
-    }
-    types {
-      id: 4
-      location_id: 1
-      class_name: "java.lang.Object"
-    }
-    types {
-      id: 5
-      location_id: 1
-      class_name: "MySuperClass"
-    }
-    types {
-      id: 6
-      location_id: 2
-      class_name: "MyChildClass"
-    }
-
-    field_names {
-      iid: 1
-      str: "java.lang.Class.superClass"
-    }
-
-    location_names {
-      iid: 1
-      str: "l1"
-    }
-    location_names {
-      iid: 2
-      str: "l2"
-    }
-    continued: false
-    index: 0
-  }
-}
diff --git a/test/trace_processor/profiling/heap_graph_two_locations.textproto b/test/trace_processor/profiling/heap_graph_two_locations.textproto
deleted file mode 100644
index 59a8ccf..0000000
--- a/test/trace_processor/profiling/heap_graph_two_locations.textproto
+++ /dev/null
@@ -1,168 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-packet {
-  timestamp: 1
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 0
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  timestamp: 10
-  process_stats {
-    processes {
-      pid: 2
-      rss_anon_kb: 1000
-      vm_swap_kb: 3000
-      oom_score_adj: 0
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-      object_ids: 0x05
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-      reference_field_id: 1
-      reference_object_id: 0x02
-      reference_field_id: 3
-      reference_object_id: 0x02
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-      self_size: 128
-    }
-    objects {
-      id: 0x04
-      type_id: 3
-      self_size: 256
-      reference_field_id: 2
-      reference_object_id: 0x01
-    }
-    objects {
-      id: 0x05
-      type_id: 4
-      self_size: 256
-    }
-    objects {
-      id: 0x06
-      type_id: 5
-      self_size: 256
-    }
-    continued: true
-    index: 0
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    location_names {
-      iid: 1
-      str: "/data/app/~~ASDFG==/invalid.test.android-SDASD/test.apk"
-    }
-    location_names {
-      iid: 2
-      str: "/data/app/~~ASDFG==/invalid.test2.android-SDASD/test.apk"
-    }
-    types {
-      id: 1
-      class_name: "FactoryProducerDelegateImplActor"
-      location_id: 1
-    }
-    types {
-      id: 2
-      class_name: "a"
-      location_id: 2
-    }
-    types {
-      id: 3
-      class_name: "a"
-      location_id: 1
-    }
-    types {
-      id: 4
-      class_name: "a[]"
-      location_id: 1
-    }
-    types {
-      id: 5
-      class_name: "java.lang.Class<a[]>"
-      location_id: 1
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    field_names {
-      iid: 2
-      str: "int a.a"
-    }
-    field_names {
-      iid: 3
-      str: "a.b"
-    }
-    continued: false
-    index: 1
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.test.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "DeobfuscatedA"
-      obfuscated_members {
-        obfuscated_name: "a"
-        deobfuscated_name: "deobfuscatedA"
-      }
-      obfuscated_members {
-        obfuscated_name: "b"
-        deobfuscated_name: "Other.deobfuscatedA"
-      }
-    }
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "invalid.test2.android"
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "Foo"
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_profile_deobfuscate.out b/test/trace_processor/profiling/heap_profile_deobfuscate.out
deleted file mode 100644
index 4381edc..0000000
--- a/test/trace_processor/profiling/heap_profile_deobfuscate.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"deobfuscated_name","mapping","rel_pc"
-"Bar.function1",0,4096
diff --git a/test/trace_processor/profiling/heap_profile_deobfuscate.sql b/test/trace_processor/profiling/heap_profile_deobfuscate.sql
deleted file mode 100644
index c0260b4..0000000
--- a/test/trace_processor/profiling/heap_profile_deobfuscate.sql
+++ /dev/null
@@ -1,16 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 deobfuscated_name, mapping, rel_pc FROM stack_profile_frame ORDER BY name;
diff --git a/test/trace_processor/profiling/heap_profile_deobfuscate.textproto b/test/trace_processor/profiling/heap_profile_deobfuscate.textproto
deleted file mode 100644
index 1782b1c..0000000
--- a/test/trace_processor/profiling/heap_profile_deobfuscate.textproto
+++ /dev/null
@@ -1,102 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-
-packet {
-  clock_snapshot {
-    clocks: {
-      clock_id: 6 # BOOTTIME
-      timestamp: 0
-    }
-    clocks: {
-      clock_id: 4 # MONOTONIC_COARSE
-      timestamp: 10
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 999
-  previous_packet_dropped: true
-  incremental_state_cleared: true
-  timestamp: 10
-  profile_packet {
-    strings {
-      iid: 1
-      str: "a.f1"
-    }
-    strings {
-      iid: 2
-      str: "data/app/com.google.android.webview-6XfQhnaSkFwGK0sYL9is0G==/base.apk"
-    }
-    strings {
-      iid: 3
-      str: "build-id"
-    }
-    frames {
-      iid: 1
-      function_name_id: 1
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-      frame_ids: 1
-    }
-    mappings {
-      iid: 1
-      path_string_ids: 2
-      build_id: 3
-    }
-    process_dumps {
-      pid: 2
-      samples {
-        callstack_id: 1
-        self_allocated: 2000
-        self_freed: 1000
-        alloc_count: 2
-        free_count: 1
-      }
-    }
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "com.google.android.wrong"
-    version_code: 1234
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "Foo"
-      obfuscated_methods {
-        obfuscated_name: "f1"
-        deobfuscated_name: "function2"
-      }
-    }
-  }
-  deobfuscation_mapping {
-    package_name: "com.google.android.webview"
-    version_code: 1234
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "Bar"
-      obfuscated_methods {
-        obfuscated_name: "f1"
-        deobfuscated_name: "function1"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_profile_deobfuscate_memfd.textproto b/test/trace_processor/profiling/heap_profile_deobfuscate_memfd.textproto
deleted file mode 100644
index 4fdc403..0000000
--- a/test/trace_processor/profiling/heap_profile_deobfuscate_memfd.textproto
+++ /dev/null
@@ -1,90 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-
-packet {
-  clock_snapshot {
-    clocks: {
-      clock_id: 6 # BOOTTIME
-      timestamp: 0
-    }
-    clocks: {
-      clock_id: 4 # MONOTONIC_COARSE
-      timestamp: 10
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 999
-  previous_packet_dropped: true
-  incremental_state_cleared: true
-  timestamp: 10
-  profile_packet {
-    strings {
-      iid: 1
-      str: "a.f1"
-    }
-    strings {
-      iid: 2
-      str: "memfd:jit-cache"
-    }
-    strings {
-      iid: 3
-      str: "build-id"
-    }
-    frames {
-      iid: 1
-      function_name_id: 1
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-      frame_ids: 1
-    }
-    mappings {
-      iid: 1
-      path_string_ids: 2
-      build_id: 3
-    }
-    process_dumps {
-      pid: 2
-      samples {
-        callstack_id: 1
-        self_allocated: 2000
-        self_freed: 1000
-        alloc_count: 2
-        free_count: 1
-      }
-    }
-  }
-}
-packet {
-  deobfuscation_mapping {
-    package_name: "com.google.android.webview"
-    version_code: 1234
-    obfuscated_classes {
-      obfuscated_name: "a"
-      deobfuscated_name: "Bar"
-      obfuscated_methods {
-        obfuscated_name: "f1"
-        deobfuscated_name: "function1"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/heap_profile_dump_max.out b/test/trace_processor/profiling/heap_profile_dump_max.out
deleted file mode 100644
index 1ef5076..0000000
--- a/test/trace_processor/profiling/heap_profile_dump_max.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"id","type","ts","upid","heap_name","callsite_id","count","size"
-0,"heap_profile_allocation",-10,2,"malloc",2,6,1000
-1,"heap_profile_allocation",-10,2,"malloc",3,1,90
diff --git a/test/trace_processor/profiling/heap_profile_dump_max.textproto b/test/trace_processor/profiling/heap_profile_dump_max.textproto
deleted file mode 100644
index 6efbfe1..0000000
--- a/test/trace_processor/profiling/heap_profile_dump_max.textproto
+++ /dev/null
@@ -1,149 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-
-packet {
-  clock_snapshot {
-    clocks: {
-      clock_id: 6 # BOOTTIME
-      timestamp: 0
-    }
-    clocks: {
-      clock_id: 4 # MONOTONIC_COARSE
-      timestamp: 10
-    }
-  }
-}
-
-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
-      orig_sampling_interval_bytes: 1024
-      sampling_interval_bytes: 1024
-      samples {
-        callstack_id: 1
-        self_max: 1000
-        self_max_count: 6
-      }
-      samples {
-        callstack_id: 2
-        self_max: 90
-        self_max_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/trace_processor/profiling/heap_profile_dump_max_legacy.out b/test/trace_processor/profiling/heap_profile_dump_max_legacy.out
deleted file mode 100644
index a5e6319..0000000
--- a/test/trace_processor/profiling/heap_profile_dump_max_legacy.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"id","type","ts","upid","heap_name","callsite_id","count","size"
-0,"heap_profile_allocation",-10,2,"malloc",2,0,1000
-1,"heap_profile_allocation",-10,2,"malloc",3,0,90
diff --git a/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto b/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto
deleted file mode 100644
index 86cadb4..0000000
--- a/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto
+++ /dev/null
@@ -1,147 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-      uid: 0
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-      uid: 1000
-    }
-  }
-}
-
-packet {
-  clock_snapshot {
-    clocks: {
-      clock_id: 6 # BOOTTIME
-      timestamp: 0
-    }
-    clocks: {
-      clock_id: 4 # MONOTONIC_COARSE
-      timestamp: 10
-    }
-  }
-}
-
-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_max: 1000
-        self_max_count: 6
-      }
-      samples {
-        callstack_id: 2
-        self_max: 90
-        self_max_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/trace_processor/profiling/heap_profile_tracker_new_stack.out b/test/trace_processor/profiling/heap_profile_tracker_new_stack.out
deleted file mode 100644
index 9306208..0000000
--- a/test/trace_processor/profiling/heap_profile_tracker_new_stack.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"id","type","ts","upid","heap_name","callsite_id","count","size"
-0,"heap_profile_allocation",0,0,"malloc",0,1,1
-1,"heap_profile_allocation",0,0,"malloc",0,-1,-1
-2,"heap_profile_allocation",1,0,"malloc",0,1,1
-3,"heap_profile_allocation",1,0,"malloc",0,-1,-1
diff --git a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.out b/test/trace_processor/profiling/heap_profile_tracker_twoheaps.out
deleted file mode 100644
index cc78466..0000000
--- a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"id","type","ts","upid","heap_name","callsite_id","count","size"
-0,"heap_profile_allocation",0,0,"malloc",0,1,1
-1,"heap_profile_allocation",0,0,"malloc",0,-1,-1
-2,"heap_profile_allocation",0,0,"custom",0,1,1
-3,"heap_profile_allocation",0,0,"custom",0,-1,-1
diff --git a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.sql b/test/trace_processor/profiling/heap_profile_tracker_twoheaps.sql
deleted file mode 100644
index efed7da..0000000
--- a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.sql
+++ /dev/null
@@ -1 +0,0 @@
-select * from heap_profile_allocation;
diff --git a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.textproto b/test/trace_processor/profiling/heap_profile_tracker_twoheaps.textproto
deleted file mode 100644
index b5a4aed..0000000
--- a/test/trace_processor/profiling/heap_profile_tracker_twoheaps.textproto
+++ /dev/null
@@ -1,62 +0,0 @@
-packet {
-  clock_snapshot {
-    clocks: {
-      clock_id: 6 # BOOTTIME
-      timestamp: 0
-    }
-    clocks: {
-      clock_id: 4 # MONOTONIC_COARSE
-      timestamp: 0
-    }
-  }
-}
-
-packet {
-  previous_packet_dropped: true
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  interned_data {
-    mappings {
-      iid: 1
-    }
-    frames {
-      iid: 1
-      mapping_id: 1
-      rel_pc: 0x123
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  profile_packet {
-    index: 0
-    continued: false
-    process_dumps {
-      heap_name: "malloc"
-      samples {
-        callstack_id: 1
-        self_allocated: 1
-        alloc_count: 1
-        self_freed: 1
-        free_count: 1
-      }
-    }
-    process_dumps {
-      heap_name: "custom"
-      samples {
-        callstack_id: 1
-        self_allocated: 1
-        alloc_count: 1
-        self_freed: 1
-        free_count: 1
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/index b/test/trace_processor/profiling/index
deleted file mode 100644
index 66ae8e4..0000000
--- a/test/trace_processor/profiling/index
+++ /dev/null
@@ -1,53 +0,0 @@
-# Contains heap profiling, perf profiling and heap graph tests.
-
-heap_profile_jit.textproto heap_profile_frames.sql heap_profile_jit.out
-heap_profile_deobfuscate.textproto heap_profile_deobfuscate.sql heap_profile_deobfuscate.out
-heap_profile_deobfuscate_memfd.textproto heap_profile_deobfuscate.sql heap_profile_deobfuscate.out
-heap_profile_dump_max_legacy.textproto heap_profile_tracker_new_stack.sql heap_profile_dump_max_legacy.out
-heap_profile_dump_max.textproto heap_profile_tracker_new_stack.sql heap_profile_dump_max.out
-
-
-profiler_smaps.textproto profiler_smaps.sql profiler_smaps.out
-
-heap_graph_baseapk.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
-heap_graph_baseapk.textproto heap_graph_object.sql heap_graph_object.out
-heap_graph_baseapk.textproto heap_graph_reference.sql heap_graph_reference.out
-
-heap_graph_duplicate.textproto heap_graph_flamegraph.sql heap_graph_duplicate_flamegraph.out
-
-heap_graph.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
-heap_graph.textproto heap_graph_object.sql heap_graph_object.out
-heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
-heap_graph_two_locations.textproto heap_graph_object.sql heap_graph_two_locations.out
-heap_graph_legacy.textproto heap_graph_object.sql heap_graph_object.out
-heap_graph_legacy.textproto heap_graph_reference.sql heap_graph_reference.out
-heap_graph_interleaved.textproto heap_graph_object.sql heap_graph_interleaved_object.out
-heap_graph_interleaved.textproto heap_graph_reference.sql heap_graph_interleaved_reference.out
-../../data/system-server-heap-graph-new.pftrace heap_graph_flamegraph.sql heap_graph_flamegraph_system-server-heap-graph.out
-../../data/system-server-native-profile heap_profile_flamegraph.sql heap_profile_flamegraph_system-server-native-profile.out
-heap_profile_tracker_new_stack.textproto heap_profile_tracker_new_stack.sql heap_profile_tracker_new_stack.out
-heap_profile_tracker_twoheaps.textproto heap_profile_tracker_twoheaps.sql heap_profile_tracker_twoheaps.out
-heap_graph_branching.textproto heap_graph_flamegraph_focused.sql heap_graph_flamegraph_focused.out
-heap_graph_superclass.textproto heap_graph_superclass.sql heap_graph_superclass.out
-
-# TODO(b/153552977): Stop supporting legacy heap graphs. These never made
-#                    it into a public release, so we should eventually stop
-#                    supporting workarounds for them.
-heap_graph_legacy.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
-
-stack_profile_tracker_empty_callstack.textproto stack_profile_tracker_empty_callstack.sql stack_profile_tracker_empty_callstack.out
-
-# Metrics
-heap_profile_no_symbols.textproto unsymbolized_frames unsymbolized_frames.out
-
-heap_graph.textproto java_heap_stats java_heap_stats.out
-heap_graph_closest_proc.textproto java_heap_stats heap_stats_closest_proc.out
-heap_graph.textproto java_heap_histogram java_heap_histogram.out
-
-# perf_sample table (traced_perf) with android R and S trace inputs.
-../../data/perf_sample.pb perf_sample.sql perf_sample_rvc.out
-../../data/perf_sample_sc.pb perf_sample.sql perf_sample_sc.out
-
-# this uses llvm-symbolizer to test the offline symbolization built into
-# trace_processor_shell.
-../../data/heapprofd_standalone_client_example-trace stack_profile_symbols.sql stack_profile_symbols.out
diff --git a/test/trace_processor/profiling/java_heap_histogram.out b/test/trace_processor/profiling/java_heap_histogram.out
deleted file mode 100644
index 824b68c..0000000
--- a/test/trace_processor/profiling/java_heap_histogram.out
+++ /dev/null
@@ -1,37 +0,0 @@
-java_heap_histogram {
-  instance_stats {
-    upid: 2
-    process {
-      name: "system_server"
-      uid: 1000
-    }
-    samples {
-      ts: 10
-      type_count {
-        type_name: "DeobfuscatedA[]"
-        obj_count: 1
-        reachable_obj_count: 1
-      }
-      type_count {
-        type_name: "FactoryProducerDelegateImplActor"
-        obj_count: 1
-        reachable_obj_count: 1
-      }
-      type_count {
-        type_name: "Foo"
-        obj_count: 2
-        reachable_obj_count: 1
-      }
-      type_count {
-        type_name: "DeobfuscatedA"
-        obj_count: 1
-        reachable_obj_count: 0
-      }
-      type_count {
-        type_name: "java.lang.Class<DeobfuscatedA[]>"
-        obj_count: 1
-        reachable_obj_count: 0
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/profiling/perf_sample.sql b/test/trace_processor/profiling/perf_sample.sql
deleted file mode 100644
index 5c0f1b4..0000000
--- a/test/trace_processor/profiling/perf_sample.sql
+++ /dev/null
@@ -1,31 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 ps.ts, ps.cpu, ps.cpu_mode, ps.unwind_error, ps.perf_session_id,
-       pct.name cntr_name, pct.is_timebase,
-       thread.tid,
-       spf.name
-from experimental_annotated_callstack eac
-join perf_sample ps
-  on (eac.start_id == ps.callsite_id)
-join perf_counter_track pct
-  using(perf_session_id, cpu)
-join thread
-  using(utid)
-join stack_profile_frame spf
-  on (eac.frame_id == spf.id)
-order by ps.ts asc, eac.depth asc
-
diff --git a/test/trace_processor/profiling/perf_sample_rvc.out b/test/trace_processor/profiling/perf_sample_rvc.out
deleted file mode 100644
index 00f7325..0000000
--- a/test/trace_processor/profiling/perf_sample_rvc.out
+++ /dev/null
@@ -1,22 +0,0 @@
-"ts","cpu","cpu_mode","unwind_error","perf_session_id","cntr_name","is_timebase","tid","name"
-260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
-260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
-260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
-260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"poll"
-260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"__ppoll"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"poll"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__ppoll"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__kernel_rt_sigreturn"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZL21HandleProfilingSignaliP7siginfoPv"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN12_GLOBAL__N_117netdClientConnectEiPK8sockaddrj.cfi"
-260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__connect"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner26RunImmediateAndDelayedTaskEv"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner22RunFileDescriptorWatchEi"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base10UnixSocket7OnEventEv"
-260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto3ipc25BufferedFrameDeserializer12BeginReceiveEv"
diff --git a/test/trace_processor/profiling/perf_sample_sc.out b/test/trace_processor/profiling/perf_sample_sc.out
deleted file mode 100644
index 4ddbb3a..0000000
--- a/test/trace_processor/profiling/perf_sample_sc.out
+++ /dev/null
@@ -1,96 +0,0 @@
-"ts","cpu","cpu_mode","unwind_error","perf_session_id","cntr_name","is_timebase","tid","name"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"__start_thread"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZL15__pthread_startPv"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN13thread_data_t10trampolineEPKS_"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android6Thread11_threadLoopEPv"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android10PoolThread10threadLoopEv"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14IPCThreadState14joinThreadPoolEb"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14IPCThreadState14executeCommandEi"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7_JNIEnv17CallBooleanMethodEP8_jobjectP10_jmethodIDz"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN3art3JNIILb0EE18CallBooleanMethodVEP7_JNIEnvP8_jobjectP10_jmethodIDSt9__va_list"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN3art35InvokeVirtualOrInterfaceWithVarArgsIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_St9__va_list"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"art_quick_invoke_stub"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.os.Binder.execTransact"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.os.Binder.execTransactInternal"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.wm.Session.onTransact"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.view.IWindowSession$Stub.onTransact"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.wm.Session.sendWallpaperCommand"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.ThreadPriorityBooster.boost"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"art_jni_trampoline"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_Z36android_os_Process_getThreadPriorityP7_JNIEnvP8_jobjecti"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"getpriority"
-105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"__getpriority"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher29reportTouchEventForStatisticsERKNS0_11MotionEntryE"
-105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android17LatencyStatistics12shouldReportEv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"__start_thread"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZL15__pthread_startPv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN13thread_data_t10trampolineEPKS_"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android6Thread11_threadLoopEPv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZThn32_N7android13SensorService10threadLoopEv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android13SensorService10threadLoopEv"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android12SensorDevice7pollFmqEP15sensors_event_tm"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android8hardware9EventFlag10waitHelperEjPjl"
-105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"syscall"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
-105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher34verifiedMotionEventFromMotionEntryERKNS0_11MotionEntryE"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher30findTouchedWindowTargetsLockedElRKNS0_11MotionEntryERNSt3__16vectorINS0_11InputTargetENS5_9allocatorIS7_EEEEPlPb"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZNK7android15inputdispatcher15InputDispatcher29hasResponsiveConnectionLockedERNS_17InputWindowHandleE"
-105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZNK7android7RefBase9incStrongEPKv"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"__start_thread"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZL15__pthread_startPv"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art6Thread14CreateCallbackEPv"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art35InvokeVirtualOrInterfaceWithJValuesIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_PK6jvalue"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"art_quick_invoke_stub"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"com.android.server.UiThread.run"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.HandlerThread.run"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.Looper.loop"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.Looper.loopOnce"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.MessageQueue.next"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"art_jni_trampoline"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7androidL38android_os_MessageQueue_nativePollOnceEP7_JNIEnvP8_jobjectli"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android6Looper8pollOnceEiPiS1_PPv"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android6Looper9pollInnerEi"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android24NativeInputEventReceiver11handleEventEiiPv"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android24NativeInputEventReceiver13consumeEventsEP7_JNIEnvblPb"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art3JNIILb0EE9FindClassEP7_JNIEnvPKc"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE"
-105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,""
diff --git a/test/trace_processor/profiling/stack_profile_symbols.out b/test/trace_processor/profiling/stack_profile_symbols.out
deleted file mode 100644
index 64e7397..0000000
--- a/test/trace_processor/profiling/stack_profile_symbols.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"name","source_file","line_number"
-"[NULL]","[NULL]",0
-"_start","??",0
-"(anonymous namespace)::OtherFn(unsigned int, unsigned long)","/builds/master/experiment/external/perfetto/out/linux_clang_release/../../src/profiling/memory/heapprofd_standalone_client_example.cc",24
-"main","/builds/master/experiment/external/perfetto/out/linux_clang_release/../../src/profiling/memory/heapprofd_standalone_client_example.cc",32
diff --git a/test/trace_processor/profiling/stack_profile_symbols.sql b/test/trace_processor/profiling/stack_profile_symbols.sql
deleted file mode 100644
index e57f84d..0000000
--- a/test/trace_processor/profiling/stack_profile_symbols.sql
+++ /dev/null
@@ -1 +0,0 @@
-select name, source_file, line_number from stack_profile_symbol
diff --git a/test/trace_processor/python/api_integrationtest.py b/test/trace_processor/python/api_integrationtest.py
deleted file mode 100644
index 392e28e..0000000
--- a/test/trace_processor/python/api_integrationtest.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import unittest
-
-from trace_processor.api import TraceProcessor
-
-
-class TestApi(unittest.TestCase):
-
-  def test_trace_file(self):
-    # Get path to trace_processor_shell and construct TraceProcessor
-    tp = TraceProcessor(
-        file_path=os.path.join(os.environ["ROOT_DIR"], 'test', 'data',
-                               'example_android_trace_30s.pb'),
-        bin_path=os.environ["SHELL_PATH"])
-    qr_iterator = tp.query('select * from slice limit 10')
-    dur_result = [
-        178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 275312,
-        65313
-    ]
-
-    for num, row in enumerate(qr_iterator):
-      self.assertEqual(row.type, 'internal_slice')
-      self.assertEqual(row.dur, dur_result[num])
-
-    # Test the batching logic by issuing a large query and ensuring we receive
-    # all rows, not just a truncated subset.
-    qr_iterator = tp.query('select count(*) as cnt from slice')
-    expected_count = next(qr_iterator).cnt
-    self.assertGreater(expected_count, 0)
-
-    qr_iterator = tp.query('select * from slice')
-    count = sum(1 for _ in qr_iterator)
-    self.assertEqual(count, expected_count)
-
-    tp.close()
diff --git a/test/trace_processor/python/api_unittest.py b/test/trace_processor/python/api_unittest.py
deleted file mode 100755
index 52e2c41..0000000
--- a/test/trace_processor/python/api_unittest.py
+++ /dev/null
@@ -1,292 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-
-from trace_processor.api import TraceProcessor, TraceProcessorException
-from trace_processor.protos import ProtoFactory
-
-
-class TestQueryResultIterator(unittest.TestCase):
-  # The numbers input into cells correspond the the CellType enum values
-  # defined under trace_processor.proto
-  CELL_VARINT = ProtoFactory().CellsBatch().CELL_VARINT
-  CELL_STRING = ProtoFactory().CellsBatch().CELL_STRING
-  CELL_INVALID = ProtoFactory().CellsBatch().CELL_INVALID
-
-  def test_one_batch(self):
-    int_values = [100, 200]
-    str_values = ['bar1', 'bar2']
-
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend(int_values)
-    batch.string_cells = "\0".join(str_values) + "\0"
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    for num, row in enumerate(qr_iterator):
-      self.assertEqual(row.foo_id, str_values[num])
-      self.assertEqual(row.foo_num, int_values[num])
-
-  def test_many_batches(self):
-    int_values = [100, 200, 300, 400]
-    str_values = ['bar1', 'bar2', 'bar3', 'bar4']
-
-    batch_1 = ProtoFactory().CellsBatch()
-    batch_1.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch_1.varint_cells.extend(int_values[:2])
-    batch_1.string_cells = "\0".join(str_values[:2]) + "\0"
-    batch_1.is_last_batch = False
-
-    batch_2 = ProtoFactory().CellsBatch()
-    batch_2.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch_2.varint_cells.extend(int_values[2:])
-    batch_2.string_cells = "\0".join(str_values[2:]) + "\0"
-    batch_2.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch_1, batch_2])
-
-    for num, row in enumerate(qr_iterator):
-      self.assertEqual(row.foo_id, str_values[num])
-      self.assertEqual(row.foo_num, int_values[num])
-
-  def test_empty_batch(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator([], [batch])
-
-    for num, row in enumerate(qr_iterator):
-      self.assertIsNone(row.foo_id)
-      self.assertIsNone(row.foo_num)
-
-  def test_invalid_batch(self):
-    batch = ProtoFactory().CellsBatch()
-
-    qr_iterator = TraceProcessor.QueryResultIterator([], [batch])
-
-    # Since the batch isn't defined as the last batch, the QueryResultsIterator
-    # expects another batch and thus raises IndexError as no next batch exists.
-    with self.assertRaises(IndexError):
-      for row in qr_iterator:
-        pass
-
-  def test_incorrect_cells_batch(self):
-    str_values = ['bar1', 'bar2']
-
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.string_cells = "\0".join(str_values) + "\0"
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    # The batch specifies there ought to be 2 cells of type VARINT and 2 cells
-    # of type STRING, but there are no string cells defined in the batch. Thus
-    # an IndexError occurs as it tries to access the empty string cells list.
-    with self.assertRaises(IndexError):
-      for row in qr_iterator:
-        pass
-
-  def test_incorrect_columns_batch(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend([100, 200])
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(
-        ['foo_id', 'foo_num', 'foo_dur', 'foo_ms'], [batch])
-
-    # It's always the case that the number of cells is a multiple of the number
-    # of columns. However, here this is clearly not the case, so when the
-    # iterator tries to access the cell for the third column, it raises an
-    # IndexError due to having exhausted the cells list.
-    with self.assertRaises(IndexError):
-      for row in qr_iterator:
-        pass
-
-  def test_invalid_cell_type(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_INVALID,
-        TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend([100, 200])
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    # In this batch we declare the columns types to be CELL_INVALID,
-    # CELL_VARINT but that doesn't match the data which are both ints*
-    # so we should raise a TraceProcessorException.
-    with self.assertRaises(TraceProcessorException):
-      for row in qr_iterator:
-        pass
-
-  def test_one_batch_as_pandas(self):
-    int_values = [100, 200]
-    str_values = ['bar1', 'bar2']
-
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend(int_values)
-    batch.string_cells = "\0".join(str_values) + "\0"
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    qr_df = qr_iterator.as_pandas_dataframe()
-    for num, row in qr_df.iterrows():
-      self.assertEqual(row['foo_id'], str_values[num])
-      self.assertEqual(row['foo_num'], int_values[num])
-
-  def test_many_batches_as_pandas(self):
-    int_values = [100, 200, 300, 400]
-    str_values = ['bar1', 'bar2', 'bar3', 'bar4']
-
-    batch_1 = ProtoFactory().CellsBatch()
-    batch_1.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch_1.varint_cells.extend(int_values[:2])
-    batch_1.string_cells = "\0".join(str_values[:2]) + "\0"
-    batch_1.is_last_batch = False
-
-    batch_2 = ProtoFactory().CellsBatch()
-    batch_2.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch_2.varint_cells.extend(int_values[2:])
-    batch_2.string_cells = "\0".join(str_values[2:]) + "\0"
-    batch_2.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch_1, batch_2])
-
-    qr_df = qr_iterator.as_pandas_dataframe()
-    for num, row in qr_df.iterrows():
-      self.assertEqual(row['foo_id'], str_values[num])
-      self.assertEqual(row['foo_num'], int_values[num])
-
-  def test_empty_batch_as_pandas(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator([], [batch])
-
-    qr_df = qr_iterator.as_pandas_dataframe()
-    for num, row in qr_df.iterrows():
-      self.assertEqual(row['foo_id'], str_values[num])
-      self.assertEqual(row['foo_num'], int_values[num])
-
-  def test_invalid_batch_as_pandas(self):
-    batch = ProtoFactory().CellsBatch()
-
-    qr_iterator = TraceProcessor.QueryResultIterator([], [batch])
-
-    # Since the batch isn't defined as the last batch, the QueryResultsIterator
-    # expects another batch and thus raises IndexError as no next batch exists.
-    with self.assertRaises(IndexError):
-      qr_df = qr_iterator.as_pandas_dataframe()
-
-  def test_incorrect_cells_batch_as_pandas(self):
-    str_values = ['bar1', 'bar2']
-
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_STRING,
-        TestQueryResultIterator.CELL_VARINT,
-        TestQueryResultIterator.CELL_STRING, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.string_cells = "\0".join(str_values) + "\0"
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    # The batch specifies there ought to be 2 cells of type VARINT and 2 cells
-    # of type STRING, but there are no string cells defined in the batch. Thus
-    # an IndexError occurs as it tries to access the empty string cells list.
-    with self.assertRaises(IndexError):
-      qr_df = qr_iterator.as_pandas_dataframe()
-
-  def test_incorrect_columns_batch_as_pandas(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_VARINT, TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend([100, 200])
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(
-        ['foo_id', 'foo_num', 'foo_dur', 'foo_ms'], [batch])
-
-    # It's always the case that the number of cells is a multiple of the number
-    # of columns. However, here this is clearly not the case, so when the
-    # iterator tries to access the cell for the third column, it raises an
-    # IndexError due to having exhausted the cells list.
-    with self.assertRaises(IndexError):
-      qr_df = qr_iterator.as_pandas_dataframe()
-
-  def test_invalid_cell_type_as_pandas(self):
-    batch = ProtoFactory().CellsBatch()
-    batch.cells.extend([
-        TestQueryResultIterator.CELL_INVALID,
-        TestQueryResultIterator.CELL_VARINT
-    ])
-    batch.varint_cells.extend([100, 200])
-    batch.is_last_batch = True
-
-    qr_iterator = TraceProcessor.QueryResultIterator(['foo_id', 'foo_num'],
-                                                     [batch])
-
-    # In this batch we declare the columns types to be CELL_INVALID,
-    # CELL_VARINT but that doesn't match the data which are both ints*
-    # so we should raise a TraceProcessorException.
-    with self.assertRaises(TraceProcessorException):
-      qr_df = qr_iterator.as_pandas_dataframe()
diff --git a/test/trace_processor/reused_thread_print.py b/test/trace_processor/reused_thread_print.py
new file mode 100644
index 0000000..576eada
--- /dev/null
+++ b/test/trace_processor/reused_thread_print.py
@@ -0,0 +1,51 @@
+#!/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_packet(ts=1)
+trace.add_process(10, 0, "parent")
+trace.add_process(11, 0, "short_lived")
+
+# Make the short lived thread emit a begin/end pair then exit.
+trace.add_ftrace_packet(0)
+trace.add_atrace_begin(ts=10, tid=11, pid=11, buf='test')
+trace.add_atrace_end(ts=11, tid=11, pid=11)
+trace.add_process_free(ts=12, tid=11, comm='short_lived', prio=0)
+
+# Now, reuse tid 11 and emit a begin on the parent and an end on the child.
+# This is an abuse of sync events (which technically should always be associated
+# with a single thread) but this happens all the time in places like ART so
+# we should support it.
+trace.add_ftrace_packet(0)
+trace.add_newtask(
+    ts=15, tid=10, new_tid=11, new_comm='child', flags=CLONE_THREAD)
+trace.add_rename(
+    ts=17, tid=11, old_comm='child', new_comm='true_name', oom_score_adj=1000)
+trace.add_atrace_begin(ts=18, tid=10, pid=10, buf='test')
+trace.add_atrace_end(ts=19, tid=11, pid=10)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat.sql b/test/trace_processor/rss_stat.sql
similarity index 100%
rename from test/trace_processor/parsing/rss_stat.sql
rename to test/trace_processor/rss_stat.sql
diff --git a/test/trace_processor/parsing/rss_stat_after_free.out b/test/trace_processor/rss_stat_after_free.out
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_after_free.out
rename to test/trace_processor/rss_stat_after_free.out
diff --git a/test/trace_processor/rss_stat_after_free.py b/test/trace_processor/rss_stat_after_free.py
new file mode 100644
index 0000000..d408955
--- /dev/null
+++ b/test/trace_processor/rss_stat_after_free.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+#!/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 handling of the mm_id field in the rss_stat
+# event when mm_structs are reused on process death.
+
+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(ts=1)
+trace.add_process(10, 1, "parent_process")
+trace.add_process(11, 1, "other_process")
+
+trace.add_ftrace_packet(1)
+
+# Emit an event on an irrelevant thread.
+trace.add_rss_stat(90, tid=11, member=0, size=20, mm_id=0x5678, curr=1)
+
+# Emit an event for the process.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Now kill the process.
+trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
+
+# Emit an event on another thread which reuses the struct after free.
+trace.add_rss_stat(103, tid=11, member=0, size=10, mm_id=0x1234, curr=0)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_after_free.sql b/test/trace_processor/rss_stat_after_free.sql
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_after_free.sql
rename to test/trace_processor/rss_stat_after_free.sql
diff --git a/test/trace_processor/parsing/rss_stat_legacy.out b/test/trace_processor/rss_stat_legacy.out
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_legacy.out
rename to test/trace_processor/rss_stat_legacy.out
diff --git a/test/trace_processor/rss_stat_legacy.py b/test/trace_processor/rss_stat_legacy.py
new file mode 100644
index 0000000..c9d6c17
--- /dev/null
+++ b/test/trace_processor/rss_stat_legacy.py
@@ -0,0 +1,52 @@
+#!/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 legacy rss_stat events on old kernels which
+# do not have the mm_id change and thus we cannot accurately track
+# rss changes when one process changes another's mm struct.
+
+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(ts=1)
+trace.add_process(10, 0, "process")
+
+trace.add_ftrace_packet(0)
+
+# Create a new child process (treated internally as a thread) of kthreadd.
+trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
+
+# Add an event on tid 3 which affects its own rss.
+trace.add_rss_stat(ts=90, tid=3, member=0, size=9)
+
+# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
+# where kthreadd is cleaning up the mm struct of another process.
+trace.add_rss_stat(ts=91, tid=3, member=0, size=900)
+
+# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
+# where a process reaches into another process' mm struct.
+trace.add_rss_stat(ts=99, tid=10, member=0, size=10)
+
+# Add an event on tid 10 which affects its own rss.
+trace.add_rss_stat(ts=100, tid=10, member=0, size=1000)
+
+# Add an event on tid 10 from tid 3.
+trace.add_rss_stat(ts=101, tid=3, member=0, size=900)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id.out b/test/trace_processor/rss_stat_mm_id.out
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_mm_id.out
rename to test/trace_processor/rss_stat_mm_id.out
diff --git a/test/trace_processor/rss_stat_mm_id.py b/test/trace_processor/rss_stat_mm_id.py
new file mode 100644
index 0000000..d7101a5
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id.py
@@ -0,0 +1,52 @@
+#!/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 handling of the mm_id field in the rss_stat
+# event.
+
+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(ts=1)
+trace.add_process(10, 0, "process")
+
+trace.add_ftrace_packet(0)
+
+# Create a new child process (treated internally as a thread) of kthreadd.
+trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
+
+# Add an event on tid 3 which affects its own rss.
+trace.add_rss_stat(ts=90, tid=3, member=0, size=9, mm_id=4321, curr=True)
+
+# Try to add an event for tid 10. However, as we've not seen an event
+# with curr == True for tid == 10, this event will be dropped.
+trace.add_rss_stat(ts=91, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
+# where a process reaches into another process' mm struct.
+trace.add_rss_stat(ts=99, tid=10, member=0, size=10, mm_id=4321, curr=False)
+
+# Add an event on tid 10 which affects its own rss.
+trace.add_rss_stat(ts=100, tid=10, member=0, size=1000, mm_id=1234, curr=True)
+
+# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
+# where kthreadd is cleaning up the mm struct of another process.
+trace.add_rss_stat(ts=101, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id_clone.out b/test/trace_processor/rss_stat_mm_id_clone.out
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_mm_id_clone.out
rename to test/trace_processor/rss_stat_mm_id_clone.out
diff --git a/test/trace_processor/rss_stat_mm_id_clone.py b/test/trace_processor/rss_stat_mm_id_clone.py
new file mode 100644
index 0000000..42319c1
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_clone.py
@@ -0,0 +1,98 @@
+#!/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 handling of the mm_id field in the rss_stat
+# event during clone events which have various flag combinations set.
+
+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(ts=1)
+trace.add_process(10, 1, "parent_process")
+trace.add_process(3, 2, "kernel_thread")
+
+# In this packet, check what happens to userspace processes with different
+# clone flags.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the main thread of the process to associate it
+# with an mm_id.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Create a newtask event emulating vfork/posix_spawn (i.e. CLONE_VM and
+# CLONE_VFORK set).
+trace.add_newtask(
+    101,
+    tid=10,
+    new_tid=11,
+    new_comm="child_process",
+    flags=synth_common.CLONE_VFORK | synth_common.CLONE_VM)
+
+# The child process will now change its own (and parent's) VM space with
+# |curr| set to 1 (emulating cleaning up some memory in parent).
+trace.add_rss_stat(102, tid=11, member=0, size=90, mm_id=0x1234, curr=1)
+
+# At this point, the child process will obtain a new mm struct. From this
+# point on, all mm_ids from the child should be different from the parent.
+
+# The child process will now change its parents VM space with curr set to
+# 0 (emulating e.g. cleaning up its stack).
+trace.add_rss_stat(103, tid=11, member=0, size=85, mm_id=0x1234, curr=0)
+
+# Now the child process should exec another process.
+
+# The child can now change its own memory.
+trace.add_rss_stat(104, tid=11, member=0, size=10, mm_id=0x5678, curr=1)
+
+# The parent can now resume execution and may emit another rss event.
+trace.add_rss_stat(105, tid=10, member=0, size=95, mm_id=0x1234, curr=1)
+
+# The parent can now go ahead and start a new thread.
+trace.add_newtask(
+    106,
+    tid=10,
+    new_tid=12,
+    new_comm="parent_thread",
+    flags=synth_common.CLONE_VM | synth_common.CLONE_THREAD)
+
+# Since this thread shares mm space with the parent, it should have the
+# same mm id and have curr set to 1.
+trace.add_rss_stat(107, tid=12, member=0, size=105, mm_id=0x1234, curr=1)
+
+# The parent can also emit events with the same mm struct at the same time.
+trace.add_rss_stat(108, tid=10, member=0, size=110, mm_id=0x1234, curr=1)
+
+# In this packet, we check what happens to kernel threads in RSS stat.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the the existing kernel thread.
+trace.add_rss_stat(100, tid=3, member=0, size=10, mm_id=0x2345, curr=1)
+
+# Start a new kernel thread.
+trace.add_newtask(
+    101,
+    tid=2,
+    new_tid=4,
+    new_comm="kernel_thread2",
+    flags=synth_common.CLONE_VM)
+
+# Emit a rss stat for the new kernel thread.
+trace.add_rss_stat(102, tid=4, member=0, size=20, mm_id=0x2345, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/rss_stat_mm_id_reuse.out b/test/trace_processor/rss_stat_mm_id_reuse.out
similarity index 100%
rename from test/trace_processor/parsing/rss_stat_mm_id_reuse.out
rename to test/trace_processor/rss_stat_mm_id_reuse.out
diff --git a/test/trace_processor/rss_stat_mm_id_reuse.py b/test/trace_processor/rss_stat_mm_id_reuse.py
new file mode 100644
index 0000000..142fe6c
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_reuse.py
@@ -0,0 +1,43 @@
+#!/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 handling of the mm_id field in the rss_stat
+# event when mm_structs are reused on process death.
+
+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(ts=1)
+trace.add_process(10, 1, "parent_process")
+
+trace.add_ftrace_packet(1)
+
+# Emit an event for the process.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Now kill the process.
+trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
+
+# Create a new thread which reuses the pid and mm struct.
+trace.add_newtask(102, tid=1, new_tid=10, new_comm="new_process", flags=0)
+
+# Emit an event for the new thread.
+trace.add_rss_stat(103, tid=10, member=0, size=10, mm_id=0x1234, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/sched_slices.sql b/test/trace_processor/sched_slices.sql
similarity index 100%
rename from test/trace_processor/parsing/sched_slices.sql
rename to test/trace_processor/sched_slices.sql
diff --git a/test/trace_processor/sched_slices_sched_switch_compact.out b/test/trace_processor/sched_slices_sched_switch_compact.out
new file mode 100644
index 0000000..c570299
--- /dev/null
+++ b/test/trace_processor/sched_slices_sched_switch_compact.out
@@ -0,0 +1,77 @@
+"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
new file mode 100644
index 0000000..fe6f0c5
--- /dev/null
+++ b/test/trace_processor/sched_slices_sched_switch_original.out
@@ -0,0 +1,83 @@
+"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/parsing/sched_smoke.sql b/test/trace_processor/sched_smoke.sql
similarity index 100%
rename from test/trace_processor/parsing/sched_smoke.sql
rename to test/trace_processor/sched_smoke.sql
diff --git a/test/trace_processor/parsing/sched_smoke_trailing_empty.out b/test/trace_processor/sched_smoke_trailing_empty.out
similarity index 100%
rename from test/trace_processor/parsing/sched_smoke_trailing_empty.out
rename to test/trace_processor/sched_smoke_trailing_empty.out
diff --git a/test/trace_processor/parsing/sched_wakeup.sql b/test/trace_processor/sched_wakeup.sql
similarity index 100%
rename from test/trace_processor/parsing/sched_wakeup.sql
rename to test/trace_processor/sched_wakeup.sql
diff --git a/test/trace_processor/parsing/sched_wakeup_android_sched_and_ps.out b/test/trace_processor/sched_wakeup_android_sched_and_ps.out
similarity index 100%
rename from test/trace_processor/parsing/sched_wakeup_android_sched_and_ps.out
rename to test/trace_processor/sched_wakeup_android_sched_and_ps.out
diff --git a/test/trace_processor/parsing/sched_waking_instants.sql b/test/trace_processor/sched_waking_instants.sql
similarity index 100%
rename from test/trace_processor/parsing/sched_waking_instants.sql
rename to test/trace_processor/sched_waking_instants.sql
diff --git a/test/trace_processor/parsing/sched_waking_instants_compact_sched.out b/test/trace_processor/sched_waking_instants_compact_sched.out
similarity index 100%
rename from test/trace_processor/parsing/sched_waking_instants_compact_sched.out
rename to test/trace_processor/sched_waking_instants_compact_sched.out
diff --git a/test/trace_processor/parsing/sched_waking_raw.sql b/test/trace_processor/sched_waking_raw.sql
similarity index 100%
rename from test/trace_processor/parsing/sched_waking_raw.sql
rename to test/trace_processor/sched_waking_raw.sql
diff --git a/test/trace_processor/parsing/sched_waking_raw_compact_sched.out b/test/trace_processor/sched_waking_raw_compact_sched.out
similarity index 100%
rename from test/trace_processor/parsing/sched_waking_raw_compact_sched.out
rename to test/trace_processor/sched_waking_raw_compact_sched.out
diff --git a/test/trace_processor/process_tracking/sde_tracing_mark_write.textproto b/test/trace_processor/sde_tracing_mark_write.textproto
similarity index 100%
rename from test/trace_processor/process_tracking/sde_tracing_mark_write.textproto
rename to test/trace_processor/sde_tracing_mark_write.textproto
diff --git a/test/trace_processor/smoke/sfgate_smoke.out b/test/trace_processor/sfgate_smoke.out
similarity index 100%
rename from test/trace_processor/smoke/sfgate_smoke.out
rename to test/trace_processor/sfgate_smoke.out
diff --git a/test/trace_processor/smoke/sfgate_smoke_slices.out b/test/trace_processor/sfgate_smoke_slices.out
similarity index 100%
rename from test/trace_processor/smoke/sfgate_smoke_slices.out
rename to test/trace_processor/sfgate_smoke_slices.out
diff --git a/test/trace_processor/span_join/slice_span_join_b118665515.sql b/test/trace_processor/slice_span_join_b118665515.sql
similarity index 100%
rename from test/trace_processor/span_join/slice_span_join_b118665515.sql
rename to test/trace_processor/slice_span_join_b118665515.sql
diff --git a/test/trace_processor/process_tracking/slice_with_pid.sql b/test/trace_processor/slice_with_pid.sql
similarity index 100%
rename from test/trace_processor/process_tracking/slice_with_pid.sql
rename to test/trace_processor/slice_with_pid.sql
diff --git a/test/trace_processor/process_tracking/slice_with_pid_sde_tracing_mark_write.out b/test/trace_processor/slice_with_pid_sde_tracing_mark_write.out
similarity index 100%
rename from test/trace_processor/process_tracking/slice_with_pid_sde_tracing_mark_write.out
rename to test/trace_processor/slice_with_pid_sde_tracing_mark_write.out
diff --git a/test/trace_processor/common/smoke.sql b/test/trace_processor/smoke.sql
similarity index 100%
rename from test/trace_processor/common/smoke.sql
rename to test/trace_processor/smoke.sql
diff --git a/test/trace_processor/smoke/index b/test/trace_processor/smoke/index
deleted file mode 100644
index ebc2042..0000000
--- a/test/trace_processor/smoke/index
+++ /dev/null
@@ -1,23 +0,0 @@
-# Contains smoke tests which test the most fundamentally important
-# features of trace processor
-#
-# Note: new tests here should only be added by the Perfetto team.
-
-# JSON trace parsing
-../../data/sfgate.json ../common/smoke.sql sfgate_smoke.out
-../../data/sfgate.json ../common/smoke_slices.sql sfgate_smoke_slices.out
-
-# Sched events
-../../data/android_sched_and_ps.pb ../common/smoke.sql android_sched_and_ps_smoke.out
-
-# Compresesed traces
-../../data/compressed.pb ../common/smoke.sql compressed_smoke.out
-
-# Sched events from sythetic trace
-../common/synth_1.py ../common/smoke.sql synth_1_smoke.out
-
-# Compute CPU time metric testing several core tables.
-../../data/example_android_trace_30s.pb thread_cpu_time.sql thread_cpu_time_example_android_trace_30s.out
-
-# Compute power proxy metric
-../../data/cpu_counters.pb proxy_power.sql proxy_power.out
diff --git a/test/trace_processor/smoke/proxy_power.out b/test/trace_processor/smoke/proxy_power.out
deleted file mode 100644
index d57cfc5..0000000
--- a/test/trace_processor/smoke/proxy_power.out
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-"utid","power_mas"
-122,80.118876
-121,73.090167
-140,54.378097
-31,15.297968
-161,13.740925
-23,12.703770
-205,11.924118
-43,10.011150
-258,9.165919
-1,9.137632
diff --git a/test/trace_processor/smoke/proxy_power.sql b/test/trace_processor/smoke/proxy_power.sql
deleted file mode 100644
index 5f055ab..0000000
--- a/test/trace_processor/smoke/proxy_power.sql
+++ /dev/null
@@ -1,34 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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/android_proxy_power.sql') AS suppress_query_output;
-
--- The test trace doesn't contain metadata necessary to determine the device
--- name, so we create a table with the name directly.
-DROP VIEW device;
-
-CREATE TABLE device (name STRING);
-
-INSERT INTO device VALUES ('walleye');
-
--- Select the top 10 threads by power usage.
-SELECT
-  utid,
-  SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
-FROM power_per_thread
-GROUP BY utid
-ORDER BY power_mas DESC
-LIMIT 10;
diff --git a/test/trace_processor/smoke/thread_cpu_time_example_android_trace_30s.out b/test/trace_processor/smoke/thread_cpu_time_example_android_trace_30s.out
deleted file mode 100644
index 63be1d6..0000000
--- a/test/trace_processor/smoke/thread_cpu_time_example_android_trace_30s.out
+++ /dev/null
@@ -1,1655 +0,0 @@
-"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","[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]"
diff --git a/test/trace_processor/fuchsia/smoke_counters.sql b/test/trace_processor/smoke_counters.sql
similarity index 100%
rename from test/trace_processor/fuchsia/smoke_counters.sql
rename to test/trace_processor/smoke_counters.sql
diff --git a/test/trace_processor/fuchsia/smoke_instants.sql b/test/trace_processor/smoke_instants.sql
similarity index 100%
rename from test/trace_processor/fuchsia/smoke_instants.sql
rename to test/trace_processor/smoke_instants.sql
diff --git a/test/trace_processor/common/smoke_slices.sql b/test/trace_processor/smoke_slices.sql
similarity index 100%
rename from test/trace_processor/common/smoke_slices.sql
rename to test/trace_processor/smoke_slices.sql
diff --git a/test/trace_processor/tables/smoke_window.sql b/test/trace_processor/smoke_window.sql
similarity index 100%
rename from test/trace_processor/tables/smoke_window.sql
rename to test/trace_processor/smoke_window.sql
diff --git a/test/trace_processor/span_join/index b/test/trace_processor/span_join/index
deleted file mode 100644
index b0635e2..0000000
--- a/test/trace_processor/span_join/index
+++ /dev/null
@@ -1,23 +0,0 @@
-# Contains tests on the behaviour of the SPAN_JOIN operator table.
-
-# Smoke tests
-../common/synth_1.py span_join_unordered_cols.sql span_join_unordered_cols_synth_1.out
-../common/synth_1.py span_join_unordered_cols_reverse.sql span_join_unordered_cols_synth_1.out
-../../data/android_sched_and_ps.pb span_join_zero_negative_dur.sql span_join_zero_negative_dur.out
-
-# Regression tests
-../../data/android_sched_and_ps.pb slice_span_join_b118665515.sql android_sched_and_ps_slice_span_join_b118665515.out
-../../data/android_sched_and_ps.pb span_join_unpartitioned_empty.sql span_join_unpartitioned_empty.out
-
-# Outer join
-../../data/android_sched_and_ps.pb span_outer_join.sql span_outer_join.out
-../../data/android_sched_and_ps.pb span_outer_join_empty.sql span_outer_join_empty_android_sched_and_ps.out
-
-# Left join
-../../data/android_sched_and_ps.pb span_left_join.sql span_left_join.out
-../../data/android_sched_and_ps.pb span_left_join_unpartitioned.sql span_left_join_unpartitioned.out
-../../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_left_join_empty_right.sql span_left_join_empty_right.out
-../../data/android_sched_and_ps.pb span_left_join_unordered.sql span_left_join_unordered_android_sched_and_ps.out
-
diff --git a/test/trace_processor/span_join/span_join_unordered_cols.sql b/test/trace_processor/span_join_unordered_cols.sql
similarity index 100%
rename from test/trace_processor/span_join/span_join_unordered_cols.sql
rename to test/trace_processor/span_join_unordered_cols.sql
diff --git a/test/trace_processor/span_join/span_join_unordered_cols_reverse.sql b/test/trace_processor/span_join_unordered_cols_reverse.sql
similarity index 100%
rename from test/trace_processor/span_join/span_join_unordered_cols_reverse.sql
rename to test/trace_processor/span_join_unordered_cols_reverse.sql
diff --git a/test/trace_processor/span_join/span_join_unordered_cols_synth_1.out b/test/trace_processor/span_join_unordered_cols_synth_1.out
similarity index 100%
rename from test/trace_processor/span_join/span_join_unordered_cols_synth_1.out
rename to test/trace_processor/span_join_unordered_cols_synth_1.out
diff --git a/test/trace_processor/span_join/span_join_unpartitioned_empty.out b/test/trace_processor/span_join_unpartitioned_empty.out
similarity index 100%
rename from test/trace_processor/span_join/span_join_unpartitioned_empty.out
rename to test/trace_processor/span_join_unpartitioned_empty.out
diff --git a/test/trace_processor/span_join/span_join_unpartitioned_empty.sql b/test/trace_processor/span_join_unpartitioned_empty.sql
similarity index 100%
rename from test/trace_processor/span_join/span_join_unpartitioned_empty.sql
rename to test/trace_processor/span_join_unpartitioned_empty.sql
diff --git a/test/trace_processor/span_join/span_join_zero_negative_dur.out b/test/trace_processor/span_join_zero_negative_dur.out
similarity index 100%
rename from test/trace_processor/span_join/span_join_zero_negative_dur.out
rename to test/trace_processor/span_join_zero_negative_dur.out
diff --git a/test/trace_processor/span_join/span_join_zero_negative_dur.sql b/test/trace_processor/span_join_zero_negative_dur.sql
similarity index 100%
rename from test/trace_processor/span_join/span_join_zero_negative_dur.sql
rename to test/trace_processor/span_join_zero_negative_dur.sql
diff --git a/test/trace_processor/span_join/span_left_join.out b/test/trace_processor/span_left_join.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join.out
rename to test/trace_processor/span_left_join.out
diff --git a/test/trace_processor/span_join/span_left_join.sql b/test/trace_processor/span_left_join.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join.sql
rename to test/trace_processor/span_left_join.sql
diff --git a/test/trace_processor/span_join/span_left_join_empty_right.out b/test/trace_processor/span_left_join_empty_right.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_empty_right.out
rename to test/trace_processor/span_left_join_empty_right.out
diff --git a/test/trace_processor/span_join/span_left_join_empty_right.sql b/test/trace_processor/span_left_join_empty_right.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_empty_right.sql
rename to test/trace_processor/span_left_join_empty_right.sql
diff --git a/test/trace_processor/span_join/span_left_join_left_partitioned.out b/test/trace_processor/span_left_join_left_partitioned.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_left_partitioned.out
rename to test/trace_processor/span_left_join_left_partitioned.out
diff --git a/test/trace_processor/span_join/span_left_join_left_partitioned.sql b/test/trace_processor/span_left_join_left_partitioned.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_left_partitioned.sql
rename to test/trace_processor/span_left_join_left_partitioned.sql
diff --git a/test/trace_processor/span_join/span_left_join_left_unpartitioned.out b/test/trace_processor/span_left_join_left_unpartitioned.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_left_unpartitioned.out
rename to test/trace_processor/span_left_join_left_unpartitioned.out
diff --git a/test/trace_processor/span_join/span_left_join_left_unpartitioned.sql b/test/trace_processor/span_left_join_left_unpartitioned.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_left_unpartitioned.sql
rename to test/trace_processor/span_left_join_left_unpartitioned.sql
diff --git a/test/trace_processor/span_join/span_left_join_unordered.sql b/test/trace_processor/span_left_join_unordered.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_unordered.sql
rename to test/trace_processor/span_left_join_unordered.sql
diff --git a/test/trace_processor/span_join/span_left_join_unordered_android_sched_and_ps.out b/test/trace_processor/span_left_join_unordered_android_sched_and_ps.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_unordered_android_sched_and_ps.out
rename to test/trace_processor/span_left_join_unordered_android_sched_and_ps.out
diff --git a/test/trace_processor/span_join/span_left_join_unpartitioned.out b/test/trace_processor/span_left_join_unpartitioned.out
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_unpartitioned.out
rename to test/trace_processor/span_left_join_unpartitioned.out
diff --git a/test/trace_processor/span_join/span_left_join_unpartitioned.sql b/test/trace_processor/span_left_join_unpartitioned.sql
similarity index 100%
rename from test/trace_processor/span_join/span_left_join_unpartitioned.sql
rename to test/trace_processor/span_left_join_unpartitioned.sql
diff --git a/test/trace_processor/span_join/span_outer_join.out b/test/trace_processor/span_outer_join.out
similarity index 100%
rename from test/trace_processor/span_join/span_outer_join.out
rename to test/trace_processor/span_outer_join.out
diff --git a/test/trace_processor/span_join/span_outer_join.sql b/test/trace_processor/span_outer_join.sql
similarity index 100%
rename from test/trace_processor/span_join/span_outer_join.sql
rename to test/trace_processor/span_outer_join.sql
diff --git a/test/trace_processor/span_join/span_outer_join_empty.sql b/test/trace_processor/span_outer_join_empty.sql
similarity index 100%
rename from test/trace_processor/span_join/span_outer_join_empty.sql
rename to test/trace_processor/span_outer_join_empty.sql
diff --git a/test/trace_processor/span_join/span_outer_join_empty_android_sched_and_ps.out b/test/trace_processor/span_outer_join_empty_android_sched_and_ps.out
similarity index 100%
rename from test/trace_processor/span_join/span_outer_join_empty_android_sched_and_ps.out
rename to test/trace_processor/span_outer_join_empty_android_sched_and_ps.out
diff --git a/test/trace_processor/profiling/stack_profile_tracker_empty_callstack.out b/test/trace_processor/stack_profile_tracker_empty_callstack.out
similarity index 100%
rename from test/trace_processor/profiling/stack_profile_tracker_empty_callstack.out
rename to test/trace_processor/stack_profile_tracker_empty_callstack.out
diff --git a/test/trace_processor/profiling/stack_profile_tracker_empty_callstack.sql b/test/trace_processor/stack_profile_tracker_empty_callstack.sql
similarity index 100%
rename from test/trace_processor/profiling/stack_profile_tracker_empty_callstack.sql
rename to test/trace_processor/stack_profile_tracker_empty_callstack.sql
diff --git a/test/trace_processor/profiling/stack_profile_tracker_empty_callstack.textproto b/test/trace_processor/stack_profile_tracker_empty_callstack.textproto
similarity index 100%
rename from test/trace_processor/profiling/stack_profile_tracker_empty_callstack.textproto
rename to test/trace_processor/stack_profile_tracker_empty_callstack.textproto
diff --git a/test/trace_processor/startup/android_startup.out b/test/trace_processor/startup/android_startup.out
deleted file mode 100644
index a7dd383..0000000
--- a/test/trace_processor/startup/android_startup.out
+++ /dev/null
@@ -1,48 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 2
-    package_name: "com.google.android.calendar"
-    process_name: "com.google.android.calendar"
-    process: {
-      name: "com.google.android.calendar"
-      uid: 10001
-      package {
-        package_name: "com.google.android.calendar"
-        apk_version_code: 123
-        debuggable: false
-      }
-      packages_for_uid {
-        package_name: "com.google.android.calendar"
-        apk_version_code: 123
-        debuggable: false
-      }
-    }
-    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: 129
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 10
-      }
-      other_processes_spawned_count: 1
-      time_activity_manager {
-        dur_ns: 8
-        dur_ms: 8e-06
-      }
-      mcycles_by_core_type {
-      }
-      dur_ms: 0.000108
-    }
-    report_fully_drawn {
-      dur_ns: 198
-      dur_ms: 0.000198
-    }
-    event_timestamps {
-      intent_received: 102
-      first_frame: 210
-    }
-  }
-}
diff --git a/test/trace_processor/startup/android_startup.py b/test/trace_processor/startup/android_startup.py
deleted file mode 100644
index 494849c..0000000
--- a/test/trace_processor/startup/android_startup.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar', 10001)
-trace.add_process(4, 1, 'com.google.android.calendar')
-
-trace.add_package_list(
-    ts=1, name='com.google.android.calendar', uid=10001, version_code=123)
-
-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)
-
-# Some time after, add a slice for fully drawn frame.
-trace.add_atrace_begin(
-    ts=300,
-    tid=3,
-    pid=3,
-    buf='reportFullyDrawn() for \{com.google.android.calendar\}')
-trace.add_atrace_end(ts=305, 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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_attribution.out b/test/trace_processor/startup/android_startup_attribution.out
deleted file mode 100644
index 5046ed4..0000000
--- a/test/trace_processor/startup/android_startup_attribution.out
+++ /dev/null
@@ -1,68 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 1
-    package_name: "com.some.app"
-    process_name: "com.some.app"
-    zygote_new_process: false
-    to_first_frame {
-      dur_ns: 999999900
-      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
-        dur_ms: 2e-06
-      }
-      dur_ms: 999.9999
-      time_dex_open {
-        dur_ns: 20
-        dur_ms: 2e-05
-      }
-      time_verify_class {
-        dur_ns: 40
-        dur_ms: 4e-05
-      }
-      mcycles_by_core_type {
-      }
-      jit_compiled_methods: 2
-      time_jit_thread_pool_on_cpu {
-        dur_ns: 20
-        dur_ms: 2e-05
-      }
-      time_gc_total {
-        dur_ns: 130
-        dur_ms: 0.00013
-      }
-      time_gc_on_cpu {
-        dur_ns: 50
-        dur_ms: 5e-05
-      }
-    }
-    activity_hosting_process_count: 1
-    process {
-      name: "com.some.app"
-    }
-    event_timestamps {
-      intent_received: 100
-      first_frame: 1000000000
-    }
-    long_binder_transactions {
-      duration {
-        dur_ns: 100000000
-        dur_ms: 100
-      }
-      thread: "Binder"
-    }
-    long_binder_transactions {
-      duration {
-        dur_ns: 200000000
-        dur_ms: 200
-      }
-      thread: "fonts"
-    }
-  }
-}
diff --git a/test/trace_processor/startup/android_startup_attribution.py b/test/trace_processor/startup/android_startup_attribution.py
deleted file mode 100644
index 61d9ebc..0000000
--- a/test/trace_processor/startup/android_startup_attribution.py
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-APP_PID = 3
-APP_TID = 1
-SECOND_APP_TID = 3
-JIT_TID = 4
-GC_TID = 5
-GC2_TID = 6
-BINDER_TID = 7
-FONTS_TID = 8
-SYSTEM_SERVER_PID = 2
-SYSTEM_SERVER_TID = 2
-LAUNCH_START_TS = 100
-LAUNCH_END_TS = 10**9
-
-trace = synth_common.create_trace()
-trace.add_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(SYSTEM_SERVER_PID, 1, 'system_server')
-trace.add_process(APP_PID, 1, 'com.some.app')
-trace.add_thread(tid=SECOND_APP_TID, tgid=APP_PID, cmdline='second_thread')
-trace.add_thread(
-    tid=JIT_TID,
-    tgid=APP_PID,
-    cmdline='Jit thread pool',
-    name='Jit thread pool')
-trace.add_thread(
-    tid=GC_TID, tgid=APP_PID, cmdline='HeapTaskDaemon', name='HeapTaskDaemon')
-trace.add_thread(
-    tid=GC2_TID, tgid=APP_PID, cmdline='HeapTaskDaemon', name='HeapTaskDaemon')
-trace.add_thread(tid=BINDER_TID, tgid=APP_PID, cmdline='Binder', name='Binder')
-trace.add_thread(tid=FONTS_TID, tgid=APP_PID, cmdline='fonts', name='fonts')
-
-trace.add_ftrace_packet(cpu=0)
-# Start intent.
-trace.add_atrace_begin(
-    ts=LAUNCH_START_TS,
-    pid=SYSTEM_SERVER_PID,
-    tid=SYSTEM_SERVER_TID,
-    buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(
-    ts=LAUNCH_START_TS + 1, tid=SYSTEM_SERVER_TID, pid=SYSTEM_SERVER_PID)
-
-# System server launching the app.
-trace.add_atrace_async_begin(
-    ts=LAUNCH_START_TS + 2,
-    pid=SYSTEM_SERVER_PID,
-    tid=SYSTEM_SERVER_TID,
-    buf='launching: com.some.app')
-
-# OpenDex slices within the startup.
-trace.add_atrace_begin(
-    ts=150, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(something)')
-trace.add_atrace_end(ts=165, pid=APP_PID, tid=APP_TID)
-
-trace.add_atrace_begin(
-    ts=170, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(something else)')
-trace.add_atrace_end(ts=175, pid=APP_PID, tid=APP_TID)
-
-# OpenDex slice outside the startup.
-trace.add_atrace_begin(
-    ts=5, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(nothing)')
-trace.add_atrace_end(ts=35, pid=APP_PID, tid=APP_TID)
-
-trace.add_atrace_async_end(
-    ts=LAUNCH_END_TS,
-    tid=SYSTEM_SERVER_TID,
-    pid=SYSTEM_SERVER_PID,
-    buf='launching: com.some.app')
-
-# VerifyClass slices within the startup.
-trace.add_atrace_begin(ts=250, pid=APP_PID, tid=APP_TID, buf='VerifyClass vr')
-trace.add_atrace_end(ts=265, pid=APP_PID, tid=APP_TID)
-
-trace.add_atrace_begin(ts=270, pid=APP_PID, tid=APP_TID, buf='VerifyClass dl')
-trace.add_atrace_end(ts=275, pid=APP_PID, tid=APP_TID)
-
-# VerifyClass slice outside the startup.
-trace.add_atrace_begin(ts=55, pid=APP_PID, tid=APP_TID, buf='VerifyClass xf')
-trace.add_atrace_end(ts=65, pid=APP_PID, tid=APP_TID)
-
-# VerifyClass slice on a different thread, overlapping with the other slices.
-trace.add_atrace_begin(
-    ts=260, pid=APP_PID, tid=SECOND_APP_TID, buf='VerifyClass vp')
-trace.add_atrace_end(ts=280, pid=APP_PID, tid=SECOND_APP_TID)
-
-# JIT compilation slices
-trace.add_atrace_begin(
-    ts=150, pid=APP_PID, tid=JIT_TID, buf='JIT compiling someting')
-trace.add_atrace_end(ts=160, pid=APP_PID, tid=JIT_TID)
-
-trace.add_sched(ts=155, prev_pid=0, next_pid=JIT_TID)
-trace.add_sched(ts=165, prev_pid=JIT_TID, next_pid=0)
-
-trace.add_atrace_begin(
-    ts=170, pid=APP_PID, tid=JIT_TID, buf='JIT compiling something else')
-trace.add_atrace_end(ts=190, pid=APP_PID, tid=JIT_TID)
-
-trace.add_sched(ts=170, prev_pid=0, next_pid=JIT_TID)
-trace.add_sched(ts=175, prev_pid=JIT_TID, next_pid=0, prev_state='R')
-trace.add_sched(ts=185, prev_pid=0, next_pid=JIT_TID)
-trace.add_sched(ts=190, prev_pid=JIT_TID, next_pid=0)
-
-# JIT slice, but not on JIT thread.
-trace.add_atrace_begin(
-    ts=200, pid=APP_PID, tid=SECOND_APP_TID, buf='JIT compiling nothing')
-trace.add_atrace_end(ts=210, pid=APP_PID, tid=SECOND_APP_TID)
-
-# Slice on JIT thread, but name doesn't match
-trace.add_atrace_begin(
-    ts=200, pid=APP_PID, tid=JIT_TID, buf='JIT compiled something')
-trace.add_atrace_end(ts=210, pid=APP_PID, tid=JIT_TID)
-
-# GC slices.
-trace.add_atrace_begin(
-    ts=300, pid=APP_PID, tid=GC_TID, buf='Background concurrent copying GC')
-trace.add_atrace_end(ts=330, pid=APP_PID, tid=GC_TID)
-
-trace.add_atrace_begin(
-    ts=340, pid=APP_PID, tid=GC_TID, buf='CollectorTransition mark sweep GC')
-trace.add_atrace_end(ts=390, pid=APP_PID, tid=GC_TID)
-
-trace.add_atrace_begin(ts=320, pid=APP_PID, tid=GC2_TID, buf='semispace GC')
-trace.add_atrace_end(ts=370, pid=APP_PID, tid=GC2_TID)
-
-# Start running copying slice on the first thread
-trace.add_sched(ts=310, prev_pid=0, next_pid=GC_TID)
-# Switch to the second thread to run semispace slice
-trace.add_sched(ts=325, prev_pid=GC_TID, next_pid=GC2_TID)
-# Switch back to the first thread to run mark sweep slice
-trace.add_sched(ts=350, prev_pid=GC2_TID, next_pid=GC_TID)
-# Finish running for GC.
-trace.add_sched(ts=360, prev_pid=GC_TID, next_pid=0)
-
-# Long binder transactions.
-trace.add_atrace_begin(
-    ts=10**8, pid=APP_PID, tid=BINDER_TID, buf='binder transaction')
-trace.add_atrace_end(ts=2 * (10**8), pid=APP_PID, tid=BINDER_TID)
-
-trace.add_atrace_begin(
-    ts=3 * (10**8), pid=APP_PID, tid=FONTS_TID, buf='binder transaction')
-trace.add_atrace_end(ts=5 * (10**8), pid=APP_PID, tid=FONTS_TID)
-
-# A short binder transaction.
-trace.add_atrace_begin(
-    ts=10**7, pid=APP_PID, tid=BINDER_TID, buf='binder transaction')
-trace.add_atrace_end(ts=6 * (10**7), pid=APP_PID, tid=BINDER_TID)
-
-# Intent successful.
-trace.add_atrace_begin(
-    ts=LAUNCH_END_TS + 1,
-    pid=SYSTEM_SERVER_PID,
-    tid=SYSTEM_SERVER_TID,
-    buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
-trace.add_atrace_end(
-    ts=LAUNCH_END_TS + 2, tid=SYSTEM_SERVER_TID, pid=SYSTEM_SERVER_PID)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_battery.py b/test/trace_processor/startup/android_startup_battery.py
deleted file mode 100644
index 3727a12..0000000
--- a/test/trace_processor/startup/android_startup_battery.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_breakdown.out b/test/trace_processor/startup/android_startup_breakdown.out
deleted file mode 100644
index cebd9d0..0000000
--- a/test/trace_processor/startup/android_startup_breakdown.out
+++ /dev/null
@@ -1,75 +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: 108000000000
-      main_thread_by_task_state {
-        running_dur_ns: 25000000000
-        runnable_dur_ns: 5000000000
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 0
-      }
-      other_processes_spawned_count: 0
-      time_activity_manager {
-        dur_ns: 8000000000
-        dur_ms: 8000
-      }
-      time_bind_application {
-        dur_ns: 9000000000
-        dur_ms: 9000
-      }
-      time_before_start_process {
-        dur_ns: 18000000000
-        dur_ms: 18000
-      }
-      time_during_start_process {
-        dur_ns: 35000000000
-        dur_ms: 35000
-      }
-      dur_ms: 108000
-      to_bind_application {
-        dur_ns: 83000000000
-        dur_ms: 83000
-      }
-      time_inflate {
-        dur_ns: 3000000000
-        dur_ms: 3000
-      }
-      time_get_resources {
-        dur_ns: 1000000000
-        dur_ms: 1000
-      }
-      mcycles_by_core_type {
-        unknown: 103
-      }
-    }
-    activity_hosting_process_count: 1
-    process {
-      name: "com.google.android.calendar"
-    }
-    activities {
-      name: "com.google.android.calendar.MainActivity"
-      method: "performCreate"
-      ts_method_start: 188000000000
-    }
-    optimization_status {
-      odex_status: "up-to-date"
-      compilation_filter: "speed"
-      compilation_reason: "prebuilt"
-      location: "/system/framework/oat/arm/com.android.location.provider.odex"
-    }
-    optimization_status {
-      odex_status: "io-error-no-oat"
-      compilation_filter: "run-from-apk"
-      compilation_reason: "unknown"
-      location: "error"
-    }
-    event_timestamps {
-      intent_received: 102000000000
-      first_frame: 210000000000
-    }
-  }
-}
diff --git a/test/trace_processor/startup/android_startup_breakdown.py b/test/trace_processor/startup/android_startup_breakdown.py
deleted file mode 100644
index 11df3e5..0000000
--- a/test/trace_processor/startup/android_startup_breakdown.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-
-def to_s(ts):
-  return ts * 1000 * 1000 * 1000
-
-
-trace = synth_common.create_trace()
-trace.add_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=to_s(102),
-    tid=2,
-    pid=2,
-    buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(ts=to_s(103), tid=2, pid=2)
-
-trace.add_atrace_async_begin(
-    ts=to_s(110), tid=2, pid=2, buf='launching: com.google.android.calendar')
-
-trace.add_atrace_begin(
-    ts=to_s(120), tid=2, pid=2, buf='Start proc: com.google.android.calendar')
-trace.add_atrace_end(ts=to_s(155), tid=2, pid=2)
-
-# Unrelated process binding, ignored
-trace.add_atrace_begin(ts=to_s(125), tid=1, pid=1, buf='bindApplication')
-trace.add_atrace_end(ts=to_s(195), tid=1, pid=1)
-
-trace.add_atrace_begin(ts=to_s(185), tid=3, pid=3, buf='bindApplication')
-trace.add_atrace_begin(
-    ts=to_s(188),
-    tid=3,
-    pid=3,
-    buf='performCreate:com.google.android.calendar.MainActivity')
-trace.add_atrace_begin(ts=to_s(188), tid=3, pid=3, buf='inflate')
-trace.add_atrace_end(ts=to_s(189), tid=3, pid=3)
-trace.add_atrace_begin(
-    ts=to_s(188), tid=3, pid=3, buf='ResourcesManager#getResources')
-trace.add_atrace_end(ts=to_s(189), tid=3, pid=3)
-trace.add_atrace_begin(ts=to_s(190), tid=3, pid=3, buf='inflate')
-trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
-trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
-trace.add_atrace_begin(
-    ts=193,
-    tid=3,
-    pid=3,
-    buf='performResume:com.google.android.calendar.MainActivity')
-trace.add_atrace_end(ts=to_s(194), tid=3, pid=3)
-trace.add_atrace_end(ts=to_s(195), tid=3, pid=3)
-
-trace.add_atrace_begin(
-    ts=to_s(200),
-    tid=3,
-    pid=3,
-    buf='location=error status=io-error-no-oat ' \
-        'filter=run-from-apk reason=unknown')
-trace.add_atrace_end(ts=to_s(202), tid=3, pid=3)
-trace.add_atrace_begin(
-    ts=to_s(204),
-    tid=3,
-    pid=3,
-    buf='location=/system/framework/oat/arm/com.android.location.provider' \
-        '.odex status=up-to-date filter=speed reason=prebuilt')
-trace.add_atrace_end(ts=to_s(205), tid=3, pid=3)
-
-trace.add_atrace_async_end(
-    ts=to_s(210), tid=2, pid=2, buf='launching: com.google.android.calendar')
-trace.add_atrace_begin(
-    ts=to_s(211),
-    tid=2,
-    pid=2,
-    buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
-trace.add_atrace_end(ts=to_s(212), tid=2, pid=2)
-
-# Add the scheduling data to match the timestamps of events above but with
-# some idle time inbetween to make the computation more realisitic.
-trace.add_cpufreq(ts=to_s(50), freq=1000, cpu=0)
-trace.add_sched(ts=to_s(100), prev_pid=0, next_pid=2)
-trace.add_sched(ts=to_s(115), prev_pid=2, next_pid=0)
-trace.add_sched(ts=to_s(120), prev_pid=0, next_pid=2)
-trace.add_sched(ts=to_s(125), prev_pid=2, next_pid=1)
-trace.add_sched(ts=to_s(150), prev_pid=1, next_pid=2)
-trace.add_sched(ts=to_s(160), prev_pid=2, next_pid=1)
-trace.add_sched(ts=to_s(180), prev_pid=1, next_pid=3)
-trace.add_sched(ts=to_s(205), prev_pid=3, next_pid=2)
-trace.add_sched(ts=to_s(220), prev_pid=2, next_pid=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_cpu.py b/test/trace_processor/startup/android_startup_cpu.py
deleted file mode 100644
index 0876340..0000000
--- a/test/trace_processor/startup/android_startup_cpu.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_system_info(fingerprint="fingerprint/walleye/P")
-
-trace.add_ftrace_packet(cpu=0)
-
-# CPU counters for CPU 0.
-trace.add_cpufreq(ts=9 * 1000000, freq=500000, cpu=0)
-trace.add_cpufreq(ts=15 * 1000000, freq=1400000, cpu=0)
-trace.add_cpufreq(ts=17 * 1000000, freq=2500000, cpu=0)
-
-# CPU counters for CPU 6.
-trace.add_cpufreq(ts=11 * 1000000, freq=2000000, cpu=6)
-trace.add_cpufreq(ts=15 * 1000000, freq=8000000, cpu=6)
-
-# Add 3 processes. This also adds one main thread per process.
-trace.add_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 * 1000000, prev_pid=0, next_pid=1)
-trace.add_sched(ts=12 * 1000000, prev_pid=1, next_pid=3)
-trace.add_sched(ts=16 * 1000000, prev_pid=3, next_pid=4)
-trace.add_sched(ts=17 * 1000000, prev_pid=4, next_pid=2)
-trace.add_sched(ts=19 * 1000000, prev_pid=2, next_pid=0)
-
-# Schedule threads in CPU 6.
-trace.add_ftrace_packet(cpu=6)
-trace.add_sched(ts=11 * 1000000, prev_pid=0, next_pid=5)
-trace.add_sched(ts=13 * 1000000, prev_pid=5, next_pid=6)
-trace.add_sched(ts=16 * 1000000, prev_pid=6, next_pid=3)
-trace.add_sched(ts=18 * 1000000, prev_pid=3, next_pid=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_powrails.py b/test/trace_processor/startup/android_startup_powrails.py
deleted file mode 100644
index 3e1b6d7..0000000
--- a/test/trace_processor/startup/android_startup_powrails.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/android_startup_process_track.out b/test/trace_processor/startup/android_startup_process_track.out
deleted file mode 100644
index 357603d..0000000
--- a/test/trace_processor/startup/android_startup_process_track.out
+++ /dev/null
@@ -1,64 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 1
-    package_name: "com.google.android.calendar"
-    process_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
-        dur_ms: 2e-06
-      }
-      mcycles_by_core_type {
-      }
-      dur_ms: 4e-06
-    }
-    event_timestamps {
-      intent_received: 100
-      first_frame: 104
-    }
-    activity_hosting_process_count: 1
-  }
-  startup {
-    startup_id: 2
-    package_name: "com.google.android.calendar"
-    process_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
-        dur_ms: 2e-06
-      }
-      mcycles_by_core_type {
-      }
-      dur_ms: 4e-06
-    }
-    event_timestamps {
-      intent_received: 200
-      first_frame: 204
-    }
-    activity_hosting_process_count: 1
-  }
-}
diff --git a/test/trace_processor/startup/android_startup_process_track.py b/test/trace_processor/startup/android_startup_process_track.py
deleted file mode 100644
index a9696ad..0000000
--- a/test/trace_processor/startup/android_startup_process_track.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-# 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
-
-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_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)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/startup/index b/test/trace_processor/startup/index
deleted file mode 100644
index 1780fa8..0000000
--- a/test/trace_processor/startup/index
+++ /dev/null
@@ -1,12 +0,0 @@
-# Contains tests related to the startup of Android apps.
-
-# Startup metric tests.
-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_attribution.py android_startup android_startup_attribution.out
-
-# Other metrics associated with startup.
-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
diff --git a/test/trace_processor/stats.sql b/test/trace_processor/stats.sql
new file mode 100644
index 0000000..5962ae5
--- /dev/null
+++ b/test/trace_processor/stats.sql
@@ -0,0 +1,16 @@
+--
+-- 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 * from stats where name like 'ftrace_cpu_%' or name like 'traced_buf_%';
\ No newline at end of file
diff --git a/test/trace_processor/synth_1.py b/test/trace_processor/synth_1.py
new file mode 100644
index 0000000..88c466a
--- /dev/null
+++ b/test/trace_processor/synth_1.py
@@ -0,0 +1,42 @@
+#!/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()
+trace.add_process(1, 0, "init")
+trace.add_process(2, 1, "two_thread_process")
+trace.add_process(4, 1, "single_thread_process")
+trace.add_thread(3, 2, "two_thread_process")
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_sched(ts=1, prev_pid=1, next_pid=3)
+trace.add_cpufreq(ts=50, freq=50, cpu=0)
+trace.add_sched(ts=100, prev_pid=3, next_pid=2)
+trace.add_sched(ts=115, prev_pid=2, next_pid=3)
+
+trace.add_ftrace_packet(cpu=1)
+trace.add_sched(ts=50, prev_pid=4, next_pid=1)
+trace.add_sched(ts=120, prev_pid=1, next_pid=2)
+trace.add_sched(ts=170, prev_pid=2, next_pid=0)
+trace.add_sched(ts=250, prev_pid=0, next_pid=2)
+trace.add_sched(ts=390, prev_pid=2, next_pid=4)
+trace.add_cpufreq(ts=400, freq=100, cpu=0)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/tables/synth_1_filter_counter.out b/test/trace_processor/synth_1_filter_counter.out
similarity index 100%
rename from test/trace_processor/tables/synth_1_filter_counter.out
rename to test/trace_processor/synth_1_filter_counter.out
diff --git a/test/trace_processor/tables/synth_1_filter_sched.out b/test/trace_processor/synth_1_filter_sched.out
similarity index 100%
rename from test/trace_processor/tables/synth_1_filter_sched.out
rename to test/trace_processor/synth_1_filter_sched.out
diff --git a/test/trace_processor/smoke/synth_1_smoke.out b/test/trace_processor/synth_1_smoke.out
similarity index 100%
rename from test/trace_processor/smoke/synth_1_smoke.out
rename to test/trace_processor/synth_1_smoke.out
diff --git a/test/trace_processor/synth_oom.py b/test/trace_processor/synth_oom.py
new file mode 100644
index 0000000..434ef6e
--- /dev/null
+++ b/test/trace_processor/synth_oom.py
@@ -0,0 +1,63 @@
+#!/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
+
+trace = synth_common.create_trace()
+trace.add_packet()
+trace.add_process(1, 0, "init")
+trace.add_process(2, 1, "process_a")
+trace.add_process(3, 1, "process_b")
+
+trace.add_ftrace_packet(0)
+trace.add_rss_stat(100, 2, file_member, 100)
+trace.add_rss_stat(100, 2, anon_member, 200)
+trace.add_oom_score_update(100, 1000, 2)
+trace.add_rss_stat(105, 2, file_member, 50)
+trace.add_oom_score_update(107, -300, 2)
+trace.add_rss_stat(110, 2, anon_member, 100)
+trace.add_rss_stat(120, 2, anon_member, 75)
+trace.add_rss_stat(121, 2, file_member, 95)
+trace.add_oom_score_update(122, 300, 2)
+trace.add_rss_stat(123, 2, anon_member, 200)
+trace.add_rss_stat(124, 2, file_member, 75)
+trace.add_rss_stat(125, 2, file_member, 35)
+trace.add_oom_score_update(126, 0, 2)
+trace.add_rss_stat(126, 2, file_member, 0)
+trace.add_rss_stat(126, 2, anon_member, 0)
+
+trace.add_ftrace_packet(0)
+trace.add_rss_stat(104, 3, file_member, 400)
+trace.add_rss_stat(107, 3, anon_member, 300)
+trace.add_oom_score_update(110, 0, 3)
+trace.add_rss_stat(113, 3, file_member, 75)
+trace.add_rss_stat(114, 3, anon_member, 800)
+trace.add_oom_score_update(115, 600, 3)
+trace.add_rss_stat(117, 3, file_member, 25)
+trace.add_rss_stat(118, 3, file_member, 80)
+trace.add_oom_score_update(118, -500, 3)
+trace.add_rss_stat(123, 3, file_member, 85)
+trace.add_rss_stat(126, 3, anon_member, 600)
+trace.add_rss_stat(129, 3, file_member, 90)
+trace.add_oom_score_update(130, 200, 3)
+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/parsing/synth_oom_oom_query.out b/test/trace_processor/synth_oom_oom_query.out
similarity index 100%
rename from test/trace_processor/parsing/synth_oom_oom_query.out
rename to test/trace_processor/synth_oom_oom_query.out
diff --git a/test/trace_processor/synth_process_tracking.py b/test/trace_processor/synth_process_tracking.py
new file mode 100644
index 0000000..e44f196
--- /dev/null
+++ b/test/trace_processor/synth_process_tracking.py
@@ -0,0 +1,103 @@
+#!/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 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
+
+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=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
+# SQL level we should be able to tell that p1-t0 and p1-t2 belong to 'process1'
+# but p1-t1 should be left unjoinable.
+trace.add_packet(ts=5)
+trace.add_process(10, 0, "process1", 1001)
+trace.add_thread(12, 10, "p1-t2")
+
+# Now create another process (pid=20) with three threads(tids=20,21,22).
+# This will be slightly more complicated. We'll pretend that tids=20,21 were
+# 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=14, prev_pid=22, next_pid=0, prev_comm='p2-t2')
+
+# From the process tracker viewpoint we pretend we only scraped tids=20,21.
+trace.add_packet(ts=15)
+trace.add_process(20, 0, "process_2", 1002)
+trace.add_thread(21, 20, "p2-t1")
+
+# Finally the very complex case: a third process (pid=30) which spawns threads
+# in the following order (notation: A->B means thread A spawns thread B).
+# 31->32, 31->33, 32->34.
+# Last but not least we spawn a further process (pid=40) which spawns a thread
+# 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_packet(ts=26)
+trace.add_process(30, 0, "process_3")
+trace.add_thread(31, 30, "p3-t1")
+
+# This event pretends that TID=32 forks() a new process 40 (note the absence of
+# 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_packet(ts=29)
+trace.add_process(40, 0, "process_4")
+
+# 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')
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/parsing/sys.sql b/test/trace_processor/sys.sql
similarity index 100%
rename from test/trace_processor/parsing/sys.sql
rename to test/trace_processor/sys.sql
diff --git a/test/trace_processor/parsing/sys_syscall.out b/test/trace_processor/sys_syscall.out
similarity index 100%
rename from test/trace_processor/parsing/sys_syscall.out
rename to test/trace_processor/sys_syscall.out
diff --git a/test/trace_processor/syscall.py b/test/trace_processor/syscall.py
new file mode 100644
index 0000000..3ca27ef
--- /dev/null
+++ b/test/trace_processor/syscall.py
@@ -0,0 +1,35 @@
+#!/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_system_info(arch='aarch64')
+
+trace.add_packet()
+trace.add_process(pid=1, ppid=0, cmdline="init")
+trace.add_process(pid=2, ppid=1, cmdline="two_thread_process")
+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)
+trace.add_sys_exit(ts=106, tid=1, id=0, ret=0)
+trace.add_sys_exit(ts=110, tid=2, id=1, ret=0)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/systrace_html.out b/test/trace_processor/systrace_html.out
new file mode 100644
index 0000000..1ddb616
--- /dev/null
+++ b/test/trace_processor/systrace_html.out
@@ -0,0 +1,3700 @@
+"ts","cpu","dur","ts_end","utid","end_state","priority","upid","name","tid"
+6824711826499000,6,20000,6824711826519000,630,"S",100,630,"kworker/u17:1",1134
+6824711826519000,6,69000,6824711826588000,669,"S",120,669,"kworker/6:1",14833
+6824711826574000,2,133000,6824711826707000,2487,"S",120,739,"UsbFfs-worker",20308
+6824711826588000,6,32000,6824711826620000,5,"S",120,5,"rcu_preempt",7
+6824711826620000,6,72000,6824711826692000,38,"S",120,38,"rcuop/4",44
+6824711826692000,6,16000,6824711826708000,6,"S",120,6,"rcu_sched",8
+6824711826707000,2,81000,6824711826788000,52,"S",120,52,"rcuop/6",60
+6824711826708000,6,352000,6824711827060000,0,"R",120,"[NULL]","swapper/5",0
+6824711826730000,0,80000,6824711826810000,8,"S",120,8,"rcuop/0",10
+6824711826788000,2,81000,6824711826869000,45,"S",120,45,"rcuop/5",52
+6824711826810000,0,15054000,6824711841864000,0,"R",120,"[NULL]","swapper/5",0
+6824711826820000,3,33000,6824711826853000,9,"S",120,9,"rcuos/0",11
+6824711826853000,3,54000,6824711826907000,17,"S",120,17,"rcuop/1",20
+6824711826869000,2,165000,6824711827034000,739,"S",120,739,"adbd",20305
+6824711826907000,3,380000,6824711827287000,0,"R",120,"[NULL]","swapper/5",0
+6824711826997000,1,21000,6824711827018000,18,"S",120,18,"rcuos/1",21
+6824711827018000,1,27430000,6824711854448000,0,"R",120,"[NULL]","swapper/5",0
+6824711827034000,2,51000,6824711827085000,59,"S",120,59,"rcuop/7",68
+6824711827060000,6,8000,6824711827068000,702,"S",120,702,"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,702,"S",120,702,"kworker/u16:7",19422
+6824711827104000,6,9000,6824711827113000,0,"R",120,"[NULL]","swapper/5",0
+6824711827113000,6,31000,6824711827144000,702,"S",120,702,"kworker/u16:7",19422
+6824711827138000,7,5000,6824711827143000,711,"S",120,711,"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,2731,"I",120,760,"sh",20447
+6824711828286000,3,281000,6824711828567000,2732,"I",120,739,"shell",20448
+6824711828567000,3,8000,6824711828575000,25,"S",120,25,"rcuos/2",29
+6824711828575000,3,250000,6824711828825000,739,"S",120,739,"adbd",20305
+6824711828824000,6,43000,6824711828867000,630,"S",100,630,"kworker/u17:1",1134
+6824711828825000,3,15722000,6824711844547000,0,"R",120,"[NULL]","swapper/5",0
+6824711828867000,6,19000,6824711828886000,669,"S",120,669,"kworker/6:1",14833
+6824711828886000,6,64000,6824711828950000,0,"R",120,"[NULL]","swapper/5",0
+6824711828893000,2,28000,6824711828921000,2487,"S",120,739,"UsbFfs-worker",20308
+6824711828921000,2,72000,6824711828993000,0,"R",120,"[NULL]","swapper/5",0
+6824711828950000,6,14000,6824711828964000,630,"S",100,630,"kworker/u17:1",1134
+6824711828964000,6,21000,6824711828985000,669,"S",120,669,"kworker/6:1",14833
+6824711828985000,6,4000,6824711828989000,0,"R",120,"[NULL]","swapper/5",0
+6824711828989000,6,9000,6824711828998000,630,"S",100,630,"kworker/u17:1",1134
+6824711828993000,2,26000,6824711829019000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824711829134000,6,38000,6824711829172000,0,"R",120,"[NULL]","swapper/5",0
+6824711829172000,6,16000,6824711829188000,630,"S",100,630,"kworker/u17:1",1134
+6824711829188000,6,23000,6824711829211000,669,"S",120,669,"kworker/6:1",14833
+6824711829211000,6,11000,6824711829222000,0,"R",120,"[NULL]","swapper/5",0
+6824711829222000,6,33000,6824711829255000,630,"S",100,630,"kworker/u17:1",1134
+6824711829227000,2,70000,6824711829297000,2487,"S",120,739,"UsbFfs-worker",20308
+6824711829255000,6,40000,6824711829295000,0,"R",120,"[NULL]","swapper/5",0
+6824711829295000,6,13000,6824711829308000,630,"S",100,630,"kworker/u17:1",1134
+6824711829297000,2,153000,6824711829450000,739,"S",120,739,"adbd",20305
+6824711829308000,6,19000,6824711829327000,669,"S",120,669,"kworker/6:1",14833
+6824711829327000,6,75000,6824711829402000,0,"R",120,"[NULL]","swapper/5",0
+6824711829402000,6,12000,6824711829414000,630,"S",100,630,"kworker/u17:1",1134
+6824711829414000,6,7000,6824711829421000,669,"S",120,669,"kworker/6:1",14833
+6824711829421000,6,16000,6824711829437000,0,"R",120,"[NULL]","swapper/5",0
+6824711829437000,6,7000,6824711829444000,630,"S",100,630,"kworker/u17:1",1134
+6824711829444000,6,452000,6824711829896000,0,"R",120,"[NULL]","swapper/5",0
+6824711829450000,2,41000,6824711829491000,2487,"S",120,739,"UsbFfs-worker",20308
+6824711829491000,2,68000,6824711829559000,739,"S",120,739,"adbd",20305
+6824711829559000,2,4671000,6824711834230000,0,"R",120,"[NULL]","swapper/5",0
+6824711829896000,6,16000,6824711829912000,669,"S",120,669,"kworker/6:1",14833
+6824711829912000,6,3511000,6824711833423000,0,"R",120,"[NULL]","swapper/5",0
+6824711833250000,5,36000,6824711833286000,483,"S",49,483,"sugov:4",606
+6824711833286000,5,153000,6824711833439000,113,"R+",120,113,"kswapd0",150
+6824711833423000,6,19000,6824711833442000,5,"S",120,5,"rcu_preempt",7
+6824711833439000,5,74000,6824711833513000,24,"S",120,24,"rcuop/2",28
+6824711833442000,6,8000,6824711833450000,6,"S",120,6,"rcu_sched",8
+6824711833450000,6,7442000,6824711840892000,0,"R",120,"[NULL]","swapper/5",0
+6824711833513000,5,994000,6824711834507000,113,"S",120,113,"kswapd0",150
+6824711834230000,2,26000,6824711834256000,31,"S",120,31,"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,482,"S",49,482,"sugov:0",605
+6824711840142000,2,74000,6824711840216000,22,"S",120,22,"ksoftirqd/2",25
+6824711840216000,2,1649000,6824711841865000,0,"R",120,"[NULL]","swapper/5",0
+6824711840892000,6,39000,6824711840931000,5,"S",120,5,"rcu_preempt",7
+6824711840931000,6,24000,6824711840955000,6,"S",120,6,"rcu_sched",8
+6824711840955000,6,143000,6824711841098000,38,"S",120,38,"rcuop/4",44
+6824711841071000,5,11000,6824711841082000,39,"S",120,39,"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,53,"S",120,53,"rcuos/6",61
+6824711841115000,7,12000,6824711841127000,60,"S",120,60,"rcuos/7",69
+6824711841127000,7,10000,6824711841137000,668,"S",120,668,"kworker/7:2",14813
+6824711841137000,7,290852000,6824712131989000,0,"R",120,"[NULL]","swapper/5",0
+6824711841864000,0,161000,6824711842025000,8,"S",120,8,"rcuop/0",10
+6824711841865000,2,1300000,6824711843165000,45,"S",120,45,"rcuop/5",52
+6824711842025000,0,12144000,6824711854169000,0,"R",120,"[NULL]","swapper/5",0
+6824711843165000,2,225000,6824711843390000,52,"R",120,52,"rcuop/6",60
+6824711843390000,2,108000,6824711843498000,482,"S",49,482,"sugov:0",605
+6824711843498000,2,131000,6824711843629000,17,"S",120,17,"rcuop/1",20
+6824711843629000,2,152000,6824711843781000,52,"S",120,52,"rcuop/6",60
+6824711843781000,2,441000,6824711844222000,59,"S",120,59,"rcuop/7",68
+6824711844180000,6,95000,6824711844275000,702,"D",120,702,"kworker/u16:7",19422
+6824711844222000,2,48000,6824711844270000,694,"S",120,694,"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,77,"S",120,77,"smem_native_rpm",87
+6824711844719000,3,2190000,6824711846909000,0,"R",120,"[NULL]","swapper/5",0
+6824711844847000,6,13000,6824711844860000,702,"S",120,702,"kworker/u16:7",19422
+6824711844860000,6,1757000,6824711846617000,0,"R",120,"[NULL]","swapper/5",0
+6824711846617000,6,22000,6824711846639000,5,"S",120,5,"rcu_preempt",7
+6824711846639000,6,16000,6824711846655000,6,"S",120,6,"rcu_sched",8
+6824711846655000,6,11000,6824711846666000,669,"S",120,669,"kworker/6:1",14833
+6824711846666000,6,149000,6824711846815000,702,"S",120,702,"kworker/u16:7",19422
+6824711846773000,5,35000,6824711846808000,24,"S",120,24,"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,25,"S",120,25,"rcuos/2",29
+6824711846973000,3,63000,6824711847036000,32,"S",120,32,"rcuos/3",37
+6824711847022000,2,328000,6824711847350000,31,"S",120,31,"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,29,"S",120,29,"ksoftirqd/3",33
+6824711850582000,3,24018000,6824711874600000,0,"R",120,"[NULL]","swapper/5",0
+6824711854105000,6,13000,6824711854118000,5,"S",120,5,"rcu_preempt",7
+6824711854118000,6,7000,6824711854125000,6,"S",120,6,"rcu_sched",8
+6824711854125000,6,6654000,6824711860779000,0,"R",120,"[NULL]","swapper/5",0
+6824711854169000,0,120000,6824711854289000,743,"S",120,743,"kworker/0:5",20371
+6824711854289000,0,462000,6824711854751000,0,"R",120,"[NULL]","swapper/5",0
+6824711854448000,1,404000,6824711854852000,786,"S",111,494,"SDM_EventThread",685
+6824711854751000,0,327000,6824711855078000,777,"S",120,493,"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,771,"S",97,493,"DispSync",676
+6824711855357000,1,545000,6824711855902000,0,"R",120,"[NULL]","swapper/5",0
+6824711855549000,0,272000,6824711855821000,773,"S",97,493,"app",678
+6824711855821000,0,1794000,6824711857615000,0,"R",120,"[NULL]","swapper/5",0
+6824711855902000,1,1771000,6824711857673000,644,"S",120,644,"ndroid.systemui",1664
+6824711855961000,2,72000,6824711856033000,771,"S",97,493,"DispSync",676
+6824711856033000,2,5351000,6824711861384000,0,"R",120,"[NULL]","swapper/5",0
+6824711857615000,0,250000,6824711857865000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824711858171000,1,29595000,6824711887766000,0,"R",120,"[NULL]","swapper/5",0
+6824711858291000,0,79000,6824711858370000,771,"S",97,493,"DispSync",676
+6824711858370000,0,1693000,6824711860063000,0,"R",120,"[NULL]","swapper/5",0
+6824711860063000,0,48000,6824711860111000,3,"S",120,3,"ksoftirqd/0",3
+6824711860111000,0,5836000,6824711865947000,0,"R",120,"[NULL]","swapper/5",0
+6824711860779000,6,128000,6824711860907000,483,"S",49,483,"sugov:4",606
+6824711860907000,6,78000,6824711860985000,5,"S",120,5,"rcu_preempt",7
+6824711860985000,6,67000,6824711861052000,6,"S",120,6,"rcu_sched",8
+6824711861052000,6,50000,6824711861102000,39,"S",120,39,"rcuos/4",45
+6824711861102000,6,168000,6824711861270000,38,"S",120,38,"rcuop/4",44
+6824711861270000,6,32000,6824711861302000,52,"S",120,52,"rcuop/6",60
+6824711861302000,6,12006000,6824711873308000,0,"R",120,"[NULL]","swapper/5",0
+6824711861384000,2,457000,6824711861841000,45,"S",120,45,"rcuop/5",52
+6824711861841000,2,27907000,6824711889748000,0,"R",120,"[NULL]","swapper/5",0
+6824711865947000,0,139000,6824711866086000,482,"S",49,482,"sugov:0",605
+6824711866086000,0,46000,6824711866132000,3,"S",120,3,"ksoftirqd/0",3
+6824711866132000,0,889000,6824711867021000,0,"R",120,"[NULL]","swapper/5",0
+6824711867021000,0,47000,6824711867068000,3,"S",120,3,"ksoftirqd/0",3
+6824711867068000,0,702000,6824711867770000,0,"R",120,"[NULL]","swapper/5",0
+6824711867770000,0,70000,6824711867840000,5,"S",120,5,"rcu_preempt",7
+6824711867840000,0,4623000,6824711872463000,0,"R",120,"[NULL]","swapper/5",0
+6824711872463000,0,52000,6824711872515000,3,"S",120,3,"ksoftirqd/0",3
+6824711872515000,0,868000,6824711873383000,0,"R",120,"[NULL]","swapper/5",0
+6824711873308000,6,68000,6824711873376000,702,"D",120,702,"kworker/u16:7",19422
+6824711873376000,6,665000,6824711874041000,0,"R",120,"[NULL]","swapper/5",0
+6824711873383000,0,136000,6824711873519000,5,"S",120,5,"rcu_preempt",7
+6824711873519000,0,76000,6824711873595000,24,"S",120,24,"rcuop/2",28
+6824711873595000,0,115000,6824711873710000,743,"S",120,743,"kworker/0:5",20371
+6824711873710000,0,46000,6824711873756000,8,"S",120,8,"rcuop/0",10
+6824711873756000,0,6329000,6824711880085000,0,"R",120,"[NULL]","swapper/5",0
+6824711874041000,6,477000,6824711874518000,702,"D",120,702,"kworker/u16:7",19422
+6824711874518000,6,672000,6824711875190000,0,"R",120,"[NULL]","swapper/5",0
+6824711874600000,3,138000,6824711874738000,77,"S",120,77,"smem_native_rpm",87
+6824711874738000,3,920000,6824711875658000,0,"R",120,"[NULL]","swapper/5",0
+6824711875190000,6,207000,6824711875397000,702,"D",120,702,"kworker/u16:7",19422
+6824711875397000,6,667000,6824711876064000,0,"R",120,"[NULL]","swapper/5",0
+6824711875658000,3,86000,6824711875744000,77,"S",120,77,"smem_native_rpm",87
+6824711875744000,3,729000,6824711876473000,0,"R",120,"[NULL]","swapper/5",0
+6824711876064000,6,202000,6824711876266000,702,"D",120,702,"kworker/u16:7",19422
+6824711876266000,6,110000,6824711876376000,0,"R",120,"[NULL]","swapper/5",0
+6824711876376000,6,96000,6824711876472000,702,"D",120,702,"kworker/u16:7",19422
+6824711876472000,6,704000,6824711877176000,0,"R",120,"[NULL]","swapper/5",0
+6824711876473000,3,71000,6824711876544000,77,"S",120,77,"smem_native_rpm",87
+6824711876544000,3,783000,6824711877327000,0,"R",120,"[NULL]","swapper/5",0
+6824711877176000,6,125000,6824711877301000,702,"D",120,702,"kworker/u16:7",19422
+6824711877301000,6,678000,6824711877979000,0,"R",120,"[NULL]","swapper/5",0
+6824711877327000,3,143000,6824711877470000,77,"S",120,77,"smem_native_rpm",87
+6824711877470000,3,716000,6824711878186000,0,"R",120,"[NULL]","swapper/5",0
+6824711877979000,6,198000,6824711878177000,702,"D",120,702,"kworker/u16:7",19422
+6824711878177000,6,472000,6824711878649000,0,"R",120,"[NULL]","swapper/5",0
+6824711878186000,3,193000,6824711878379000,77,"S",120,77,"smem_native_rpm",87
+6824711878379000,3,469000,6824711878848000,0,"R",120,"[NULL]","swapper/5",0
+6824711878649000,6,182000,6824711878831000,702,"D",120,702,"kworker/u16:7",19422
+6824711878831000,6,446000,6824711879277000,0,"R",120,"[NULL]","swapper/5",0
+6824711878848000,3,140000,6824711878988000,77,"S",120,77,"smem_native_rpm",87
+6824711878988000,3,666000,6824711879654000,0,"R",120,"[NULL]","swapper/5",0
+6824711879277000,6,161000,6824711879438000,702,"D",120,702,"kworker/u16:7",19422
+6824711879438000,6,112000,6824711879550000,0,"R",120,"[NULL]","swapper/5",0
+6824711879550000,6,82000,6824711879632000,702,"D",120,702,"kworker/u16:7",19422
+6824711879632000,6,169000,6824711879801000,0,"R",120,"[NULL]","swapper/5",0
+6824711879654000,3,182000,6824711879836000,77,"S",120,77,"smem_native_rpm",87
+6824711879801000,6,192000,6824711879993000,702,"D",120,702,"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,3,"S",120,3,"ksoftirqd/0",3
+6824711880224000,6,143000,6824711880367000,702,"D",120,702,"kworker/u16:7",19422
+6824711880234000,3,64000,6824711880298000,77,"S",120,77,"smem_native_rpm",87
+6824711880240000,0,57000,6824711880297000,5,"S",120,5,"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,77,"S",120,77,"smem_native_rpm",87
+6824711880553000,6,58000,6824711880611000,702,"S",120,702,"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,50,"S",120,50,"ksoftirqd/6",57
+6824711885679000,6,8649000,6824711894328000,0,"R",120,"[NULL]","swapper/5",0
+6824711886679000,0,139000,6824711886818000,5,"S",120,5,"rcu_preempt",7
+6824711886818000,0,59000,6824711886877000,52,"S",120,52,"rcuop/6",60
+6824711886877000,0,585000,6824711887462000,0,"R",120,"[NULL]","swapper/5",0
+6824711887462000,0,118000,6824711887580000,743,"S",120,743,"kworker/0:5",20371
+6824711887580000,0,455000,6824711888035000,0,"R",120,"[NULL]","swapper/5",0
+6824711887766000,1,377000,6824711888143000,786,"S",111,494,"SDM_EventThread",685
+6824711888035000,0,327000,6824711888362000,777,"S",120,493,"HwBinder:640_1",721
+6824711888143000,1,88000,6824711888231000,0,"R",120,"[NULL]","swapper/5",0
+6824711888231000,1,85000,6824711888316000,771,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824711889144000,0,532000,6824711889676000,0,"R",120,"[NULL]","swapper/5",0
+6824711889295000,1,275000,6824711889570000,773,"S",97,493,"app",678
+6824711889570000,1,1823000,6824711891393000,0,"R",120,"[NULL]","swapper/5",0
+6824711889676000,0,1753000,6824711891429000,644,"S",120,644,"ndroid.systemui",1664
+6824711889748000,2,86000,6824711889834000,771,"S",97,493,"DispSync",676
+6824711889834000,2,34646000,6824711924480000,0,"R",120,"[NULL]","swapper/5",0
+6824711891393000,1,280000,6824711891673000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824711892000000,0,1451000,6824711893451000,0,"R",120,"[NULL]","swapper/5",0
+6824711892145000,1,95000,6824711892240000,771,"S",97,493,"DispSync",676
+6824711892240000,1,12180000,6824711904420000,0,"R",120,"[NULL]","swapper/5",0
+6824711893451000,0,109000,6824711893560000,5,"S",120,5,"rcu_preempt",7
+6824711893560000,0,38000,6824711893598000,24,"S",120,24,"rcuop/2",28
+6824711893598000,0,52000,6824711893650000,8,"S",120,8,"rcuop/0",10
+6824711893650000,0,78000,6824711893728000,743,"D",120,743,"kworker/0:5",20371
+6824711893728000,0,65000,6824711893793000,705,"S",120,705,"kworker/0:1",19511
+6824711893793000,0,59000,6824711893852000,743,"S",120,743,"kworker/0:5",20371
+6824711893852000,0,27555000,6824711921407000,0,"R",120,"[NULL]","swapper/5",0
+6824711894328000,6,300000,6824711894628000,702,"D",120,702,"kworker/u16:7",19422
+6824711894628000,6,2368000,6824711896996000,0,"R",120,"[NULL]","swapper/5",0
+6824711894870000,3,77000,6824711894947000,77,"S",120,77,"smem_native_rpm",87
+6824711894947000,3,4289000,6824711899236000,0,"R",120,"[NULL]","swapper/5",0
+6824711896996000,6,306000,6824711897302000,702,"D",120,702,"kworker/u16:7",19422
+6824711897302000,6,48000,6824711897350000,0,"R",120,"[NULL]","swapper/5",0
+6824711897350000,6,43000,6824711897393000,50,"S",120,50,"ksoftirqd/6",57
+6824711897393000,6,3585000,6824711900978000,0,"R",120,"[NULL]","swapper/5",0
+6824711899236000,3,257000,6824711899493000,77,"S",120,77,"smem_native_rpm",87
+6824711899493000,3,4694000,6824711904187000,0,"R",120,"[NULL]","swapper/5",0
+6824711900978000,6,122000,6824711901100000,702,"S",120,702,"kworker/u16:7",19422
+6824711901100000,6,50000,6824711901150000,0,"R",120,"[NULL]","swapper/5",0
+6824711901150000,6,40000,6824711901190000,50,"S",120,50,"ksoftirqd/6",57
+6824711901190000,6,826872000,6824712728062000,0,"R",120,"[NULL]","swapper/5",0
+6824711904187000,3,212000,6824711904399000,77,"S",120,77,"smem_native_rpm",87
+6824711904399000,3,55334000,6824711959733000,0,"R",120,"[NULL]","swapper/5",0
+6824711904420000,1,72000,6824711904492000,15,"S",120,15,"ksoftirqd/1",17
+6824711904492000,1,14769000,6824711919261000,0,"R",120,"[NULL]","swapper/5",0
+6824711919261000,1,145000,6824711919406000,15,"S",120,15,"ksoftirqd/1",17
+6824711919406000,1,3219000,6824711922625000,0,"R",120,"[NULL]","swapper/5",0
+6824711921407000,0,185000,6824711921592000,743,"S",120,743,"kworker/0:5",20371
+6824711921592000,0,726000,6824711922318000,786,"S",111,494,"SDM_EventThread",685
+6824711922318000,0,65000,6824711922383000,0,"R",120,"[NULL]","swapper/5",0
+6824711922383000,0,57000,6824711922440000,3,"S",120,3,"ksoftirqd/0",3
+6824711922440000,0,585000,6824711923025000,0,"R",120,"[NULL]","swapper/5",0
+6824711922625000,1,477000,6824711923102000,777,"S",120,493,"HwBinder:640_1",721
+6824711923025000,0,239000,6824711923264000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824711924095000,1,2591000,6824711926686000,0,"R",120,"[NULL]","swapper/5",0
+6824711924337000,0,2416000,6824711926753000,644,"S",120,644,"ndroid.systemui",1664
+6824711924480000,2,93000,6824711924573000,771,"S",97,493,"DispSync",676
+6824711924573000,2,34369000,6824711958942000,0,"R",120,"[NULL]","swapper/5",0
+6824711926686000,1,341000,6824711927027000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824711927540000,0,30747000,6824711958287000,0,"R",120,"[NULL]","swapper/5",0
+6824711927822000,1,86000,6824711927908000,771,"S",97,493,"DispSync",676
+6824711927908000,1,30404000,6824711958312000,0,"R",120,"[NULL]","swapper/5",0
+6824711935090000,5,59000,6824711935149000,113,"S",120,113,"kswapd0",150
+6824711935149000,5,791709000,6824712726858000,0,"R",120,"[NULL]","swapper/5",0
+6824711958287000,0,325000,6824711958612000,771,"S",97,493,"DispSync",676
+6824711958312000,1,275000,6824711958587000,15,"S",120,15,"ksoftirqd/1",17
+6824711958587000,1,120000,6824711958707000,693,"S",120,693,"kworker/1:1",18800
+6824711958612000,0,107000,6824711958719000,743,"S",120,743,"kworker/0:5",20371
+6824711958707000,1,827000,6824711959534000,0,"R",120,"[NULL]","swapper/5",0
+6824711958719000,0,580000,6824711959299000,786,"S",111,494,"SDM_EventThread",685
+6824711958942000,2,402000,6824711959344000,773,"S",97,493,"app",678
+6824711959299000,0,1274000,6824711960573000,702,"R+",120,702,"kworker/u16:7",19422
+6824711959344000,2,862000,6824711960206000,0,"R",120,"[NULL]","swapper/5",0
+6824711959534000,1,579000,6824711960113000,777,"S",120,493,"HwBinder:640_1",721
+6824711959733000,3,66000,6824711959799000,771,"S",97,493,"DispSync",676
+6824711959799000,3,2784000,6824711962583000,644,"S",120,644,"ndroid.systemui",1664
+6824711960113000,1,3163000,6824711963276000,0,"R",120,"[NULL]","swapper/5",0
+6824711960206000,2,86000,6824711960292000,771,"S",97,493,"DispSync",676
+6824711960292000,2,31867000,6824711992159000,0,"R",120,"[NULL]","swapper/5",0
+6824711960573000,0,54000,6824711960627000,77,"S",120,77,"smem_native_rpm",87
+6824711960627000,0,52000,6824711960679000,702,"D",120,702,"kworker/u16:7",19422
+6824711960679000,0,1939000,6824711962618000,0,"R",120,"[NULL]","swapper/5",0
+6824711962583000,3,212000,6824711962795000,702,"D",120,702,"kworker/u16:7",19422
+6824711962618000,0,399000,6824711963017000,770,"S",120,493,"Binder:640_2",675
+6824711962795000,3,29662000,6824711992457000,0,"R",120,"[NULL]","swapper/5",0
+6824711963017000,0,225000,6824711963242000,77,"S",120,77,"smem_native_rpm",87
+6824711963242000,0,720000,6824711963962000,0,"R",120,"[NULL]","swapper/5",0
+6824711963276000,1,193000,6824711963469000,773,"S",97,493,"app",678
+6824711963469000,1,75000,6824711963544000,702,"S",120,702,"kworker/u16:7",19422
+6824711963544000,1,27817000,6824711991361000,0,"R",120,"[NULL]","swapper/5",0
+6824711963962000,0,93000,6824711964055000,771,"S",97,493,"DispSync",676
+6824711964055000,0,26981000,6824711991036000,0,"R",120,"[NULL]","swapper/5",0
+6824711991036000,0,265000,6824711991301000,743,"S",120,743,"kworker/0:5",20371
+6824711991301000,0,902000,6824711992203000,786,"S",111,494,"SDM_EventThread",685
+6824711991361000,1,512000,6824711991873000,771,"S",97,493,"DispSync",676
+6824711991873000,1,90000,6824711991963000,0,"R",120,"[NULL]","swapper/5",0
+6824711991963000,1,86000,6824711992049000,15,"S",120,15,"ksoftirqd/1",17
+6824711992049000,1,1109000,6824711993158000,0,"R",120,"[NULL]","swapper/5",0
+6824711992159000,2,539000,6824711992698000,773,"S",97,493,"app",678
+6824711992203000,0,811000,6824711993014000,0,"R",120,"[NULL]","swapper/5",0
+6824711992457000,3,561000,6824711993018000,777,"S",120,493,"HwBinder:640_1",721
+6824711992698000,2,31632000,6824712024330000,0,"R",120,"[NULL]","swapper/5",0
+6824711993014000,0,3047000,6824711996061000,644,"S",120,644,"ndroid.systemui",1664
+6824711993018000,3,29607000,6824712022625000,0,"R",120,"[NULL]","swapper/5",0
+6824711993158000,1,88000,6824711993246000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824711996491000,1,795000,6824711997286000,0,"R",120,"[NULL]","swapper/5",0
+6824711996784000,0,206000,6824711996990000,773,"S",97,493,"app",678
+6824711996990000,0,72000,6824711997062000,0,"R",120,"[NULL]","swapper/5",0
+6824711997062000,0,65000,6824711997127000,3,"S",120,3,"ksoftirqd/0",3
+6824711997127000,0,25255000,6824712022382000,0,"R",120,"[NULL]","swapper/5",0
+6824711997286000,1,89000,6824711997375000,771,"S",97,493,"DispSync",676
+6824711997375000,1,26567000,6824712023942000,0,"R",120,"[NULL]","swapper/5",0
+6824712022382000,0,182000,6824712022564000,743,"S",120,743,"kworker/0:5",20371
+6824712022564000,0,1155000,6824712023719000,786,"S",111,494,"SDM_EventThread",685
+6824712022625000,3,91000,6824712022716000,686,"S",120,686,"kworker/3:1",17791
+6824712022716000,3,37690000,6824712060406000,0,"R",120,"[NULL]","swapper/5",0
+6824712023719000,0,311000,6824712024030000,702,"S",120,702,"kworker/u16:7",19422
+6824712023942000,1,639000,6824712024581000,777,"S",120,493,"HwBinder:640_1",721
+6824712024030000,0,921000,6824712024951000,0,"R",120,"[NULL]","swapper/5",0
+6824712024330000,2,324000,6824712024654000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824712025482000,0,3497000,6824712028979000,0,"R",120,"[NULL]","swapper/5",0
+6824712025771000,1,3163000,6824712028934000,644,"S",120,644,"ndroid.systemui",1664
+6824712025862000,2,83000,6824712025945000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712029372000,0,798000,6824712030170000,0,"R",120,"[NULL]","swapper/5",0
+6824712029651000,1,204000,6824712029855000,773,"S",97,493,"app",678
+6824712029855000,1,29454000,6824712059309000,0,"R",120,"[NULL]","swapper/5",0
+6824712030170000,0,89000,6824712030259000,771,"S",97,493,"DispSync",676
+6824712030259000,0,70000,6824712030329000,0,"R",120,"[NULL]","swapper/5",0
+6824712030329000,0,70000,6824712030399000,3,"S",120,3,"ksoftirqd/0",3
+6824712030399000,0,28593000,6824712058992000,0,"R",120,"[NULL]","swapper/5",0
+6824712058992000,0,265000,6824712059257000,743,"S",120,743,"kworker/0:5",20371
+6824712059257000,0,1001000,6824712060258000,786,"S",111,494,"SDM_EventThread",685
+6824712059309000,1,519000,6824712059828000,771,"S",97,493,"DispSync",676
+6824712059828000,1,364000,6824712060192000,0,"R",120,"[NULL]","swapper/5",0
+6824712060124000,2,513000,6824712060637000,773,"S",97,493,"app",678
+6824712060192000,1,37000,6824712060229000,15,"S",120,15,"ksoftirqd/1",17
+6824712060229000,1,111000,6824712060340000,693,"S",120,693,"kworker/1:1",18800
+6824712060258000,0,735000,6824712060993000,702,"R+",120,702,"kworker/u16:7",19422
+6824712060340000,1,928000,6824712061268000,0,"R",120,"[NULL]","swapper/5",0
+6824712060406000,3,546000,6824712060952000,777,"S",120,493,"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,771,"S",97,493,"DispSync",676
+6824712061058000,0,280000,6824712061338000,702,"S",120,702,"kworker/u16:7",19422
+6824712061268000,1,3172000,6824712064440000,644,"S",120,644,"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,770,"S",120,493,"Binder:640_2",675
+6824712064872000,0,780000,6824712065652000,0,"R",120,"[NULL]","swapper/5",0
+6824712065150000,1,201000,6824712065351000,773,"S",97,493,"app",678
+6824712065351000,1,10437000,6824712075788000,0,"R",120,"[NULL]","swapper/5",0
+6824712065652000,0,89000,6824712065741000,771,"S",97,493,"DispSync",676
+6824712065741000,0,24857000,6824712090598000,0,"R",120,"[NULL]","swapper/5",0
+6824712075788000,1,292000,6824712076080000,1919,"S",120,667,"Executor-7",14762
+6824712076080000,1,88000,6824712076168000,0,"R",120,"[NULL]","swapper/5",0
+6824712076168000,1,225000,6824712076393000,15,"S",120,15,"ksoftirqd/1",17
+6824712076393000,1,162000,6824712076555000,702,"S",120,702,"kworker/u16:7",19422
+6824712076555000,1,15181000,6824712091736000,0,"R",120,"[NULL]","swapper/5",0
+6824712090598000,0,224000,6824712090822000,743,"S",120,743,"kworker/0:5",20371
+6824712090822000,0,1321000,6824712092143000,786,"S",111,494,"SDM_EventThread",685
+6824712091736000,1,410000,6824712092146000,771,"S",97,493,"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,3,"S",120,3,"ksoftirqd/0",3
+6824712092312000,0,820000,6824712093132000,0,"R",120,"[NULL]","swapper/5",0
+6824712092339000,2,602000,6824712092941000,777,"S",120,493,"HwBinder:640_1",721
+6824712092492000,3,487000,6824712092979000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712093222000,0,3125000,6824712096347000,0,"R",120,"[NULL]","swapper/5",0
+6824712093290000,1,3028000,6824712096318000,644,"S",120,644,"ndroid.systemui",1664
+6824712096318000,1,443000,6824712096761000,0,"R",120,"[NULL]","swapper/5",0
+6824712096347000,0,516000,6824712096863000,770,"S",120,493,"Binder:640_2",675
+6824712096761000,1,208000,6824712096969000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712097387000,2,27295000,6824712124682000,0,"R",120,"[NULL]","swapper/5",0
+6824712124662000,0,474000,6824712125136000,771,"S",97,493,"DispSync",676
+6824712124682000,2,304000,6824712124986000,22,"S",120,22,"ksoftirqd/2",25
+6824712124986000,2,1342000,6824712126328000,0,"R",120,"[NULL]","swapper/5",0
+6824712125136000,0,150000,6824712125286000,743,"S",120,743,"kworker/0:5",20371
+6824712125286000,0,705000,6824712125991000,786,"R+",111,494,"SDM_EventThread",685
+6824712125516000,1,532000,6824712126048000,773,"S",97,493,"app",678
+6824712125991000,0,50000,6824712126041000,771,"S",97,493,"DispSync",676
+6824712126041000,0,199000,6824712126240000,786,"S",111,494,"SDM_EventThread",685
+6824712126048000,1,3632000,6824712129680000,0,"R",120,"[NULL]","swapper/5",0
+6824712126240000,0,149000,6824712126389000,702,"S",120,702,"kworker/u16:7",19422
+6824712126328000,2,2927000,6824712129255000,644,"S",120,644,"ndroid.systemui",1664
+6824712126389000,0,970000,6824712127359000,0,"R",120,"[NULL]","swapper/5",0
+6824712126484000,3,712000,6824712127196000,777,"S",120,493,"HwBinder:640_1",721
+6824712127196000,3,32061000,6824712159257000,0,"R",120,"[NULL]","swapper/5",0
+6824712127359000,0,84000,6824712127443000,771,"S",97,493,"DispSync",676
+6824712127443000,0,1769000,6824712129212000,0,"R",120,"[NULL]","swapper/5",0
+6824712129212000,0,299000,6824712129511000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824712129857000,1,28493000,6824712158350000,0,"R",120,"[NULL]","swapper/5",0
+6824712130041000,0,88000,6824712130129000,771,"S",97,493,"DispSync",676
+6824712130129000,0,64000,6824712130193000,0,"R",120,"[NULL]","swapper/5",0
+6824712130193000,0,56000,6824712130249000,3,"S",120,3,"ksoftirqd/0",3
+6824712130249000,0,496000,6824712130745000,0,"R",120,"[NULL]","swapper/5",0
+6824712130745000,0,331000,6824712131076000,702,"R+",120,702,"kworker/u16:7",19422
+6824712131076000,0,202000,6824712131278000,1199,"D",120,611,"rild",1339
+6824712131278000,0,65000,6824712131343000,702,"R+",120,702,"kworker/u16:7",19422
+6824712131343000,0,671000,6824712132014000,1199,"S",120,611,"rild",1339
+6824712131989000,7,56000,6824712132045000,711,"S",120,711,"kworker/u16:2",19725
+6824712132014000,0,442000,6824712132456000,1187,"S",120,611,"rild",1260
+6824712132045000,7,62353000,6824712194398000,0,"R",120,"[NULL]","swapper/5",0
+6824712132456000,0,749000,6824712133205000,543,"S",120,543,"suspend@1.0-ser",796
+6824712133205000,0,1823000,6824712135028000,1187,"S",120,611,"rild",1260
+6824712135028000,0,81000,6824712135109000,8,"S",120,8,"rcuop/0",10
+6824712135109000,0,37000,6824712135146000,5,"S",120,5,"rcu_preempt",7
+6824712135146000,0,240000,6824712135386000,543,"S",120,543,"suspend@1.0-ser",796
+6824712135386000,0,65000,6824712135451000,702,"S",120,702,"kworker/u16:7",19422
+6824712135451000,0,5153000,6824712140604000,0,"R",120,"[NULL]","swapper/5",0
+6824712140604000,0,103000,6824712140707000,5,"S",120,5,"rcu_preempt",7
+6824712140707000,0,133000,6824712140840000,8,"S",120,8,"rcuop/0",10
+6824712140840000,0,16732000,6824712157572000,0,"R",120,"[NULL]","swapper/5",0
+6824712157572000,0,451000,6824712158023000,743,"S",120,743,"kworker/0:5",20371
+6824712158023000,0,992000,6824712159015000,786,"S",111,494,"SDM_EventThread",685
+6824712158350000,1,452000,6824712158802000,771,"S",97,493,"DispSync",676
+6824712158802000,1,87000,6824712158889000,0,"R",120,"[NULL]","swapper/5",0
+6824712158889000,1,87000,6824712158976000,15,"S",120,15,"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,773,"S",97,493,"app",678
+6824712159257000,3,559000,6824712159816000,777,"S",120,493,"HwBinder:640_1",721
+6824712159493000,0,708000,6824712160201000,644,"R",120,644,"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,771,"S",97,493,"DispSync",676
+6824712160044000,1,3767000,6824712163811000,0,"R",120,"[NULL]","swapper/5",0
+6824712160201000,0,878000,6824712161079000,702,"S",120,702,"kworker/u16:7",19422
+6824712161079000,0,86000,6824712161165000,743,"S",120,743,"kworker/0:5",20371
+6824712161165000,0,2618000,6824712163783000,644,"S",120,644,"ndroid.systemui",1664
+6824712163783000,0,718000,6824712164501000,0,"R",120,"[NULL]","swapper/5",0
+6824712163811000,1,405000,6824712164216000,770,"S",120,493,"Binder:640_2",675
+6824712164216000,1,792000,6824712165008000,0,"R",120,"[NULL]","swapper/5",0
+6824712164501000,0,203000,6824712164704000,773,"S",97,493,"app",678
+6824712164704000,0,26926000,6824712191630000,0,"R",120,"[NULL]","swapper/5",0
+6824712165008000,1,88000,6824712165096000,771,"S",97,493,"DispSync",676
+6824712165096000,1,26545000,6824712191641000,0,"R",120,"[NULL]","swapper/5",0
+6824712191630000,0,479000,6824712192109000,771,"S",97,493,"DispSync",676
+6824712191641000,1,258000,6824712191899000,15,"S",120,15,"ksoftirqd/1",17
+6824712191899000,1,160000,6824712192059000,0,"R",120,"[NULL]","swapper/5",0
+6824712192059000,1,615000,6824712192674000,773,"S",97,493,"app",678
+6824712192109000,0,139000,6824712192248000,743,"S",120,743,"kworker/0:5",20371
+6824712192248000,0,299000,6824712192547000,702,"S",120,702,"kworker/u16:7",19422
+6824712192547000,0,966000,6824712193513000,786,"S",111,494,"SDM_EventThread",685
+6824712192674000,1,1433000,6824712194107000,0,"R",120,"[NULL]","swapper/5",0
+6824712192943000,2,3173000,6824712196116000,644,"S",120,644,"ndroid.systemui",1664
+6824712193087000,3,109000,6824712193196000,771,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824712194398000,7,72000,6824712194470000,711,"S",120,711,"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,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712196533000,0,781000,6824712197314000,0,"R",120,"[NULL]","swapper/5",0
+6824712196812000,1,200000,6824712197012000,773,"S",97,493,"app",678
+6824712197012000,1,28707000,6824712225719000,0,"R",120,"[NULL]","swapper/5",0
+6824712197314000,0,88000,6824712197402000,771,"S",97,493,"DispSync",676
+6824712197402000,0,28073000,6824712225475000,0,"R",120,"[NULL]","swapper/5",0
+6824712225475000,0,204000,6824712225679000,743,"S",120,743,"kworker/0:5",20371
+6824712225679000,0,916000,6824712226595000,786,"S",111,494,"SDM_EventThread",685
+6824712225719000,1,521000,6824712226240000,771,"S",97,493,"DispSync",676
+6824712226240000,1,81000,6824712226321000,0,"R",120,"[NULL]","swapper/5",0
+6824712226321000,1,87000,6824712226408000,15,"S",120,15,"ksoftirqd/1",17
+6824712226408000,1,1183000,6824712227591000,0,"R",120,"[NULL]","swapper/5",0
+6824712226530000,2,669000,6824712227199000,773,"S",97,493,"app",678
+6824712226595000,0,894000,6824712227489000,0,"R",120,"[NULL]","swapper/5",0
+6824712226848000,3,546000,6824712227394000,777,"S",120,493,"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,644,"S",120,644,"ndroid.systemui",1664
+6824712227591000,1,88000,6824712227679000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712231087000,1,782000,6824712231869000,0,"R",120,"[NULL]","swapper/5",0
+6824712231367000,0,200000,6824712231567000,773,"S",97,493,"app",678
+6824712231567000,0,13149000,6824712244716000,0,"R",120,"[NULL]","swapper/5",0
+6824712231869000,1,87000,6824712231956000,771,"S",97,493,"DispSync",676
+6824712231956000,1,12891000,6824712244847000,0,"R",120,"[NULL]","swapper/5",0
+6824712244716000,0,324000,6824712245040000,1808,"S",120,663,"ogle.android.as",15167
+6824712244847000,1,193000,6824712245040000,1807,"S",120,663,"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,3,"S",120,3,"ksoftirqd/0",3
+6824712245385000,0,12652000,6824712258037000,0,"R",120,"[NULL]","swapper/5",0
+6824712247262000,7,203000,6824712247465000,711,"S",120,711,"kworker/u16:2",19725
+6824712247465000,7,71000,6824712247536000,0,"R",120,"[NULL]","swapper/5",0
+6824712247536000,7,62000,6824712247598000,57,"S",120,57,"ksoftirqd/7",65
+6824712247598000,7,14402000,6824712262000000,0,"R",120,"[NULL]","swapper/5",0
+6824712258037000,0,225000,6824712258262000,743,"S",120,743,"kworker/0:5",20371
+6824712258262000,0,1133000,6824712259395000,786,"S",111,494,"SDM_EventThread",685
+6824712259296000,1,626000,6824712259922000,777,"S",120,493,"HwBinder:640_1",721
+6824712259395000,0,83000,6824712259478000,0,"R",120,"[NULL]","swapper/5",0
+6824712259478000,0,86000,6824712259564000,3,"S",120,3,"ksoftirqd/0",3
+6824712259564000,0,904000,6824712260468000,0,"R",120,"[NULL]","swapper/5",0
+6824712259685000,2,648000,6824712260333000,771,"S",97,493,"DispSync",676
+6824712259922000,1,1420000,6824712261342000,0,"R",120,"[NULL]","swapper/5",0
+6824712260333000,2,128000,6824712260461000,694,"S",120,694,"kworker/2:0",18823
+6824712260461000,2,979000,6824712261440000,0,"R",120,"[NULL]","swapper/5",0
+6824712260468000,0,523000,6824712260991000,773,"S",97,493,"app",678
+6824712260991000,0,3489000,6824712264480000,0,"R",120,"[NULL]","swapper/5",0
+6824712261342000,1,3074000,6824712264416000,644,"S",120,644,"ndroid.systemui",1664
+6824712261440000,2,98000,6824712261538000,771,"S",97,493,"DispSync",676
+6824712261538000,2,31144000,6824712292682000,0,"R",120,"[NULL]","swapper/5",0
+6824712262000000,7,773000,6824712262773000,711,"S",120,711,"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,770,"S",120,493,"Binder:640_2",675
+6824712264879000,0,791000,6824712265670000,0,"R",120,"[NULL]","swapper/5",0
+6824712265161000,1,209000,6824712265370000,773,"S",97,493,"app",678
+6824712265370000,1,26002000,6824712291372000,0,"R",120,"[NULL]","swapper/5",0
+6824712265670000,0,96000,6824712265766000,771,"S",97,493,"DispSync",676
+6824712265766000,0,19023000,6824712284789000,0,"R",120,"[NULL]","swapper/5",0
+6824712284789000,0,487000,6824712285276000,1694,"D",100,660,"thermal-engine",2490
+6824712285276000,0,89000,6824712285365000,0,"R",120,"[NULL]","swapper/5",0
+6824712285365000,0,85000,6824712285450000,3,"S",120,3,"ksoftirqd/0",3
+6824712285450000,0,2460000,6824712287910000,0,"R",120,"[NULL]","swapper/5",0
+6824712287910000,0,209000,6824712288119000,743,"R+",120,743,"kworker/0:5",20371
+6824712288119000,0,555000,6824712288674000,1694,"S",100,660,"thermal-engine",2490
+6824712288674000,0,111000,6824712288785000,743,"S",120,743,"kworker/0:5",20371
+6824712288785000,0,83000,6824712288868000,0,"R",120,"[NULL]","swapper/5",0
+6824712288868000,0,79000,6824712288947000,3,"S",120,3,"ksoftirqd/0",3
+6824712288947000,0,1078000,6824712290025000,0,"R",120,"[NULL]","swapper/5",0
+6824712290025000,0,115000,6824712290140000,743,"S",120,743,"kworker/0:5",20371
+6824712290140000,0,986000,6824712291126000,786,"S",111,494,"SDM_EventThread",685
+6824712291126000,0,55000,6824712291181000,0,"R",120,"[NULL]","swapper/5",0
+6824712291181000,0,48000,6824712291229000,3,"S",120,3,"ksoftirqd/0",3
+6824712291229000,0,733000,6824712291962000,0,"R",120,"[NULL]","swapper/5",0
+6824712291372000,1,758000,6824712292130000,777,"S",120,493,"HwBinder:640_1",721
+6824712291962000,0,316000,6824712292278000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824712293237000,2,4208000,6824712297445000,0,"R",120,"[NULL]","swapper/5",0
+6824712293515000,0,3069000,6824712296584000,644,"S",120,644,"ndroid.systemui",1664
+6824712293612000,1,83000,6824712293695000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712296899000,0,235000,6824712297134000,773,"S",97,493,"app",678
+6824712296993000,1,153000,6824712297146000,711,"S",120,711,"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,771,"S",97,493,"DispSync",676
+6824712297536000,2,29403000,6824712326939000,0,"R",120,"[NULL]","swapper/5",0
+6824712326930000,0,479000,6824712327409000,771,"S",97,493,"DispSync",676
+6824712326939000,2,165000,6824712327104000,22,"S",120,22,"ksoftirqd/2",25
+6824712327104000,2,1506000,6824712328610000,0,"R",120,"[NULL]","swapper/5",0
+6824712327409000,0,171000,6824712327580000,743,"S",120,743,"kworker/0:5",20371
+6824712327580000,0,701000,6824712328281000,786,"R+",111,494,"SDM_EventThread",685
+6824712327808000,1,528000,6824712328336000,773,"S",97,493,"app",678
+6824712328281000,0,52000,6824712328333000,771,"S",97,493,"DispSync",676
+6824712328333000,0,226000,6824712328559000,786,"S",111,494,"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,644,"S",120,644,"ndroid.systemui",1664
+6824712328781000,3,574000,6824712329355000,777,"S",120,493,"HwBinder:640_1",721
+6824712329355000,3,32279000,6824712361634000,0,"R",120,"[NULL]","swapper/5",0
+6824712329497000,0,87000,6824712329584000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712332220000,0,790000,6824712333010000,0,"R",120,"[NULL]","swapper/5",0
+6824712332509000,1,202000,6824712332711000,773,"S",97,493,"app",678
+6824712332711000,1,27609000,6824712360320000,0,"R",120,"[NULL]","swapper/5",0
+6824712333010000,0,85000,6824712333095000,771,"S",97,493,"DispSync",676
+6824712333095000,0,26074000,6824712359169000,0,"R",120,"[NULL]","swapper/5",0
+6824712359169000,0,225000,6824712359394000,743,"S",120,743,"kworker/0:5",20371
+6824712359394000,0,1615000,6824712361009000,786,"S",111,494,"SDM_EventThread",685
+6824712360320000,1,440000,6824712360760000,771,"S",97,493,"DispSync",676
+6824712360760000,1,80000,6824712360840000,0,"R",120,"[NULL]","swapper/5",0
+6824712360840000,1,552000,6824712361392000,777,"S",120,493,"HwBinder:640_1",721
+6824712361009000,0,85000,6824712361094000,743,"S",120,743,"kworker/0:5",20371
+6824712361053000,2,490000,6824712361543000,773,"S",97,493,"app",678
+6824712361094000,0,1024000,6824712362118000,711,"S",120,711,"kworker/u16:2",19725
+6824712361392000,1,52000,6824712361444000,0,"R",120,"[NULL]","swapper/5",0
+6824712361444000,1,3028000,6824712364472000,644,"S",120,644,"ndroid.systemui",1664
+6824712361543000,2,32596000,6824712394139000,0,"R",120,"[NULL]","swapper/5",0
+6824712361634000,3,102000,6824712361736000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712364910000,0,797000,6824712365707000,0,"R",120,"[NULL]","swapper/5",0
+6824712365196000,1,209000,6824712365405000,773,"S",97,493,"app",678
+6824712365405000,1,27749000,6824712393154000,0,"R",120,"[NULL]","swapper/5",0
+6824712365707000,0,88000,6824712365795000,771,"S",97,493,"DispSync",676
+6824712365795000,0,27098000,6824712392893000,0,"R",120,"[NULL]","swapper/5",0
+6824712392893000,0,266000,6824712393159000,743,"S",120,743,"kworker/0:5",20371
+6824712393154000,1,677000,6824712393831000,771,"S",97,493,"DispSync",676
+6824712393159000,0,1045000,6824712394204000,786,"S",111,494,"SDM_EventThread",685
+6824712393831000,1,936000,6824712394767000,0,"R",120,"[NULL]","swapper/5",0
+6824712394139000,2,561000,6824712394700000,773,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824712394949000,0,3133000,6824712398082000,644,"S",120,644,"ndroid.systemui",1664
+6824712395102000,3,102000,6824712395204000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712398523000,1,782000,6824712399305000,0,"R",120,"[NULL]","swapper/5",0
+6824712398805000,0,206000,6824712399011000,773,"S",97,493,"app",678
+6824712399011000,0,27138000,6824712426149000,0,"R",120,"[NULL]","swapper/5",0
+6824712399305000,1,88000,6824712399393000,771,"S",97,493,"DispSync",676
+6824712399393000,1,27547000,6824712426940000,0,"R",120,"[NULL]","swapper/5",0
+6824712426149000,0,223000,6824712426372000,743,"S",120,743,"kworker/0:5",20371
+6824712426372000,0,1235000,6824712427607000,786,"S",111,494,"SDM_EventThread",685
+6824712426940000,1,447000,6824712427387000,771,"S",97,493,"DispSync",676
+6824712427387000,1,62000,6824712427449000,0,"R",120,"[NULL]","swapper/5",0
+6824712427449000,1,556000,6824712428005000,777,"S",120,493,"HwBinder:640_1",721
+6824712427607000,0,142000,6824712427749000,711,"S",120,711,"kworker/u16:2",19725
+6824712427676000,2,485000,6824712428161000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712428354000,3,33090000,6824712461444000,0,"R",120,"[NULL]","swapper/5",0
+6824712428804000,0,3132000,6824712431936000,644,"S",120,644,"ndroid.systemui",1664
+6824712431936000,0,704000,6824712432640000,0,"R",120,"[NULL]","swapper/5",0
+6824712431969000,1,397000,6824712432366000,770,"S",120,493,"Binder:640_2",675
+6824712432366000,1,792000,6824712433158000,0,"R",120,"[NULL]","swapper/5",0
+6824712432640000,0,216000,6824712432856000,773,"S",97,493,"app",678
+6824712432856000,0,26763000,6824712459619000,0,"R",120,"[NULL]","swapper/5",0
+6824712433158000,1,88000,6824712433246000,771,"S",97,493,"DispSync",676
+6824712433246000,1,27279000,6824712460525000,0,"R",120,"[NULL]","swapper/5",0
+6824712459619000,0,225000,6824712459844000,743,"S",120,743,"kworker/0:5",20371
+6824712459844000,0,1326000,6824712461170000,786,"S",111,494,"SDM_EventThread",685
+6824712460525000,1,447000,6824712460972000,771,"S",97,493,"DispSync",676
+6824712460972000,1,1100000,6824712462072000,0,"R",120,"[NULL]","swapper/5",0
+6824712461170000,0,668000,6824712461838000,711,"R+",120,711,"kworker/u16:2",19725
+6824712461291000,2,529000,6824712461820000,773,"S",97,493,"app",678
+6824712461444000,3,570000,6824712462014000,777,"S",120,493,"HwBinder:640_1",721
+6824712461820000,2,32964000,6824712494784000,0,"R",120,"[NULL]","swapper/5",0
+6824712461838000,0,60000,6824712461898000,771,"S",97,493,"DispSync",676
+6824712461898000,0,133000,6824712462031000,743,"S",120,743,"kworker/0:5",20371
+6824712462014000,3,33363000,6824712495377000,0,"R",120,"[NULL]","swapper/5",0
+6824712462031000,0,281000,6824712462312000,711,"S",120,711,"kworker/u16:2",19725
+6824712462072000,1,3236000,6824712465308000,644,"S",120,644,"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,770,"S",120,493,"Binder:640_2",675
+6824712465765000,0,787000,6824712466552000,0,"R",120,"[NULL]","swapper/5",0
+6824712466045000,1,204000,6824712466249000,773,"S",97,493,"app",678
+6824712466249000,1,27754000,6824712494003000,0,"R",120,"[NULL]","swapper/5",0
+6824712466552000,0,174000,6824712466726000,771,"S",97,493,"DispSync",676
+6824712466726000,0,26386000,6824712493112000,0,"R",120,"[NULL]","swapper/5",0
+6824712493112000,0,746000,6824712493858000,743,"S",120,743,"kworker/0:5",20371
+6824712493858000,0,917000,6824712494775000,786,"S",111,494,"SDM_EventThread",685
+6824712494003000,1,505000,6824712494508000,771,"S",97,493,"DispSync",676
+6824712494508000,1,79000,6824712494587000,0,"R",120,"[NULL]","swapper/5",0
+6824712494587000,1,558000,6824712495145000,777,"S",120,493,"HwBinder:640_1",721
+6824712494775000,0,149000,6824712494924000,711,"S",120,711,"kworker/u16:2",19725
+6824712494784000,2,486000,6824712495270000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712495482000,3,33062000,6824712528544000,0,"R",120,"[NULL]","swapper/5",0
+6824712495913000,0,3157000,6824712499070000,644,"S",120,644,"ndroid.systemui",1664
+6824712499070000,0,712000,6824712499782000,0,"R",120,"[NULL]","swapper/5",0
+6824712499096000,1,408000,6824712499504000,770,"S",120,493,"Binder:640_2",675
+6824712499504000,1,790000,6824712500294000,0,"R",120,"[NULL]","swapper/5",0
+6824712499782000,0,306000,6824712500088000,773,"S",97,493,"app",678
+6824712500088000,0,26796000,6824712526884000,0,"R",120,"[NULL]","swapper/5",0
+6824712500294000,1,92000,6824712500386000,771,"S",97,493,"DispSync",676
+6824712500386000,1,27266000,6824712527652000,0,"R",120,"[NULL]","swapper/5",0
+6824712526884000,0,181000,6824712527065000,743,"S",120,743,"kworker/0:5",20371
+6824712527065000,0,125000,6824712527190000,711,"S",120,711,"kworker/u16:2",19725
+6824712527190000,0,978000,6824712528168000,786,"S",111,494,"SDM_EventThread",685
+6824712527652000,1,437000,6824712528089000,771,"S",97,493,"DispSync",676
+6824712528089000,1,1245000,6824712529334000,0,"R",120,"[NULL]","swapper/5",0
+6824712528168000,0,70000,6824712528238000,702,"S",120,702,"kworker/u16:7",19422
+6824712528238000,0,994000,6824712529232000,0,"R",120,"[NULL]","swapper/5",0
+6824712528446000,2,487000,6824712528933000,773,"S",97,493,"app",678
+6824712528544000,3,620000,6824712529164000,777,"S",120,493,"HwBinder:640_1",721
+6824712528933000,2,52000,6824712528985000,0,"R",120,"[NULL]","swapper/5",0
+6824712528985000,2,78000,6824712529063000,773,"S",97,493,"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,644,"R",120,644,"ndroid.systemui",1664
+6824712529334000,1,86000,6824712529420000,771,"S",97,493,"DispSync",676
+6824712529420000,1,3171000,6824712532591000,0,"R",120,"[NULL]","swapper/5",0
+6824712530067000,0,157000,6824712530224000,1920,"S",120,667,"Executor-7",14763
+6824712530224000,0,2349000,6824712532573000,644,"S",120,644,"ndroid.systemui",1664
+6824712532573000,0,701000,6824712533274000,0,"R",120,"[NULL]","swapper/5",0
+6824712532591000,1,395000,6824712532986000,770,"S",120,493,"Binder:640_2",675
+6824712532986000,1,786000,6824712533772000,0,"R",120,"[NULL]","swapper/5",0
+6824712533274000,0,198000,6824712533472000,773,"S",97,493,"app",678
+6824712533472000,0,70000,6824712533542000,0,"R",120,"[NULL]","swapper/5",0
+6824712533542000,0,67000,6824712533609000,3,"S",120,3,"ksoftirqd/0",3
+6824712533609000,0,26476000,6824712560085000,0,"R",120,"[NULL]","swapper/5",0
+6824712533772000,1,89000,6824712533861000,771,"S",97,493,"DispSync",676
+6824712533861000,1,27413000,6824712561274000,0,"R",120,"[NULL]","swapper/5",0
+6824712560085000,0,224000,6824712560309000,743,"S",120,743,"kworker/0:5",20371
+6824712560309000,0,1129000,6824712561438000,786,"S",111,494,"SDM_EventThread",685
+6824712561274000,1,622000,6824712561896000,777,"S",120,493,"HwBinder:640_1",721
+6824712561438000,0,79000,6824712561517000,0,"R",120,"[NULL]","swapper/5",0
+6824712561517000,0,189000,6824712561706000,3,"S",120,3,"ksoftirqd/0",3
+6824712561658000,2,329000,6824712561987000,771,"S",97,493,"DispSync",676
+6824712561706000,0,1079000,6824712562785000,702,"S",120,702,"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,773,"S",97,493,"app",678
+6824712562785000,0,106000,6824712562891000,743,"S",120,743,"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,644,"S",120,644,"ndroid.systemui",1664
+6824712563387000,2,84000,6824712563471000,771,"S",97,493,"DispSync",676
+6824712563471000,2,66000,6824712563537000,0,"R",120,"[NULL]","swapper/5",0
+6824712563537000,2,61000,6824712563598000,22,"S",120,22,"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,770,"S",120,493,"Binder:640_2",675
+6824712566926000,0,798000,6824712567724000,0,"R",120,"[NULL]","swapper/5",0
+6824712567207000,1,209000,6824712567416000,773,"S",97,493,"app",678
+6824712567416000,1,25855000,6824712593271000,0,"R",120,"[NULL]","swapper/5",0
+6824712567724000,0,90000,6824712567814000,771,"S",97,493,"DispSync",676
+6824712567814000,0,23951000,6824712591765000,0,"R",120,"[NULL]","swapper/5",0
+6824712591765000,0,69000,6824712591834000,3,"S",120,3,"ksoftirqd/0",3
+6824712591774000,2,643000,6824712592417000,479,"S",120,479,"hwservicemanage",602
+6824712591834000,0,141000,6824712591975000,743,"S",120,743,"kworker/0:5",20371
+6824712591975000,0,943000,6824712592918000,786,"S",111,494,"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,777,"S",120,493,"HwBinder:640_1",721
+6824712593773000,0,313000,6824712594086000,771,"S",97,493,"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,15,"S",120,15,"ksoftirqd/1",17
+6824712594167000,1,1145000,6824712595312000,0,"R",120,"[NULL]","swapper/5",0
+6824712594391000,2,543000,6824712594934000,773,"S",97,493,"app",678
+6824712594934000,2,33189000,6824712628123000,0,"R",120,"[NULL]","swapper/5",0
+6824712595209000,0,3193000,6824712598402000,644,"S",120,644,"ndroid.systemui",1664
+6824712595312000,1,84000,6824712595396000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712598837000,1,566000,6824712599403000,0,"R",120,"[NULL]","swapper/5",0
+6824712599040000,0,182000,6824712599222000,773,"S",97,493,"app",678
+6824712599222000,0,27826000,6824712627048000,0,"R",120,"[NULL]","swapper/5",0
+6824712599403000,1,87000,6824712599490000,771,"S",97,493,"DispSync",676
+6824712599490000,1,27821000,6824712627311000,0,"R",120,"[NULL]","swapper/5",0
+6824712627048000,0,215000,6824712627263000,743,"S",120,743,"kworker/0:5",20371
+6824712627263000,0,865000,6824712628128000,786,"S",111,494,"SDM_EventThread",685
+6824712627311000,1,535000,6824712627846000,771,"S",97,493,"DispSync",676
+6824712627846000,1,97000,6824712627943000,0,"R",120,"[NULL]","swapper/5",0
+6824712627943000,1,143000,6824712628086000,15,"S",120,15,"ksoftirqd/1",17
+6824712628086000,1,559000,6824712628645000,777,"S",120,493,"HwBinder:640_1",721
+6824712628123000,2,487000,6824712628610000,773,"S",97,493,"app",678
+6824712628128000,0,134000,6824712628262000,702,"S",120,702,"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,644,"S",120,644,"ndroid.systemui",1664
+6824712629402000,0,86000,6824712629488000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712632825000,0,777000,6824712633602000,0,"R",120,"[NULL]","swapper/5",0
+6824712633103000,1,300000,6824712633403000,773,"S",97,493,"app",678
+6824712633403000,1,24713000,6824712658116000,0,"R",120,"[NULL]","swapper/5",0
+6824712633602000,0,89000,6824712633691000,771,"S",97,493,"DispSync",676
+6824712633691000,0,8761000,6824712642452000,0,"R",120,"[NULL]","swapper/5",0
+6824712642452000,0,1867000,6824712644319000,702,"R+",120,702,"kworker/u16:7",19422
+6824712644319000,0,91000,6824712644410000,458,"S",100,458,"kworker/0:1H",558
+6824712644410000,0,777000,6824712645187000,711,"D",120,711,"kworker/u16:2",19725
+6824712645187000,0,70000,6824712645257000,77,"S",120,77,"smem_native_rpm",87
+6824712645257000,0,107000,6824712645364000,702,"S",120,702,"kworker/u16:7",19422
+6824712645364000,0,605000,6824712645969000,0,"R",120,"[NULL]","swapper/5",0
+6824712645969000,0,204000,6824712646173000,711,"D",120,711,"kworker/u16:2",19725
+6824712646173000,0,123000,6824712646296000,77,"S",120,77,"smem_native_rpm",87
+6824712646296000,0,140000,6824712646436000,711,"D",120,711,"kworker/u16:2",19725
+6824712646436000,0,48000,6824712646484000,77,"S",120,77,"smem_native_rpm",87
+6824712646484000,0,171000,6824712646655000,0,"R",120,"[NULL]","swapper/5",0
+6824712646655000,0,46000,6824712646701000,458,"S",100,458,"kworker/0:1H",558
+6824712646701000,0,144000,6824712646845000,711,"D",120,711,"kworker/u16:2",19725
+6824712646845000,0,124000,6824712646969000,77,"S",120,77,"smem_native_rpm",87
+6824712646969000,0,167000,6824712647136000,711,"D",120,711,"kworker/u16:2",19725
+6824712647136000,0,49000,6824712647185000,77,"S",120,77,"smem_native_rpm",87
+6824712647185000,0,104000,6824712647289000,0,"R",120,"[NULL]","swapper/5",0
+6824712647289000,0,146000,6824712647435000,711,"D",120,711,"kworker/u16:2",19725
+6824712647435000,0,48000,6824712647483000,77,"S",120,77,"smem_native_rpm",87
+6824712647483000,0,945000,6824712648428000,0,"R",120,"[NULL]","swapper/5",0
+6824712648428000,0,169000,6824712648597000,711,"D",120,711,"kworker/u16:2",19725
+6824712648597000,0,119000,6824712648716000,77,"S",120,77,"smem_native_rpm",87
+6824712648716000,0,149000,6824712648865000,711,"D",120,711,"kworker/u16:2",19725
+6824712648865000,0,54000,6824712648919000,77,"S",120,77,"smem_native_rpm",87
+6824712648919000,0,62000,6824712648981000,0,"R",120,"[NULL]","swapper/5",0
+6824712648981000,0,150000,6824712649131000,711,"D",120,711,"kworker/u16:2",19725
+6824712649131000,0,113000,6824712649244000,77,"S",120,77,"smem_native_rpm",87
+6824712649244000,0,139000,6824712649383000,711,"D",120,711,"kworker/u16:2",19725
+6824712649383000,0,48000,6824712649431000,77,"S",120,77,"smem_native_rpm",87
+6824712649431000,0,72000,6824712649503000,0,"R",120,"[NULL]","swapper/5",0
+6824712649503000,0,130000,6824712649633000,711,"R+",120,711,"kworker/u16:2",19725
+6824712649633000,0,28000,6824712649661000,77,"S",120,77,"smem_native_rpm",87
+6824712649661000,0,41000,6824712649702000,711,"D",120,711,"kworker/u16:2",19725
+6824712649702000,0,58000,6824712649760000,0,"R",120,"[NULL]","swapper/5",0
+6824712649760000,0,262000,6824712650022000,711,"R+",120,711,"kworker/u16:2",19725
+6824712650022000,0,45000,6824712650067000,458,"S",100,458,"kworker/0:1H",558
+6824712650067000,0,34000,6824712650101000,77,"S",120,77,"smem_native_rpm",87
+6824712650101000,0,134000,6824712650235000,711,"R+",120,711,"kworker/u16:2",19725
+6824712650235000,0,27000,6824712650262000,77,"S",120,77,"smem_native_rpm",87
+6824712650262000,0,42000,6824712650304000,711,"D",120,711,"kworker/u16:2",19725
+6824712650304000,0,91000,6824712650395000,0,"R",120,"[NULL]","swapper/5",0
+6824712650395000,0,177000,6824712650572000,711,"R+",120,711,"kworker/u16:2",19725
+6824712650572000,0,63000,6824712650635000,77,"S",120,77,"smem_native_rpm",87
+6824712650635000,0,222000,6824712650857000,711,"D",120,711,"kworker/u16:2",19725
+6824712650857000,0,1177000,6824712652034000,0,"R",120,"[NULL]","swapper/5",0
+6824712652034000,0,108000,6824712652142000,711,"R+",120,711,"kworker/u16:2",19725
+6824712652142000,0,349000,6824712652491000,702,"S",120,702,"kworker/u16:7",19422
+6824712652491000,0,379000,6824712652870000,711,"S",120,711,"kworker/u16:2",19725
+6824712652870000,0,45000,6824712652915000,702,"S",120,702,"kworker/u16:7",19422
+6824712652915000,0,447000,6824712653362000,0,"R",120,"[NULL]","swapper/5",0
+6824712653004000,3,59000,6824712653063000,469,"S",100,469,"kworker/3:1H",578
+6824712653063000,3,70763000,6824712723826000,0,"R",120,"[NULL]","swapper/5",0
+6824712653362000,0,46000,6824712653408000,458,"S",100,458,"kworker/0:1H",558
+6824712653408000,0,4244000,6824712657652000,0,"R",120,"[NULL]","swapper/5",0
+6824712657652000,0,93000,6824712657745000,743,"S",120,743,"kworker/0:5",20371
+6824712657745000,0,488000,6824712658233000,786,"S",111,494,"SDM_EventThread",685
+6824712658116000,1,447000,6824712658563000,777,"S",120,493,"HwBinder:640_1",721
+6824712658233000,0,57000,6824712658290000,0,"R",120,"[NULL]","swapper/5",0
+6824712658290000,0,53000,6824712658343000,3,"S",120,3,"ksoftirqd/0",3
+6824712658343000,0,1697000,6824712660040000,0,"R",120,"[NULL]","swapper/5",0
+6824712658407000,2,117000,6824712658524000,771,"S",97,493,"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,743,"S",120,743,"kworker/0:5",20371
+6824712660100000,1,184000,6824712660284000,771,"S",97,493,"DispSync",676
+6824712660137000,0,391000,6824712660528000,702,"S",120,702,"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,773,"S",97,493,"app",678
+6824712660883000,2,33798000,6824712694681000,0,"R",120,"[NULL]","swapper/5",0
+6824712660962000,0,1928000,6824712662890000,644,"S",120,644,"ndroid.systemui",1664
+6824712661032000,1,82000,6824712661114000,771,"S",97,493,"DispSync",676
+6824712661114000,1,1692000,6824712662806000,0,"R",120,"[NULL]","swapper/5",0
+6824712662806000,1,304000,6824712663110000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824712663482000,0,57000,6824712663539000,0,"R",120,"[NULL]","swapper/5",0
+6824712663539000,0,53000,6824712663592000,3,"S",120,3,"ksoftirqd/0",3
+6824712663592000,0,2553000,6824712666145000,0,"R",120,"[NULL]","swapper/5",0
+6824712663607000,1,90000,6824712663697000,771,"S",97,493,"DispSync",676
+6824712663697000,1,25560000,6824712689257000,0,"R",120,"[NULL]","swapper/5",0
+6824712666145000,0,109000,6824712666254000,77,"S",120,77,"smem_native_rpm",87
+6824712666254000,0,23413000,6824712689667000,0,"R",120,"[NULL]","swapper/5",0
+6824712689257000,1,201000,6824712689458000,15,"S",120,15,"ksoftirqd/1",17
+6824712689458000,1,81000,6824712689539000,693,"D",120,693,"kworker/1:1",18800
+6824712689539000,1,2472000,6824712692011000,0,"R",120,"[NULL]","swapper/5",0
+6824712689667000,0,99000,6824712689766000,702,"S",120,702,"kworker/u16:7",19422
+6824712689766000,0,1565000,6824712691331000,0,"R",120,"[NULL]","swapper/5",0
+6824712691331000,0,95000,6824712691426000,743,"S",120,743,"kworker/0:5",20371
+6824712691426000,0,518000,6824712691944000,786,"S",111,494,"SDM_EventThread",685
+6824712691944000,0,66000,6824712692010000,0,"R",120,"[NULL]","swapper/5",0
+6824712692010000,0,52000,6824712692062000,3,"S",120,3,"ksoftirqd/0",3
+6824712692011000,1,436000,6824712692447000,777,"S",120,493,"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,771,"S",97,493,"DispSync",676
+6824712692587000,0,1292000,6824712693879000,0,"R",120,"[NULL]","swapper/5",0
+6824712693618000,1,43000,6824712693661000,15,"S",120,15,"ksoftirqd/1",17
+6824712693661000,1,535000,6824712694196000,0,"R",120,"[NULL]","swapper/5",0
+6824712693879000,0,175000,6824712694054000,771,"S",97,493,"DispSync",676
+6824712694054000,0,541000,6824712694595000,0,"R",120,"[NULL]","swapper/5",0
+6824712694196000,1,322000,6824712694518000,773,"S",97,493,"app",678
+6824712694518000,1,1868000,6824712696386000,0,"R",120,"[NULL]","swapper/5",0
+6824712694595000,0,1875000,6824712696470000,644,"S",120,644,"ndroid.systemui",1664
+6824712694681000,2,92000,6824712694773000,771,"S",97,493,"DispSync",676
+6824712694773000,2,2264000,6824712697037000,0,"R",120,"[NULL]","swapper/5",0
+6824712696386000,1,443000,6824712696829000,770,"S",120,493,"Binder:640_2",675
+6824712696470000,0,141000,6824712696611000,0,"R",120,"[NULL]","swapper/5",0
+6824712696611000,0,78000,6824712696689000,773,"S",97,493,"app",678
+6824712696689000,0,44000,6824712696733000,0,"R",120,"[NULL]","swapper/5",0
+6824712696733000,0,164000,6824712696897000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712697128000,2,25635000,6824712722763000,0,"R",120,"[NULL]","swapper/5",0
+6824712703122000,0,62000,6824712703184000,702,"D",120,702,"kworker/u16:7",19422
+6824712703184000,0,133000,6824712703317000,0,"R",120,"[NULL]","swapper/5",0
+6824712703317000,0,21000,6824712703338000,3,"S",120,3,"ksoftirqd/0",3
+6824712703338000,0,51000,6824712703389000,743,"D",120,743,"kworker/0:5",20371
+6824712703389000,0,49000,6824712703438000,0,"R",120,"[NULL]","swapper/5",0
+6824712703438000,0,613000,6824712704051000,702,"D",120,702,"kworker/u16:7",19422
+6824712704051000,0,129000,6824712704180000,77,"S",120,77,"smem_native_rpm",87
+6824712704180000,0,129000,6824712704309000,702,"D",120,702,"kworker/u16:7",19422
+6824712704309000,0,114000,6824712704423000,77,"S",120,77,"smem_native_rpm",87
+6824712704423000,0,123000,6824712704546000,702,"D",120,702,"kworker/u16:7",19422
+6824712704546000,0,107000,6824712704653000,77,"S",120,77,"smem_native_rpm",87
+6824712704653000,0,136000,6824712704789000,702,"D",120,702,"kworker/u16:7",19422
+6824712704789000,0,50000,6824712704839000,77,"S",120,77,"smem_native_rpm",87
+6824712704839000,0,628000,6824712705467000,0,"R",120,"[NULL]","swapper/5",0
+6824712705467000,0,160000,6824712705627000,702,"D",120,702,"kworker/u16:7",19422
+6824712705627000,0,121000,6824712705748000,77,"S",120,77,"smem_native_rpm",87
+6824712705748000,0,124000,6824712705872000,702,"D",120,702,"kworker/u16:7",19422
+6824712705872000,0,136000,6824712706008000,77,"S",120,77,"smem_native_rpm",87
+6824712706008000,0,152000,6824712706160000,702,"D",120,702,"kworker/u16:7",19422
+6824712706160000,0,114000,6824712706274000,77,"S",120,77,"smem_native_rpm",87
+6824712706274000,0,125000,6824712706399000,702,"D",120,702,"kworker/u16:7",19422
+6824712706399000,0,48000,6824712706447000,77,"S",120,77,"smem_native_rpm",87
+6824712706447000,0,873000,6824712707320000,0,"R",120,"[NULL]","swapper/5",0
+6824712707137000,1,57000,6824712707194000,15,"S",120,15,"ksoftirqd/1",17
+6824712707194000,1,15412000,6824712722606000,0,"R",120,"[NULL]","swapper/5",0
+6824712707320000,0,162000,6824712707482000,702,"D",120,702,"kworker/u16:7",19422
+6824712707482000,0,105000,6824712707587000,77,"S",120,77,"smem_native_rpm",87
+6824712707587000,0,128000,6824712707715000,702,"D",120,702,"kworker/u16:7",19422
+6824712707715000,0,115000,6824712707830000,77,"S",120,77,"smem_native_rpm",87
+6824712707830000,0,124000,6824712707954000,702,"D",120,702,"kworker/u16:7",19422
+6824712707954000,0,110000,6824712708064000,77,"S",120,77,"smem_native_rpm",87
+6824712708064000,0,140000,6824712708204000,702,"D",120,702,"kworker/u16:7",19422
+6824712708204000,0,114000,6824712708318000,77,"S",120,77,"smem_native_rpm",87
+6824712708318000,0,82000,6824712708400000,702,"S",120,702,"kworker/u16:7",19422
+6824712708400000,0,15285000,6824712723685000,0,"R",120,"[NULL]","swapper/5",0
+6824712722606000,1,109000,6824712722715000,13,"S",0,13,"watchdog/1",15
+6824712722715000,1,79000,6824712722794000,0,"R",120,"[NULL]","swapper/5",0
+6824712722763000,2,73000,6824712722836000,20,"S",0,20,"watchdog/2",23
+6824712722794000,1,64000,6824712722858000,15,"S",120,15,"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,705,"D",120,705,"kworker/0:1",19511
+6824712723826000,3,72000,6824712723898000,27,"S",0,27,"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,701,"S",120,701,"kworker/0:3",19397
+6824712724739000,0,236000,6824712724975000,705,"R+",120,705,"kworker/0:1",19511
+6824712724975000,0,544000,6824712725519000,786,"S",111,494,"SDM_EventThread",685
+6824712725519000,0,64000,6824712725583000,705,"S",120,705,"kworker/0:1",19511
+6824712725583000,0,365000,6824712725948000,0,"R",120,"[NULL]","swapper/5",0
+6824712725647000,1,483000,6824712726130000,777,"S",120,493,"HwBinder:640_1",721
+6824712725948000,0,129000,6824712726077000,771,"S",97,493,"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,34,"S",0,34,"watchdog/4",39
+6824712726449000,4,657913000,6824713384362000,0,"R",120,"[NULL]","swapper/5",0
+6824712726858000,5,46000,6824712726904000,41,"S",0,41,"watchdog/5",47
+6824712726904000,5,48000,6824712726952000,0,"R",120,"[NULL]","swapper/5",0
+6824712726952000,5,38000,6824712726990000,43,"S",120,43,"ksoftirqd/5",49
+6824712726990000,5,678798000,6824713405788000,0,"R",120,"[NULL]","swapper/5",0
+6824712727327000,0,178000,6824712727505000,771,"S",97,493,"DispSync",676
+6824712727505000,0,702000,6824712728207000,0,"R",120,"[NULL]","swapper/5",0
+6824712727717000,1,350000,6824712728067000,773,"S",97,493,"app",678
+6824712728062000,6,48000,6824712728110000,48,"S",0,48,"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,644,"S",120,644,"ndroid.systemui",1664
+6824712728273000,2,88000,6824712728361000,771,"S",97,493,"DispSync",676
+6824712728361000,2,33537000,6824712761898000,0,"R",120,"[NULL]","swapper/5",0
+6824712729998000,7,46000,6824712730044000,55,"S",0,55,"watchdog/7",63
+6824712730044000,7,136266000,6824712866310000,0,"R",120,"[NULL]","swapper/5",0
+6824712730330000,1,314000,6824712730644000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824712731023000,0,2119000,6824712733142000,0,"R",120,"[NULL]","swapper/5",0
+6824712731211000,1,95000,6824712731306000,771,"S",97,493,"DispSync",676
+6824712731306000,1,27902000,6824712759208000,0,"R",120,"[NULL]","swapper/5",0
+6824712733142000,0,190000,6824712733332000,77,"S",120,77,"smem_native_rpm",87
+6824712733332000,0,25059000,6824712758391000,0,"R",120,"[NULL]","swapper/5",0
+6824712758312000,3,37000,6824712758349000,29,"S",120,29,"ksoftirqd/3",33
+6824712758349000,3,119000,6824712758468000,702,"S",120,702,"kworker/u16:7",19422
+6824712758391000,0,96000,6824712758487000,705,"S",120,705,"kworker/0:1",19511
+6824712758468000,3,38802000,6824712797270000,0,"R",120,"[NULL]","swapper/5",0
+6824712758487000,0,574000,6824712759061000,786,"S",111,494,"SDM_EventThread",685
+6824712759061000,0,699000,6824712759760000,0,"R",120,"[NULL]","swapper/5",0
+6824712759208000,1,489000,6824712759697000,777,"S",120,493,"HwBinder:640_1",721
+6824712759697000,1,1610000,6824712761307000,0,"R",120,"[NULL]","swapper/5",0
+6824712759760000,0,131000,6824712759891000,771,"S",97,493,"DispSync",676
+6824712759891000,0,227000,6824712760118000,0,"R",120,"[NULL]","swapper/5",0
+6824712760118000,0,54000,6824712760172000,705,"S",120,705,"kworker/0:1",19511
+6824712760172000,0,509000,6824712760681000,702,"S",120,702,"kworker/u16:7",19422
+6824712760681000,0,231000,6824712760912000,0,"R",120,"[NULL]","swapper/5",0
+6824712760912000,0,182000,6824712761094000,771,"S",97,493,"DispSync",676
+6824712761094000,0,708000,6824712761802000,0,"R",120,"[NULL]","swapper/5",0
+6824712761307000,1,363000,6824712761670000,773,"S",97,493,"app",678
+6824712761670000,1,2291000,6824712763961000,0,"R",120,"[NULL]","swapper/5",0
+6824712761802000,0,2190000,6824712763992000,644,"S",120,644,"ndroid.systemui",1664
+6824712761898000,2,92000,6824712761990000,771,"S",97,493,"DispSync",676
+6824712761990000,2,35024000,6824712797014000,0,"R",120,"[NULL]","swapper/5",0
+6824712763961000,1,312000,6824712764273000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824712764631000,0,30567000,6824712795198000,0,"R",120,"[NULL]","swapper/5",0
+6824712764812000,1,95000,6824712764907000,771,"S",97,493,"DispSync",676
+6824712764907000,1,30302000,6824712795209000,0,"R",120,"[NULL]","swapper/5",0
+6824712795198000,0,480000,6824712795678000,771,"S",97,493,"DispSync",676
+6824712795209000,1,163000,6824712795372000,15,"S",120,15,"ksoftirqd/1",17
+6824712795372000,1,877000,6824712796249000,0,"R",120,"[NULL]","swapper/5",0
+6824712795678000,0,171000,6824712795849000,705,"S",120,705,"kworker/0:1",19511
+6824712795849000,0,1068000,6824712796917000,786,"S",111,494,"SDM_EventThread",685
+6824712796249000,1,683000,6824712796932000,773,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824712797270000,3,69000,6824712797339000,771,"S",97,493,"DispSync",676
+6824712797339000,3,3182000,6824712800521000,644,"S",120,644,"ndroid.systemui",1664
+6824712797629000,2,32555000,6824712830184000,0,"R",120,"[NULL]","swapper/5",0
+6824712797779000,0,87000,6824712797866000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712800939000,0,790000,6824712801729000,0,"R",120,"[NULL]","swapper/5",0
+6824712801226000,1,203000,6824712801429000,773,"S",97,493,"app",678
+6824712801429000,1,28175000,6824712829604000,0,"R",120,"[NULL]","swapper/5",0
+6824712801729000,0,88000,6824712801817000,771,"S",97,493,"DispSync",676
+6824712801817000,0,26133000,6824712827950000,0,"R",120,"[NULL]","swapper/5",0
+6824712827950000,0,303000,6824712828253000,705,"S",120,705,"kworker/0:1",19511
+6824712828253000,0,1174000,6824712829427000,786,"S",111,494,"SDM_EventThread",685
+6824712829427000,0,87000,6824712829514000,0,"R",120,"[NULL]","swapper/5",0
+6824712829514000,0,249000,6824712829763000,3,"S",120,3,"ksoftirqd/0",3
+6824712829604000,1,771000,6824712830375000,777,"S",120,493,"HwBinder:640_1",721
+6824712829763000,0,134000,6824712829897000,702,"S",120,702,"kworker/u16:7",19422
+6824712829897000,0,1050000,6824712830947000,0,"R",120,"[NULL]","swapper/5",0
+6824712830184000,2,302000,6824712830486000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824712831478000,0,3444000,6824712834922000,0,"R",120,"[NULL]","swapper/5",0
+6824712831761000,1,3128000,6824712834889000,644,"S",120,644,"ndroid.systemui",1664
+6824712831893000,2,86000,6824712831979000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824712835320000,0,775000,6824712836095000,0,"R",120,"[NULL]","swapper/5",0
+6824712835596000,1,201000,6824712835797000,773,"S",97,493,"app",678
+6824712835797000,1,24848000,6824712860645000,0,"R",120,"[NULL]","swapper/5",0
+6824712836095000,0,93000,6824712836188000,771,"S",97,493,"DispSync",676
+6824712836188000,0,23047000,6824712859235000,0,"R",120,"[NULL]","swapper/5",0
+6824712838657000,6,193000,6824712838850000,630,"S",100,630,"kworker/u17:1",1134
+6824712838850000,6,70000,6824712838920000,0,"R",120,"[NULL]","swapper/5",0
+6824712838920000,6,49000,6824712838969000,50,"S",120,50,"ksoftirqd/6",57
+6824712838969000,6,3751000,6824712842720000,0,"R",120,"[NULL]","swapper/5",0
+6824712841394000,2,165000,6824712841559000,22,"S",120,22,"ksoftirqd/2",25
+6824712841559000,2,3497000,6824712845056000,0,"R",120,"[NULL]","swapper/5",0
+6824712842720000,6,303000,6824712843023000,630,"S",100,630,"kworker/u17:1",1134
+6824712843023000,6,564000,6824712843587000,669,"S",120,669,"kworker/6:1",14833
+6824712843587000,6,2780000,6824712846367000,0,"R",120,"[NULL]","swapper/5",0
+6824712845056000,2,686000,6824712845742000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712845742000,2,3405000,6824712849147000,0,"R",120,"[NULL]","swapper/5",0
+6824712846367000,6,406000,6824712846773000,630,"S",100,630,"kworker/u17:1",1134
+6824712846773000,6,355000,6824712847128000,669,"S",120,669,"kworker/6:1",14833
+6824712847128000,6,206037000,6824713053165000,0,"R",120,"[NULL]","swapper/5",0
+6824712849147000,2,1203000,6824712850350000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712850350000,2,3128000,6824712853478000,739,"R+",120,739,"adbd",20305
+6824712853478000,2,128000,6824712853606000,24,"S",120,24,"rcuop/2",28
+6824712853606000,2,62000,6824712853668000,5,"S",120,5,"rcu_preempt",7
+6824712853668000,2,3944000,6824712857612000,739,"S",120,739,"adbd",20305
+6824712857612000,2,2594000,6824712860206000,2733,"R+",120,761,"sh",20457
+6824712859235000,0,137000,6824712859372000,705,"S",120,705,"kworker/0:1",19511
+6824712859372000,0,965000,6824712860337000,786,"S",111,494,"SDM_EventThread",685
+6824712860206000,2,85000,6824712860291000,694,"S",120,694,"kworker/2:0",18823
+6824712860291000,2,57000,6824712860348000,5,"S",120,5,"rcu_preempt",7
+6824712860337000,0,922000,6824712861259000,702,"S",120,702,"kworker/u16:7",19422
+6824712860348000,2,3024000,6824712863372000,2733,"R+",120,761,"sh",20457
+6824712860645000,1,709000,6824712861354000,777,"S",120,493,"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,771,"S",97,493,"DispSync",676
+6824712861731000,3,1521000,6824712863252000,0,"R",120,"[NULL]","swapper/5",0
+6824712861812000,0,223000,6824712862035000,771,"S",97,493,"DispSync",676
+6824712862035000,0,716000,6824712862751000,0,"R",120,"[NULL]","swapper/5",0
+6824712862392000,1,491000,6824712862883000,773,"S",97,493,"app",678
+6824712862751000,0,3243000,6824712865994000,644,"S",120,644,"ndroid.systemui",1664
+6824712862883000,1,3367000,6824712866250000,0,"R",120,"[NULL]","swapper/5",0
+6824712863252000,3,63000,6824712863315000,771,"S",97,493,"DispSync",676
+6824712863315000,3,230000,6824712863545000,25,"S",120,25,"rcuos/2",29
+6824712863372000,2,95000,6824712863467000,5,"S",120,5,"rcu_preempt",7
+6824712863467000,2,80000,6824712863547000,24,"S",120,24,"rcuop/2",28
+6824712863545000,3,13874000,6824712877419000,0,"R",120,"[NULL]","swapper/5",0
+6824712863547000,2,40000,6824712863587000,6,"S",120,6,"rcu_sched",8
+6824712863587000,2,24000,6824712863611000,5,"S",120,5,"rcu_preempt",7
+6824712863611000,2,1548000,6824712865159000,2733,"R+",120,761,"sh",20457
+6824712865159000,2,3064000,6824712868223000,739,"R+",120,739,"adbd",20305
+6824712865994000,0,1047000,6824712867041000,0,"R",120,"[NULL]","swapper/5",0
+6824712866250000,1,587000,6824712866837000,770,"S",120,493,"Binder:640_2",675
+6824712866310000,7,74000,6824712866384000,145,"S",120,145,"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,773,"S",97,493,"app",678
+6824712867326000,0,9974000,6824712877300000,0,"R",120,"[NULL]","swapper/5",0
+6824712867608000,1,76000,6824712867684000,771,"S",97,493,"DispSync",676
+6824712867684000,1,110000,6824712867794000,630,"S",100,630,"kworker/u17:1",1134
+6824712867794000,1,62000,6824712867856000,0,"R",120,"[NULL]","swapper/5",0
+6824712867856000,1,140000,6824712867996000,630,"S",100,630,"kworker/u17:1",1134
+6824712867996000,1,60000,6824712868056000,698,"R+",120,698,"kworker/1:0",19220
+6824712868056000,1,59000,6824712868115000,630,"S",100,630,"kworker/u17:1",1134
+6824712868115000,1,111000,6824712868226000,698,"R+",120,698,"kworker/1:0",19220
+6824712868223000,2,292000,6824712868515000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712868226000,1,78000,6824712868304000,630,"S",100,630,"kworker/u17:1",1134
+6824712868304000,1,48000,6824712868352000,698,"R+",120,698,"kworker/1:0",19220
+6824712868352000,1,57000,6824712868409000,630,"S",100,630,"kworker/u17:1",1134
+6824712868409000,1,45000,6824712868454000,698,"R+",120,698,"kworker/1:0",19220
+6824712868454000,1,72000,6824712868526000,630,"S",100,630,"kworker/u17:1",1134
+6824712868515000,2,145000,6824712868660000,739,"S",120,739,"adbd",20305
+6824712868526000,1,257000,6824712868783000,698,"S",120,698,"kworker/1:0",19220
+6824712868660000,2,454000,6824712869114000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712868783000,1,1322000,6824712870105000,0,"R",120,"[NULL]","swapper/5",0
+6824712869114000,2,770000,6824712869884000,739,"S",120,739,"adbd",20305
+6824712869884000,2,197000,6824712870081000,2733,"R+",120,761,"sh",20457
+6824712870081000,2,56000,6824712870137000,5,"S",120,5,"rcu_preempt",7
+6824712870105000,1,117000,6824712870222000,630,"S",100,630,"kworker/u17:1",1134
+6824712870137000,2,41000,6824712870178000,6,"S",120,6,"rcu_sched",8
+6824712870178000,2,153000,6824712870331000,2733,"R+",120,761,"sh",20457
+6824712870222000,1,113000,6824712870335000,698,"R+",120,698,"kworker/1:0",19220
+6824712870331000,2,69000,6824712870400000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712870335000,1,43000,6824712870378000,630,"S",100,630,"kworker/u17:1",1134
+6824712870378000,1,66000,6824712870444000,698,"S",120,698,"kworker/1:0",19220
+6824712870400000,2,6436000,6824712876836000,2733,"R+",120,761,"sh",20457
+6824712870444000,1,20085000,6824712890529000,0,"R",120,"[NULL]","swapper/5",0
+6824712873102000,7,72000,6824712873174000,145,"S",120,145,"hwrng",215
+6824712873174000,7,5793000,6824712878967000,0,"R",120,"[NULL]","swapper/5",0
+6824712876836000,2,146000,6824712876982000,6,"S",120,6,"rcu_sched",8
+6824712876982000,2,88000,6824712877070000,5,"S",120,5,"rcu_preempt",7
+6824712877070000,2,86000,6824712877156000,24,"S",120,24,"rcuop/2",28
+6824712877156000,2,40000,6824712877196000,5,"S",120,5,"rcu_preempt",7
+6824712877196000,2,374000,6824712877570000,2734,"R",120,739,"shell",20458
+6824712877300000,0,156000,6824712877456000,702,"S",120,702,"kworker/u16:7",19422
+6824712877419000,3,189000,6824712877608000,25,"S",120,25,"rcuos/2",29
+6824712877456000,0,6419000,6824712883875000,0,"R",120,"[NULL]","swapper/5",0
+6824712877570000,2,32000,6824712877602000,6,"S",120,6,"rcu_sched",8
+6824712877602000,2,441000,6824712878043000,2734,"S",120,739,"shell",20458
+6824712877608000,3,13785000,6824712891393000,0,"R",120,"[NULL]","swapper/5",0
+6824712878043000,2,5493000,6824712883536000,2733,"R+",120,761,"sh",20457
+6824712878967000,7,74000,6824712879041000,145,"S",120,145,"hwrng",215
+6824712879041000,7,22599000,6824712901640000,0,"R",120,"[NULL]","swapper/5",0
+6824712883536000,2,224000,6824712883760000,482,"S",49,482,"sugov:0",605
+6824712883760000,2,7130000,6824712890890000,2733,"R",120,761,"sh",20457
+6824712883875000,0,37000,6824712883912000,6,"S",120,6,"rcu_sched",8
+6824712883912000,0,38000,6824712883950000,5,"S",120,5,"rcu_preempt",7
+6824712883950000,0,6876000,6824712890826000,0,"R",120,"[NULL]","swapper/5",0
+6824712890529000,1,61000,6824712890590000,693,"S",120,693,"kworker/1:1",18800
+6824712890590000,1,2884000,6824712893474000,0,"R",120,"[NULL]","swapper/5",0
+6824712890826000,0,72000,6824712890898000,5,"S",120,5,"rcu_preempt",7
+6824712890890000,2,188000,6824712891078000,24,"S",120,24,"rcuop/2",28
+6824712890898000,0,80000,6824712890978000,6,"S",120,6,"rcu_sched",8
+6824712890978000,0,595000,6824712891573000,0,"R",120,"[NULL]","swapper/5",0
+6824712891078000,2,5651000,6824712896729000,2733,"R",120,761,"sh",20457
+6824712891393000,3,58000,6824712891451000,25,"S",120,25,"rcuos/2",29
+6824712891451000,3,4407000,6824712895858000,0,"R",120,"[NULL]","swapper/5",0
+6824712891573000,0,40000,6824712891613000,5,"S",120,5,"rcu_preempt",7
+6824712891613000,0,803000,6824712892416000,0,"R",120,"[NULL]","swapper/5",0
+6824712892416000,0,105000,6824712892521000,705,"S",120,705,"kworker/0:1",19511
+6824712892521000,0,800000,6824712893321000,786,"S",111,494,"SDM_EventThread",685
+6824712893321000,0,850000,6824712894171000,0,"R",120,"[NULL]","swapper/5",0
+6824712893474000,1,566000,6824712894040000,777,"S",120,493,"HwBinder:640_1",721
+6824712894040000,1,1068000,6824712895108000,0,"R",120,"[NULL]","swapper/5",0
+6824712894171000,0,111000,6824712894282000,771,"S",97,493,"DispSync",676
+6824712894282000,0,714000,6824712894996000,0,"R",120,"[NULL]","swapper/5",0
+6824712894996000,0,140000,6824712895136000,771,"S",97,493,"DispSync",676
+6824712895108000,1,410000,6824712895518000,773,"S",97,493,"app",678
+6824712895136000,0,301000,6824712895437000,0,"R",120,"[NULL]","swapper/5",0
+6824712895437000,0,1223000,6824712896660000,644,"R",120,644,"ndroid.systemui",1664
+6824712895518000,1,2511000,6824712898029000,0,"R",120,"[NULL]","swapper/5",0
+6824712895858000,3,55000,6824712895913000,771,"S",97,493,"DispSync",676
+6824712895913000,3,20866000,6824712916779000,0,"R",120,"[NULL]","swapper/5",0
+6824712896660000,0,76000,6824712896736000,5,"S",120,5,"rcu_preempt",7
+6824712896729000,2,38000,6824712896767000,24,"S",120,24,"rcuop/2",28
+6824712896736000,0,1181000,6824712897917000,644,"S",120,644,"ndroid.systemui",1664
+6824712896767000,2,3122000,6824712899889000,2733,"R",120,761,"sh",20457
+6824712897917000,0,362000,6824712898279000,0,"R",120,"[NULL]","swapper/5",0
+6824712898029000,1,330000,6824712898359000,770,"S",120,493,"Binder:640_2",675
+6824712898279000,0,181000,6824712898460000,773,"S",97,493,"app",678
+6824712898359000,1,40000,6824712898399000,0,"R",120,"[NULL]","swapper/5",0
+6824712898399000,1,53000,6824712898452000,771,"S",97,493,"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,24,"S",120,24,"rcuop/2",28
+6824712900013000,2,3333000,6824712903346000,2733,"R",120,761,"sh",20457
+6824712900383000,0,51000,6824712900434000,5,"S",120,5,"rcu_preempt",7
+6824712900434000,0,6845000,6824712907279000,0,"R",120,"[NULL]","swapper/5",0
+6824712901640000,7,72000,6824712901712000,145,"S",120,145,"hwrng",215
+6824712901712000,7,80781000,6824712982493000,0,"R",120,"[NULL]","swapper/5",0
+6824712903346000,2,197000,6824712903543000,482,"S",49,482,"sugov:0",605
+6824712903543000,2,3857000,6824712907400000,2733,"R",120,761,"sh",20457
+6824712907279000,0,57000,6824712907336000,743,"S",120,743,"kworker/0:5",20371
+6824712907336000,0,77000,6824712907413000,5,"S",120,5,"rcu_preempt",7
+6824712907400000,2,66000,6824712907466000,24,"S",120,24,"rcuop/2",28
+6824712907413000,0,51000,6824712907464000,0,"R",120,"[NULL]","swapper/5",0
+6824712907464000,0,27000,6824712907491000,5,"S",120,5,"rcu_preempt",7
+6824712907466000,2,180000,6824712907646000,2733,"R+",120,761,"sh",20457
+6824712907491000,0,6442000,6824712913933000,0,"R",120,"[NULL]","swapper/5",0
+6824712907646000,2,198000,6824712907844000,2734,"S",120,739,"shell",20458
+6824712907844000,2,962000,6824712908806000,739,"R+",120,739,"adbd",20305
+6824712908806000,2,188000,6824712908994000,630,"S",100,630,"kworker/u17:1",1134
+6824712908994000,2,81000,6824712909075000,694,"S",120,694,"kworker/2:0",18823
+6824712909075000,2,25000,6824712909100000,670,"S",100,670,"kworker/u17:2",14944
+6824712909100000,2,79000,6824712909179000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712909179000,2,99000,6824712909278000,739,"R+",120,739,"adbd",20305
+6824712909278000,2,50000,6824712909328000,670,"S",100,670,"kworker/u17:2",14944
+6824712909328000,2,49000,6824712909377000,694,"R+",120,694,"kworker/2:0",18823
+6824712909377000,2,21000,6824712909398000,670,"S",100,670,"kworker/u17:2",14944
+6824712909398000,2,10000,6824712909408000,694,"S",120,694,"kworker/2:0",18823
+6824712909408000,2,164000,6824712909572000,739,"R+",120,739,"adbd",20305
+6824712909572000,2,42000,6824712909614000,670,"S",100,670,"kworker/u17:2",14944
+6824712909614000,2,53000,6824712909667000,739,"R+",120,739,"adbd",20305
+6824712909667000,2,62000,6824712909729000,670,"S",100,670,"kworker/u17:2",14944
+6824712909729000,2,88000,6824712909817000,739,"S",120,739,"adbd",20305
+6824712909817000,2,183000,6824712910000000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712910000000,2,101000,6824712910101000,694,"S",120,694,"kworker/2:0",18823
+6824712910101000,2,40000,6824712910141000,2487,"R",120,739,"UsbFfs-worker",20308
+6824712910141000,2,36000,6824712910177000,670,"S",100,670,"kworker/u17:2",14944
+6824712910177000,2,35000,6824712910212000,2487,"R",120,739,"UsbFfs-worker",20308
+6824712910212000,2,56000,6824712910268000,670,"S",100,670,"kworker/u17:2",14944
+6824712910268000,2,37000,6824712910305000,694,"R",120,694,"kworker/2:0",18823
+6824712910305000,2,35000,6824712910340000,670,"S",100,670,"kworker/u17:2",14944
+6824712910340000,2,34000,6824712910374000,694,"R",120,694,"kworker/2:0",18823
+6824712910374000,2,46000,6824712910420000,670,"S",100,670,"kworker/u17:2",14944
+6824712910420000,2,78000,6824712910498000,694,"S",120,694,"kworker/2:0",18823
+6824712910498000,2,292000,6824712910790000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712910790000,2,280000,6824712911070000,739,"R+",120,739,"adbd",20305
+6824712911070000,2,92000,6824712911162000,670,"S",100,670,"kworker/u17:2",14944
+6824712911162000,2,10000,6824712911172000,630,"S",100,630,"kworker/u17:1",1134
+6824712911172000,2,47000,6824712911219000,739,"R",120,739,"adbd",20305
+6824712911219000,2,22000,6824712911241000,630,"S",100,630,"kworker/u17:1",1134
+6824712911241000,2,85000,6824712911326000,739,"S",120,739,"adbd",20305
+6824712911326000,2,112000,6824712911438000,2734,"S",120,739,"shell",20458
+6824712911438000,2,42000,6824712911480000,694,"S",120,694,"kworker/2:0",18823
+6824712911480000,2,22000,6824712911502000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712911502000,2,2059000,6824712913561000,2733,"S",120,761,"sh",20457
+6824712913561000,2,431000,6824712913992000,2735,"R+",120,762,"sh",20459
+6824712913933000,0,84000,6824712914017000,5,"S",120,5,"rcu_preempt",7
+6824712913992000,2,65000,6824712914057000,24,"S",120,24,"rcuop/2",28
+6824712914017000,0,1135000,6824712915152000,0,"R",120,"[NULL]","swapper/5",0
+6824712914057000,2,670000,6824712914727000,2735,"R+",120,762,"sh",20459
+6824712914727000,2,46000,6824712914773000,24,"S",120,24,"rcuop/2",28
+6824712914773000,2,1850000,6824712916623000,2735,"R+",120,762,"sh",20459
+6824712915152000,0,39000,6824712915191000,5,"S",120,5,"rcu_preempt",7
+6824712915191000,0,2005000,6824712917196000,0,"R",120,"[NULL]","swapper/5",0
+6824712916623000,2,1909000,6824712918532000,2733,"I",120,761,"sh",20457
+6824712916779000,3,89000,6824712916868000,25,"S",120,25,"rcuos/2",29
+6824712916868000,3,6871000,6824712923739000,0,"R",120,"[NULL]","swapper/5",0
+6824712917196000,0,38000,6824712917234000,6,"S",120,6,"rcu_sched",8
+6824712917234000,0,3105000,6824712920339000,0,"R",120,"[NULL]","swapper/5",0
+6824712918532000,2,938000,6824712919470000,2734,"I",120,739,"shell",20458
+6824712919470000,2,1271000,6824712920741000,739,"S",120,739,"adbd",20305
+6824712920339000,0,118000,6824712920457000,630,"S",100,630,"kworker/u17:1",1134
+6824712920457000,0,98000,6824712920555000,743,"S",120,743,"kworker/0:5",20371
+6824712920555000,0,67000,6824712920622000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712920622000,0,44000,6824712920666000,630,"S",100,630,"kworker/u17:1",1134
+6824712920666000,0,83000,6824712920749000,5,"S",120,5,"rcu_preempt",7
+6824712920741000,2,90000,6824712920831000,24,"S",120,24,"rcuop/2",28
+6824712920749000,0,63000,6824712920812000,0,"R",120,"[NULL]","swapper/5",0
+6824712920812000,0,59000,6824712920871000,630,"S",100,630,"kworker/u17:1",1134
+6824712920831000,2,100000,6824712920931000,2735,"R+",120,762,"sh",20459
+6824712920871000,0,56000,6824712920927000,743,"R+",120,743,"kworker/0:5",20371
+6824712920927000,0,28000,6824712920955000,630,"S",100,630,"kworker/u17:1",1134
+6824712920931000,2,327000,6824712921258000,482,"S",49,482,"sugov:0",605
+6824712920955000,0,8000,6824712920963000,743,"S",120,743,"kworker/0:5",20371
+6824712920963000,0,23000,6824712920986000,2487,"R",120,739,"UsbFfs-worker",20308
+6824712920986000,0,40000,6824712921026000,630,"S",100,630,"kworker/u17:1",1134
+6824712921026000,0,41000,6824712921067000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712921067000,0,15000,6824712921082000,5,"R+",120,5,"rcu_preempt",7
+6824712921082000,0,68000,6824712921150000,630,"S",100,630,"kworker/u17:1",1134
+6824712921150000,0,50000,6824712921200000,743,"R+",120,743,"kworker/0:5",20371
+6824712921200000,0,48000,6824712921248000,630,"S",100,630,"kworker/u17:1",1134
+6824712921248000,0,48000,6824712921296000,743,"R+",120,743,"kworker/0:5",20371
+6824712921258000,2,54000,6824712921312000,2735,"I",120,762,"sh",20459
+6824712921296000,0,38000,6824712921334000,630,"S",100,630,"kworker/u17:1",1134
+6824712921312000,2,8350000,6824712929662000,0,"R",120,"[NULL]","swapper/5",0
+6824712921334000,0,41000,6824712921375000,743,"S",120,743,"kworker/0:5",20371
+6824712921375000,0,204000,6824712921579000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712921579000,0,177000,6824712921756000,739,"S",120,739,"adbd",20305
+6824712921756000,0,15000,6824712921771000,5,"S",120,5,"rcu_preempt",7
+6824712921771000,0,337000,6824712922108000,0,"R",120,"[NULL]","swapper/5",0
+6824712922108000,0,39000,6824712922147000,630,"S",100,630,"kworker/u17:1",1134
+6824712922147000,0,31000,6824712922178000,743,"S",120,743,"kworker/0:5",20371
+6824712922178000,0,23000,6824712922201000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712922201000,0,1099000,6824712923300000,0,"R",120,"[NULL]","swapper/5",0
+6824712923300000,0,66000,6824712923366000,6,"S",120,6,"rcu_sched",8
+6824712923366000,0,2472000,6824712925838000,0,"R",120,"[NULL]","swapper/5",0
+6824712923739000,3,108000,6824712923847000,25,"S",120,25,"rcuos/2",29
+6824712923847000,3,21000,6824712923868000,6,"S",120,6,"rcu_sched",8
+6824712923868000,3,6431000,6824712930299000,0,"R",120,"[NULL]","swapper/5",0
+6824712925838000,0,33000,6824712925871000,743,"R+",120,743,"kworker/0:5",20371
+6824712925871000,0,645000,6824712926516000,786,"S",111,494,"SDM_EventThread",685
+6824712926516000,0,30000,6824712926546000,743,"S",120,743,"kworker/0:5",20371
+6824712926546000,0,967000,6824712927513000,0,"R",120,"[NULL]","swapper/5",0
+6824712926764000,1,82000,6824712926846000,702,"S",120,702,"kworker/u16:7",19422
+6824712926846000,1,16000,6824712926862000,5,"S",120,5,"rcu_preempt",7
+6824712926862000,1,489000,6824712927351000,777,"S",120,493,"HwBinder:640_1",721
+6824712927351000,1,1624000,6824712928975000,0,"R",120,"[NULL]","swapper/5",0
+6824712927513000,0,89000,6824712927602000,771,"S",97,493,"DispSync",676
+6824712927602000,0,969000,6824712928571000,0,"R",120,"[NULL]","swapper/5",0
+6824712928571000,0,92000,6824712928663000,771,"S",97,493,"DispSync",676
+6824712928663000,0,909000,6824712929572000,0,"R",120,"[NULL]","swapper/5",0
+6824712928975000,1,295000,6824712929270000,773,"S",97,493,"app",678
+6824712929270000,1,2298000,6824712931568000,0,"R",120,"[NULL]","swapper/5",0
+6824712929572000,0,1853000,6824712931425000,644,"S",120,644,"ndroid.systemui",1664
+6824712929662000,2,29000,6824712929691000,771,"S",97,493,"DispSync",676
+6824712929691000,2,2432000,6824712932123000,0,"R",120,"[NULL]","swapper/5",0
+6824712930299000,3,39000,6824712930338000,6,"S",120,6,"rcu_sched",8
+6824712930338000,3,37000,6824712930375000,25,"S",120,25,"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,770,"S",120,493,"Binder:640_2",675
+6824712931744000,0,102000,6824712931846000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824712932156000,2,1529000,6824712933685000,0,"R",120,"[NULL]","swapper/5",0
+6824712933309000,1,55000,6824712933364000,5,"S",120,5,"rcu_preempt",7
+6824712933364000,1,935000,6824712934299000,0,"R",120,"[NULL]","swapper/5",0
+6824712933685000,2,248000,6824712933933000,24,"S",120,24,"rcuop/2",28
+6824712933933000,2,27866000,6824712961799000,0,"R",120,"[NULL]","swapper/5",0
+6824712934299000,1,19000,6824712934318000,5,"S",120,5,"rcu_preempt",7
+6824712934318000,1,7968000,6824712942286000,0,"R",120,"[NULL]","swapper/5",0
+6824712942286000,1,302000,6824712942588000,482,"S",49,482,"sugov:0",605
+6824712942588000,1,197000,6824712942785000,5,"S",120,5,"rcu_preempt",7
+6824712942785000,1,171000,6824712942956000,24,"S",120,24,"rcuop/2",28
+6824712942956000,1,19657000,6824712962613000,0,"R",120,"[NULL]","swapper/5",0
+6824712961799000,2,620000,6824712962419000,22,"S",120,22,"ksoftirqd/2",25
+6824712961802000,0,176000,6824712961978000,743,"S",120,743,"kworker/0:5",20371
+6824712961978000,0,108000,6824712962086000,630,"S",100,630,"kworker/u17:1",1134
+6824712962086000,0,239000,6824712962325000,786,"R+",111,494,"SDM_EventThread",685
+6824712962325000,0,174000,6824712962499000,630,"S",100,630,"kworker/u17:1",1134
+6824712962419000,2,165000,6824712962584000,694,"S",120,694,"kworker/2:0",18823
+6824712962499000,0,997000,6824712963496000,702,"S",120,702,"kworker/u16:7",19422
+6824712962584000,2,967000,6824712963551000,0,"R",120,"[NULL]","swapper/5",0
+6824712962613000,1,435000,6824712963048000,771,"S",97,493,"DispSync",676
+6824712963048000,1,140000,6824712963188000,630,"S",100,630,"kworker/u17:1",1134
+6824712963188000,1,505000,6824712963693000,693,"S",120,693,"kworker/1:1",18800
+6824712963496000,0,688000,6824712964184000,786,"S",111,494,"SDM_EventThread",685
+6824712963551000,2,518000,6824712964069000,773,"S",97,493,"app",678
+6824712963693000,1,156000,6824712963849000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712963849000,1,66000,6824712963915000,0,"R",120,"[NULL]","swapper/5",0
+6824712963915000,1,403000,6824712964318000,644,"R",120,644,"ndroid.systemui",1664
+6824712964069000,2,11256000,6824712975325000,0,"R",120,"[NULL]","swapper/5",0
+6824712964184000,0,198000,6824712964382000,743,"S",120,743,"kworker/0:5",20371
+6824712964318000,1,572000,6824712964890000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712964382000,0,882000,6824712965264000,0,"R",120,"[NULL]","swapper/5",0
+6824712964448000,3,67000,6824712964515000,771,"S",97,493,"DispSync",676
+6824712964515000,3,578000,6824712965093000,777,"S",120,493,"HwBinder:640_1",721
+6824712964890000,1,6507000,6824712971397000,739,"S",120,739,"adbd",20305
+6824712965093000,3,29801000,6824712994894000,0,"R",120,"[NULL]","swapper/5",0
+6824712965264000,0,98000,6824712965362000,771,"S",97,493,"DispSync",676
+6824712965362000,0,9149000,6824712974511000,0,"R",120,"[NULL]","swapper/5",0
+6824712971397000,1,2878000,6824712974275000,644,"S",120,644,"ndroid.systemui",1664
+6824712974275000,1,2508000,6824712976783000,2720,"R+",120,755,"sh",20460
+6824712974511000,0,515000,6824712975026000,770,"S",120,493,"Binder:640_2",675
+6824712975026000,0,904000,6824712975930000,0,"R",120,"[NULL]","swapper/5",0
+6824712975325000,2,324000,6824712975649000,773,"S",97,493,"app",678
+6824712975649000,2,11143000,6824712986792000,0,"R",120,"[NULL]","swapper/5",0
+6824712975930000,0,113000,6824712976043000,771,"S",97,493,"DispSync",676
+6824712976043000,0,5748000,6824712981791000,0,"R",120,"[NULL]","swapper/5",0
+6824712976783000,1,140000,6824712976923000,702,"S",120,702,"kworker/u16:7",19422
+6824712976923000,1,2388000,6824712979311000,2720,"R+",120,755,"sh",20460
+6824712979311000,1,127000,6824712979438000,9,"S",120,9,"rcuos/0",11
+6824712979438000,1,54000,6824712979492000,6,"S",120,6,"rcu_sched",8
+6824712979492000,1,1949000,6824712981441000,2720,"R+",120,755,"sh",20460
+6824712981441000,1,88000,6824712981529000,8,"S",120,8,"rcuop/0",10
+6824712981529000,1,40000,6824712981569000,5,"S",120,5,"rcu_preempt",7
+6824712981569000,1,1127000,6824712982696000,2720,"R+",120,755,"sh",20460
+6824712981791000,0,2438000,6824712984229000,739,"S",120,739,"adbd",20305
+6824712982493000,7,74000,6824712982567000,145,"S",120,145,"hwrng",215
+6824712982567000,7,268581000,6824713251148000,0,"R",120,"[NULL]","swapper/5",0
+6824712982696000,1,31000,6824712982727000,145,"S",120,145,"hwrng",215
+6824712982727000,1,630000,6824712983357000,2720,"R",120,755,"sh",20460
+6824712983357000,1,58000,6824712983415000,6,"S",120,6,"rcu_sched",8
+6824712983415000,1,820000,6824712984235000,2720,"R+",120,755,"sh",20460
+6824712984229000,0,571000,6824712984800000,2728,"S",120,739,"shell",20461
+6824712984235000,1,175000,6824712984410000,630,"S",100,630,"kworker/u17:1",1134
+6824712984410000,1,138000,6824712984548000,693,"S",120,693,"kworker/1:1",18800
+6824712984548000,1,27000,6824712984575000,145,"S",120,145,"hwrng",215
+6824712984575000,1,155000,6824712984730000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712984730000,1,290000,6824712985020000,2720,"R+",120,755,"sh",20460
+6824712984800000,0,3033000,6824712987833000,0,"R",120,"[NULL]","swapper/5",0
+6824712985020000,1,73000,6824712985093000,630,"S",100,630,"kworker/u17:1",1134
+6824712985093000,1,600000,6824712985693000,2720,"R+",120,755,"sh",20460
+6824712985693000,1,141000,6824712985834000,630,"S",100,630,"kworker/u17:1",1134
+6824712985834000,1,51000,6824712985885000,693,"R+",120,693,"kworker/1:1",18800
+6824712985885000,1,79000,6824712985964000,630,"S",100,630,"kworker/u17:1",1134
+6824712985964000,1,186000,6824712986150000,693,"S",120,693,"kworker/1:1",18800
+6824712986150000,1,639000,6824712986789000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824712986789000,1,238000,6824712987027000,482,"S",49,482,"sugov:0",605
+6824712986792000,2,82000,6824712986874000,5,"S",120,5,"rcu_preempt",7
+6824712986874000,2,6897000,6824712993771000,0,"R",120,"[NULL]","swapper/5",0
+6824712987027000,1,358000,6824712987385000,739,"S",120,739,"adbd",20305
+6824712987385000,1,192000,6824712987577000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712987577000,1,951000,6824712988528000,2720,"R+",120,755,"sh",20460
+6824712987833000,0,421000,6824712988254000,739,"S",120,739,"adbd",20305
+6824712988254000,0,185000,6824712988439000,2728,"S",120,739,"shell",20461
+6824712988439000,0,4499000,6824712992938000,0,"R",120,"[NULL]","swapper/5",0
+6824712988528000,1,87000,6824712988615000,630,"S",100,630,"kworker/u17:1",1134
+6824712988615000,1,69000,6824712988684000,693,"S",120,693,"kworker/1:1",18800
+6824712988684000,1,65000,6824712988749000,2487,"S",120,739,"UsbFfs-worker",20308
+6824712988749000,1,1248000,6824712989997000,2720,"R",120,755,"sh",20460
+6824712989997000,1,90000,6824712990087000,6,"S",120,6,"rcu_sched",8
+6824712990087000,1,92000,6824712990179000,9,"S",120,9,"rcuos/0",11
+6824712990179000,1,76000,6824712990255000,18,"S",120,18,"rcuos/1",21
+6824712990255000,1,24000,6824712990279000,6,"S",120,6,"rcu_sched",8
+6824712990279000,1,2760000,6824712993039000,2720,"R+",120,755,"sh",20460
+6824712992938000,0,152000,6824712993090000,743,"S",120,743,"kworker/0:5",20371
+6824712993039000,1,804000,6824712993843000,786,"S",111,494,"SDM_EventThread",685
+6824712993090000,0,998000,6824712994088000,0,"R",120,"[NULL]","swapper/5",0
+6824712993771000,2,89000,6824712993860000,5,"S",120,5,"rcu_preempt",7
+6824712993843000,1,145000,6824712993988000,8,"S",120,8,"rcuop/0",10
+6824712993860000,2,587000,6824712994447000,0,"R",120,"[NULL]","swapper/5",0
+6824712993988000,1,34000,6824712994022000,17,"S",120,17,"rcuop/1",20
+6824712994022000,1,2637000,6824712996659000,2720,"R",120,755,"sh",20460
+6824712994088000,0,576000,6824712994664000,777,"S",120,493,"HwBinder:640_1",721
+6824712994447000,2,41000,6824712994488000,5,"S",120,5,"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,771,"S",97,493,"DispSync",676
+6824712995124000,3,1089000,6824712996213000,0,"R",120,"[NULL]","swapper/5",0
+6824712995416000,0,388000,6824712995804000,773,"S",97,493,"app",678
+6824712995804000,0,2854000,6824712998658000,0,"R",120,"[NULL]","swapper/5",0
+6824712996084000,2,2507000,6824712998591000,644,"S",120,644,"ndroid.systemui",1664
+6824712996213000,3,61000,6824712996274000,771,"S",97,493,"DispSync",676
+6824712996274000,3,31193000,6824713027467000,0,"R",120,"[NULL]","swapper/5",0
+6824712996659000,1,76000,6824712996735000,6,"S",120,6,"rcu_sched",8
+6824712996735000,1,52000,6824712996787000,9,"S",120,9,"rcuos/0",11
+6824712996787000,1,28000,6824712996815000,18,"S",120,18,"rcuos/1",21
+6824712996815000,1,3192000,6824713000007000,2720,"R+",120,755,"sh",20460
+6824712998591000,2,346000,6824712998937000,0,"R",120,"[NULL]","swapper/5",0
+6824712998658000,0,379000,6824712999037000,770,"S",120,493,"Binder:640_2",675
+6824712998937000,2,202000,6824712999139000,773,"S",97,493,"app",678
+6824712999037000,0,34000,6824712999071000,0,"R",120,"[NULL]","swapper/5",0
+6824712999071000,0,62000,6824712999133000,771,"S",97,493,"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,5,"S",120,5,"rcu_preempt",7
+6824713000114000,1,92000,6824713000206000,8,"S",120,8,"rcuop/0",10
+6824713000206000,1,61000,6824713000267000,17,"S",120,17,"rcuop/1",20
+6824713000267000,1,3074000,6824713003341000,2720,"R",120,755,"sh",20460
+6824713003341000,1,209000,6824713003550000,482,"S",49,482,"sugov:0",605
+6824713003550000,1,7239000,6824713010789000,2720,"R",120,755,"sh",20460
+6824713010789000,1,52000,6824713010841000,8,"S",120,8,"rcuop/0",10
+6824713010841000,1,35000,6824713010876000,5,"S",120,5,"rcu_preempt",7
+6824713010876000,1,95000,6824713010971000,2720,"R+",120,755,"sh",20460
+6824713010971000,1,26000,6824713010997000,145,"S",120,145,"hwrng",215
+6824713010997000,1,5636000,6824713016633000,2720,"R",120,755,"sh",20460
+6824713016633000,1,67000,6824713016700000,5,"S",120,5,"rcu_preempt",7
+6824713016700000,1,66000,6824713016766000,8,"S",120,8,"rcuop/0",10
+6824713016766000,1,36000,6824713016802000,17,"S",120,17,"rcuop/1",20
+6824713016802000,1,12000,6824713016814000,5,"S",120,5,"rcu_preempt",7
+6824713016814000,1,1724000,6824713018538000,2720,"S",120,755,"sh",20460
+6824713018538000,1,2161000,6824713020699000,2721,"R+",120,756,"sh",20462
+6824713020699000,1,225000,6824713020924000,482,"S",49,482,"sugov:0",605
+6824713020924000,1,273000,6824713021197000,2721,"S",120,756,"sh",20462
+6824713021197000,1,5881000,6824713027078000,0,"R",120,"[NULL]","swapper/5",0
+6824713021926000,0,1729000,6824713023655000,2722,"R+",120,757,"ps",20463
+6824713023655000,0,62000,6824713023717000,9,"S",120,9,"rcuos/0",11
+6824713023717000,0,29000,6824713023746000,6,"S",120,6,"rcu_sched",8
+6824713023746000,0,29000,6824713023775000,2722,"R+",120,757,"ps",20463
+6824713023775000,0,30000,6824713023805000,5,"S",120,5,"rcu_preempt",7
+6824713023805000,0,413000,6824713024218000,2722,"R+",120,757,"ps",20463
+6824713024218000,0,23000,6824713024241000,145,"S",120,145,"hwrng",215
+6824713024241000,0,556000,6824713024797000,2722,"R+",120,757,"ps",20463
+6824713024797000,0,9000,6824713024806000,145,"S",120,145,"hwrng",215
+6824713024806000,0,1217000,6824713026023000,2722,"R+",120,757,"ps",20463
+6824713026023000,0,91000,6824713026114000,743,"S",120,743,"kworker/0:5",20371
+6824713026114000,0,814000,6824713026928000,786,"S",111,494,"SDM_EventThread",685
+6824713026928000,0,45000,6824713026973000,5,"S",120,5,"rcu_preempt",7
+6824713026973000,0,263000,6824713027236000,2722,"R+",120,757,"ps",20463
+6824713027078000,1,93000,6824713027171000,702,"S",120,702,"kworker/u16:7",19422
+6824713027171000,1,67000,6824713027238000,8,"S",120,8,"rcuop/0",10
+6824713027212000,2,447000,6824713027659000,777,"S",120,493,"HwBinder:640_1",721
+6824713027236000,0,14000,6824713027250000,5,"S",120,5,"rcu_preempt",7
+6824713027238000,1,61000,6824713027299000,17,"S",120,17,"rcuop/1",20
+6824713027250000,0,2732000,6824713029982000,2722,"R",120,757,"ps",20463
+6824713027299000,1,655000,6824713027954000,0,"R",120,"[NULL]","swapper/5",0
+6824713027467000,3,179000,6824713027646000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824713028268000,1,2352000,6824713030620000,0,"R",120,"[NULL]","swapper/5",0
+6824713028560000,2,1914000,6824713030474000,644,"S",120,644,"ndroid.systemui",1664
+6824713028675000,3,34000,6824713028709000,771,"S",97,493,"DispSync",676
+6824713028709000,3,34349000,6824713063058000,0,"R",120,"[NULL]","swapper/5",0
+6824713029982000,0,33000,6824713030015000,6,"S",120,6,"rcu_sched",8
+6824713030015000,0,3308000,6824713033323000,2722,"R+",120,757,"ps",20463
+6824713030474000,2,705000,6824713031179000,0,"R",120,"[NULL]","swapper/5",0
+6824713030620000,1,274000,6824713030894000,770,"S",120,493,"Binder:640_2",675
+6824713030894000,1,696000,6824713031590000,0,"R",120,"[NULL]","swapper/5",0
+6824713031179000,2,137000,6824713031316000,773,"S",97,493,"app",678
+6824713031316000,2,29313000,6824713060629000,0,"R",120,"[NULL]","swapper/5",0
+6824713031590000,1,43000,6824713031633000,771,"S",97,493,"DispSync",676
+6824713031633000,1,2153000,6824713033786000,0,"R",120,"[NULL]","swapper/5",0
+6824713033323000,0,89000,6824713033412000,5,"S",120,5,"rcu_preempt",7
+6824713033412000,0,86000,6824713033498000,8,"S",120,8,"rcuop/0",10
+6824713033498000,0,13000,6824713033511000,5,"S",120,5,"rcu_preempt",7
+6824713033511000,0,3137000,6824713036648000,2722,"R",120,757,"ps",20463
+6824713033786000,1,36000,6824713033822000,17,"S",120,17,"rcuop/1",20
+6824713033822000,1,6659000,6824713040481000,0,"R",120,"[NULL]","swapper/5",0
+6824713036648000,0,56000,6824713036704000,6,"S",120,6,"rcu_sched",8
+6824713036704000,0,54000,6824713036758000,9,"S",120,9,"rcuos/0",11
+6824713036758000,0,10000,6824713036768000,6,"S",120,6,"rcu_sched",8
+6824713036768000,0,6593000,6824713043361000,2722,"R",120,757,"ps",20463
+6824713040481000,1,46000,6824713040527000,5,"S",120,5,"rcu_preempt",7
+6824713040527000,1,3210000,6824713043737000,0,"R",120,"[NULL]","swapper/5",0
+6824713043361000,0,195000,6824713043556000,482,"S",49,482,"sugov:0",605
+6824713043556000,0,3032000,6824713046588000,2722,"R",120,757,"ps",20463
+6824713043737000,1,36000,6824713043773000,6,"S",120,6,"rcu_sched",8
+6824713043773000,1,3242000,6824713047015000,0,"R",120,"[NULL]","swapper/5",0
+6824713046588000,0,37000,6824713046625000,482,"S",49,482,"sugov:0",605
+6824713046625000,0,431000,6824713047056000,2722,"R",120,757,"ps",20463
+6824713047015000,1,48000,6824713047063000,5,"S",120,5,"rcu_preempt",7
+6824713047056000,0,43000,6824713047099000,8,"S",120,8,"rcuop/0",10
+6824713047063000,1,3191000,6824713050254000,0,"R",120,"[NULL]","swapper/5",0
+6824713047099000,0,3188000,6824713050287000,2722,"R",120,757,"ps",20463
+6824713050254000,1,42000,6824713050296000,6,"S",120,6,"rcu_sched",8
+6824713050287000,0,36000,6824713050323000,9,"S",120,9,"rcuos/0",11
+6824713050296000,1,4103000,6824713054399000,0,"R",120,"[NULL]","swapper/5",0
+6824713050323000,0,3621000,6824713053944000,2722,"R",120,757,"ps",20463
+6824713053165000,6,647000,6824713053812000,650,"S",120,650,"m.android.phone",1702
+6824713053812000,6,196550000,6824713250362000,0,"R",120,"[NULL]","swapper/5",0
+6824713053944000,0,46000,6824713053990000,8,"S",120,8,"rcuop/0",10
+6824713053990000,0,65000,6824713054055000,2722,"R+",120,757,"ps",20463
+6824713054055000,0,22000,6824713054077000,145,"S",120,145,"hwrng",215
+6824713054077000,0,5450000,6824713059527000,2722,"R",120,757,"ps",20463
+6824713054399000,1,30000,6824713054429000,5,"S",120,5,"rcu_preempt",7
+6824713054429000,1,6141000,6824713060570000,0,"R",120,"[NULL]","swapper/5",0
+6824713059527000,0,91000,6824713059618000,743,"S",120,743,"kworker/0:5",20371
+6824713059618000,0,735000,6824713060353000,786,"S",111,494,"SDM_EventThread",685
+6824713060353000,0,48000,6824713060401000,743,"S",120,743,"kworker/0:5",20371
+6824713060401000,0,2914000,6824713063315000,2722,"R+",120,757,"ps",20463
+6824713060570000,1,23000,6824713060593000,15,"S",120,15,"ksoftirqd/1",17
+6824713060593000,1,54000,6824713060647000,5,"S",120,5,"rcu_preempt",7
+6824713060629000,2,431000,6824713061060000,777,"S",120,493,"HwBinder:640_1",721
+6824713060647000,1,274000,6824713060921000,0,"R",120,"[NULL]","swapper/5",0
+6824713060921000,1,103000,6824713061024000,771,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824713062024000,1,1073000,6824713063097000,0,"R",120,"[NULL]","swapper/5",0
+6824713062373000,2,326000,6824713062699000,773,"S",97,493,"app",678
+6824713062699000,2,2701000,6824713065400000,0,"R",120,"[NULL]","swapper/5",0
+6824713063058000,3,1709000,6824713064767000,644,"S",120,644,"ndroid.systemui",1664
+6824713063097000,1,28000,6824713063125000,771,"S",97,493,"DispSync",676
+6824713063125000,1,518000,6824713063643000,0,"R",120,"[NULL]","swapper/5",0
+6824713063315000,0,161000,6824713063476000,482,"S",49,482,"sugov:0",605
+6824713063476000,0,29511000,6824713092987000,2722,"R+",120,757,"ps",20463
+6824713063643000,1,682000,6824713064325000,702,"S",120,702,"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,770,"S",120,493,"Binder:640_2",675
+6824713065150000,1,321000,6824713065471000,0,"R",120,"[NULL]","swapper/5",0
+6824713065400000,2,110000,6824713065510000,773,"S",97,493,"app",678
+6824713065471000,1,26000,6824713065497000,771,"S",97,493,"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,5,"S",120,5,"rcu_preempt",7
+6824713066704000,2,53000,6824713066757000,8,"S",120,8,"rcuop/0",10
+6824713066709000,1,41000,6824713066750000,0,"R",120,"[NULL]","swapper/5",0
+6824713066750000,1,18000,6824713066768000,5,"S",120,5,"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,2728,"S",120,739,"shell",20461
+6824713071298000,1,679000,6824713071977000,0,"R",120,"[NULL]","swapper/5",0
+6824713071460000,2,412000,6824713071872000,739,"S",120,739,"adbd",20305
+6824713071872000,2,322000,6824713072194000,0,"R",120,"[NULL]","swapper/5",0
+6824713071977000,1,50000,6824713072027000,630,"S",100,630,"kworker/u17:1",1134
+6824713072027000,1,34000,6824713072061000,693,"S",120,693,"kworker/1:1",18800
+6824713072061000,1,129000,6824713072190000,0,"R",120,"[NULL]","swapper/5",0
+6824713072190000,1,20000,6824713072210000,630,"S",100,630,"kworker/u17:1",1134
+6824713072194000,2,45000,6824713072239000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713072529000,2,26000,6824713072555000,694,"S",120,694,"kworker/2:0",18823
+6824713072547000,1,36000,6824713072583000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713072661000,2,249000,6824713072910000,0,"R",120,"[NULL]","swapper/5",0
+6824713072910000,2,25000,6824713072935000,630,"S",100,630,"kworker/u17:1",1134
+6824713072935000,2,32000,6824713072967000,694,"S",120,694,"kworker/2:0",18823
+6824713072957000,1,71000,6824713073028000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713072967000,2,23000,6824713072990000,0,"R",120,"[NULL]","swapper/5",0
+6824713072990000,2,99000,6824713073089000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713073285000,2,117000,6824713073402000,8,"S",120,8,"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,5,"S",120,5,"rcu_preempt",7
+6824713073573000,1,3170000,6824713076743000,0,"R",120,"[NULL]","swapper/5",0
+6824713076743000,1,148000,6824713076891000,702,"D",120,702,"kworker/u16:7",19422
+6824713076891000,1,199000,6824713077090000,0,"R",120,"[NULL]","swapper/5",0
+6824713077090000,1,16000,6824713077106000,702,"S",120,702,"kworker/u16:7",19422
+6824713077103000,2,19000,6824713077122000,77,"S",120,77,"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,2728,"S",120,739,"shell",20461
+6824713079518000,1,417000,6824713079935000,0,"R",120,"[NULL]","swapper/5",0
+6824713079664000,2,293000,6824713079957000,739,"S",120,739,"adbd",20305
+6824713079935000,1,31000,6824713079966000,630,"S",100,630,"kworker/u17:1",1134
+6824713079957000,2,23000,6824713079980000,0,"R",120,"[NULL]","swapper/5",0
+6824713079966000,1,28000,6824713079994000,693,"S",120,693,"kworker/1:1",18800
+6824713079980000,2,20000,6824713080000000,630,"S",100,630,"kworker/u17:1",1134
+6824713079994000,1,24000,6824713080018000,2487,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713080166000,3,419000,6824713080585000,0,"R",120,"[NULL]","swapper/5",0
+6824713080320000,2,27000,6824713080347000,630,"S",100,630,"kworker/u17:1",1134
+6824713080347000,2,41000,6824713080388000,694,"S",120,694,"kworker/2:0",18823
+6824713080388000,2,452000,6824713080840000,0,"R",120,"[NULL]","swapper/5",0
+6824713080536000,1,38000,6824713080574000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713080574000,1,488000,6824713081062000,0,"R",120,"[NULL]","swapper/5",0
+6824713080585000,3,26000,6824713080611000,630,"S",100,630,"kworker/u17:1",1134
+6824713080611000,3,6419000,6824713087030000,0,"R",120,"[NULL]","swapper/5",0
+6824713080840000,2,23000,6824713080863000,630,"S",100,630,"kworker/u17:1",1134
+6824713080863000,2,43000,6824713080906000,694,"S",120,694,"kworker/2:0",18823
+6824713080906000,2,345000,6824713081251000,0,"R",120,"[NULL]","swapper/5",0
+6824713081062000,1,72000,6824713081134000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713081134000,1,6852000,6824713087986000,0,"R",120,"[NULL]","swapper/5",0
+6824713081251000,2,106000,6824713081357000,739,"S",120,739,"adbd",20305
+6824713081357000,2,6049000,6824713087406000,0,"R",120,"[NULL]","swapper/5",0
+6824713087030000,3,62000,6824713087092000,5,"S",120,5,"rcu_preempt",7
+6824713087092000,3,964000,6824713088056000,0,"R",120,"[NULL]","swapper/5",0
+6824713087406000,2,284000,6824713087690000,8,"S",120,8,"rcuop/0",10
+6824713087690000,2,783000,6824713088473000,0,"R",120,"[NULL]","swapper/5",0
+6824713087986000,1,139000,6824713088125000,2728,"S",120,739,"shell",20461
+6824713088056000,3,22000,6824713088078000,5,"S",120,5,"rcu_preempt",7
+6824713088078000,3,36000,6824713088114000,0,"R",120,"[NULL]","swapper/5",0
+6824713088114000,3,404000,6824713088518000,739,"S",120,739,"adbd",20305
+6824713088125000,1,464000,6824713088589000,0,"R",120,"[NULL]","swapper/5",0
+6824713088473000,2,53000,6824713088526000,630,"S",100,630,"kworker/u17:1",1134
+6824713088518000,3,43000,6824713088561000,0,"R",120,"[NULL]","swapper/5",0
+6824713088526000,2,74000,6824713088600000,694,"S",120,694,"kworker/2:0",18823
+6824713088561000,3,34000,6824713088595000,630,"S",100,630,"kworker/u17:1",1134
+6824713088589000,1,37000,6824713088626000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713088765000,3,41000,6824713088806000,686,"S",120,686,"kworker/3:1",17791
+6824713088806000,3,14000,6824713088820000,0,"R",120,"[NULL]","swapper/5",0
+6824713088820000,3,17000,6824713088837000,630,"S",100,630,"kworker/u17:1",1134
+6824713088837000,3,135000,6824713088972000,0,"R",120,"[NULL]","swapper/5",0
+6824713088972000,3,44000,6824713089016000,630,"S",100,630,"kworker/u17:1",1134
+6824713089016000,3,47000,6824713089063000,0,"R",120,"[NULL]","swapper/5",0
+6824713089063000,3,35000,6824713089098000,630,"S",100,630,"kworker/u17:1",1134
+6824713089098000,3,89000,6824713089187000,686,"S",120,686,"kworker/3:1",17791
+6824713089187000,3,4413000,6824713093600000,0,"R",120,"[NULL]","swapper/5",0
+6824713089216000,1,154000,6824713089370000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713089370000,1,4023000,6824713093393000,0,"R",120,"[NULL]","swapper/5",0
+6824713089621000,2,127000,6824713089748000,739,"S",120,739,"adbd",20305
+6824713089748000,2,4425000,6824713094173000,0,"R",120,"[NULL]","swapper/5",0
+6824713092987000,0,74000,6824713093061000,743,"S",120,743,"kworker/0:5",20371
+6824713093061000,0,3580000,6824713096641000,2722,"R+",120,757,"ps",20463
+6824713093393000,1,580000,6824713093973000,786,"S",111,494,"SDM_EventThread",685
+6824713093600000,3,36000,6824713093636000,5,"S",120,5,"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,777,"S",120,493,"HwBinder:640_1",721
+6824713094480000,1,99000,6824713094579000,771,"S",97,493,"DispSync",676
+6824713094540000,2,9000,6824713094549000,0,"R",120,"[NULL]","swapper/5",0
+6824713094549000,2,126000,6824713094675000,777,"S",120,493,"HwBinder:640_1",721
+6824713094579000,1,9000,6824713094588000,0,"R",120,"[NULL]","swapper/5",0
+6824713094588000,1,74000,6824713094662000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824713095274000,3,5029000,6824713100303000,0,"R",120,"[NULL]","swapper/5",0
+6824713095596000,1,2136000,6824713097732000,644,"S",120,644,"ndroid.systemui",1664
+6824713095679000,2,17000,6824713095696000,771,"S",97,493,"DispSync",676
+6824713095696000,2,2152000,6824713097848000,0,"R",120,"[NULL]","swapper/5",0
+6824713096641000,0,233000,6824713096874000,482,"S",49,482,"sugov:0",605
+6824713096874000,0,29589000,6824713126463000,2722,"R+",120,757,"ps",20463
+6824713097732000,1,701000,6824713098433000,0,"R",120,"[NULL]","swapper/5",0
+6824713097848000,2,321000,6824713098169000,770,"S",120,493,"Binder:640_2",675
+6824713098169000,2,724000,6824713098893000,0,"R",120,"[NULL]","swapper/5",0
+6824713098433000,1,171000,6824713098604000,773,"S",97,493,"app",678
+6824713098604000,1,39000,6824713098643000,0,"R",120,"[NULL]","swapper/5",0
+6824713098643000,1,113000,6824713098756000,482,"S",49,482,"sugov:0",605
+6824713098756000,1,488000,6824713099244000,0,"R",120,"[NULL]","swapper/5",0
+6824713098893000,2,25000,6824713098918000,771,"S",97,493,"DispSync",676
+6824713098918000,2,480000,6824713099398000,0,"R",120,"[NULL]","swapper/5",0
+6824713099244000,1,183000,6824713099427000,2728,"S",120,739,"shell",20461
+6824713099398000,2,1576000,6824713100974000,739,"S",120,739,"adbd",20305
+6824713099427000,1,51000,6824713099478000,0,"R",120,"[NULL]","swapper/5",0
+6824713099478000,1,65000,6824713099543000,1919,"S",120,667,"Executor-7",14762
+6824713099543000,1,1075000,6824713100618000,0,"R",120,"[NULL]","swapper/5",0
+6824713100303000,3,67000,6824713100370000,630,"S",100,630,"kworker/u17:1",1134
+6824713100370000,3,9000,6824713100379000,0,"R",120,"[NULL]","swapper/5",0
+6824713100379000,3,72000,6824713100451000,630,"S",100,630,"kworker/u17:1",1134
+6824713100451000,3,97000,6824713100548000,686,"S",120,686,"kworker/3:1",17791
+6824713100548000,3,59000,6824713100607000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713100607000,3,31000,6824713100638000,630,"S",100,630,"kworker/u17:1",1134
+6824713100618000,1,54000,6824713100672000,5,"S",120,5,"rcu_preempt",7
+6824713100638000,3,17000,6824713100655000,686,"S",120,686,"kworker/3:1",17791
+6824713100655000,3,15000,6824713100670000,2487,"R",120,739,"UsbFfs-worker",20308
+6824713100670000,3,12000,6824713100682000,630,"S",100,630,"kworker/u17:1",1134
+6824713100672000,1,561000,6824713101233000,8,"S",120,8,"rcuop/0",10
+6824713100682000,3,60000,6824713100742000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713101302000,3,605000,6824713101907000,0,"R",120,"[NULL]","swapper/5",0
+6824713101606000,2,31000,6824713101637000,5,"S",120,5,"rcu_preempt",7
+6824713101637000,2,471000,6824713102108000,0,"R",120,"[NULL]","swapper/5",0
+6824713101907000,3,54000,6824713101961000,630,"S",100,630,"kworker/u17:1",1134
+6824713101961000,3,73000,6824713102034000,686,"S",120,686,"kworker/3:1",17791
+6824713102020000,1,177000,6824713102197000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713102034000,3,8819000,6824713110853000,0,"R",120,"[NULL]","swapper/5",0
+6824713102108000,2,177000,6824713102285000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713107045000,2,1111000,6824713108156000,0,"R",120,"[NULL]","swapper/5",0
+6824713107427000,1,382000,6824713107809000,8,"S",120,8,"rcuop/0",10
+6824713107809000,1,1784000,6824713109593000,0,"R",120,"[NULL]","swapper/5",0
+6824713108156000,2,24000,6824713108180000,5,"S",120,5,"rcu_preempt",7
+6824713108180000,2,1871000,6824713110051000,0,"R",120,"[NULL]","swapper/5",0
+6824713109593000,1,155000,6824713109748000,2728,"S",120,739,"shell",20461
+6824713109748000,1,1604000,6824713111352000,0,"R",120,"[NULL]","swapper/5",0
+6824713110051000,2,506000,6824713110557000,739,"S",120,739,"adbd",20305
+6824713110557000,2,728000,6824713111285000,0,"R",120,"[NULL]","swapper/5",0
+6824713110853000,3,66000,6824713110919000,630,"S",100,630,"kworker/u17:1",1134
+6824713110919000,3,54000,6824713110973000,686,"S",120,686,"kworker/3:1",17791
+6824713110973000,3,1252000,6824713112225000,0,"R",120,"[NULL]","swapper/5",0
+6824713111285000,2,35000,6824713111320000,630,"S",100,630,"kworker/u17:1",1134
+6824713111320000,2,474000,6824713111794000,0,"R",120,"[NULL]","swapper/5",0
+6824713111352000,1,75000,6824713111427000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713111427000,1,882000,6824713112309000,0,"R",120,"[NULL]","swapper/5",0
+6824713111794000,2,71000,6824713111865000,630,"S",100,630,"kworker/u17:1",1134
+6824713111865000,2,64000,6824713111929000,694,"S",120,694,"kworker/2:0",18823
+6824713111929000,2,466000,6824713112395000,0,"R",120,"[NULL]","swapper/5",0
+6824713112225000,3,47000,6824713112272000,630,"S",100,630,"kworker/u17:1",1134
+6824713112272000,3,72000,6824713112344000,686,"S",120,686,"kworker/3:1",17791
+6824713112309000,1,168000,6824713112477000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713112344000,3,10051000,6824713122395000,0,"R",120,"[NULL]","swapper/5",0
+6824713112395000,2,142000,6824713112537000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713113333000,2,3671000,6824713117004000,0,"R",120,"[NULL]","swapper/5",0
+6824713117004000,2,42000,6824713117046000,5,"S",120,5,"rcu_preempt",7
+6824713117046000,2,851000,6824713117897000,0,"R",120,"[NULL]","swapper/5",0
+6824713117371000,1,213000,6824713117584000,8,"S",120,8,"rcuop/0",10
+6824713117584000,1,3602000,6824713121186000,0,"R",120,"[NULL]","swapper/5",0
+6824713117897000,2,22000,6824713117919000,5,"S",120,5,"rcu_preempt",7
+6824713117919000,2,3713000,6824713121632000,0,"R",120,"[NULL]","swapper/5",0
+6824713121186000,1,154000,6824713121340000,2728,"S",120,739,"shell",20461
+6824713121340000,1,1525000,6824713122865000,0,"R",120,"[NULL]","swapper/5",0
+6824713121632000,2,519000,6824713122151000,739,"S",120,739,"adbd",20305
+6824713122151000,2,341000,6824713122492000,0,"R",120,"[NULL]","swapper/5",0
+6824713122395000,3,74000,6824713122469000,630,"S",100,630,"kworker/u17:1",1134
+6824713122469000,3,51000,6824713122520000,686,"S",120,686,"kworker/3:1",17791
+6824713122492000,2,31000,6824713122523000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713122688000,2,30000,6824713122718000,694,"S",120,694,"kworker/2:0",18823
+6824713122718000,2,23000,6824713122741000,0,"R",120,"[NULL]","swapper/5",0
+6824713122741000,2,16000,6824713122757000,630,"S",100,630,"kworker/u17:1",1134
+6824713122757000,2,136000,6824713122893000,0,"R",120,"[NULL]","swapper/5",0
+6824713122865000,1,95000,6824713122960000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713122893000,2,34000,6824713122927000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713123070000,2,76000,6824713123146000,694,"S",120,694,"kworker/2:0",18823
+6824713123128000,1,152000,6824713123280000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713123146000,2,29000,6824713123175000,0,"R",120,"[NULL]","swapper/5",0
+6824713123175000,2,190000,6824713123365000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713123663000,3,3867000,6824713127530000,0,"R",120,"[NULL]","swapper/5",0
+6824713126463000,0,72000,6824713126535000,743,"S",120,743,"kworker/0:5",20371
+6824713126535000,0,3430000,6824713129965000,2722,"R+",120,757,"ps",20463
+6824713126839000,1,582000,6824713127421000,786,"S",111,494,"SDM_EventThread",685
+6824713126913000,2,467000,6824713127380000,702,"R+",120,702,"kworker/u16:7",19422
+6824713127380000,2,198000,6824713127578000,771,"S",97,493,"DispSync",676
+6824713127421000,1,507000,6824713127928000,0,"R",120,"[NULL]","swapper/5",0
+6824713127530000,3,44000,6824713127574000,77,"S",120,77,"smem_native_rpm",87
+6824713127574000,3,559000,6824713128133000,0,"R",120,"[NULL]","swapper/5",0
+6824713127578000,2,33000,6824713127611000,702,"S",120,702,"kworker/u16:7",19422
+6824713127611000,2,338000,6824713127949000,777,"S",120,493,"HwBinder:640_1",721
+6824713127928000,1,258000,6824713128186000,773,"S",97,493,"app",678
+6824713127949000,2,518000,6824713128467000,0,"R",120,"[NULL]","swapper/5",0
+6824713128133000,3,26000,6824713128159000,771,"S",97,493,"DispSync",676
+6824713128159000,3,8000,6824713128167000,0,"R",120,"[NULL]","swapper/5",0
+6824713128167000,3,13000,6824713128180000,771,"S",97,493,"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,644,"S",120,644,"ndroid.systemui",1664
+6824713129965000,0,223000,6824713130188000,482,"S",49,482,"sugov:0",605
+6824713129984000,3,64000,6824713130048000,5,"S",120,5,"rcu_preempt",7
+6824713130048000,3,1593000,6824713131641000,0,"R",120,"[NULL]","swapper/5",0
+6824713130188000,0,29833000,6824713160021000,2722,"R",120,757,"ps",20463
+6824713130421000,2,758000,6824713131179000,0,"R",120,"[NULL]","swapper/5",0
+6824713130520000,1,356000,6824713130876000,770,"S",120,493,"Binder:640_2",675
+6824713130876000,1,61000,6824713130937000,8,"R",120,8,"rcuop/0",10
+6824713130937000,1,114000,6824713131051000,482,"S",49,482,"sugov:0",605
+6824713131051000,1,355000,6824713131406000,8,"S",120,8,"rcuop/0",10
+6824713131179000,2,114000,6824713131293000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824713131671000,3,95000,6824713131766000,0,"R",120,"[NULL]","swapper/5",0
+6824713131766000,3,183000,6824713131949000,2728,"S",120,739,"shell",20461
+6824713131886000,2,26000,6824713131912000,5,"S",120,5,"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,739,"S",120,739,"adbd",20305
+6824713132978000,2,164000,6824713133142000,630,"S",100,630,"kworker/u17:1",1134
+6824713133072000,1,496000,6824713133568000,0,"R",120,"[NULL]","swapper/5",0
+6824713133142000,2,65000,6824713133207000,694,"S",120,694,"kworker/2:0",18823
+6824713133207000,2,70000,6824713133277000,0,"R",120,"[NULL]","swapper/5",0
+6824713133277000,2,50000,6824713133327000,630,"S",100,630,"kworker/u17:1",1134
+6824713133327000,2,20000,6824713133347000,694,"S",120,694,"kworker/2:0",18823
+6824713133347000,2,160000,6824713133507000,0,"R",120,"[NULL]","swapper/5",0
+6824713133492000,3,53000,6824713133545000,670,"S",100,670,"kworker/u17:2",14944
+6824713133507000,2,8000,6824713133515000,630,"S",100,630,"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,2487,"S",120,739,"UsbFfs-worker",20308
+6824713133580000,2,40000,6824713133620000,670,"S",100,670,"kworker/u17:2",14944
+6824713133620000,2,86000,6824713133706000,694,"S",120,694,"kworker/2:0",18823
+6824713133672000,1,11000,6824713133683000,0,"R",120,"[NULL]","swapper/5",0
+6824713133683000,1,142000,6824713133825000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713133706000,2,37000,6824713133743000,0,"R",120,"[NULL]","swapper/5",0
+6824713133743000,2,140000,6824713133883000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713136987000,2,3274000,6824713140261000,0,"R",120,"[NULL]","swapper/5",0
+6824713140261000,2,37000,6824713140298000,5,"S",120,5,"rcu_preempt",7
+6824713140298000,2,1112000,6824713141410000,0,"R",120,"[NULL]","swapper/5",0
+6824713140652000,1,423000,6824713141075000,8,"S",120,8,"rcuop/0",10
+6824713141075000,1,1022000,6824713142097000,0,"R",120,"[NULL]","swapper/5",0
+6824713141410000,2,18000,6824713141428000,5,"S",120,5,"rcu_preempt",7
+6824713141428000,2,1111000,6824713142539000,0,"R",120,"[NULL]","swapper/5",0
+6824713142097000,1,152000,6824713142249000,2728,"S",120,739,"shell",20461
+6824713142249000,1,2185000,6824713144434000,0,"R",120,"[NULL]","swapper/5",0
+6824713142539000,2,518000,6824713143057000,739,"S",120,739,"adbd",20305
+6824713143057000,2,1528000,6824713144585000,0,"R",120,"[NULL]","swapper/5",0
+6824713143278000,3,57000,6824713143335000,670,"S",100,670,"kworker/u17:2",14944
+6824713143335000,3,606000,6824713143941000,0,"R",120,"[NULL]","swapper/5",0
+6824713143941000,3,76000,6824713144017000,670,"S",100,670,"kworker/u17:2",14944
+6824713144017000,3,60000,6824713144077000,686,"S",120,686,"kworker/3:1",17791
+6824713144077000,3,438000,6824713144515000,0,"R",120,"[NULL]","swapper/5",0
+6824713144434000,1,56000,6824713144490000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713144490000,1,687000,6824713145177000,0,"R",120,"[NULL]","swapper/5",0
+6824713144515000,3,36000,6824713144551000,670,"S",100,670,"kworker/u17:2",14944
+6824713144551000,3,44000,6824713144595000,686,"S",120,686,"kworker/3:1",17791
+6824713144585000,2,61000,6824713144646000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713144595000,3,37000,6824713144632000,670,"S",100,670,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713144730000,2,57000,6824713144787000,694,"S",120,694,"kworker/2:0",18823
+6824713144771000,3,137000,6824713144908000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713145328000,1,1971000,6824713147299000,0,"R",120,"[NULL]","swapper/5",0
+6824713146916000,2,42000,6824713146958000,5,"S",120,5,"rcu_preempt",7
+6824713146958000,2,950000,6824713147908000,0,"R",120,"[NULL]","swapper/5",0
+6824713147299000,1,265000,6824713147564000,8,"S",120,8,"rcuop/0",10
+6824713147564000,1,6404000,6824713153968000,0,"R",120,"[NULL]","swapper/5",0
+6824713147908000,2,20000,6824713147928000,5,"S",120,5,"rcu_preempt",7
+6824713147928000,2,5718000,6824713153646000,0,"R",120,"[NULL]","swapper/5",0
+6824713153646000,2,49000,6824713153695000,5,"S",120,5,"rcu_preempt",7
+6824713153695000,2,724000,6824713154419000,0,"R",120,"[NULL]","swapper/5",0
+6824713153968000,1,154000,6824713154122000,2728,"S",120,739,"shell",20461
+6824713154122000,1,591000,6824713154713000,0,"R",120,"[NULL]","swapper/5",0
+6824713154200000,3,176000,6824713154376000,8,"S",120,8,"rcuop/0",10
+6824713154376000,3,873000,6824713155249000,0,"R",120,"[NULL]","swapper/5",0
+6824713154419000,2,564000,6824713154983000,739,"S",120,739,"adbd",20305
+6824713154713000,1,18000,6824713154731000,5,"S",120,5,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713155332000,3,55000,6824713155387000,686,"S",120,686,"kworker/3:1",17791
+6824713155387000,3,344000,6824713155731000,0,"R",120,"[NULL]","swapper/5",0
+6824713155666000,2,78000,6824713155744000,670,"S",100,670,"kworker/u17:2",14944
+6824713155731000,3,19000,6824713155750000,630,"S",100,630,"kworker/u17:1",1134
+6824713155732000,1,85000,6824713155817000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713155879000,2,58000,6824713155937000,694,"S",120,694,"kworker/2:0",18823
+6824713155909000,1,37000,6824713155946000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713155927000,3,16000,6824713155943000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713156142000,2,27000,6824713156169000,0,"R",120,"[NULL]","swapper/5",0
+6824713156169000,2,40000,6824713156209000,630,"S",100,630,"kworker/u17:1",1134
+6824713156209000,2,45000,6824713156254000,694,"S",120,694,"kworker/2:0",18823
+6824713156254000,2,364000,6824713156618000,0,"R",120,"[NULL]","swapper/5",0
+6824713156561000,1,142000,6824713156703000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713156618000,2,133000,6824713156751000,739,"S",120,739,"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,743,"S",120,743,"kworker/0:5",20371
+6824713160130000,0,33314000,6824713193444000,2722,"R+",120,757,"ps",20463
+6824713160463000,1,578000,6824713161041000,786,"S",111,494,"SDM_EventThread",685
+6824713161041000,1,887000,6824713161928000,0,"R",120,"[NULL]","swapper/5",0
+6824713161260000,2,459000,6824713161719000,777,"S",120,493,"HwBinder:640_1",721
+6824713161719000,2,304000,6824713162023000,0,"R",120,"[NULL]","swapper/5",0
+6824713161928000,1,140000,6824713162068000,771,"S",97,493,"DispSync",676
+6824713162023000,2,447000,6824713162470000,773,"S",97,493,"app",678
+6824713162068000,1,358000,6824713162426000,0,"R",120,"[NULL]","swapper/5",0
+6824713162426000,1,1725000,6824713164151000,644,"S",120,644,"ndroid.systemui",1664
+6824713162470000,2,1183000,6824713163653000,0,"R",120,"[NULL]","swapper/5",0
+6824713162766000,3,32000,6824713162798000,771,"S",97,493,"DispSync",676
+6824713162798000,3,917000,6824713163715000,0,"R",120,"[NULL]","swapper/5",0
+6824713163653000,2,751000,6824713164404000,702,"S",120,702,"kworker/u16:7",19422
+6824713163715000,3,56000,6824713163771000,5,"S",120,5,"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,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824713164960000,1,408000,6824713165368000,0,"R",120,"[NULL]","swapper/5",0
+6824713165224000,2,31000,6824713165255000,771,"S",97,493,"DispSync",676
+6824713165255000,2,581000,6824713165836000,0,"R",120,"[NULL]","swapper/5",0
+6824713165368000,1,186000,6824713165554000,2728,"S",120,739,"shell",20461
+6824713165554000,1,1573000,6824713167127000,0,"R",120,"[NULL]","swapper/5",0
+6824713165836000,2,847000,6824713166683000,739,"R+",120,739,"adbd",20305
+6824713166570000,3,92000,6824713166662000,630,"S",100,630,"kworker/u17:1",1134
+6824713166662000,3,58000,6824713166720000,686,"S",120,686,"kworker/3:1",17791
+6824713166683000,2,227000,6824713166910000,482,"S",49,482,"sugov:0",605
+6824713166720000,3,109000,6824713166829000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713166829000,3,636000,6824713167465000,0,"R",120,"[NULL]","swapper/5",0
+6824713166910000,2,644000,6824713167554000,739,"S",120,739,"adbd",20305
+6824713167127000,1,100000,6824713167227000,630,"S",100,630,"kworker/u17:1",1134
+6824713167227000,1,42000,6824713167269000,0,"R",120,"[NULL]","swapper/5",0
+6824713167269000,1,51000,6824713167320000,630,"S",100,630,"kworker/u17:1",1134
+6824713167320000,1,35000,6824713167355000,0,"R",120,"[NULL]","swapper/5",0
+6824713167355000,1,100000,6824713167455000,630,"S",100,630,"kworker/u17:1",1134
+6824713167455000,1,63000,6824713167518000,693,"S",120,693,"kworker/1:1",18800
+6824713167465000,3,195000,6824713167660000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713167518000,1,54000,6824713167572000,630,"S",100,630,"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,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713167830000,1,52000,6824713167882000,693,"R",120,693,"kworker/1:1",18800
+6824713167882000,1,132000,6824713168014000,482,"S",49,482,"sugov:0",605
+6824713168014000,1,125000,6824713168139000,693,"S",120,693,"kworker/1:1",18800
+6824713168116000,3,145000,6824713168261000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713168139000,1,2254000,6824713170393000,0,"R",120,"[NULL]","swapper/5",0
+6824713168188000,2,118000,6824713168306000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713170044000,3,912000,6824713170956000,0,"R",120,"[NULL]","swapper/5",0
+6824713170393000,1,203000,6824713170596000,8,"S",120,8,"rcuop/0",10
+6824713170596000,1,7765000,6824713178361000,0,"R",120,"[NULL]","swapper/5",0
+6824713170956000,3,31000,6824713170987000,5,"S",120,5,"rcu_preempt",7
+6824713170987000,3,6024000,6824713177011000,0,"R",120,"[NULL]","swapper/5",0
+6824713177011000,3,31000,6824713177042000,5,"S",120,5,"rcu_preempt",7
+6824713177042000,3,653000,6824713177695000,0,"R",120,"[NULL]","swapper/5",0
+6824713177043000,2,352000,6824713177395000,702,"D",120,702,"kworker/u16:7",19422
+6824713177395000,2,498000,6824713177893000,0,"R",120,"[NULL]","swapper/5",0
+6824713177695000,3,144000,6824713177839000,77,"S",120,77,"smem_native_rpm",87
+6824713177839000,3,5798000,6824713183637000,0,"R",120,"[NULL]","swapper/5",0
+6824713177893000,2,35000,6824713177928000,702,"S",120,702,"kworker/u16:7",19422
+6824713177928000,2,920000,6824713178848000,0,"R",120,"[NULL]","swapper/5",0
+6824713178361000,1,204000,6824713178565000,2728,"S",120,739,"shell",20461
+6824713178565000,1,1277000,6824713179842000,0,"R",120,"[NULL]","swapper/5",0
+6824713178848000,2,801000,6824713179649000,739,"S",120,739,"adbd",20305
+6824713179649000,2,622000,6824713180271000,0,"R",120,"[NULL]","swapper/5",0
+6824713179842000,1,126000,6824713179968000,630,"S",100,630,"kworker/u17:1",1134
+6824713179968000,1,67000,6824713180035000,693,"S",120,693,"kworker/1:1",18800
+6824713180035000,1,535000,6824713180570000,0,"R",120,"[NULL]","swapper/5",0
+6824713180271000,2,74000,6824713180345000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713180345000,2,438000,6824713180783000,0,"R",120,"[NULL]","swapper/5",0
+6824713180570000,1,46000,6824713180616000,630,"S",100,630,"kworker/u17:1",1134
+6824713180616000,1,116000,6824713180732000,0,"R",120,"[NULL]","swapper/5",0
+6824713180732000,1,31000,6824713180763000,630,"S",100,630,"kworker/u17:1",1134
+6824713180763000,1,28000,6824713180791000,693,"S",120,693,"kworker/1:1",18800
+6824713180783000,2,71000,6824713180854000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713180791000,1,34000,6824713180825000,0,"R",120,"[NULL]","swapper/5",0
+6824713180825000,1,17000,6824713180842000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713181056000,1,406000,6824713181462000,0,"R",120,"[NULL]","swapper/5",0
+6824713181462000,1,39000,6824713181501000,630,"S",100,630,"kworker/u17:1",1134
+6824713181501000,1,44000,6824713181545000,693,"S",120,693,"kworker/1:1",18800
+6824713181545000,1,414000,6824713181959000,0,"R",120,"[NULL]","swapper/5",0
+6824713181884000,2,150000,6824713182034000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713181959000,1,179000,6824713182138000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713183695000,3,1423000,6824713185118000,0,"R",120,"[NULL]","swapper/5",0
+6824713184058000,1,700000,6824713184758000,8,"S",120,8,"rcuop/0",10
+6824713184758000,1,3775000,6824713188533000,0,"R",120,"[NULL]","swapper/5",0
+6824713185118000,3,22000,6824713185140000,5,"S",120,5,"rcu_preempt",7
+6824713185140000,3,5295000,6824713190435000,0,"R",120,"[NULL]","swapper/5",0
+6824713188533000,1,169000,6824713188702000,2728,"S",120,739,"shell",20461
+6824713188702000,1,1106000,6824713189808000,0,"R",120,"[NULL]","swapper/5",0
+6824713189029000,2,560000,6824713189589000,739,"S",120,739,"adbd",20305
+6824713189589000,2,668000,6824713190257000,0,"R",120,"[NULL]","swapper/5",0
+6824713189808000,1,118000,6824713189926000,630,"S",100,630,"kworker/u17:1",1134
+6824713189926000,1,53000,6824713189979000,693,"S",120,693,"kworker/1:1",18800
+6824713189979000,1,588000,6824713190567000,0,"R",120,"[NULL]","swapper/5",0
+6824713190257000,2,67000,6824713190324000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713190324000,2,156000,6824713190480000,0,"R",120,"[NULL]","swapper/5",0
+6824713190435000,3,53000,6824713190488000,5,"S",120,5,"rcu_preempt",7
+6824713190480000,2,615000,6824713191095000,8,"S",120,8,"rcuop/0",10
+6824713190488000,3,904000,6824713191392000,0,"R",120,"[NULL]","swapper/5",0
+6824713190567000,1,41000,6824713190608000,630,"S",100,630,"kworker/u17:1",1134
+6824713190608000,1,445000,6824713191053000,0,"R",120,"[NULL]","swapper/5",0
+6824713191053000,1,39000,6824713191092000,630,"S",100,630,"kworker/u17:1",1134
+6824713191092000,1,23000,6824713191115000,693,"R+",120,693,"kworker/1:1",18800
+6824713191095000,2,22000,6824713191117000,0,"R",120,"[NULL]","swapper/5",0
+6824713191115000,1,33000,6824713191148000,630,"S",100,630,"kworker/u17:1",1134
+6824713191117000,2,95000,6824713191212000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713191148000,1,15000,6824713191163000,693,"S",120,693,"kworker/1:1",18800
+6824713191163000,1,41000,6824713191204000,0,"R",120,"[NULL]","swapper/5",0
+6824713191204000,1,40000,6824713191244000,630,"S",100,630,"kworker/u17:1",1134
+6824713191212000,2,58000,6824713191270000,0,"R",120,"[NULL]","swapper/5",0
+6824713191244000,1,41000,6824713191285000,693,"S",120,693,"kworker/1:1",18800
+6824713191270000,2,141000,6824713191411000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713191285000,1,50000,6824713191335000,0,"R",120,"[NULL]","swapper/5",0
+6824713191335000,1,184000,6824713191519000,739,"S",120,739,"adbd",20305
+6824713191392000,3,26000,6824713191418000,5,"S",120,5,"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,743,"S",120,743,"kworker/0:5",20371
+6824713193520000,0,3109000,6824713196629000,2722,"R+",120,757,"ps",20463
+6824713193831000,1,657000,6824713194488000,786,"S",111,494,"SDM_EventThread",685
+6824713194488000,1,600000,6824713195088000,0,"R",120,"[NULL]","swapper/5",0
+6824713194795000,2,411000,6824713195206000,777,"S",120,493,"HwBinder:640_1",721
+6824713195088000,1,141000,6824713195229000,771,"S",97,493,"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,773,"S",97,493,"app",678
+6824713195814000,3,811000,6824713196625000,0,"R",120,"[NULL]","swapper/5",0
+6824713196118000,1,2042000,6824713198160000,644,"S",120,644,"ndroid.systemui",1664
+6824713196196000,2,19000,6824713196215000,771,"S",97,493,"DispSync",676
+6824713196215000,2,3119000,6824713199334000,0,"R",120,"[NULL]","swapper/5",0
+6824713196625000,3,44000,6824713196669000,5,"S",120,5,"rcu_preempt",7
+6824713196629000,0,168000,6824713196797000,482,"S",49,482,"sugov:0",605
+6824713196669000,3,1654000,6824713198323000,0,"R",120,"[NULL]","swapper/5",0
+6824713196797000,0,30115000,6824713226912000,2722,"R+",120,757,"ps",20463
+6824713198160000,1,730000,6824713198890000,0,"R",120,"[NULL]","swapper/5",0
+6824713198323000,3,309000,6824713198632000,770,"S",120,493,"Binder:640_2",675
+6824713198632000,3,5040000,6824713203672000,0,"R",120,"[NULL]","swapper/5",0
+6824713198890000,1,161000,6824713199051000,773,"S",97,493,"app",678
+6824713199051000,1,29000,6824713199080000,0,"R",120,"[NULL]","swapper/5",0
+6824713199080000,1,118000,6824713199198000,482,"S",49,482,"sugov:0",605
+6824713199198000,1,5504000,6824713204702000,0,"R",120,"[NULL]","swapper/5",0
+6824713199334000,2,29000,6824713199363000,771,"S",97,493,"DispSync",676
+6824713199363000,2,4705000,6824713204068000,0,"R",120,"[NULL]","swapper/5",0
+6824713203672000,3,74000,6824713203746000,5,"S",120,5,"rcu_preempt",7
+6824713203746000,3,1079000,6824713204825000,0,"R",120,"[NULL]","swapper/5",0
+6824713204068000,2,436000,6824713204504000,8,"S",120,8,"rcuop/0",10
+6824713204504000,2,743000,6824713205247000,0,"R",120,"[NULL]","swapper/5",0
+6824713204702000,1,215000,6824713204917000,2728,"S",120,739,"shell",20461
+6824713204825000,3,28000,6824713204853000,5,"S",120,5,"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,739,"S",120,739,"adbd",20305
+6824713205984000,1,70000,6824713206054000,630,"S",100,630,"kworker/u17:1",1134
+6824713206054000,1,9000,6824713206063000,0,"R",120,"[NULL]","swapper/5",0
+6824713206063000,1,59000,6824713206122000,630,"S",100,630,"kworker/u17:1",1134
+6824713206122000,1,57000,6824713206179000,693,"S",120,693,"kworker/1:1",18800
+6824713206179000,1,100000,6824713206279000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713206550000,3,436000,6824713206986000,0,"R",120,"[NULL]","swapper/5",0
+6824713206986000,3,67000,6824713207053000,630,"S",100,630,"kworker/u17:1",1134
+6824713207053000,3,47000,6824713207100000,686,"S",120,686,"kworker/3:1",17791
+6824713207100000,3,2871000,6824713209971000,0,"R",120,"[NULL]","swapper/5",0
+6824713207117000,2,57000,6824713207174000,630,"S",100,630,"kworker/u17:1",1134
+6824713207174000,2,56000,6824713207230000,694,"S",120,694,"kworker/2:0",18823
+6824713207230000,2,623000,6824713207853000,0,"R",120,"[NULL]","swapper/5",0
+6824713207410000,1,204000,6824713207614000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713207614000,1,16701000,6824713224315000,0,"R",120,"[NULL]","swapper/5",0
+6824713207853000,2,179000,6824713208032000,739,"S",120,739,"adbd",20305
+6824713208032000,2,2366000,6824713210398000,0,"R",120,"[NULL]","swapper/5",0
+6824713209971000,3,55000,6824713210026000,5,"S",120,5,"rcu_preempt",7
+6824713210026000,3,1318000,6824713211344000,0,"R",120,"[NULL]","swapper/5",0
+6824713210398000,2,635000,6824713211033000,8,"S",120,8,"rcuop/0",10
+6824713211033000,2,6391000,6824713217424000,0,"R",120,"[NULL]","swapper/5",0
+6824713211344000,3,26000,6824713211370000,5,"S",120,5,"rcu_preempt",7
+6824713211370000,3,5656000,6824713217026000,0,"R",120,"[NULL]","swapper/5",0
+6824713217026000,3,51000,6824713217077000,5,"S",120,5,"rcu_preempt",7
+6824713217077000,3,770000,6824713217847000,0,"R",120,"[NULL]","swapper/5",0
+6824713217424000,2,75000,6824713217499000,8,"S",120,8,"rcuop/0",10
+6824713217499000,2,6882000,6824713224381000,0,"R",120,"[NULL]","swapper/5",0
+6824713217847000,3,19000,6824713217866000,5,"S",120,5,"rcu_preempt",7
+6824713217866000,3,6087000,6824713223953000,0,"R",120,"[NULL]","swapper/5",0
+6824713223953000,3,87000,6824713224040000,5,"S",120,5,"rcu_preempt",7
+6824713224040000,3,879000,6824713224919000,0,"R",120,"[NULL]","swapper/5",0
+6824713224315000,1,256000,6824713224571000,2728,"S",120,739,"shell",20461
+6824713224381000,2,258000,6824713224639000,8,"S",120,8,"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,739,"S",120,739,"adbd",20305
+6824713225160000,1,33000,6824713225193000,5,"S",120,5,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713226236000,2,76000,6824713226312000,694,"S",120,694,"kworker/2:0",18823
+6824713226312000,2,35000,6824713226347000,0,"R",120,"[NULL]","swapper/5",0
+6824713226347000,2,23000,6824713226370000,630,"S",100,630,"kworker/u17:1",1134
+6824713226370000,2,20000,6824713226390000,694,"S",120,694,"kworker/2:0",18823
+6824713226390000,2,562000,6824713226952000,0,"R",120,"[NULL]","swapper/5",0
+6824713226606000,3,144000,6824713226750000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713226750000,3,199000,6824713226949000,0,"R",120,"[NULL]","swapper/5",0
+6824713226912000,0,65000,6824713226977000,743,"S",120,743,"kworker/0:5",20371
+6824713226949000,3,43000,6824713226992000,630,"S",100,630,"kworker/u17:1",1134
+6824713226952000,2,113000,6824713227065000,702,"S",120,702,"kworker/u16:7",19422
+6824713226977000,0,23808000,6824713250785000,2722,"R",120,757,"ps",20463
+6824713226992000,3,43000,6824713227035000,0,"R",120,"[NULL]","swapper/5",0
+6824713227035000,3,61000,6824713227096000,630,"S",100,630,"kworker/u17:1",1134
+6824713227065000,2,78000,6824713227143000,0,"R",120,"[NULL]","swapper/5",0
+6824713227096000,3,66000,6824713227162000,686,"S",120,686,"kworker/3:1",17791
+6824713227143000,2,162000,6824713227305000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713227162000,3,446000,6824713227608000,0,"R",120,"[NULL]","swapper/5",0
+6824713227289000,1,566000,6824713227855000,786,"S",111,494,"SDM_EventThread",685
+6824713227305000,2,440000,6824713227745000,0,"R",120,"[NULL]","swapper/5",0
+6824713227608000,3,224000,6824713227832000,739,"S",120,739,"adbd",20305
+6824713227745000,2,443000,6824713228188000,777,"S",120,493,"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,771,"S",97,493,"DispSync",676
+6824713228538000,1,565000,6824713229103000,0,"R",120,"[NULL]","swapper/5",0
+6824713228869000,2,274000,6824713229143000,773,"S",97,493,"app",678
+6824713229103000,1,1753000,6824713230856000,644,"S",120,644,"ndroid.systemui",1664
+6824713229143000,2,1167000,6824713230310000,0,"R",120,"[NULL]","swapper/5",0
+6824713229467000,3,23000,6824713229490000,771,"S",97,493,"DispSync",676
+6824713229490000,3,1513000,6824713231003000,0,"R",120,"[NULL]","swapper/5",0
+6824713230310000,2,45000,6824713230355000,5,"S",120,5,"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,770,"S",120,493,"Binder:640_2",675
+6824713231261000,3,5466000,6824713236727000,0,"R",120,"[NULL]","swapper/5",0
+6824713231498000,1,138000,6824713231636000,773,"S",97,493,"app",678
+6824713231636000,1,6415000,6824713238051000,0,"R",120,"[NULL]","swapper/5",0
+6824713231897000,2,28000,6824713231925000,771,"S",97,493,"DispSync",676
+6824713231925000,2,4745000,6824713236670000,0,"R",120,"[NULL]","swapper/5",0
+6824713236670000,2,70000,6824713236740000,5,"S",120,5,"rcu_preempt",7
+6824713236727000,3,267000,6824713236994000,8,"S",120,8,"rcuop/0",10
+6824713236740000,2,246000,6824713236986000,0,"R",120,"[NULL]","swapper/5",0
+6824713236986000,2,17000,6824713237003000,5,"S",120,5,"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,2728,"S",120,739,"shell",20461
+6824713238261000,1,7678000,6824713245939000,0,"R",120,"[NULL]","swapper/5",0
+6824713238544000,3,824000,6824713239368000,739,"S",120,739,"adbd",20305
+6824713239368000,3,631000,6824713239999000,0,"R",120,"[NULL]","swapper/5",0
+6824713239999000,3,127000,6824713240126000,630,"S",100,630,"kworker/u17:1",1134
+6824713240126000,3,61000,6824713240187000,686,"S",120,686,"kworker/3:1",17791
+6824713240187000,3,594000,6824713240781000,0,"R",120,"[NULL]","swapper/5",0
+6824713240476000,2,102000,6824713240578000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713240578000,2,560000,6824713241138000,0,"R",120,"[NULL]","swapper/5",0
+6824713240781000,3,38000,6824713240819000,630,"S",100,630,"kworker/u17:1",1134
+6824713240819000,3,32000,6824713240851000,686,"S",120,686,"kworker/3:1",17791
+6824713240851000,3,284000,6824713241135000,0,"R",120,"[NULL]","swapper/5",0
+6824713241135000,3,35000,6824713241170000,630,"S",100,630,"kworker/u17:1",1134
+6824713241138000,2,73000,6824713241211000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713241170000,3,27000,6824713241197000,0,"R",120,"[NULL]","swapper/5",0
+6824713241197000,3,40000,6824713241237000,630,"S",100,630,"kworker/u17:1",1134
+6824713241211000,2,447000,6824713241658000,0,"R",120,"[NULL]","swapper/5",0
+6824713241237000,3,43000,6824713241280000,686,"S",120,686,"kworker/3:1",17791
+6824713241280000,3,763000,6824713242043000,0,"R",120,"[NULL]","swapper/5",0
+6824713241658000,2,183000,6824713241841000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713241841000,2,1454000,6824713243295000,0,"R",120,"[NULL]","swapper/5",0
+6824713242043000,3,215000,6824713242258000,739,"S",120,739,"adbd",20305
+6824713242258000,3,5163000,6824713247421000,0,"R",120,"[NULL]","swapper/5",0
+6824713243295000,2,43000,6824713243338000,5,"S",120,5,"rcu_preempt",7
+6824713243338000,2,3652000,6824713246990000,0,"R",120,"[NULL]","swapper/5",0
+6824713245939000,1,86000,6824713246025000,1807,"S",120,663,"ogle.android.as",15166
+6824713246025000,1,64000,6824713246089000,1808,"S",120,663,"ogle.android.as",15167
+6824713246089000,1,9699000,6824713255788000,0,"R",120,"[NULL]","swapper/5",0
+6824713246990000,2,51000,6824713247041000,5,"S",120,5,"rcu_preempt",7
+6824713247041000,2,1235000,6824713248276000,0,"R",120,"[NULL]","swapper/5",0
+6824713247421000,3,487000,6824713247908000,8,"S",120,8,"rcuop/0",10
+6824713247908000,3,4863000,6824713252771000,0,"R",120,"[NULL]","swapper/5",0
+6824713248276000,2,25000,6824713248301000,5,"S",120,5,"rcu_preempt",7
+6824713248301000,2,4882000,6824713253183000,0,"R",120,"[NULL]","swapper/5",0
+6824713250362000,6,413000,6824713250775000,2728,"S",120,739,"shell",20461
+6824713250775000,6,72000,6824713250847000,0,"R",120,"[NULL]","swapper/5",0
+6824713250785000,0,74000,6824713250859000,11,"S",0,11,"migration/0",13
+6824713250847000,6,2556000,6824713253403000,2722,"R",120,757,"ps",20463
+6824713250859000,0,61000,6824713250920000,0,"R",120,"[NULL]","swapper/5",0
+6824713250920000,0,247000,6824713251167000,482,"S",49,482,"sugov:0",605
+6824713251148000,7,902000,6824713252050000,739,"S",120,739,"adbd",20305
+6824713251167000,0,342000,6824713251509000,0,"R",120,"[NULL]","swapper/5",0
+6824713251509000,0,58000,6824713251567000,52,"S",120,52,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713252968000,3,186000,6824713253154000,686,"S",120,686,"kworker/3:1",17791
+6824713253154000,3,188000,6824713253342000,630,"S",100,630,"kworker/u17:1",1134
+6824713253183000,2,568000,6824713253751000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713253342000,3,68000,6824713253410000,686,"S",120,686,"kworker/3:1",17791
+6824713253403000,6,156000,6824713253559000,483,"S",49,483,"sugov:4",606
+6824713253410000,3,69000,6824713253479000,630,"S",100,630,"kworker/u17:1",1134
+6824713253479000,3,642000,6824713254121000,0,"R",120,"[NULL]","swapper/5",0
+6824713253559000,6,223000,6824713253782000,2722,"R+",120,757,"ps",20463
+6824713253751000,2,72000,6824713253823000,5,"S",120,5,"rcu_preempt",7
+6824713253782000,6,16000,6824713253798000,2728,"S",120,739,"shell",20461
+6824713253798000,6,1208000,6824713255006000,2722,"I",120,757,"ps",20463
+6824713253823000,2,1690000,6824713255513000,0,"R",120,"[NULL]","swapper/5",0
+6824713254121000,3,94000,6824713254215000,630,"S",100,630,"kworker/u17:1",1134
+6824713254215000,3,534000,6824713254749000,0,"R",120,"[NULL]","swapper/5",0
+6824713254749000,3,113000,6824713254862000,630,"S",100,630,"kworker/u17:1",1134
+6824713254862000,3,213000,6824713255075000,686,"S",120,686,"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,53,"S",120,53,"rcuos/6",61
+6824713255199000,7,23000,6824713255222000,6,"S",120,6,"rcu_sched",8
+6824713255222000,7,6211000,6824713261433000,0,"R",120,"[NULL]","swapper/5",0
+6824713255513000,2,403000,6824713255916000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713255788000,1,140000,6824713255928000,482,"S",49,482,"sugov:0",605
+6824713255916000,2,1029000,6824713256945000,739,"R",120,739,"adbd",20305
+6824713255928000,1,733000,6824713256661000,2721,"R+",120,756,"sh",20462
+6824713256661000,1,87000,6824713256748000,482,"S",49,482,"sugov:0",605
+6824713256748000,1,2388000,6824713259136000,2721,"S",120,756,"sh",20462
+6824713256945000,2,173000,6824713257118000,630,"S",100,630,"kworker/u17:1",1134
+6824713257118000,2,59000,6824713257177000,694,"R+",120,694,"kworker/2:0",18823
+6824713257177000,2,41000,6824713257218000,630,"S",100,630,"kworker/u17:1",1134
+6824713257218000,2,23000,6824713257241000,670,"S",100,670,"kworker/u17:2",14944
+6824713257241000,2,60000,6824713257301000,694,"R+",120,694,"kworker/2:0",18823
+6824713257301000,2,26000,6824713257327000,670,"S",100,670,"kworker/u17:2",14944
+6824713257327000,2,72000,6824713257399000,694,"S",120,694,"kworker/2:0",18823
+6824713257399000,2,76000,6824713257475000,2487,"R",120,739,"UsbFfs-worker",20308
+6824713257475000,2,44000,6824713257519000,670,"S",100,670,"kworker/u17:2",14944
+6824713257519000,2,62000,6824713257581000,2487,"R",120,739,"UsbFfs-worker",20308
+6824713257581000,2,65000,6824713257646000,670,"S",100,670,"kworker/u17:2",14944
+6824713257646000,2,44000,6824713257690000,694,"S",120,694,"kworker/2:0",18823
+6824713257690000,2,127000,6824713257817000,739,"S",120,739,"adbd",20305
+6824713257817000,2,122000,6824713257939000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713257939000,2,73000,6824713258012000,482,"S",49,482,"sugov:0",605
+6824713258012000,2,131000,6824713258143000,739,"S",120,739,"adbd",20305
+6824713258143000,2,148000,6824713258291000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713258291000,2,1744000,6824713260035000,0,"R",120,"[NULL]","swapper/5",0
+6824713258690000,0,164000,6824713258854000,739,"S",120,739,"adbd",20305
+6824713258854000,0,1935000,6824713260789000,0,"R",120,"[NULL]","swapper/5",0
+6824713259136000,1,895000,6824713260031000,2729,"R+",120,758,"ps",20464
+6824713260031000,1,69000,6824713260100000,693,"S",120,693,"kworker/1:1",18800
+6824713260035000,2,103000,6824713260138000,5,"S",120,5,"rcu_preempt",7
+6824713260100000,1,747000,6824713260847000,2729,"R+",120,758,"ps",20464
+6824713260138000,2,1298000,6824713261436000,0,"R",120,"[NULL]","swapper/5",0
+6824713260571000,3,513000,6824713261084000,8,"S",120,8,"rcuop/0",10
+6824713260789000,0,106000,6824713260895000,743,"S",120,743,"kworker/0:5",20371
+6824713260847000,1,692000,6824713261539000,786,"S",111,494,"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,6,"S",120,6,"rcu_sched",8
+6824713261436000,2,254000,6824713261690000,771,"S",97,493,"DispSync",676
+6824713261485000,7,50000,6824713261535000,53,"S",120,53,"rcuos/6",61
+6824713261535000,7,2709000,6824713264244000,0,"R",120,"[NULL]","swapper/5",0
+6824713261539000,1,1177000,6824713262716000,2729,"R+",120,758,"ps",20464
+6824713261690000,2,748000,6824713262438000,0,"R",120,"[NULL]","swapper/5",0
+6824713261826000,0,412000,6824713262238000,777,"S",120,493,"HwBinder:640_1",721
+6824713262078000,3,319000,6824713262397000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824713262484000,2,2645000,6824713265129000,0,"R",120,"[NULL]","swapper/5",0
+6824713262716000,1,92000,6824713262808000,9,"S",120,9,"rcuos/0",11
+6824713262767000,0,2217000,6824713264984000,644,"S",120,644,"ndroid.systemui",1664
+6824713262808000,1,549000,6824713263357000,2729,"R+",120,758,"ps",20464
+6824713263357000,1,1008000,6824713264365000,702,"S",120,702,"kworker/u16:7",19422
+6824713264244000,7,55000,6824713264299000,6,"S",120,6,"rcu_sched",8
+6824713264299000,7,7113000,6824713271412000,0,"R",120,"[NULL]","swapper/5",0
+6824713264365000,1,230000,6824713264595000,2729,"R+",120,758,"ps",20464
+6824713264595000,1,23000,6824713264618000,145,"S",120,145,"hwrng",215
+6824713264618000,1,6871000,6824713271489000,2729,"R+",120,758,"ps",20464
+6824713264984000,0,719000,6824713265703000,0,"R",120,"[NULL]","swapper/5",0
+6824713265129000,2,305000,6824713265434000,770,"S",120,493,"Binder:640_2",675
+6824713265434000,2,29000,6824713265463000,145,"S",120,145,"hwrng",215
+6824713265463000,2,364000,6824713265827000,0,"R",120,"[NULL]","swapper/5",0
+6824713265703000,0,185000,6824713265888000,773,"S",97,493,"app",678
+6824713265827000,2,52000,6824713265879000,771,"S",97,493,"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,5,"R+",120,5,"rcu_preempt",7
+6824713266783000,2,33000,6824713266816000,52,"S",120,52,"rcuop/6",60
+6824713266816000,2,36000,6824713266852000,5,"S",120,5,"rcu_preempt",7
+6824713266852000,2,6898000,6824713273750000,0,"R",120,"[NULL]","swapper/5",0
+6824713271412000,7,52000,6824713271464000,6,"S",120,6,"rcu_sched",8
+6824713271464000,7,1149000,6824713272613000,0,"R",120,"[NULL]","swapper/5",0
+6824713271489000,1,125000,6824713271614000,9,"S",120,9,"rcuos/0",11
+6824713271614000,1,43000,6824713271657000,18,"S",120,18,"rcuos/1",21
+6824713271657000,1,2660000,6824713274317000,2729,"R+",120,758,"ps",20464
+6824713272613000,7,50000,6824713272663000,6,"S",120,6,"rcu_sched",8
+6824713272663000,7,4324000,6824713276987000,0,"R",120,"[NULL]","swapper/5",0
+6824713273750000,2,109000,6824713273859000,5,"R+",120,5,"rcu_preempt",7
+6824713273859000,2,152000,6824713274011000,52,"S",120,52,"rcuop/6",60
+6824713274011000,2,24000,6824713274035000,24,"S",120,24,"rcuop/2",28
+6824713274035000,2,26000,6824713274061000,5,"S",120,5,"rcu_preempt",7
+6824713274061000,2,6571000,6824713280632000,0,"R",120,"[NULL]","swapper/5",0
+6824713274253000,3,160000,6824713274413000,8,"S",120,8,"rcuop/0",10
+6824713274317000,1,223000,6824713274540000,17,"S",120,17,"rcuop/1",20
+6824713274413000,3,13234000,6824713287647000,0,"R",120,"[NULL]","swapper/5",0
+6824713274540000,1,2103000,6824713276643000,2729,"R+",120,758,"ps",20464
+6824713276643000,1,103000,6824713276746000,702,"S",120,702,"kworker/u16:7",19422
+6824713276746000,1,294000,6824713277040000,2729,"R+",120,758,"ps",20464
+6824713276987000,7,34000,6824713277021000,6,"S",120,6,"rcu_sched",8
+6824713277021000,7,53046000,6824713330067000,0,"R",120,"[NULL]","swapper/5",0
+6824713277040000,1,41000,6824713277081000,9,"S",120,9,"rcuos/0",11
+6824713277081000,1,23000,6824713277104000,18,"S",120,18,"rcuos/1",21
+6824713277104000,1,2914000,6824713280018000,2729,"R+",120,758,"ps",20464
+6824713280018000,1,235000,6824713280253000,482,"S",49,482,"sugov:0",605
+6824713280253000,1,7441000,6824713287694000,2729,"R",120,758,"ps",20464
+6824713280632000,2,120000,6824713280752000,482,"S",49,482,"sugov:0",605
+6824713280752000,2,55000,6824713280807000,5,"R+",120,5,"rcu_preempt",7
+6824713280807000,2,27000,6824713280834000,24,"S",120,24,"rcuop/2",28
+6824713280834000,2,20000,6824713280854000,5,"S",120,5,"rcu_preempt",7
+6824713280854000,2,6307000,6824713287161000,0,"R",120,"[NULL]","swapper/5",0
+6824713287161000,2,80000,6824713287241000,5,"S",120,5,"rcu_preempt",7
+6824713287241000,2,805000,6824713288046000,0,"R",120,"[NULL]","swapper/5",0
+6824713287647000,3,85000,6824713287732000,8,"S",120,8,"rcuop/0",10
+6824713287694000,1,49000,6824713287743000,17,"S",120,17,"rcuop/1",20
+6824713287732000,3,6253000,6824713293985000,0,"R",120,"[NULL]","swapper/5",0
+6824713287743000,1,6273000,6824713294016000,2729,"R+",120,758,"ps",20464
+6824713288046000,2,19000,6824713288065000,5,"S",120,5,"rcu_preempt",7
+6824713288065000,2,5544000,6824713293609000,0,"R",120,"[NULL]","swapper/5",0
+6824713289124000,0,238000,6824713289362000,1694,"D",100,660,"thermal-engine",2490
+6824713289362000,0,803000,6824713290165000,0,"R",120,"[NULL]","swapper/5",0
+6824713290165000,0,67000,6824713290232000,743,"S",120,743,"kworker/0:5",20371
+6824713290232000,0,256000,6824713290488000,1694,"S",100,660,"thermal-engine",2490
+6824713290488000,0,3702000,6824713294190000,0,"R",120,"[NULL]","swapper/5",0
+6824713293609000,2,45000,6824713293654000,5,"S",120,5,"rcu_preempt",7
+6824713293654000,2,1390000,6824713295044000,0,"R",120,"[NULL]","swapper/5",0
+6824713293985000,3,43000,6824713294028000,8,"S",120,8,"rcuop/0",10
+6824713294016000,1,29000,6824713294045000,17,"S",120,17,"rcuop/1",20
+6824713294028000,3,1525000,6824713295553000,0,"R",120,"[NULL]","swapper/5",0
+6824713294045000,1,182000,6824713294227000,2729,"R",120,758,"ps",20464
+6824713294190000,0,70000,6824713294260000,743,"S",120,743,"kworker/0:5",20371
+6824713294227000,1,650000,6824713294877000,786,"S",111,494,"SDM_EventThread",685
+6824713294260000,0,501000,6824713294761000,0,"R",120,"[NULL]","swapper/5",0
+6824713294761000,0,350000,6824713295111000,777,"S",120,493,"HwBinder:640_1",721
+6824713294877000,1,8453000,6824713303330000,2729,"R+",120,758,"ps",20464
+6824713295044000,2,186000,6824713295230000,771,"S",97,493,"DispSync",676
+6824713295111000,0,16000,6824713295127000,0,"R",120,"[NULL]","swapper/5",0
+6824713295127000,0,113000,6824713295240000,777,"S",120,493,"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,773,"S",97,493,"app",678
+6824713295879000,3,4297000,6824713300176000,0,"R",120,"[NULL]","swapper/5",0
+6824713296162000,0,1958000,6824713298120000,644,"S",120,644,"ndroid.systemui",1664
+6824713296243000,2,31000,6824713296274000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824713298517000,2,708000,6824713299225000,0,"R",120,"[NULL]","swapper/5",0
+6824713298792000,0,153000,6824713298945000,773,"S",97,493,"app",678
+6824713298945000,0,25615000,6824713324560000,0,"R",120,"[NULL]","swapper/5",0
+6824713299225000,2,37000,6824713299262000,771,"S",97,493,"DispSync",676
+6824713299262000,2,1065000,6824713300327000,0,"R",120,"[NULL]","swapper/5",0
+6824713300176000,3,48000,6824713300224000,8,"S",120,8,"rcuop/0",10
+6824713300224000,3,7418000,6824713307642000,0,"R",120,"[NULL]","swapper/5",0
+6824713300327000,2,21000,6824713300348000,145,"S",120,145,"hwrng",215
+6824713300348000,2,36000,6824713300384000,5,"S",120,5,"rcu_preempt",7
+6824713300384000,2,6852000,6824713307236000,0,"R",120,"[NULL]","swapper/5",0
+6824713303330000,1,176000,6824713303506000,482,"S",49,482,"sugov:0",605
+6824713303506000,1,3115000,6824713306621000,2729,"R+",120,758,"ps",20464
+6824713306621000,1,71000,6824713306692000,482,"S",49,482,"sugov:0",605
+6824713306692000,1,994000,6824713307686000,2729,"R+",120,758,"ps",20464
+6824713307236000,2,69000,6824713307305000,5,"S",120,5,"rcu_preempt",7
+6824713307305000,2,404000,6824713307709000,0,"R",120,"[NULL]","swapper/5",0
+6824713307642000,3,72000,6824713307714000,8,"S",120,8,"rcuop/0",10
+6824713307686000,1,32000,6824713307718000,17,"S",120,17,"rcuop/1",20
+6824713307709000,2,17000,6824713307726000,5,"S",120,5,"rcu_preempt",7
+6824713307714000,3,9638000,6824713317352000,0,"R",120,"[NULL]","swapper/5",0
+6824713307718000,1,9664000,6824713317382000,2729,"R+",120,758,"ps",20464
+6824713307726000,2,5944000,6824713313670000,0,"R",120,"[NULL]","swapper/5",0
+6824713313670000,2,31000,6824713313701000,5,"S",120,5,"rcu_preempt",7
+6824713313701000,2,3234000,6824713316935000,0,"R",120,"[NULL]","swapper/5",0
+6824713316935000,2,46000,6824713316981000,5,"S",120,5,"rcu_preempt",7
+6824713316981000,2,773000,6824713317754000,0,"R",120,"[NULL]","swapper/5",0
+6824713317352000,3,56000,6824713317408000,8,"S",120,8,"rcuop/0",10
+6824713317382000,1,116000,6824713317498000,17,"S",120,17,"rcuop/1",20
+6824713317408000,3,6640000,6824713324048000,0,"R",120,"[NULL]","swapper/5",0
+6824713317498000,1,5825000,6824713323323000,2729,"R+",120,758,"ps",20464
+6824713317754000,2,15000,6824713317769000,5,"S",120,5,"rcu_preempt",7
+6824713317769000,2,5877000,6824713323646000,0,"R",120,"[NULL]","swapper/5",0
+6824713323323000,1,140000,6824713323463000,482,"S",49,482,"sugov:0",605
+6824713323463000,1,4344000,6824713327807000,2729,"R+",120,758,"ps",20464
+6824713323646000,2,54000,6824713323700000,5,"S",120,5,"rcu_preempt",7
+6824713323700000,2,893000,6824713324593000,0,"R",120,"[NULL]","swapper/5",0
+6824713324048000,3,59000,6824713324107000,8,"S",120,8,"rcuop/0",10
+6824713324107000,3,3572000,6824713327679000,0,"R",120,"[NULL]","swapper/5",0
+6824713324560000,0,209000,6824713324769000,17,"S",120,17,"rcuop/1",20
+6824713324593000,2,17000,6824713324610000,5,"S",120,5,"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,702,"D",120,702,"kworker/u16:7",19422
+6824713327297000,2,154000,6824713327451000,0,"R",120,"[NULL]","swapper/5",0
+6824713327451000,2,31000,6824713327482000,702,"S",120,702,"kworker/u16:7",19422
+6824713327482000,2,276000,6824713327758000,0,"R",120,"[NULL]","swapper/5",0
+6824713327679000,3,43000,6824713327722000,77,"S",120,77,"smem_native_rpm",87
+6824713327713000,0,92000,6824713327805000,743,"S",120,743,"kworker/0:5",20371
+6824713327722000,3,1218000,6824713328940000,0,"R",120,"[NULL]","swapper/5",0
+6824713327758000,2,602000,6824713328360000,786,"S",111,494,"SDM_EventThread",685
+6824713327805000,0,570000,6824713328375000,0,"R",120,"[NULL]","swapper/5",0
+6824713327807000,1,48000,6824713327855000,14,"S",0,14,"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,2729,"R",120,758,"ps",20464
+6824713328940000,3,397000,6824713329337000,777,"S",120,493,"HwBinder:640_1",721
+6824713329043000,6,147000,6824713329190000,483,"S",49,483,"sugov:4",606
+6824713329135000,1,153000,6824713329288000,771,"S",97,493,"DispSync",676
+6824713329190000,6,433000,6824713329623000,2728,"S",120,739,"shell",20461
+6824713329244000,2,244000,6824713329488000,773,"S",97,493,"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,11,"S",0,11,"migration/0",13
+6824713329691000,0,2040000,6824713331731000,0,"R",120,"[NULL]","swapper/5",0
+6824713329736000,6,3595000,6824713333331000,2729,"R+",120,758,"ps",20464
+6824713329811000,1,17000,6824713329828000,771,"S",97,493,"DispSync",676
+6824713329828000,1,2390000,6824713332218000,0,"R",120,"[NULL]","swapper/5",0
+6824713329958000,2,20000,6824713329978000,52,"S",120,52,"rcuop/6",60
+6824713329978000,2,29000,6824713330007000,5,"S",120,5,"rcu_preempt",7
+6824713330007000,2,1145000,6824713331152000,0,"R",120,"[NULL]","swapper/5",0
+6824713330059000,3,1520000,6824713331579000,644,"S",120,644,"ndroid.systemui",1664
+6824713330067000,7,915000,6824713330982000,739,"S",120,739,"adbd",20305
+6824713330982000,7,71506000,6824713402488000,0,"R",120,"[NULL]","swapper/5",0
+6824713331152000,2,172000,6824713331324000,670,"S",100,670,"kworker/u17:2",14944
+6824713331324000,2,62000,6824713331386000,694,"S",120,694,"kworker/2:0",18823
+6824713331386000,2,66000,6824713331452000,630,"S",100,630,"kworker/u17:1",1134
+6824713331452000,2,4000,6824713331456000,670,"S",100,670,"kworker/u17:2",14944
+6824713331456000,2,12000,6824713331468000,694,"S",120,694,"kworker/2:0",18823
+6824713331468000,2,57000,6824713331525000,2487,"R",120,739,"UsbFfs-worker",20308
+6824713331525000,2,14000,6824713331539000,670,"S",100,670,"kworker/u17:2",14944
+6824713331539000,2,119000,6824713331658000,2487,"S",120,739,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713331731000,0,215000,6824713331946000,770,"S",120,493,"Binder:640_2",675
+6824713331751000,2,33000,6824713331784000,0,"R",120,"[NULL]","swapper/5",0
+6824713331784000,2,39000,6824713331823000,670,"S",100,670,"kworker/u17:2",14944
+6824713331823000,2,43000,6824713331866000,694,"S",120,694,"kworker/2:0",18823
+6824713331866000,2,172000,6824713332038000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713331946000,0,667000,6824713332613000,0,"R",120,"[NULL]","swapper/5",0
+6824713332038000,2,397000,6824713332435000,739,"S",120,739,"adbd",20305
+6824713332218000,1,104000,6824713332322000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824713332637000,0,5094000,6824713337731000,0,"R",120,"[NULL]","swapper/5",0
+6824713333331000,6,103000,6824713333434000,483,"S",49,483,"sugov:4",606
+6824713333434000,6,9802000,6824713343236000,2729,"R+",120,758,"ps",20464
+6824713336951000,2,72000,6824713337023000,5,"S",120,5,"rcu_preempt",7
+6824713337023000,2,6609000,6824713343632000,0,"R",120,"[NULL]","swapper/5",0
+6824713337341000,3,53000,6824713337394000,8,"S",120,8,"rcuop/0",10
+6824713337394000,3,14884000,6824713352278000,0,"R",120,"[NULL]","swapper/5",0
+6824713337731000,0,167000,6824713337898000,17,"S",120,17,"rcuop/1",20
+6824713337898000,0,14895000,6824713352793000,0,"R",120,"[NULL]","swapper/5",0
+6824713343236000,6,17000,6824713343253000,483,"S",49,483,"sugov:4",606
+6824713343253000,6,797000,6824713344050000,2729,"R+",120,758,"ps",20464
+6824713343632000,2,147000,6824713343779000,482,"S",49,482,"sugov:0",605
+6824713343779000,2,140000,6824713343919000,5,"R+",120,5,"rcu_preempt",7
+6824713343919000,2,29000,6824713343948000,52,"S",120,52,"rcuop/6",60
+6824713343948000,2,28000,6824713343976000,5,"S",120,5,"rcu_preempt",7
+6824713343976000,2,7683000,6824713351659000,0,"R",120,"[NULL]","swapper/5",0
+6824713344050000,6,47000,6824713344097000,2728,"R+",120,739,"shell",20461
+6824713344097000,6,32000,6824713344129000,483,"S",49,483,"sugov:4",606
+6824713344129000,6,10000,6824713344139000,2728,"S",120,739,"shell",20461
+6824713344139000,6,5756000,6824713349895000,2729,"R+",120,758,"ps",20464
+6824713349895000,6,389000,6824713350284000,739,"S",120,739,"adbd",20305
+6824713350284000,6,1235000,6824713351519000,2729,"R+",120,758,"ps",20464
+6824713351519000,6,22000,6824713351541000,483,"S",49,483,"sugov:4",606
+6824713351541000,6,108000,6824713351649000,670,"S",100,670,"kworker/u17:2",14944
+6824713351649000,6,56000,6824713351705000,669,"S",120,669,"kworker/6:1",14833
+6824713351659000,2,259000,6824713351918000,5,"R+",120,5,"rcu_preempt",7
+6824713351705000,6,212000,6824713351917000,2729,"R+",120,758,"ps",20464
+6824713351917000,6,39000,6824713351956000,670,"S",100,670,"kworker/u17:2",14944
+6824713351918000,2,591000,6824713352509000,52,"S",120,52,"rcuop/6",60
+6824713351956000,6,11000,6824713351967000,669,"S",120,669,"kworker/6:1",14833
+6824713351967000,6,121000,6824713352088000,2729,"R",120,758,"ps",20464
+6824713352088000,6,38000,6824713352126000,670,"S",100,670,"kworker/u17:2",14944
+6824713352126000,6,58000,6824713352184000,2729,"R+",120,758,"ps",20464
+6824713352184000,6,60000,6824713352244000,670,"S",100,670,"kworker/u17:2",14944
+6824713352244000,6,24000,6824713352268000,669,"S",120,669,"kworker/6:1",14833
+6824713352268000,6,6413000,6824713358681000,2729,"R+",120,758,"ps",20464
+6824713352278000,3,219000,6824713352497000,8,"S",120,8,"rcuop/0",10
+6824713352497000,3,11953000,6824713364450000,0,"R",120,"[NULL]","swapper/5",0
+6824713352509000,2,289000,6824713352798000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713352793000,0,205000,6824713352998000,17,"S",120,17,"rcuop/1",20
+6824713352798000,2,418000,6824713353216000,739,"S",120,739,"adbd",20305
+6824713352998000,0,8273000,6824713361271000,0,"R",120,"[NULL]","swapper/5",0
+6824713353216000,2,150000,6824713353366000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713353366000,2,154000,6824713353520000,739,"S",120,739,"adbd",20305
+6824713353520000,2,163000,6824713353683000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713353683000,2,57000,6824713353740000,5,"S",120,5,"rcu_preempt",7
+6824713353740000,2,7167000,6824713360907000,0,"R",120,"[NULL]","swapper/5",0
+6824713358681000,6,60000,6824713358741000,2728,"S",120,739,"shell",20461
+6824713358741000,6,311000,6824713359052000,739,"S",120,739,"adbd",20305
+6824713359052000,6,875000,6824713359927000,2729,"R+",120,758,"ps",20464
+6824713359927000,6,41000,6824713359968000,669,"S",120,669,"kworker/6:1",14833
+6824713359968000,6,3312000,6824713363280000,2729,"R",120,758,"ps",20464
+6824713360907000,2,128000,6824713361035000,5,"R+",120,5,"rcu_preempt",7
+6824713361035000,2,355000,6824713361390000,52,"S",120,52,"rcuop/6",60
+6824713361271000,0,118000,6824713361389000,670,"S",100,670,"kworker/u17:2",14944
+6824713361389000,0,127000,6824713361516000,743,"R+",120,743,"kworker/0:5",20371
+6824713361390000,2,51000,6824713361441000,5,"S",120,5,"rcu_preempt",7
+6824713361441000,2,95000,6824713361536000,0,"R",120,"[NULL]","swapper/5",0
+6824713361516000,0,44000,6824713361560000,670,"S",100,670,"kworker/u17:2",14944
+6824713361536000,2,952000,6824713362488000,786,"S",111,494,"SDM_EventThread",685
+6824713361560000,0,61000,6824713361621000,743,"R+",120,743,"kworker/0:5",20371
+6824713361621000,0,33000,6824713361654000,670,"S",100,670,"kworker/u17:2",14944
+6824713361654000,0,67000,6824713361721000,743,"S",120,743,"kworker/0:5",20371
+6824713361721000,0,80000,6824713361801000,0,"R",120,"[NULL]","swapper/5",0
+6824713361801000,0,57000,6824713361858000,670,"S",100,670,"kworker/u17:2",14944
+6824713361858000,0,46000,6824713361904000,0,"R",120,"[NULL]","swapper/5",0
+6824713361904000,0,39000,6824713361943000,670,"S",100,670,"kworker/u17:2",14944
+6824713361943000,0,43000,6824713361986000,0,"R",120,"[NULL]","swapper/5",0
+6824713361986000,0,70000,6824713362056000,670,"S",100,670,"kworker/u17:2",14944
+6824713362056000,0,69000,6824713362125000,743,"S",120,743,"kworker/0:5",20371
+6824713362125000,0,232000,6824713362357000,0,"R",120,"[NULL]","swapper/5",0
+6824713362357000,0,537000,6824713362894000,777,"S",120,493,"HwBinder:640_1",721
+6824713362488000,2,279000,6824713362767000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713362767000,2,401000,6824713363168000,739,"S",120,739,"adbd",20305
+6824713362894000,0,738000,6824713363632000,0,"R",120,"[NULL]","swapper/5",0
+6824713363107000,1,274000,6824713363381000,771,"S",97,493,"DispSync",676
+6824713363168000,2,157000,6824713363325000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713363280000,6,49000,6824713363329000,483,"S",49,483,"sugov:4",606
+6824713363325000,2,157000,6824713363482000,739,"S",120,739,"adbd",20305
+6824713363329000,6,6630000,6824713369959000,2729,"R+",120,758,"ps",20464
+6824713363381000,1,919000,6824713364300000,0,"R",120,"[NULL]","swapper/5",0
+6824713363482000,2,776000,6824713364258000,702,"S",120,702,"kworker/u16:7",19422
+6824713363632000,0,355000,6824713363987000,773,"S",97,493,"app",678
+6824713363987000,0,2520000,6824713366507000,0,"R",120,"[NULL]","swapper/5",0
+6824713364258000,2,164000,6824713364422000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713364300000,1,2117000,6824713366417000,644,"S",120,644,"ndroid.systemui",1664
+6824713364422000,2,2600000,6824713367022000,0,"R",120,"[NULL]","swapper/5",0
+6824713364450000,3,65000,6824713364515000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824713366797000,1,143000,6824713366940000,773,"S",97,493,"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,771,"S",97,493,"DispSync",676
+6824713367055000,2,85000,6824713367140000,5,"R+",120,5,"rcu_preempt",7
+6824713367140000,2,409000,6824713367549000,52,"S",120,52,"rcuop/6",60
+6824713367549000,2,34000,6824713367583000,5,"S",120,5,"rcu_preempt",7
+6824713367583000,2,5336000,6824713372919000,0,"R",120,"[NULL]","swapper/5",0
+6824713369959000,6,65000,6824713370024000,2728,"R+",120,739,"shell",20461
+6824713370024000,6,36000,6824713370060000,483,"S",49,483,"sugov:4",606
+6824713370060000,6,15000,6824713370075000,2728,"S",120,739,"shell",20461
+6824713370075000,6,299000,6824713370374000,739,"S",120,739,"adbd",20305
+6824713370374000,6,10921000,6824713381295000,2729,"R+",120,758,"ps",20464
+6824713372472000,0,237000,6824713372709000,670,"R+",100,670,"kworker/u17:2",14944
+6824713372709000,0,188000,6824713372897000,482,"S",49,482,"sugov:0",605
+6824713372897000,0,74000,6824713372971000,670,"S",100,670,"kworker/u17:2",14944
+6824713372919000,2,89000,6824713373008000,630,"S",100,630,"kworker/u17:1",1134
+6824713372971000,0,177000,6824713373148000,743,"R+",120,743,"kworker/0:5",20371
+6824713373008000,2,144000,6824713373152000,0,"R",120,"[NULL]","swapper/5",0
+6824713373148000,0,64000,6824713373212000,670,"S",100,670,"kworker/u17:2",14944
+6824713373152000,2,734000,6824713373886000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713373212000,0,142000,6824713373354000,743,"R+",120,743,"kworker/0:5",20371
+6824713373354000,0,79000,6824713373433000,670,"S",100,670,"kworker/u17:2",14944
+6824713373433000,0,170000,6824713373603000,743,"S",120,743,"kworker/0:5",20371
+6824713373603000,0,8922000,6824713382525000,0,"R",120,"[NULL]","swapper/5",0
+6824713373886000,2,518000,6824713374404000,739,"S",120,739,"adbd",20305
+6824713374404000,2,168000,6824713374572000,5,"R+",120,5,"rcu_preempt",7
+6824713374572000,2,494000,6824713375066000,52,"S",120,52,"rcuop/6",60
+6824713375066000,2,44000,6824713375110000,5,"S",120,5,"rcu_preempt",7
+6824713375110000,2,127000,6824713375237000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713375237000,2,235000,6824713375472000,739,"S",120,739,"adbd",20305
+6824713375472000,2,230000,6824713375702000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713375702000,2,1343000,6824713377045000,0,"R",120,"[NULL]","swapper/5",0
+6824713377045000,2,741000,6824713377786000,702,"S",120,702,"kworker/u16:7",19422
+6824713377786000,2,2753000,6824713380539000,0,"R",120,"[NULL]","swapper/5",0
+6824713378015000,3,111000,6824713378126000,77,"S",120,77,"smem_native_rpm",87
+6824713378126000,3,5664000,6824713383790000,0,"R",120,"[NULL]","swapper/5",0
+6824713380539000,2,133000,6824713380672000,482,"S",49,482,"sugov:0",605
+6824713380672000,2,103000,6824713380775000,5,"R+",120,5,"rcu_preempt",7
+6824713380775000,2,390000,6824713381165000,52,"S",120,52,"rcuop/6",60
+6824713381165000,2,41000,6824713381206000,5,"R+",120,5,"rcu_preempt",7
+6824713381206000,2,75000,6824713381281000,482,"S",49,482,"sugov:0",605
+6824713381281000,2,45000,6824713381326000,5,"S",120,5,"rcu_preempt",7
+6824713381295000,6,45000,6824713381340000,483,"S",49,483,"sugov:4",606
+6824713381326000,2,1876000,6824713383202000,0,"R",120,"[NULL]","swapper/5",0
+6824713381340000,6,66000,6824713381406000,2728,"S",120,739,"shell",20461
+6824713381406000,6,288000,6824713381694000,739,"S",120,739,"adbd",20305
+6824713381694000,6,1546000,6824713383240000,2729,"R+",120,758,"ps",20464
+6824713382525000,0,114000,6824713382639000,670,"S",100,670,"kworker/u17:2",14944
+6824713382639000,0,173000,6824713382812000,743,"S",120,743,"kworker/0:5",20371
+6824713382812000,0,744000,6824713383556000,0,"R",120,"[NULL]","swapper/5",0
+6824713383202000,2,136000,6824713383338000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713383240000,6,170000,6824713383410000,483,"D",49,483,"sugov:4",606
+6824713383338000,2,443000,6824713383781000,0,"R",120,"[NULL]","swapper/5",0
+6824713383410000,6,5051000,6824713388461000,2729,"R+",120,758,"ps",20464
+6824713383556000,0,102000,6824713383658000,670,"S",100,670,"kworker/u17:2",14944
+6824713383658000,0,115000,6824713383773000,743,"R+",120,743,"kworker/0:5",20371
+6824713383773000,0,53000,6824713383826000,670,"S",100,670,"kworker/u17:2",14944
+6824713383781000,2,83000,6824713383864000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713383790000,3,60000,6824713383850000,77,"S",120,77,"smem_native_rpm",87
+6824713383826000,0,167000,6824713383993000,743,"S",120,743,"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,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713383993000,0,6047000,6824713390040000,0,"R",120,"[NULL]","swapper/5",0
+6824713384138000,2,253000,6824713384391000,739,"S",120,739,"adbd",20305
+6824713384362000,4,24000,6824713384386000,483,"S",49,483,"sugov:4",606
+6824713384386000,4,18375000,6824713402761000,0,"R",120,"[NULL]","swapper/5",0
+6824713384391000,2,105000,6824713384496000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713384496000,2,149000,6824713384645000,739,"S",120,739,"adbd",20305
+6824713384645000,2,120000,6824713384765000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713384765000,2,2176000,6824713386941000,0,"R",120,"[NULL]","swapper/5",0
+6824713386941000,2,96000,6824713387037000,5,"R+",120,5,"rcu_preempt",7
+6824713387037000,2,340000,6824713387377000,52,"S",120,52,"rcuop/6",60
+6824713387377000,2,41000,6824713387418000,5,"S",120,5,"rcu_preempt",7
+6824713387418000,2,3209000,6824713390627000,0,"R",120,"[NULL]","swapper/5",0
+6824713388461000,6,29000,6824713388490000,2728,"S",120,739,"shell",20461
+6824713388490000,6,145000,6824713388635000,739,"S",120,739,"adbd",20305
+6824713388635000,6,3783000,6824713392418000,2729,"R+",120,758,"ps",20464
+6824713390040000,0,142000,6824713390182000,670,"S",100,670,"kworker/u17:2",14944
+6824713390182000,0,178000,6824713390360000,743,"S",120,743,"kworker/0:5",20371
+6824713390360000,0,476000,6824713390836000,0,"R",120,"[NULL]","swapper/5",0
+6824713390627000,2,119000,6824713390746000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713390746000,2,516000,6824713391262000,0,"R",120,"[NULL]","swapper/5",0
+6824713390836000,0,87000,6824713390923000,670,"S",100,670,"kworker/u17:2",14944
+6824713390923000,0,144000,6824713391067000,743,"S",120,743,"kworker/0:5",20371
+6824713391067000,0,424000,6824713391491000,0,"R",120,"[NULL]","swapper/5",0
+6824713391262000,2,94000,6824713391356000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713391356000,2,737000,6824713392093000,0,"R",120,"[NULL]","swapper/5",0
+6824713391491000,0,76000,6824713391567000,670,"S",100,670,"kworker/u17:2",14944
+6824713391567000,0,314000,6824713391881000,0,"R",120,"[NULL]","swapper/5",0
+6824713391881000,0,87000,6824713391968000,670,"S",100,670,"kworker/u17:2",14944
+6824713391968000,0,163000,6824713392131000,743,"S",120,743,"kworker/0:5",20371
+6824713392093000,2,134000,6824713392227000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713392131000,0,1225000,6824713393356000,0,"R",120,"[NULL]","swapper/5",0
+6824713392227000,2,294000,6824713392521000,739,"S",120,739,"adbd",20305
+6824713392418000,6,21000,6824713392439000,2728,"S",120,739,"shell",20461
+6824713392439000,6,7047000,6824713399486000,2729,"R+",120,758,"ps",20464
+6824713392521000,2,105000,6824713392626000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713392626000,2,812000,6824713393438000,739,"S",120,739,"adbd",20305
+6824713393356000,0,90000,6824713393446000,670,"S",100,670,"kworker/u17:2",14944
+6824713393438000,2,137000,6824713393575000,5,"S",120,5,"rcu_preempt",7
+6824713393446000,0,64000,6824713393510000,743,"S",120,743,"kworker/0:5",20371
+6824713393510000,0,41000,6824713393551000,0,"R",120,"[NULL]","swapper/5",0
+6824713393551000,0,67000,6824713393618000,670,"S",100,670,"kworker/u17:2",14944
+6824713393575000,2,258000,6824713393833000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713393618000,0,173000,6824713393791000,0,"R",120,"[NULL]","swapper/5",0
+6824713393791000,0,72000,6824713393863000,670,"S",100,670,"kworker/u17:2",14944
+6824713393833000,2,136000,6824713393969000,0,"R",120,"[NULL]","swapper/5",0
+6824713393863000,0,110000,6824713393973000,743,"R+",120,743,"kworker/0:5",20371
+6824713393969000,2,167000,6824713394136000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713393973000,0,35000,6824713394008000,670,"S",100,670,"kworker/u17:2",14944
+6824713394008000,0,46000,6824713394054000,743,"S",120,743,"kworker/0:5",20371
+6824713394054000,0,41000,6824713394095000,0,"R",120,"[NULL]","swapper/5",0
+6824713394095000,0,67000,6824713394162000,670,"S",100,670,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713394400000,0,224000,6824713394624000,743,"S",120,743,"kworker/0:5",20371
+6824713394483000,2,486000,6824713394969000,786,"S",111,494,"SDM_EventThread",685
+6824713394624000,0,46000,6824713394670000,0,"R",120,"[NULL]","swapper/5",0
+6824713394670000,0,199000,6824713394869000,771,"S",97,493,"DispSync",676
+6824713394869000,0,625000,6824713395494000,0,"R",120,"[NULL]","swapper/5",0
+6824713394969000,2,86000,6824713395055000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713395055000,2,184000,6824713395239000,739,"S",120,739,"adbd",20305
+6824713395078000,1,283000,6824713395361000,773,"S",97,493,"app",678
+6824713395162000,3,322000,6824713395484000,777,"S",120,493,"HwBinder:640_1",721
+6824713395239000,2,104000,6824713395343000,2487,"R+",120,739,"UsbFfs-worker",20308
+6824713395343000,2,155000,6824713395498000,739,"S",120,739,"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,771,"S",97,493,"DispSync",676
+6824713395498000,2,120000,6824713395618000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713395543000,0,1769000,6824713397312000,644,"S",120,644,"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,770,"S",120,493,"Binder:640_2",675
+6824713397587000,1,483000,6824713398070000,0,"R",120,"[NULL]","swapper/5",0
+6824713397735000,0,162000,6824713397897000,773,"S",97,493,"app",678
+6824713397897000,0,2323000,6824713400220000,0,"R",120,"[NULL]","swapper/5",0
+6824713398070000,1,74000,6824713398144000,771,"S",97,493,"DispSync",676
+6824713398144000,1,3426000,6824713401570000,0,"R",120,"[NULL]","swapper/5",0
+6824713399486000,6,30000,6824713399516000,2728,"S",120,739,"shell",20461
+6824713399516000,6,162000,6824713399678000,739,"S",120,739,"adbd",20305
+6824713399678000,6,3250000,6824713402928000,2729,"R+",120,758,"ps",20464
+6824713400220000,0,111000,6824713400331000,670,"S",100,670,"kworker/u17:2",14944
+6824713400331000,0,120000,6824713400451000,743,"S",120,743,"kworker/0:5",20371
+6824713400451000,0,43000,6824713400494000,2487,"R",120,739,"UsbFfs-worker",20308
+6824713400494000,0,70000,6824713400564000,670,"S",100,670,"kworker/u17:2",14944
+6824713400564000,0,40000,6824713400604000,743,"R+",120,743,"kworker/0:5",20371
+6824713400604000,0,34000,6824713400638000,670,"S",100,670,"kworker/u17:2",14944
+6824713400638000,0,17000,6824713400655000,743,"S",120,743,"kworker/0:5",20371
+6824713400655000,0,97000,6824713400752000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713400752000,0,71000,6824713400823000,670,"S",100,670,"kworker/u17:2",14944
+6824713400823000,0,363000,6824713401186000,0,"R",120,"[NULL]","swapper/5",0
+6824713401186000,0,78000,6824713401264000,670,"S",100,670,"kworker/u17:2",14944
+6824713401264000,0,103000,6824713401367000,743,"S",120,743,"kworker/0:5",20371
+6824713401367000,0,329000,6824713401696000,0,"R",120,"[NULL]","swapper/5",0
+6824713401570000,1,237000,6824713401807000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713401696000,0,372000,6824713402068000,739,"S",120,739,"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,2728,"S",120,739,"shell",20461
+6824713402539000,7,4230000,6824713406769000,0,"R",120,"[NULL]","swapper/5",0
+6824713402761000,4,165000,6824713402926000,739,"S",120,739,"adbd",20305
+6824713402926000,4,350000,6824713403276000,0,"R",120,"[NULL]","swapper/5",0
+6824713402928000,6,24000,6824713402952000,49,"S",0,49,"migration/6",56
+6824713402952000,6,43000,6824713402995000,483,"S",49,483,"sugov:4",606
+6824713402995000,6,4234000,6824713407229000,0,"R",120,"[NULL]","swapper/5",0
+6824713403276000,4,53289000,6824713456565000,2729,"R",120,758,"ps",20464
+6824713403325000,2,97000,6824713403422000,22,"S",120,22,"ksoftirqd/2",25
+6824713403422000,2,498000,6824713403920000,0,"R",120,"[NULL]","swapper/5",0
+6824713403479000,0,104000,6824713403583000,670,"S",100,670,"kworker/u17:2",14944
+6824713403583000,0,99000,6824713403682000,743,"S",120,743,"kworker/0:5",20371
+6824713403641000,3,96000,6824713403737000,5,"S",120,5,"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,52,"S",120,52,"rcuop/6",60
+6824713403944000,1,83000,6824713404027000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713404027000,1,662000,6824713404689000,0,"R",120,"[NULL]","swapper/5",0
+6824713404189000,0,132000,6824713404321000,670,"R+",100,670,"kworker/u17:2",14944
+6824713404321000,0,140000,6824713404461000,482,"S",49,482,"sugov:0",605
+6824713404450000,2,572000,6824713405022000,0,"R",120,"[NULL]","swapper/5",0
+6824713404461000,0,55000,6824713404516000,670,"S",100,670,"kworker/u17:2",14944
+6824713404516000,0,125000,6824713404641000,743,"S",120,743,"kworker/0:5",20371
+6824713404622000,3,59000,6824713404681000,630,"S",100,630,"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,5,"S",120,5,"rcu_preempt",7
+6824713404751000,1,4130000,6824713408881000,0,"R",120,"[NULL]","swapper/5",0
+6824713405022000,2,120000,6824713405142000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713405142000,2,330000,6824713405472000,0,"R",120,"[NULL]","swapper/5",0
+6824713405263000,3,117000,6824713405380000,630,"S",100,630,"kworker/u17:1",1134
+6824713405380000,3,138000,6824713405518000,686,"S",120,686,"kworker/3:1",17791
+6824713405472000,2,245000,6824713405717000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713405850000,5,1152000,6824713407002000,0,"R",120,"[NULL]","swapper/5",0
+6824713406769000,7,10000,6824713406779000,38,"S",120,38,"rcuop/4",44
+6824713406779000,7,26544000,6824713433323000,0,"R",120,"[NULL]","swapper/5",0
+6824713407002000,5,29000,6824713407031000,2728,"S",120,739,"shell",20461
+6824713407031000,5,7986000,6824713415017000,0,"R",120,"[NULL]","swapper/5",0
+6824713407229000,6,96000,6824713407325000,739,"S",120,739,"adbd",20305
+6824713407325000,6,1876000,6824713409201000,0,"R",120,"[NULL]","swapper/5",0
+6824713407890000,3,127000,6824713408017000,630,"S",100,630,"kworker/u17:1",1134
+6824713408017000,3,114000,6824713408131000,686,"S",120,686,"kworker/3:1",17791
+6824713408131000,3,8216000,6824713416347000,0,"R",120,"[NULL]","swapper/5",0
+6824713408168000,2,97000,6824713408265000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713408265000,2,326000,6824713408591000,0,"R",120,"[NULL]","swapper/5",0
+6824713408420000,0,106000,6824713408526000,630,"S",100,630,"kworker/u17:1",1134
+6824713408526000,0,129000,6824713408655000,743,"S",120,743,"kworker/0:5",20371
+6824713408591000,2,198000,6824713408789000,630,"S",100,630,"kworker/u17:1",1134
+6824713408655000,0,53000,6824713408708000,0,"R",120,"[NULL]","swapper/5",0
+6824713408708000,0,44000,6824713408752000,670,"S",100,670,"kworker/u17:2",14944
+6824713408752000,0,7418000,6824713416170000,0,"R",120,"[NULL]","swapper/5",0
+6824713408789000,2,105000,6824713408894000,694,"S",120,694,"kworker/2:0",18823
+6824713408881000,1,261000,6824713409142000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713409261000,6,6003000,6824713415264000,0,"R",120,"[NULL]","swapper/5",0
+6824713410030000,1,92000,6824713410122000,5,"S",120,5,"rcu_preempt",7
+6824713410122000,1,6146000,6824713416268000,0,"R",120,"[NULL]","swapper/5",0
+6824713410365000,2,1409000,6824713411774000,52,"S",120,52,"rcuop/6",60
+6824713411774000,2,3953000,6824713415727000,0,"R",120,"[NULL]","swapper/5",0
+6824713415017000,5,41000,6824713415058000,2728,"S",120,739,"shell",20461
+6824713415058000,5,871000,6824713415929000,0,"R",120,"[NULL]","swapper/5",0
+6824713415264000,6,114000,6824713415378000,739,"S",120,739,"adbd",20305
+6824713415378000,6,2157000,6824713417535000,0,"R",120,"[NULL]","swapper/5",0
+6824713415727000,2,177000,6824713415904000,630,"S",100,630,"kworker/u17:1",1134
+6824713415904000,2,176000,6824713416080000,694,"S",120,694,"kworker/2:0",18823
+6824713415929000,5,22000,6824713415951000,2728,"S",120,739,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713416268000,1,135000,6824713416403000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713416271000,0,81000,6824713416352000,743,"S",120,743,"kworker/0:5",20371
+6824713416347000,3,56000,6824713416403000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713416675000,1,57000,6824713416732000,5,"S",120,5,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713416908000,2,119000,6824713417027000,694,"S",120,694,"kworker/2:0",18823
+6824713417027000,2,1013000,6824713418040000,0,"R",120,"[NULL]","swapper/5",0
+6824713417253000,1,234000,6824713417487000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713417487000,1,1008000,6824713418495000,0,"R",120,"[NULL]","swapper/5",0
+6824713417535000,6,118000,6824713417653000,739,"S",120,739,"adbd",20305
+6824713417653000,6,1707000,6824713419360000,0,"R",120,"[NULL]","swapper/5",0
+6824713418040000,2,115000,6824713418155000,630,"S",100,630,"kworker/u17:1",1134
+6824713418155000,2,178000,6824713418333000,694,"S",120,694,"kworker/2:0",18823
+6824713418333000,2,395000,6824713418728000,0,"R",120,"[NULL]","swapper/5",0
+6824713418495000,1,107000,6824713418602000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713418563000,3,106000,6824713418669000,630,"S",100,630,"kworker/u17:1",1134
+6824713418602000,1,455000,6824713419057000,0,"R",120,"[NULL]","swapper/5",0
+6824713418669000,3,117000,6824713418786000,686,"S",120,686,"kworker/3:1",17791
+6824713418728000,2,76000,6824713418804000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713418952000,2,87000,6824713419039000,694,"S",120,694,"kworker/2:0",18823
+6824713419039000,2,1615000,6824713420654000,0,"R",120,"[NULL]","swapper/5",0
+6824713419057000,1,251000,6824713419308000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713419308000,1,1797000,6824713421105000,0,"R",120,"[NULL]","swapper/5",0
+6824713419360000,6,50000,6824713419410000,739,"S",120,739,"adbd",20305
+6824713419410000,6,798000,6824713420208000,0,"R",120,"[NULL]","swapper/5",0
+6824713419965000,5,29000,6824713419994000,2728,"S",120,739,"shell",20461
+6824713419994000,5,3214000,6824713423208000,0,"R",120,"[NULL]","swapper/5",0
+6824713420208000,6,90000,6824713420298000,739,"S",120,739,"adbd",20305
+6824713420298000,6,1655000,6824713421953000,0,"R",120,"[NULL]","swapper/5",0
+6824713420654000,2,115000,6824713420769000,630,"S",100,630,"kworker/u17:1",1134
+6824713420769000,2,111000,6824713420880000,694,"S",120,694,"kworker/2:0",18823
+6824713420880000,2,66000,6824713420946000,0,"R",120,"[NULL]","swapper/5",0
+6824713420946000,2,147000,6824713421093000,630,"S",100,630,"kworker/u17:1",1134
+6824713421093000,2,133000,6824713421226000,694,"S",120,694,"kworker/2:0",18823
+6824713421105000,1,129000,6824713421234000,2487,"S",120,739,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713421438000,0,49000,6824713421487000,0,"R",120,"[NULL]","swapper/5",0
+6824713421455000,3,119000,6824713421574000,630,"S",100,630,"kworker/u17:1",1134
+6824713421487000,0,43000,6824713421530000,670,"S",100,670,"kworker/u17:2",14944
+6824713421530000,0,6608000,6824713428138000,0,"R",120,"[NULL]","swapper/5",0
+6824713421574000,3,130000,6824713421704000,686,"S",120,686,"kworker/3:1",17791
+6824713421658000,1,224000,6824713421882000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713422005000,6,1245000,6824713423250000,0,"R",120,"[NULL]","swapper/5",0
+6824713423208000,5,44000,6824713423252000,2728,"S",120,739,"shell",20461
+6824713423250000,6,81000,6824713423331000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713423421000,6,90000,6824713423511000,38,"S",120,38,"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,5,"S",120,5,"rcu_preempt",7
+6824713423600000,1,800000,6824713424400000,0,"R",120,"[NULL]","swapper/5",0
+6824713423944000,3,121000,6824713424065000,630,"S",100,630,"kworker/u17:1",1134
+6824713424065000,3,113000,6824713424178000,686,"S",120,686,"kworker/3:1",17791
+6824713424178000,3,631000,6824713424809000,0,"R",120,"[NULL]","swapper/5",0
+6824713424400000,1,98000,6824713424498000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713424498000,1,773000,6824713425271000,0,"R",120,"[NULL]","swapper/5",0
+6824713424809000,3,127000,6824713424936000,630,"S",100,630,"kworker/u17:1",1134
+6824713424936000,3,111000,6824713425047000,686,"S",120,686,"kworker/3:1",17791
+6824713425047000,3,3858000,6824713428905000,0,"R",120,"[NULL]","swapper/5",0
+6824713425093000,2,105000,6824713425198000,630,"S",100,630,"kworker/u17:1",1134
+6824713425198000,2,89000,6824713425287000,694,"S",120,694,"kworker/2:0",18823
+6824713425271000,1,260000,6824713425531000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713425626000,6,2459000,6824713428085000,0,"R",120,"[NULL]","swapper/5",0
+6824713426874000,2,103000,6824713426977000,702,"S",120,702,"kworker/u16:7",19422
+6824713426977000,2,1675000,6824713428652000,0,"R",120,"[NULL]","swapper/5",0
+6824713427836000,5,29000,6824713427865000,2728,"S",120,739,"shell",20461
+6824713427865000,5,2265000,6824713430130000,0,"R",120,"[NULL]","swapper/5",0
+6824713428085000,6,99000,6824713428184000,739,"S",120,739,"adbd",20305
+6824713428138000,0,104000,6824713428242000,743,"S",120,743,"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,786,"S",111,494,"SDM_EventThread",685
+6824713428905000,3,123000,6824713429028000,630,"S",100,630,"kworker/u17:1",1134
+6824713428982000,1,322000,6824713429304000,777,"S",120,493,"HwBinder:640_1",721
+6824713429028000,3,118000,6824713429146000,686,"S",120,686,"kworker/3:1",17791
+6824713429089000,2,544000,6824713429633000,0,"R",120,"[NULL]","swapper/5",0
+6824713429140000,0,196000,6824713429336000,771,"S",97,493,"DispSync",676
+6824713429146000,3,734000,6824713429880000,0,"R",120,"[NULL]","swapper/5",0
+6824713429304000,1,93000,6824713429397000,2487,"S",120,739,"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,773,"S",97,493,"app",678
+6824713429867000,1,193000,6824713430060000,771,"S",97,493,"DispSync",676
+6824713429880000,3,203000,6824713430083000,630,"S",100,630,"kworker/u17:1",1134
+6824713429920000,2,86000,6824713430006000,0,"R",120,"[NULL]","swapper/5",0
+6824713430006000,2,61000,6824713430067000,5,"S",120,5,"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,644,"S",120,644,"ndroid.systemui",1664
+6824713430083000,3,143000,6824713430226000,686,"S",120,686,"kworker/3:1",17791
+6824713430130000,5,24000,6824713430154000,2728,"S",120,739,"shell",20461
+6824713430154000,5,3393000,6824713433547000,0,"R",120,"[NULL]","swapper/5",0
+6824713430180000,2,112000,6824713430292000,2487,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713430672000,1,134000,6824713430806000,693,"S",120,693,"kworker/1:1",18800
+6824713430761000,2,222000,6824713430983000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713431172000,6,1852000,6824713433024000,0,"R",120,"[NULL]","swapper/5",0
+6824713431501000,1,118000,6824713431619000,630,"S",100,630,"kworker/u17:1",1134
+6824713431590000,2,264000,6824713431854000,770,"R+",120,493,"Binder:640_2",675
+6824713431619000,1,101000,6824713431720000,693,"S",120,693,"kworker/1:1",18800
+6824713431720000,1,103000,6824713431823000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713431823000,1,758000,6824713432581000,0,"R",120,"[NULL]","swapper/5",0
+6824713431854000,2,46000,6824713431900000,773,"S",97,493,"app",678
+6824713431861000,0,492000,6824713432353000,0,"R",120,"[NULL]","swapper/5",0
+6824713431900000,2,159000,6824713432059000,770,"S",120,493,"Binder:640_2",675
+6824713431932000,3,91000,6824713432023000,630,"S",100,630,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713432243000,3,110000,6824713432353000,686,"S",120,686,"kworker/3:1",17791
+6824713432353000,3,349000,6824713432702000,0,"R",120,"[NULL]","swapper/5",0
+6824713432353000,0,196000,6824713432549000,773,"S",97,493,"app",678
+6824713432549000,0,28791000,6824713461340000,0,"R",120,"[NULL]","swapper/5",0
+6824713432581000,1,110000,6824713432691000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713432691000,1,29017000,6824713461708000,0,"R",120,"[NULL]","swapper/5",0
+6824713432702000,3,77000,6824713432779000,630,"S",100,630,"kworker/u17:1",1134
+6824713432714000,2,166000,6824713432880000,771,"S",97,493,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713433070000,6,31000,6824713433101000,669,"S",120,669,"kworker/6:1",14833
+6824713433101000,6,1961000,6824713435062000,0,"R",120,"[NULL]","swapper/5",0
+6824713433323000,7,68000,6824713433391000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713433391000,7,2508000,6824713435899000,0,"R",120,"[NULL]","swapper/5",0
+6824713433547000,5,47000,6824713433594000,739,"S",120,739,"adbd",20305
+6824713433594000,5,1241000,6824713434835000,0,"R",120,"[NULL]","swapper/5",0
+6824713434835000,5,30000,6824713434865000,2728,"S",120,739,"shell",20461
+6824713434865000,5,2740000,6824713437605000,0,"R",120,"[NULL]","swapper/5",0
+6824713435062000,6,101000,6824713435163000,739,"S",120,739,"adbd",20305
+6824713435163000,6,471000,6824713435634000,0,"R",120,"[NULL]","swapper/5",0
+6824713435634000,6,36000,6824713435670000,630,"S",100,630,"kworker/u17:1",1134
+6824713435670000,6,13000,6824713435683000,669,"S",120,669,"kworker/6:1",14833
+6824713435683000,6,316000,6824713435999000,0,"R",120,"[NULL]","swapper/5",0
+6824713435899000,7,15000,6824713435914000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713435914000,7,346000,6824713436260000,0,"R",120,"[NULL]","swapper/5",0
+6824713435999000,6,24000,6824713436023000,630,"S",100,630,"kworker/u17:1",1134
+6824713436023000,6,13000,6824713436036000,669,"S",120,669,"kworker/6:1",14833
+6824713436036000,6,273000,6824713436309000,0,"R",120,"[NULL]","swapper/5",0
+6824713436260000,7,20000,6824713436280000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713436280000,7,302000,6824713436582000,0,"R",120,"[NULL]","swapper/5",0
+6824713436309000,6,29000,6824713436338000,630,"S",100,630,"kworker/u17:1",1134
+6824713436338000,6,35000,6824713436373000,0,"R",120,"[NULL]","swapper/5",0
+6824713436373000,6,29000,6824713436402000,630,"S",100,630,"kworker/u17:1",1134
+6824713436402000,6,14000,6824713436416000,669,"S",120,669,"kworker/6:1",14833
+6824713436416000,6,184000,6824713436600000,0,"R",120,"[NULL]","swapper/5",0
+6824713436582000,7,40000,6824713436622000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713436600000,6,53000,6824713436653000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713436736000,6,216000,6824713436952000,38,"S",120,38,"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,5,"S",120,5,"rcu_preempt",7
+6824713437040000,2,6321000,6824713443361000,0,"R",120,"[NULL]","swapper/5",0
+6824713437605000,5,30000,6824713437635000,2728,"S",120,739,"shell",20461
+6824713437630000,6,82000,6824713437712000,739,"S",120,739,"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,630,"S",100,630,"kworker/u17:1",1134
+6824713437741000,6,40000,6824713437781000,0,"R",120,"[NULL]","swapper/5",0
+6824713437781000,6,19000,6824713437800000,630,"S",100,630,"kworker/u17:1",1134
+6824713437800000,6,9000,6824713437809000,669,"S",120,669,"kworker/6:1",14833
+6824713437809000,6,39000,6824713437848000,0,"R",120,"[NULL]","swapper/5",0
+6824713437848000,6,25000,6824713437873000,630,"S",100,630,"kworker/u17:1",1134
+6824713437873000,6,136000,6824713438009000,0,"R",120,"[NULL]","swapper/5",0
+6824713437982000,7,13000,6824713437995000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713437995000,7,43000,6824713438038000,0,"R",120,"[NULL]","swapper/5",0
+6824713438009000,6,19000,6824713438028000,630,"S",100,630,"kworker/u17:1",1134
+6824713438028000,6,10000,6824713438038000,669,"S",120,669,"kworker/6:1",14833
+6824713438038000,7,7000,6824713438045000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713438038000,6,283000,6824713438321000,0,"R",120,"[NULL]","swapper/5",0
+6824713438045000,7,470000,6824713438515000,0,"R",120,"[NULL]","swapper/5",0
+6824713438321000,6,20000,6824713438341000,630,"S",100,630,"kworker/u17:1",1134
+6824713438341000,6,34000,6824713438375000,0,"R",120,"[NULL]","swapper/5",0
+6824713438375000,6,29000,6824713438404000,630,"S",100,630,"kworker/u17:1",1134
+6824713438404000,6,71000,6824713438475000,0,"R",120,"[NULL]","swapper/5",0
+6824713438475000,6,29000,6824713438504000,630,"S",100,630,"kworker/u17:1",1134
+6824713438504000,6,14000,6824713438518000,669,"S",120,669,"kworker/6:1",14833
+6824713438515000,7,34000,6824713438549000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713438518000,6,10000,6824713438528000,0,"R",120,"[NULL]","swapper/5",0
+6824713438528000,6,43000,6824713438571000,739,"S",120,739,"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,2728,"S",120,739,"shell",20461
+6824713440667000,5,2936000,6824713443603000,0,"R",120,"[NULL]","swapper/5",0
+6824713440865000,6,84000,6824713440949000,739,"S",120,739,"adbd",20305
+6824713440949000,6,533000,6824713441482000,0,"R",120,"[NULL]","swapper/5",0
+6824713441482000,6,36000,6824713441518000,630,"S",100,630,"kworker/u17:1",1134
+6824713441518000,6,12000,6824713441530000,669,"S",120,669,"kworker/6:1",14833
+6824713441530000,6,315000,6824713441845000,0,"R",120,"[NULL]","swapper/5",0
+6824713441741000,7,12000,6824713441753000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713441753000,7,349000,6824713442102000,0,"R",120,"[NULL]","swapper/5",0
+6824713441845000,6,22000,6824713441867000,630,"S",100,630,"kworker/u17:1",1134
+6824713441867000,6,11000,6824713441878000,669,"S",120,669,"kworker/6:1",14833
+6824713441878000,6,270000,6824713442148000,0,"R",120,"[NULL]","swapper/5",0
+6824713442102000,7,15000,6824713442117000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713442117000,7,369000,6824713442486000,0,"R",120,"[NULL]","swapper/5",0
+6824713442148000,6,16000,6824713442164000,630,"S",100,630,"kworker/u17:1",1134
+6824713442164000,6,35000,6824713442199000,0,"R",120,"[NULL]","swapper/5",0
+6824713442199000,6,26000,6824713442225000,630,"S",100,630,"kworker/u17:1",1134
+6824713442225000,6,51000,6824713442276000,0,"R",120,"[NULL]","swapper/5",0
+6824713442276000,6,29000,6824713442305000,630,"S",100,630,"kworker/u17:1",1134
+6824713442305000,6,15000,6824713442320000,669,"S",120,669,"kworker/6:1",14833
+6824713442320000,6,184000,6824713442504000,0,"R",120,"[NULL]","swapper/5",0
+6824713442486000,7,38000,6824713442524000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713442504000,6,45000,6824713442549000,739,"S",120,739,"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,5,"S",120,5,"rcu_preempt",7
+6824713443453000,2,362000,6824713443815000,0,"R",120,"[NULL]","swapper/5",0
+6824713443603000,5,161000,6824713443764000,38,"S",120,38,"rcuop/4",44
+6824713443764000,5,254000,6824713444018000,0,"R",120,"[NULL]","swapper/5",0
+6824713443815000,2,49000,6824713443864000,5,"S",120,5,"rcu_preempt",7
+6824713443864000,2,6152000,6824713450016000,0,"R",120,"[NULL]","swapper/5",0
+6824713444018000,5,29000,6824713444047000,2728,"S",120,739,"shell",20461
+6824713444047000,5,6341000,6824713450388000,0,"R",120,"[NULL]","swapper/5",0
+6824713444253000,6,82000,6824713444335000,739,"S",120,739,"adbd",20305
+6824713444335000,6,323000,6824713444658000,0,"R",120,"[NULL]","swapper/5",0
+6824713444658000,6,36000,6824713444694000,630,"S",100,630,"kworker/u17:1",1134
+6824713444694000,6,11000,6824713444705000,669,"S",120,669,"kworker/6:1",14833
+6824713444705000,6,416000,6824713445121000,0,"R",120,"[NULL]","swapper/5",0
+6824713444885000,7,14000,6824713444899000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713444899000,7,439000,6824713445338000,0,"R",120,"[NULL]","swapper/5",0
+6824713445121000,6,35000,6824713445156000,630,"S",100,630,"kworker/u17:1",1134
+6824713445156000,6,9000,6824713445165000,669,"S",120,669,"kworker/6:1",14833
+6824713445165000,6,50000,6824713445215000,0,"R",120,"[NULL]","swapper/5",0
+6824713445215000,6,27000,6824713445242000,630,"S",100,630,"kworker/u17:1",1134
+6824713445242000,6,9000,6824713445251000,669,"S",120,669,"kworker/6:1",14833
+6824713445251000,6,106000,6824713445357000,0,"R",120,"[NULL]","swapper/5",0
+6824713445338000,7,42000,6824713445380000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713445357000,6,38000,6824713445395000,739,"S",120,739,"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,2728,"S",120,739,"shell",20461
+6824713447869000,7,782000,6824713448651000,0,"R",120,"[NULL]","swapper/5",0
+6824713448074000,6,85000,6824713448159000,739,"S",120,739,"adbd",20305
+6824713448159000,6,279000,6824713448438000,0,"R",120,"[NULL]","swapper/5",0
+6824713448438000,6,36000,6824713448474000,630,"S",100,630,"kworker/u17:1",1134
+6824713448474000,6,11000,6824713448485000,669,"S",120,669,"kworker/6:1",14833
+6824713448485000,6,380000,6824713448865000,0,"R",120,"[NULL]","swapper/5",0
+6824713448651000,7,12000,6824713448663000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713448663000,7,456000,6824713449119000,0,"R",120,"[NULL]","swapper/5",0
+6824713448865000,6,23000,6824713448888000,630,"S",100,630,"kworker/u17:1",1134
+6824713448888000,6,11000,6824713448899000,669,"S",120,669,"kworker/6:1",14833
+6824713448899000,6,269000,6824713449168000,0,"R",120,"[NULL]","swapper/5",0
+6824713449119000,7,15000,6824713449134000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713449134000,7,353000,6824713449487000,0,"R",120,"[NULL]","swapper/5",0
+6824713449168000,6,27000,6824713449195000,630,"S",100,630,"kworker/u17:1",1134
+6824713449195000,6,48000,6824713449243000,0,"R",120,"[NULL]","swapper/5",0
+6824713449243000,6,29000,6824713449272000,630,"S",100,630,"kworker/u17:1",1134
+6824713449272000,6,15000,6824713449287000,669,"S",120,669,"kworker/6:1",14833
+6824713449287000,6,389000,6824713449676000,0,"R",120,"[NULL]","swapper/5",0
+6824713449487000,7,38000,6824713449525000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713449525000,7,2642000,6824713452167000,0,"R",120,"[NULL]","swapper/5",0
+6824713449676000,6,51000,6824713449727000,739,"S",120,739,"adbd",20305
+6824713449727000,6,349000,6824713450076000,0,"R",120,"[NULL]","swapper/5",0
+6824713450016000,2,95000,6824713450111000,5,"S",120,5,"rcu_preempt",7
+6824713450076000,6,87000,6824713450163000,38,"S",120,38,"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,5,"S",120,5,"rcu_preempt",7
+6824713450401000,5,6481000,6824713456882000,0,"R",120,"[NULL]","swapper/5",0
+6824713452167000,7,26000,6824713452193000,2728,"S",120,739,"shell",20461
+6824713452193000,7,989000,6824713453182000,0,"R",120,"[NULL]","swapper/5",0
+6824713452362000,6,87000,6824713452449000,739,"S",120,739,"adbd",20305
+6824713452449000,6,485000,6824713452934000,0,"R",120,"[NULL]","swapper/5",0
+6824713452934000,6,35000,6824713452969000,630,"S",100,630,"kworker/u17:1",1134
+6824713452969000,6,12000,6824713452981000,669,"S",120,669,"kworker/6:1",14833
+6824713452981000,6,601000,6824713453582000,0,"R",120,"[NULL]","swapper/5",0
+6824713453182000,7,12000,6824713453194000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713453194000,7,648000,6824713453842000,0,"R",120,"[NULL]","swapper/5",0
+6824713453582000,6,35000,6824713453617000,630,"S",100,630,"kworker/u17:1",1134
+6824713453617000,6,11000,6824713453628000,669,"S",120,669,"kworker/6:1",14833
+6824713453628000,6,571000,6824713454199000,0,"R",120,"[NULL]","swapper/5",0
+6824713453842000,7,15000,6824713453857000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713453857000,7,551000,6824713454408000,0,"R",120,"[NULL]","swapper/5",0
+6824713454199000,6,30000,6824713454229000,630,"S",100,630,"kworker/u17:1",1134
+6824713454229000,6,15000,6824713454244000,669,"S",120,669,"kworker/6:1",14833
+6824713454244000,6,182000,6824713454426000,0,"R",120,"[NULL]","swapper/5",0
+6824713454408000,7,40000,6824713454448000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713454426000,6,45000,6824713454471000,739,"S",120,739,"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,2728,"S",120,739,"shell",20461
+6824713455964000,7,1116000,6824713457080000,0,"R",120,"[NULL]","swapper/5",0
+6824713456168000,6,83000,6824713456251000,739,"S",120,739,"adbd",20305
+6824713456251000,6,535000,6824713456786000,0,"R",120,"[NULL]","swapper/5",0
+6824713456565000,4,16000,6824713456581000,716,"S",120,716,"kworker/4:1",19875
+6824713456581000,4,3324000,6824713459905000,2729,"R",120,758,"ps",20464
+6824713456786000,6,36000,6824713456822000,630,"S",100,630,"kworker/u17:1",1134
+6824713456822000,6,11000,6824713456833000,669,"S",120,669,"kworker/6:1",14833
+6824713456833000,6,411000,6824713457244000,0,"R",120,"[NULL]","swapper/5",0
+6824713456882000,5,15000,6824713456897000,5,"S",120,5,"rcu_preempt",7
+6824713456897000,5,644000,6824713457541000,0,"R",120,"[NULL]","swapper/5",0
+6824713457080000,7,12000,6824713457092000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713457092000,7,408000,6824713457500000,0,"R",120,"[NULL]","swapper/5",0
+6824713457244000,6,70000,6824713457314000,38,"S",120,38,"rcuop/4",44
+6824713457314000,6,585000,6824713457899000,0,"R",120,"[NULL]","swapper/5",0
+6824713457500000,7,44000,6824713457544000,630,"S",100,630,"kworker/u17:1",1134
+6824713457541000,5,8000,6824713457549000,5,"S",120,5,"rcu_preempt",7
+6824713457544000,7,12000,6824713457556000,668,"S",120,668,"kworker/7:2",14813
+6824713457549000,5,2749000,6824713460298000,0,"R",120,"[NULL]","swapper/5",0
+6824713457556000,7,13000,6824713457569000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713457569000,7,270000,6824713457839000,0,"R",120,"[NULL]","swapper/5",0
+6824713457839000,7,32000,6824713457871000,630,"S",100,630,"kworker/u17:1",1134
+6824713457871000,7,12000,6824713457883000,668,"S",120,668,"kworker/7:2",14813
+6824713457883000,7,36000,6824713457919000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713457899000,6,46000,6824713457945000,739,"S",120,739,"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,716,"S",120,716,"kworker/4:1",19875
+6824713459919000,4,6161000,6824713466080000,2729,"I",120,758,"ps",20464
+6824713460102000,7,30000,6824713460132000,2728,"S",120,739,"shell",20461
+6824713460132000,7,539000,6824713460671000,0,"R",120,"[NULL]","swapper/5",0
+6824713460298000,5,97000,6824713460395000,739,"S",120,739,"adbd",20305
+6824713460395000,5,1447000,6824713461842000,0,"R",120,"[NULL]","swapper/5",0
+6824713460671000,7,35000,6824713460706000,630,"S",100,630,"kworker/u17:1",1134
+6824713460706000,7,8000,6824713460714000,668,"S",120,668,"kworker/7:2",14813
+6824713460714000,7,9000,6824713460723000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713460723000,7,306000,6824713461029000,0,"R",120,"[NULL]","swapper/5",0
+6824713461029000,7,22000,6824713461051000,630,"S",100,630,"kworker/u17:1",1134
+6824713461051000,7,8000,6824713461059000,668,"S",120,668,"kworker/7:2",14813
+6824713461059000,7,11000,6824713461070000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713461070000,7,261000,6824713461331000,0,"R",120,"[NULL]","swapper/5",0
+6824713461331000,7,30000,6824713461361000,630,"S",100,630,"kworker/u17:1",1134
+6824713461340000,0,109000,6824713461449000,743,"S",120,743,"kworker/0:5",20371
+6824713461361000,7,250000,6824713461611000,0,"R",120,"[NULL]","swapper/5",0
+6824713461440000,2,373000,6824713461813000,786,"S",111,494,"SDM_EventThread",685
+6824713461449000,0,460000,6824713461909000,0,"R",120,"[NULL]","swapper/5",0
+6824713461611000,7,30000,6824713461641000,630,"S",100,630,"kworker/u17:1",1134
+6824713461641000,7,13000,6824713461654000,668,"S",120,668,"kworker/7:2",14813
+6824713461654000,7,36000,6824713461690000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713461690000,7,2930000,6824713464620000,0,"R",120,"[NULL]","swapper/5",0
+6824713461708000,1,421000,6824713462129000,777,"S",120,493,"HwBinder:640_1",721
+6824713461813000,2,364000,6824713462177000,0,"R",120,"[NULL]","swapper/5",0
+6824713461842000,5,49000,6824713461891000,739,"S",120,739,"adbd",20305
+6824713461891000,5,1341000,6824713463232000,0,"R",120,"[NULL]","swapper/5",0
+6824713461909000,0,68000,6824713461977000,771,"S",97,493,"DispSync",676
+6824713461977000,0,38000,6824713462015000,0,"R",120,"[NULL]","swapper/5",0
+6824713462015000,0,162000,6824713462177000,771,"S",97,493,"DispSync",676
+6824713462129000,1,262000,6824713462391000,0,"R",120,"[NULL]","swapper/5",0
+6824713462177000,2,255000,6824713462432000,773,"S",97,493,"app",678
+6824713462177000,0,142000,6824713462319000,0,"R",120,"[NULL]","swapper/5",0
+6824713462319000,0,1790000,6824713464109000,644,"S",120,644,"ndroid.systemui",1664
+6824713462391000,1,75000,6824713462466000,771,"S",97,493,"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,5,"S",120,5,"rcu_preempt",7
+6824713463241000,5,334000,6824713463575000,0,"R",120,"[NULL]","swapper/5",0
+6824713463575000,5,14000,6824713463589000,5,"S",120,5,"rcu_preempt",7
+6824713463589000,5,243000,6824713463832000,0,"R",120,"[NULL]","swapper/5",0
+6824713463618000,2,521000,6824713464139000,702,"S",120,702,"kworker/u16:7",19422
+6824713463764000,6,70000,6824713463834000,38,"S",120,38,"rcuop/4",44
+6824713463832000,5,5000,6824713463837000,5,"S",120,5,"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,770,"S",120,493,"Binder:640_2",675
+6824713464431000,3,3478000,6824713467909000,0,"R",120,"[NULL]","swapper/5",0
+6824713464597000,0,172000,6824713464769000,773,"S",97,493,"app",678
+6824713464620000,7,27000,6824713464647000,2728,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713464956000,5,693000,6824713465649000,0,"R",120,"[NULL]","swapper/5",0
+6824713465016000,1,91000,6824713465107000,771,"S",97,493,"DispSync",676
+6824713465107000,1,1435000,6824713466542000,0,"R",120,"[NULL]","swapper/5",0
+6824713465229000,7,21000,6824713465250000,630,"S",100,630,"kworker/u17:1",1134
+6824713465250000,7,9000,6824713465259000,668,"S",120,668,"kworker/7:2",14813
+6824713465259000,7,10000,6824713465269000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713465269000,7,284000,6824713465553000,0,"R",120,"[NULL]","swapper/5",0
+6824713465553000,7,29000,6824713465582000,630,"S",100,630,"kworker/u17:1",1134
+6824713465582000,7,689000,6824713466271000,0,"R",120,"[NULL]","swapper/5",0
+6824713465649000,5,20000,6824713465669000,2728,"S",120,739,"shell",20461
+6824713465669000,5,418000,6824713466087000,0,"R",120,"[NULL]","swapper/5",0
+6824713466071000,6,16000,6824713466087000,39,"S",120,39,"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,6,"S",120,6,"rcu_sched",8
+6824713466095000,5,2929000,6824713469024000,0,"R",120,"[NULL]","swapper/5",0
+6824713466271000,7,37000,6824713466308000,630,"S",100,630,"kworker/u17:1",1134
+6824713466308000,7,8000,6824713466316000,668,"S",120,668,"kworker/7:2",14813
+6824713466316000,7,14000,6824713466330000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713466330000,7,308000,6824713466638000,0,"R",120,"[NULL]","swapper/5",0
+6824713466542000,1,3584000,6824713470126000,2721,"I",120,756,"sh",20462
+6824713466638000,7,28000,6824713466666000,630,"S",100,630,"kworker/u17:1",1134
+6824713466666000,7,11000,6824713466677000,668,"S",120,668,"kworker/7:2",14813
+6824713466677000,7,39000,6824713466716000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713466716000,7,622000,6824713467338000,0,"R",120,"[NULL]","swapper/5",0
+6824713466892000,4,113000,6824713467005000,739,"S",120,739,"adbd",20305
+6824713466959000,0,61000,6824713467020000,8,"S",120,8,"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,483,"D",49,483,"sugov:4",606
+6824713467587000,7,70000,6824713467657000,630,"S",100,630,"kworker/u17:1",1134
+6824713467657000,7,50000,6824713467707000,668,"S",120,668,"kworker/7:2",14813
+6824713467707000,7,60000,6824713467767000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713467767000,7,9375000,6824713477142000,0,"R",120,"[NULL]","swapper/5",0
+6824713467909000,3,104000,6824713468013000,77,"S",120,77,"smem_native_rpm",87
+6824713468013000,3,1027000,6824713469040000,0,"R",120,"[NULL]","swapper/5",0
+6824713468153000,4,109000,6824713468262000,630,"R+",100,630,"kworker/u17:1",1134
+6824713468262000,4,82000,6824713468344000,483,"S",49,483,"sugov:4",606
+6824713468344000,4,36000,6824713468380000,716,"R",120,716,"kworker/4:1",19875
+6824713468380000,4,232000,6824713468612000,483,"D",49,483,"sugov:4",606
+6824713468612000,4,48000,6824713468660000,630,"S",100,630,"kworker/u17:1",1134
+6824713468660000,4,23000,6824713468683000,716,"S",120,716,"kworker/4:1",19875
+6824713468683000,4,29000,6824713468712000,0,"R",120,"[NULL]","swapper/5",0
+6824713468712000,4,53000,6824713468765000,630,"S",100,630,"kworker/u17:1",1134
+6824713468765000,4,18000,6824713468783000,716,"S",120,716,"kworker/4:1",19875
+6824713468768000,0,71000,6824713468839000,670,"S",100,670,"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,2487,"S",120,739,"UsbFfs-worker",20308
+6824713469040000,3,71000,6824713469111000,77,"S",120,77,"smem_native_rpm",87
+6824713469046000,4,43000,6824713469089000,739,"S",120,739,"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,483,"S",49,483,"sugov:4",606
+6824713469256000,4,2174000,6824713471430000,0,"R",120,"[NULL]","swapper/5",0
+6824713469747000,2,68000,6824713469815000,9,"S",120,9,"rcuos/0",11
+6824713469815000,2,281000,6824713470096000,0,"R",120,"[NULL]","swapper/5",0
+6824713469919000,5,7000,6824713469926000,6,"S",120,6,"rcu_sched",8
+6824713469926000,5,6000,6824713469932000,5,"S",120,5,"rcu_preempt",7
+6824713469932000,5,770000,6824713470702000,0,"R",120,"[NULL]","swapper/5",0
+6824713470096000,2,3770000,6824713473866000,2720,"I",120,755,"sh",20460
+6824713470126000,1,2368000,6824713472494000,0,"R",120,"[NULL]","swapper/5",0
+6824713470702000,5,43000,6824713470745000,5,"S",120,5,"rcu_preempt",7
+6824713470745000,5,381000,6824713471126000,0,"R",120,"[NULL]","swapper/5",0
+6824713470882000,3,62000,6824713470944000,24,"S",120,24,"rcuop/2",28
+6824713470944000,3,15328000,6824713486272000,0,"R",120,"[NULL]","swapper/5",0
+6824713470980000,6,109000,6824713471089000,38,"S",120,38,"rcuop/4",44
+6824713471089000,6,2971000,6824713474060000,0,"R",120,"[NULL]","swapper/5",0
+6824713471126000,5,89000,6824713471215000,2728,"S",120,739,"shell",20461
+6824713471215000,5,687000,6824713471902000,0,"R",120,"[NULL]","swapper/5",0
+6824713471430000,4,246000,6824713471676000,739,"S",120,739,"adbd",20305
+6824713471676000,4,2529000,6824713474205000,0,"R",120,"[NULL]","swapper/5",0
+6824713471902000,5,68000,6824713471970000,2728,"S",120,739,"shell",20461
+6824713471970000,5,263000,6824713472233000,0,"R",120,"[NULL]","swapper/5",0
+6824713472041000,0,131000,6824713472172000,670,"S",100,670,"kworker/u17:2",14944
+6824713472172000,0,119000,6824713472291000,743,"S",120,743,"kworker/0:5",20371
+6824713472233000,5,23000,6824713472256000,2487,"S",120,739,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713472590000,1,47000,6824713472637000,0,"R",120,"[NULL]","swapper/5",0
+6824713472637000,1,100000,6824713472737000,670,"S",100,670,"kworker/u17:2",14944
+6824713472737000,1,105000,6824713472842000,693,"S",120,693,"kworker/1:1",18800
+6824713472793000,5,17000,6824713472810000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713472799000,0,61000,6824713472860000,670,"S",100,670,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713472979000,0,453000,6824713473432000,0,"R",120,"[NULL]","swapper/5",0
+6824713473109000,5,8000,6824713473117000,25,"S",120,25,"rcuos/2",29
+6824713473117000,5,861000,6824713473978000,0,"R",120,"[NULL]","swapper/5",0
+6824713473432000,0,106000,6824713473538000,670,"S",100,670,"kworker/u17:2",14944
+6824713473538000,0,135000,6824713473673000,743,"S",120,743,"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,2487,"S",120,739,"UsbFfs-worker",20308
+6824713474053000,5,975000,6824713475028000,0,"R",120,"[NULL]","swapper/5",0
+6824713474060000,6,244000,6824713474304000,2728,"I",120,739,"shell",20461
+6824713474149000,2,49000,6824713474198000,52,"S",120,52,"rcuop/6",60
+6824713474198000,2,596000,6824713474794000,0,"R",120,"[NULL]","swapper/5",0
+6824713474205000,4,149000,6824713474354000,739,"S",120,739,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713474727000,0,110000,6824713474837000,743,"S",120,743,"kworker/0:5",20371
+6824713474794000,2,81000,6824713474875000,670,"S",100,670,"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,2487,"S",120,739,"UsbFfs-worker",20308
+6824713475041000,5,348000,6824713475389000,0,"R",120,"[NULL]","swapper/5",0
+6824713475064000,2,217000,6824713475281000,670,"S",100,670,"kworker/u17:2",14944
+6824713475281000,2,288000,6824713475569000,694,"S",120,694,"kworker/2:0",18823
+6824713475358000,0,96000,6824713475454000,670,"S",100,670,"kworker/u17:2",14944
+6824713475389000,5,10000,6824713475399000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713475399000,5,31000,6824713475430000,0,"R",120,"[NULL]","swapper/5",0
+6824713475420000,4,11000,6824713475431000,630,"S",100,630,"kworker/u17:1",1134
+6824713475430000,5,7000,6824713475437000,2487,"S",120,739,"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,743,"S",120,743,"kworker/0:5",20371
+6824713475512000,5,39000,6824713475551000,2487,"S",120,739,"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,739,"S",120,739,"adbd",20305
+6824713475788000,1,89000,6824713475877000,670,"S",100,670,"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,670,"S",100,670,"kworker/u17:2",14944
+6824713476618000,5,8000,6824713476626000,5,"S",120,5,"rcu_preempt",7
+6824713476626000,5,41000,6824713476667000,702,"S",120,702,"kworker/u16:7",19422
+6824713476667000,5,361000,6824713477028000,0,"R",120,"[NULL]","swapper/5",0
+6824713476698000,1,154000,6824713476852000,693,"S",120,693,"kworker/1:1",18800
+6824713476792000,6,30000,6824713476822000,6,"S",120,6,"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,2487,"S",120,739,"UsbFfs-worker",20308
+6824713477070000,5,7334000,6824713484404000,0,"R",120,"[NULL]","swapper/5",0
+6824713477142000,7,19000,6824713477161000,39,"S",120,39,"rcuos/4",45
+6824713477161000,7,61280000,6824713538441000,0,"R",120,"[NULL]","swapper/5",0
+6824713477264000,4,40000,6824713477304000,739,"S",120,739,"adbd",20305
+6824713477304000,4,31231000,6824713508535000,0,"R",120,"[NULL]","swapper/5",0
+6824713484404000,5,44000,6824713484448000,5,"S",120,5,"rcu_preempt",7
+6824713484448000,5,365000,6824713484813000,0,"R",120,"[NULL]","swapper/5",0
+6824713484499000,6,23000,6824713484522000,6,"S",120,6,"rcu_sched",8
+6824713484522000,6,6802000,6824713491324000,0,"R",120,"[NULL]","swapper/5",0
+6824713484813000,5,36000,6824713484849000,25,"S",120,25,"rcuos/2",29
+6824713484849000,5,6226000,6824713491075000,0,"R",120,"[NULL]","swapper/5",0
+6824713485756000,2,159000,6824713485915000,9,"S",120,9,"rcuos/0",11
+6824713485758000,0,157000,6824713485915000,8,"S",120,8,"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,17,"S",120,17,"rcuop/1",20
+6824713486272000,3,94000,6824713486366000,18,"S",120,18,"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,5,"S",120,5,"rcu_preempt",7
+6824713491133000,5,6463000,6824713497596000,0,"R",120,"[NULL]","swapper/5",0
+6824713491324000,6,54000,6824713491378000,38,"S",120,38,"rcuop/4",44
+6824713491378000,6,47434000,6824713538812000,0,"R",120,"[NULL]","swapper/5",0
+6824713492438000,2,218000,6824713492656000,52,"S",120,52,"rcuop/6",60
+6824713492440000,3,215000,6824713492655000,24,"S",120,24,"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,743,"S",120,743,"kworker/0:5",20371
+6824713495302000,0,61000,6824713495363000,0,"R",120,"[NULL]","swapper/5",0
+6824713495363000,0,62000,6824713495425000,3,"S",120,3,"ksoftirqd/0",3
+6824713495425000,0,586000,6824713496011000,0,"R",120,"[NULL]","swapper/5",0
+6824713495501000,2,575000,6824713496076000,786,"S",111,494,"SDM_EventThread",685
+6824713496011000,0,264000,6824713496275000,771,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824713496534000,2,458000,6824713496992000,773,"S",97,493,"app",678
+6824713496780000,0,101000,6824713496881000,771,"S",97,493,"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,771,"S",97,493,"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,644,"S",120,644,"ndroid.systemui",1664
+6824713497596000,5,25000,6824713497621000,5,"S",120,5,"rcu_preempt",7
+6824713497621000,5,6805000,6824713504426000,0,"R",120,"[NULL]","swapper/5",0
+6824713499282000,3,328000,6824713499610000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824713499874000,1,154000,6824713500028000,771,"S",97,493,"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,483,"D",49,483,"sugov:4",606
+6824713504740000,5,82000,6824713504822000,5,"S",120,5,"rcu_preempt",7
+6824713504822000,5,26596000,6824713531418000,0,"R",120,"[NULL]","swapper/5",0
+6824713506860000,3,291000,6824713507151000,77,"S",120,77,"smem_native_rpm",87
+6824713506861000,0,290000,6824713507151000,8,"S",120,8,"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,22,"S",120,22,"ksoftirqd/2",25
+6824713507259000,2,10658000,6824713517917000,0,"R",120,"[NULL]","swapper/5",0
+6824713507552000,1,436000,6824713507988000,17,"S",120,17,"rcuop/1",20
+6824713507988000,1,16424000,6824713524412000,0,"R",120,"[NULL]","swapper/5",0
+6824713508535000,4,250000,6824713508785000,483,"S",49,483,"sugov:4",606
+6824713508607000,0,56000,6824713508663000,8,"S",120,8,"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,5,"S",120,5,"rcu_preempt",7
+6824713513035000,0,4264000,6824713517299000,0,"R",120,"[NULL]","swapper/5",0
+6824713517299000,0,410000,6824713517709000,5,"S",120,5,"rcu_preempt",7
+6824713517709000,0,229000,6824713517938000,24,"S",120,24,"rcuop/2",28
+6824713517917000,2,73000,6824713517990000,31,"S",120,31,"rcuop/3",36
+6824713517938000,0,144000,6824713518082000,38,"S",120,38,"rcuop/4",44
+6824713517990000,2,147000,6824713518137000,52,"S",120,52,"rcuop/6",60
+6824713518082000,0,5664000,6824713523746000,0,"R",120,"[NULL]","swapper/5",0
+6824713518137000,2,83000,6824713518220000,45,"S",120,45,"rcuop/5",52
+6824713518220000,2,10550000,6824713528770000,0,"R",120,"[NULL]","swapper/5",0
+6824713523746000,0,88000,6824713523834000,5,"S",120,5,"rcu_preempt",7
+6824713523834000,0,154000,6824713523988000,8,"R+",120,8,"rcuop/0",10
+6824713523988000,0,28000,6824713524016000,5,"S",120,5,"rcu_preempt",7
+6824713524016000,0,43000,6824713524059000,8,"S",120,8,"rcuop/0",10
+6824713524059000,0,4757000,6824713528816000,0,"R",120,"[NULL]","swapper/5",0
+6824713524412000,1,87000,6824713524499000,17,"S",120,17,"rcuop/1",20
+6824713524499000,1,4727000,6824713529226000,0,"R",120,"[NULL]","swapper/5",0
+6824713528770000,2,179000,6824713528949000,22,"S",120,22,"ksoftirqd/2",25
+6824713528816000,0,175000,6824713528991000,743,"S",120,743,"kworker/0:5",20371
+6824713528949000,2,1466000,6824713530415000,786,"S",111,494,"SDM_EventThread",685
+6824713528991000,0,531000,6824713529522000,702,"R+",120,702,"kworker/u16:7",19422
+6824713529226000,1,134000,6824713529360000,670,"S",100,670,"kworker/u17:2",14944
+6824713529360000,1,961000,6824713530321000,0,"R",120,"[NULL]","swapper/5",0
+6824713529522000,0,135000,6824713529657000,670,"S",100,670,"kworker/u17:2",14944
+6824713529649000,3,475000,6824713530124000,771,"S",97,493,"DispSync",676
+6824713529657000,0,56000,6824713529713000,743,"R+",120,743,"kworker/0:5",20371
+6824713529713000,0,55000,6824713529768000,670,"S",100,670,"kworker/u17:2",14944
+6824713529768000,0,119000,6824713529887000,743,"R+",120,743,"kworker/0:5",20371
+6824713529887000,0,214000,6824713530101000,670,"S",100,670,"kworker/u17:2",14944
+6824713530101000,0,105000,6824713530206000,743,"S",120,743,"kworker/0:5",20371
+6824713530124000,3,93000,6824713530217000,77,"S",120,77,"smem_native_rpm",87
+6824713530206000,0,40000,6824713530246000,5,"S",120,5,"rcu_preempt",7
+6824713530217000,3,33925000,6824713564142000,0,"R",120,"[NULL]","swapper/5",0
+6824713530246000,0,81000,6824713530327000,702,"S",120,702,"kworker/u16:7",19422
+6824713530321000,1,505000,6824713530826000,773,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824713531340000,0,2759000,6824713534099000,644,"S",120,644,"ndroid.systemui",1664
+6824713531384000,1,2683000,6824713534067000,0,"R",120,"[NULL]","swapper/5",0
+6824713531417000,2,89000,6824713531506000,771,"S",97,493,"DispSync",676
+6824713531418000,5,849000,6824713532267000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713531506000,2,8373000,6824713539879000,0,"R",120,"[NULL]","swapper/5",0
+6824713532267000,5,3668000,6824713535935000,739,"S",120,739,"adbd",20305
+6824713534067000,1,310000,6824713534377000,770,"S",120,493,"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,773,"S",97,493,"app",678
+6824713534720000,0,2286000,6824713537006000,0,"R",120,"[NULL]","swapper/5",0
+6824713534887000,1,85000,6824713534972000,771,"S",97,493,"DispSync",676
+6824713534972000,1,29038000,6824713564010000,0,"R",120,"[NULL]","swapper/5",0
+6824713535935000,5,3107000,6824713539042000,2736,"R+",120,763,"sh",20465
+6824713537006000,0,74000,6824713537080000,5,"S",120,5,"rcu_preempt",7
+6824713537080000,0,59000,6824713537139000,8,"S",120,8,"rcuop/0",10
+6824713537139000,0,2739000,6824713539878000,0,"R",120,"[NULL]","swapper/5",0
+6824713538441000,7,113000,6824713538554000,39,"S",120,39,"rcuos/4",45
+6824713538554000,7,5437000,6824713543991000,0,"R",120,"[NULL]","swapper/5",0
+6824713538812000,6,55000,6824713538867000,6,"S",120,6,"rcu_sched",8
+6824713538867000,6,4782000,6824713543649000,0,"R",120,"[NULL]","swapper/5",0
+6824713539042000,5,1123000,6824713540165000,739,"S",120,739,"adbd",20305
+6824713539878000,0,278000,6824713540156000,38,"R+",120,38,"rcuop/4",44
+6824713539879000,2,332000,6824713540211000,145,"S",120,145,"hwrng",215
+6824713540156000,0,139000,6824713540295000,670,"S",100,670,"kworker/u17:2",14944
+6824713540165000,5,271000,6824713540436000,2736,"R+",120,763,"sh",20465
+6824713540211000,2,1202000,6824713541413000,0,"R",120,"[NULL]","swapper/5",0
+6824713540295000,0,37000,6824713540332000,5,"S",120,5,"rcu_preempt",7
+6824713540332000,0,118000,6824713540450000,743,"S",120,743,"kworker/0:5",20371
+6824713540436000,5,70000,6824713540506000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713540450000,0,46000,6824713540496000,38,"S",120,38,"rcuop/4",44
+6824713540496000,0,316000,6824713540812000,0,"R",120,"[NULL]","swapper/5",0
+6824713540506000,5,886000,6824713541392000,2736,"R",120,763,"sh",20465
+6824713540812000,0,76000,6824713540888000,670,"S",100,670,"kworker/u17:2",14944
+6824713540888000,0,6183000,6824713547071000,0,"R",120,"[NULL]","swapper/5",0
+6824713541392000,5,115000,6824713541507000,670,"S",100,670,"kworker/u17:2",14944
+6824713541413000,2,46000,6824713541459000,145,"S",120,145,"hwrng",215
+6824713541459000,2,6115000,6824713547574000,0,"R",120,"[NULL]","swapper/5",0
+6824713541507000,5,68000,6824713541575000,697,"R+",120,697,"kworker/5:2",19092
+6824713541575000,5,59000,6824713541634000,670,"S",100,670,"kworker/u17:2",14944
+6824713541634000,5,105000,6824713541739000,697,"S",120,697,"kworker/5:2",19092
+6824713541739000,5,246000,6824713541985000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713541985000,5,354000,6824713542339000,739,"R+",120,739,"adbd",20305
+6824713542339000,5,29000,6824713542368000,670,"S",100,670,"kworker/u17:2",14944
+6824713542368000,5,84000,6824713542452000,739,"S",120,739,"adbd",20305
+6824713542452000,5,329000,6824713542781000,2736,"R+",120,763,"sh",20465
+6824713542781000,5,61000,6824713542842000,670,"S",100,670,"kworker/u17:2",14944
+6824713542842000,5,68000,6824713542910000,697,"S",120,697,"kworker/5:2",19092
+6824713542910000,5,36000,6824713542946000,2487,"S",120,739,"UsbFfs-worker",20308
+6824713542946000,5,4105000,6824713547051000,2736,"R",120,763,"sh",20465
+6824713543649000,6,83000,6824713543732000,6,"S",120,6,"rcu_sched",8
+6824713543732000,6,730000,6824713544462000,0,"R",120,"[NULL]","swapper/5",0
+6824713543991000,7,134000,6824713544125000,39,"S",120,39,"rcuos/4",45
+6824713544125000,7,6499000,6824713550624000,0,"R",120,"[NULL]","swapper/5",0
+6824713544380000,4,97000,6824713544477000,46,"S",120,46,"rcuos/5",53
+6824713544462000,6,45000,6824713544507000,6,"S",120,6,"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,5,"S",120,5,"rcu_preempt",7
+6824713547071000,0,137000,6824713547208000,1920,"S",120,667,"Executor-7",14763
+6824713547146000,5,228000,6824713547374000,2737,"R",120,739,"shell",20466
+6824713547208000,0,181000,6824713547389000,38,"S",120,38,"rcuop/4",44
+6824713547374000,5,21000,6824713547395000,5,"S",120,5,"rcu_preempt",7
+6824713547389000,0,13607000,6824713560996000,0,"R",120,"[NULL]","swapper/5",0
+6824713547395000,5,225000,6824713547620000,2737,"S",120,739,"shell",20466
+6824713547574000,2,56000,6824713547630000,45,"S",120,45,"rcuop/5",52
+6824713547620000,5,5690000,6824713553310000,2736,"R",120,763,"sh",20465
+6824713547630000,2,46000,6824713547676000,145,"S",120,145,"hwrng",215
+6824713547676000,2,15043000,6824713562719000,0,"R",120,"[NULL]","swapper/5",0
+6824713550291000,6,80000,6824713550371000,6,"S",120,6,"rcu_sched",8
+6824713550371000,6,24532000,6824713574903000,0,"R",120,"[NULL]","swapper/5",0
+6824713550624000,7,88000,6824713550712000,39,"S",120,39,"rcuos/4",45
+6824713550712000,7,23645000,6824713574357000,0,"R",120,"[NULL]","swapper/5",0
+6824713550971000,4,48000,6824713551019000,46,"S",120,46,"rcuos/5",53
+6824713551019000,4,14066000,6824713565085000,0,"R",120,"[NULL]","swapper/5",0
+6824713553310000,5,86000,6824713553396000,5,"S",120,5,"rcu_preempt",7
+6824713553396000,5,69000,6824713553465000,38,"S",120,38,"rcuop/4",44
+6824713553465000,5,36000,6824713553501000,45,"S",120,45,"rcuop/5",52
+6824713553501000,5,6486000,6824713559987000,2736,"R",120,763,"sh",20465
+6824713559987000,5,57000,6824713560044000,697,"S",120,697,"kworker/5:2",19092
+6824713560044000,5,2577000,6824713562621000,2736,"R+",120,763,"sh",20465
+6824713560996000,0,1098000,6824713562094000,943,"D",100,563,"FileWatcherThre",908
+6824713562094000,0,235000,6824713562329000,743,"S",120,743,"kworker/0:5",20371
+6824713562329000,0,966000,6824713563295000,0,"R",120,"[NULL]","swapper/5",0
+6824713562621000,5,180000,6824713562801000,483,"S",49,483,"sugov:4",606
+6824713562719000,2,997000,6824713563716000,786,"S",111,494,"SDM_EventThread",685
+6824713562801000,5,33000,6824713562834000,38,"S",120,38,"rcuop/4",44
+6824713562834000,5,14000,6824713562848000,5,"S",120,5,"rcu_preempt",7
+6824713562848000,5,3776000,6824713566624000,2736,"R",120,763,"sh",20465
+6824713563295000,0,346000,6824713563641000,771,"S",97,493,"DispSync",676
+6824713563641000,0,888000,6824713564529000,702,"S",120,702,"kworker/u16:7",19422
+6824713563716000,2,72000,6824713563788000,145,"S",120,145,"hwrng",215
+6824713563788000,2,972000,6824713564760000,0,"R",120,"[NULL]","swapper/5",0
+6824713564010000,1,574000,6824713564584000,777,"S",120,493,"HwBinder:640_1",721
+6824713564142000,3,453000,6824713564595000,773,"S",97,493,"app",678
+6824713564529000,0,91000,6824713564620000,743,"S",120,743,"kworker/0:5",20371
+6824713564584000,1,2497000,6824713567081000,0,"R",120,"[NULL]","swapper/5",0
+6824713564595000,3,3222000,6824713567817000,644,"S",120,644,"ndroid.systemui",1664
+6824713564620000,0,1978000,6824713566598000,0,"R",120,"[NULL]","swapper/5",0
+6824713564760000,2,90000,6824713564850000,771,"S",97,493,"DispSync",676
+6824713564850000,2,3091000,6824713567941000,0,"R",120,"[NULL]","swapper/5",0
+6824713565085000,4,514000,6824713565599000,943,"D",100,563,"FileWatcherThre",908
+6824713565599000,4,22373000,6824713587972000,0,"R",120,"[NULL]","swapper/5",0
+6824713566598000,0,117000,6824713566715000,743,"S",120,743,"kworker/0:5",20371
+6824713566624000,5,23000,6824713566647000,5,"S",120,5,"rcu_preempt",7
+6824713566647000,5,2458000,6824713569105000,2736,"S",120,763,"sh",20465
+6824713566715000,0,1121000,6824713567836000,0,"R",120,"[NULL]","swapper/5",0
+6824713567081000,1,530000,6824713567611000,943,"S",100,563,"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,8,"S",120,8,"rcuop/0",10
+6824713567904000,0,700000,6824713568604000,0,"R",120,"[NULL]","swapper/5",0
+6824713567941000,2,390000,6824713568331000,770,"S",120,493,"Binder:640_2",675
+6824713568331000,2,4718000,6824713573049000,0,"R",120,"[NULL]","swapper/5",0
+6824713568604000,0,218000,6824713568822000,773,"S",97,493,"app",678
+6824713568822000,0,11756000,6824713580578000,0,"R",120,"[NULL]","swapper/5",0
+6824713569105000,5,4189000,6824713573294000,2738,"R+",120,764,"atrace",20467
+6824713569129000,1,107000,6824713569236000,771,"S",97,493,"DispSync",676
+6824713569236000,1,12634000,6824713581870000,0,"R",120,"[NULL]","swapper/5",0
+6824713573049000,2,113000,6824713573162000,145,"S",120,145,"hwrng",215
+6824713573162000,2,2555000,6824713575717000,0,"R",120,"[NULL]","swapper/5",0
+6824713573294000,5,49000,6824713573343000,5,"S",120,5,"rcu_preempt",7
+6824713573343000,5,37000,6824713573380000,38,"S",120,38,"rcuop/4",44
+6824713573380000,5,23000,6824713573403000,45,"S",120,45,"rcuop/5",52
+6824713573403000,5,6607000,6824713580010000,2738,"R+",120,764,"atrace",20467
+6824713574357000,7,104000,6824713574461000,39,"S",120,39,"rcuos/4",45
+6824713574461000,7,12988000,6824713587449000,0,"R",120,"[NULL]","swapper/5",0
+6824713574903000,6,48000,6824713574951000,6,"S",120,6,"rcu_sched",8
+6824713574951000,6,5495000,6824713580446000,0,"R",120,"[NULL]","swapper/5",0
+6824713575717000,2,111000,6824713575828000,145,"S",120,145,"hwrng",215
+6824713575828000,2,22002000,6824713597830000,0,"R",120,"[NULL]","swapper/5",0
+6824713580010000,5,60000,6824713580070000,5,"S",120,5,"rcu_preempt",7
+6824713580070000,5,3250000,6824713583320000,2738,"R+",120,764,"atrace",20467
+6824713580446000,6,32000,6824713580478000,6,"S",120,6,"rcu_sched",8
+6824713580478000,6,6544000,6824713587022000,0,"R",120,"[NULL]","swapper/5",0
+6824713580578000,0,647000,6824713581225000,702,"D",120,702,"kworker/u16:7",19422
+6824713581225000,0,158000,6824713581383000,8,"S",120,8,"rcuop/0",10
+6824713581383000,0,892000,6824713582275000,0,"R",120,"[NULL]","swapper/5",0
+6824713581760000,3,187000,6824713581947000,77,"S",120,77,"smem_native_rpm",87
+6824713581870000,1,91000,6824713581961000,17,"S",120,17,"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,702,"S",120,702,"kworker/u16:7",19422
+6824713582364000,0,14442000,6824713596806000,0,"R",120,"[NULL]","swapper/5",0
+6824713583320000,5,148000,6824713583468000,483,"S",49,483,"sugov:4",606
+6824713583468000,5,3138000,6824713586606000,2738,"R",120,764,"atrace",20467
+6824713586606000,5,29000,6824713586635000,5,"S",120,5,"rcu_preempt",7
+6824713586635000,5,43000,6824713586678000,38,"S",120,38,"rcuop/4",44
+6824713586678000,5,94000,6824713586772000,45,"S",120,45,"rcuop/5",52
+6824713586772000,5,8000,6824713586780000,5,"S",120,5,"rcu_preempt",7
+6824713586780000,5,6480000,6824713593260000,2738,"R",120,764,"atrace",20467
+6824713587022000,6,46000,6824713587068000,6,"S",120,6,"rcu_sched",8
+6824713587068000,6,1013000,6824713588081000,0,"R",120,"[NULL]","swapper/5",0
+6824713587449000,7,83000,6824713587532000,39,"S",120,39,"rcuos/4",45
+6824713587532000,7,6610000,6824713594142000,0,"R",120,"[NULL]","swapper/5",0
+6824713587972000,4,51000,6824713588023000,46,"S",120,46,"rcuos/5",53
+6824713588023000,4,6549000,6824713594572000,0,"R",120,"[NULL]","swapper/5",0
+6824713588081000,6,24000,6824713588105000,6,"S",120,6,"rcu_sched",8
+6824713588105000,6,5555000,6824713593660000,0,"R",120,"[NULL]","swapper/5",0
+6824713593260000,5,24000,6824713593284000,5,"S",120,5,"rcu_preempt",7
+6824713593284000,5,18000,6824713593302000,38,"S",120,38,"rcuop/4",44
+6824713593302000,5,19000,6824713593321000,45,"S",120,45,"rcuop/5",52
+6824713593321000,5,9953000,6824713603274000,2738,"R",120,764,"atrace",20467
+6824713593660000,6,42000,6824713593702000,6,"S",120,6,"rcu_sched",8
+6824713593702000,6,41271000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
+6824713594142000,7,54000,6824713594196000,39,"S",120,39,"rcuos/4",45
+6824713594196000,7,40777000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
+6824713594572000,4,31000,6824713594603000,46,"S",120,46,"rcuos/5",53
+6824713594603000,4,40370000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
+6824713596806000,0,434000,6824713597240000,771,"S",97,493,"DispSync",676
+6824713597240000,0,240000,6824713597480000,743,"S",120,743,"kworker/0:5",20371
+6824713597480000,0,864000,6824713598344000,0,"R",120,"[NULL]","swapper/5",0
+6824713597562000,1,518000,6824713598080000,773,"S",97,493,"app",678
+6824713597830000,2,805000,6824713598635000,786,"S",111,494,"SDM_EventThread",685
+6824713598080000,1,765000,6824713598845000,0,"R",120,"[NULL]","swapper/5",0
+6824713598344000,0,3217000,6824713601561000,644,"S",120,644,"ndroid.systemui",1664
+6824713598504000,3,105000,6824713598609000,771,"S",97,493,"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,777,"S",120,493,"HwBinder:640_1",721
+6824713599401000,1,2173000,6824713601574000,0,"R",120,"[NULL]","swapper/5",0
+6824713599567000,2,90000,6824713599657000,771,"S",97,493,"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,770,"S",120,493,"Binder:640_2",675
+6824713601969000,1,395000,6824713602364000,0,"R",120,"[NULL]","swapper/5",0
+6824713602239000,0,209000,6824713602448000,773,"S",97,493,"app",678
+6824713602364000,1,79000,6824713602443000,771,"S",97,493,"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,483,"S",49,483,"sugov:4",606
+6824713603389000,5,17861000,6824713621250000,2738,"R+",120,764,"atrace",20467
+6824713621250000,5,138000,6824713621388000,483,"S",49,483,"sugov:4",606
+6824713621388000,5,35000,6824713621423000,38,"S",120,38,"rcuop/4",44
+6824713621423000,5,19000,6824713621442000,5,"S",120,5,"rcu_preempt",7
+6824713621442000,5,5171000,6824713626613000,2738,"R",120,764,"atrace",20467
+6824713623222000,2,232000,6824713623454000,145,"S",120,145,"hwrng",215
+6824713623454000,2,5577000,6824713629031000,0,"R",120,"[NULL]","swapper/5",0
+6824713626613000,5,45000,6824713626658000,5,"S",120,5,"rcu_preempt",7
+6824713626658000,5,26000,6824713626684000,38,"S",120,38,"rcuop/4",44
+6824713626684000,5,21000,6824713626705000,45,"S",120,45,"rcuop/5",52
+6824713626705000,5,6000,6824713626711000,5,"S",120,5,"rcu_preempt",7
+6824713626711000,5,282000,6824713626993000,2738,"S",120,764,"atrace",20467
+6824713626993000,5,7817000,6824713634810000,0,"R",120,"[NULL]","swapper/5",0
+6824713629031000,2,2744000,6824713631775000,479,"R+",120,479,"hwservicemanage",602
+6824713629430000,0,258000,6824713629688000,743,"S",120,743,"kworker/0:5",20371
+6824713629688000,0,932000,6824713630620000,786,"R+",111,494,"SDM_EventThread",685
+6824713630376000,1,388000,6824713630764000,771,"S",97,493,"DispSync",676
+6824713630620000,0,466000,6824713631086000,773,"S",97,493,"app",678
+6824713630764000,1,886000,6824713631650000,0,"R",120,"[NULL]","swapper/5",0
+6824713631031000,3,505000,6824713631536000,777,"S",120,493,"HwBinder:640_1",721
+6824713631086000,0,116000,6824713631202000,702,"S",120,702,"kworker/u16:7",19422
+6824713631202000,0,181000,6824713631383000,786,"S",111,494,"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,771,"S",97,493,"DispSync",676
+6824713631713000,1,1737000,6824713633450000,644,"S",120,644,"ndroid.systemui",1664
+6824713631775000,2,255000,6824713632030000,482,"S",49,482,"sugov:0",605
+6824713632030000,2,108000,6824713632138000,479,"S",120,479,"hwservicemanage",602
+6824713632138000,2,437000,6824713632575000,2738,"R+",120,764,"atrace",20467
+6824713632575000,2,334000,6824713632909000,479,"S",120,479,"hwservicemanage",602
+6824713632909000,2,263000,6824713633172000,2738,"R+",120,764,"atrace",20467
+6824713633172000,2,340000,6824713633512000,489,"S",120,489,"atrace@1.0-serv",635
+6824713633450000,1,1179000,6824713634629000,0,"R",120,"[NULL]","swapper/5",0
+6824713633512000,2,169000,6824713633681000,2738,"R+",120,764,"atrace",20467
+6824713633674000,0,213000,6824713633887000,770,"S",120,493,"Binder:640_2",675
+6824713633681000,2,75000,6824713633756000,489,"S",120,489,"atrace@1.0-serv",635
+6824713633756000,2,1217000,6824713634973000,2738,"R",120,764,"atrace",20467
+6824713633887000,0,1086000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
+6824713634629000,1,131000,6824713634760000,773,"S",97,493,"app",678
+6824713634760000,1,213000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
+6824713634810000,5,70000,6824713634880000,5,"S",120,5,"rcu_preempt",7
+6824713634880000,5,39000,6824713634919000,38,"S",120,38,"rcuop/4",44
+6824713634919000,5,54000,6824713634973000,45,"S",120,45,"rcuop/5",52
+6824713634973000,5,0,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
diff --git a/test/trace_processor/parsing/systrace_html.sql b/test/trace_processor/systrace_html.sql
similarity index 100%
rename from test/trace_processor/parsing/systrace_html.sql
rename to test/trace_processor/systrace_html.sql
diff --git a/test/trace_processor/tables/counters_group_by_freq.py b/test/trace_processor/tables/counters_group_by_freq.py
deleted file mode 100644
index daf1775..0000000
--- a/test/trace_processor/tables/counters_group_by_freq.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_cpufreq(ts=1000, freq=3000, cpu=1)
-trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
-trace.add_cpufreq(ts=1003, freq=3000, cpu=1)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/tables/counters_where_cpu.py b/test/trace_processor/tables/counters_where_cpu.py
deleted file mode 100644
index 239390e..0000000
--- a/test/trace_processor/tables/counters_where_cpu.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_cpufreq(ts=1000, freq=3000, cpu=1)
-trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
-trace.add_cpufreq(ts=1002, freq=5000, cpu=2)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/tables/index b/test/trace_processor/tables/index
deleted file mode 100644
index 811c198..0000000
--- a/test/trace_processor/tables/index
+++ /dev/null
@@ -1,35 +0,0 @@
-# Contains tests for the handling of tables by trace processor. The focus of tests here
-# is to check that trace processor is correctly returning and handling constraints on
-# the really important tables in trace processor.
-#
-# Note: It's generally *not* advisable to add tests here. Check the guidance provided by
-# http://perfetto/dev/docs/analysis/trace-processor#diff-tests for choosing which folder
-# to add a new test to.
-
-# Window table
-../../data/android_sched_and_ps.pb smoke_window.sql android_sched_and_ps_smoke_window.out
-
-# Sched table
-../common/synth_1.py filter_sched.sql synth_1_filter_sched.out
-../../data/android_sched_and_ps.pb b119496959.sql android_sched_and_ps_b119496959.out
-../../data/android_sched_and_ps.pb b119301023.sql android_sched_and_ps_b119301023.out
-
-# Counters table
-../common/synth_1.py filter_counter.sql synth_1_filter_counter.out
-../../data/memory_counters.pb b120278869_neg_ts_end.sql memory_counters_b120278869_neg_ts_end.out
-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
-../../data/example_android_trace_30s.pb filter_row_vector.sql filter_row_vector_example_android_trace_30s.out
-../../data/example_android_trace_30s.pb counter_dur.sql counter_dur_example_android_trace_30s.out
-
-# Null printing
-../common/synth_1.py nulls.sql nulls.out
-
-# Thread table
-thread_main_thread.textproto thread_main_thread.sql thread_main_thread.out
-
-# Json output
-../../data/memory_counters.pb trace_metadata trace_metadata.json.out
-
-# Processes as a metric
-process_uids.textproto android_task_names android_task_names.out
diff --git a/test/trace_processor/tables/trace_metadata.json.out b/test/trace_processor/tables/trace_metadata.json.out
deleted file mode 100644
index 0d3f5d0..0000000
--- a/test/trace_processor/tables/trace_metadata.json.out
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "trace_metadata": {
-    "trace_duration_ns": 9519159074,
-    "trace_size_bytes": 6365447,
-    "trace_config_pbtxt": "buffers: {\n  size_kb: 32768\n  fill_policy: UNSPECIFIED\n}\ndata_sources: {\n  config: {\n    name: \"linux.ftrace\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      ftrace_events: \"print\"\n      ftrace_events: \"sched_switch\"\n      ftrace_events: \"rss_stat\"\n      ftrace_events: \"ion_heap_shrink\"\n      ftrace_events: \"ion_heap_grow\"\n      atrace_categories: \"am\"\n      atrace_categories: \"dalvik\"\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 0\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 0\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\ndata_sources: {\n  config: {\n    name: \"linux.process_stats\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 100\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 0\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\ndata_sources: {\n  config: {\n    name: \"linux.sys_stats\"\n    target_buffer: 0\n    trace_duration_ms: 0\n    tracing_session_id: 0\n    ftrace_config: {\n      buffer_size_kb: 0\n      drain_period_ms: 0\n    }\n    chrome_config: {\n      trace_config: \"\"\n    }\n    inode_file_config: {\n      scan_interval_ms: 0\n      scan_delay_ms: 0\n      scan_batch_size: 0\n      do_not_scan: false\n    }\n    process_stats_config: {\n      scan_all_processes_on_start: false\n      record_thread_names: false\n      proc_stats_poll_ms: 0\n    }\n    sys_stats_config: {\n      meminfo_period_ms: 50\n      meminfo_counters: MEMINFO_MEM_AVAILABLE\n      meminfo_counters: MEMINFO_SWAP_CACHED\n      meminfo_counters: MEMINFO_ACTIVE\n      meminfo_counters: MEMINFO_INACTIVE\n      vmstat_period_ms: 0\n      stat_period_ms: 0\n    }\n    heapprofd_config: {\n      sampling_interval_bytes: 0\n      all: false\n      continuous_dump_config: {\n        dump_phase_ms: 0\n        dump_interval_ms: 0\n      }\n    }\n    legacy_config: \"\"\n  }\n}\nduration_ms: 10000\nenable_extra_guardrails: false\nlockdown_mode: LOCKDOWN_UNCHANGED\nstatsd_metadata: {\n  triggering_alert_id: 0\n  triggering_config_uid: 0\n  triggering_config_id: 0\n}\nwrite_into_file: false\nfile_write_period_ms: 0\nmax_file_size_bytes: 0\nguardrail_overrides: {\n  max_upload_per_day_bytes: 0\n}\ndeferred_start: false",
-    "sched_duration_ns": 9452761359
-  }
-}
diff --git a/test/trace_processor/smoke/thread_cpu_time.sql b/test/trace_processor/thread_cpu_time.sql
similarity index 100%
rename from test/trace_processor/smoke/thread_cpu_time.sql
rename to test/trace_processor/thread_cpu_time.sql
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
new file mode 100644
index 0000000..ed48018
--- /dev/null
+++ b/test/trace_processor/thread_cpu_time_example_android_trace_30s.out
@@ -0,0 +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]"
diff --git a/test/trace_processor/tables/thread_main_thread.out b/test/trace_processor/thread_main_thread.out
similarity index 100%
rename from test/trace_processor/tables/thread_main_thread.out
rename to test/trace_processor/thread_main_thread.out
diff --git a/test/trace_processor/tables/thread_main_thread.sql b/test/trace_processor/thread_main_thread.sql
similarity index 100%
rename from test/trace_processor/tables/thread_main_thread.sql
rename to test/trace_processor/thread_main_thread.sql
diff --git a/test/trace_processor/tables/thread_main_thread.textproto b/test/trace_processor/thread_main_thread.textproto
similarity index 100%
rename from test/trace_processor/tables/thread_main_thread.textproto
rename to test/trace_processor/thread_main_thread.textproto
diff --git a/test/trace_processor/thread_time_in_state.out b/test/trace_processor/thread_time_in_state.out
new file mode 100644
index 0000000..7c2ff56
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state.out
@@ -0,0 +1,16 @@
+"ts","tid","cpu","freq","time_ms"
+2,5,0,100,10
+2,5,0,200,10
+3,5,0,100,20
+3,5,0,200,10
+3,7,2,1000,10
+3,11,2,2000,10
+3,12,2,2000,10
+4,5,0,200,20
+4,11,2,2000,20
+4,12,2,2000,20
+5,17,0,100,10
+5,17,0,200,10
+5,17,2,1000,0
+5,17,2,2000,0
+6,17,0,100,20
diff --git a/test/trace_processor/thread_time_in_state.sql b/test/trace_processor/thread_time_in_state.sql
new file mode 100644
index 0000000..5f2574d
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state.sql
@@ -0,0 +1,12 @@
+SELECT
+  ts,
+  tid,
+  CAST(SUBSTR(slices.name, 18) AS int) AS cpu,
+  CAST(key AS int) AS freq,
+  int_value AS time_ms
+FROM slices
+JOIN thread_track ON (slices.track_id = thread_track.id)
+JOIN thread USING (utid)
+JOIN args USING (arg_set_id)
+WHERE slices.name LIKE "time_in_state.%"
+ORDER BY ts, tid, cpu, key;
diff --git a/test/trace_processor/thread_time_in_state.textproto b/test/trace_processor/thread_time_in_state.textproto
new file mode 100644
index 0000000..2f431f9
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state.textproto
@@ -0,0 +1,179 @@
+packet {
+  system_info {
+    hz: 100
+  }
+}
+packet {
+  timestamp: 1
+  process_tree {
+    processes {
+      pid: 5
+      ppid: 1
+      cmdline: "com.google.pid5"
+    }
+    threads {
+      tid: 5
+      tgid: 5
+    }
+    threads {
+      tid: 7
+      tgid: 5
+      name: "tid7"
+    }
+    processes {
+      pid: 11
+      ppid: 1
+      cmdline: "com.google.pid11"
+    }
+    threads {
+      tid: 11
+      tgid: 11
+      name: "tid11"
+    }
+    threads {
+      tid: 12
+      tgid: 11
+      name: "tid12"
+    }
+  }
+}
+packet {
+  timestamp: 2
+  process_stats {
+    processes {
+      pid: 5
+      threads {
+        tid: 5
+        cpu_freq_indices: 1
+        cpu_freq_ticks: 1
+        cpu_freq_indices: 2
+        cpu_freq_ticks: 1
+      }
+    }
+  }
+}
+packet {
+  timestamp: 3
+  process_stats {
+    processes {
+      pid: 5
+      threads {
+        tid: 5
+        cpu_freq_indices: 1
+        cpu_freq_ticks: 2
+        cpu_freq_indices: 2
+        cpu_freq_ticks: 1
+      }
+      threads {
+        tid: 7
+        cpu_freq_indices: 5
+        cpu_freq_ticks: 1
+      }
+    }
+    processes {
+      pid: 11
+      threads {
+        tid: 11
+        cpu_freq_indices: 6
+        cpu_freq_ticks: 1
+      }
+      threads {
+        tid: 12
+        cpu_freq_indices: 6
+        cpu_freq_ticks: 1
+      }
+    }
+  }
+}
+packet {
+  timestamp: 4
+  process_stats {
+    processes {
+      pid: 5
+      threads {
+        tid: 5
+        # cpu_freq_indices: 1 was skipped because it did not change.
+        cpu_freq_indices: 2
+        cpu_freq_ticks: 2
+      }
+    }
+    processes {
+      pid: 11
+      threads {
+        tid: 11
+        cpu_freq_indices: 6
+        cpu_freq_ticks: 2
+      }
+      threads {
+        tid: 12
+        cpu_freq_indices: 6
+        cpu_freq_ticks: 2
+      }
+    }
+  }
+}
+packet {
+  timestamp: 5
+  process_tree {
+    processes {
+      pid: 17
+      ppid: 1
+      cmdline: "com.google.pid17"
+    }
+    threads {
+      tid: 17
+      tgid: 17
+    }
+  }
+}
+packet {
+  timestamp: 5
+  process_stats {
+    processes {
+      pid: 17
+      threads {
+        tid: 17
+        cpu_freq_indices: 1
+        cpu_freq_ticks: 1
+        cpu_freq_indices: 2
+        cpu_freq_ticks: 1
+        cpu_freq_full: true
+      }
+    }
+  }
+}
+packet {
+  timestamp: 6
+  process_stats {
+    processes {
+      pid: 17
+      threads {
+        tid: 17
+        cpu_freq_indices: 1
+        cpu_freq_ticks: 2
+        # cpu_freq_indices: 2 was skipped because it did not change.
+      }
+    }
+  }
+}
+packet {
+  timestamp: 1
+  cpu_info {
+    cpus {
+      frequencies: 100
+      frequencies: 200
+    }
+    cpus {
+      frequencies: 100
+      frequencies: 200
+    }
+    cpus {
+      frequencies: 1000
+      frequencies: 2000
+    }
+    cpus {
+      frequencies: 1000
+      frequencies: 2000
+    }
+  }
+}
diff --git a/test/trace_processor/thread_time_in_state_annotations.out b/test/trace_processor/thread_time_in_state_annotations.out
new file mode 100644
index 0000000..55243be
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state_annotations.out
@@ -0,0 +1,8 @@
+
+
+"track_type","track_name","ts","dur","upid","value"
+"counter","Total unknown core cycles / sec",3000000000,1000000000,0,33000
+"counter","Thread 10 (1) (unknown core)",3000000000,1000000000,1,22000
+"counter","Thread 20 (3) (unknown core)",3000000000,1000000000,2,11000
+"counter","Thread 10 (1) (unknown core)",2000000000,1000000000,1,1100
+"counter","Total unknown core cycles / sec",2000000000,1000000000,0,1100
diff --git a/test/trace_processor/thread_time_in_state_annotations.py b/test/trace_processor/thread_time_in_state_annotations.py
new file mode 100644
index 0000000..e26e22e
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state_annotations.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+# Since we do various time based conversions to build cycles/sec, ensure that
+# the timestamps look a bit realistic so they don't make those results look
+# weird.
+SEC = 1000000000
+
+trace = synth_common.create_trace()
+
+trace.add_system_info(arch='x86_64')
+trace.packet.system_info.hz = 1
+
+trace.add_packet(1)
+trace.add_cpu([100, 200])
+trace.add_cpu([1000, 2000])
+
+trace.add_packet(1 * SEC)
+trace.add_process_stats(pid=1, freqs={1: 1, 2: 1, 3: 1, 4: 1})
+trace.add_process_stats(pid=2, freqs={1: 1, 2: 1, 3: 1, 4: 1})
+
+trace.add_packet(2 * SEC)
+trace.add_process_stats(pid=1, freqs={1: 2, 3: 2})
+# Don't log anything for pid=2 thread, test that the packet at t=3 is based
+# against t=2 anyway.
+
+trace.add_packet(3 * SEC)
+trace.add_process_stats(pid=1, freqs={2: 11, 4: 11})
+trace.add_process_stats(pid=2, freqs={1: 11, 3: 11})
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/thread_time_in_state_annotations.sql b/test/trace_processor/thread_time_in_state_annotations.sql
new file mode 100644
index 0000000..be86992
--- /dev/null
+++ b/test/trace_processor/thread_time_in_state_annotations.sql
@@ -0,0 +1,21 @@
+--
+-- Copyright 2020 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     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 so that RUN_METRIC will run without outputting any rows.
+CREATE TABLE TEST_TMP AS
+SELECT RUN_METRIC('android/android_thread_time_in_state.sql');
+DROP TABLE TEST_TMP;
+
+SELECT * FROM android_thread_time_in_state_annotations;
diff --git a/test/trace_processor/parsing/trace_size.sql b/test/trace_processor/trace_size.sql
similarity index 100%
rename from test/trace_processor/parsing/trace_size.sql
rename to test/trace_processor/trace_size.sql
diff --git a/test/trace_processor/track_event/flow_events.sql b/test/trace_processor/track_event/flow_events.sql
deleted file mode 100644
index 11ef1a9..0000000
--- a/test/trace_processor/track_event/flow_events.sql
+++ /dev/null
@@ -1,18 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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 t1.name as slice_out, t2.name as slice_in from flow t
-join slice t1 on t.slice_out == t1.slice_id
-join slice t2 on t.slice_in == t2.slice_id;
diff --git a/test/trace_processor/track_event/flow_events_proto_v1.out b/test/trace_processor/track_event/flow_events_proto_v1.out
deleted file mode 100644
index b9283ed..0000000
--- a/test/trace_processor/track_event/flow_events_proto_v1.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"slice_out","slice_in"
-"FlowBeginSlice","FlowEndSlice_1"
-"FlowEndSlice_1","FlowStepSlice"
-"FlowStepSlice","FlowEndSlice_2"
diff --git a/test/trace_processor/track_event/flow_events_proto_v1.textproto b/test/trace_processor/track_event/flow_events_proto_v1.textproto
deleted file mode 100644
index 19c1265..0000000
--- a/test/trace_processor/track_event/flow_events_proto_v1.textproto
+++ /dev/null
@@ -1,142 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 2
-    thread {
-      pid: 2
-      tid: 2
-      thread_name: "t2"
-    }
-  }
-}
-packet {
-  timestamp: 10000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowBeginSlice"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 10000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "Flow330"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      phase: 115 # 's'
-      unscoped_id: 330
-    }
-  }
-}
-packet {
-  timestamp: 29999
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "Flow330"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      phase: 102 # 'f'
-      unscoped_id: 330
-    }
-  }
-}
-packet {
-  timestamp: 30000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowEndSlice_1"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 30001
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "Flow331"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      phase: 115 # 's'
-      unscoped_id: 331
-    }
-  }
-}
-packet {
-  timestamp: 50000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowStepSlice"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 50100
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "Flow331"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      phase: 116 # 't'
-      unscoped_id: 331
-    }
-  }
-}
-packet {
-  timestamp: 55000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowEndSlice_2"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 55100
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "Flow331"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      phase: 102 # 'f'
-      bind_to_enclosing: true
-      unscoped_id: 331
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/track_event/flow_events_proto_v2.out b/test/trace_processor/track_event/flow_events_proto_v2.out
deleted file mode 100644
index a8e6334..0000000
--- a/test/trace_processor/track_event/flow_events_proto_v2.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"slice_out","slice_in"
-"FlowBeginSlice","FlowEndSlice_1"
-"FlowBeginSlice","FlowStepSlice"
-"FlowStepSlice","FlowEndSlice_2"
diff --git a/test/trace_processor/track_event/flow_events_proto_v2.textproto b/test/trace_processor/track_event/flow_events_proto_v2.textproto
deleted file mode 100644
index d4312da..0000000
--- a/test/trace_processor/track_event/flow_events_proto_v2.textproto
+++ /dev/null
@@ -1,84 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 2
-    thread {
-      pid: 2
-      tid: 2
-      thread_name: "t2"
-    }
-  }
-}
-packet {
-  timestamp: 10000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowBeginSlice"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      bind_id: 1
-      flow_direction: FLOW_OUT
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 30000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowEndSlice_1"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      bind_id: 1
-      flow_direction: FLOW_IN
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 50000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowStepSlice"
-    categories: "test"
-    track_uuid: 1
-    legacy_event {
-      bind_id: 1
-      flow_direction: FLOW_INOUT
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 55000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowEndSlice_2"
-    categories: "test"
-    track_uuid: 2
-    legacy_event {
-      bind_id: 1
-      flow_direction: FLOW_IN
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/track_event/flow_events_track_event.out b/test/trace_processor/track_event/flow_events_track_event.out
deleted file mode 100644
index 895f2a1..0000000
--- a/test/trace_processor/track_event/flow_events_track_event.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"slice_out","slice_in"
-"FlowSlice1Start","FlowSlice1End"
-"FlowSlice1Start2Start","FlowSlice1End"
-"FlowSlice1Start2Start","FlowSlice2End"
-"FlowSlice3Begin","FlowSlice3End4Begin"
-"FlowSlice3End4Begin","FlowSlice4Step"
-"FlowSlice4Step","FlowSlice4End"
diff --git a/test/trace_processor/track_event/flow_events_track_event.textproto b/test/trace_processor/track_event/flow_events_track_event.textproto
deleted file mode 100644
index af20150..0000000
--- a/test/trace_processor/track_event/flow_events_track_event.textproto
+++ /dev/null
@@ -1,176 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 2
-    thread {
-      pid: 2
-      tid: 2
-      thread_name: "t2"
-    }
-  }
-}
-packet {
-  timestamp: 10000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice1Start"
-    categories: "test"
-    track_uuid: 1,
-    flow_ids: 1,
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 30000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice1End"
-    categories: "test"
-    track_uuid: 2,
-    terminating_flow_ids: 1,
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 50000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice1Start2Start"
-    categories: "test"
-    track_uuid: 1,
-    flow_ids: 1,
-    flow_ids: 2,
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  timestamp: 55000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice1End"
-    categories: "test"
-    track_uuid: 2,
-    flow_ids: 1,
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-
-packet {
-  timestamp: 58000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice3Begin"
-    categories: "test"
-    track_uuid: 2,
-    flow_ids: 3,
-    legacy_event {
-      phase: 73 # 'I'
-    }
-  }
-}
-packet {
-  timestamp: 59000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice2End"
-    categories: "test"
-    track_uuid: 2,
-    flow_ids: 2,
-    legacy_event {
-      duration_us: 10
-      phase: 88 # 'X'
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 11
-    name: "async"
-  }
-}
-packet {
-  timestamp: 60000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice3End4Begin"
-    categories: "test"
-    track_uuid: 11,
-    terminating_flow_ids: 3,
-    flow_ids: 4,
-    type: 1, # 'TYPE_SLICE_BEGIN'
-  }
-}
-packet {
-  timestamp: 61000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice4Step"
-    categories: "test"
-    track_uuid: 11,
-    flow_ids: 4,
-    type: 3, # 'TYPE_SLICE_INSTANT'
-  }
-}
-packet {
-  timestamp: 62000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice3End4Begin"
-    categories: "test"
-    track_uuid: 11,
-    type: 2, # 'TYPE_SLICE_END'
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 13
-    name: "processTrack"
-    process {
-      pid: 3
-      process_name: "processTrack"
-    }
-  }
-}
-packet {
-  timestamp: 65000
-  trusted_packet_sequence_id: 1
-  track_event {
-    name: "FlowSlice4End"
-    categories: "test"
-    track_uuid: 13,
-    terminating_flow_ids: 4,
-    legacy_event {
-      phase: 105  # 'i'
-      instant_event_scope: 2  # SCOPE_PROCESS
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/index b/test/trace_processor/track_event/index
deleted file mode 100644
index d0881e0..0000000
--- a/test/trace_processor/track_event/index
+++ /dev/null
@@ -1,40 +0,0 @@
-# Contains tests on the parsing and ingestion of TrackEvent packets.
-
-# Same tid handling
-track_event_same_tids.textproto ../common/process_tracking.sql track_event_same_tids_threads.out
-track_event_same_tids.textproto track_event_slices.sql track_event_same_tids_slices.out
-
-# Typed args
-track_event_typed_args.textproto track_event_slices.sql track_event_typed_args_slices.out
-track_event_typed_args.textproto track_event_args.sql track_event_typed_args_args.out
-
-# Track handling
-track_event_tracks.textproto track_event_slices.sql track_event_tracks_slices.out
-track_event_tracks.textproto track_event_processes.sql track_event_tracks_processes.out
-
-# Instant events
-track_event_instant.textproto track_event_slices.sql track_event_instant_slices.out
-
-# Legacy async events
-legacy_async_event.textproto track_event_slice_with_args.sql legacy_async_event.out
-
-# Legacy atrace
-track_event_with_atrace.textproto track_event_slices.sql track_event_with_atrace.out
-
-# Debug annotations
-track_event_merged_debug_annotations.textproto track_event_args.sql track_event_merged_debug_annotations_args.out
-
-# Counters
-track_event_counters.textproto track_event_slices.sql track_event_counters_slices.out
-track_event_counters.textproto track_event_counters.sql track_event_counters_counters.out
-
-# Clock handling
-track_event_monotonic_trace_clock.textproto track_event_slices.sql track_event_monotonic_trace_clock_slices.out
-
-# HistogramName interning
-track_event_chrome_histogram_sample.textproto track_event_args.sql track_event_chrome_histogram_sample_args.out
-
-# Flow events importing from proto
-flow_events_track_event.textproto flow_events.sql flow_events_track_event.out
-flow_events_proto_v2.textproto flow_events.sql flow_events_proto_v2.out
-flow_events_proto_v1.textproto flow_events.sql flow_events_proto_v1.out
diff --git a/test/trace_processor/track_event/legacy_async_event.out b/test/trace_processor/track_event/legacy_async_event.out
deleted file mode 100644
index ddf1b1f..0000000
--- a/test/trace_processor/track_event/legacy_async_event.out
+++ /dev/null
@@ -1,15 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name","key","string_value","int_value"
-"name1","[NULL]","[NULL]","[NULL]",1000,7000,"cat","name1","legacy_event.passthrough_utid","[NULL]",1
-"name1","[NULL]","[NULL]","[NULL]",1000,7000,"cat","name1","legacy_event.phase","S","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",1000,7000,"cat","name1","debug.arg1","value1","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",1000,7000,"cat","name1","debug.arg2","value2","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",2000,1000,"cat","name1","legacy_event.passthrough_utid","[NULL]",2
-"name1","[NULL]","[NULL]","[NULL]",2000,1000,"cat","name1","legacy_event.phase","S","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",3000,0,"cat","name1","legacy_event.passthrough_utid","[NULL]",1
-"name1","[NULL]","[NULL]","[NULL]",3000,0,"cat","name1","legacy_event.phase","T","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",3000,0,"cat","name1","debug.arg3","value3","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",3000,0,"cat","name1","debug.step","Step1","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",5000,0,"cat","name1","legacy_event.passthrough_utid","[NULL]",1
-"name1","[NULL]","[NULL]","[NULL]",5000,0,"cat","name1","legacy_event.phase","p","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",5000,0,"cat","name1","debug.step","Step2","[NULL]"
-"name1","[NULL]","[NULL]","[NULL]",5000,0,"cat","name1","debug.arg4","value4","[NULL]"
diff --git a/test/trace_processor/track_event/legacy_async_event.textproto b/test/trace_processor/track_event/legacy_async_event.textproto
deleted file mode 100644
index b47d02c..0000000
--- a/test/trace_processor/track_event/legacy_async_event.textproto
+++ /dev/null
@@ -1,132 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 5
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  # Emitted on tid 1.
-  # BEGIN parent 1
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    debug_annotations {
-      name: "arg1"
-      string_value: "value1"
-    }
-    legacy_event {
-      phase: 83  # 'S'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 5.
-  # BEGIN parent 2
-  trusted_packet_sequence_id: 2
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    legacy_event {
-      phase: 83  # 'S'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 5.
-  # END parent 2
-  trusted_packet_sequence_id: 2
-  timestamp: 3000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    legacy_event {
-      phase: 70  # 'F'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 1.
-  # END parent 1
-  trusted_packet_sequence_id: 1
-  timestamp: 8000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    debug_annotations {
-      name: "arg2"
-      string_value: "value2"
-    }
-    legacy_event {
-      phase: 70  # 'F'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 1.
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    debug_annotations {
-      name: "arg3"
-      string_value: "value3"
-    }
-    debug_annotations {
-      name: "step"
-      string_value: "Step1"
-    }
-    legacy_event {
-      phase: 84  # 'T'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 1.
-  trusted_packet_sequence_id: 1
-  timestamp: 5000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    debug_annotations {
-      name: "arg4"
-      string_value: "value4"
-    }
-    debug_annotations {
-      name: "step"
-      string_value: "Step2"
-    }
-    legacy_event {
-      phase: 112  # 'p'
-      global_id: 1234
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_args.sql b/test/trace_processor/track_event/track_event_args.sql
deleted file mode 100644
index d1d4cc3..0000000
--- a/test/trace_processor/track_event/track_event_args.sql
+++ /dev/null
@@ -1,16 +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 flat_key, key, int_value, string_value from args order by arg_set_id, key asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event/track_event_chrome_histogram_sample.textproto b/test/trace_processor/track_event/track_event_chrome_histogram_sample.textproto
deleted file mode 100644
index c9c9deb..0000000
--- a/test/trace_processor/track_event/track_event_chrome_histogram_sample.textproto
+++ /dev/null
@@ -1,127 +0,0 @@
-# Valid interning of Compositing.Display.DrawToSwapUs.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name_hash: 10
-      sample: 100
-      name_iid: 1
-    }
-  }
-  interned_data {
-    histogram_names {
-      iid: 1
-      name: "Compositing.Display.DrawToSwapUs"
-    }
-  }
-}
-# Valid interning of CompositorLatency.TotalLatency.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name_hash: 20
-      sample: 200
-      name_iid: 2
-    }
-  }
-  interned_data {
-    histogram_names {
-      iid: 2
-      name: "CompositorLatency.TotalLatency"
-    }
-  }
-}
-# Both name_iid and name are set for chrome_histogram_sample: name must not
-# change.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name: "Graphics.Smoothness.Checkerboarding.MainThreadAnimation"
-      name_hash: 30
-      sample: 300
-      name_iid: 3
-    }
-  }
-  interned_data {
-    histogram_names {
-      iid: 3
-      name: "Graphics.Smoothness.Checkerboarding.PinchZoom"
-    }
-  }
-}
-# Invalid interning of CompositorLatency.TotalLatency: wrong iid.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name_hash: 40
-      sample: 400
-      name_iid: 4
-    }
-  }
-  interned_data {
-    histogram_names {
-      iid: 1
-      name: "CompositorLatency.TotalLatency"
-    }
-  }
-}
-# name_iid is not set for chrome_histogram_sample.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name_hash: 50
-      sample: 500
-    }
-  }
-  interned_data {
-    histogram_names {
-      iid: 5
-      name: "CompositorLatency.TotalLatency"
-    }
-  }
-}
-# No name interning.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_event {
-    categories: "disabled-by-default-histogram_samples"
-    type: 3
-    name_iid: 1
-    chrome_histogram_sample {
-      name_hash: 60
-      sample: 600
-      name: "Memory.GPU.PeakMemoryUsage.PageLoad"
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_chrome_histogram_sample_args.out b/test/trace_processor/track_event/track_event_chrome_histogram_sample_args.out
deleted file mode 100644
index c2265c9..0000000
--- a/test/trace_processor/track_event/track_event_chrome_histogram_sample_args.out
+++ /dev/null
@@ -1,24 +0,0 @@
-"flat_key","key","int_value","string_value"
-"is_root_in_scope","is_root_in_scope",1,"[NULL]"
-"source","source","[NULL]","descriptor"
-"source_id","source_id",0,"[NULL]"
-"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","Compositing.Display.DrawToSwapUs"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",10,"[NULL]"
-"chrome_histogram_sample.name_iid","chrome_histogram_sample.name_iid",1,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",100,"[NULL]"
-"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","CompositorLatency.TotalLatency"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",20,"[NULL]"
-"chrome_histogram_sample.name_iid","chrome_histogram_sample.name_iid",2,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",200,"[NULL]"
-"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","Graphics.Smoothness.Checkerboarding.MainThreadAnimation"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",30,"[NULL]"
-"chrome_histogram_sample.name_iid","chrome_histogram_sample.name_iid",3,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",300,"[NULL]"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",40,"[NULL]"
-"chrome_histogram_sample.name_iid","chrome_histogram_sample.name_iid",4,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",400,"[NULL]"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",50,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",500,"[NULL]"
-"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","Memory.GPU.PeakMemoryUsage.PageLoad"
-"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",60,"[NULL]"
-"chrome_histogram_sample.sample","chrome_histogram_sample.sample",600,"[NULL]"
diff --git a/test/trace_processor/track_event/track_event_counters.sql b/test/trace_processor/track_event/track_event_counters.sql
deleted file mode 100644
index ffa5d57..0000000
--- a/test/trace_processor/track_event/track_event_counters.sql
+++ /dev/null
@@ -1,31 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  counter_track.name as counter_name,
-  process.name as process,
-  thread.name as thread,
-  thread_process.name as thread_process,
-  counter_track.unit as unit,
-  counter.ts,
-  counter.value
-from counter
-left join counter_track on counter.track_id = counter_track.id
-left join process_counter_track on counter.track_id = process_counter_track.id
-left join process on process_counter_track.upid = process.upid
-left join thread_counter_track on counter.track_id = thread_counter_track.id
-left join thread on thread_counter_track.utid = thread.utid
-left join process thread_process on thread.upid = thread_process.upid
-order by ts asc;
diff --git a/test/trace_processor/track_event/track_event_counters.textproto b/test/trace_processor/track_event/track_event_counters.textproto
deleted file mode 100644
index 53c479c..0000000
--- a/test/trace_processor/track_event/track_event_counters.textproto
+++ /dev/null
@@ -1,334 +0,0 @@
-# Sequence 1 defaults to track for "t1" and extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 10  # Counter "c1", defined below.
-    }
-  }
-}
-
-# Process track for the thread.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 3
-    process {
-      pid: 5
-      process_name: "Browser"
-    }
-  }
-}
-
-# Counter track "c1", a thread-scoped counter for "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 10
-    parent_uuid: 1
-    counter {
-      type: 1                # COUNTER_THREAD_TIME_NS.
-      unit_multiplier: 1000  # provided in ys.
-      is_incremental: true   # use delta encoding.
-    }
-  }
-}
-
-# Sequence 2 has no defaults. Define a new global counter "MySizeCounter".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 11
-    name: "MySizeCounter"
-    counter {
-      unit: 3  # UNIT_SIZE_BYTES.
-    }
-  }
-}
-
-# Should appear on default track "t1" with extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 1000  # First value, so effectively absolute.
-  }
-}
-
-# End for event above.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 1100
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 1010.
-  }
-}
-
-# Resetting incremental state on sequence 1 will restart counter at 0.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 10  # Counter "c1", defined below.
-    }
-  }
-}
-
-# Reemit process track for the thread.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_descriptor {
-    uuid: 3
-    process {
-      pid: 5
-      process_name: "Browser"
-    }
-  }
-}
-
-# Reemit counter descriptor, too.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_descriptor {
-    uuid: 10
-    parent_uuid: 1
-    counter {
-      type: 1                # COUNTER_THREAD_TIME_NS.
-      unit_multiplier: 1000  # provided in us.
-      is_incremental: true   # use delta encoding.
-    }
-  }
-}
-
-# Should appear on default track "t1" with extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event2_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 2000  # First value after reset, so absolute.
-  }
-}
-
-# Nested value that happens to be emitted at the same timestamp but different
-# thread time value.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event3_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 10    # Absolute: 2010
-  }
-}
-
-# End for event above.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2200
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 2020.
-  }
-}
-
-# End for event for "event2_on_t1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2200
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 2030.
-  }
-}
-
-# Counter type event for "MySizeCounter" on sequence 1.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    track_uuid: 11       # "MySizeCounter".
-    type: 4              # TYPE_COUNTER.
-    counter_value: 1024  # Absolute.
-  }
-}
-
-# Counter type event for "MySizeCounter" on sequence 2.
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 3100
-  track_event {
-    track_uuid: 11       # "MySizeCounter".
-    type: 4              # TYPE_COUNTER.
-    counter_value: 2048  # Absolute.
-  }
-}
-
-# Override the default extra_counter_values.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4000
-  track_event {
-    categories: "cat"
-    name: "event4_on_t1"
-    type: 3                        # TYPE_INSTANT.
-    extra_counter_track_uuids: 10  # "c1".
-    extra_counter_track_uuids: 11  # "MySizeCounter".
-    extra_counter_values: 10       # Absolute: 2040.
-    extra_counter_values: 1024     # Absolute: 2040.
-  }
-}
-
-# Sequence 3 defaults to track for "t4" and uses legacy thread time and
-# instruction count.
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 4
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 4
-      thread_name: "t4"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 4
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 4000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t3"
-    type: 1                        # TYPE_SLICE_BEGIN.
-    thread_time_absolute_us: 10
-    thread_instruction_count_absolute: 20
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 4100
-  track_event {
-    categories: "cat"
-    name: "event1_on_t3"
-    type: 2                        # TYPE_SLICE_END.
-    thread_time_absolute_us: 15
-    thread_instruction_count_absolute: 25
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4200
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 12
-    name: "MyDoubleCounter"
-    counter {
-    }
-  }
-}
-
-# Floating point counter value.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4200
-  track_event {
-    track_uuid: 12                   # "MyDoubleCounter".
-    type: 4                          # TYPE_COUNTER.
-    double_counter_value: 3.1415926  # Floating point.
-  }
-}
-
-# Floating point extra counter value.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4300
-  track_event {
-    categories: "cat"
-    name: "float_counter_on_t1"
-    type: 3                               # TYPE_INSTANT.
-    extra_double_counter_track_uuids: 12  # "MyDoubleCounter".
-    extra_double_counter_values: 0.5
-  }
-}
-
-# Floating point extra counter value with sequence defaults (used together with
-# an integer counter).
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4400
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 11         # "MySizeCounter"
-      extra_double_counter_track_uuids: 12  # "MyDoubleCounter"
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4500
-  track_event {
-    categories: "cat"
-    name: "float_counter_on_t1"
-    type: 3                        # TYPE_INSTANT.
-    extra_counter_values: 4096
-    extra_double_counter_values: 2.71828
-  }
-}
\ No newline at end of file
diff --git a/test/trace_processor/track_event/track_event_counters_counters.out b/test/trace_processor/track_event/track_event_counters_counters.out
deleted file mode 100644
index 840ffe1..0000000
--- a/test/trace_processor/track_event/track_event_counters_counters.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"counter_name","process","thread","thread_process","unit","ts","value"
-"thread_time","[NULL]","t1","Browser","ns",1000,1000000.000000
-"thread_time","[NULL]","t1","Browser","ns",1100,1010000.000000
-"thread_time","[NULL]","t1","Browser","ns",2000,2000000.000000
-"thread_time","[NULL]","t1","Browser","ns",2000,2010000.000000
-"thread_time","[NULL]","t1","Browser","ns",2200,2020000.000000
-"thread_time","[NULL]","t1","Browser","ns",2200,2030000.000000
-"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",3000,1024.000000
-"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",3100,2048.000000
-"thread_time","[NULL]","t1","Browser","ns",4000,2040000.000000
-"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",4000,1024.000000
-"thread_time","[NULL]","t4","Browser","[NULL]",4000,10000.000000
-"thread_instruction_count","[NULL]","t4","Browser","[NULL]",4000,20.000000
-"thread_time","[NULL]","t4","Browser","[NULL]",4100,15000.000000
-"thread_instruction_count","[NULL]","t4","Browser","[NULL]",4100,25.000000
-"MyDoubleCounter","[NULL]","[NULL]","[NULL]","[NULL]",4200,3.141593
-"MyDoubleCounter","[NULL]","[NULL]","[NULL]","[NULL]",4300,0.500000
-"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",4500,4096.000000
-"MyDoubleCounter","[NULL]","[NULL]","[NULL]","[NULL]",4500,2.718280
diff --git a/test/trace_processor/track_event/track_event_counters_slices.out b/test/trace_processor/track_event/track_event_counters_slices.out
deleted file mode 100644
index cf188ef..0000000
--- a/test/trace_processor/track_event/track_event_counters_slices.out
+++ /dev/null
@@ -1,8 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","Browser",1000,100,"cat","event1_on_t1"
-"[NULL]","[NULL]","t1","Browser",2000,200,"cat","event2_on_t1"
-"[NULL]","[NULL]","t1","Browser",2000,200,"cat","event3_on_t1"
-"[NULL]","[NULL]","t1","Browser",4000,0,"cat","event4_on_t1"
-"[NULL]","[NULL]","t4","Browser",4000,100,"cat","event1_on_t3"
-"[NULL]","[NULL]","t1","Browser",4300,0,"cat","float_counter_on_t1"
-"[NULL]","[NULL]","t1","Browser",4500,0,"cat","float_counter_on_t1"
diff --git a/test/trace_processor/track_event/track_event_instant.textproto b/test/trace_processor/track_event/track_event_instant.textproto
deleted file mode 100644
index 48046a9..0000000
--- a/test/trace_processor/track_event/track_event_instant.textproto
+++ /dev/null
@@ -1,50 +0,0 @@
-# Sequence 1 defaults to track for "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "instant_on_t1"
-    type: 3
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "legacy_instant_on_t1"
-    legacy_event {
-      phase: 73               # 'I'
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    categories: "cat"
-    name: "legacy_mark_on_t1"
-    legacy_event {
-      phase: 82               # 'R'
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_instant_slices.out b/test/trace_processor/track_event/track_event_instant_slices.out
deleted file mode 100644
index 9237f4d..0000000
--- a/test/trace_processor/track_event/track_event_instant_slices.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","instant_on_t1"
-"[NULL]","[NULL]","t1","[NULL]",2000,0,"cat","legacy_instant_on_t1"
-"[NULL]","[NULL]","t1","[NULL]",3000,0,"cat","legacy_mark_on_t1"
diff --git a/test/trace_processor/track_event/track_event_merged_debug_annotations.textproto b/test/trace_processor/track_event/track_event_merged_debug_annotations.textproto
deleted file mode 100644
index 3ad016b..0000000
--- a/test/trace_processor/track_event/track_event_merged_debug_annotations.textproto
+++ /dev/null
@@ -1,133 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 5
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  # Emitted on tid 1.
-  # Should set the legacy_passthrough_utid to utid 1.
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "name1"
-    debug_annotations {
-      name: "debug1"
-      nested_value {
-        nested_type: 1  # DICT
-        dict_keys: "key1"
-        dict_keys: "key2"
-        dict_values {
-          nested_type: 0  # leaf
-          int_value: 10
-        }
-        dict_values {
-          nested_type: 2  # ARRAY
-          array_values {
-            nested_type: 0  # leaf
-            int_value: 20
-          }
-          array_values {
-            nested_type: 0  # leaf
-            int_value: 21
-          }
-        }
-      }
-    }
-    debug_annotations {
-      name: "debug2"
-      legacy_json_value: "{\"key1\": 10, \"key2\": [20, 21],"
-                         " \"key3\": {\"key31\": 31}}"
-    }
-    debug_annotations {
-      name: "debug3"
-      int_value: 31
-    }
-    debug_annotations {
-      name: "debug4"
-      dict_entries {
-        name: "key1"
-        int_value: 10
-      }
-      dict_entries {
-        name: "key2"
-        array_values {
-          int_value: 20
-        }
-        array_values {
-          int_value: 21
-        }
-      }
-    }
-    legacy_event {
-      phase: 98  # 'b'
-      global_id: 1234
-    }
-  }
-}
-packet {
-  # Emitted on tid 5.
-  # Should NOT override the legacy_passthrough_utid from the BEGIN event.
-  trusted_packet_sequence_id: 2
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    debug_annotations {
-      name: "debug1"
-      nested_value {
-        nested_type: 1  # DICT
-        dict_keys: "key3"
-        dict_keys: "key2"
-        dict_values {
-          nested_type: 0  # leaf
-          int_value: 30
-        }
-        dict_values {
-          nested_type: 2  # ARRAY
-          array_values {
-            nested_type: 0  # leaf
-            int_value: 22
-          }
-          array_values {
-            nested_type: 0  # leaf
-            int_value: 23
-          }
-        }
-      }
-    }
-    debug_annotations {
-      name: "debug2"
-      legacy_json_value: "{\"key4\": 40, \"key2\": [22, 23],"
-                         " \"key3\": {\"key32\": 32}}"
-    }
-    debug_annotations {
-      name: "debug3"
-      int_value: 32
-    }
-    legacy_event {
-      phase: 101  # 'e'
-      global_id: 1234
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_merged_debug_annotations_args.out b/test/trace_processor/track_event/track_event_merged_debug_annotations_args.out
deleted file mode 100644
index b0c0529..0000000
--- a/test/trace_processor/track_event/track_event_merged_debug_annotations_args.out
+++ /dev/null
@@ -1,27 +0,0 @@
-"flat_key","key","int_value","string_value"
-"is_root_in_scope","is_root_in_scope",1,"[NULL]"
-"source","source","[NULL]","descriptor"
-"source_id","source_id",1,"[NULL]"
-"source","source","[NULL]","chrome"
-"source_id","source_id",1234,"[NULL]"
-"source_id_is_process_scoped","source_id_is_process_scoped",0,"[NULL]"
-"source_scope","source_scope","[NULL]","cat"
-"debug.debug1.key1","debug.debug1.key1",10,"[NULL]"
-"debug.debug1.key2","debug.debug1.key2[0]",20,"[NULL]"
-"debug.debug1.key2","debug.debug1.key2[1]",21,"[NULL]"
-"debug.debug1.key2","debug.debug1.key2[2]",22,"[NULL]"
-"debug.debug1.key2","debug.debug1.key2[3]",23,"[NULL]"
-"debug.debug1.key3","debug.debug1.key3",30,"[NULL]"
-"debug.debug2.key1","debug.debug2.key1",10,"[NULL]"
-"debug.debug2.key2","debug.debug2.key2[0]",20,"[NULL]"
-"debug.debug2.key2","debug.debug2.key2[1]",21,"[NULL]"
-"debug.debug2.key2","debug.debug2.key2[2]",22,"[NULL]"
-"debug.debug2.key2","debug.debug2.key2[3]",23,"[NULL]"
-"debug.debug2.key3.key31","debug.debug2.key3.key31",31,"[NULL]"
-"debug.debug2.key3.key32","debug.debug2.key3.key32",32,"[NULL]"
-"debug.debug2.key4","debug.debug2.key4",40,"[NULL]"
-"debug.debug3","debug.debug3",32,"[NULL]"
-"debug.debug4.key1","debug.debug4.key1",10,"[NULL]"
-"debug.debug4.key2[0]","debug.debug4.key2[0]",20,"[NULL]"
-"debug.debug4.key2[1]","debug.debug4.key2[1]",21,"[NULL]"
-"legacy_event.passthrough_utid","legacy_event.passthrough_utid",1,"[NULL]"
diff --git a/test/trace_processor/track_event/track_event_monotonic_trace_clock_slices.out b/test/trace_processor/track_event/track_event_monotonic_trace_clock_slices.out
deleted file mode 100644
index 55c67b8..0000000
--- a/test/trace_processor/track_event/track_event_monotonic_trace_clock_slices.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"name1","[NULL]","[NULL]","[NULL]",1000,0,"cat","name1"
-"name1","[NULL]","[NULL]","[NULL]",2000,0,"cat","name2"
diff --git a/test/trace_processor/track_event/track_event_processes.sql b/test/trace_processor/track_event/track_event_processes.sql
deleted file mode 100644
index 316e927..0000000
--- a/test/trace_processor/track_event/track_event_processes.sql
+++ /dev/null
@@ -1,20 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     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
-  id,
-  name,
-  extract_arg(arg_set_id, "chrome.host_app_package_name") as host_app
-from process;
diff --git a/test/trace_processor/track_event/track_event_same_tids_slices.out b/test/trace_processor/track_event/track_event_same_tids_slices.out
deleted file mode 100644
index 0812854..0000000
--- a/test/trace_processor/track_event/track_event_same_tids_slices.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1"
-"[NULL]","[NULL]","t2","[NULL]",2000,0,"cat","name2"
diff --git a/test/trace_processor/track_event/track_event_slice_with_args.sql b/test/trace_processor/track_event/track_event_slice_with_args.sql
deleted file mode 100644
index 8cf8501..0000000
--- a/test/trace_processor/track_event/track_event_slice_with_args.sql
+++ /dev/null
@@ -1,36 +0,0 @@
---
--- Copyright 2021 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.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
-  track.name as track,
-  process.name as process,
-  thread.name as thread,
-  thread_process.name as thread_process,
-  slice.ts,
-  slice.dur,
-  slice.category,
-  slice.name,
-  args.key,
-  args.string_value,
-  args.int_value
-from slice
-left join track on slice.track_id = track.id
-left join process_track on slice.track_id = process_track.id
-left join process on process_track.upid = process.upid
-left join thread_track on slice.track_id = thread_track.id
-left join thread on thread_track.utid = thread.utid
-left join process thread_process on thread.upid = thread_process.upid
-left join args on slice.arg_set_id = args.arg_set_id
-order by ts asc;
diff --git a/test/trace_processor/track_event/track_event_slices.sql b/test/trace_processor/track_event/track_event_slices.sql
deleted file mode 100644
index 8308b16..0000000
--- a/test/trace_processor/track_event/track_event_slices.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.
---
-select
-  track.name as track,
-  process.name as process,
-  thread.name as thread,
-  thread_process.name as thread_process,
-  slice.ts,
-  slice.dur,
-  slice.category,
-  slice.name
-from slice
-left join track on slice.track_id = track.id
-left join process_track on slice.track_id = process_track.id
-left join process on process_track.upid = process.upid
-left join thread_track on slice.track_id = thread_track.id
-left join thread on thread_track.utid = thread.utid
-left join process thread_process on thread.upid = thread_process.upid
-order by ts asc;
diff --git a/test/trace_processor/track_event/track_event_tracks.textproto b/test/trace_processor/track_event/track_event_tracks.textproto
deleted file mode 100644
index c2d3f7e..0000000
--- a/test/trace_processor/track_event/track_event_tracks.textproto
+++ /dev/null
@@ -1,319 +0,0 @@
-# Sequence 1 defaults to track for "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 10
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-    }
-  }
-}
-# Sequence 2 defaults to track for "t2".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 2
-    parent_uuid: 10
-    thread {
-      pid: 5
-      tid: 2
-      thread_name: "t2"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 2
-    }
-  }
-}
-# Both thread tracks are nested underneath this process track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 10
-    process {
-      pid: 5
-      process_name: "p1"
-    }
-    chrome_process {
-      host_app_package_name: "host_app"
-    }
-  }
-}
-# And we have an async track underneath the process too.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 11
-    parent_uuid: 10
-    name: "async"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 100
-  track_descriptor {
-    uuid: 12
-    parent_uuid: 10
-    name: "async2"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 200
-  track_descriptor {
-    uuid: 12
-    parent_uuid: 10
-    name: "async2"
-  }
-}
-
-# Should appear on default track "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t1"
-    type: 3
-  }
-}
-# Should appear on default track "t2".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t2"
-    type: 3
-  }
-}
-# Should appear on overridden track "t2".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    track_uuid: 2
-    categories: "cat"
-    name: "event2_on_t2"
-    type: 3
-  }
-}
-# Should appear on process track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4000
-  track_event {
-    track_uuid: 10
-    categories: "cat"
-    name: "event1_on_p1"
-    type: 3
-  }
-}
-# Should appear on async track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 5000
-  track_event {
-    track_uuid: 11
-    categories: "cat"
-    name: "event1_on_async"
-    type: 3
-  }
-}
-# Event for the "async2" track starting on one thread and ending on another.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 5100
-  track_event {
-    track_uuid: 12
-    categories: "cat"
-    name: "event1_on_async2"
-    type: 1
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 5200
-  track_event {
-    track_uuid: 12
-    categories: "cat"
-    name: "event1_on_async2"
-    type: 2
-  }
-}
-
-# If we later see another track descriptor for tid 1, but with a different uuid,
-# we should detect tid reuse and start a new thread.
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 10000
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 3
-    parent_uuid: 10
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t3"
-    }
-  }
-}
-# Should appear on t3.
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 11000
-  track_event {
-    track_uuid: 3
-    categories: "cat"
-    name: "event1_on_t3"
-    type: 3
-  }
-}
-
-# If we later see another track descriptor for pid 5, but with a different uuid,
-# we should detect pid reuse and start a new process.
-packet {
-  trusted_packet_sequence_id: 4
-  timestamp: 20000
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 20
-    process {
-      pid: 5
-      process_name: "p2"
-    }
-  }
-}
-# Should appear on p2.
-packet {
-  trusted_packet_sequence_id: 4
-  timestamp: 21000
-  track_event {
-    track_uuid: 20
-    categories: "cat"
-    name: "event1_on_p2"
-    type: 3
-  }
-}
-# Another thread t4 in the new process.
-packet {
-  trusted_packet_sequence_id: 4
-  timestamp: 22000
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 21
-    parent_uuid: 20
-    thread {
-      pid: 5
-      tid: 4
-      thread_name: "t4"
-    }
-  }
-}
-# Should appear on t4.
-packet {
-  trusted_packet_sequence_id: 4
-  timestamp: 22000
-  track_event {
-    track_uuid: 21
-    categories: "cat"
-    name: "event1_on_t4"
-    type: 3
-  }
-}
-
-# Another packet for a thread track in the old process, badly sorted.
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 6000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "event3_on_t1"
-    type: 3
-  }
-}
-
-# Override the track to the default descriptor track for an event with a
-# TrackEvent type. Should appear on the default descriptor track instead of
-# "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 30000
-  track_event {
-    track_uuid: 0
-    categories: "cat"
-    name: "event1_on_t1"
-    type: 3
-  }
-}
-
-# But a legacy event without TrackEvent type falls back to legacy tracks (based
-# on ThreadDescriptor / async IDs / legacy instant scopes). This instant event
-# should appear on the process track "p2".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 31000
-  track_event {
-    track_uuid: 0
-    categories: "cat"
-    name: "event2_on_p2"
-    legacy_event {
-      phase: 73               # 'I'
-      instant_event_scope: 2  # Process scope
-    }
-  }
-}
-
-# And pid/tid overrides take effect even for TrackEvent type events.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 32000
-  track_event {
-    track_uuid: 0
-    categories: "cat"
-    name: "event2_on_t4"
-    type: 3
-    legacy_event {
-      pid_override: 5
-      tid_override: 4
-    }
-  }
-}
-
-# Track descriptor without name and process/thread association derives its
-# name from the first event on the track.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 40000
-  track_descriptor {
-    uuid: 13
-    parent_uuid: 10
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 40000
-  track_event {
-    track_uuid: 13
-    categories: "cat"
-    name: "event_and_track_async3"
-    type: 3
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_tracks_processes.out b/test/trace_processor/track_event/track_event_tracks_processes.out
deleted file mode 100644
index cdf3653..0000000
--- a/test/trace_processor/track_event/track_event_tracks_processes.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"id","name","host_app"
-0,"[NULL]","[NULL]"
-1,"p1","host_app"
-2,"p2","[NULL]"
diff --git a/test/trace_processor/track_event/track_event_tracks_slices.out b/test/trace_processor/track_event/track_event_tracks_slices.out
deleted file mode 100644
index d0186cc..0000000
--- a/test/trace_processor/track_event/track_event_tracks_slices.out
+++ /dev/null
@@ -1,15 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","p1",1000,0,"cat","event1_on_t1"
-"[NULL]","[NULL]","t2","p1",2000,0,"cat","event1_on_t2"
-"[NULL]","[NULL]","t2","p1",3000,0,"cat","event2_on_t2"
-"[NULL]","p1","[NULL]","[NULL]",4000,0,"cat","event1_on_p1"
-"async","p1","[NULL]","[NULL]",5000,0,"cat","event1_on_async"
-"async2","p1","[NULL]","[NULL]",5100,100,"cat","event1_on_async2"
-"[NULL]","[NULL]","t1","p1",6000,0,"cat","event3_on_t1"
-"[NULL]","[NULL]","t3","p1",11000,0,"cat","event1_on_t3"
-"[NULL]","p2","[NULL]","[NULL]",21000,0,"cat","event1_on_p2"
-"[NULL]","[NULL]","t4","p2",22000,0,"cat","event1_on_t4"
-"Default Track","[NULL]","[NULL]","[NULL]",30000,0,"cat","event1_on_t1"
-"[NULL]","p2","[NULL]","[NULL]",31000,0,"cat","event2_on_p2"
-"[NULL]","[NULL]","t4","p2",32000,0,"cat","event2_on_t4"
-"event_and_track_async3","p1","[NULL]","[NULL]",40000,0,"cat","event_and_track_async3"
diff --git a/test/trace_processor/track_event/track_event_typed_args.textproto b/test/trace_processor/track_event/track_event_typed_args.textproto
deleted file mode 100644
index 6ff29b1..0000000
--- a/test/trace_processor/track_event/track_event_typed_args.textproto
+++ /dev/null
@@ -1,165 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name1"
-    type: 3
-    chrome_user_event {
-      action: "NewTab"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name2"
-    type: 3
-    chrome_legacy_ipc {
-      message_class: 1
-      message_line: 10
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name3"
-    type: 3
-    chrome_keyed_service {
-      name: "MediaRouter"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name4"
-    type: 3
-    chrome_latency_info {
-      trace_id: 7
-      component_info {
-        component_type: 3
-        time_us: 1201
-      }
-      component_info {
-        time_us: 928310
-      }
-      is_coalesced: true
-    }
-    [perfetto.protos.TestExtension.string_extension_for_testing]:
-        "an extension string!"
-    [perfetto.protos.TestExtension.int_extension_for_testing]: 42
-    [perfetto.protos.TestExtension.int_extension_for_testing]: 1337
-    [perfetto.protos.TestExtension.omitted_extension_for_testing]:
-        "should be absent from result"
-    [perfetto.protos.TestExtension.nested_message_extension_for_testing] {
-      child_field_for_testing: "nesting test"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 5000
-  extension_descriptor {
-    extension_set {
-      file {
-        package: "perfetto.protos"
-        message_type {
-          extension {
-            name: "string_extension_for_testing"
-            extendee: ".perfetto.protos.TrackEvent"
-            number: 9900
-            type: TYPE_STRING
-            label: LABEL_OPTIONAL
-          }
-          extension {
-            name: "int_extension_for_testing"
-            extendee: ".perfetto.protos.TrackEvent"
-            number: 9901
-            type: TYPE_INT32
-            label: LABEL_REPEATED
-          }
-          extension {
-            name: "nested_message_extension_for_testing"
-            extendee: ".perfetto.protos.TrackEvent"
-            number: 9903
-            type: TYPE_MESSAGE
-            label: LABEL_OPTIONAL
-            type_name: ".perfetto.protos.TestExtensionChild"
-          }
-        }
-        message_type {
-          name: "TestExtensionChild"
-          field {
-            name: "child_field_for_testing"
-            number: 1
-            type: TYPE_STRING
-            label: LABEL_OPTIONAL
-          }
-        }
-      }
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 6000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name5"
-    type: 3
-    [perfetto.protos.ChromeTrackEvent.chrome_app_state]: APP_STATE_FOREGROUND
-  }
-}
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 7000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    name: "name6"
-    type: 3
-    source_location_iid: 1
-    [perfetto.protos.ChromeTrackEvent.chrome_memory_pressure_notification] {
-      creation_location_iid: 2
-    }
-  }
-  interned_data: {
-    source_locations: {
-      iid: 1
-      file_name: "source.cc"
-      function_name: "SourceFunction"
-    }
-    source_locations: {
-      iid: 2
-      file_name: "another_source.cc"
-      function_name: "AnotherSourceFunction"
-      line_number: 1337
-    }
-  }
-}
diff --git a/test/trace_processor/track_event/track_event_typed_args_args.out b/test/trace_processor/track_event/track_event_typed_args_args.out
deleted file mode 100644
index ac7d608..0000000
--- a/test/trace_processor/track_event/track_event_typed_args_args.out
+++ /dev/null
@@ -1,25 +0,0 @@
-"flat_key","key","int_value","string_value"
-"is_root_in_scope","is_root_in_scope",1,"[NULL]"
-"source","source","[NULL]","descriptor"
-"source_id","source_id",1,"[NULL]"
-"chrome_user_event.action","chrome_user_event.action","[NULL]","NewTab"
-"chrome_legacy_ipc.message_class","chrome_legacy_ipc.message_class","[NULL]","CLASS_AUTOMATION"
-"chrome_legacy_ipc.message_line","chrome_legacy_ipc.message_line",10,"[NULL]"
-"chrome_keyed_service.name","chrome_keyed_service.name","[NULL]","MediaRouter"
-"chrome_latency_info.component_info.component_type","chrome_latency_info.component_info[0].component_type","[NULL]","COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL"
-"chrome_latency_info.component_info.time_us","chrome_latency_info.component_info[0].time_us",1201,"[NULL]"
-"chrome_latency_info.component_info.time_us","chrome_latency_info.component_info[1].time_us",928310,"[NULL]"
-"chrome_latency_info.is_coalesced","chrome_latency_info.is_coalesced",1,"[NULL]"
-"chrome_latency_info.trace_id","chrome_latency_info.trace_id",7,"[NULL]"
-"int_extension_for_testing","int_extension_for_testing[0]",42,"[NULL]"
-"int_extension_for_testing","int_extension_for_testing[1]",1337,"[NULL]"
-"nested_message_extension_for_testing.child_field_for_testing","nested_message_extension_for_testing.child_field_for_testing","[NULL]","nesting test"
-"string_extension_for_testing","string_extension_for_testing","[NULL]","an extension string!"
-"chrome_app_state","chrome_app_state","[NULL]","APP_STATE_FOREGROUND"
-"chrome_memory_pressure_notification.file_name","chrome_memory_pressure_notification.file_name","[NULL]","another_source.cc"
-"chrome_memory_pressure_notification.function_name","chrome_memory_pressure_notification.function_name","[NULL]","AnotherSourceFunction"
-"chrome_memory_pressure_notification.line_number","chrome_memory_pressure_notification.line_number",1337,"[NULL]"
-"source.file_name","source.file_name","[NULL]","source.cc"
-"source.function_name","source.function_name","[NULL]","SourceFunction"
-"source.line_number","source.line_number",0,"[NULL]"
-"source_location_iid","source_location_iid",1,"[NULL]"
diff --git a/test/trace_processor/track_event/track_event_typed_args_slices.out b/test/trace_processor/track_event/track_event_typed_args_slices.out
deleted file mode 100644
index 1c10497..0000000
--- a/test/trace_processor/track_event/track_event_typed_args_slices.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1"
-"[NULL]","[NULL]","t1","[NULL]",2000,0,"cat","name2"
-"[NULL]","[NULL]","t1","[NULL]",3000,0,"cat","name3"
-"[NULL]","[NULL]","t1","[NULL]",4000,0,"cat","name4"
-"[NULL]","[NULL]","t1","[NULL]",6000,0,"cat","name5"
-"[NULL]","[NULL]","t1","[NULL]",7000,0,"cat","name6"
diff --git a/test/trace_processor/track_event/track_event_with_atrace.out b/test/trace_processor/track_event/track_event_with_atrace.out
deleted file mode 100644
index cb5f333..0000000
--- a/test/trace_processor/track_event/track_event_with_atrace.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"track","process","thread","thread_process","ts","dur","category","name"
-"[NULL]","[NULL]","t1","[NULL]",10000,1000,"cat","event1"
-"[NULL]","[NULL]","t1","[NULL]",20000,8000,"cat","event2"
-"[NULL]","[NULL]","t1","[NULL]",21000,7000,"[NULL]","atrace"
diff --git a/test/trace_processor/track_event_args.sql b/test/trace_processor/track_event_args.sql
new file mode 100644
index 0000000..10187a2
--- /dev/null
+++ b/test/trace_processor/track_event_args.sql
@@ -0,0 +1,16 @@
+--
+-- 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 arg_set_id, flat_key, key, int_value, string_value from args order by arg_set_id, key asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_counters.sql b/test/trace_processor/track_event_counters.sql
new file mode 100644
index 0000000..bfdce7e
--- /dev/null
+++ b/test/trace_processor/track_event_counters.sql
@@ -0,0 +1,32 @@
+--
+-- Copyright 2020 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     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
+  counter_track.name as counter_name,
+  process.name as process,
+  thread.name as thread,
+  thread_process.name as thread_process,
+  counter_track.unit as unit,
+  counter_track.source_arg_set_id as track_args,
+  counter.ts,
+  counter.value
+from counter
+left join counter_track on counter.track_id = counter_track.id
+left join process_counter_track on counter.track_id = process_counter_track.id
+left join process on process_counter_track.upid = process.upid
+left join thread_counter_track on counter.track_id = thread_counter_track.id
+left join thread on thread_counter_track.utid = thread.utid
+left join process thread_process on thread.upid = thread_process.upid
+order by ts asc;
diff --git a/test/trace_processor/track_event_counters.textproto b/test/trace_processor/track_event_counters.textproto
new file mode 100644
index 0000000..decdd68
--- /dev/null
+++ b/test/trace_processor/track_event_counters.textproto
@@ -0,0 +1,245 @@
+# Sequence 1 defaults to track for "t1" and extra_counter_values for "c1".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    parent_uuid: 3
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+  trace_packet_defaults {
+    track_event_defaults {
+      track_uuid: 1
+      extra_counter_track_uuids: 10  # Counter "c1", defined below.
+    }
+  }
+}
+
+# Process track for the thread.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 3
+    process {
+      pid: 5
+      process_name: "p1"
+    }
+  }
+}
+
+# Counter track "c1", a thread-scoped counter for "t1".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 10
+    parent_uuid: 1
+    counter {
+      type: 1                # COUNTER_THREAD_TIME_NS.
+      unit_multiplier: 1000  # provided in ys.
+      is_incremental: true   # use delta encoding.
+    }
+  }
+}
+
+# Sequence 2 has no defaults. Define a new global counter "MySizeCounter".
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 11
+    name: "MySizeCounter"
+    counter {
+      unit: 3  # UNIT_SIZE_BYTES.
+    }
+  }
+}
+
+# Should appear on default track "t1" with extra_counter_values for "c1".
+packet {
+  trusted_packet_sequence_id: 1
+  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
+  timestamp: 1000
+  track_event {
+    categories: "cat"
+    name: "event1_on_t1"
+    type: 1                     # TYPE_SLICE_BEGIN.
+    extra_counter_values: 1000  # First value, so effectively absolute.
+  }
+}
+
+# End for event above.
+packet {
+  trusted_packet_sequence_id: 1
+  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
+  timestamp: 1100
+  track_event {
+    type: 2                   # TYPE_SLICE_END.
+    extra_counter_values: 10  # Absolute: 1010.
+  }
+}
+
+# Resetting incremental state on sequence 1 will restart counter at 0.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    parent_uuid: 3
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+  trace_packet_defaults {
+    track_event_defaults {
+      track_uuid: 1
+      extra_counter_track_uuids: 10  # Counter "c1", defined below.
+    }
+  }
+}
+
+# Reemit process track for the thread.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_descriptor {
+    uuid: 3
+    process {
+      pid: 5
+      process_name: "p1"
+    }
+  }
+}
+
+# Reemit counter descriptor, too.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_descriptor {
+    uuid: 10
+    parent_uuid: 1
+    counter {
+      type: 1                # COUNTER_THREAD_TIME_NS.
+      unit_multiplier: 1000  # provided in ys.
+      is_incremental: true   # use delta encoding.
+    }
+  }
+}
+
+# Should appear on default track "t1" with extra_counter_values for "c1".
+packet {
+  trusted_packet_sequence_id: 1
+  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
+  timestamp: 2000
+  track_event {
+    categories: "cat"
+    name: "event2_on_t1"
+    type: 1                     # TYPE_SLICE_BEGIN.
+    extra_counter_values: 2000  # First value after reset, so absolute.
+  }
+}
+
+# End for event above.
+packet {
+  trusted_packet_sequence_id: 1
+  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
+  timestamp: 2200
+  track_event {
+    type: 2                   # TYPE_SLICE_END.
+    extra_counter_values: 10  # Absolute: 2010.
+  }
+}
+
+# Counter type event for "MySizeCounter" on sequence 1.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    track_uuid: 11       # "MySizeCounter".
+    type: 4              # TYPE_COUNTER.
+    counter_value: 1024  # Absolute.
+  }
+}
+
+# Counter type event for "MySizeCounter" on sequence 2.
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 3100
+  track_event {
+    track_uuid: 11       # "MySizeCounter".
+    type: 4              # TYPE_COUNTER.
+    counter_value: 2048  # Absolute.
+  }
+}
+
+# Override the default extra_counter_values.
+packet {
+  trusted_packet_sequence_id: 1
+  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
+  timestamp: 4000
+  track_event {
+    categories: "cat"
+    name: "event3_on_t1"
+    type: 3                        # TYPE_INSTANT.
+    extra_counter_track_uuids: 10  # "c1".
+    extra_counter_track_uuids: 11  # "MySizeCounter".
+    extra_counter_values: 10       # Absolute: 2020.
+    extra_counter_values: 1024     # Absolute: 2020.
+  }
+}
+
+# Sequence 3 defaults to track for "t4" and uses legacy thread time and
+# instruction count.
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 4
+    parent_uuid: 3
+    thread {
+      pid: 5
+      tid: 4
+      thread_name: "t4"
+    }
+  }
+  trace_packet_defaults {
+    track_event_defaults {
+      track_uuid: 4
+    }
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 4000
+  track_event {
+    categories: "cat"
+    name: "event1_on_t3"
+    type: 1                        # TYPE_SLICE_BEGIN.
+    thread_time_absolute_us: 10
+    thread_instruction_count_absolute: 20
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 4100
+  track_event {
+    categories: "cat"
+    name: "event1_on_t3"
+    type: 2                        # TYPE_SLICE_END.
+    thread_time_absolute_us: 15
+    thread_instruction_count_absolute: 25
+  }
+}
diff --git a/test/trace_processor/track_event_counters_counters.out b/test/trace_processor/track_event_counters_counters.out
new file mode 100644
index 0000000..d5cc7b2
--- /dev/null
+++ b/test/trace_processor/track_event_counters_counters.out
@@ -0,0 +1,13 @@
+"counter_name","process","thread","thread_process","unit","track_args","ts","value"
+"thread_time","[NULL]","t1","p1","ns",1,1000,1000000.000000
+"thread_time","[NULL]","t1","p1","ns",1,1100,1010000.000000
+"thread_time","[NULL]","t1","p1","ns",1,2000,2000000.000000
+"thread_time","[NULL]","t1","p1","ns",1,2200,2010000.000000
+"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",2,3000,1024.000000
+"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",2,3100,2048.000000
+"thread_time","[NULL]","t1","p1","ns",1,4000,2020000.000000
+"MySizeCounter","[NULL]","[NULL]","[NULL]","bytes",2,4000,1024.000000
+"thread_time","[NULL]","t4","p1","[NULL]","[NULL]",4000,10000.000000
+"thread_instruction_count","[NULL]","t4","p1","[NULL]","[NULL]",4000,20.000000
+"thread_time","[NULL]","t4","p1","[NULL]","[NULL]",4100,15000.000000
+"thread_instruction_count","[NULL]","t4","p1","[NULL]","[NULL]",4100,25.000000
diff --git a/test/trace_processor/track_event_counters_slices.out b/test/trace_processor/track_event_counters_slices.out
new file mode 100644
index 0000000..f17c0b4
--- /dev/null
+++ b/test/trace_processor/track_event_counters_slices.out
@@ -0,0 +1,5 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","p1",1000,100,"cat","event1_on_t1",0
+"[NULL]","[NULL]","t1","p1",2000,200,"cat","event2_on_t1",0
+"[NULL]","[NULL]","t1","p1",4000,0,"cat","event3_on_t1",0
+"[NULL]","[NULL]","t4","p1",4000,100,"cat","event1_on_t3",0
diff --git a/test/trace_processor/track_event_merged_debug_annotations.textproto b/test/trace_processor/track_event_merged_debug_annotations.textproto
new file mode 100644
index 0000000..41d3565
--- /dev/null
+++ b/test/trace_processor/track_event_merged_debug_annotations.textproto
@@ -0,0 +1,117 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 5
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  # Emitted on tid 1.
+  # Should set the legacy_passthrough_utid to utid 1.
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    categories: "cat"
+    name: "name1"
+    debug_annotations {
+      name: "debug1"
+      nested_value {
+        nested_type: 1  # DICT
+        dict_keys: "key1"
+        dict_keys: "key2"
+        dict_values {
+          nested_type: 0  # leaf
+          int_value: 10
+        }
+        dict_values {
+          nested_type: 2  # ARRAY
+          array_values {
+            nested_type: 0  # leaf
+            int_value: 20
+          }
+          array_values {
+            nested_type: 0  # leaf
+            int_value: 21
+          }
+        }
+      }
+    }
+    debug_annotations {
+      name: "debug2"
+      legacy_json_value: "{\"key1\": 10, \"key2\": [20, 21],"
+                         " \"key3\": {\"key31\": 31}}"
+    }
+    debug_annotations {
+      name: "debug3"
+      int_value: 31
+    }
+    legacy_event {
+      phase: 98  # 'b'
+      global_id: 1234
+    }
+  }
+}
+packet {
+  # Emitted on tid 5.
+  # Should NOT override the legacy_passthrough_utid from the BEGIN event.
+  trusted_packet_sequence_id: 2
+  timestamp: 2000
+  track_event {
+    categories: "cat"
+    debug_annotations {
+      name: "debug1"
+      nested_value {
+        nested_type: 1  # DICT
+        dict_keys: "key3"
+        dict_keys: "key2"
+        dict_values {
+          nested_type: 0  # leaf
+          int_value: 30
+        }
+        dict_values {
+          nested_type: 2  # ARRAY
+          array_values {
+            nested_type: 0  # leaf
+            int_value: 22
+          }
+          array_values {
+            nested_type: 0  # leaf
+            int_value: 23
+          }
+        }
+      }
+    }
+    debug_annotations {
+      name: "debug2"
+      legacy_json_value: "{\"key4\": 40, \"key2\": [22, 23],"
+                         " \"key3\": {\"key32\": 32}}"
+    }
+    debug_annotations {
+      name: "debug3"
+      int_value: 32
+    }
+    legacy_event {
+      phase: 101  # 'e'
+      global_id: 1234
+    }
+  }
+}
diff --git a/test/trace_processor/track_event_merged_debug_annotations_args.out b/test/trace_processor/track_event_merged_debug_annotations_args.out
new file mode 100644
index 0000000..5cb53f9
--- /dev/null
+++ b/test/trace_processor/track_event_merged_debug_annotations_args.out
@@ -0,0 +1,21 @@
+"arg_set_id","flat_key","key","int_value","string_value"
+1,"source","source","[NULL]","chrome"
+1,"source_id","source_id",1234,"[NULL]"
+1,"source_id_is_process_scoped","source_id_is_process_scoped",0,"[NULL]"
+1,"source_scope","source_scope","[NULL]","cat"
+2,"debug1.key1","debug1.key1",10,"[NULL]"
+2,"debug1.key2","debug1.key2[0]",20,"[NULL]"
+2,"debug1.key2","debug1.key2[1]",21,"[NULL]"
+2,"debug1.key2","debug1.key2[2]",22,"[NULL]"
+2,"debug1.key2","debug1.key2[3]",23,"[NULL]"
+2,"debug1.key3","debug1.key3",30,"[NULL]"
+2,"debug2.key1","debug2.key1",10,"[NULL]"
+2,"debug2.key2","debug2.key2[0]",20,"[NULL]"
+2,"debug2.key2","debug2.key2[1]",21,"[NULL]"
+2,"debug2.key2","debug2.key2[2]",22,"[NULL]"
+2,"debug2.key2","debug2.key2[3]",23,"[NULL]"
+2,"debug2.key3.key31","debug2.key3.key31",31,"[NULL]"
+2,"debug2.key3.key32","debug2.key3.key32",32,"[NULL]"
+2,"debug2.key4","debug2.key4",40,"[NULL]"
+2,"debug3","debug3",32,"[NULL]"
+2,"legacy_event.passthrough_utid","legacy_event.passthrough_utid",1,"[NULL]"
diff --git a/test/trace_processor/track_event/track_event_monotonic_trace_clock.textproto b/test/trace_processor/track_event_monotonic_trace_clock.textproto
similarity index 100%
rename from test/trace_processor/track_event/track_event_monotonic_trace_clock.textproto
rename to test/trace_processor/track_event_monotonic_trace_clock.textproto
diff --git a/test/trace_processor/track_event_monotonic_trace_clock_slices.out b/test/trace_processor/track_event_monotonic_trace_clock_slices.out
new file mode 100644
index 0000000..c3726b6
--- /dev/null
+++ b/test/trace_processor/track_event_monotonic_trace_clock_slices.out
@@ -0,0 +1,3 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"name1","[NULL]","[NULL]","[NULL]",1000,0,"cat","name1",0
+"name1","[NULL]","[NULL]","[NULL]",2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event/track_event_same_tids.textproto b/test/trace_processor/track_event_same_tids.textproto
similarity index 100%
rename from test/trace_processor/track_event/track_event_same_tids.textproto
rename to test/trace_processor/track_event_same_tids.textproto
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
new file mode 100644
index 0000000..d882f13
--- /dev/null
+++ b/test/trace_processor/track_event_same_tids_slices.out
@@ -0,0 +1,3 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1",0
+"[NULL]","[NULL]","t2","[NULL]",2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event/track_event_same_tids_threads.out b/test/trace_processor/track_event_same_tids_threads.out
similarity index 100%
rename from test/trace_processor/track_event/track_event_same_tids_threads.out
rename to test/trace_processor/track_event_same_tids_threads.out
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
new file mode 100644
index 0000000..5146810
--- /dev/null
+++ b/test/trace_processor/track_event_slices.sql
@@ -0,0 +1,33 @@
+--
+-- 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
+  track.name as track,
+  process.name as process,
+  thread.name as thread,
+  thread_process.name as thread_process,
+  slice.ts,
+  slice.dur,
+  slice.category,
+  slice.name,
+  slice.arg_set_id
+from slice
+left join track on slice.track_id = track.id
+left join process_track on slice.track_id = process_track.id
+left join process on process_track.upid = process.upid
+left join thread_track on slice.track_id = thread_track.id
+left join thread on thread_track.utid = thread.utid
+left join process thread_process on thread.upid = thread_process.upid
+order by ts asc;
diff --git a/test/trace_processor/track_event_tracks.textproto b/test/trace_processor/track_event_tracks.textproto
new file mode 100644
index 0000000..65c8401
--- /dev/null
+++ b/test/trace_processor/track_event_tracks.textproto
@@ -0,0 +1,294 @@
+# Sequence 1 defaults to track for "t1".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    parent_uuid: 10
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+  trace_packet_defaults {
+    track_event_defaults {
+      track_uuid: 1
+    }
+  }
+}
+# Sequence 2 defaults to track for "t2".
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 2
+    parent_uuid: 10
+    thread {
+      pid: 5
+      tid: 2
+      thread_name: "t2"
+    }
+  }
+  trace_packet_defaults {
+    track_event_defaults {
+      track_uuid: 2
+    }
+  }
+}
+# Both thread tracks are nested underneath this process track.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 10
+    process {
+      pid: 5
+      process_name: "p1"
+    }
+  }
+}
+# And we have an async track underneath the process too.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 11
+    parent_uuid: 10
+    name: "async"
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 100
+  track_descriptor {
+    uuid: 12
+    parent_uuid: 10
+    name: "async2"
+  }
+}
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 200
+  track_descriptor {
+    uuid: 12
+    parent_uuid: 10
+    name: "async2"
+  }
+}
+
+# Should appear on default track "t1".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    categories: "cat"
+    name: "event1_on_t1"
+    type: 3
+  }
+}
+# Should appear on default track "t2".
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 2000
+  track_event {
+    categories: "cat"
+    name: "event1_on_t2"
+    type: 3
+  }
+}
+# Should appear on overridden track "t2".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    track_uuid: 2
+    categories: "cat"
+    name: "event2_on_t2"
+    type: 3
+  }
+}
+# Should appear on process track.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 4000
+  track_event {
+    track_uuid: 10
+    categories: "cat"
+    name: "event1_on_p1"
+    type: 3
+  }
+}
+# Should appear on async track.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 5000
+  track_event {
+    track_uuid: 11
+    categories: "cat"
+    name: "event1_on_async"
+    type: 3
+  }
+}
+# Event for the "async2" track starting on one thread and ending on another.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 5100
+  track_event {
+    track_uuid: 12
+    categories: "cat"
+    name: "event1_on_async2"
+    type: 1
+  }
+}
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 5200
+  track_event {
+    track_uuid: 12
+    categories: "cat"
+    name: "event1_on_async2"
+    type: 2
+  }
+}
+
+# If we later see another track descriptor for tid 1, but with a different uuid,
+# we should detect tid reuse and start a new thread.
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 10000
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 3
+    parent_uuid: 10
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t3"
+    }
+  }
+}
+# Should appear on t3.
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 11000
+  track_event {
+    track_uuid: 3
+    categories: "cat"
+    name: "event1_on_t3"
+    type: 3
+  }
+}
+
+# If we later see another track descriptor for pid 5, but with a different uuid,
+# we should detect pid reuse and start a new process.
+packet {
+  trusted_packet_sequence_id: 4
+  timestamp: 20000
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 20
+    process {
+      pid: 5
+      process_name: "p2"
+    }
+  }
+}
+# Should appear on p2.
+packet {
+  trusted_packet_sequence_id: 4
+  timestamp: 21000
+  track_event {
+    track_uuid: 20
+    categories: "cat"
+    name: "event1_on_p2"
+    type: 3
+  }
+}
+# Another thread t4 in the new process.
+packet {
+  trusted_packet_sequence_id: 4
+  timestamp: 22000
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 21
+    parent_uuid: 20
+    thread {
+      pid: 5
+      tid: 4
+      thread_name: "t4"
+    }
+  }
+}
+# Should appear on t4.
+packet {
+  trusted_packet_sequence_id: 4
+  timestamp: 22000
+  track_event {
+    track_uuid: 21
+    categories: "cat"
+    name: "event1_on_t4"
+    type: 3
+  }
+}
+
+# Another packet for a thread track in the old process, badly sorted.
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 6000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "event3_on_t1"
+    type: 3
+  }
+}
+
+# Override the track to the default descriptor track for an event with a
+# TrackEvent type. Should appear on the default descriptor track instead of
+# "t1".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 30000
+  track_event {
+    track_uuid: 0
+    categories: "cat"
+    name: "event1_on_t1"
+    type: 3
+  }
+}
+
+# But a legacy event without TrackEvent type falls back to legacy tracks (based
+# on ThreadDescriptor / async IDs / legacy instant scopes). This instant event
+# should appear on the process track "p2".
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 31000
+  track_event {
+    track_uuid: 0
+    categories: "cat"
+    name: "event2_on_p2"
+    legacy_event {
+      phase: 73               # 'I'
+      instant_event_scope: 2  # Process scope
+    }
+  }
+}
+
+# And pid/tid overrides take effect even for TrackEvent type events.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 32000
+  track_event {
+    track_uuid: 0
+    categories: "cat"
+    name: "event2_on_t4"
+    type: 3
+    legacy_event {
+      pid_override: 5
+      tid_override: 4
+    }
+  }
+}
diff --git a/test/trace_processor/track_event_tracks_slices.out b/test/trace_processor/track_event_tracks_slices.out
new file mode 100644
index 0000000..1471f76
--- /dev/null
+++ b/test/trace_processor/track_event_tracks_slices.out
@@ -0,0 +1,14 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","p1",1000,0,"cat","event1_on_t1",0
+"[NULL]","[NULL]","t2","p1",2000,0,"cat","event1_on_t2",0
+"[NULL]","[NULL]","t2","p1",3000,0,"cat","event2_on_t2",0
+"[NULL]","p1","[NULL]","[NULL]",4000,0,"cat","event1_on_p1",3
+"async","p1","[NULL]","[NULL]",5000,0,"cat","event1_on_async",3
+"async2","p1","[NULL]","[NULL]",5100,100,"cat","event1_on_async2",3
+"[NULL]","[NULL]","t1","p1",6000,0,"cat","event3_on_t1",0
+"[NULL]","[NULL]","t3","p1",11000,0,"cat","event1_on_t3",0
+"[NULL]","p2","[NULL]","[NULL]",21000,0,"cat","event1_on_p2",7
+"[NULL]","[NULL]","t4","p2",22000,0,"cat","event1_on_t4",0
+"Default Track","[NULL]","[NULL]","[NULL]",30000,0,"cat","event1_on_t1",0
+"[NULL]","p2","[NULL]","[NULL]",31000,0,"cat","event2_on_p2",6
+"[NULL]","[NULL]","t4","p2",32000,0,"cat","event2_on_t4",0
diff --git a/test/trace_processor/track_event_typed_args.pb b/test/trace_processor/track_event_typed_args.pb
new file mode 100644
index 0000000..c478cb0
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args.pb
Binary files differ
diff --git a/test/trace_processor/track_event_typed_args.textproto b/test/trace_processor/track_event_typed_args.textproto
new file mode 100644
index 0000000..67e37b2
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args.textproto
@@ -0,0 +1,74 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name1"
+    type: 3
+    chrome_user_event {
+      action: "NewTab"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name2"
+    type: 3
+    chrome_legacy_ipc {
+      message_class: 1
+      message_line: 10
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name3"
+    type: 3
+    chrome_keyed_service {
+      name: "MediaRouter"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 4000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name4"
+    type: 3
+    chrome_latency_info {
+      trace_id: 7
+      component_info {
+        component_type: 3
+        time_us: 1201
+      }
+      component_info {
+        time_us: 928310
+      }
+      is_coalesced: true
+    }
+  }
+}
diff --git a/test/trace_processor/track_event_typed_args_args.out b/test/trace_processor/track_event_typed_args_args.out
new file mode 100644
index 0000000..e6d06f7
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_args.out
@@ -0,0 +1,10 @@
+"arg_set_id","flat_key","key","int_value","string_value"
+1,"chrome_user_event.action","chrome_user_event.action","[NULL]","NewTab"
+2,"chrome_legacy_ipc.message_class","chrome_legacy_ipc.message_class","[NULL]","CLASS_AUTOMATION"
+2,"chrome_legacy_ipc.message_line","chrome_legacy_ipc.message_line",10,"[NULL]"
+3,"chrome_keyed_service.name","chrome_keyed_service.name","[NULL]","MediaRouter"
+4,"chrome_latency_info.component_info.component_type","chrome_latency_info.component_info[0].component_type","[NULL]","COMPONENT_INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL"
+4,"chrome_latency_info.component_info.time_us","chrome_latency_info.component_info[0].time_us",1201,"[NULL]"
+4,"chrome_latency_info.component_info.time_us","chrome_latency_info.component_info[1].time_us",928310,"[NULL]"
+4,"chrome_latency_info.is_coalesced","chrome_latency_info.is_coalesced",1,"[NULL]"
+4,"chrome_latency_info.trace_id","chrome_latency_info.trace_id",7,"[NULL]"
diff --git a/test/trace_processor/track_event_typed_args_slices.out b/test/trace_processor/track_event_typed_args_slices.out
new file mode 100644
index 0000000..84026f7
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_slices.out
@@ -0,0 +1,5 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1",1
+"[NULL]","[NULL]","t1","[NULL]",2000,0,"cat","name2",2
+"[NULL]","[NULL]","t1","[NULL]",3000,0,"cat","name3",3
+"[NULL]","[NULL]","t1","[NULL]",4000,0,"cat","name4",4
diff --git a/test/trace_processor/track_event_with_atrace.out b/test/trace_processor/track_event_with_atrace.out
new file mode 100644
index 0000000..5f12ba4
--- /dev/null
+++ b/test/trace_processor/track_event_with_atrace.out
@@ -0,0 +1,4 @@
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","[NULL]",10000,1000,"cat","event1",0
+"[NULL]","[NULL]","t1","[NULL]",20000,8000,"cat","event2",0
+"[NULL]","[NULL]","t1","[NULL]",21000,7000,"[NULL]","atrace",0
diff --git a/test/trace_processor/track_event/track_event_with_atrace.textproto b/test/trace_processor/track_event_with_atrace.textproto
similarity index 100%
rename from test/trace_processor/track_event/track_event_with_atrace.textproto
rename to test/trace_processor/track_event_with_atrace.textproto
diff --git a/test/trace_processor/parsing/trigger_packet_trace.textproto b/test/trace_processor/trigger_packet_trace.textproto
similarity index 100%
rename from test/trace_processor/parsing/trigger_packet_trace.textproto
rename to test/trace_processor/trigger_packet_trace.textproto
diff --git a/test/trace_processor/parsing/triggers_packets.sql b/test/trace_processor/triggers_packets.sql
similarity index 100%
rename from test/trace_processor/parsing/triggers_packets.sql
rename to test/trace_processor/triggers_packets.sql
diff --git a/test/trace_processor/parsing/triggers_packets_trigger_packet_trace.out b/test/trace_processor/triggers_packets_trigger_packet_trace.out
similarity index 100%
rename from test/trace_processor/parsing/triggers_packets_trigger_packet_trace.out
rename to test/trace_processor/triggers_packets_trigger_packet_trace.out
diff --git a/test/trace_processor/parsing/ts_desc_filter.sql b/test/trace_processor/ts_desc_filter.sql
similarity index 100%
rename from test/trace_processor/parsing/ts_desc_filter.sql
rename to test/trace_processor/ts_desc_filter.sql
diff --git a/test/trace_processor/parsing/ts_desc_filter_android_sched_and_ps.out b/test/trace_processor/ts_desc_filter_android_sched_and_ps.out
similarity index 100%
rename from test/trace_processor/parsing/ts_desc_filter_android_sched_and_ps.out
rename to test/trace_processor/ts_desc_filter_android_sched_and_ps.out
diff --git a/test/trace_processor/graphics/vulkan_api_events.out b/test/trace_processor/vulkan_api_events.out
similarity index 100%
rename from test/trace_processor/graphics/vulkan_api_events.out
rename to test/trace_processor/vulkan_api_events.out
diff --git a/test/trace_processor/vulkan_api_events.py b/test/trace_processor/vulkan_api_events.py
new file mode 100644
index 0000000..b279f7a
--- /dev/null
+++ b/test/trace_processor/vulkan_api_events.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+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_vk_queue_submit(
+    ts=10,
+    dur=2,
+    pid=42,
+    tid=43,
+    vk_queue=10,
+    vk_command_buffers=[100],
+    submission_id=1)
+
+trace.add_vk_queue_submit(
+    ts=20,
+    dur=2,
+    pid=44,
+    tid=45,
+    vk_queue=11,
+    vk_command_buffers=[200, 300, 400],
+    submission_id=2)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/vulkan_api_events.sql b/test/trace_processor/vulkan_api_events.sql
similarity index 100%
rename from test/trace_processor/graphics/vulkan_api_events.sql
rename to test/trace_processor/vulkan_api_events.sql
diff --git a/tools/BUILD.gn b/tools/BUILD.gn
index 772f6a2..a018fd4 100644
--- a/tools/BUILD.gn
+++ b/tools/BUILD.gn
@@ -22,14 +22,13 @@
   testonly = true
   deps = [
     ":copy_protoc",
+    ":idle_alloc",
     "compact_reencode",
     "ftrace_proto_gen",
-    "proto_filter",
     "protoprofile",
   ]
   if (is_linux || is_android) {
     deps += [
-      ":idle_alloc",
       "busy_threads",
       "cpu_utilization",
       "dump_ftrace_stats",
@@ -53,22 +52,11 @@
       "../src/profiling/memory:client",
     ]
   }
-
-  executable("multithreaded_alloc") {
-    sources = [ "multithreaded_alloc.cc" ]
-    deps = [
-      "../gn:default_deps",
-      "../src/base",
-      "../src/profiling/memory:client_api_standalone",
-    ]
-  }
 }
 
-if (is_linux || is_android) {
-  executable("idle_alloc") {
-    deps = [ "../gn:default_deps" ]
-    sources = [ "idle_alloc.cc" ]
-  }
+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
diff --git a/tools/add_test_trace.sh b/tools/add_test_trace.sh
index 1eea759..f91551d 100755
--- a/tools/add_test_trace.sh
+++ b/tools/add_test_trace.sh
@@ -52,8 +52,12 @@
 gsutil acl ch -u AllUsers:R gs://perfetto/$NEW_TEST_DATA
 
 echo ""
-echo "SHA-256 of file $NEW_TEST_DATA is"
-NEW_SHA=$(shasum -a 256 /tmp/$NEW_TEST_DATA | cut -c1-64)
+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
+else
+NEW_SHA=$(sha1sum /tmp/$NEW_TEST_DATA | cut -c1-40)  # Linux
+fi
 echo $NEW_SHA
 
 echo ""
@@ -67,7 +71,7 @@
 echo "Updating tools/install-build-deps"
 echo ""
 
-OLD_SHA=$(cat tools/install-build-deps | grep '/test-data-.*.zip' -A1 | tail -n1 | egrep -o '[a-f0-9]+')
+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 \
diff --git a/tools/add_tp_diff_test.py b/tools/add_tp_diff_test.py
deleted file mode 100755
index 83ce9d0..0000000
--- a/tools/add_tp_diff_test.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import argparse
-import os
-import pathlib
-import sys
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def create_if_not_exists(path):
-  create = not os.path.exists(path)
-  if create:
-    print('Creating empty file {}'.format(os.path.relpath(path, ROOT_DIR)))
-    with open(path, 'a'):
-      pass
-  return create
-
-
-def stdout_write(*args, **kwargs):
-  sys.stdout.write(*args, **kwargs)
-  sys.stdout.flush()
-
-
-def main():
-  test_dir = os.path.join(ROOT_DIR, 'test', 'trace_processor')
-  include_index_path = os.path.join(test_dir, 'include_index')
-
-  if not os.path.exists(include_index_path):
-    print('Error: include index does not exist at {}'.format(
-        os.path.relpath(include_index_path, ROOT_DIR)))
-    return 1
-
-  existing_folders = []
-  with open(include_index_path, 'r') as include_index_file:
-    for line in include_index_file.readlines():
-      stripped = line.rstrip()
-      existing_folders.append(stripped.replace('/index', ''))
-
-  print('Pick a folder to add a test to. This can either be an existing '
-        'folder or a new one to create.')
-  print()
-  print('Picking the correct folder is important to the long term health '
-        'of trace processor. For help in this, please see the guidance at '
-        'http://perfetto.dev/docs/analysis/trace-processor#diff-tests')
-  print()
-  print('Existing folders: {}.'.format(existing_folders))
-  stdout_write('Folder: ')
-
-  chosen_folder = sys.stdin.readline().rstrip()
-  chosen_folder_path = os.path.abspath(os.path.join(test_dir, chosen_folder))
-  chosen_folder_path_rel_root = os.path.relpath(chosen_folder_path, ROOT_DIR)
-  if chosen_folder not in existing_folders:
-    print('Creating new folder {} and adding include to include_index file'
-          .format(chosen_folder))
-    os.mkdir(chosen_folder_path)
-
-    out_include_index = list(map(lambda x: x + '/index', existing_folders))
-    out_include_index.append(chosen_folder + '/index')
-    out_include_index.sort()
-
-    with open(include_index_path, 'w') as include_index_file:
-      include_index_file.write('\n'.join(out_include_index))
-      include_index_file.write('\n')
-
-  print()
-  stdout_write('Pick the type of trace to be added [proto/textproto/python]: ')
-  trace_type = sys.stdin.readline().rstrip()
-
-  print()
-  trace_file = ''
-  if trace_type == 'proto':
-    print('Proto traces should be added to the test-data zip '
-          'using the tools/add_test_trace.sh')
-    stdout_write('Provide the name of the trace (including any '
-                 'extension) relative to test/data: ')
-
-    pb_file = sys.stdin.readline().rstrip()
-    pb_path = os.path.abspath(os.path.join(ROOT_DIR, 'test', 'data', pb_file))
-    if not os.path.exists(pb_path):
-      print('Error: provided pb file {} does not exist',
-            os.path.relpath(pb_path, ROOT_DIR))
-      return 1
-
-    trace_file = os.path.relpath(pb_path, chosen_folder_path)
-  elif trace_type == 'textproto':
-    print('Provide the path to the textproto trace relative to the '
-          'chosen folder {}'.format(chosen_folder_path_rel_root))
-    stdout_write(
-        'If the file does not already exist, an empty file will be created: ')
-
-    textproto_file = sys.stdin.readline().rstrip()
-    textproto_path = os.path.abspath(
-        os.path.join(chosen_folder_path, textproto_file))
-    create_if_not_exists(textproto_path)
-
-    trace_file = textproto_file
-  elif trace_type == 'python':
-    print(
-        'Provide the path to the Python trace '
-        'relative to the chosen folder {}'.format(chosen_folder_path_rel_root))
-    stdout_write(
-        'If the file does not already exist, an empty file will be created: ')
-
-    python_file = sys.stdin.readline().rstrip()
-    python_path = os.path.abspath(os.path.join(chosen_folder_path, python_file))
-    if create_if_not_exists(python_path):
-      print('For examples of how Python traces are constructed, '
-            'check the existing traces in test/trace_processor')
-
-    trace_file = python_file
-  else:
-    print('Error: unexpected trace type {}'.format(trace_type))
-    return 1
-
-  print()
-  print('Provide the path to the SQL file relative to the chosen folder {}'
-        .format(chosen_folder_path_rel_root))
-  stdout_write(
-      'If the file does not already exist, an empty file will be created: ')
-
-  sql_file = sys.stdin.readline().rstrip()
-  sql_path = os.path.abspath(os.path.join(chosen_folder_path, sql_file))
-  create_if_not_exists(sql_path)
-
-  default_out_file = '{}_{}.out'.format(
-      pathlib.Path(trace_file).stem,
-      pathlib.Path(sql_file).stem)
-
-  print()
-  print('Provide the name of the output file (or leave empty '
-        'to accept the default: {})'.format(default_out_file))
-  stdout_write(
-      'If the file does not already exist, an empty file will be created: ')
-  out_file = sys.stdin.readline().rstrip()
-  if not out_file:
-    out_file = default_out_file
-
-  out_path = os.path.abspath(os.path.join(chosen_folder_path, out_file))
-  create_if_not_exists(out_path)
-
-  print()
-  print('Appending test to index file')
-  with open(os.path.join(chosen_folder_path, 'index'), 'a') as index_file:
-    index_file.write('{} {} {}\n'.format(trace_file, sql_file, out_file))
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/add_tp_diff_test.sh b/tools/add_tp_diff_test.sh
new file mode 100755
index 0000000..196fd5f
--- /dev/null
+++ b/tools/add_tp_diff_test.sh
@@ -0,0 +1,41 @@
+#!/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 -e
+
+read -p "Name of SQL file to create (in test/trace_processor): " sqlfile
+read -p "Name to trace file (in test/): " tracefile
+
+ROOTDIR=$(dirname $(dirname $(readlink -f $0)))
+TEST_PATH=$ROOTDIR/test
+TRACE_PROC_PATH=$TEST_PATH/trace_processor
+
+SQL_FILE_NAME=${sqlfile%.*}
+
+echo "Creating $TRACE_PROC_PATH/$sqlfile"
+touch $TRACE_PROC_PATH/$sqlfile
+
+TRACE_PATH=$TEST_PATH/$tracefile
+TRACE_BASE=$(basename $tracefile)
+TRACE_FILE_NAME=${TRACE_BASE%.*}
+OUT_FILE="$SQL_FILE_NAME""_$TRACE_FILE_NAME.out"
+
+echo "Creating $TRACE_PROC_PATH/$OUT_FILE"
+touch $TRACE_PROC_PATH/$OUT_FILE
+
+RELTRACE=$(realpath -s $TRACE_PATH --relative-to=$TRACE_PROC_PATH --relative-base=$ROOTDIR)
+echo "Adding index line to $TRACE_PROC_PATH/index"
+echo >> $TRACE_PROC_PATH/index
+echo "$RELTRACE $sqlfile $OUT_FILE" >> $TRACE_PROC_PATH/index
diff --git a/tools/analyze_profiling_sampling_distribution.py b/tools/analyze_profiling_sampling_distribution.py
index e739b47..e1e41cb 100644
--- a/tools/analyze_profiling_sampling_distribution.py
+++ b/tools/analyze_profiling_sampling_distribution.py
@@ -14,8 +14,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import os
 import sys
 
+import numpy as np
 import scipy as sp
 import seaborn as sns
 
@@ -44,11 +46,11 @@
 
   # Map from key to list of bytes allocated, one for each iteration.
   flat_distributions = {
-      key: list(value.values()) for key, value in distributions.items()
+      key: value.values() for key, value in distributions.iteritems()
   }
 
-  for key, value in flat_distributions.items():
-    print(key, "ground truth %d " % ground_truth[key], sp.stats.describe(value))
+  for key, value in flat_distributions.iteritems():
+    print key, "ground truth %d " % ground_truth[key], sp.stats.describe(value)
     sns.distplot(value)
     plt.show()
 
diff --git a/tools/build_all_configs.py b/tools/build_all_configs.py
index 95fe044..c1e22a0 100755
--- a/tools/build_all_configs.py
+++ b/tools/build_all_configs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import absolute_import
-from __future__ import division
 from __future__ import print_function
 
 import argparse
@@ -35,11 +33,11 @@
 
 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',
-         'extra_cflags="-funwind-tables"', 'android_api_level=29'),
+    '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',
@@ -72,8 +70,6 @@
   parser.add_argument('--ccache', action='store_true', default=False)
   parser.add_argument('--host-only', action='store_true', default=False)
   parser.add_argument('--android', action='store_true', default=False)
-  parser.add_argument(
-      '--export-compile-commands', action="store_true", default=False)
   parser.add_argument('--build', metavar='TARGET')
   args = parser.parse_args()
 
@@ -117,8 +113,6 @@
     if not os.path.isdir(out_dir):
       os.mkdir(out_dir)
     gn_cmd = (gn, 'gen', out_dir, '--args=%s' % (' '.join(gn_args)), '--check')
-    if args.export_compile_commands:
-      gn_cmd += ('--export-compile-commands',)
     print(' '.join(quote(c) for c in gn_cmd))
     subprocess.check_call(gn_cmd, cwd=ROOT_DIR)
     if args.build:
diff --git a/tools/busy_threads/busy_threads.cc b/tools/busy_threads/busy_threads.cc
index 56a80e2..d6dc6d7 100644
--- a/tools/busy_threads/busy_threads.cc
+++ b/tools/busy_threads/busy_threads.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <getopt.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <unistd.h>
@@ -22,14 +23,11 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
-#include "perfetto/ext/base/scoped_file.h"
 
 #define PERFETTO_HAVE_PTHREADS                \
   (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-   PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE))
+   PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX))
 
 #if PERFETTO_HAVE_PTHREADS
 #include <pthread.h>
@@ -53,13 +51,12 @@
 void PrintUsage(const char* bin_name) {
 #if PERFETTO_HAVE_PTHREADS
   PERFETTO_ELOG(
-      "Usage: %s [--background] --threads=N --period_us=N --duty_cycle=[1-100] "
+      "Usage: %s --threads=N --period_us=N --duty_cycle=[1-100] "
       "[--thread_names=N]",
       bin_name);
 #else
-  PERFETTO_ELOG(
-      "Usage: %s [--background] --threads=N --period_us=N --duty_cycle=[1-100]",
-      bin_name);
+  PERFETTO_ELOG("Usage: %s --threads=N --period_us=N --duty_cycle=[1-100]",
+                bin_name);
 #endif
 }
 
@@ -95,35 +92,31 @@
 }
 
 int BusyThreadsMain(int argc, char** argv) {
-  bool background = false;
   int64_t num_threads = -1;
   int64_t period_us = -1;
   int64_t duty_cycle = -1;
   uint32_t thread_name_count = 0;
 
-  static option long_options[] = {
-    {"background", no_argument, nullptr, 'd'},
+  static struct option long_options[] = {
     {"threads", required_argument, nullptr, 't'},
     {"period_us", required_argument, nullptr, 'p'},
-    {"duty_cycle", required_argument, nullptr, 'c'},
+    {"duty_cycle", required_argument, nullptr, 'd'},
 #if PERFETTO_HAVE_PTHREADS
     {"thread_names", required_argument, nullptr, 'r'},
 #endif
     {nullptr, 0, nullptr, 0}
   };
+  int option_index;
   int c;
-  while ((c = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
+  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
     switch (c) {
-      case 'd':
-        background = true;
-        break;
       case 't':
         num_threads = atol(optarg);
         break;
       case 'p':
         period_us = atol(optarg);
         break;
-      case 'c':
+      case 'd':
         duty_cycle = atol(optarg);
         break;
 #if PERFETTO_HAVE_PTHREADS
@@ -141,33 +134,7 @@
     return 1;
   }
 
-  if (background) {
-    pid_t pid;
-    switch (pid = fork()) {
-      case -1:
-        PERFETTO_FATAL("fork");
-      case 0: {
-        PERFETTO_CHECK(setsid() != -1);
-        base::ignore_result(chdir("/"));
-        base::ScopedFile null = base::OpenFile("/dev/null", O_RDONLY);
-        PERFETTO_CHECK(null);
-        PERFETTO_CHECK(dup2(*null, STDIN_FILENO) != -1);
-        PERFETTO_CHECK(dup2(*null, STDOUT_FILENO) != -1);
-        PERFETTO_CHECK(dup2(*null, STDERR_FILENO) != -1);
-        // Do not accidentally close stdin/stdout/stderr.
-        if (*null <= 2)
-          null.release();
-        break;
-      }
-      default:
-        printf("%d\n", pid);
-        exit(0);
-    }
-  }
-
-  int64_t busy_us =
-      static_cast<int64_t>(static_cast<double>(period_us) *
-                           (static_cast<double>(duty_cycle) / 100.0));
+  int64_t busy_us = static_cast<int64_t>(period_us * (duty_cycle / 100.0));
 
   PERFETTO_LOG("Spawning %" PRId64 " threads; period duration: %" PRId64
                "us; busy duration: %" PRId64 "us.",
diff --git a/tools/check_include_violations b/tools/check_include_violations
index d86931b..e308ec7 100755
--- a/tools/check_include_violations
+++ b/tools/check_include_violations
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,10 +19,6 @@
 # - public includes don't end up depending on private src/ headers.
 # - We use consistently <angle brackets> for other libraries.
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import re
 import subprocess
diff --git a/tools/check_proto_comments b/tools/check_proto_comments
deleted file mode 100755
index 6e7392f..0000000
--- a/tools/check_proto_comments
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This tool checks for inline comments in proto files
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import re
-import sys
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-def main():
-  errors = 0
-  protos_root = os.path.join(ROOT_DIR, 'protos')
-  for root, _, files in os.walk(protos_root):
-    for fname in files:
-      fpath = os.path.join(root, fname)
-      if not os.path.isfile(fpath):
-        continue
-      if not fpath.endswith('.proto'):
-        continue
-      with open(fpath) as f:
-        lines = f.readlines()
-      for line in lines:
-        comm = line.find('//')
-        alt_comm = re.search(r'^\s*\*', line)
-        only_comm = re.search(r'^\s*//', line)
-
-        # Allow comments only if not inline
-        if comm == -1 or alt_comm or only_comm:
-          continue
-
-        rel_path = os.path.relpath(fpath, ROOT_DIR)
-        sys.stderr.write(
-            ('Proto file %s has inline comment, please move to ' +
-            'the previous line:\t%s') % (rel_path, line))
-        errors += 1
-
-  return 0 if errors == 0 else 1
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/check_sql_metrics.py b/tools/check_sql_metrics.py
deleted file mode 100755
index 2fe57df..0000000
--- a/tools/check_sql_metrics.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 that every create (table|view) is prefixed by
-# drop (table|view).
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import re
-import sys
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def check(path):
-  with open(path) as f:
-    lines = [l.strip() for l in f.readlines()]
-
-  errors = 0
-  d_type, d_name = None, None
-  for line in lines:
-    m = re.match(r'^DROP (TABLE|VIEW) IF EXISTS (.*);$', line)
-    if m is not None:
-      d_type, d_name = m.group(1), m.group(2)
-      continue
-    m = re.match(r'^CREATE (?:VIRTUAL )?(TABLE|VIEW) (.*) (?:AS|USING).*', line)
-    if m is None:
-      continue
-    type, name = m.group(1), m.group(2)
-    if type != d_type or name != d_name:
-      sys.stderr.write(('%s:\n  "%s" vs %s %s\n') % (path, line, d_type, d_name))
-      errors += 1
-    d_type, d_name = None, None
-  return errors
-
-
-def main():
-  errors = 0
-  metrics_sources = os.path.join(ROOT_DIR, 'src', 'trace_processor', 'metrics')
-  for root, _, files in os.walk(metrics_sources, topdown=True):
-    for f in files:
-      path = os.path.join(root, f)
-      if path.endswith('.sql'):
-        errors += check(path)
-  return 0 if errors == 0 else 1
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/compact_reencode/main.cc b/tools/compact_reencode/main.cc
index 19d4c22..ae4a2c4 100644
--- a/tools/compact_reencode/main.cc
+++ b/tools/compact_reencode/main.cc
@@ -15,7 +15,6 @@
  */
 
 #include <stdint.h>
-#include <stdio.h>
 #include <string>
 #include <vector>
 
@@ -45,7 +44,7 @@
 namespace {
 
 void WriteToFile(const std::string& out, const char* path) {
-  PERFETTO_CHECK(!remove(path) || errno == ENOENT);
+  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())) {
diff --git a/tools/compat.py b/tools/compat.py
index 44b0c02..cdf5afa 100644
--- a/tools/compat.py
+++ b/tools/compat.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/tools/cpu_utilization/cpu_utilization.cc b/tools/cpu_utilization/cpu_utilization.cc
index 2aea7ba..829fd7f 100644
--- a/tools/cpu_utilization/cpu_utilization.cc
+++ b/tools/cpu_utilization/cpu_utilization.cc
@@ -15,6 +15,7 @@
  */
 
 #include <fcntl.h>
+#include <getopt.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <sys/stat.h>
@@ -26,8 +27,6 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
 #include "perfetto/ext/base/scoped_file.h"
 
 // Periodically prints an un-normalized cpu usage ratio (full use of a single
@@ -67,13 +66,14 @@
   int sleep_intervals = 6;
   int target_pid = -1;
 
-  static option long_options[] = {
+  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, nullptr)) != -1) {
+  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
     switch (c) {
       case 'p':
         target_pid = atoi(optarg);
@@ -156,8 +156,8 @@
     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 / static_cast<double>(wall_diff_ms);
-    double stime_ratio = stime_diff_ms / static_cast<double>(wall_diff_ms);
+    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);
@@ -174,8 +174,8 @@
   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 / static_cast<double>(wall_diff_ms);
-  double stime_ratio = stime_diff_ms / static_cast<double>(wall_diff_ms);
+  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);
diff --git a/tools/dev_server b/tools/dev_server
new file mode 100755
index 0000000..331720e
--- /dev/null
+++ b/tools/dev_server
@@ -0,0 +1,173 @@
+#!/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 sys
+import os
+import time
+import argparse
+import socket
+import subprocess
+import threading
+
+try:
+  import socketserver
+  from http.server import SimpleHTTPRequestHandler
+except ImportError:
+  import SocketServer as socketserver
+  import SimpleHTTPServer
+  SimpleHTTPRequestHandler = SimpleHTTPServer.SimpleHTTPRequestHandler
+
+
+class TCPServer(socketserver.TCPServer):
+
+  def server_bind(self):
+    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    self.socket.bind(self.server_address)
+
+
+class Server(object):
+
+  def __init__(self, port, directory, rebuilder):
+    self.port = port
+    self.directory = directory
+    self.rebuilder = rebuilder
+    self.lock = threading.Lock()
+
+  def serve(self):
+    this = self
+
+    class Handler(SimpleHTTPRequestHandler):
+
+      def __init__(self, *args, **kwargs):
+        SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
+        self.extensions_map['.wasm'] = 'application/wasm'
+
+      def translate_path(self, path):
+        path = SimpleHTTPRequestHandler.translate_path(self, path)
+        relpath = os.path.relpath(path, os.getcwd())
+        fullpath = os.path.join(this.directory, relpath)
+        return fullpath
+
+      def do_GET(self):
+        try:
+          with this.lock:
+            this.rebuilder.rebuild_if_needed()
+        except RebuildFailed as e:
+          self.send_response(200)
+          self.send_header("Content-type", "text/html")
+          self.end_headers()
+          self.wfile.write("<pre>")
+          self.wfile.write(e.stdout_and_stderr)
+          return
+        return SimpleHTTPRequestHandler.do_GET(self)
+
+    print('Starting server at http://localhost:{}'.format(self.port))
+    httpd = TCPServer(('', self.port), Handler)
+    try:
+      httpd.serve_forever()
+    except KeyboardInterrupt:
+      httpd.shutdown()
+    httpd.server_close()
+
+
+class RebuildFailed(Exception):
+
+  def __init__(self, stdout_and_stderr):
+    self.stdout_and_stderr = stdout_and_stderr
+
+
+class Rebuilder(object):
+
+  def __init__(self, command, ignored_paths):
+    self.command = command
+    self.ignored_paths = ignored_paths
+    self.last_disk_state = None
+    self.abs_ignored_paths = [os.path.abspath(p) for p in self.ignored_paths]
+
+  def rebuild_if_needed(self):
+    if self.last_disk_state == self.last_modified_time():
+      return
+    stdout_and_stderr, success = self.rebuild()
+    if not success:
+      message = b"Failed to build! Command output:\n\n" + stdout_and_stderr
+      raise RebuildFailed(message)
+    self.last_disk_state = self.last_modified_time()
+
+  def last_modified_time(self):
+    start_time = time.time()
+    max_mtime = 0
+    for dirpath, dirnames, filenames in os.walk(
+        os.path.abspath('.'), topdown=True):
+      dirnames[:] = [
+          n for n in dirnames
+          if not self.should_ignore_path(os.path.join(dirpath, n))
+      ]
+      for filename in filenames:
+        path = os.path.join(dirpath, filename)
+        if self.should_ignore_path(path):
+          continue
+        mtime = os.stat(path).st_mtime
+        max_mtime = max(max_mtime, mtime)
+    print(' scanned in {:.03f}s'.format(time.time() - start_time).rjust(
+        80, '='))
+    return max_mtime
+
+  def should_ignore_path(self, path):
+    return path in self.abs_ignored_paths
+
+  def rebuild(self):
+    print('Running command: {}'.format(self.command))
+    print(' begin build'.rjust(80, '='))
+    start_time = time.time()
+    status = 0
+    try:
+      stdout_and_stderr = subprocess.check_output(
+          self.command, shell=True, stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as e:
+      status = e.returncode
+      stdout_and_stderr = e.output
+    print(stdout_and_stderr.decode('utf8'))
+    print(' built in {:.03f}s'.format(time.time() - start_time).rjust(80, '='))
+    return stdout_and_stderr, status == 0
+
+
+def main(argv):
+  parser = argparse.ArgumentParser(description='HTTP server for UI development')
+  parser.add_argument(
+      '-p',
+      '--port',
+      help='port number (default: 3000)',
+      type=int,
+      default=3000)
+  parser.add_argument(
+      '-i', '--ignore', default=[], action='append', help='Ignore this path')
+  parser.add_argument(
+      '-s',
+      '--serve',
+      default=os.getcwd(),
+      help='Serve this directory (default: current directory)')
+  parser.add_argument('command', default='', nargs='?', help='Command to run')
+
+  args = parser.parse_args(argv)
+
+  rebuilder = Rebuilder(args.command, args.ignore)
+  server = Server(args.port, args.serve, rebuilder)
+  server.serve()
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index 8f84a85..ea1f5b5 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,10 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import argparse
 import datetime
 import difflib
@@ -30,23 +26,10 @@
 import tempfile
 
 from itertools import chain
+from google.protobuf import descriptor, descriptor_pb2, message_factory
 from google.protobuf import reflection, text_format
 
-from proto_utils import create_message_factory, serialize_textproto_trace, serialize_python_trace
-
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-ENV = {
-    'PERFETTO_BINARY_PATH': os.path.join(ROOT_DIR, 'test', 'data'),
-}
-if sys.platform.startswith('linux'):
-  ENV['PATH'] = os.path.join(ROOT_DIR, 'buildtools', 'linux64', 'clang', 'bin')
-elif sys.platform.startswith('dawin'):
-  # Sadly, on macOS we need to check out the Android deps to get
-  # llvm symbolizer.
-  ENV['PATH'] = os.path.join(ROOT_DIR, 'buildtools', 'ndk', 'toolchains',
-                             'llvm', 'prebuilt', 'darwin-x86_64', 'bin')
-elif sys.platform.startswith('win32'):
-  ENV['PATH'] = os.path.join(ROOT_DIR, 'buildtools', 'win', 'clang', 'bin')
 
 
 class Test(object):
@@ -69,6 +52,55 @@
     self.real_time_ns = int(real_time_ns_str)
 
 
+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, trace, cmd, expected, actual,
@@ -83,20 +115,6 @@
     self.exit_code = exit_code
 
 
-def create_metrics_message_factory(metrics_descriptor_paths):
-  return create_message_factory(metrics_descriptor_paths,
-                                'perfetto.protos.TraceMetrics')
-
-
-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)
-
-
 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:
@@ -108,17 +126,16 @@
       '--run-metrics',
       metric,
       '--metrics-output=%s' % ('json' if json_output else 'binary'),
+      gen_trace_path,
       '--perf-file',
       perf_path,
-      gen_trace_path,
   ]
-  tp = subprocess.Popen(
-      cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=ENV)
+  tp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   (stdout, stderr) = tp.communicate()
 
   if json_output:
     expected_text = expected
-    actual_text = stdout.decode('utf8')
+    actual_text = stdout
   else:
     # Expected will be in text proto format and we'll need to parse it to a real
     # proto.
@@ -135,7 +152,7 @@
     actual_text = text_format.MessageToString(actual_message)
 
   return TestResult('metric', metric, gen_trace_path, cmd, expected_text,
-                    actual_text, stderr.decode('utf8'), tp.returncode)
+                    actual_text, stderr, tp.returncode)
 
 
 def run_query_test(trace_processor_path, gen_trace_path, query_path,
@@ -147,24 +164,21 @@
       trace_processor_path,
       '-q',
       query_path,
+      gen_trace_path,
       '--perf-file',
       perf_path,
-      gen_trace_path,
   ]
 
-  tp = subprocess.Popen(
-      cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=ENV)
+  tp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   (stdout, stderr) = tp.communicate()
-  return TestResult('query', query_path, gen_trace_path, cmd, expected,
-                    stdout.decode('utf8'), stderr.decode('utf8'), tp.returncode)
+  return TestResult('query', query_path, gen_trace_path, cmd, expected, stdout,
+                    stderr, tp.returncode)
 
 
 def run_all_tests(trace_processor, trace_descriptor_path,
-                  extension_descriptor_paths, metrics_message_factory, tests,
-                  keep_input, rebase):
+                  metrics_message_factory, tests, keep_input):
   perf_data = []
   test_failure = 0
-  rebased = 0
   for test in tests:
     trace_path = test.trace_path
     expected_path = test.expected_path
@@ -177,75 +191,53 @@
       test_failure += 1
       continue
 
-    is_generated_trace = trace_path.endswith('.py') or trace_path.endswith(
-        '.textproto')
     if trace_path.endswith('.py'):
       gen_trace_file = tempfile.NamedTemporaryFile(delete=False)
-      serialize_python_trace(trace_descriptor_path, trace_path, gen_trace_file)
+      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(delete=False)
-      serialize_textproto_trace(trace_descriptor_path,
-                                extension_descriptor_paths, trace_path,
-                                gen_trace_file)
+      serialize_text_proto_to_file(trace_descriptor_path, trace_path,
+                                   gen_trace_file)
       gen_trace_path = os.path.realpath(gen_trace_file.name)
     else:
       gen_trace_file = None
       gen_trace_path = trace_path
 
-    # We can't use delete=True here. When using that on Windwows, the resulting
-    # file is opened in exclusive mode (in turn that's a subtle side-effect of
-    # the underlying CreateFile(FILE_ATTRIBUTE_TEMPORARY)) and TP fails to open
-    # the passed path.
-    tmp_perf_file = tempfile.NamedTemporaryFile(delete=False)
-    sys.stderr.write('[ RUN      ] {} {}\n'.format(
-        os.path.basename(test.query_path_or_metric),
-        os.path.basename(trace_path)))
+    with tempfile.NamedTemporaryFile() as tmp_perf_file:
+      sys.stderr.write('[ RUN      ] {} {}\n'.format(
+          os.path.basename(test.query_path_or_metric),
+          os.path.basename(trace_path)))
 
-    tmp_perf_path = tmp_perf_file.name
-    if test.type == 'queries':
-      query_path = test.query_path_or_metric
+      tmp_perf_path = tmp_perf_file.name
+      if test.type == 'queries':
+        query_path = test.query_path_or_metric
 
-      if not os.path.exists(test.query_path_or_metric):
-        print('Query file not found {}'.format(query_path))
-        test_failure += 1
-        continue
+        if not os.path.exists(test.query_path_or_metric):
+          print('Query file not found {}'.format(query_path))
+          test_failure += 1
+          continue
 
-      result = run_query_test(trace_processor, gen_trace_path, query_path,
-                              expected_path, tmp_perf_path)
-    elif test.type == 'metrics':
-      result = run_metrics_test(trace_processor, gen_trace_path,
-                                test.query_path_or_metric, expected_path,
-                                tmp_perf_path, metrics_message_factory)
-    else:
-      assert False
+        result = run_query_test(trace_processor, gen_trace_path, query_path,
+                                expected_path, tmp_perf_path)
+      elif test.type == 'metrics':
+        result = run_metrics_test(trace_processor, gen_trace_path,
+                                  test.query_path_or_metric, expected_path,
+                                  tmp_perf_path, metrics_message_factory)
+      else:
+        assert False
 
-    perf_lines = [line.decode('utf8') for line in tmp_perf_file.readlines()]
-    tmp_perf_file.close()
-    os.remove(tmp_perf_file.name)
+      perf_lines = tmp_perf_file.readlines()
 
     if gen_trace_file:
       if keep_input:
-        sys.stderr.write(
-            "Saving generated input trace: {}\n".format(gen_trace_path))
+        print "Saving generated input trace: ", gen_trace_path
       else:
         gen_trace_file.close()
         os.remove(gen_trace_path)
 
-    def write_cmdlines():
-      if is_generated_trace:
-        sys.stderr.write(
-            'Command to generate trace:\n'
-            'tools/serialize_test_trace.py --descriptor {} {} > {}\n'.format(
-                os.path.relpath(trace_descriptor_path, ROOT_DIR),
-                os.path.relpath(trace_path, ROOT_DIR),
-                os.path.relpath(gen_trace_path, ROOT_DIR)))
-      sys.stderr.write('Command line:\n{}\n'.format(' '.join(result.cmd)))
-
-    contents_equal = (
-        result.expected.replace('\r\n',
-                                '\n') == result.actual.replace('\r\n', '\n'))
-    if result.exit_code != 0 or not contents_equal:
+    if result.exit_code != 0 or result.expected != result.actual:
       sys.stderr.write(result.stderr)
 
       if result.exit_code == 0:
@@ -253,25 +245,16 @@
             '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))
-        write_cmdlines()
+        sys.stderr.write('Command line: {}\n'.format(' '.join(result.cmd)))
+
         write_diff(result.expected, result.actual)
       else:
-        write_cmdlines()
+        sys.stderr.write('Command line: {}\n'.format(' '.join(result.cmd)))
 
       sys.stderr.write('[     FAIL ] {} {}\n'.format(
           os.path.basename(test.query_path_or_metric),
           os.path.basename(trace_path)))
 
-      if rebase:
-        if result.exit_code == 0:
-          sys.stderr.write('Rebasing {}\n'.format(expected_path))
-          with open(expected_path, 'w') as f:
-            f.write(result.actual)
-          rebase += 1
-        else:
-          sys.stderr.write(
-              'Rebase failed for {} as query failed\n'.format(expected_path))
-
       test_failure += 1
     else:
       assert len(perf_lines) == 1
@@ -289,14 +272,20 @@
               perf_result.ingest_time_ns / 1000000,
               perf_result.real_time_ns / 1000000))
 
-  return test_failure, perf_data, rebased
+  return test_failure, perf_data
 
 
-def read_all_tests_from_index(index_path, query_metric_pattern, trace_pattern):
-  index_dir = os.path.dirname(index_path)
+def read_all_tests(test_type, query_metric_pattern, trace_pattern):
+  if test_type == 'queries':
+    index = os.path.join(ROOT_DIR, 'test', 'trace_processor', 'index')
+  elif test_type == 'metrics':
+    index = os.path.join(ROOT_DIR, 'test', 'metrics', 'index')
+  else:
+    assert False
 
-  with open(index_path, 'r') as index_file:
-    index_lines = index_file.readlines()
+  index_dir = os.path.dirname(index)
+  with open(index, 'r') as file:
+    index_lines = file.readlines()
 
   tests = []
   for line in index_lines:
@@ -316,29 +305,14 @@
     trace_path = os.path.abspath(os.path.join(index_dir, trace_fname))
     expected_path = os.path.abspath(os.path.join(index_dir, expected_fname))
 
-    if query_fname_or_metric.endswith('.sql'):
-      test_type = 'queries'
+    query_path_or_metric = query_fname_or_metric
+    if test_type == 'queries':
       query_path_or_metric = os.path.abspath(
           os.path.join(index_dir, query_fname_or_metric))
-    else:
-      test_type = 'metrics'
-      query_path_or_metric = query_fname_or_metric
 
     tests.append(
         Test(test_type, trace_path, query_path_or_metric, expected_path))
-  return tests
 
-
-def read_all_tests(query_metric_pattern, trace_pattern):
-  include_index_dir = os.path.join(ROOT_DIR, 'test', 'trace_processor')
-  include_index = os.path.join(include_index_dir, 'include_index')
-  tests = []
-  with open(include_index, 'r') as include_file:
-    for index_relpath in include_file.readlines():
-      index_path = os.path.join(include_index_dir, index_relpath.strip())
-      tests.extend(
-          read_all_tests_from_index(index_path, query_metric_pattern,
-                                    trace_pattern))
   return tests
 
 
@@ -364,65 +338,56 @@
       action='store_true',
       help='Save the (generated) input pb file for debugging')
   parser.add_argument(
-      '--rebase',
-      action='store_true',
-      help='Update the expected output file with the actual result')
-  parser.add_argument(
       'trace_processor', type=str, help='location of trace processor binary')
   args = parser.parse_args()
 
+  test_type = args.test_type
+  if test_type != 'all' and test_type != 'queries' and test_type != 'metrics':
+    print('Unknown test type {}. Supported: all, queries, metrics'.format(
+        test_type))
+    return 1
+
   query_metric_pattern = re.compile(args.query_metric_filter)
   trace_pattern = re.compile(args.trace_filter)
 
-  tests = read_all_tests(query_metric_pattern, trace_pattern)
+  tests = []
+  if test_type == 'all' or test_type == 'metrics':
+    tests += read_all_tests('metrics', query_metric_pattern, trace_pattern)
+
+  if test_type == 'all' or test_type == 'queries':
+    tests += read_all_tests('queries', query_metric_pattern, trace_pattern)
+
   sys.stderr.write('[==========] Running {} tests.\n'.format(len(tests)))
 
-  out_path = os.path.dirname(args.trace_processor)
   if args.trace_descriptor:
     trace_descriptor_path = args.trace_descriptor
   else:
-    def find_trace_descriptor(parent):
-      trace_protos_path = os.path.join(parent, 'gen', 'protos', 'perfetto',
-                                       'trace')
-      return os.path.join(trace_protos_path, 'trace.descriptor')
-
-    trace_descriptor_path = find_trace_descriptor(out_path)
-    if not os.path.exists(trace_descriptor_path):
-      trace_descriptor_path = find_trace_descriptor(
-          os.path.join(out_path, 'gcc_like_host'))
-
+    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')
 
   if args.metrics_descriptor:
-    metrics_descriptor_paths = [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_paths = [
-        os.path.join(metrics_protos_path, 'metrics.descriptor'),
-        os.path.join(metrics_protos_path, 'chrome',
-                     'all_chrome_metrics.descriptor')
-    ]
-
-  chrome_extensions = os.path.join(out_path, 'gen', 'protos', 'third_party',
-                                   'chromium', 'chrome_track_event.descriptor')
-  test_extensions = os.path.join(out_path, 'gen', 'protos', 'perfetto', 'trace',
-                                 'test_extensions.descriptor')
+    metrics_descriptor_path = os.path.join(metrics_protos_path,
+                                           'metrics.descriptor')
 
   metrics_message_factory = create_metrics_message_factory(
-      metrics_descriptor_paths)
+      metrics_descriptor_path)
 
   test_run_start = datetime.datetime.now()
-  test_failure, perf_data, rebased = run_all_tests(
-      args.trace_processor, trace_descriptor_path,
-      [chrome_extensions, test_extensions], metrics_message_factory, tests,
-      args.keep_input, args.rebase)
+  test_failure, perf_data = run_all_tests(
+      args.trace_processor, trace_descriptor_path, metrics_message_factory,
+      tests, args.keep_input)
   test_run_end = datetime.datetime.now()
 
   sys.stderr.write('[==========] {} tests ran. ({} ms total)\n'.format(
       len(tests), int((test_run_end - test_run_start).total_seconds() * 1000)))
   sys.stderr.write('[  PASSED  ] {} tests.\n'.format(len(tests) - test_failure))
-  if args.rebase:
-    sys.stderr.write('{} tests rebased.\n'.format(rebased))
 
   if test_failure == 0:
     if args.perf_file:
@@ -430,10 +395,7 @@
       trace_processor_dir = os.path.join(test_dir, 'trace_processor')
 
       metrics = []
-      sorted_data = sorted(
-          perf_data,
-          key=lambda x: (x.test_type, x.trace_path, x.query_path_or_metric))
-      for perf_args in sorted_data:
+      for perf_args in sorted(perf_data):
         trace_short_path = os.path.relpath(perf_args.trace_path, test_dir)
 
         query_short_path_or_metric = perf_args.query_path_or_metric
diff --git a/tools/export_power_profiles.py b/tools/export_power_profiles.py
deleted file mode 100755
index db6e7ce..0000000
--- a/tools/export_power_profiles.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env vpython
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import argparse
-import os
-import sys
-import xml.etree.ElementTree as ET
-
-
-def ExtractValues(xml_path, correction):
-  root = ET.parse(xml_path).getroot()
-
-  speeds = []
-  power = []
-  clusters = []
-  for array in root.iter('array'):
-    if array.get('name') == 'cpu.clusters.cores':
-      clusters = [int(value.text) for value in array.iter('value')]
-    if array.get('name').startswith('cpu.core_speeds.'):
-      speeds.append([int(value.text) for value in array.iter('value')])
-    if array.get('name').startswith('cpu.core_power.'):
-      power.append([float(value.text) for value in array.iter('value')])
-
-  values = []
-  cpu = 0
-  for cluster, n_cpus in enumerate(clusters):
-    for _ in range(n_cpus):
-      for freq, drain in zip(speeds[cluster], power[cluster]):
-        if correction:
-          drain /= n_cpus
-        values.append((cpu, cluster, freq, drain))
-      cpu += 1
-
-  return values
-
-
-def ExportProfiles(device_xmls, sql_path):
-  sql_values = []
-  for device, xml_path, correction in device_xmls:
-    sql_values += [
-        '("%s", %s, %s, %s, %s)' % ((device,) + v)
-        for v in ExtractValues(xml_path, correction == 'yes')
-    ]
-
-  with open(sql_path, 'w') as sql_file:
-    sql_file.write('INSERT OR REPLACE INTO power_profile VALUES\n')
-    sql_file.write(',\n'.join(sql_values))
-    sql_file.write(';\n')
-
-
-def main(args):
-  parser = argparse.ArgumentParser(
-      description='Export XML power profile as a SQL INSERT query.',
-      epilog='Example usage:\n'
-      'python export_power_profiles.py '
-      '--device-xml sailfish sailfish/power_profile.xml no '
-      '--device-xml sargo sargo/power_profile.xml yes '
-      '--output power_profile_data.sql')
-  parser.add_argument(
-      '--device-xml',
-      nargs=3,
-      metavar=('DEVICE', 'XML_FILE', 'CORRECTION'),
-      action='append',
-      help='First argument: device name; second argument: path to the XML '
-      'file with the device power profile; third argument(yes|no): '
-      'whether correction is necessary. Can be used multiple times.')
-  parser.add_argument(
-      '--output', metavar='SQL_FILE', help='Path to the output file.')
-
-  args = parser.parse_args(args)
-
-  sql_path = 'result.sql'
-  ExportProfiles(args.device_xml, args.output)
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
diff --git a/tools/extract_linux_syscall_tables b/tools/extract_linux_syscall_tables
index 0f2d2a6..d1753bf 100755
--- a/tools/extract_linux_syscall_tables
+++ b/tools/extract_linux_syscall_tables
@@ -1,19 +1,18 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 
 import re
 import sys
-
-from  urllib.request import urlopen
+import urllib2
 
 syscalls = {}
 
 
 def print_table(name):
   tab = syscalls[name]
-  print('\n\n----------------- BEGIN OF %s -----------------' % name)
-  for i in range(max(tab.keys()) + 1):
-    print('"%s",  // %d' % (tab.get(i, ''), i))
-  print('----------------- END OF %s -----------------' % name)
+  print '\n\n----------------- BEGIN OF %s -----------------' % name
+  for i in xrange(max(tab.keys()) + 1):
+    print '"%s",  // %d' % (tab.get(i, ''), i)
+  print '----------------- END OF %s -----------------' % name
 
 
 # Parses a .tbl file (new format).
@@ -42,24 +41,24 @@
 def Main():
   KSRC = 'https://raw.githubusercontent.com/torvalds/linux/v4.20/'
 
-  response = urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_64.tbl')
-  syscalls['x86_64'] = parse_tlb(response.read().decode())
+  response = urllib2.urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_64.tbl')
+  syscalls['x86_64'] = parse_tlb(response.read())
 
-  response = urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_32.tbl')
-  syscalls['x86'] = parse_tlb(response.read().decode())
+  response = urllib2.urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_32.tbl')
+  syscalls['x86'] = parse_tlb(response.read())
 
-  response = urlopen(KSRC + 'arch/arm/tools/syscall.tbl')
-  syscalls['armeabi'] = parse_tlb(response.read().decode())
+  response = urllib2.urlopen(KSRC + 'arch/arm/tools/syscall.tbl')
+  syscalls['armeabi'] = parse_tlb(response.read())
 
-  response = urlopen(KSRC + 'arch/arm64/include/asm/unistd32.h')
-  syscalls['aarch32'] = parse_def(response.read().decode())
+  response = urllib2.urlopen(KSRC + 'arch/arm64/include/asm/unistd32.h')
+  syscalls['aarch32'] = parse_def(response.read())
 
   # From:
   # arch/arm64/include/asm/unistd.h
   #   -> arch/arm64/include/uapi/asm/unistd.h
   #     -> include/uapi/asm-generic/unistd.h
-  response = urlopen(KSRC + 'include/uapi/asm-generic/unistd.h')
-  syscalls['aarch64'] = parse_def(response.read().decode())
+  response = urllib2.urlopen(KSRC + 'include/uapi/asm-generic/unistd.h')
+  syscalls['aarch64'] = parse_def(response.read())
 
   print_table('x86_64')
   print_table('x86')
@@ -69,4 +68,4 @@
 
 
 if __name__ == '__main__':
-  sys.exit(Main())
\ No newline at end of file
+  sys.exit(Main())
diff --git a/tools/find_scan_roots.py b/tools/find_scan_roots.py
index f6bf892..b483bfb 100755
--- a/tools/find_scan_roots.py
+++ b/tools/find_scan_roots.py
@@ -43,7 +43,7 @@
     return n
 
   def __iter__(self):
-    for child in self.children.values():
+    for child in self.children.itervalues():
       yield self.name + '/' + child.name, child
       for p, ch in child:
         yield self.name + '/' + p, ch
@@ -56,7 +56,7 @@
 
     self.marked = True
 
-    for child in self.children.values():
+    for child in self.children.itervalues():
       child.Mark(labels)
 
     return True
@@ -89,7 +89,7 @@
   root = BuildTree()
   for fullpath, elem in root:
     if elem.Mark(args.labels):
-      print(fullpath)
+      print fullpath
 
 
 if __name__ == '__main__':
diff --git a/tools/fix_include_guards b/tools/fix_include_guards
index 1848eda..4f08b41 100755
--- a/tools/fix_include_guards
+++ b/tools/fix_include_guards
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -67,8 +67,7 @@
 def main():
   checkonly = '--check-only' in sys.argv
   num_files_changed = 0
-  for topdir in ('src', 'include', 'src/profiling/memory/include', 'test',
-                 'tools'):
+  for topdir in ('src', 'include', 'test', 'tools'):
     for root, dirs, files in os.walk(topdir):
       for name in files:
         if not name.endswith('.h'):
diff --git a/tools/ftrace_proto_gen/BUILD.gn b/tools/ftrace_proto_gen/BUILD.gn
index 5560e54..1b96c30 100644
--- a/tools/ftrace_proto_gen/BUILD.gn
+++ b/tools/ftrace_proto_gen/BUILD.gn
@@ -23,7 +23,7 @@
     "../../gn:default_deps",
     "../../gn:protobuf_full",
     "../../src/base",
-    "../../src/traced/probes/ftrace/format_parser",
+    "../../src/traced/probes/ftrace:format_parser",
   ]
 }
 
@@ -52,6 +52,6 @@
     "../../gn:default_deps",
     "../../gn:protobuf_full",
     "../../src/base",
-    "../../src/traced/probes/ftrace/format_parser",
+    "../../src/traced/probes/ftrace:format_parser",
   ]
 }
diff --git a/tools/ftrace_proto_gen/event_list b/tools/ftrace_proto_gen/event_list
deleted file mode 100644
index a4193d4..0000000
--- a/tools/ftrace_proto_gen/event_list
+++ /dev/null
@@ -1,355 +0,0 @@
-ftrace/print
-sched/sched_switch
-removed cpufreq_interactive/cpufreq_interactive_already
-removed cpufreq_interactive/cpufreq_interactive_boost
-removed cpufreq_interactive/cpufreq_interactive_notyet
-removed cpufreq_interactive/cpufreq_interactive_setspeed
-removed cpufreq_interactive/cpufreq_interactive_target
-removed cpufreq_interactive/cpufreq_interactive_unboost
-power/cpu_frequency
-power/cpu_frequency_limits
-power/cpu_idle
-power/clock_enable
-power/clock_disable
-power/clock_set_rate
-sched/sched_wakeup
-sched/sched_blocked_reason
-sched/sched_cpu_hotplug
-sched/sched_waking
-ipi/ipi_entry
-ipi/ipi_exit
-ipi/ipi_raise
-irq/softirq_entry
-irq/softirq_exit
-irq/softirq_raise
-i2c/i2c_read
-i2c/i2c_write
-i2c/i2c_result
-i2c/i2c_reply
-i2c/smbus_read
-i2c/smbus_write
-i2c/smbus_result
-i2c/smbus_reply
-lowmemorykiller/lowmemory_kill
-irq/irq_handler_entry
-irq/irq_handler_exit
-sync/sync_pt
-sync/sync_timeline
-sync/sync_wait
-ext4/ext4_da_write_begin
-ext4/ext4_da_write_end
-ext4/ext4_sync_file_enter
-ext4/ext4_sync_file_exit
-block/block_rq_issue
-vmscan/mm_vmscan_direct_reclaim_begin
-vmscan/mm_vmscan_direct_reclaim_end
-vmscan/mm_vmscan_kswapd_wake
-vmscan/mm_vmscan_kswapd_sleep
-binder/binder_transaction
-binder/binder_transaction_received
-binder/binder_set_priority
-binder/binder_lock
-binder/binder_locked
-binder/binder_unlock
-workqueue/workqueue_activate_work
-workqueue/workqueue_execute_end
-workqueue/workqueue_execute_start
-workqueue/workqueue_queue_work
-regulator/regulator_disable
-regulator/regulator_disable_complete
-regulator/regulator_enable
-regulator/regulator_enable_complete
-regulator/regulator_enable_delay
-regulator/regulator_set_voltage
-regulator/regulator_set_voltage_complete
-cgroup/cgroup_attach_task
-cgroup/cgroup_mkdir
-cgroup/cgroup_remount
-cgroup/cgroup_rmdir
-cgroup/cgroup_transfer_tasks
-cgroup/cgroup_destroy_root
-cgroup/cgroup_release
-cgroup/cgroup_rename
-cgroup/cgroup_setup_root
-mdss/mdp_cmd_kickoff
-mdss/mdp_commit
-mdss/mdp_perf_set_ot
-mdss/mdp_sspp_change
-mdss/tracing_mark_write
-mdss/mdp_cmd_pingpong_done
-mdss/mdp_compare_bw
-mdss/mdp_perf_set_panic_luts
-mdss/mdp_sspp_set
-mdss/mdp_cmd_readptr_done
-mdss/mdp_misr_crc
-mdss/mdp_perf_set_qos_luts
-mdss/mdp_trace_counter
-mdss/mdp_cmd_release_bw
-mdss/mdp_mixer_update
-mdss/mdp_perf_set_wm_levels
-mdss/mdp_video_underrun_done
-mdss/mdp_cmd_wait_pingpong
-mdss/mdp_perf_prefill_calc
-mdss/mdp_perf_update_bus
-mdss/rotator_bw_ao_as_context
-filemap/mm_filemap_add_to_page_cache
-filemap/mm_filemap_delete_from_page_cache
-compaction/mm_compaction_begin
-compaction/mm_compaction_defer_compaction
-compaction/mm_compaction_deferred
-compaction/mm_compaction_defer_reset
-compaction/mm_compaction_end
-compaction/mm_compaction_finished
-compaction/mm_compaction_isolate_freepages
-compaction/mm_compaction_isolate_migratepages
-compaction/mm_compaction_kcompactd_sleep
-compaction/mm_compaction_kcompactd_wake
-compaction/mm_compaction_migratepages
-compaction/mm_compaction_suitable
-compaction/mm_compaction_try_to_compact_pages
-compaction/mm_compaction_wakeup_kcompactd
-power/suspend_resume
-sched/sched_wakeup_new
-block/block_bio_backmerge
-block/block_bio_bounce
-block/block_bio_complete
-block/block_bio_frontmerge
-block/block_bio_queue
-block/block_bio_remap
-block/block_dirty_buffer
-block/block_getrq
-block/block_plug
-block/block_rq_abort
-block/block_rq_complete
-block/block_rq_insert
-removed
-block/block_rq_remap
-block/block_rq_requeue
-block/block_sleeprq
-block/block_split
-block/block_touch_buffer
-block/block_unplug
-ext4/ext4_alloc_da_blocks
-ext4/ext4_allocate_blocks
-ext4/ext4_allocate_inode
-ext4/ext4_begin_ordered_truncate
-ext4/ext4_collapse_range
-ext4/ext4_da_release_space
-ext4/ext4_da_reserve_space
-ext4/ext4_da_update_reserve_space
-ext4/ext4_da_write_pages
-ext4/ext4_da_write_pages_extent
-ext4/ext4_direct_IO_enter
-ext4/ext4_direct_IO_exit
-ext4/ext4_discard_blocks
-ext4/ext4_discard_preallocations
-ext4/ext4_drop_inode
-ext4/ext4_es_cache_extent
-ext4/ext4_es_find_delayed_extent_range_enter
-ext4/ext4_es_find_delayed_extent_range_exit
-ext4/ext4_es_insert_extent
-ext4/ext4_es_lookup_extent_enter
-ext4/ext4_es_lookup_extent_exit
-ext4/ext4_es_remove_extent
-ext4/ext4_es_shrink
-ext4/ext4_es_shrink_count
-ext4/ext4_es_shrink_scan_enter
-ext4/ext4_es_shrink_scan_exit
-ext4/ext4_evict_inode
-ext4/ext4_ext_convert_to_initialized_enter
-ext4/ext4_ext_convert_to_initialized_fastpath
-ext4/ext4_ext_handle_unwritten_extents
-ext4/ext4_ext_in_cache
-ext4/ext4_ext_load_extent
-ext4/ext4_ext_map_blocks_enter
-ext4/ext4_ext_map_blocks_exit
-ext4/ext4_ext_put_in_cache
-ext4/ext4_ext_remove_space
-ext4/ext4_ext_remove_space_done
-ext4/ext4_ext_rm_idx
-ext4/ext4_ext_rm_leaf
-ext4/ext4_ext_show_extent
-ext4/ext4_fallocate_enter
-ext4/ext4_fallocate_exit
-ext4/ext4_find_delalloc_range
-ext4/ext4_forget
-ext4/ext4_free_blocks
-ext4/ext4_free_inode
-ext4/ext4_get_implied_cluster_alloc_exit
-ext4/ext4_get_reserved_cluster_alloc
-ext4/ext4_ind_map_blocks_enter
-ext4/ext4_ind_map_blocks_exit
-ext4/ext4_insert_range
-ext4/ext4_invalidatepage
-ext4/ext4_journal_start
-ext4/ext4_journal_start_reserved
-ext4/ext4_journalled_invalidatepage
-ext4/ext4_journalled_write_end
-ext4/ext4_load_inode
-ext4/ext4_load_inode_bitmap
-ext4/ext4_mark_inode_dirty
-ext4/ext4_mb_bitmap_load
-ext4/ext4_mb_buddy_bitmap_load
-ext4/ext4_mb_discard_preallocations
-ext4/ext4_mb_new_group_pa
-ext4/ext4_mb_new_inode_pa
-ext4/ext4_mb_release_group_pa
-ext4/ext4_mb_release_inode_pa
-ext4/ext4_mballoc_alloc
-ext4/ext4_mballoc_discard
-ext4/ext4_mballoc_free
-ext4/ext4_mballoc_prealloc
-ext4/ext4_other_inode_update_time
-ext4/ext4_punch_hole
-ext4/ext4_read_block_bitmap_load
-ext4/ext4_readpage
-ext4/ext4_releasepage
-ext4/ext4_remove_blocks
-ext4/ext4_request_blocks
-ext4/ext4_request_inode
-ext4/ext4_sync_fs
-ext4/ext4_trim_all_free
-ext4/ext4_trim_extent
-ext4/ext4_truncate_enter
-ext4/ext4_truncate_exit
-ext4/ext4_unlink_enter
-ext4/ext4_unlink_exit
-ext4/ext4_write_begin
-removed
-removed
-removed
-removed
-removed
-removed
-removed
-removed
-removed
-removed
-ext4/ext4_write_end
-ext4/ext4_writepage
-ext4/ext4_writepages
-ext4/ext4_writepages_result
-ext4/ext4_zero_range
-task/task_newtask
-task/task_rename
-sched/sched_process_exec
-sched/sched_process_exit
-sched/sched_process_fork
-sched/sched_process_free
-sched/sched_process_hang
-sched/sched_process_wait
-f2fs/f2fs_do_submit_bio
-f2fs/f2fs_evict_inode
-f2fs/f2fs_fallocate
-f2fs/f2fs_get_data_block
-f2fs/f2fs_get_victim
-f2fs/f2fs_iget
-f2fs/f2fs_iget_exit
-f2fs/f2fs_new_inode
-f2fs/f2fs_readpage
-f2fs/f2fs_reserve_new_block
-f2fs/f2fs_set_page_dirty
-f2fs/f2fs_submit_write_page
-f2fs/f2fs_sync_file_enter
-f2fs/f2fs_sync_file_exit
-f2fs/f2fs_sync_fs
-f2fs/f2fs_truncate
-f2fs/f2fs_truncate_blocks_enter
-f2fs/f2fs_truncate_blocks_exit
-f2fs/f2fs_truncate_data_blocks_range
-f2fs/f2fs_truncate_inode_blocks_enter
-f2fs/f2fs_truncate_inode_blocks_exit
-f2fs/f2fs_truncate_node
-f2fs/f2fs_truncate_nodes_enter
-f2fs/f2fs_truncate_nodes_exit
-f2fs/f2fs_truncate_partial_nodes
-f2fs/f2fs_unlink_enter
-f2fs/f2fs_unlink_exit
-f2fs/f2fs_vm_page_mkwrite
-f2fs/f2fs_write_begin
-f2fs/f2fs_write_checkpoint
-f2fs/f2fs_write_end
-kmem/alloc_pages_iommu_end
-kmem/alloc_pages_iommu_fail
-kmem/alloc_pages_iommu_start
-kmem/alloc_pages_sys_end
-kmem/alloc_pages_sys_fail
-kmem/alloc_pages_sys_start
-kmem/dma_alloc_contiguous_retry
-kmem/iommu_map_range
-kmem/iommu_sec_ptbl_map_range_end
-kmem/iommu_sec_ptbl_map_range_start
-kmem/ion_alloc_buffer_end
-kmem/ion_alloc_buffer_fail
-kmem/ion_alloc_buffer_fallback
-kmem/ion_alloc_buffer_start
-kmem/ion_cp_alloc_retry
-kmem/ion_cp_secure_buffer_end
-kmem/ion_cp_secure_buffer_start
-kmem/ion_prefetching
-kmem/ion_secure_cma_add_to_pool_end
-kmem/ion_secure_cma_add_to_pool_start
-kmem/ion_secure_cma_allocate_end
-kmem/ion_secure_cma_allocate_start
-kmem/ion_secure_cma_shrink_pool_end
-kmem/ion_secure_cma_shrink_pool_start
-kmem/kfree
-kmem/kmalloc
-kmem/kmalloc_node
-kmem/kmem_cache_alloc
-kmem/kmem_cache_alloc_node
-kmem/kmem_cache_free
-kmem/migrate_pages_end
-kmem/migrate_pages_start
-kmem/migrate_retry
-kmem/mm_page_alloc
-kmem/mm_page_alloc_extfrag
-kmem/mm_page_alloc_zone_locked
-kmem/mm_page_free
-kmem/mm_page_free_batched
-kmem/mm_page_pcpu_drain
-kmem/rss_stat
-kmem/ion_heap_shrink
-kmem/ion_heap_grow
-fence/fence_init
-fence/fence_destroy
-fence/fence_enable_signal
-fence/fence_signaled
-clk/clk_enable
-clk/clk_disable
-clk/clk_set_rate
-binder/binder_transaction_alloc_buf
-signal/signal_deliver
-signal/signal_generate
-oom/oom_score_adj_update
-mm_event/mm_event_record
-raw_syscalls/sys_enter
-raw_syscalls/sys_exit
-systrace/0
-power/gpu_frequency
-sde/tracing_mark_write
-oom/mark_victim
-ion/ion_stat
-kmem/ion_buffer_create
-kmem/ion_buffer_destroy
-scm/scm_call_start
-scm/scm_call_end
-gpu_mem/gpu_mem_total
-thermal/thermal_temperature
-thermal/cdev_update
-cpuhp/cpuhp_exit
-cpuhp/cpuhp_multi_enter
-cpuhp/cpuhp_enter
-cpuhp/cpuhp_latency
-fastrpc/fastrpc_dma_stat
-dpu/tracing_mark_write
-g2d/tracing_mark_write
-mali/tracing_mark_write
-dmabuf_heap/dma_heap_stat
-cpuhp/cpuhp_pause
-sched/sched_pi_setprio
-sde/sde_evtlog
-sde/sde_perf_calc_crtc
-sde/sde_perf_crtc_update
-sde/sde_perf_set_qos_luts
-sde/sde_perf_update_bus
diff --git a/tools/ftrace_proto_gen/event_whitelist b/tools/ftrace_proto_gen/event_whitelist
new file mode 100644
index 0000000..f4affc6
--- /dev/null
+++ b/tools/ftrace_proto_gen/event_whitelist
@@ -0,0 +1,335 @@
+ftrace/print
+sched/sched_switch
+removed cpufreq_interactive/cpufreq_interactive_already
+removed cpufreq_interactive/cpufreq_interactive_boost
+removed cpufreq_interactive/cpufreq_interactive_notyet
+removed cpufreq_interactive/cpufreq_interactive_setspeed
+removed cpufreq_interactive/cpufreq_interactive_target
+removed cpufreq_interactive/cpufreq_interactive_unboost
+power/cpu_frequency
+power/cpu_frequency_limits
+power/cpu_idle
+power/clock_enable
+power/clock_disable
+power/clock_set_rate
+sched/sched_wakeup
+sched/sched_blocked_reason
+sched/sched_cpu_hotplug
+sched/sched_waking
+ipi/ipi_entry
+ipi/ipi_exit
+ipi/ipi_raise
+irq/softirq_entry
+irq/softirq_exit
+irq/softirq_raise
+i2c/i2c_read
+i2c/i2c_write
+i2c/i2c_result
+i2c/i2c_reply
+i2c/smbus_read
+i2c/smbus_write
+i2c/smbus_result
+i2c/smbus_reply
+lowmemorykiller/lowmemory_kill
+irq/irq_handler_entry
+irq/irq_handler_exit
+sync/sync_pt
+sync/sync_timeline
+sync/sync_wait
+ext4/ext4_da_write_begin
+ext4/ext4_da_write_end
+ext4/ext4_sync_file_enter
+ext4/ext4_sync_file_exit
+block/block_rq_issue
+vmscan/mm_vmscan_direct_reclaim_begin
+vmscan/mm_vmscan_direct_reclaim_end
+vmscan/mm_vmscan_kswapd_wake
+vmscan/mm_vmscan_kswapd_sleep
+binder/binder_transaction
+binder/binder_transaction_received
+binder/binder_set_priority
+binder/binder_lock
+binder/binder_locked
+binder/binder_unlock
+workqueue/workqueue_activate_work
+workqueue/workqueue_execute_end
+workqueue/workqueue_execute_start
+workqueue/workqueue_queue_work
+regulator/regulator_disable
+regulator/regulator_disable_complete
+regulator/regulator_enable
+regulator/regulator_enable_complete
+regulator/regulator_enable_delay
+regulator/regulator_set_voltage
+regulator/regulator_set_voltage_complete
+cgroup/cgroup_attach_task
+cgroup/cgroup_mkdir
+cgroup/cgroup_remount
+cgroup/cgroup_rmdir
+cgroup/cgroup_transfer_tasks
+cgroup/cgroup_destroy_root
+cgroup/cgroup_release
+cgroup/cgroup_rename
+cgroup/cgroup_setup_root
+mdss/mdp_cmd_kickoff
+mdss/mdp_commit
+mdss/mdp_perf_set_ot
+mdss/mdp_sspp_change
+mdss/tracing_mark_write
+mdss/mdp_cmd_pingpong_done
+mdss/mdp_compare_bw
+mdss/mdp_perf_set_panic_luts
+mdss/mdp_sspp_set
+mdss/mdp_cmd_readptr_done
+mdss/mdp_misr_crc
+mdss/mdp_perf_set_qos_luts
+mdss/mdp_trace_counter
+mdss/mdp_cmd_release_bw
+mdss/mdp_mixer_update
+mdss/mdp_perf_set_wm_levels
+mdss/mdp_video_underrun_done
+mdss/mdp_cmd_wait_pingpong
+mdss/mdp_perf_prefill_calc
+mdss/mdp_perf_update_bus
+mdss/rotator_bw_ao_as_context
+filemap/mm_filemap_add_to_page_cache
+filemap/mm_filemap_delete_from_page_cache
+compaction/mm_compaction_begin
+compaction/mm_compaction_defer_compaction
+compaction/mm_compaction_deferred
+compaction/mm_compaction_defer_reset
+compaction/mm_compaction_end
+compaction/mm_compaction_finished
+compaction/mm_compaction_isolate_freepages
+compaction/mm_compaction_isolate_migratepages
+compaction/mm_compaction_kcompactd_sleep
+compaction/mm_compaction_kcompactd_wake
+compaction/mm_compaction_migratepages
+compaction/mm_compaction_suitable
+compaction/mm_compaction_try_to_compact_pages
+compaction/mm_compaction_wakeup_kcompactd
+power/suspend_resume
+sched/sched_wakeup_new
+block/block_bio_backmerge
+block/block_bio_bounce
+block/block_bio_complete
+block/block_bio_frontmerge
+block/block_bio_queue
+block/block_bio_remap
+block/block_dirty_buffer
+block/block_getrq
+block/block_plug
+block/block_rq_abort
+block/block_rq_complete
+block/block_rq_insert
+removed
+block/block_rq_remap
+block/block_rq_requeue
+block/block_sleeprq
+block/block_split
+block/block_touch_buffer
+block/block_unplug
+ext4/ext4_alloc_da_blocks
+ext4/ext4_allocate_blocks
+ext4/ext4_allocate_inode
+ext4/ext4_begin_ordered_truncate
+ext4/ext4_collapse_range
+ext4/ext4_da_release_space
+ext4/ext4_da_reserve_space
+ext4/ext4_da_update_reserve_space
+ext4/ext4_da_write_pages
+ext4/ext4_da_write_pages_extent
+ext4/ext4_direct_IO_enter
+ext4/ext4_direct_IO_exit
+ext4/ext4_discard_blocks
+ext4/ext4_discard_preallocations
+ext4/ext4_drop_inode
+ext4/ext4_es_cache_extent
+ext4/ext4_es_find_delayed_extent_range_enter
+ext4/ext4_es_find_delayed_extent_range_exit
+ext4/ext4_es_insert_extent
+ext4/ext4_es_lookup_extent_enter
+ext4/ext4_es_lookup_extent_exit
+ext4/ext4_es_remove_extent
+ext4/ext4_es_shrink
+ext4/ext4_es_shrink_count
+ext4/ext4_es_shrink_scan_enter
+ext4/ext4_es_shrink_scan_exit
+ext4/ext4_evict_inode
+ext4/ext4_ext_convert_to_initialized_enter
+ext4/ext4_ext_convert_to_initialized_fastpath
+ext4/ext4_ext_handle_unwritten_extents
+ext4/ext4_ext_in_cache
+ext4/ext4_ext_load_extent
+ext4/ext4_ext_map_blocks_enter
+ext4/ext4_ext_map_blocks_exit
+ext4/ext4_ext_put_in_cache
+ext4/ext4_ext_remove_space
+ext4/ext4_ext_remove_space_done
+ext4/ext4_ext_rm_idx
+ext4/ext4_ext_rm_leaf
+ext4/ext4_ext_show_extent
+ext4/ext4_fallocate_enter
+ext4/ext4_fallocate_exit
+ext4/ext4_find_delalloc_range
+ext4/ext4_forget
+ext4/ext4_free_blocks
+ext4/ext4_free_inode
+ext4/ext4_get_implied_cluster_alloc_exit
+ext4/ext4_get_reserved_cluster_alloc
+ext4/ext4_ind_map_blocks_enter
+ext4/ext4_ind_map_blocks_exit
+ext4/ext4_insert_range
+ext4/ext4_invalidatepage
+ext4/ext4_journal_start
+ext4/ext4_journal_start_reserved
+ext4/ext4_journalled_invalidatepage
+ext4/ext4_journalled_write_end
+ext4/ext4_load_inode
+ext4/ext4_load_inode_bitmap
+ext4/ext4_mark_inode_dirty
+ext4/ext4_mb_bitmap_load
+ext4/ext4_mb_buddy_bitmap_load
+ext4/ext4_mb_discard_preallocations
+ext4/ext4_mb_new_group_pa
+ext4/ext4_mb_new_inode_pa
+ext4/ext4_mb_release_group_pa
+ext4/ext4_mb_release_inode_pa
+ext4/ext4_mballoc_alloc
+ext4/ext4_mballoc_discard
+ext4/ext4_mballoc_free
+ext4/ext4_mballoc_prealloc
+ext4/ext4_other_inode_update_time
+ext4/ext4_punch_hole
+ext4/ext4_read_block_bitmap_load
+ext4/ext4_readpage
+ext4/ext4_releasepage
+ext4/ext4_remove_blocks
+ext4/ext4_request_blocks
+ext4/ext4_request_inode
+ext4/ext4_sync_fs
+ext4/ext4_trim_all_free
+ext4/ext4_trim_extent
+ext4/ext4_truncate_enter
+ext4/ext4_truncate_exit
+ext4/ext4_unlink_enter
+ext4/ext4_unlink_exit
+ext4/ext4_write_begin
+removed
+removed
+removed
+removed
+removed
+removed
+removed
+removed
+removed
+removed
+ext4/ext4_write_end
+ext4/ext4_writepage
+ext4/ext4_writepages
+ext4/ext4_writepages_result
+ext4/ext4_zero_range
+task/task_newtask
+task/task_rename
+sched/sched_process_exec
+sched/sched_process_exit
+sched/sched_process_fork
+sched/sched_process_free
+sched/sched_process_hang
+sched/sched_process_wait
+f2fs/f2fs_do_submit_bio
+f2fs/f2fs_evict_inode
+f2fs/f2fs_fallocate
+f2fs/f2fs_get_data_block
+f2fs/f2fs_get_victim
+f2fs/f2fs_iget
+f2fs/f2fs_iget_exit
+f2fs/f2fs_new_inode
+f2fs/f2fs_readpage
+f2fs/f2fs_reserve_new_block
+f2fs/f2fs_set_page_dirty
+f2fs/f2fs_submit_write_page
+f2fs/f2fs_sync_file_enter
+f2fs/f2fs_sync_file_exit
+f2fs/f2fs_sync_fs
+f2fs/f2fs_truncate
+f2fs/f2fs_truncate_blocks_enter
+f2fs/f2fs_truncate_blocks_exit
+f2fs/f2fs_truncate_data_blocks_range
+f2fs/f2fs_truncate_inode_blocks_enter
+f2fs/f2fs_truncate_inode_blocks_exit
+f2fs/f2fs_truncate_node
+f2fs/f2fs_truncate_nodes_enter
+f2fs/f2fs_truncate_nodes_exit
+f2fs/f2fs_truncate_partial_nodes
+f2fs/f2fs_unlink_enter
+f2fs/f2fs_unlink_exit
+f2fs/f2fs_vm_page_mkwrite
+f2fs/f2fs_write_begin
+f2fs/f2fs_write_checkpoint
+f2fs/f2fs_write_end
+kmem/alloc_pages_iommu_end
+kmem/alloc_pages_iommu_fail
+kmem/alloc_pages_iommu_start
+kmem/alloc_pages_sys_end
+kmem/alloc_pages_sys_fail
+kmem/alloc_pages_sys_start
+kmem/dma_alloc_contiguous_retry
+kmem/iommu_map_range
+kmem/iommu_sec_ptbl_map_range_end
+kmem/iommu_sec_ptbl_map_range_start
+kmem/ion_alloc_buffer_end
+kmem/ion_alloc_buffer_fail
+kmem/ion_alloc_buffer_fallback
+kmem/ion_alloc_buffer_start
+kmem/ion_cp_alloc_retry
+kmem/ion_cp_secure_buffer_end
+kmem/ion_cp_secure_buffer_start
+kmem/ion_prefetching
+kmem/ion_secure_cma_add_to_pool_end
+kmem/ion_secure_cma_add_to_pool_start
+kmem/ion_secure_cma_allocate_end
+kmem/ion_secure_cma_allocate_start
+kmem/ion_secure_cma_shrink_pool_end
+kmem/ion_secure_cma_shrink_pool_start
+kmem/kfree
+kmem/kmalloc
+kmem/kmalloc_node
+kmem/kmem_cache_alloc
+kmem/kmem_cache_alloc_node
+kmem/kmem_cache_free
+kmem/migrate_pages_end
+kmem/migrate_pages_start
+kmem/migrate_retry
+kmem/mm_page_alloc
+kmem/mm_page_alloc_extfrag
+kmem/mm_page_alloc_zone_locked
+kmem/mm_page_free
+kmem/mm_page_free_batched
+kmem/mm_page_pcpu_drain
+kmem/rss_stat
+kmem/ion_heap_shrink
+kmem/ion_heap_grow
+fence/fence_init
+fence/fence_destroy
+fence/fence_enable_signal
+fence/fence_signaled
+clk/clk_enable
+clk/clk_disable
+clk/clk_set_rate
+binder/binder_transaction_alloc_buf
+signal/signal_deliver
+signal/signal_generate
+oom/oom_score_adj_update
+mm_event/mm_event_record
+raw_syscalls/sys_enter
+raw_syscalls/sys_exit
+systrace/0
+power/gpu_frequency
+sde/tracing_mark_write
+oom/mark_victim
+ion/ion_stat
+kmem/ion_buffer_create
+kmem/ion_buffer_destroy
+gpu_mem/gpu_mem_total
diff --git a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
index 13d2803..e230a9e 100644
--- a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
@@ -16,9 +16,6 @@
 
 #include "tools/ftrace_proto_gen/ftrace_descriptor_gen.h"
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-
 namespace perfetto {
 
 void GenerateFtraceDescriptors(
diff --git a/tools/ftrace_proto_gen/ftrace_descriptor_gen.h b/tools/ftrace_proto_gen/ftrace_descriptor_gen.h
index f713ee7..1a2f6ab 100644
--- a/tools/ftrace_proto_gen/ftrace_descriptor_gen.h
+++ b/tools/ftrace_proto_gen/ftrace_descriptor_gen.h
@@ -17,15 +17,12 @@
 #ifndef TOOLS_FTRACE_PROTO_GEN_FTRACE_DESCRIPTOR_GEN_H_
 #define TOOLS_FTRACE_PROTO_GEN_FTRACE_DESCRIPTOR_GEN_H_
 
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+
 #include "perfetto/base/logging.h"
 #include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
 
-namespace google {
-namespace protobuf {
-class DescriptorPool;
-}
-}  // namespace google
-
 namespace perfetto {
 
 // Uses the ftrace event descriptor file to generate a
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index b372ee5..7ed8110 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -16,6 +16,9 @@
 
 #include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
 
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
 #include <algorithm>
 #include <fstream>
 #include <regex>
@@ -56,10 +59,8 @@
 std::string EventNameToProtoFieldName(const std::string& group,
                                       const std::string& name) {
   std::string event_name = (name == "0") ? "zero" : name;
-  // These groups have events where the name alone conflicts with an existing
-  // proto:
-  if (group == "sde" || group == "g2d" || group == "dpu" || group == "mali") {
-    event_name = group + "_" + event_name;
+  if (group == "sde") {
+    event_name = "sde_" + event_name;
   }
   return event_name;
 }
@@ -69,12 +70,12 @@
   return ToCamelCase(EventNameToProtoFieldName(group, name)) + "FtraceEvent";
 }
 
-std::vector<FtraceEventName> ReadAllowList(const std::string& filename) {
+std::vector<FtraceEventName> ReadWhitelist(const std::string& filename) {
   std::string line;
   std::vector<FtraceEventName> lines;
   std::ifstream fin(filename, std::ios::in);
   if (!fin) {
-    fprintf(stderr, "failed to open event list %s\n", filename.c_str());
+    fprintf(stderr, "failed to open whitelist %s\n", filename.c_str());
     return lines;
   }
   while (std::getline(fin, line)) {
@@ -115,7 +116,7 @@
   return true;
 }
 
-void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_eventlist,
+void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
                               const std::set<std::string>& groups,
                               std::ostream* fout) {
   *fout << kCopyrightHeader;
@@ -147,7 +148,7 @@
 )";
 
   int i = 3;
-  for (const FtraceEventName& event : raw_eventlist) {
+  for (const FtraceEventName& event : raw_whitelist) {
     if (!event.valid()) {
       *fout << "    // removed field with id " << i << ";\n";
       ++i;
@@ -220,7 +221,7 @@
   return s;
 }
 
-// This will generate the event_info.cc file for the listed protos.
+// This will generate the event_info.cc file for the whitelisted protos.
 void GenerateEventInfo(const std::vector<std::string>& events_info,
                        std::ostream* fout) {
   std::string s = kCopyrightHeader;
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.h b/tools/ftrace_proto_gen/ftrace_proto_gen.h
index 5d6d0e3..f9faed4 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.h
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.h
@@ -24,7 +24,7 @@
 #include <string>
 #include <vector>
 
-#include "src/traced/probes/ftrace/format_parser/format_parser.h"
+#include "src/traced/probes/ftrace/format_parser.h"
 #include "tools/ftrace_proto_gen/proto_gen_utils.h"
 
 namespace perfetto {
@@ -38,8 +38,8 @@
 std::string EventNameToProtoFieldName(const std::string& group,
                                       const std::string& name);
 
-std::vector<FtraceEventName> ReadAllowList(const std::string& filename);
-void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_eventlist,
+std::vector<FtraceEventName> ReadWhitelist(const std::string& filename);
+void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
                               const std::set<std::string>& groups,
                               std::ostream* fout);
 std::string SingleEventInfo(perfetto::Proto proto,
diff --git a/tools/ftrace_proto_gen/main.cc b/tools/ftrace_proto_gen/main.cc
index 6fca8ce..d051c4a 100644
--- a/tools/ftrace_proto_gen/main.cc
+++ b/tools/ftrace_proto_gen/main.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <getopt.h>
 #include <sys/stat.h>
 #include <fstream>
 #include <map>
@@ -28,8 +29,7 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
-#include "src/traced/probes/ftrace/format_parser/format_parser.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"
 
@@ -45,24 +45,25 @@
 
 void PrintUsage(const char* bin_name) {
   fprintf(stderr,
-          "Usage: %s -w event_list_path -o output_dir -d proto_descriptor "
+          "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) {
-  static option long_options[] = {
-      {"event_list", required_argument, nullptr, 'w'},
+  static struct option long_options[] = {
+      {"whitelist_path", required_argument, nullptr, 'w'},
       {"output_dir", required_argument, nullptr, 'o'},
       {"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;
 
-  std::string event_list_path;
+  std::string whitelist_path;
   std::string output_dir;
   std::string proto_descriptor;
   bool update_build_files = false;
@@ -70,10 +71,10 @@
   std::unique_ptr<std::ostream> (*ostream_factory)(const std::string&) =
       &MakeOFStream;
 
-  while ((c = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
+  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
     switch (c) {
       case 'w':
-        event_list_path = optarg;
+        whitelist_path = optarg;
         break;
       case 'o':
         output_dir = optarg;
@@ -99,12 +100,12 @@
     return 1;
   }
 
-  PERFETTO_CHECK(!event_list_path.empty());
+  PERFETTO_CHECK(!whitelist_path.empty());
   PERFETTO_CHECK(!output_dir.empty());
   PERFETTO_CHECK(!proto_descriptor.empty());
 
-  std::vector<perfetto::FtraceEventName> event_list =
-      perfetto::ReadAllowList(event_list_path);
+  std::vector<perfetto::FtraceEventName> whitelist =
+      perfetto::ReadWhitelist(whitelist_path);
   std::vector<std::string> events_info;
 
   google::protobuf::DescriptorPool descriptor_pool;
@@ -126,7 +127,7 @@
   std::set<std::string> groups;
   std::multimap<std::string, const perfetto::FtraceEventName*> group_to_event;
   std::set<std::string> new_events;
-  for (const auto& event : event_list) {
+  for (const auto& event : whitelist) {
     if (!event.valid())
       continue;
     groups.emplace(event.group());
@@ -142,7 +143,7 @@
   {
     std::unique_ptr<std::ostream> out =
         ostream_factory(output_dir + "/ftrace_event.proto");
-    perfetto::GenerateFtraceEventProto(event_list, groups, out.get());
+    perfetto::GenerateFtraceEventProto(whitelist, groups, out.get());
   }
 
   for (const std::string& group : groups) {
@@ -199,7 +200,7 @@
       }
 
       uint32_t i = 0;
-      for (; it->second != &event_list[i]; i++)
+      for (; it->second != &whitelist[i]; i++)
         ;
 
       // The first id used for events in FtraceEvent proto is 3.
diff --git a/tools/ftrace_proto_gen/proto_gen_utils.cc b/tools/ftrace_proto_gen/proto_gen_utils.cc
index 189c8f1..ba29c72 100644
--- a/tools/ftrace_proto_gen/proto_gen_utils.cc
+++ b/tools/ftrace_proto_gen/proto_gen_utils.cc
@@ -16,6 +16,9 @@
 
 #include "tools/ftrace_proto_gen/proto_gen_utils.h"
 
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
 #include <algorithm>
 #include <fstream>
 #include <regex>
@@ -32,7 +35,7 @@
 namespace {
 
 std::string RunClangFmt(const std::string& input) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   const std::string platform = "mac";
 #else
   const std::string platform = "linux64";
diff --git a/tools/ftrace_proto_gen/proto_gen_utils.h b/tools/ftrace_proto_gen/proto_gen_utils.h
index 2f9b300..805c402 100644
--- a/tools/ftrace_proto_gen/proto_gen_utils.h
+++ b/tools/ftrace_proto_gen/proto_gen_utils.h
@@ -25,14 +25,14 @@
 
 #include <google/protobuf/descriptor.h>
 
-#include "src/traced/probes/ftrace/format_parser/format_parser.h"
+#include "src/traced/probes/ftrace/format_parser.h"
 
 namespace perfetto {
 
 class VerifyStream : public std::ostringstream {
  public:
   VerifyStream(std::string filename);
-  ~VerifyStream() override;
+  virtual ~VerifyStream();
 
  private:
   std::string filename_;
diff --git a/tools/gen_all b/tools/gen_all
index b065236..92d545c 100755
--- a/tools/gen_all
+++ b/tools/gen_all
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,7 +49,6 @@
         'Output directory "{}" is not a directory'.format(out)
     check_only = ['--check-only'] if args.check_only else []
     call('check_include_violations')
-    call('check_proto_comments')
     call('fix_include_guards', *check_only)
     call('gen_bazel', *check_only)
     call('gen_android_bp', *check_only)
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
index bff4641..79a572d 100755
--- a/tools/gen_amalgamated
+++ b/tools/gen_amalgamated
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,24 +53,22 @@
 # 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
-# include each other but rely on forward declarations. The alternative would
+# 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. We also do this for cpp bindings since some
-# tracing SDK functions depend on them (and the system tracing IPC mechanism
-# does so too).
-recurse_in_header_deps = '^//protos/.*(cpp|zero)$'
+# but doing that is unmaintainable.
+recurse_in_header_deps = '^//protos/.*zero$'
 
 # Compiler flags which aren't filtered out.
-cflag_allowlist = r'^-(W.*|fno-exceptions|fPIC|std.*|fvisibility.*)$'
+cflag_whitelist = r'^-(W.*|fno-exceptions|fPIC|std.*|fvisibility.*)$'
 
 # Linker flags which aren't filtered out.
-ldflag_allowlist = r'^-()$'
+ldflag_whitelist = r'^-()$'
 
 # Libraries which are filtered out.
-lib_denylist = r'^(c|gcc_eh)$'
+lib_blacklist = r'^(c|gcc_eh)$'
 
 # Macros which aren't filtered out.
-define_allowlist = r'^(PERFETTO.*|GOOGLE_PROTOBUF.*)$'
+define_whitelist = r'^(PERFETTO.*|GOOGLE_PROTOBUF.*)$'
 
 # Includes which will be removed from the generated source.
 includes_to_remove = r'^(gtest).*$'
@@ -138,12 +136,12 @@
 """ % tool_name
 
 
-def apply_denylist(denylist, items):
-  return [item for item in items if not re.match(denylist, item)]
+def apply_blacklist(blacklist, items):
+  return [item for item in items if not re.match(blacklist, item)]
 
 
-def apply_allowlist(allowlist, items):
-  return [item for item in items if re.match(allowlist, item)]
+def apply_whitelist(whitelist, items):
+  return [item for item in items if re.match(whitelist, item)]
 
 
 def normalize_path(path):
@@ -241,7 +239,7 @@
     self._add_target_headers(target_name)
 
     # Recurse into target deps, but only for protos. This generates headers
-    # for all the .{pbzero,gen}.h files, even if they don't #include each other.
+    # 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)):
@@ -297,7 +295,7 @@
         result.append(flag)
       else:
         result[-1] += flag
-    return apply_allowlist(cflag_allowlist, result)
+    return apply_whitelist(cflag_whitelist, result)
 
   def _add_target_flags(self, target_name):
     for target_name in self._iterate_target_and_deps(target_name):
@@ -305,10 +303,10 @@
       self.cflags.update(self._filter_cflags(target.get('cflags', [])))
       self.cflags.update(self._filter_cflags(target.get('cflags_cc', [])))
       self.ldflags.update(
-          apply_allowlist(ldflag_allowlist, target.get('ldflags', [])))
-      self.libs.update(apply_denylist(lib_denylist, target.get('libs', [])))
+          apply_whitelist(ldflag_whitelist, target.get('ldflags', [])))
+      self.libs.update(apply_blacklist(lib_blacklist, target.get('libs', [])))
       self.defines.update(
-          apply_allowlist(define_allowlist, target.get('defines', [])))
+          apply_whitelist(define_whitelist, target.get('defines', [])))
 
   def _add_target_headers(self, target_name):
     target = self.desc[target_name]
@@ -331,8 +329,6 @@
 
   def _add_source_included_header(self, include_dirs, allowed_files,
                                   header_name):
-    if header_name in self._processed_headers:
-      return
     if header_name in self._processed_source_headers:
       return
     self._processed_source_headers.add(header_name)
@@ -511,6 +507,7 @@
       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:
@@ -528,16 +525,7 @@
     """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')
-
-    if sys.platform.startswith('linux'):
-      llvm_script = os.path.join(gn_utils.repo_root(), 'gn',
-                                 'standalone', 'toolchain',
-                                 'linux_find_llvm.py')
-      cxx = subprocess.check_output([llvm_script]).splitlines()[2].decode()
-    else:
-      cxx = 'clang++'
-
-    build_cmd = [cxx, source, '-o', library, '-shared'] + \
+    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)
@@ -580,13 +568,6 @@
   args = parser.parse_args()
   targets = args.targets or default_targets
 
-  # The CHANGELOG mtime triggers the the perfetto_version.gen.h genrule. This is
-  # to avoid emitting a stale version information in the remote case of somebody
-  # running gen_amalgamated incrementally after having moved to another commit.
-  changelog_path = os.path.join(project_root, 'CHANGELOG')
-  assert(os.path.exists(changelog_path))
-  subprocess.check_call(['touch', '-c', changelog_path])
-
   output = args.output
   if args.check:
     output = os.path.join(tempfile.mkdtemp(), 'perfetto_amalgamated')
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 9c4f408..099c384 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,7 +26,6 @@
 # libraries are also mapped to their Android equivalents -- see |builtin_deps|.
 
 import argparse
-import collections
 import json
 import os
 import re
@@ -58,14 +57,10 @@
     '//src/perfetto_cmd:perfetto',
     '//src/perfetto_cmd:trigger_perfetto',
     '//src/profiling/memory:heapprofd_client',
-    '//src/profiling/memory:heapprofd_client_api',
-    '//src/profiling/memory:heapprofd_api_noop',
     '//src/profiling/memory:heapprofd',
-    '//src/profiling/memory:heapprofd_standalone_client',
     '//src/profiling/perf:traced_perf',
     '//src/traced/probes:traced_probes',
     '//src/traced/service:traced',
-    '//src/trace_processor:trace_processor_shell',
     '//test/cts:perfetto_cts_deps',
     '//test/cts:perfetto_cts_jni_deps',
     '//test:perfetto_gtest_logcat_printer',
@@ -79,6 +74,7 @@
     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,
@@ -93,24 +89,21 @@
 }
 
 target_host_supported = [
-    '//:libperfetto',
     '//protos/perfetto/trace:perfetto_trace_protos',
-    '//src/trace_processor:trace_processor_shell',
+    '//:libperfetto',
 ]
 
 # All module names are prefixed with this string to avoid collisions.
 module_prefix = 'perfetto_'
 
 # Shared libraries which are directly translated to Android system equivalents.
-shared_library_allowlist = [
+shared_library_whitelist = [
     'android',
     'android.hardware.atrace@1.0',
     'android.hardware.health@2.0',
     'android.hardware.power.stats@1.0',
-    "android.hardware.power.stats-V1-cpp",
     'base',
     'binder',
-    'binder_ndk',
     'cutils',
     'hidlbase',
     'hidltransport',
@@ -119,12 +112,11 @@
     'log',
     'services',
     'statssocket',
-    "tracingproxy",
     'utils',
 ]
 
 # Static libraries which are directly translated to Android system equivalents.
-static_library_allowlist = [
+static_library_whitelist = [
     'statslog_perfetto',
 ]
 
@@ -135,17 +127,11 @@
 # Location of the project in the Android source tree.
 tree_path = 'external/perfetto'
 
-# Path for the protobuf sources in the standalone build.
-buildtools_protobuf_src = '//buildtools/protobuf/src'
-
-# Location of the protobuf src dir in the Android source tree.
-android_protobuf_src = 'external/protobuf/src'
-
 # Compiler flags which are passed through to the blueprint.
-cflag_allowlist = r'^-DPERFETTO.*$'
+cflag_whitelist = r'^-DPERFETTO.*$'
 
 # Compiler defines which are passed through to the blueprint.
-define_allowlist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
+define_whitelist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
 
 # Shared libraries which are not in PDK.
 library_not_in_pdk = {
@@ -174,77 +160,35 @@
 
 # Additional arguments to apply to Android.bp rules.
 additional_args = {
-    'heapprofd_client_api': [
-        ('static_libs', {'libasync_safe'}),
-        # heapprofd_client_api MUST NOT have global constructors. Because it
-        # is loaded in an __attribute__((constructor)) of libc, we cannot
-        # guarantee that the global constructors get run before it is used.
-        ('cflags', {'-Wglobal-constructors', '-Werror=global-constructors'}),
-        ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
-        ('stubs', {
-          'versions': ['S'],
-          'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
-        }),
-        ('export_include_dirs', {'src/profiling/memory/include'}),
-    ],
-    'heapprofd_api_noop': [
-        ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
-        ('stubs', {
-          'versions': ['S'],
-          'symbol_file': 'src/profiling/memory/heapprofd_client_api.map.txt',
-        }),
-        ('export_include_dirs', {'src/profiling/memory/include'}),
-    ],
     'heapprofd_client': [
         ('include_dirs', {'bionic/libc'}),
         ('static_libs', {'libasync_safe'}),
-    ],
-    'heapprofd_standalone_client': [
-        ('static_libs', {'libasync_safe'}),
-        ('version_script', 'src/profiling/memory/heapprofd_client_api.map.txt'),
-        ('export_include_dirs', {'src/profiling/memory/include'}),
-        ('stl', 'libc++_static'),
+        ('header_libs', {'bionic_libc_platform_headers'}),
     ],
     'perfetto_unittests': [
         ('data', set(enumerate_data_deps())),
         ('include_dirs', {'bionic/libc/kernel'}),
     ],
-    'perfetto_integrationtests': [
-      ('test_suites', {'general-tests'}),
-      ('test_config', 'PerfettoIntegrationTests.xml'),
-    ],
     'traced_probes': [
         ('required', {'libperfetto_android_internal',
                       'trigger_perfetto',
-                      'traced_perf',
-                      'mm_events'}),
+                      'traced_perf'}),
     ],
     'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
     'trace_processor_shell': [
-      ('strip', {'all': True}),
-      ('host', {
-        'stl': 'libc++_static',
-        'dist': {'targets': ['sdk_repo']},
-      }),
+      ('stl', 'libc++_static'),
     ],
     'libperfetto_client_experimental': [
       ('apex_available', {
         '//apex_available:platform',
-        'com.android.art',
-        'com.android.art.debug'}),
-      ('min_sdk_version', 'S'),
-      ('shared_libs', {'liblog'}),
-      ('export_include_dirs', {'include', buildflags_dir}),
+        'com.android.art.debug',
+        'com.android.art.release'}),
     ],
     'perfetto_trace_protos': [
       ('apex_available', {
         '//apex_available:platform',
-        'com.android.art',
-        'com.android.art.debug'}),
-      ('min_sdk_version', 'S'),
-    ],
-    'libperfetto': [
-      ('export_include_dirs', {'include', buildflags_dir}),
+        'com.android.art.debug',
+        'com.android.art.release'}),
     ],
 }
 
@@ -257,13 +201,7 @@
 
 
 def enable_protobuf_full(module):
-  if module.type == 'cc_binary_host':
-    module.static_libs.add('libprotobuf-cpp-full')
-  elif module.host_supported:
-    module.host.static_libs.add('libprotobuf-cpp-full')
-    module.android.shared_libs.add('libprotobuf-cpp-full')
-  else:
-    module.shared_libs.add('libprotobuf-cpp-full')
+  module.shared_libs.add('libprotobuf-cpp-full')
 
 
 def enable_protobuf_lite(module):
@@ -278,16 +216,9 @@
 
 
 def enable_libunwindstack(module):
-  if module.name != 'heapprofd_standalone_client':
-    module.shared_libs.add('libunwindstack')
-    module.shared_libs.add('libprocinfo')
-    module.shared_libs.add('libbase')
-  else:
-    module.static_libs.add('libunwindstack')
-    module.static_libs.add('libprocinfo')
-    module.static_libs.add('libbase')
-    module.static_libs.add('liblzma')
-    module.static_libs.add('libdexfile_support')
+  module.shared_libs.add('libunwindstack')
+  module.shared_libs.add('libprocinfo')
+  module.shared_libs.add('libbase')
 
 
 def enable_libunwind(module):
@@ -298,26 +229,18 @@
 def enable_sqlite(module):
   if module.type == 'cc_binary_host':
     module.static_libs.add('libsqlite')
-  elif module.host_supported:
+  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')
-  else:
-    module.shared_libs.add('libsqlite')
-    module.shared_libs.add('libandroidicu')
-    module.shared_libs.add('liblog')
-    module.shared_libs.add('libutils')
 
 
 def enable_zlib(module):
   if module.type == 'cc_binary_host':
     module.static_libs.add('libz')
-  elif module.host_supported:
-    module.android.shared_libs.add('libz')
-    module.host.static_libs.add('libz')
   else:
     module.shared_libs.add('libz')
 
@@ -325,9 +248,6 @@
 def enable_uapi_headers(module):
   module.include_dirs.add('bionic/libc/kernel')
 
-def enable_bionic_libc_platform_headers_on_android(module):
-  module.header_libs.add('bionic_libc_platform_headers')
-
 
 # Android equivalents for third-party libraries that the upstream project
 # depends on.
@@ -344,8 +264,6 @@
     '//gn:sqlite': enable_sqlite,
     '//gn:zlib': enable_zlib,
     '//gn:bionic_kernel_uapi_headers' : enable_uapi_headers,
-    '//src/profiling/memory:bionic_libc_platform_headers_on_android':
-      enable_bionic_libc_platform_headers_on_android,
 }
 
 # ----------------------------------------------------------------------------
@@ -408,9 +326,6 @@
     self.static_libs = set()
     self.whole_static_libs = set()
     self.cflags = set()
-    self.dist = dict()
-    self.strip = dict()
-    self.stl = None
 
   def to_string(self, output):
     nested_out = []
@@ -418,9 +333,6 @@
     self._output_field(nested_out, 'static_libs')
     self._output_field(nested_out, 'whole_static_libs')
     self._output_field(nested_out, 'cflags')
-    self._output_field(nested_out, 'stl')
-    self._output_field(nested_out, 'dist')
-    self._output_field(nested_out, 'strip')
 
     if nested_out:
       output.append('  %s: {' % self.name)
@@ -468,16 +380,11 @@
     self.strip = dict()
     self.data = set()
     self.apex_available = set()
-    self.min_sdk_version = None
     # 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()
-    self.version_script = None
-    self.test_suites = set()
-    self.test_config = None
-    self.stubs = {}
 
   def to_string(self, output):
     if self.comment:
@@ -507,11 +414,6 @@
     self._output_field(output, 'data')
     self._output_field(output, 'stl')
     self._output_field(output, 'apex_available')
-    self._output_field(output, 'min_sdk_version')
-    self._output_field(output, 'version_script')
-    self._output_field(output, 'test_suites')
-    self._output_field(output, 'test_config')
-    self._output_field(output, 'stubs')
 
     target_out = []
     self._output_field(target_out, 'android')
@@ -546,25 +448,6 @@
     output.append('}')
     output.append('')
 
-
-  def add_android_static_lib(self, lib):
-    if self.type == 'cc_binary_host':
-      raise Exception('Adding Android static lib for host tool is unsupported')
-    elif self.host_supported:
-      self.android.static_libs.add(lib)
-    else:
-      self.static_libs.add(lib)
-
-
-  def add_android_shared_lib(self, lib):
-    if self.type == 'cc_binary_host':
-      raise Exception('Adding Android shared lib for host tool is unsupported')
-    elif self.host_supported:
-      self.android.shared_libs.add(lib)
-    else:
-      self.shared_libs.add(lib)
-
-
   def _output_field(self, output, name, sort=True):
     value = getattr(self, name)
     return write_blueprint_key_value(output, name, value, sort)
@@ -627,64 +510,20 @@
         The source_genrule module.
     """
   assert (target.type == 'proto_library')
-
-  tools = {'aprotoc'}
   cpp_out_dir = '$(genDir)/%s/' % tree_path
-  target_module_name = label_to_module_name(target.name)
-
-  # In GN builds the proto path is always relative to the output directory
-  # (out/tmp.xxx).
   cmd = ['mkdir -p %s &&' % cpp_out_dir, '$(location aprotoc)']
-  cmd += ['--proto_path=%s' % tree_path]
-
-  if buildtools_protobuf_src in target.proto_paths:
-    cmd += ['--proto_path=%s' % android_protobuf_src]
-
-  # We don't generate any targets for source_set proto modules because
-  # they will be inlined into other modules if required.
-  if target.proto_plugin == 'source_set':
-    return None
-
-  # Descriptor targets only generate a single target.
-  if target.proto_plugin == 'descriptor':
-    out = '{}.bin'.format(target_module_name)
-
-    cmd += ['--descriptor_set_out=$(out)']
-    cmd += ['$(in)']
-
-    descriptor_module = Module('genrule', target_module_name, target.name)
-    descriptor_module.cmd = ' '.join(cmd)
-    descriptor_module.out = [out]
-    descriptor_module.tools = tools
-    blueprint.add_module(descriptor_module)
-
-    # Recursively extract the .proto files of all the dependencies and
-    # add them to srcs.
-    target_queue = collections.deque([target.name])
-    seen_targets = set()
-    while target_queue:
-      dep = target_queue.popleft()
-      if dep in seen_targets:
-        continue
-      seen_targets.add(dep)
-
-      current_target = gn.get_target(dep)
-      descriptor_module.srcs.update(
-          gn_utils.label_to_path(src) for src in current_target.sources)
-      target_queue.extend(current_target.proto_deps)
-
-    return descriptor_module
 
   # 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 = target_module_name + '_gen'
+  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'}
 
   header_module = Module('genrule', source_module_name + '_headers',
                          target.name)
@@ -701,6 +540,10 @@
   source_module.genrule_srcs.add(':' + source_module.name)
   source_module.genrule_headers.add(header_module.name)
 
+  # In GN builds the proto path is always relative to the output directory
+  # (out/tmp.xxx).
+  cmd += ['--proto_path=%s' % tree_path]
+
   if target.proto_plugin == 'proto':
     suffixes = ['pb']
     source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
@@ -743,8 +586,9 @@
 
 
 def create_merged_sql_metrics_module(blueprint, target):
-  bp_module_name = label_to_module_name(target.name)
-  module = Module('genrule', bp_module_name, target.name)
+  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',
   ]
@@ -753,55 +597,17 @@
       '--cpp_out=$(out)',
       '$(in)',
   ])
-  module.genrule_headers.add(module.name)
   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_cc_proto_descriptor_module(blueprint, target):
-  bp_module_name = label_to_module_name(target.name)
-  module = Module('genrule', bp_module_name, target.name)
-  module.tool_files = [
-      'tools/gen_cc_proto_descriptor.py',
-  ]
-  module.cmd = ' '.join([
-      '$(location tools/gen_cc_proto_descriptor.py)',
-      '--gen_dir=$(genDir)',
-      '--cpp_out=$(out)',
-      '$(in)'
-  ])
-  module.genrule_headers.add(module.name)
-  module.srcs.update(
-      ':' + label_to_module_name(dep) for dep in target.proto_deps)
-  module.out.update(target.outputs)
-  blueprint.add_module(module)
-  return module
-
-
-def create_gen_version_module(blueprint, target, bp_module_name):
-  module = Module('genrule', bp_module_name, gn_utils.GEN_VERSION_TARGET)
-  script_path = gn_utils.label_to_path(target.script)
-  module.genrule_headers.add(bp_module_name)
-  module.tool_files = [ script_path ]
-  module.out.update(target.outputs)
-  module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
-  module.cmd = ' '.join([
-        'python3 $(location %s)' % script_path,
-        '--no_git',
-        '--changelog=$(location CHANGELOG)',
-        '--cpp_out=$(out)'
-  ])
-  blueprint.add_module(module)
-  return module
-
-
 def _get_cflags(target):
-  cflags = {flag for flag in target.cflags if re.match(cflag_allowlist, flag)}
+  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_allowlist, define))
+                if re.match(define_whitelist, define))
   return cflags
 
 
@@ -820,6 +626,7 @@
   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:
@@ -831,8 +638,10 @@
     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':
@@ -841,24 +650,13 @@
     return None
   elif target.type == 'proto_library':
     module = create_proto_modules(blueprint, gn, target)
-    if module is None:
-      return None
-  elif target.type == 'action':
-    if 'gen_merged_sql_metrics' in target.name:
-      module = create_merged_sql_metrics_module(blueprint, target)
-    elif re.match('.*gen_cc_.*_descriptor$', target.name):
-      module = create_cc_proto_descriptor_module(blueprint, target)
-    elif target.type == 'action' and gn_utils.label_without_toolchain(
-        target.name) == gn_utils.GEN_VERSION_TARGET:
-      module = create_gen_version_module(blueprint, target, bp_module_name)
-    else:
-      raise Error('Unhandled action: {}'.format(target.name))
+  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))
 
   blueprint.add_module(module)
-  module.host_supported = (gn_utils.label_without_toolchain(target.name) in
-                           target_host_supported)
+  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)
@@ -875,13 +673,12 @@
     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) or AIDL c++
-      # libraries (e.g. "android.hardware.power.stats-V1-cpp")
-      android_lib = lib if '@' in lib or "-cpp" in lib else 'lib' + lib
-      if lib in shared_library_allowlist:
-        module.add_android_shared_lib(android_lib)
-      if lib in static_library_allowlist:
-        module.add_android_static_lib(android_lib)
+      # are HAL libraries (e.g., android.hardware.health@2.0).
+      android_lib = lib if '@' in lib else 'lib' + lib
+      if lib in shared_library_whitelist:
+        module.shared_libs.add(android_lib)
+      if lib in static_library_whitelist:
+        module.static_libs.add(android_lib)
 
   # If the module is a static library, export all the generated headers.
   if module.type == 'cc_library_static':
@@ -894,15 +691,10 @@
       curr.update(add_val)
     elif isinstance(add_val, str) and (not curr or isinstance(curr, str)):
       setattr(module, key, add_val)
-    elif isinstance(add_val, bool) and (not curr or isinstance(curr, bool)):
-      setattr(module, key, add_val)
     elif isinstance(add_val, dict) and isinstance(curr, dict):
       curr.update(add_val)
-    elif isinstance(add_val, dict) and isinstance(curr, Target):
-      curr.__dict__.update(add_val)
     else:
-      raise Error('Unimplemented type %r of additional_args: %r' %
-                  (type(add_val), key))
+      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:
@@ -969,8 +761,7 @@
   # 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,
-      tree_path + '/src/profiling/memory/include'
+      tree_path, tree_path + '/include', tree_path + '/' + buildflags_dir
   }
   defaults.cflags = [
       '-Wno-error=return-type',
@@ -1026,15 +817,6 @@
   gn = gn_utils.GnParser(desc)
   blueprint = create_blueprint_for_targets(gn, desc, args.targets or
                                            default_targets)
-  project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
-  tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
-
-  # TODO(primiano): enable this on Android after the TODO in
-  # perfetto_component.gni is fixed.
-  # Check for ODR violations
-  # for target_name in default_targets:
-    # checker = gn_utils.ODRChecker(gn, target_name)
-
   output = [
       """// Copyright (C) 2017 The Android Open Source Project
 //
@@ -1051,7 +833,7 @@
 // limitations under the License.
 //
 // This file is automatically generated by %s. Do not edit.
-""" % (tool_name)
+""" % (__file__)
   ]
   blueprint.to_string(output)
   with open(args.extras, 'r') as r:
@@ -1064,8 +846,6 @@
   out_files.append(args.output + '.swp')
   with open(out_files[-1], 'w') as f:
     f.write('\n'.join(output))
-    # Text files should have a trailing EOL.
-    f.write('\n')
 
   # Generate the perfetto_build_flags.h file.
   out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
diff --git a/tools/gen_bazel b/tools/gen_bazel
index f4e3650..ce82c1e 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -65,7 +65,7 @@
     '//test:client_api_example',
     '//src/ipc:perfetto_ipc',
     '//src/ipc/protoc_plugin:ipc_plugin',
-    '//src/protozero:protozero',
+    '//src/protozero:libprotozero',
     '//src/protozero/protoc_plugin:protozero_plugin',
     '//src/protozero/protoc_plugin:cppgen_plugin',
 ] + public_targets
@@ -82,9 +82,6 @@
     '//protos/perfetto/config:lite',
 ]
 
-# Path for the protobuf sources in the standalone build.
-buildtools_protobuf_src = '//buildtools/protobuf/src'
-
 # The directory where the generated perfetto_build_flags.h will be copied into.
 buildflags_dir = 'include/perfetto/base/build_configs/bazel'
 
@@ -103,10 +100,10 @@
         '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'
-    ]],
-    gn_utils.GEN_VERSION_TARGET: ['PERFETTO_CONFIG.deps.version_header'],
+        ":cc_merged_sql_metrics"
+    ]]
 }
 
 
@@ -115,30 +112,11 @@
   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.exec_tools += [':gen_merged_sql_metrics_py']
-  return [label]
-
-
-def gen_version_header(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_version_header_py)'
-  label.cmd += r' --cpp_out=$@ --changelog=$(location CHANGELOG)'
-  label.exec_tools += [':gen_version_header_py']
-  return [label]
-
-
-def gen_cc_metrics_descriptor(target):
-  label = BazelLabel(
-      get_bazel_label_name(target.name), 'perfetto_cc_proto_descriptor')
-  label.deps += [':' + get_bazel_label_name(x) for x in target.proto_deps]
-  label.outs += target.outputs
+  label.tools += [':gen_merged_sql_metrics_py']
   return [label]
 
 
 custom_actions = {
-    gn_utils.GEN_VERSION_TARGET: gen_version_header,
     '//src/trace_processor/metrics:gen_merged_sql_metrics': gen_sql_metrics,
 }
 
@@ -163,7 +141,6 @@
     self.deps = []
     self.external_deps = []
     self.tools = []
-    self.exec_tools = []
     self.outs = []
 
   def __lt__(self, other):
@@ -178,10 +155,7 @@
     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',
-      'exec_tools'
-    ]
+    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):
@@ -203,7 +177,7 @@
           indent = '           '
         else:
           indent = '    '
-        for entry in sorted(v):
+        for entry in v:
           if entry.startswith('PERFETTO_CONFIG.'):
             res += '%s    %s,\n' % (indent, entry)
           else:
@@ -233,10 +207,10 @@
 def get_bazel_label_name(gn_name):
   """Converts a GN target name into a Bazel label name.
 
-  If target is in the public target list, returns only the GN target 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 target, returns a mangled path.
+  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:
@@ -248,20 +222,47 @@
   """ Generates the xx_proto_library label for proto targets.
 
   Bazel requires that each protobuf-related target is modeled with two labels:
-  1. A plugin-agnostic target that defines only the .proto sources and their
+  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.
-  2. A plugin-dependent target (e.g. cc_library, cc_protozero_library) that has
-     only a dependency on 1 and does NOT refer to any .proto sources.
   """
   assert (target.type == 'proto_library')
 
   def get_sources_label(target_name):
-    return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '',
+    return re.sub('_(lite|zero|cpp|ipc)$', '',
                   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 in ('cppgen', 'ipc'):
+    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))
@@ -279,60 +280,12 @@
   ]
   sources_label.deps = sorted(deps)
 
-  # In Bazel, proto_paths are not a supported concept becauase strong dependency
-  # checking is enabled. Instead, we need to depend on the target which includes
-  # the proto we want to depend on.
-  # For example, we include the proto_path |buildtools_protobuf_src| because we
-  # want to depend on the "google/protobuf/descriptor.proto" proto file. This
-  # will be exposed by the |protobuf_descriptor_proto| dep.
-  if buildtools_protobuf_src in target.proto_paths:
-    sources_label.external_deps = [
-        'PERFETTO_CONFIG.deps.protobuf_descriptor_proto'
-    ]
-
   if target.name in proto_targets:
     sources_label.visibility = PUBLIC_VISIBILITY
   else:
     sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
 
-  # For 'source_set' plugins, we don't want to generate any plugin-dependent
-  # targets so just return the label of the proto sources only.
-  if target.proto_plugin == 'source_set':
-    return [sources_label]
-
-  # Generates 2.
-  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'
-  elif target.proto_plugin == 'descriptor':
-    plugin_label_type = 'perfetto_proto_descriptor'
-  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 plugins 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}.
-  if target.proto_deps and target.proto_plugin in (
-      'cppgen', 'ipc', 'protozero'):
-    plugin_label.deps += [
-        ':' + get_bazel_label_name(x) for x in target.proto_deps
-    ]
-
-  if target.proto_plugin == 'descriptor':
-    plugin_label.outs = [plugin_label_name + '.bin']
-
-  return [sources_label, plugin_label]
+  return [plugin_label, sources_label]
 
 
 def gen_target(gn_target):
@@ -341,8 +294,6 @@
   elif gn_target.type == 'action':
     if gn_target.name in custom_actions:
       return custom_actions[gn_target.name](gn_target)
-    elif re.match('.*gen_cc_.*_descriptor$', gn_target.name):
-      return gen_cc_metrics_descriptor(gn_target)
     return []
   elif gn_target.type == 'group':
     return []
@@ -361,19 +312,10 @@
   label = BazelLabel(get_bazel_label_name(gn_target.name), bazel_type)
   label.comment = gn_target.name
 
-  # Supporting 'public' on source_sets would require not converting them to
-  # filegroups in bazel.
-  if gn_target.public_headers:
-    if bazel_type == 'perfetto_cc_library':
-      label.hdrs += [x[2:] for x in gn_target.public_headers]
-    else:
-      raise Error('%s: \'public\' currently supported only for cc_library' %
-              gn_target.name)
-
   raw_srcs = [x[2:] for x in gn_target.sources]
   if bazel_type == 'perfetto_cc_library':
-    label.srcs += [x for x in raw_srcs if not x.startswith('include')]
-    label.hdrs += [x for x in raw_srcs if x.startswith('include')]
+    label.srcs = [x for x in raw_srcs if not x.startswith('include')]
+    label.hdrs = [x for x in raw_srcs if x.startswith('include')]
 
     # Most Perfetto libraries cannot by dynamically linked as they would
     # cause ODR violations.
@@ -421,8 +363,6 @@
 
 def generate_build(gn_desc, targets, extras):
   gn = gn_utils.GnParser(gn_desc)
-  project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
-  tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
   res = '''
 # Copyright (C) 2019 The Android Open Source Project
 #
@@ -446,16 +386,13 @@
     "perfetto_cc_binary",
     "perfetto_cc_ipc_library",
     "perfetto_cc_library",
-    "perfetto_cc_proto_descriptor",
     "perfetto_cc_proto_library",
     "perfetto_cc_protocpp_library",
     "perfetto_cc_protozero_library",
     "perfetto_java_proto_library",
     "perfetto_java_lite_proto_library",
     "perfetto_proto_library",
-    "perfetto_proto_descriptor",
     "perfetto_py_binary",
-    "perfetto_py_library",
     "perfetto_gensignature_internal_only",
 )
 
@@ -465,7 +402,7 @@
 
 exports_files(["NOTICE"])
 
-'''.format(tool_name).lstrip()
+'''.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
@@ -526,13 +463,9 @@
   res += public_str
   res += '# Content from BUILD.extras\n\n'
   res += extras
-
-  # Check for ODR violations
-  for target_name in default_targets + proto_targets:
-    checker = gn_utils.ODRChecker(gn, target_name)
-
   return res
 
+
 def main():
   parser = argparse.ArgumentParser(
       description='Generate BUILD from a GN description.')
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index d25d9bd..ae752f8 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,22 +18,26 @@
 from __future__ import print_function
 import os
 import re
+import sys
 import argparse
 import tempfile
 import subprocess
 import hashlib
+import textwrap
 from compat import iteritems
 
-SOURCE_TARGET = [
-    (
-      'protos/perfetto/trace_processor/trace_processor.proto',
-      'src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor'
-    ),
-    (
-      'protos/perfetto/metrics/metrics.proto',
-      'src/trace_processor/python/perfetto/trace_processor/metrics.descriptor'
-    ),
-]
+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/protozero/test/example_proto/test_messages.proto':
+        'src/protozero/test/example_proto/test_messages.descriptor.h',
+    'protos/perfetto/trace/track_event/track_event.proto':
+        'src/trace_processor/importers/proto/track_event.descriptor.h',
+    'protos/perfetto/metrics/custom_options.proto':
+        'src/trace_processor/metrics/custom_options.descriptor.h',
+}
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
 
@@ -54,16 +58,11 @@
   return None
 
 
-
 def check(source, target):
   assert os.path.exists(os.path.join(ROOT_DIR, target)), \
       'Output file {} does not exist and so cannot be checked'.format(target)
 
-  sha1_file = target + '.sha1'
-  assert os.path.exists(sha1_file), \
-      'SHA1 file {} does not exist and so cannot be checked'.format(sha1_file)
-
-  with open(sha1_file, 'rb') as f:
+  with open(target, 'rb') as f:
     s = f.read()
 
   hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s.decode())
@@ -75,6 +74,10 @@
 
 
 def generate(source, target, protoc_path):
+  _, source_name = os.path.split(source)
+  _, target_name = os.path.split(target)
+  assert source_name.replace('.proto', '.descriptor.h') == target_name
+
   with tempfile.NamedTemporaryFile() as fdescriptor:
     subprocess.check_call([
         protoc_path,
@@ -88,23 +91,74 @@
                           cwd=ROOT_DIR)
 
     s = fdescriptor.read()
-    with open(target, 'wb') as out:
-      out.write(s)
+    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='     ')
+    include_guard = target.replace('/', '_').replace('.', '_').upper() + '_'
 
-    sha1_path = target + '.sha1'
-    with open(sha1_path, 'wb') as c:
-      c.write("""
+    with open(os.path.join(ROOT_DIR, target), 'wb') as f:
+      f.write("""/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_guard}
+#define {include_guard}
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+
+// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
+
 // SHA1({script_path})
 // {script_hash}
 // SHA1({source_path})
 // {source_hash}
-  """.format(
+
+// This is the proto {proto_name} encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {{
+
+constexpr std::array<uint8_t, {size}> {constant_name}{{
+{binary}}};
+
+}}  // 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())
 
+
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--check-only', action='store_true')
@@ -112,7 +166,7 @@
   args = parser.parse_args()
 
   try:
-    for source, target in SOURCE_TARGET:
+    for source, target in iteritems(SOURCE_TARGET):
       if args.check_only:
         check(source, target)
       else:
diff --git a/tools/gen_cc_proto_descriptor.py b/tools/gen_cc_proto_descriptor.py
deleted file mode 100755
index 0c2dc66..0000000
--- a/tools/gen_cc_proto_descriptor.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-import os
-import sys
-import argparse
-import tempfile
-import subprocess
-import textwrap
-
-
-def write_cpp_header(gendir, target, descriptor_bytes):
-  _, target_name = os.path.split(target)
-
-  proto_name = target_name[:-len('.descriptor.h')].title().replace("_", "")
-  try:
-    ord(descriptor_bytes[0])
-    ordinal = ord
-  except TypeError:
-    ordinal = lambda x: x
-  binary = '{' + ', '.join(
-      '{0:#04x}'.format(ordinal(c)) for c in descriptor_bytes) + '}'
-  binary = textwrap.fill(
-      binary, width=80, initial_indent='    ', subsequent_indent='     ')
-
-  relative_target = os.path.relpath(target, gendir)
-  include_guard = relative_target.replace('\\', '_').replace('/', '_').replace(
-      '.', '_').upper() + '_'
-
-  with open(target, 'wb') as f:
-    f.write("""/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef {include_guard}
-#define {include_guard}
-
-#include <stddef.h>
-#include <stdint.h>
-#include <array>
-
-namespace perfetto {{
-
-constexpr std::array<uint8_t, {size}> k{proto_name}Descriptor{{
-{binary}}};
-
-}}  // namespace perfetto
-
-#endif  // {include_guard}
-""".format(
-        proto_name=proto_name,
-        size=len(descriptor_bytes),
-        binary=binary,
-        include_guard=include_guard,
-    ).encode())
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--cpp_out', required=True)
-  parser.add_argument('--gen_dir', default='')
-  parser.add_argument('descriptor')
-  args = parser.parse_args()
-
-  with open(args.descriptor, 'rb') as fdescriptor:
-    s = fdescriptor.read()
-    write_cpp_header(args.gen_dir, args.cpp_out, s)
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 67adf4c..dee1920 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +22,6 @@
 from codecs import open
 
 PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-SELF_PATH = os.path.relpath(__file__, PROJECT_ROOT)
 
 CONFIG_PROTO_ROOTS = [
     'protos/perfetto/common/data_source_descriptor.proto',
@@ -31,9 +30,7 @@
 ]
 MERGED_CONFIG_PROTO = 'protos/perfetto/config/perfetto_config.proto'
 
-TRACE_PROTO_ROOTS = CONFIG_PROTO_ROOTS + [
-  'protos/perfetto/trace/trace.proto',
-]
+TRACE_PROTO_ROOTS = CONFIG_PROTO_ROOTS + ['protos/perfetto/trace/trace.proto']
 MERGED_TRACE_PROTO = 'protos/perfetto/trace/perfetto_trace.proto'
 
 METRICS_PROTOS_ROOTS = ['protos/perfetto/metrics/metrics.proto']
@@ -70,14 +67,15 @@
 
 
 def merge_protos_content(proto_paths):
-  merged_content = REPLACEMENT_HEADER.lstrip() % SELF_PATH
+  root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+  merged_content = REPLACEMENT_HEADER.lstrip() % __file__
   added_files = set()
   for proto in proto_paths:
     if proto in added_files:
       continue
     added_files.add(proto)
 
-    path = os.path.join(PROJECT_ROOT, proto)
+    path = os.path.join(root_dir, proto)
     with open(path, 'r', encoding='utf-8') as f:
       content = f.read()
 
@@ -119,12 +117,13 @@
 
 
 def merge_protos(root_paths, output_path):
+  root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
   all_protos = []
   for root_path in root_paths:
     all_protos += get_transitive_imports(root_path, visited=set())
   merged_content = merge_protos_content(all_protos)
 
-  out_path = os.path.join(PROJECT_ROOT, output_path)
+  out_path = os.path.join(root_dir, output_path)
   prev_content = None
   if os.path.exists(out_path):
     with open(out_path, 'r', encoding='utf-8') as fprev:
diff --git a/tools/gen_merged_sql_metrics.py b/tools/gen_merged_sql_metrics.py
index eed5d8e..065ff1b 100755
--- a/tools/gen_merged_sql_metrics.py
+++ b/tools/gen_merged_sql_metrics.py
@@ -95,19 +95,9 @@
     for path, sql in sql_outputs.items():
       name = os.path.basename(path)
       variable = filename_to_variable(os.path.splitext(name)[0])
-      output.write('\nconst char {}[] = '.format(variable))
-      # MSVC doesn't like string literals that are individually longer than 16k.
-      # However it's still fine "if" "we" "concatenate" "many" "of" "them".
-      # This code splits the sql in string literals of ~1000 chars each.
-      line_groups = ['']
-      for line in sql.split('\n'):
-        line_groups[-1] += line + '\n'
-        if len(line_groups[-1]) > 1000:
-          line_groups.append('')
-
-      for line in line_groups:
-        output.write('R"_d3l1m1t3r_({})_d3l1m1t3r_"\n'.format(line))
-      output.write(';\n')
+      output.write(
+          '\nconst char {}[] = R"gendelimiter(\n{})gendelimiter";\n'.format(
+              variable, sql))
 
     output.write(FILE_TO_SQL_STRUCT)
 
diff --git a/tools/gn_utils.py b/tools/gn_utils.py
index 85f0ee5..da69431 100644
--- a/tools/gn_utils.py
+++ b/tools/gn_utils.py
@@ -16,7 +16,6 @@
 # projects.
 
 from __future__ import print_function
-import collections
 import errno
 import filecmp
 import json
@@ -28,17 +27,10 @@
 from compat import iteritems
 
 BUILDFLAGS_TARGET = '//gn:gen_buildflags'
-GEN_VERSION_TARGET = '//src/base:version_gen_h'
 TARGET_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
 HOST_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
 LINKER_UNIT_TYPES = ('executable', 'shared_library', 'static_library')
 
-# TODO(primiano): investigate these, they require further componentization.
-ODR_VIOLATION_IGNORE_TARGETS = {
-    '//test/cts:perfetto_cts_deps',
-    '//:perfetto_integrationtests',
-}
-
 
 def _check_command_output(cmd, cwd):
   try:
@@ -198,79 +190,6 @@
   return res
 
 
-class ODRChecker(object):
-  """Detects ODR violations in linker units
-
-  When we turn GN source sets into Soong & Bazel file groups, there is the risk
-  to create ODR violations by including the same file group into different
-  linker unit (this is because other build systems don't have a concept
-  equivalent to GN's source_set). This class navigates the transitive
-  dependencies (mostly static libraries) of a target and detects if multiple
-  paths end up including the same file group. This is to avoid situations like:
-
-  traced.exe -> base(file group)
-  traced.exe -> libperfetto(static lib) -> base(file group)
-  """
-
-  def __init__(self, gn, target_name):
-    self.gn = gn
-    self.root = gn.get_target(target_name)
-    self.source_sets = collections.defaultdict(set)
-    self.deps_visited = set()
-    self.source_set_hdr_only = {}
-
-    self._visit(target_name)
-    num_violations = 0
-    if target_name in ODR_VIOLATION_IGNORE_TARGETS:
-      return
-    for sset, paths in self.source_sets.items():
-      if self.is_header_only(sset):
-        continue
-      if len(paths) != 1:
-        num_violations += 1
-        print(
-            'ODR violation in target %s, multiple paths include %s:\n  %s' %
-            (target_name, sset, '\n  '.join(paths)),
-            file=sys.stderr)
-    if num_violations > 0:
-      raise Exception('%d ODR violations detected. Build generation aborted' %
-                      num_violations)
-
-  def _visit(self, target_name, parent_path=''):
-    target = self.gn.get_target(target_name)
-    path = ((parent_path + ' > ') if parent_path else '') + target_name
-    if not target:
-      raise Exception('Cannot find target %s' % target_name)
-    for ssdep in target.source_set_deps:
-      name_and_path = '%s (via %s)' % (target_name, path)
-      self.source_sets[ssdep].add(name_and_path)
-    deps = set(target.deps).union(target.proto_deps) - self.deps_visited
-    for dep_name in deps:
-      dep = self.gn.get_target(dep_name)
-      if dep.type == 'executable':
-        continue  # Execs are strong boundaries and don't cause ODR violations.
-      # static_library dependencies should reset the path. It doesn't matter if
-      # we get to a source file via:
-      # source_set1 > static_lib > source.cc OR
-      # source_set1 > source_set2 > static_lib > source.cc
-      # This is NOT an ODR violation because source.cc is linked from the same
-      # static library
-      next_parent_path = path if dep.type != 'static_library' else ''
-      self.deps_visited.add(dep_name)
-      self._visit(dep_name, next_parent_path)
-
-  def is_header_only(self, source_set_name):
-    cached = self.source_set_hdr_only.get(source_set_name)
-    if cached is not None:
-      return cached
-    target = self.gn.get_target(source_set_name)
-    if target.type != 'source_set':
-      raise TypeError('%s is not a source_set' % source_set_name)
-    res = all(src.endswith('.h') for src in target.sources)
-    self.source_set_hdr_only[source_set_name] = res
-    return res
-
-
 class GnParser(object):
   """A parser with some cleverness for GN json desc files
 
@@ -305,15 +224,11 @@
       self.testonly = False
       self.toolchain = None
 
-      # These are valid only for type == proto_library.
+      # Only set when type == proto_library.
       # This is typically: 'proto', 'protozero', 'ipc'.
       self.proto_plugin = None
-      self.proto_paths = set()
 
       self.sources = set()
-      # TODO(primiano): consider whether the public section should be part of
-      # bubbled-up sources.
-      self.public_headers = set()  # 'public'
 
       # These are valid only for type == 'action'
       self.inputs = set()
@@ -356,7 +271,7 @@
 
     def update(self, other):
       for key in ('cflags', 'defines', 'deps', 'include_dirs', 'ldflags',
-                  'source_set_deps', 'proto_deps', 'libs', 'proto_paths'):
+                  'source_set_deps', 'proto_deps', 'libs'):
         self.__dict__[key].update(other.__dict__.get(key, []))
 
   def __init__(self, gn_desc):
@@ -399,7 +314,6 @@
       self.proto_libs[target.name] = target
       target.type = 'proto_library'
       target.proto_plugin = proto_target_type
-      target.proto_paths.update(self.get_proto_paths(proto_desc))
       target.sources.update(proto_desc.get('sources', []))
       assert (all(x.endswith('.proto') for x in target.sources))
     elif target.type == 'source_set':
@@ -410,8 +324,7 @@
       target.sources.update(desc.get('sources', []))
     elif target.type == 'action':
       self.actions[gn_target_name] = target
-      target.inputs.update(desc.get('inputs', []))
-      target.sources.update(desc.get('sources', []))
+      target.inputs.update(desc['inputs'])
       outs = [re.sub('^//out/.+?/gen/', '', x) for x in desc['outputs']]
       target.outputs.update(outs)
       target.script = desc['script']
@@ -419,14 +332,6 @@
       # because root build dir is typically out/xxx/).
       target.args = [re.sub('^../../', '//', x) for x in desc['args']]
 
-    # Default for 'public' is //* - all headers in 'sources' are public.
-    # TODO(primiano): if a 'public' section is specified (even if empty), then
-    # the rest of 'sources' is considered inaccessible by gn. Consider
-    # emulating that, so that generated build files don't end up with overly
-    # accessible headers.
-    public_headers = [x for x in desc.get('public', []) if x != '*']
-    target.public_headers.update(public_headers)
-
     target.cflags.update(desc.get('cflags', []) + desc.get('cflags_cc', []))
     target.libs.update(desc.get('libs', []))
     target.ldflags.update(desc.get('ldflags', []))
@@ -440,11 +345,7 @@
         target.deps.add(dep_name)
       elif dep.type == 'proto_library':
         target.proto_deps.add(dep_name)
-        target.proto_paths.update(dep.proto_paths)
-
-        # Don't bubble deps for action targets
-        if target.type != 'action':
-          target.proto_deps.update(dep.proto_deps)  # Bubble up deps.
+        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.
@@ -458,51 +359,18 @@
 
     return target
 
-  def get_proto_paths(self, proto_desc):
-    # import_dirs in metadata will be available for source_set targets.
-    metadata = proto_desc.get('metadata', {})
-    import_dirs = metadata.get('import_dirs', [])
-    if import_dirs:
-      return import_dirs
-
-    # For all non-source-set targets, we need to parse the command line
-    # of the protoc invocation.
-    proto_paths = []
-    args = proto_desc.get('args', [])
-    for i, arg in enumerate(args):
-      if arg != '--proto_path':
-        continue
-      proto_paths.append(re.sub('^../../', '//', args[i + 1]))
-    return proto_paths
-
   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, proto_desc) where |plugin| is 'proto' in the default (lite)
-            case or 'protozero' or 'ipc' or 'descriptor'; |proto_desc| is the GN
-            json desc of the target with the .proto sources (_gen target for
-            non-descriptor types or the target itself for descriptor type).
+            (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 ''
-
-    # Descriptor targets don't have a _gen target; instead we look for the
-    # characteristic flag in the args of the target itself.
-    desc = self.gn_desc_.get(target.name)
-    if '--descriptor_set_out' in desc.get('args', []):
-      return 'descriptor', desc
-
-    # Source set proto targets have a non-empty proto_library_sources in the
-    # metadata of the descirption.
-    metadata = desc.get('metadata', {})
-    if 'proto_library_sources' in metadata:
-      return 'source_set', desc
-
-    # In all other cases, we want to look at the _gen target as that has the
-    # important information.
     gen_desc = self.gn_desc_.get('%s_gen%s' % (name, toolchain))
     if gen_desc is None or gen_desc['type'] != 'action':
       return None, None
diff --git a/tools/heap_profile b/tools/heap_profile
index b635a12..3c5890c 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 
 # Copyright (C) 2017 The Android Open Source Project
 #
@@ -29,12 +29,11 @@
 import tempfile
 import time
 import uuid
-import platform
 
 
 TRACE_TO_TEXT_SHAS = {
-    'linux': '7e3e10dfb324e31723efd63ac25037856e06eba0',
-    'mac': '21f0f42dd019b4f09addd404a114fbf2322ca8a4',
+    'linux': 'aba0e660818bfc249992ebbceb13a2e4c9a62c3a',
+    'mac': 'c7d1b9d904f008bfb95125b204837eff946c3ed7',
 }
 TRACE_TO_TEXT_PATH = tempfile.gettempdir()
 TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
@@ -45,22 +44,18 @@
     'stderr': NULL,
 }
 
-UUID = str(uuid.uuid4())[-6:]
+UUID = str(uuid.uuid4())
 
 def check_hash(file_name, sha_value):
-  file_hash = hashlib.sha1()
   with open(file_name, 'rb') as fd:
-    while True:
-      chunk = fd.read(4096)
-      if not chunk:
-        break
-      file_hash.update(chunk)
-    return file_hash.hexdigest() == sha_value
+    # TODO(fmayer): Chunking.
+    file_hash = hashlib.sha1(fd.read()).hexdigest()
+    return file_hash == sha_value
 
 
-def load_trace_to_text(os_name):
-  sha_value = TRACE_TO_TEXT_SHAS[os_name]
-  file_name = 'trace_to_text-' + os_name + '-' + sha_value
+def load_trace_to_text(platform):
+  sha_value = TRACE_TO_TEXT_SHAS[platform]
+  file_name = 'trace_to_text-' + platform + '-' + sha_value
   local_file = os.path.join(TRACE_TO_TEXT_PATH, file_name)
 
   if os.path.exists(local_file):
@@ -87,16 +82,18 @@
 
 CFG_INDENT = '      '
 CFG = '''buffers {{
-  size_kb: 63488
+  size_kb: 32768
 }}
 
 data_sources {{
   config {{
     name: "android.heapprofd"
     heapprofd_config {{
+
       shmem_size_bytes: {shmem_size}
       sampling_interval_bytes: {interval}
 {target_cfg}
+{continuous_dump_cfg}
     }}
   }}
 }}
@@ -116,7 +113,7 @@
       }}
 """
 
-PROFILE_LOCAL_PATH = os.path.join(tempfile.gettempdir(), UUID)
+PROFILE_LOCAL_PATH = '/tmp/profile-' + UUID
 
 IS_INTERRUPTED = False
 
@@ -129,26 +126,9 @@
   print("No profiles generated", file=sys.stderr)
   print(
     "If this is unexpected, check "
-    "https://perfetto.dev/docs/data-sources/native-heap-profiler#troubleshooting.",
+    "https://docs.perfetto.dev/#/heapprofd?id=troubleshooting.",
     file=sys.stderr)
 
-def known_issues_url(number):
-  return ('https://perfetto.dev/docs/data-sources/native-heap-profiler'
-          '#known-issues-android{}'.format(number))
-
-KNOWN_ISSUES = {
-  '10': known_issues_url(10),
-  'Q': known_issues_url(10),
-  '11': known_issues_url(11),
-  'R': known_issues_url(11),
-}
-
-def maybe_known_issues():
-  release_or_codename = subprocess.check_output(
-    ['adb', 'shell', 'getprop', 'ro.build.version.release_or_codename']
-  ).decode('utf-8').strip()
-  return KNOWN_ISSUES.get(release_or_codename, None)
-
 SDK = {
     'R': 30,
 }
@@ -176,12 +156,10 @@
   parser.add_argument(
       "-d",
       "--duration",
-      help="Duration of profile (ms). 0 to run until interrupted. "
-      "Default: until interrupted by user.",
+      help="Duration of profile (ms). "
+      "Default 7 days.",
       type=int,
-      default=0)
-  # This flag is a no-op now. We never start heapprofd explicitly using system
-  # properties.
+      default=604800000)
   parser.add_argument(
       "--no-start", help="Do not start heapprofd.", action='store_true')
   parser.add_argument(
@@ -203,22 +181,6 @@
       type=int,
       default=0)
   parser.add_argument(
-      "--heaps",
-      help="Comma-separated list of heaps to collect, e.g: malloc,art. "
-      "Requires Android 12.",
-      metavar="HEAPS")
-  parser.add_argument(
-      "--all-heaps",
-      action="store_true",
-      help="Collect allocations from all heaps registered by target."
-  )
-  parser.add_argument(
-      "--no-android-tree-symbolization",
-      action="store_true",
-      help="Do not symbolize using currently lunched target in the "
-      "Android tree."
-  )
-  parser.add_argument(
       "--disable-selinux",
       action="store_true",
       help="Disable SELinux enforcement for duration of "
@@ -296,6 +258,19 @@
       default=None)
 
   args = parser.parse_args()
+
+  # TODO(fmayer): Maybe feature detect whether we can remove traces instead of
+  # this.
+  uuid_trace = release_or_newer('R')
+  if uuid_trace:
+    profile_device_path = '/data/misc/perfetto-traces/profile-' + UUID
+  else:
+    user = subprocess.check_output(
+      ['adb', 'shell', 'whoami']).decode('utf-8').strip()
+    profile_device_path = '/data/misc/perfetto-traces/profile-' + user
+  perfetto_cmd = ('CFG=\'{cfg}\'; echo ${{CFG}} | '
+                  'perfetto --txt -c - -o ' + profile_device_path + ' -d')
+
   fail = False
   if args.block_client and args.no_block_client:
     print(
@@ -322,21 +297,19 @@
 
   target_cfg = ""
   if not args.no_block_client:
-    target_cfg += CFG_INDENT + "block_client: true\n"
+    target_cfg += "block_client: true\n"
   if args.block_client_timeout:
-    target_cfg += (
-      CFG_INDENT + "block_client_timeout_us: %s\n" % args.block_client_timeout
-    )
+    target_cfg += "block_client_timeout_us: %s\n" % args.block_client_timeout
+  if args.idle_allocations:
+    target_cfg += "idle_allocations: true\n"
   if args.no_startup:
-    target_cfg += CFG_INDENT + "no_startup: true\n"
+    target_cfg += "no_startup: true\n"
   if args.no_running:
-    target_cfg += CFG_INDENT + "no_running: true\n"
+    target_cfg += "no_running: true\n"
   if args.dump_at_max:
-    target_cfg += CFG_INDENT + "dump_at_max: true\n"
+    target_cfg += "dump_at_max: true\n"
   if args.disable_fork_teardown:
-    target_cfg += CFG_INDENT + "disable_fork_teardown: true\n"
-  if args.all_heaps:
-    target_cfg += CFG_INDENT + "all_heaps: true\n"
+    target_cfg += "disable_fork_teardown: true\n"
   if args.pid:
     for pid in args.pid.split(','):
       try:
@@ -344,26 +317,37 @@
       except ValueError:
         print("FATAL: invalid PID %s" % pid, file=sys.stderr)
         fail = True
-      target_cfg += CFG_INDENT + 'pid: {}\n'.format(pid)
+      target_cfg += '{}pid: {}\n'.format(CFG_INDENT, pid)
   if args.name:
     for name in args.name.split(','):
-      target_cfg += CFG_INDENT + 'process_cmdline: "{}"\n'.format(name)
-  if args.heaps:
-    for heap in args.heaps.split(','):
-      target_cfg += CFG_INDENT + 'heaps: "{}"\n'.format(heap)
+      target_cfg += '{}process_cmdline: "{}"\n'.format(CFG_INDENT, name)
 
   if fail:
     parser.print_help()
     return 1
 
   trace_to_text_binary = args.trace_to_text_binary
+  if trace_to_text_binary is None:
+    platform = None
+    if sys.platform.startswith('linux'):
+      platform = 'linux'
+    elif sys.platform.startswith('darwin'):
+      platform = 'mac'
+    else:
+      print("Invalid platform: {}".format(sys.platform), file=sys.stderr)
+      return 1
 
+    trace_to_text_binary = load_trace_to_text(platform)
+
+  continuous_dump_cfg = ""
   if args.continuous_dump:
-    target_cfg += CONTINUOUS_DUMP.format(dump_interval=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
@@ -372,46 +356,6 @@
     print(cfg)
     return 0
 
-  # Do this AFTER print_config so we do not download trace_to_text only to
-  # print out the config.
-  has_trace_to_text = True
-  if trace_to_text_binary is None:
-    os_name = None
-    if sys.platform.startswith('linux'):
-      os_name = 'linux'
-    elif sys.platform.startswith('darwin'):
-      os_name = 'mac'
-    elif sys.platform.startswith('win32'):
-      has_trace_to_text = False
-    else:
-      print("Invalid platform: {}".format(sys.platform), file=sys.stderr)
-      return 1
-
-    arch = platform.machine()
-    if arch not in ['x86_64', 'amd64']:
-      has_trace_to_text = False
-
-    if has_trace_to_text:
-      trace_to_text_binary = load_trace_to_text(os_name)
-
-  known_issues = maybe_known_issues()
-  if known_issues:
-    print('If you are experiencing problems, please see the known issues for '
-          'your release: {}.'.format(known_issues))
-
-  # TODO(fmayer): Maybe feature detect whether we can remove traces instead of
-  # this.
-  uuid_trace = release_or_newer('R')
-  if uuid_trace:
-    profile_device_path = '/data/misc/perfetto-traces/profile-' + UUID
-  else:
-    user = subprocess.check_output(
-      ['adb', 'shell', 'whoami']).decode('utf-8').strip()
-    profile_device_path = '/data/misc/perfetto-traces/profile-' + user
-
-  perfetto_cmd = ('CFG=\'{cfg}\'; echo ${{CFG}} | '
-                  'perfetto --txt -c - -o ' + profile_device_path + ' -d')
-
   if args.disable_selinux:
     enforcing = subprocess.check_output(['adb', 'shell', 'getenforce'])
     atexit.register(
@@ -419,6 +363,16 @@
         ['adb', 'shell', 'su root setenforce %s' % enforcing])
     subprocess.check_call(['adb', 'shell', 'su root setenforce 0'])
 
+  if not args.no_start:
+    heapprofd_prop = subprocess.check_output(
+        ['adb', 'shell', 'getprop persist.heapprofd.enable'])
+    if heapprofd_prop.strip() != '1':
+      subprocess.check_call(
+          ['adb', 'shell', 'setprop persist.heapprofd.enable 1'])
+      atexit.register(subprocess.check_call,
+                      ['adb', 'shell', 'setprop persist.heapprofd.enable 0'])
+
+
   if args.simpleperf:
     subprocess.check_call([
         'adb', 'shell', 'mkdir -p /data/local/tmp/heapprofd_profile && '
@@ -463,7 +417,6 @@
         ['adb', 'shell', '[ -d /proc/{} ]'.format(perfetto_pid)], **NOOUT) == 0
     device_connected = subprocess.call(['adb', 'shell', 'true'], **NOOUT) == 0
     time.sleep(1)
-  print("Waiting for profiler shutdown...")
   signal.signal(signal.SIGINT, old_handler)
   if IS_INTERRUPTED:
     # Not check_call because it could have existed in the meantime.
@@ -475,9 +428,8 @@
         ['adb', 'shell', '[ -f /proc/$(pidof simpleperf)/exe ]'], **NOOUT) == 0:
       time.sleep(1)
     subprocess.check_call(
-        ['adb', 'pull', '/data/local/tmp/heapprofd_profile', profile_target])
-    print(
-      "Pulled simpleperf profile to " + profile_target + "/heapprofd_profile")
+        ['adb', 'pull', '/data/local/tmp/heapprofd_profile', '/tmp'])
+    print("Pulled simpleperf profile to /tmp/heapprofd_profile")
 
   # Wait for perfetto cmd to return.
   while exists:
@@ -485,86 +437,29 @@
         ['adb', 'shell', '[ -d /proc/{} ]'.format(perfetto_pid)]) == 0
     time.sleep(1)
 
-  profile_host_path = os.path.join(profile_target, 'raw-trace')
-  subprocess.check_call(
-    ['adb', 'pull', profile_device_path, profile_host_path], stdout=NULL)
+  subprocess.check_call([
+      'adb', 'pull', profile_device_path,
+      os.path.join(profile_target, 'raw-trace')
+  ], stdout=NULL)
   if uuid_trace:
     subprocess.check_call(
           ['adb', 'shell', 'rm', profile_device_path], stdout=NULL)
 
-  if not has_trace_to_text:
-    print('Wrote profile to {}'.format(profile_host_path))
-    print('This file can be opened using the Perfetto UI, https://ui.perfetto.dev')
-    return 0
-
-  binary_path = os.getenv('PERFETTO_BINARY_PATH')
-  if not args.no_android_tree_symbolization:
-    product_out = os.getenv('ANDROID_PRODUCT_OUT')
-    if product_out:
-      product_out_symbols = product_out + '/symbols'
-    else:
-      product_out_symbols = None
-
-    if binary_path is None:
-      binary_path = product_out_symbols
-    elif product_out_symbols is not None:
-      binary_path += ":" + product_out_symbols
-
-  trace_file = os.path.join(profile_target, 'raw-trace')
-  concat_files = [trace_file]
-
-  if binary_path is not None:
-    with open(os.path.join(profile_target, 'symbols'), 'w') as fd:
-      ret = subprocess.call([
-          trace_to_text_binary, 'symbolize',
-          os.path.join(profile_target, 'raw-trace')],
-          env=dict(os.environ, PERFETTO_BINARY_PATH=binary_path),
-          stdout=fd)
-    if ret == 0:
-      concat_files.append(os.path.join(profile_target, 'symbols'))
-    else:
-      print("Failed to symbolize. Continuing without symbols.",
-      file=sys.stderr)
-
-  proguard_map = os.getenv('PERFETTO_PROGUARD_MAP')
-  if proguard_map is not None:
-    with open(os.path.join(profile_target, 'deobfuscation-packets'), 'w') as fd:
-      ret = subprocess.call([
-          trace_to_text_binary, 'deobfuscate',
-          os.path.join(profile_target, 'raw-trace')],
-          env=dict(os.environ, PERFETTO_PROGUARD_MAP=proguard_map),
-          stdout=fd)
-    if ret == 0:
-      concat_files.append(
-        os.path.join(profile_target, 'deobfuscation-packets'))
-    else:
-      print("Failed to deobfuscate. Continuing without deobfuscated.",
-      file=sys.stderr)
-
-  if len(concat_files) > 1:
-    with open(os.path.join(profile_target, 'symbolized-trace'), 'wb') as out:
-      for fn in concat_files:
-        with open(fn, 'rb') as inp:
-          while True:
-            buf = inp.read(4096)
-            if not buf:
-              break
-            out.write(buf)
-    trace_file = os.path.join(profile_target, 'symbolized-trace')
-
   trace_to_text_output = subprocess.check_output(
-      [trace_to_text_binary, 'profile', trace_file])
+      [trace_to_text_binary, 'profile',
+          os.path.join(profile_target, 'raw-trace')],
+      env=os.environ)
   profile_path = None
   for word in trace_to_text_output.decode('utf-8').split():
     if 'heap_profile-' in word:
       profile_path = word
   if profile_path is None:
-    print_no_profile_error()
+    print_no_profile_error();
     return 1
 
   profile_files = os.listdir(profile_path)
   if not profile_files:
-    print_no_profile_error()
+    print_no_profile_error();
     return 1
 
   for profile_file in profile_files:
@@ -576,11 +471,23 @@
 
   symlink_path = None
   if args.output is None:
-    symlink_path = os.path.join(
-      os.path.dirname(profile_target), "heap_profile-latest")
-    if os.path.lexists(symlink_path):
-      os.unlink(symlink_path)
-    os.symlink(profile_target, symlink_path)
+      symlink_path = os.path.join(
+          os.path.dirname(profile_target), "heap_profile-latest")
+      if os.path.lexists(symlink_path):
+        os.unlink(symlink_path)
+      os.symlink(profile_target, symlink_path)
+
+  binary_path = os.getenv('PERFETTO_BINARY_PATH')
+  if binary_path is not None:
+      with open(os.path.join(profile_path, 'symbols'), 'w') as fd:
+          ret = subprocess.call([
+              trace_to_text_binary, 'symbolize',
+              os.path.join(profile_target, 'raw-trace')],
+              env=os.environ,
+              stdout=fd)
+          if ret != 0:
+              print("Failed to symbolize. Continuing without symbols.",
+                    file=sys.stderr)
 
   if symlink_path is not None:
     print("Wrote profiles to {} (symlink {})".format(
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 878f1f6..8707af9 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,230 +19,141 @@
 import os
 import shutil
 import subprocess
-import stat
 import sys
 import tempfile
 import zipfile
 
 from collections import namedtuple
-from platform import system, machine
+from platform import system
+
 
 # The format for the deps below is the following:
 # (target_folder, source_url, sha1, target_platform)
 # |source_url| can be either a git repo or a http url.
-# If a git repo, |checksum| is the SHA1 committish that will be checked out.
-# If a http url, |checksum| is the SHA256 of the downloaded file.
+# If a git repo, |sha1| is the committish that will be checked out.
+# If a http url, |sha1| is the shasum of the original file.
 # If the url is a .zip or .tgz file it will be automatically deflated under
 # |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_os| is either 'darwin', 'linux', 'windows' or 'all'
-# |target_arch| is either 'x64', 'aarch64' or 'all'
-# in both cases the dep only applies on matching platforms
-# |target_arch| can be 'all' when 'target_os' is not 'all' for example in the
-# case of MacOS universal binaries.
-Dependency = namedtuple(
-    'Dependency',
-    ['target_folder', 'source_url', 'checksum', 'target_os', 'target_arch'])
-
-# This is to remove old directories when build tools get {re,}moved. This is to
-# avoid accidentally referring to stale dir in custom user scripts.
-CLEANUP_OLD_DIRS = [
-    'buildtools/nodejs',  # Moved to buildtools/{mac,linux64}/nodejs
-    'buildtools/emsdk',  # Moved to buildtools/{mac,linux64}/emsdk
-    'buildtools/test_data',  # Moved to test/data by r.android.com/1539381 .
-    'buildtools/d8',  # Removed by r.android.com/1424334 .
-]
+# |target_platform| is either 'darwin', 'linux' or 'all' and applies the dep
+# only on the given platform
 
 # Dependencies required to build code on the host or when targeting desktop OS.
-BUILD_DEPS_TOOLCHAIN_HOST = [
-    # GN. From https://chrome-infra-packages.appspot.com/dl/gn/gn/.
-    # git_revision:83dad00afb232d7235dd70dff1ee90292d72a01e .
-    Dependency(
-        'buildtools/mac/gn',
-        'https://storage.googleapis.com/perfetto/gn-mac-1695-83dad00a',
-        '513d3adeb56b745e62af4e3ccb76b76f023c6aaa25d6a2be9a89e44cd10a4c1a',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/linux64/gn',
-        'https://storage.googleapis.com/perfetto/gn-linux64-1695-83dad00a',
-        '4f589364153f182b05cd845e93407489d6ce8acc03290c897928a7bd22b20cce',
-        'linux', 'x64'),
-    Dependency(
-        'buildtools/win/gn.exe',
-        'https://storage.googleapis.com/perfetto/gn-win-1695-83dad00a',
-        '908c29556539292203d2952ebf55df03697cbc7cf526a3e295f31ba2576e4cac',
-        'windows', 'x64'),
+BUILD_DEPS_HOST = [
+    # GN
+    ('buildtools/mac/gn',
+     'https://storage.googleapis.com/perfetto/gn-mac-1695-83dad00a',
+     '4c0d45772aea4146699772165e8112fa76ceb295', 'darwin'),
+    ('buildtools/linux64/gn',
+     'https://storage.googleapis.com/perfetto/gn-linux64-1695-83dad00a',
+     'fcabfc379bccaa65b4e2fc791594ba124dafc7d0', 'linux'),
 
     # clang-format
-    # From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/mac/clang-format.sha1
-    Dependency(
-        'buildtools/mac/clang-format',
-        'https://storage.googleapis.com/chromium-clang-format/62bde1baa7196ad9df969fc1f06b66360b1a927b',
-        '6df686a937443cbe6efc013467a7ba5f98d3f187eb7765bb7abc6ce47626cf66',
-        'darwin', 'x64'),
-    # From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/linux64/clang-format.sha1
-    Dependency(
-        'buildtools/linux64/clang-format',
-        'https://storage.googleapis.com/chromium-clang-format/1baf0089e895c989a311b6a38ed94d0e8be4c0a7',
-        'd02a97a87e8c28898033aaf5986967b24dc47ebd5b376e1cd93e5009f22cd75e',
-        'linux', 'x64'),
-    # From https://chromium.googlesource.com/chromium/src/buildtools/+/refs/heads/master/win/clang-format.exe.sha1
-    Dependency(
-        'buildtools/win/clang-format.exe',
-        'https://storage.googleapis.com/chromium-clang-format/d4afd4eba27022f5f6d518133aebde57281677c9',
-        '2ba1b4d3ade90ea80316890b598ab5fc16777572be26afec6ce23117da121b80',
-        'windows', 'x64'),
-
+    ('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.
-    Dependency(
-        'buildtools/clang_format/script',
-        'https://chromium.googlesource.com/chromium/llvm-project/cfe/tools/clang-format.git',
-        '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'all', 'all'),
+    ('buildtools/clang_format/script',
+     'https://chromium.googlesource.com/chromium/llvm-project/cfe/tools/clang-format.git',
+     '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'all'),
 
     # Ninja
-    Dependency(
-        'buildtools/mac/ninja',
-        'https://storage.googleapis.com/perfetto/ninja-mac-c15b0698da038b2bd2e8970c14c75fadc06b1add',
-        '4224b90734590b0148ad8ee63ee7b295e88e0652e4d1f4271ef2b91d880b0e19',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/linux64/ninja',
-        'https://storage.googleapis.com/perfetto/ninja-linux64-c866952bda50c29a669222477309287119bbb7e8',
-        '54ac6a01362190aaabf4cf276f9c8982cdf11b225438940fdde3339be0f2ecdc',
-        'linux', 'x64'),
-    Dependency(
-        'buildtools/win/ninja.exe',
-        'https://storage.googleapis.com/perfetto/ninja-win-4a5f05c24afef05ef03329a1bbfedee0678b524a',
-        '6f8af488be74ed8787d04e107080d05330587a4198ba047bd5b7f5b0c3150d61',
-        'windows', 'x64'),
+    ('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'),
 
-    # Keep the revision in sync with Chrome's PACKAGE_VERSION in
-    # tools/clang/scripts/update.py.
-    Dependency(
-        'buildtools/linux64/clang.tgz',
-        'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-12-init-5035-gd0abc757-3.tgz',
-        'b0c3015209b6d624844ad230064eb5c9b4429a2eafd4854981e73217c563d93d',
-        'linux', 'x64'),
-    Dependency(
-        'buildtools/win/clang.tgz',
-        'https://commondatastorage.googleapis.com/chromium-browser-clang/Win/clang-llvmorg-12-init-5035-gd0abc757-3.tgz',
-        'b2854d871a466e3a060469b5edb24ca355ef64576d38778f64acbd3c6d7cf530',
-        'windows', 'x64'),
-]
-
-BUILD_DEPS_HOST = [
     # Keep in sync with Android's //external/googletest/README.version.
-    Dependency(
-        'buildtools/googletest',
-        'https://android.googlesource.com/platform/external/googletest.git',
-        '3f05f651ae3621db58468153e32016bc1397800b', 'all', 'all'),
+    ('buildtools/googletest.zip',
+     'https://github.com/google/googletest/archive/3f05f651ae3621db58468153e32016bc1397800b.zip',
+     '86384688f7c533ad325a505efc917e0cdf39a0ce', 'all'),
 
     # Keep in sync with Chromium's //third_party/protobuf.
-    Dependency(
-        'buildtools/protobuf',
-        'https://chromium.googlesource.com/external/github.com/google/protobuf.git',
-        '6a59a2ad1f61d9696092f79b6d74368b4d7970a3',  # refs/tags/v3.9.0
-        'all', 'all'),
+    ('buildtools/protobuf.zip',
+     'https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protobuf-cpp-3.9.0.zip',
+     'c975536dffe9d9a3d362928aef4fb9f199012b98', '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.
-    Dependency(
-        'buildtools/libcxx',
-        'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git',
-        'd9040c75cfea5928c804ab7c235fed06a63f743a', 'all', 'all'),
-    Dependency(
-        'buildtools/libcxxabi',
-        'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git',
-        '196ba1aaa8ac285d94f4ea8d9836390a45360533', 'all', 'all'),
-    Dependency(
-        'buildtools/libunwind',
-        'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libunwind.git',
-        'd999d54f4bca789543a2eb6c995af2d9b5a1f3ed', 'all', 'all'),
+    ('buildtools/libcxx',
+     'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git',
+     '78d6a7767ed57b50122a161b91f59f19c9bd0d19', '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'),
+
+    # 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-n332890-c2443155-2.tgz',
+     'd6501ffdb5dbb0ffe8a4b873cc092a9929e661ec', 'linux'),
 
     # Keep in sync with chromium DEPS.
-    Dependency(
-        'buildtools/libfuzzer',
-        'https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer.git',
-        'debe7d2d1982e540fbd6bd78604bf001753f9e74', 'linux', 'all'),
+    ('buildtools/libfuzzer',
+     'https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer.git',
+     'debe7d2d1982e540fbd6bd78604bf001753f9e74', 'linux'),
 
     # Benchmarking tool.
-    Dependency(
-        'buildtools/benchmark',
-        'https://chromium.googlesource.com/external/github.com/google/benchmark.git',
-        '090faecb454fbd6e6e17a75ef8146acb037118d4', 'all', 'all'),
+    ('buildtools/benchmark.zip',
+     'https://github.com/google/benchmark/archive/v1.5.0.zip',
+     'a9c9bd8a28db82f5ba02998197cfcc4db5a67507', 'all'),
 
     # Libbacktrace, for stacktraces in Linux/Android debug builds.
-    # From https://github.com/ianlancetaylor/libbacktrace/archive/177940370e4a6b2509e92a0aaa9749184e64af43.zip
-    Dependency(
-        'buildtools/libbacktrace.zip',
-        'https://storage.googleapis.com/perfetto/libbacktrace-177940370e4a6b2509e92a0aaa9749184e64af43.zip',
-        '21ac9a4209f7aeef766c482be53a7fa365063c031c7077e2070b491202983b31',
-        'all', 'all'),
+    ('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 (which are not available
-    # in the amalgamation).
-    Dependency(
-        'buildtools/sqlite.zip',
-        'https://storage.googleapis.com/perfetto/sqlite-amalgamation-3350400.zip',
-        'f3bf0df69f5de0675196f4644e05d07dbc698d674dc563a12eff17d5b215cdf5',
-        'all', 'all'),
-    Dependency(
-        'buildtools/sqlite_src',
-        'https://chromium.googlesource.com/external/github.com/sqlite/sqlite.git',
-        'ee3686eb50c0e3dbb087c9a0976f7e37e1b014ae',  # refs/tags/version-3.32.3.
-        'all', 'all'),
+    # 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.
-    Dependency(
-        'buildtools/jsoncpp',
-        'https://chromium.googlesource.com/external/github.com/open-source-parsers/jsoncpp.git',
-        '6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2',  # refs/tags/1.9.3.
-        'all', 'all'),
+    ('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.
-    Dependency('buildtools/android-core',
-               'https://android.googlesource.com/platform/system/core.git',
-               '9e6cef7f07d8c11b3ea820938aeb7ff2e9dbaa52', 'all', 'all'),
-    Dependency(
-        'buildtools/android-unwinding',
-        'https://android.googlesource.com/platform/system/unwinding.git',
-        '5150e1292ec6b16e4717e86b9e3cfb855eec18a3', 'all', 'all'),
-    Dependency('buildtools/android-logging',
-               'https://android.googlesource.com/platform/system/logging.git',
-               '7b36b566c9113fc703d68f76e8f40c0c2432481c', 'all', 'all'),
-    Dependency('buildtools/android-libbase',
-               'https://android.googlesource.com/platform/system/libbase.git',
-               '78f1c2f83e625bdf66d55b48bdb3a301c20d2fb3', 'all', 'all'),
-    Dependency(
-        'buildtools/android-libprocinfo',
-        'https://android.googlesource.com/platform/system/libprocinfo.git',
-        'fd214c13ededecae97a3b15b5fccc8925a749a84', 'all', 'all'),
-    Dependency('buildtools/lzma',
-               'https://android.googlesource.com/platform/external/lzma.git',
-               '7851dce6f4ca17f5caa1c93a4e0a45686b1d56c3', 'all', 'all'),
-    Dependency('buildtools/zlib',
-               'https://android.googlesource.com/platform/external/zlib.git',
-               '5c85a2da4c13eda07f69d81a1579a5afddd35f59', 'all', 'all'),
-    Dependency('buildtools/bionic',
-               'https://android.googlesource.com/platform/bionic.git',
-               '332065d57e734b65f56474d136d22d767e36cbcd', 'all', 'all'),
+    ('buildtools/android-core',
+     'https://android.googlesource.com/platform/system/core.git',
+     '8bf4e29e44098e3232ff646331675fb113064162', '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'),
 
     # Example traces for regression tests.
-    Dependency(
-        'test/data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20210513-224349.zip',
-        '3dcc146f4ce38d17fd1f8c4c65af07e7cf7c5c4cb8aa4c7bf73ec3a095d997d1',
-        'all', 'all',
+    (
+        'buildtools/test_data.zip',
+        'https://storage.googleapis.com/perfetto/test-data-20200604-140632.zip',
+        '2c0a3307f25730d0060d7554d0e59c078c80a366',
+        'all',
     ),
 
     # Linenoise, used only by trace_processor in standalone builds.
-    Dependency('buildtools/linenoise',
-               'https://fuchsia.googlesource.com/third_party/linenoise.git',
-               'c894b9e59f02203dbe4e2be657572cf88c4230c3', 'all', 'all'),
+    ('buildtools/linenoise',
+     'https://fuchsia.googlesource.com/third_party/linenoise.git',
+     'c894b9e59f02203dbe4e2be657572cf88c4230c3', 'all'),
 ]
 
 # Dependencies required to build Android code.
@@ -251,85 +162,72 @@
 # - https://dl.google.com/android/repository/sys-img/android/sys-img.xml
 BUILD_DEPS_ANDROID = [
     # Android NDK
-    Dependency(
-        'buildtools/ndk.zip',
-        'https://dl.google.com/android/repository/android-ndk-r21e-darwin-x86_64.zip',
-        '437278103a3db12632c05b1be5c41bbb8522791a67e415cc54411a65366f499d',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/ndk.zip',
-        'https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip',
-        'ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
-        'linux', 'x64'),
+    ('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'),
 ]
 
 # Dependencies required to run Android tests.
 TEST_DEPS_ANDROID = [
     # Android emulator images.
-    Dependency(
-        'buildtools/aosp-arm.zip',
-        'https://storage.googleapis.com/perfetto/aosp-02022018-arm.zip',
-        'f5c7a3a22ad7aa0bd14ba467e8697e1e917d306699bd25622aa4419a413b9b67',
-        'all', 'all'),
+    ('buildtools/aosp-arm.zip',
+     'https://storage.googleapis.com/perfetto/aosp-02022018-arm.zip',
+     'a480d5e7d3ca888b0a58fe15ce76b1791537429a', 'all'),
 
     # platform-tools.zip contains adb binaries.
-    Dependency(
-        'buildtools/android_sdk/platform-tools.zip',
-        'https://dl.google.com/android/repository/platform-tools_r26.0.0-darwin.zip',
-        '98d392cbd21ca20d643c7e1605760cc49075611e317c534096b5564053f4ac8e',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/android_sdk/platform-tools.zip',
-        'https://dl.google.com/android/repository/platform-tools_r26.0.0-linux.zip',
-        '90208207521d85abf0d46e3374aa4e04b7aff74e4f355c792ac334de7a77e50b',
-        'linux', 'x64'),
+    ('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'),
 
     # Android emulator binaries.
-    Dependency(
-        'buildtools/emulator',
-        'https://android.googlesource.com/platform/prebuilts/android-emulator.git',
-        '4b260028dc27bc92c39bee9129cb2ba839970956', 'all', 'x64'),
+    ('buildtools/emulator',
+     'https://android.googlesource.com/platform/prebuilts/android-emulator.git',
+     '4b260028dc27bc92c39bee9129cb2ba839970956', 'all'),
 ]
 
 # This variable is updated by tools/roll-catapult-trace-viewer.
-CATAPULT_SHA256 = 'b30108e05268ce6c65bb4126b65f6bfac165d17f5c1fd285046e7e6fd76c209f'
+CATAPULT_SHA1 = '5f77256e1b24851a05e8580438b532e2480dd7fd'
 
-TYPEFACES_SHA256 = 'b3f0f14eeecd4555ae94f897ec246b2c6e046ce0ea417407553f5767e7812575'
+TYPEFACES_SHA1 = '4fb455de506f8a2859dc5264b8448c2559b08ab8'
 
 UI_DEPS = [
-    Dependency(
-        'buildtools/mac/nodejs.tgz',
-        'https://storage.googleapis.com/chromium-nodejs/14.15.4/17ba7216e09de1bffb9dc80b7ec617a1cee40330',
-        'b81a466347d2ae34b1370b6681ba173e9fb082338170a41624b37be7a2052b7e',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/linux64/nodejs.tgz',
-        'https://storage.googleapis.com/chromium-nodejs/14.15.4/b2e40ddbac04d05baafbb007f203c6663c9d4ca9',
-        '5aa88f1e2bf036950790277f3431634f64044ec78362f3e4f0dc8da28d61e9a4',
-        'linux', 'x64'),
-    Dependency(
-        'buildtools/mac/emsdk.tgz',
-        'https://storage.googleapis.com/perfetto/emscripten-2.0.12-mac.tgz',
-        'aa125f8c8ff8a386d43e18c8ea0c98c875cc19160a899403e8967a5478f96f31',
-        'darwin', 'x64'),
-    Dependency(
-        'buildtools/linux64/emsdk.tgz',
-        'https://storage.googleapis.com/perfetto/emscripten-2.0.12-linux.tgz',
-        'bfff9fb0326363c12e19b542f27a5f12cedbfc310f30621dc497c9af51d2d2e3',
-        'linux', 'x64'),
-    Dependency(
-        'buildtools/catapult_trace_viewer.tgz',
-        'https://storage.googleapis.com/perfetto/catapult_trace_viewer-%s.tar.gz'
-        % CATAPULT_SHA256, CATAPULT_SHA256, 'all', 'all'),
-    Dependency(
-        'buildtools/typefaces.tgz',
-        'https://storage.googleapis.com/perfetto/typefaces-%s.tar.gz' %
-        TYPEFACES_SHA256, TYPEFACES_SHA256, 'all', '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', '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')
 ]
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 UI_DIR = os.path.join(ROOT_DIR, 'ui')
-TOOLS_DIR = os.path.join(ROOT_DIR, 'tools')
 NODE_MODULES_STATUS_FILE = os.path.join(UI_DIR, 'node_modules', '.last_install')
 
 
@@ -337,15 +235,6 @@
   subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
 
 
-def GetArch():
-  arch = machine()
-  if arch == 'aarch64':
-    return 'aarch64'
-  else:
-    # Assume everything else is x64 matching previous behaviour.
-    return 'x64'
-
-
 def ReadFile(path):
   if not os.path.exists(path):
     return None
@@ -368,7 +257,7 @@
   if not os.path.exists(path):
     return None
   with open(path, 'rb') as f:
-    return hashlib.sha256(f.read()).hexdigest()
+    return hashlib.sha1(f.read()).hexdigest()
 
 
 def ExtractZipfilePreservePermissions(zf, info, path):
@@ -382,36 +271,13 @@
   return ReadFile(os.path.join(path, '.git', 'HEAD')) == revision
 
 
-def RmtreeIfExists(path):
-  # Git creates read-only files on windows, which cause failures with rmtree.
-  # This seems the socially accepted way to deal with it.
-  # See https://bugs.python.org/issue19643 .
-  def del_read_only_for_windows(_action, name, _exc):
-    os.chmod(name, stat.S_IWRITE)
-    os.remove(name)
-
-  if not os.path.exists(path):
-    return
-  buildtools_path = os.path.abspath(os.path.join(ROOT_DIR, 'buildtools'))
-  test_path = os.path.abspath(os.path.join(ROOT_DIR, 'test', 'data'))
-  if (not os.path.abspath(path).startswith(buildtools_path) and
-      not os.path.abspath(path).startswith(test_path)):
-    # Safety check to prevent that some merge confilct ends up doing some
-    # rm -rf / or similar.
-    logging.fatal(
-      'Cannot remove %s: outside of buildtools and test/data', path)
-    sys.exit(1)
-  logging.info('Removing %s' % path)
-  shutil.rmtree(path, onerror=del_read_only_for_windows)
-
-
 def CheckoutGitRepo(path, git_url, revision, check_only):
   if IsGitRepoCheckoutOutAtRevision(path, revision):
     return False
   if check_only:
     return True
-  path = path.replace('/', os.sep)
-  RmtreeIfExists(path)
+  if os.path.exists(path):
+    shutil.rmtree(path)
   MkdirRecursive(path)
   logging.info('Fetching %s @ %s into %s', git_url, revision, path)
   subprocess.check_call(['git', 'init', path], cwd=path)
@@ -422,20 +288,10 @@
   return True
 
 
-def InstallNodeModules(force_clean=False):
-  if force_clean:
-    node_modules = os.path.join(UI_DIR, 'node_modules')
-    logging.info('Clearing %s', node_modules)
-    subprocess.check_call(['git', 'clean', '-qxffd', node_modules],
-                          cwd=ROOT_DIR)
+def InstallNodeModules():
   logging.info("Running npm install in {0}".format(UI_DIR))
-  subprocess.check_call(
-      [os.path.join(TOOLS_DIR, 'npm'), 'install', '--no-save'], cwd=UI_DIR)
-  # pbjs has the bad habit of installing extra packages on its first run. Run
-  # it here, so we avoid fetches while building.
-  node_bin = os.path.join(TOOLS_DIR, 'node')
-  pbjs = [node_bin, 'node_modules/.bin/pbjs', '/dev/null', '-o', '/dev/null']
-  subprocess.call(pbjs, cwd=UI_DIR)
+  subprocess.check_call([os.path.join(UI_DIR, 'npm'), 'install', '--no-save'],
+                        cwd=UI_DIR)
   with open(NODE_MODULES_STATUS_FILE, 'w') as f:
     f.write(HashLocalFile(os.path.join(UI_DIR, 'package-lock.json')))
 
@@ -456,19 +312,18 @@
 
 def CheckHashes():
   for deps in [BUILD_DEPS_HOST, BUILD_DEPS_ANDROID, TEST_DEPS_ANDROID, UI_DEPS]:
-    for dep in deps:
-      if dep.source_url.endswith('.git'):
+    for rel_path, url, expected_sha1, platform in deps:
+      if url.endswith('.git'):
         continue
-      logging.info('Downloading %s from %s', dep.target_platform,
-                   dep.source_url)
+      logging.info('Downloading %s from %s', rel_path, url)
       with tempfile.NamedTemporaryFile(delete=False) as f:
         f.close()
-        DownloadURL(dep.source_url, f.name)
-        actual_checksum = HashLocalFile(f.name)
+        DownloadURL(url, f.name)
+        actual_sha1 = HashLocalFile(f.name)
         os.unlink(f.name)
-        if (actual_checksum != dep.checksum):
-          logging.fatal('SHA-256 mismatch for {} expected {} was {}'.format(
-              dep.source_url, dep.checksum, actual_checksum))
+        if (actual_sha1 != expected_sha1):
+          logging.fatal('SHA1 mismatch for {} expected {} was {}'.format(
+              url, expected_sha1, actual_sha1))
 
 
 def Main():
@@ -476,73 +331,56 @@
   parser.add_argument('--android', action='store_true')
   parser.add_argument('--ui', action='store_true')
   parser.add_argument('--check-only')
-  parser.add_argument('--filter', default='')
   parser.add_argument('--verify', help='Check all URLs', action='store_true')
-  parser.add_argument('--no-toolchain', help='Do not download toolchain',
-                      action='store_true')
   args = parser.parse_args()
   if args.verify:
     CheckHashes()
     return 0
   deps = BUILD_DEPS_HOST
-  if not args.no_toolchain:
-    deps += BUILD_DEPS_TOOLCHAIN_HOST
   if args.android:
     deps += BUILD_DEPS_ANDROID + TEST_DEPS_ANDROID
   if args.ui:
     deps += UI_DEPS
   deps_updated = False
-  nodejs_updated = False
-
-  for old_dir in CLEANUP_OLD_DIRS:
-    RmtreeIfExists(os.path.join(ROOT_DIR, old_dir))
-
-  for dep in deps:
-    target_os = system().lower()
-    target_arch = GetArch()
-    matches_os = dep.target_os == 'all' or target_os == dep.target_os
-    matches_arch = dep.target_arch == 'all' or target_arch == dep.target_arch
-    if not matches_os or not matches_arch:
+  for rel_path, url, expected_sha1, platform in deps:
+    if (platform != 'all' and platform != system().lower()):
       continue
-    if args.filter and args.filter not in dep.target_folder:
-      continue
-    local_path = os.path.join(ROOT_DIR, dep.target_folder)
-    if dep.source_url.endswith('.git'):
-      deps_updated |= CheckoutGitRepo(local_path, dep.source_url, dep.checksum,
+    local_path = os.path.join(ROOT_DIR, rel_path)
+    if url.endswith('.git'):
+      deps_updated |= CheckoutGitRepo(local_path, url, expected_sha1,
                                       args.check_only)
       continue
     is_zip = local_path.endswith('.zip') or local_path.endswith('.tgz')
     zip_target_dir = local_path[:-4] if is_zip else None
     zip_dir_stamp = os.path.join(zip_target_dir, '.stamp') if is_zip else None
 
-    if ((not is_zip and HashLocalFile(local_path) == dep.checksum) or
-        (is_zip and ReadFile(zip_dir_stamp) == dep.checksum)):
+    if ((not is_zip and HashLocalFile(local_path) == expected_sha1) or
+        (is_zip and ReadFile(zip_dir_stamp) == expected_sha1)):
       continue
     deps_updated = True
     if args.check_only:
       continue
-    MkdirRecursive(os.path.dirname(dep.target_folder))
-    if HashLocalFile(local_path) != dep.checksum:
+    MkdirRecursive(os.path.dirname(rel_path))
+    if HashLocalFile(local_path) != expected_sha1:
       download_path = local_path + '.tmp'
-      logging.info('Downloading %s from %s', local_path, dep.source_url)
-      DownloadURL(dep.source_url, download_path)
+      logging.info('Downloading %s from %s', local_path, url)
+      DownloadURL(url, download_path)
       os.chmod(download_path, 0o755)
-      actual_checksum = HashLocalFile(download_path)
-      if (actual_checksum != dep.checksum):
+      actual_sha1 = HashLocalFile(download_path)
+      if (actual_sha1 != expected_sha1):
         os.remove(download_path)
-        logging.fatal('SHA-256 mismatch for {} expected {} was {}'.format(
-            download_path, dep.checksum, actual_checksum))
+        logging.fatal('SHA1 mismatch for {} expected {} was {}'.format(
+            download_path, expected_sha1, actual_sha1))
         return 1
-      shutil.move(download_path, local_path)
-      if 'nodejs' in dep.target_folder:
-        nodejs_updated = True
-
-    assert (HashLocalFile(local_path) == dep.checksum)
+      os.rename(download_path, local_path)
+    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)
-      RmtreeIfExists(zip_target_dir)
+      if os.path.exists(zip_target_dir):
+        logging.info('Deleting stale dir %s' % zip_target_dir)
+        shutil.rmtree(zip_target_dir)
 
       # Decompress the archive.
       if local_path.endswith('.tgz'):
@@ -565,24 +403,24 @@
 
       # Create stamp and remove the archive.
       with open(zip_dir_stamp, 'w') as stamp_file:
-        stamp_file.write(dep.checksum)
+        stamp_file.write(expected_sha1)
       os.remove(local_path)
 
   if args.ui:
     # Needs to happen after nodejs is installed above.
     if args.check_only:
-      deps_updated |= not CheckNodeModules()
+      deps_updated = not CheckNodeModules()
     else:
-      InstallNodeModules(force_clean=nodejs_updated)
+      InstallNodeModules()
 
   if args.check_only:
     if not deps_updated:
       with open(args.check_only, 'w') as f:
         f.write('OK')  # The content is irrelevant, just keep GN happy.
       return 0
-    argz = ' '.join([x for x in sys.argv[1:] if not x.startswith('--check-only')])
-    print('\033[91mBuild deps are stale. ' +
-          'Please run tools/install-build-deps %s\033[0m' % argz)
+    argz = ' '.join([x for x in sys.argv[1:] if not '--check-only' in x])
+    sys.stderr.write('\033[91mBuild deps are stale. ' +
+                     'Please run tools/install-build-deps %s\033[0m' % argz)
     return 1
 
   if deps_updated:
diff --git a/tools/java_heap_dump b/tools/java_heap_dump
index 03abb01..f84a594 100755
--- a/tools/java_heap_dump
+++ b/tools/java_heap_dump
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 
 # Copyright (C) 2020 The Android Open Source Project
 #
@@ -50,8 +50,7 @@
   }}
 }}
 
-data_source_stop_timeout_ms: {data_source_stop_timeout_ms}
-duration_ms: {duration_ms}
+duration_ms: 20000
 '''
 
 CONTINUOUS_DUMP = """
@@ -65,7 +64,6 @@
                 'perfetto --txt -c - -o '
                 '/data/misc/perfetto-traces/java-profile-{user} -d')
 
-
 def main(argv):
   parser = argparse.ArgumentParser()
   parser.add_argument(
@@ -104,11 +102,6 @@
       "--print-config",
       action="store_true",
       help="Print config instead of running. For debugging.")
-  parser.add_argument(
-      "--stop-when-done",
-      action="store_true",
-      help="On recent builds of S, use a new method to stop the profile when "
-           "the dump is done. Previously, we would hardcode a duration.")
 
   args = parser.parse_args()
 
@@ -146,21 +139,9 @@
   if args.continuous_dump:
     continuous_dump_cfg = CONTINUOUS_DUMP.format(
         dump_interval=args.continuous_dump)
-
-  # TODO(fmayer): Once the changes have been in S for long enough, make this
-  #               the default for S+.
-  if args.stop_when_done:
-    duration_ms = 1000
-    data_source_stop_timeout_ms = 100000
-  else:
-    duration_ms = 20000
-    data_source_stop_timeout_ms = 0
-
   cfg = CFG.format(
       target_cfg=target_cfg,
-      continuous_dump_config=continuous_dump_cfg,
-      duration_ms=duration_ms,
-      data_source_stop_timeout_ms=data_source_stop_timeout_ms)
+      continuous_dump_config=continuous_dump_cfg)
   if not args.no_versions:
     cfg += PACKAGES_LIST_CFG
 
@@ -168,11 +149,10 @@
     print(cfg)
     return 0
 
-  user = subprocess.check_output(
-    ['adb', 'shell', 'whoami']).strip().decode('utf8')
+  user = subprocess.check_output(['adb', 'shell', 'whoami']).strip()
   perfetto_pid = subprocess.check_output(
       ['adb', 'exec-out',
-       PERFETTO_CMD.format(cfg=cfg, user=user)]).strip().decode('utf8')
+       PERFETTO_CMD.format(cfg=cfg, user=user)]).strip()
   try:
     int(perfetto_pid.strip())
   except ValueError:
diff --git a/tools/mm_events b/tools/mm_events
deleted file mode 100755
index cd66327..0000000
--- a/tools/mm_events
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/system/bin/sh
-
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Periodically arms a perfetto trace config for mm_events
-# The config is triggered by the mm_events kmem_activity trigger
-# This script gets executed as a oneshot service from perfetto.rc
-# when persist.mm_events.enabled is set to true.
-
-DEFAULT_TRACE_CONFIG=<<EOF
-unique_session_name: "perfetto_mm_events_session"
-
-bugreport_score: 100
-
-buffers: {
-  size_kb: 512
-  fill_policy: DISCARD
-}
-
-data_sources: {
-  config {
-    name: "linux.sys_stats"
-    sys_stats_config {
-      vmstat_period_ms: 500
-      vmstat_counters: VMSTAT_NR_FREE_PAGES
-      vmstat_counters: VMSTAT_NR_SLAB_RECLAIMABLE
-      vmstat_counters: VMSTAT_NR_SLAB_UNRECLAIMABLE
-      vmstat_counters: VMSTAT_NR_ACTIVE_FILE
-      vmstat_counters: VMSTAT_NR_INACTIVE_FILE
-      vmstat_counters: VMSTAT_NR_ACTIVE_ANON
-      vmstat_counters: VMSTAT_NR_INACTIVE_ANON
-      vmstat_counters: VMSTAT_WORKINGSET_REFAULT
-      vmstat_counters: VMSTAT_WORKINGSET_ACTIVATE
-      vmstat_counters: VMSTAT_NR_FILE_PAGES
-      vmstat_counters: VMSTAT_PGPGIN
-      vmstat_counters: VMSTAT_PGPGOUT
-      vmstat_counters: VMSTAT_PSWPIN
-      vmstat_counters: VMSTAT_PSWPOUT
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_DMA
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_NORMAL
-      vmstat_counters: VMSTAT_PGSTEAL_KSWAPD_MOVABLE
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_DMA
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_NORMAL
-      vmstat_counters: VMSTAT_PGSTEAL_DIRECT_MOVABLE
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_DMA
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_NORMAL
-      vmstat_counters: VMSTAT_PGSCAN_KSWAPD_MOVABLE
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_DMA
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_NORMAL
-      vmstat_counters: VMSTAT_PGSCAN_DIRECT_MOVABLE
-      vmstat_counters: VMSTAT_COMPACT_MIGRATE_SCANNED
-      vmstat_counters: VMSTAT_COMPACT_FREE_SCANNED
-    }
-  }
-}
-
-data_sources: {
-  config {
-    name: "linux.ftrace"
-    ftrace_config {
-      ftrace_events: "vmscan/mm_vmscan_kswapd_wake"
-      ftrace_events: "vmscan/mm_vmscan_kswapd_sleep"
-      ftrace_events: "vmscan/mm_vmscan_direct_reclaim_begin"
-      ftrace_events: "vmscan/mm_vmscan_direct_reclaim_end"
-      ftrace_events: "compaction/mm_compaction_begin"
-      ftrace_events: "compaction/mm_compaction_end"
-    }
-  }
-}
-
-trigger_config {
-  trigger_mode: START_TRACING
-  trigger_timeout_ms: 3600000
-  triggers {
-    name: "kmem_activity"
-    stop_delay_ms: 360000
-  }
-}
-EOF
-
-VENDOR_TRACE_CONFIG="/vendor/etc/mm_events.cfg"
-
-BASE_SLEEP=30
-SLEEP=$BASE_SLEEP
-BACKOFF_MULTIPLIER=2
-CONSECUTIVE_FAILURES=0
-FAILURES_THRESHOLD=10
-
-# Keep the mm events perfetto trace config armed
-while :
-do
-    sleep $SLEEP
-
-    # If an alternate vendor trace config exists use that instead of the default.
-    if [ -f "$VENDOR_TRACE_CONFIG" ]; then
-        /system/bin/perfetto -c "$VENDOR_TRACE_CONFIG" --txt -o /dev/null
-        EXIT_CODE=$?
-    else
-        echo "$DEFAULT_TRACE_CONFIG" | /system/bin/perfetto -c - --txt -o /dev/null
-        EXIT_CODE=$?
-    fi
-
-    if [[ $EXIT_CODE -ne 0 ]]; then
-        SLEEP=$(($SLEEP * $BACKOFF_MULTIPLIER))
-
-        CONSECUTIVE_FAILURES=$(($CONSECUTIVE_FAILURES + 1))
-        if [ $CONSECUTIVE_FAILURES -ge $FAILURES_THRESHOLD ]; then
-            exit 1
-        fi
-    else
-        SLEEP=$BASE_SLEEP
-        CONSECUTIVE_FAILURES=0
-    fi
-done
diff --git a/tools/multithreaded_alloc.cc b/tools/multithreaded_alloc.cc
deleted file mode 100644
index 6125777..0000000
--- a/tools/multithreaded_alloc.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <condition_variable>
-#include <iterator>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/getopt.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/heap_profile.h"
-
-namespace {
-
-void EnabledCallback(void*, const AHeapProfileEnableCallbackInfo*);
-
-std::atomic<bool> done;
-std::atomic<uint64_t> allocs{0};
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wglobal-constructors"
-#pragma GCC diagnostic ignored "-Wexit-time-destructors"
-std::mutex g_wake_up_mutex;
-std::condition_variable g_wake_up_cv;
-uint64_t g_rate = 0;
-
-uint32_t g_heap_id = AHeapProfile_registerHeap(
-    AHeapInfo_setEnabledCallback(AHeapInfo_create("test_heap"),
-                                 EnabledCallback,
-                                 nullptr));
-
-#pragma GCC diagnostic pop
-
-void EnabledCallback(void*, const AHeapProfileEnableCallbackInfo* info) {
-  std::lock_guard<std::mutex> l(g_wake_up_mutex);
-  g_rate = AHeapProfileEnableCallbackInfo_getSamplingInterval(info);
-  g_wake_up_cv.notify_all();
-}
-
-uint64_t ScrambleAllocId(uint64_t alloc_id, uint32_t thread_idx) {
-  return thread_idx | (~alloc_id << 24);
-}
-
-void Thread(uint32_t thread_idx, uint64_t pending_allocs) {
-  PERFETTO_CHECK(thread_idx < 1 << 24);
-  uint64_t alloc_id = 0;
-  size_t thread_allocs = 0;
-  while (!done.load(std::memory_order_relaxed)) {
-    AHeapProfile_reportAllocation(g_heap_id,
-                                  ScrambleAllocId(alloc_id, thread_idx), 1);
-    if (alloc_id > pending_allocs)
-      AHeapProfile_reportFree(
-          g_heap_id, ScrambleAllocId(alloc_id - pending_allocs, thread_idx));
-    alloc_id++;
-    thread_allocs++;
-  }
-  allocs.fetch_add(thread_allocs, std::memory_order_relaxed);
-}
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  if (argc != 4) {
-    PERFETTO_FATAL("%s NUMBER_THREADS RUNTIME_MS PENDING_ALLOCS", argv[0]);
-  }
-
-  perfetto::base::Optional<uint64_t> opt_no_threads =
-      perfetto::base::CStringToUInt64(argv[1]);
-  if (!opt_no_threads) {
-    PERFETTO_FATAL("Invalid number of threads: %s", argv[1]);
-  }
-  uint64_t no_threads = *opt_no_threads;
-
-  perfetto::base::Optional<uint64_t> opt_runtime_ms =
-      perfetto::base::CStringToUInt64(argv[2]);
-  if (!opt_runtime_ms) {
-    PERFETTO_FATAL("Invalid runtime: %s", argv[2]);
-  }
-  uint64_t runtime_ms = *opt_runtime_ms;
-
-  perfetto::base::Optional<uint64_t> opt_pending_allocs =
-      perfetto::base::CStringToUInt64(argv[3]);
-  if (!opt_runtime_ms) {
-    PERFETTO_FATAL("Invalid number of pending allocs: %s", argv[3]);
-  }
-  uint64_t pending_allocs = *opt_pending_allocs;
-
-  std::unique_lock<std::mutex> l(g_wake_up_mutex);
-  g_wake_up_cv.wait(l, [] { return g_rate > 0; });
-
-  perfetto::base::TimeMillis end =
-      perfetto::base::GetWallTimeMs() + perfetto::base::TimeMillis(runtime_ms);
-  std::vector<std::thread> threads;
-  for (size_t i = 0; i < static_cast<size_t>(no_threads); ++i)
-    threads.emplace_back(Thread, i, pending_allocs);
-
-  perfetto::base::TimeMillis current = perfetto::base::GetWallTimeMs();
-  while (current < end) {
-    usleep(useconds_t((end - current).count()) * 1000);
-    current = perfetto::base::GetWallTimeMs();
-  }
-
-  done.store(true, std::memory_order_relaxed);
-
-  for (std::thread& th : threads)
-    th.join();
-
-  printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
-         no_threads, runtime_ms, pending_allocs, g_rate,
-         allocs.load(std::memory_order_relaxed));
-  return 0;
-}
diff --git a/tools/node b/tools/node
deleted file mode 100755
index 04b4e4c..0000000
--- a/tools/node
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 -e -u
-
-# Note: this script is both executed standalone via tools/node and
-# sourced by tools/npm.
-
-ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
-
-if [ "$(uname -s)" == "Darwin" ]; then
-readonly NODE_DIR="$ROOT_DIR/buildtools/mac/nodejs"
-else
-readonly NODE_DIR="$ROOT_DIR/buildtools/linux64/nodejs"
-fi
-
-if [ ! -e "$NODE_DIR" ]; then
-  echo 'Could not find Node.js hermetic installation. Please run:'
-  echo 'tools/install-build-deps --ui'
-  exit 1
-fi
-
-exec_node() {
-  # Rationale for adding $ROOT_DIR/tools: some packages (notably protobufjs)
-  # have the bad habit of executing "npm install ..." at runtime on the first
-  # run. That will pick whatever "npm" is in the PATH which might be strongly
-  # different than ours in /buildtools.
-  export PATH="$NODE_DIR/bin:$ROOT_DIR/tools:$PATH"
-  exec node "$@"
-}
-
-# If the script is sourced (from //tools/npm) stop here. Otherwise run node.
-if [ "$0" == "${BASH_SOURCE[0]}" ]; then
-  exec_node "$@"
-fi
diff --git a/tools/npm b/tools/npm
deleted file mode 100755
index 54125ab..0000000
--- a/tools/npm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/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 -e -u
-
-ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
-. "$ROOT_DIR/tools/node"
-
-export NPM_PREFIX="$NODE_DIR"
-NPM_CLI_JS="$NPM_PREFIX/lib/node_modules/npm/bin/npm-cli.js"
-exec_node "$NPM_CLI_JS" "$@"
diff --git a/tools/print_descriptor.py b/tools/print_descriptor.py
deleted file mode 100755
index e4c0a92..0000000
--- a/tools/print_descriptor.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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_pb2
-
-
-# Take a path to file with binary protobuf descriptor as CLI argument and print
-# it in textproto format.
-#
-# Example usage:
-#   tools/print_descriptor.py path/to/file.descriptor
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      'input_file',
-      type=str,
-      help='File name with binary proto descriptor to print')
-  args = parser.parse_args()
-
-  descriptor = descriptor_pb2.FileDescriptorSet()
-  with open(args.input_file, 'rb') as f:
-    contents = f.read()
-    descriptor.MergeFromString(contents)
-
-  print(descriptor)
-
-
-if __name__ == "__main__":
-  main()
diff --git a/tools/proto_filter/BUILD.gn b/tools/proto_filter/BUILD.gn
deleted file mode 100644
index b2b6997..0000000
--- a/tools/proto_filter/BUILD.gn
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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("proto_filter") {
-  testonly = true
-  deps = [
-    "../../gn:default_deps",
-    "../../gn:protobuf_full",
-    "../../src/base",
-    "../../src/protozero",
-    "../../src/protozero/filtering:bytecode_generator",
-    "../../src/protozero/filtering:filter_util",
-    "../../src/protozero/filtering:message_filter",
-  ]
-  sources = [ "proto_filter.cc" ]
-}
diff --git a/tools/proto_filter/proto_filter.cc b/tools/proto_filter/proto_filter.cc
deleted file mode 100644
index e7443cb..0000000
--- a/tools/proto_filter/proto_filter.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/file_utils.h"
-#include "perfetto/ext/base/getopt.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/version.h"
-#include "src/protozero/filtering/filter_util.h"
-#include "src/protozero/filtering/message_filter.h"
-
-namespace perfetto {
-namespace proto_filter {
-namespace {
-
-const char kUsage[] =
-    R"(Usage: proto_filter [-s schema_in] [-i message in] [-o message out] [-f filter in] [-F filter out] [-T filter_oct_out] [-d --dedupe] [-I proto include path] [-r root message]
-
--s --schema-in:      Path to the root .proto file. Required for most operations
--I --proto_path:     Extra include directory for proto includes. If omitted assumed CWD.
--r --root_message:   Fully qualified name for the root proto message (e.g. perfetto.protos.Trace)
-                     If omitted the first message defined in the schema will be used.
--i --msg_in:         Path of a binary-encoded proto message which will be filtered.
--o --msg_out:        Path of the binary-encoded filtered proto message written in output.
--f --filter_in:      Path of a filter bytecode file previously generated by this tool.
--F --filter_out:     Path of the filter bytecode file generated from the --schema-in definition.
--T --filter_oct_out: Like --filter_out, but emits a octal-escaped C string suitable for .pbtx.
--d --dedupe:         Minimize filter size by deduping leaf messages with same field ids.
-
-Example usage:
-
-# Convert a .proto schema file into a diff-friendly list of messages/fields>
-
-  proto_filter -r perfetto.protos.Trace -s protos/perfetto/trace/trace.proto
-
-# Generate the filter bytecode from a .proto schema
-
-  proto_filter -r perfetto.protos.Trace -s protos/perfetto/trace/trace.proto \
-               -F /tmp/bytecode [--dedupe]
-
-# List the used/filtered fields from a trace file
-
-  proto_filter -r perfetto.protos.Trace -s protos/perfetto/trace/trace.proto \
-               -i test/data/example_android_trace_30s.pb -f /tmp/bytecode
-
-# Filter a trace using a filter bytecode
-
-  proto_filter -i test/data/example_android_trace_30s.pb -f /tmp/bytecode \
-               -o /tmp/filtered_trace
-)";
-
-int Main(int argc, char** argv) {
-  static const option long_options[] = {
-      {"help", no_argument, nullptr, 'h'},
-      {"version", no_argument, nullptr, 'v'},
-      {"dedupe", no_argument, nullptr, 'd'},
-      {"proto_path", no_argument, nullptr, 'I'},
-      {"schema_in", no_argument, nullptr, 's'},
-      {"root_message", no_argument, nullptr, 'r'},
-      {"msg_in", no_argument, nullptr, 'i'},
-      {"msg_out", no_argument, nullptr, 'o'},
-      {"filter_in", no_argument, nullptr, 'f'},
-      {"filter_out", no_argument, nullptr, 'F'},
-      {"filter_oct_out", no_argument, nullptr, 'T'},
-      {nullptr, 0, nullptr, 0}};
-
-  std::string msg_in;
-  std::string msg_out;
-  std::string filter_in;
-  std::string schema_in;
-  std::string filter_out;
-  std::string filter_oct_out;
-  std::string proto_path;
-  std::string root_message_arg;
-  bool dedupe = false;
-
-  for (;;) {
-    int option =
-        getopt_long(argc, argv, "hvdI:s:r:i:o:f:F:T:", long_options, nullptr);
-
-    if (option == -1)
-      break;  // EOF.
-
-    if (option == 'v') {
-      printf("%s\n", base::GetVersionString());
-      exit(0);
-    }
-
-    if (option == 'd') {
-      dedupe = true;
-      continue;
-    }
-
-    if (option == 'I') {
-      proto_path = optarg;
-      continue;
-    }
-
-    if (option == 's') {
-      schema_in = optarg;
-      continue;
-    }
-
-    if (option == 'r') {
-      root_message_arg = optarg;
-      continue;
-    }
-
-    if (option == 'i') {
-      msg_in = optarg;
-      continue;
-    }
-
-    if (option == 'o') {
-      msg_out = optarg;
-      continue;
-    }
-
-    if (option == 'f') {
-      filter_in = optarg;
-      continue;
-    }
-
-    if (option == 'F') {
-      filter_out = optarg;
-      continue;
-    }
-
-    if (option == 'T') {
-      filter_oct_out = optarg;
-      continue;
-    }
-
-    if (option == 'h') {
-      fprintf(stdout, kUsage);
-      exit(0);
-    }
-
-    fprintf(stderr, kUsage);
-    exit(1);
-  }
-
-  if (msg_in.empty() && filter_in.empty() && schema_in.empty()) {
-    fprintf(stderr, kUsage);
-    return 1;
-  }
-
-  std::string msg_in_data;
-  if (!msg_in.empty()) {
-    PERFETTO_LOG("Loading proto-encoded message from %s", msg_in.c_str());
-    if (!base::ReadFile(msg_in, &msg_in_data)) {
-      PERFETTO_ELOG("Could not open message file %s", msg_in.c_str());
-      return 1;
-    }
-  }
-
-  protozero::FilterUtil filter;
-  if (!schema_in.empty()) {
-    PERFETTO_LOG("Loading proto schema from %s", schema_in.c_str());
-    if (!filter.LoadMessageDefinition(schema_in, root_message_arg,
-                                      proto_path)) {
-      PERFETTO_ELOG("Failed to parse proto schema from %s", schema_in.c_str());
-      return 1;
-    }
-    if (dedupe)
-      filter.Dedupe();
-  }
-
-  protozero::MessageFilter msg_filter;
-  std::string filter_data;
-  std::string filter_data_src;
-  if (!filter_in.empty()) {
-    PERFETTO_LOG("Loading filter bytecode from %s", filter_in.c_str());
-    if (!base::ReadFile(filter_in, &filter_data)) {
-      PERFETTO_ELOG("Could not open filter file %s", filter_in.c_str());
-      return 1;
-    }
-    filter_data_src = filter_in;
-  } else if (!schema_in.empty()) {
-    PERFETTO_LOG("Generating filter bytecode from %s", schema_in.c_str());
-    filter_data = filter.GenerateFilterBytecode();
-    filter_data_src = schema_in;
-  }
-
-  if (!filter_data.empty()) {
-    const uint8_t* data = reinterpret_cast<const uint8_t*>(filter_data.data());
-    if (!msg_filter.LoadFilterBytecode(data, filter_data.size())) {
-      PERFETTO_ELOG("Failed to parse filter bytecode from %s",
-                    filter_data_src.c_str());
-      return 1;
-    }
-  }
-
-  // Write the filter bytecode in output.
-  if (!filter_out.empty()) {
-    auto fd = base::OpenFile(filter_out, O_WRONLY | O_TRUNC | O_CREAT, 0644);
-    if (!fd) {
-      PERFETTO_ELOG("Could not open filter out path %s", filter_out.c_str());
-      return 1;
-    }
-    PERFETTO_LOG("Writing filter bytecode (%zu bytes) into %s",
-                 filter_data.size(), filter_out.c_str());
-    base::WriteAll(*fd, filter_data.data(), filter_data.size());
-  }
-
-  if (!filter_oct_out.empty()) {
-    auto fd =
-        base::OpenFile(filter_oct_out, O_WRONLY | O_TRUNC | O_CREAT, 0644);
-    if (!fd) {
-      PERFETTO_ELOG("Could not open filter out path %s",
-                    filter_oct_out.c_str());
-      return 1;
-    }
-    std::string oct_str;
-    oct_str.reserve(filter_data.size() * 4 + 64);
-    oct_str.append("trace_filter{\n  bytecode: \"");
-    for (char c : filter_data) {
-      uint8_t octect = static_cast<uint8_t>(c);
-      char buf[5]{'\\', '0', '0', '0', 0};
-      for (uint8_t i = 0; i < 3; ++i) {
-        buf[3 - i] = static_cast<char>('0' + static_cast<uint8_t>(octect) % 8);
-        octect /= 8;
-      }
-      oct_str.append(buf);
-    }
-    oct_str.append("\"\n}\n");
-    PERFETTO_LOG("Writing filter bytecode (%zu bytes) into %s", oct_str.size(),
-                 filter_oct_out.c_str());
-    base::WriteAll(*fd, oct_str.data(), oct_str.size());
-  }
-
-  // Apply the filter to the input message (if any).
-  std::vector<uint8_t> msg_filtered_data;
-  if (!msg_in.empty()) {
-    PERFETTO_LOG("Applying filter %s to proto message %s",
-                 filter_data_src.c_str(), msg_in.c_str());
-    msg_filter.enable_field_usage_tracking(true);
-    auto res = msg_filter.FilterMessage(msg_in_data.data(), msg_in_data.size());
-    if (res.error)
-      PERFETTO_FATAL("Filtering failed");
-    msg_filtered_data.insert(msg_filtered_data.end(), res.data.get(),
-                             res.data.get() + res.size);
-  }
-
-  // Write out the filtered message.
-  if (!msg_out.empty()) {
-    PERFETTO_LOG("Writing filtered proto bytes (%zu bytes) into %s",
-                 msg_filtered_data.size(), msg_out.c_str());
-    auto fd = base::OpenFile(msg_out, O_WRONLY | O_CREAT, 0644);
-    base::WriteAll(*fd, msg_filtered_data.data(), msg_filtered_data.size());
-  }
-
-  if (!msg_in.empty()) {
-    const auto& field_usage_map = msg_filter.field_usage();
-    for (const auto& it : field_usage_map) {
-      const std::string& field_path_varint = it.first;
-      int32_t num_occurrences = it.second;
-      std::string path_str = filter.LookupField(field_path_varint);
-      printf("%-100s %s %d\n", path_str.c_str(),
-             num_occurrences < 0 ? "DROP" : "PASS", std::abs(num_occurrences));
-    }
-  } else if (!schema_in.empty()) {
-    filter.PrintAsText();
-  }
-
-  if ((!filter_out.empty() || !filter_oct_out.empty()) && !dedupe) {
-    PERFETTO_ELOG(
-        "Warning: looks like you are generating a filter without --dedupe. For "
-        "production use cases, --dedupe can make the output bytecode "
-        "significantly smaller.");
-  }
-  return 0;
-}
-
-}  // namespace
-}  // namespace proto_filter
-}  // namespace perfetto
-
-int main(int argc, char** argv) {
-  return perfetto::proto_filter::Main(argc, argv);
-}
diff --git a/tools/proto_utils.py b/tools/proto_utils.py
deleted file mode 100644
index 45fad89..0000000
--- a/tools/proto_utils.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import absolute_import
-
-import os
-import subprocess
-import tempfile
-
-from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool
-from google.protobuf import reflection, text_format
-
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def create_message_factory(descriptor_file_paths, proto_type):
-  pool = descriptor_pool.DescriptorPool()
-  for file_path in descriptor_file_paths:
-    descriptor = read_descriptor(file_path)
-    for file in descriptor.file:
-      pool.Add(file)
-
-  return message_factory.MessageFactory().GetPrototype(
-      pool.FindMessageTypeByName(proto_type))
-
-
-def read_descriptor(file_name):
-  with open(file_name, 'rb') as f:
-    contents = f.read()
-
-  descriptor = descriptor_pb2.FileDescriptorSet()
-  descriptor.MergeFromString(contents)
-
-  return descriptor
-
-
-def serialize_textproto_trace(trace_descriptor_path, extension_descriptor_paths,
-                              text_proto_path, out_stream):
-  proto = create_message_factory([trace_descriptor_path] +
-                                 extension_descriptor_paths,
-                                 'perfetto.protos.Trace')()
-
-  with open(text_proto_path, 'r') as text_proto_file:
-    text_format.Merge(text_proto_file.read(), proto)
-  out_stream.write(proto.SerializeToString())
-  out_stream.flush()
-
-
-def serialize_python_trace(trace_descriptor_path, python_trace_path,
-                           out_stream):
-  python_cmd = [
-      'python3',
-      python_trace_path,
-      trace_descriptor_path,
-  ]
-
-  # Add the test dir to the PYTHONPATH to allow synth_common to be found.
-  env = os.environ.copy()
-  if 'PYTHONPATH' in env:
-    env['PYTHONPATH'] = "{}:{}".format(
-        os.path.join(ROOT_DIR, 'test'), env['PYTHONPATH'])
-  else:
-    env['PYTHONPATH'] = os.path.join(ROOT_DIR, 'test')
-  subprocess.check_call(python_cmd, env=env, stdout=out_stream)
diff --git a/tools/protoc_helper.py b/tools/protoc_helper.py
old mode 100644
new mode 100755
index a5f937b..6861009
--- a/tools/protoc_helper.py
+++ b/tools/protoc_helper.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/tools/pull_ftrace_format_files.py b/tools/pull_ftrace_format_files.py
index 9f33df9..be934bc 100755
--- a/tools/pull_ftrace_format_files.py
+++ b/tools/pull_ftrace_format_files.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/tools/record_android_trace b/tools/record_android_trace
deleted file mode 100755
index 7874638..0000000
--- a/tools/record_android_trace
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/usr/bin/env python3
-
-import atexit
-import argparse
-import datetime
-import http.server
-import os
-import shutil
-import socketserver
-import subprocess
-import sys
-import time
-import webbrowser
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-# This is not required. It's only used as a fallback if no adb is found on the
-# PATH. It's fine if it doesn't exist so this script can be copied elsewhere.
-HERMETIC_ADB_PATH = ROOT_DIR + '/buildtools/android_sdk/platform-tools/adb'
-
-devnull = open(os.devnull, 'rb')
-adb_path = None
-procs = []
-
-
-class ANSI:
-  END = '\033[0m'
-  BOLD = '\033[1m'
-  RED = '\033[91m'
-  BLACK = '\033[30m'
-  BLUE = '\033[94m'
-  BG_YELLOW = '\033[43m'
-  BG_BLUE = '\033[44m'
-
-
-# HTTP Server used to open the trace in the browser.
-class HttpHandler(http.server.SimpleHTTPRequestHandler):
-
-  def end_headers(self):
-    self.send_header('Access-Control-Allow-Origin', '*')
-    return super().end_headers()
-
-  def do_GET(self):
-    self.server.last_request = self.path
-    return super().do_GET()
-
-  def do_POST(self):
-    self.send_error(404, "File not found")
-
-
-def main():
-  atexit.register(kill_all_subprocs_on_exit)
-  default_out_dir_str = '~/traces/'
-  default_out_dir = os.path.expanduser(default_out_dir_str)
-
-  examples = '\n'.join([
-      ANSI.BOLD + 'Examples' + ANSI.END, '  -t 10s -b 32mb sched gfx wm',
-      '  -t 5s sched/sched_switch raw_syscalls/sys_enter raw_syscalls/sys_exit',
-      '  -c /path/to/full-textual-trace.config', '',
-      ANSI.BOLD + 'Long traces' + ANSI.END,
-      'If you want to record a hours long trace and stream it into a file ',
-      'you need to pass a full trace config and set write_into_file = true.',
-      'See https://perfetto.dev/docs/concepts/config#long-traces .'
-  ])
-  parser = argparse.ArgumentParser(
-      epilog=examples, formatter_class=argparse.RawTextHelpFormatter)
-
-  help = 'Output file or directory (default: %s)' % default_out_dir_str
-  parser.add_argument('-o', '--out', default=default_out_dir, help=help)
-
-  help = 'Don\'t open in the browser'
-  parser.add_argument('-n', '--no-open', action='store_true', help=help)
-
-  grp = parser.add_argument_group(
-      'Short options: (only when not using -c/--config)')
-
-  help = 'Trace duration N[s,m,h] (default: trace until stopped)'
-  grp.add_argument('-t', '--time', default='0s', help=help)
-
-  help = 'Ring buffer size N[mb,gb] (default: 32mb)'
-  grp.add_argument('-b', '--buffer', default='32mb', help=help)
-
-  help = 'Android (atrace) app names (can be specified multiple times)'
-  grp.add_argument(
-      '-a',
-      '--app',
-      metavar='Atrace apps',
-      action='append',
-      default=[],
-      help=help)
-
-  help = 'sched, gfx, am, wm (see --list)'
-  grp.add_argument('events', metavar='Atrace events', nargs='*', help=help)
-
-  help = 'sched/sched_switch kmem/kmem (see --list-ftrace)'
-  grp.add_argument('_', metavar='Ftrace events', nargs='*', help=help)
-
-  help = 'Lists all the categories available'
-  grp.add_argument('--list', action='store_true', help=help)
-
-  help = 'Lists all the ftrace events available'
-  grp.add_argument('--list-ftrace', action='store_true', help=help)
-
-  section = ('Full trace config (only when not using short options)')
-  grp = parser.add_argument_group(section)
-
-  help = 'Can be generated with https://ui.perfetto.dev/#!/record'
-  grp.add_argument('-c', '--config', default=None, help=help)
-  args = parser.parse_args()
-
-  tstamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M')
-  fname = '%s.pftrace' % tstamp
-  device_file = '/data/misc/perfetto-traces/' + fname
-
-  find_adb()
-
-  if args.list:
-    adb('shell', 'atrace', '--list_categories').wait()
-    sys.exit(0)
-
-  if args.list_ftrace:
-    adb('shell', 'cat /d/tracing/available_events | tr : /').wait()
-    sys.exit(0)
-
-  if args.config is not None and not os.path.exists(args.config):
-    prt('Config file not found: %s' % args.config, ANSI.RED)
-    sys.exit(1)
-
-  if len(args.events) == 0 and args.config is None:
-    prt('Must either pass short options (e.g. -t 10s sched) or a --config file',
-        ANSI.RED)
-    parser.print_help()
-    sys.exit(1)
-
-  if args.config is None and args.events and os.path.exists(args.events[0]):
-    prt(('The passed event name "%s" is a local file. ' % args.events[0] +
-         'Did you mean to pass -c / --config ?'), ANSI.RED)
-    sys.exit(1)
-
-  cmd = ['perfetto', '--background', '--txt', '-o', device_file]
-  if args.config is not None:
-    cmd += ['-c', '-']
-  else:
-    cmd += ['-t', args.time, '-b', args.buffer]
-    for app in args.app:
-      cmd += ['--app', app]
-    cmd += args.events
-
-  # Perfetto will error out with a proper message if both a config file and
-  # short options are specified. No need to replicate that logic.
-
-  # Work out the output file or directory.
-  if args.out.endswith('/') or os.path.isdir(args.out):
-    host_dir = args.out
-    host_file = os.path.join(args.out, fname)
-  else:
-    host_file = args.out
-    host_dir = os.path.dirname(host_file)
-    if host_dir == '':
-      host_dir = '.'
-      host_file = './' + host_file
-  if not os.path.exists(host_dir):
-    shutil.os.makedirs(host_dir)
-
-  with open(args.config or os.devnull, 'rb') as f:
-    print('Running ' + ' '.join(cmd))
-    proc = adb('shell', *cmd, stdin=f, stdout=subprocess.PIPE)
-    bg_pid = proc.communicate()[0].decode().strip()
-    exit_code = proc.wait()
-
-  if exit_code != 0:
-    prt('Perfetto invocation failed', ANSI.RED)
-    sys.exit(1)
-
-  prt('Trace started. Press CTRL+C to stop', ANSI.BLACK + ANSI.BG_BLUE)
-  logcat = adb('logcat', '-v', 'brief', '-s', 'perfetto', '-b', 'main', '-T',
-               '1')
-
-  ctrl_c_count = 0
-  while ctrl_c_count < 2:
-    try:
-      poll = adb('shell', 'test -d /proc/' + bg_pid)
-      if poll.wait() != 0:
-        break
-      time.sleep(0.5)
-    except KeyboardInterrupt:
-      sig = 'TERM' if ctrl_c_count == 0 else 'KILL'
-      ctrl_c_count += 1
-      prt('Stopping the trace (SIG%s)' % sig, ANSI.BLACK + ANSI.BG_YELLOW)
-      res = adb('shell', 'kill -%s %s' % (sig, bg_pid)).wait()
-
-  logcat.kill()
-  logcat.wait()
-
-  prt('\n')
-  prt('Pulling into %s' % host_file, ANSI.BOLD)
-  adb('pull', device_file, host_file).wait()
-
-  if not args.no_open:
-    prt('\n')
-    prt('Opening the trace (%s) in the browser' % host_file)
-    open_trace_in_browser(host_file)
-
-
-def prt(msg, colors=ANSI.END):
-  print(colors + msg + ANSI.END)
-
-
-def find_adb():
-  """ Locate the "right" adb path
-
-  If adb is in the PATH use that (likely what the user wants) otherwise use the
-  hermetic one in our SDK copy.
-  """
-  global adb_path
-  for path in ['adb', HERMETIC_ADB_PATH]:
-    try:
-      subprocess.call([path, '--version'], stdout=devnull, stderr=devnull)
-      adb_path = path
-      break
-    except OSError:
-      continue
-  if adb_path is None:
-    sdk_url = 'https://developer.android.com/studio/releases/platform-tools'
-    prt('Could not find a suitable adb binary in the PATH. ', ANSI.RED)
-    prt('You can download adb from %s' % sdk_url, ANSI.RED)
-    sys.exit(1)
-
-
-def open_trace_in_browser(path):
-  # We reuse the HTTP+RPC port because it's the only one allowed by the CSP.
-  PORT = 9001
-  os.chdir(os.path.dirname(path))
-  fname = os.path.basename(path)
-  socketserver.TCPServer.allow_reuse_address = True
-  with socketserver.TCPServer(('127.0.0.1', PORT), HttpHandler) as httpd:
-    webbrowser.open_new_tab(
-            'https://ui.perfetto.dev/#!/?url=http://127.0.0.1:%d/%s' %
-        (PORT, fname))
-    while httpd.__dict__.get('last_request') != '/' + fname:
-      httpd.handle_request()
-
-
-def adb(*args, stdin=devnull, stdout=None):
-  cmd = [adb_path, *args]
-  setpgrp = None
-  if os.name != 'nt':
-    # On Linux/Mac, start a new process group so all child processes are killed
-    # on exit. Unsupported on Windows.
-    setpgrp = lambda: os.setpgrp()
-  proc = subprocess.Popen(cmd, stdin=stdin, stdout=stdout, preexec_fn=setpgrp)
-  procs.append(proc)
-  return proc
-
-
-def kill_all_subprocs_on_exit():
-  for p in [p for p in procs if p.poll() is None]:
-    p.kill()
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/roll-catapult-trace-viewer b/tools/roll-catapult-trace-viewer
index 84e0eb5..c163885 100755
--- a/tools/roll-catapult-trace-viewer
+++ b/tools/roll-catapult-trace-viewer
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 # Builds the current version of catapult, uploads it to GCS and updates the
-# pinned SHA256 in install-build-deps.
+# pinned SHA1 in install-build-deps.
 
 set -e
 
@@ -69,15 +69,15 @@
   tar -zcf "$ARCHIVE" catapult_trace_viewer.{js,html}
 )
 
-SHA256CMD='import hashlib; import sys; sha1=hashlib.sha256(); sha1.update(sys.stdin.read()); print(sha1.hexdigest())'
-SHA256=$(python -c "$SHA256CMD" < "$ARCHIVE")
-GCS_TARGET="gs://perfetto/catapult_trace_viewer-$SHA256.tar.gz"
+SHA1CMD='import hashlib; import sys; sha1=hashlib.sha1(); sha1.update(sys.stdin.read()); print(sha1.hexdigest())'
+SHA1=$(python -c "$SHA1CMD" < "$ARCHIVE")
+GCS_TARGET="gs://perfetto/catapult_trace_viewer-$SHA1.tar.gz"
 gsutil cp -n -a public-read "$ARCHIVE" "$GCS_TARGET"
 rm -rf "$OUTDIR"
 
 # Update the reference to the new prebuilt in tools/install-build-deps.
 sed -i -e \
-    "s/^CATAPULT_SHA256 =.*/CATAPULT_SHA256 = '"$SHA256"'/g" \
+    "s/^CATAPULT_SHA1 =.*/CATAPULT_SHA1 = '"$SHA1"'/g" \
      "$PROJECT_ROOT/tools/install-build-deps"
 
-"$PROJECT_ROOT/tools/install-build-deps" --ui
+"$PROJECT_ROOT/tools/install-build-deps" --ui
\ No newline at end of file
diff --git a/tools/run_android_emulator b/tools/run_android_emulator
index 6f6ffcf..7852919 100755
--- a/tools/run_android_emulator
+++ b/tools/run_android_emulator
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,6 +15,7 @@
 
 import argparse
 import os
+import shutil
 import sys
 
 
@@ -54,8 +55,8 @@
       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))
+  print '\n'.join('='.join(x) for x in env.items())
+  print ' '.join([emulator_bin] + emulator_args)
   if args.pid:
     with open(args.pid, 'w') as f:
       f.write(str(os.getpid()))
diff --git a/tools/run_android_test b/tools/run_android_test
index 5f38951..4707796 100755
--- a/tools/run_android_test
+++ b/tools/run_android_test
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,12 @@
 
 import argparse
 import os
+import re
 import functools
 import logging
 import subprocess
 import sys
+import tempfile
 import time
 """ Runs a test executable on Android.
 
@@ -83,7 +85,7 @@
 
 def AdbCall(*args):
   cmd = [ADB_PATH] + list(args)
-  print('> adb ' + ' '.join(args))
+  print '> adb ' + ' '.join(args)
   return subprocess.check_call(cmd)
 
 
@@ -91,18 +93,18 @@
   if not os.path.exists(host):
     logging.fatal('Cannot find %s. Was it built?', host)
   cmd = [ADB_PATH, 'push', host, device]
-  print('> adb push ' + ' '.join(cmd[2:]))
-  with open(os.devnull, 'wb') as devnull:
+  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))
-  output = subprocess.check_output(cmd).decode()
+  print '> adb ' + ' '.join(cmd)
+  output = subprocess.check_output(cmd)
   lines = output.splitlines()
   assert len(lines) == 1, 'Expected output to have one line: {}'.format(output)
-  print(lines[0])
+  print lines[0]
   return lines[0]
 
 
@@ -123,41 +125,32 @@
   parser = argparse.ArgumentParser()
   parser.add_argument('--no-cleanup', '-n', action='store_true')
   parser.add_argument('--no-data-deps', '-x', action='store_true')
-  parser.add_argument('--system-adb', action='store_true')
   parser.add_argument('--env', '-e', action='append')
   parser.add_argument('out_dir', help='out/android/')
   parser.add_argument('test_name', help='perfetto_unittests')
   parser.add_argument('cmd_args', nargs=argparse.REMAINDER)
   args = parser.parse_args()
 
-  if args.system_adb:
-    global ADB_PATH
-    ADB_PATH = 'adb'
-
   test_bin = os.path.join(args.out_dir, args.test_name)
   assert os.path.exists(test_bin)
 
-  print('Waiting for device ...')
+  print 'Waiting for device ...'
   AdbCall('wait-for-device')
   # WaitForBootCompletion()
   AdbCall('root')
   AdbCall('wait-for-device')
 
-  target_dir = '/data/local/tmp/perfetto_tests'
-  if not args.no_cleanup:
-    AdbCall('shell', 'rm -rf "%s"' % target_dir)
-  AdbCall('shell', 'mkdir -p "%s"' % target_dir)
+  target_dir = '/data/local/tmp/' + args.test_name
+  AdbCall('shell', 'rm -rf "%s"; mkdir -p "%s"' % (2 * (target_dir,)))
   # Some tests require the trace directory to exist, while true for android
   # devices in general some emulators might not have it set up. So we check to
   # see if it exists, and if not create it.
-  trace_dir = '/data/misc/perfetto-traces/bugreport'
+  trace_dir = '/data/misc/perfetto-traces'
   AdbCall('shell', 'test -d "%s" || mkdir -p "%s"' % (2 * (trace_dir,)))
   AdbCall('shell', 'rm -rf "%s/*";  ' % trace_dir)
   AdbCall('shell', 'mkdir -p /data/nativetest')
-  AdbCall('shell', 'echo 0 > /d/tracing/tracing_on')
-
   # This needs to go into /data/nativetest in order to have the system linker
-  # namespace applied, which we need in order to link libdexfile.so.
+  # namespace applied, which we need in order to link libdexfile_external.so.
   # This gets linked into our tests via libundwindstack.so.
   #
   # See https://android.googlesource.com/platform/system/core/+/master/rootdir/etc/ld.config.txt.
@@ -183,14 +176,14 @@
   if args.cmd_args:
     actual_args = [arg.replace(args.test_name, binary) for arg in args.cmd_args]
     cmd += ' ' + ' '.join(actual_args)
-  print(cmd)
-  retcode = subprocess.call([ADB_PATH, 'shell', '-tt', cmd])
+  print cmd
+  retcode = subprocess.call([ADB_PATH, 'shell', cmd])
   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', '-tt', 'echo Done; exit 42'])
+  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
diff --git a/tools/run_ftrace_proto_gen b/tools/run_ftrace_proto_gen
index d1770f5..c8e9ca7 100755
--- a/tools/run_ftrace_proto_gen
+++ b/tools/run_ftrace_proto_gen
@@ -2,7 +2,7 @@
 
 # This script generates .proto files for ftrace events from the /format files
 # in src/traced/probes/ftrace/test/data/*/events/.
-# Only the events in the event_list are translated.
+# Only the events in the whitelist are translated.
 
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 if [ "$BUILDDIR" == "" ]; then
@@ -23,7 +23,7 @@
 cd "$DIR/.."
 
 "$BUILDDIR/ftrace_proto_gen" \
-  --event_list "$DIR/ftrace_proto_gen/event_list" \
+  --whitelist_path "$DIR/ftrace_proto_gen/event_whitelist" \
   --output_dir "$DIR/../protos/perfetto/trace/ftrace/" \
   --proto_descriptor "$BUILDDIR/$DESCRIPTOR" \
   --update_build_files \
diff --git a/tools/run_python_api_tests.py b/tools/run_python_api_tests.py
deleted file mode 100755
index 789a1f0..0000000
--- a/tools/run_python_api_tests.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import argparse
-import os
-import sys
-import unittest
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def main():
-  # Append test and src paths so that all imports are loaded in correctly
-  sys.path.append(os.path.join(ROOT_DIR, 'test', 'trace_processor', 'python'))
-  sys.path.append(
-      os.path.join(ROOT_DIR, 'src', 'trace_processor', 'python', 'perfetto'))
-  import api_unittest
-  import api_integrationtest
-
-  # Set paths to trace_processor_shell and root directory as environment
-  # variables
-  parser = argparse.ArgumentParser()
-  parser.add_argument("shell", type=str)
-  os.environ["SHELL_PATH"] = parser.parse_args().shell
-  os.environ["ROOT_DIR"] = ROOT_DIR
-
-  # Initialise test suite
-  loader = unittest.TestLoader()
-  suite = unittest.TestSuite()
-
-  # Add all relevant tests to test suite
-  suite.addTests(loader.loadTestsFromModule(api_unittest))
-  suite.addTests(loader.loadTestsFromModule(api_integrationtest))
-
-  # Initialise runner to run all tests in suite
-  runner = unittest.TextTestRunner(verbosity=3)
-  result = runner.run(suite)
-
-  return 0 if result.wasSuccessful() else 1
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/run_test_like_ci b/tools/run_test_like_ci
index 1df5fff..4f35def 100755
--- a/tools/run_test_like_ci
+++ b/tools/run_test_like_ci
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -114,11 +114,8 @@
                                            'ci'),
                 'BUILDER=%s' % args.runner, 'build-sandbox'))
 
-  bundle_path = '/tmp/perfetto-ci.bundle'
-  check_call(['git', '-C', REPO_ROOT, 'bundle', 'create', bundle_path, 'HEAD' ])
-  os.chmod(bundle_path, 0o664)
   env = {
-      'PERFETTO_TEST_GIT_REF': bundle_path,
+      'PERFETTO_TEST_GIT_REF': 'file:///ci/source',
   }
   env.update(JOB_CONFIGS[args.config])
 
@@ -130,7 +127,7 @@
       args.runner, 'run', '-it', '--name', 'perfetto_ci', '--cap-add',
       'SYS_PTRACE', '--rm', '--volume',
       '%s:/ci/ramdisk' % workdir, '--tmpfs', '/tmp:exec',
-      '--volume=%s:%s:ro' % (bundle_path, bundle_path)
+      '--volume=%s:/ci/source:ro' % REPO_ROOT
   ]
   for kv in env.items():
     cmd += ['--env', '%s=%s' % kv]
@@ -145,6 +142,8 @@
       ' '.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)
diff --git a/tools/serialize_test_trace.py b/tools/serialize_test_trace.py
deleted file mode 100755
index 5bb9080..0000000
--- a/tools/serialize_test_trace.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import argparse
-import os
-import sys
-
-from proto_utils import serialize_python_trace, serialize_textproto_trace
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      '--out',
-      type=str,
-      help='out directory to search for trace descriptor')
-  parser.add_argument(
-      '--descriptor', type=str, help='path to the trace descriptor')
-  parser.add_argument('trace_path', type=str, help='path of trace to serialize')
-  args = parser.parse_args()
-
-  if args.out and not args.descriptor:
-    trace_protos_path = os.path.join(args.out, 'gen', 'protos', 'perfetto',
-                                     'trace')
-    chrome_extension_descriptor_path = os.path.join(
-        args.out, 'gen', 'protos', 'third_party', 'chromium',
-        'chrome_track_event.descriptor')
-    trace_descriptor_path = os.path.join(trace_protos_path, 'trace.descriptor')
-    test_extensions_descriptor_path = os.path.join(
-        trace_protos_path, 'test_extensions.descriptor')
-    extension_descriptors = [
-        chrome_extension_descriptor_path, test_extensions_descriptor_path
-    ]
-  elif args.descriptor and not args.out:
-    trace_descriptor_path = args.descriptor
-    extension_descriptors = []
-  else:
-    raise RuntimeError(
-        'Exactly one of --out and --descriptor should be provided')
-
-  trace_path = args.trace_path
-
-  if trace_path.endswith('.py'):
-    serialize_python_trace(trace_descriptor_path, trace_path, sys.stdout.buffer)
-  elif trace_path.endswith('.textproto'):
-    serialize_textproto_trace(trace_descriptor_path, extension_descriptors,
-                              trace_path, sys.stdout.buffer)
-  else:
-    raise RuntimeError('Invalid extension for unserialized trace file')
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/strip_android_host_binary.py b/tools/strip_android_host_binary.py
new file mode 100755
index 0000000..488368a
--- /dev/null
+++ b/tools/strip_android_host_binary.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+import argparse
+import os
+import subprocess
+import sys
+
+THIS_DIR = os.path.realpath(os.path.dirname(__file__))
+
+
+def android_build_top():
+  return os.path.realpath(os.path.join(THIS_DIR, '../../..'))
+
+
+def clang_build():
+  gofile = os.path.join(android_build_top(), 'build', 'soong', 'cc', 'config',
+                        'global.go')
+  try:
+    with open(gofile) as f:
+      lines = f.readlines()
+      versionLine = [l for l in lines if 'ClangDefaultVersion' in l][0]
+      start, end = versionLine.index('"'), versionLine.rindex('"')
+      return versionLine[start + 1:end]
+  except Exception as err:
+    raise RuntimeError("Extracting Clang version failed with {0}".format(err))
+
+
+def llvm_strip():
+  return os.path.join(android_build_top(), 'prebuilts', 'clang', 'host',
+                      'linux-x86', clang_build(), 'bin', 'llvm-strip')
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Strips a binary in the Android tree.')
+  parser.add_argument(
+      '-o', dest='output', default=None, help='Output file', required=True)
+  parser.add_argument('binary', type=str, help='location of binary')
+  args = parser.parse_args()
+  return subprocess.call([llvm_strip(), args.binary, '-o', args.output])
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/symbolize-ui-crash b/tools/symbolize-ui-crash
deleted file mode 100755
index 3792ad0..0000000
--- a/tools/symbolize-ui-crash
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python3
-# 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.
-"""Like llvm-symbolizer for UI JS/TS sources.
-
-This script is used to "symbolize" UI crashes. It takes a crash, typically
-copied from a bug reports, of the form:
-
-(https://ui.perfetto.dev/v12.1.269/frontend_bundle.js:7639:61) at foo()
-(https://ui.perfetto.dev/v12.1.269/frontend_bundle.js:9235:29) at bar()
-
-it fetches the corresponding source maps and emits in output a translated
-crash report, of the form:
-
-(https://github.com/google/perfetto/blob/de4db33f/ui/src/foo.ts#L61) at foo()
-(https://github.com/google/perfetto/blob/de4db33f/ui/src/baz.ts#L300) at bar()
-"""
-
-import logging
-import re
-import sys
-import tempfile
-import urllib.request
-import ssl
-import os
-
-try:
-  import sourcemap
-except:
-  print('Run `pip3 install sourcemap` and try again')
-  sys.exit(1)
-
-
-def fetch_url_cached(url):
-  normalized = re.sub('[^a-zA-Z0-9-._]', '_', url)
-  local_file = os.path.join(tempfile.gettempdir(), normalized)
-  if os.path.exists(local_file):
-    logging.debug('Using %s', local_file)
-    with open(local_file, 'r') as f:
-      return f.read()
-  context = ssl._create_unverified_context()
-  logging.info('Fetching %s', url)
-  resp = urllib.request.urlopen(url, context=context)
-  contents = resp.read().decode()
-  with open(local_file, 'w') as f:
-    f.write(contents)
-  return contents
-
-
-def Main():
-  if len(sys.argv) > 1:
-    with open(sys.argv[1], 'r') as f:
-      txt = f.read()
-  else:
-    if sys.stdin.isatty():
-      print('Paste the crash log and press CTRL-D\n')
-    txt = sys.stdin.read()
-
-  # Look for the GIT commitish appended in crash reports. This is not required
-  # for resolving the sourcemaps but helps generating better links.
-  matches = re.findall(r'([a-f0-9]{40})\sUA', txt)
-  git_rev = matches[0] if matches else 'HEAD'
-
-  matches = re.findall(r'((\bhttp.+?\.js):(\d+):(\d+))', txt)
-  maps_by_url = {}
-  sym_lines = ''
-  for entry in matches:
-    whole_token, script_url, line, col = entry
-    map_url = script_url + '.map'
-    if map_url in maps_by_url:
-      srcmap = maps_by_url[map_url]
-    else:
-      map_file_contents = fetch_url_cached(map_url)
-      srcmap = sourcemap.loads(map_file_contents)
-      maps_by_url[map_url] = srcmap
-    sym = srcmap.lookup(int(line), int(col))
-    src = sym.src.replace('../../', '')
-    sym_url = '%s#%s' % (src, sym.src_line)
-    if src.startswith('../out/ui/'):
-      src = src.replace('../out/ui/', 'ui/')
-      sym_url = 'https://github.com/google/perfetto/blob/%s/%s#L%d' % (
-          git_rev, src, sym.src_line)
-    sym_lines += sym_url + '\n'
-    txt = txt.replace(whole_token, sym_url)
-
-  print(txt)
-  print('\nResolved symbols:\n' + sym_lines)
-
-
-if __name__ == '__main__':
-  logging.basicConfig(level=logging.INFO)
-  sys.exit(Main())
diff --git a/tools/test_data.txt b/tools/test_data.txt
index 55ee848..abcb65d 100644
--- a/tools/test_data.txt
+++ b/tools/test_data.txt
@@ -1,8 +1,5 @@
 # List of test deps that should be pushed on the device. Paths are relative
 # to the root.
-src/traced/probes/filesystem/testdata/
 src/traced/probes/ftrace/test/data/
-test/data/android_log_ring_buffer_mode.pb
-test/data/example_android_trace_30s.pb
-test/data/full_trace_filter.bytecode
+src/traced/probes/filesystem/testdata/
 test/data/kallsyms.txt
diff --git a/tools/test_gen_amalgamated.py b/tools/test_gen_amalgamated.py
index aa99bc4..8aa5a94 100755
--- a/tools/test_gen_amalgamated.py
+++ b/tools/test_gen_amalgamated.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,6 @@
 import os
 import shutil
 import subprocess
-import sys
 
 from compat import quote
 from platform import system
@@ -43,7 +42,7 @@
   try:
     return subprocess.check_output(command, cwd=ROOT_DIR).decode()
   except subprocess.CalledProcessError as e:
-    assert False, 'Command: %s failed: %s' % (' '.join(command), e)
+    assert False, 'Command: %s failed: %s'.format(' '.join(command))
 
 
 def check_amalgamated_output():
@@ -59,14 +58,7 @@
   ]
   if system().lower() == 'linux':
     args += ['-lpthread', '-lrt']
-
-  if sys.platform.startswith('linux'):
-    llvm_script = os.path.join(ROOT_DIR, 'gn', 'standalone', 'toolchain',
-                               'linux_find_llvm.py')
-    cxx = subprocess.check_output([llvm_script]).splitlines()[2].decode()
-  else:
-    cxx = 'clang++'
-  call(cxx, *args)
+  call('clang++', *args)
 
 
 def check_amalgamated_dependencies():
diff --git a/tools/tmux b/tools/tmux
index 51d1400..c9568c6 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -15,6 +15,8 @@
 set -e
 SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
 
+export PATH="$PATH:$SCRIPT_DIR"
+
 if [ "$TMPDIR" == "" ]; then
   TMPDIR=/tmp
 fi
@@ -22,8 +24,7 @@
 function get_gn_value() {
   local out=$1
   local key=$2
-  "$SCRIPT_DIR/gn" args "$out" --list=$key --short | awk '{print $3}' \
-    | tr -d '"'
+  gn args "$out" --list=$key --short | awk '{print $3}' | tr -d '"'
 }
 
 function is_monolithic() {
diff --git a/tools/touch_file.py b/tools/touch_file.py
deleted file mode 100644
index 899a0ee..0000000
--- a/tools/touch_file.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This script writes an empty file to disk at the specified path. The main use
-# of this is to allow noop targets to be written in GN which simply propogate
-# information to the GN description files without actually generating any data.
-
-import argparse
-import sys
-import os
-
-
-def touch(fname, times=None):
-  with open(fname, 'a'):
-    os.utime(fname, times)
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--output')
-  args = parser.parse_args()
-
-  touch(args.output)
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/trace_processor b/tools/trace_processor
index 22aaab6..533d24d 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +21,7 @@
 # cat ./trace_processor | python -
 
 BASH_FALLBACK = """ "
-exec python3 - "$@" <<'#'EOF
+exec python - "$@" <<'#'EOF
 #"""
 
 import hashlib
@@ -29,11 +29,10 @@
 import sys
 import tempfile
 import subprocess
-import platform
 
 TRACE_PROCESSOR_SHELL_SHAS = {
-    'linux': 'a3ce2cbf4cbe4f86cc10b02957db727cecfafae8',
-    'mac': 'c39a5be9a3831911ef2e50d66d11c12d877688f3',
+    'linux': '3a28532ba5cb1b94cea8a563bbfa7d16175f208d',
+    'mac': '637fe7ac61f1700edd2fbaa76e0775ea97f4c394',
 }
 TRACE_PROCESSOR_SHELL_PATH = tempfile.gettempdir()
 TRACE_PROCESSOR_SHELL_BASE_URL = ('https://storage.googleapis.com/perfetto/')
@@ -70,22 +69,16 @@
 
 
 def main(argv):
-  os_name = None
+  platform = None
   if sys.platform.startswith('linux'):
-    os_name = 'linux'
+    platform = 'linux'
   elif sys.platform.startswith('darwin'):
-    os_name = 'mac'
+    platform = 'mac'
   else:
     print("Invalid platform: {}".format(sys.platform))
     return 1
 
-  arch = platform.machine()
-  if arch not in ['x86_64', 'amd64']:
-    print("Prebuilts are only available for x86_64 (found '{}' instead).".format(arch))
-    print("Follow https://perfetto.dev/docs/contributing/build-instructions to build locally.")
-    return 1
-
-  trace_processor_shell_binary = load_trace_processor_shell(os_name)
+  trace_processor_shell_binary = load_trace_processor_shell(platform)
   os.execv(trace_processor_shell_binary,
            [trace_processor_shell_binary] + argv[1:])
 
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 7c409a3..bb0cf7b 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -39,6 +39,7 @@
 source_set("utils") {
   deps = [
     "../../gn:default_deps",
+    "../../include/perfetto/profiling:deobfuscator",
     "../../include/perfetto/protozero",
     "../../include/perfetto/trace_processor",
     "../../protos/perfetto/trace:zero",
@@ -48,7 +49,10 @@
     "../../src/profiling/symbolizer",
     "../../src/profiling/symbolizer:symbolize_database",
   ]
-  public_deps = [ "../../include/perfetto/ext/base" ]
+  public_deps = [
+    "../../include/perfetto/ext/base",
+    "../../include/perfetto/profiling:deobfuscator",
+  ]
   if (enable_perfetto_zlib) {
     public_deps += [ "../../gn:zlib" ]
   }
@@ -71,7 +75,6 @@
     "../../protos/third_party/pprof:zero",
     "../../src/profiling/symbolizer",
     "../../src/profiling/symbolizer:symbolize_database",
-    "../../src/trace_processor/containers:containers",
   ]
   sources = [ "pprof_builder.cc" ]
 }
@@ -79,7 +82,7 @@
 # Exposed in bazel builds.
 static_library("libpprofbuilder") {
   complete_static_lib = true
-  public_deps = [ ":pprofbuilder" ]
+  deps = [ ":pprofbuilder" ]
 }
 
 # The core source files that are used both by the "full" version (the host
@@ -91,9 +94,9 @@
     "../../gn:default_deps",
     "../../include/perfetto/base",
     "../../include/perfetto/ext/traced:sys_stats_counters",
+    "../../include/perfetto/profiling:deobfuscator",
     "../../include/perfetto/protozero",
     "../../protos/perfetto/trace:zero",
-    "../../src/profiling:deobfuscator",
     "../../src/profiling/symbolizer",
     "../../src/profiling/symbolizer:symbolize_database",
     "../../src/trace_processor:lib",
@@ -104,8 +107,6 @@
     "main.cc",
     "symbolize_profile.cc",
     "symbolize_profile.h",
-    "trace_to_hprof.cc",
-    "trace_to_hprof.h",
     "trace_to_json.cc",
     "trace_to_json.h",
     "trace_to_profile.cc",
@@ -114,6 +115,9 @@
     "trace_to_systrace.h",
     "trace_to_text.h",
   ]
+  if (enable_perfetto_version_gen) {
+    deps += [ "//gn/standalone:gen_git_revision" ]
+  }
 }
 
 # Lite target for the WASM UI. Doesn't have any dependency on libprotobuf-full.
@@ -146,12 +150,10 @@
   ]
 }
 
-if (enable_perfetto_ui) {
-  wasm_lib("trace_to_text_wasm") {
-    name = "trace_to_text"
-    deps = [
-      ":lite",
-      "../../gn:default_deps",
-    ]
-  }
+wasm_lib("trace_to_text_wasm") {
+  name = "trace_to_text"
+  deps = [
+    ":lite",
+    "../../gn:default_deps",
+  ]
 }
diff --git a/tools/trace_to_text/deobfuscate_profile.cc b/tools/trace_to_text/deobfuscate_profile.cc
index bc11730..b6e8b8c 100644
--- a/tools/trace_to_text/deobfuscate_profile.cc
+++ b/tools/trace_to_text/deobfuscate_profile.cc
@@ -17,33 +17,70 @@
 #include <stdio.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/profiling/deobfuscator.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "src/profiling/deobfuscator.h"
 #include "tools/trace_to_text/deobfuscate_profile.h"
 #include "tools/trace_to_text/utils.h"
 
 namespace perfetto {
 namespace trace_to_text {
+namespace {
+
+bool ParseFile(profiling::ProguardParser* p, FILE* f) {
+  std::vector<std::string> lines;
+  size_t n = 0;
+  char* line = nullptr;
+  ssize_t rd = 0;
+  bool success = true;
+  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';
+      success = p->AddLine(line);
+    }
+  } while (rd > 1 && success);
+  free(line);
+  return success;
+}
+}  // namespace
 
 int DeobfuscateProfile(std::istream* input, std::ostream* output) {
   base::ignore_result(input);
   base::ignore_result(output);
-  auto maybe_map = profiling::GetPerfettoProguardMapPath();
-  if (maybe_map.empty()) {
+  auto maybe_map = GetPerfettoProguardMapPath();
+  if (!maybe_map) {
     PERFETTO_ELOG("No PERFETTO_PROGUARD_MAP specified.");
     return 1;
   }
-  if (!profiling::ReadProguardMapsToDeobfuscationPackets(
-          maybe_map, [output](const std::string& trace_proto) {
-            *output << trace_proto;
-          })) {
+  base::ScopedFstream f(fopen(maybe_map->c_str(), "r"));
+  if (!f) {
+    PERFETTO_ELOG("Failed to open %s", maybe_map->c_str());
     return 1;
   }
+  profiling::ProguardParser parser;
+  if (!ParseFile(&parser, *f)) {
+    PERFETTO_ELOG("Failed to parse %s", maybe_map->c_str());
+    return 1;
+  }
+  std::map<std::string, profiling::ObfuscatedClass> obfuscation_map =
+      parser.ConsumeMapping();
 
+  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();
+  DeobfuscateDatabase(tp.get(), obfuscation_map,
+                      [output](const std::string& packet_proto) {
+                        WriteTracePacket(packet_proto, output);
+                      });
   return 0;
 }
 
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index e4a9f1d..e3c084c 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -23,15 +23,19 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/version.h"
 #include "tools/trace_to_text/deobfuscate_profile.h"
 #include "tools/trace_to_text/symbolize_profile.h"
-#include "tools/trace_to_text/trace_to_hprof.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)
+#include "perfetto_version.gen.h"
+#else
+#define PERFETTO_GET_GIT_REVISION() "unknown"
+#endif
+
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <unistd.h>
 #endif
@@ -42,19 +46,16 @@
 
 int Usage(const char* argv0) {
   fprintf(stderr,
-          "Usage: %s MODE [OPTIONS] [input file] [output file]\n"
-          "modes:\n"
-          "  systrace|json|ctrace|text|profile|hprof|symbolize|deobfuscate\n"
-          "options:\n"
-          "  [--truncate start|end]\n"
-          "  [--full-sort]\n"
-          "\"profile\" mode options:\n"
-          "  [--perf] generate a perf profile instead of a heap profile\n"
-          "  [--no-annotations] do not suffix frame names with derived "
-          "annotations\n"
-          "  [--timestamps TIMESTAMP1,TIMESTAMP2,...] generate profiles "
-          "only for these *specific* timestamps\n"
-          "  [--pid PID] generate profiles only for this process id\n",
+          "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);
   return 1;
 }
@@ -75,11 +76,9 @@
   uint64_t pid = 0;
   std::vector<uint64_t> timestamps;
   bool full_sort = false;
-  bool perf_profile = false;
-  bool profile_no_annotations = false;
   for (int i = 1; i < argc; i++) {
     if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
-      printf("%s\n", base::GetVersionString());
+      printf("%s\n", PERFETTO_GET_GIT_REVISION());
       return 0;
     } else if (strcmp(argv[i], "-t") == 0 ||
                strcmp(argv[i], "--truncate") == 0) {
@@ -103,10 +102,6 @@
       for (const std::string& ts : ts_strings) {
         timestamps.emplace_back(StringToUint64OrDie(ts.c_str()));
       }
-    } else if (strcmp(argv[i], "--perf") == 0) {
-      perf_profile = true;
-    } else if (strcmp(argv[i], "--no-annotations") == 0) {
-      profile_no_annotations = true;
     } else if (strcmp(argv[i], "--full-sort") == 0) {
       full_sort = true;
     } else {
@@ -114,7 +109,7 @@
     }
   }
 
-  if (positional_args.empty())
+  if (positional_args.size() < 1)
     return Usage(argv[0]);
 
   std::istream* input_stream;
@@ -126,14 +121,12 @@
       PERFETTO_FATAL("Could not open %s", file_path);
     input_stream = &file_istream;
   } else {
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
     if (isatty(STDIN_FILENO)) {
       PERFETTO_ELOG("Reading from stdin but it's connected to a TTY");
       PERFETTO_LOG("It is unlikely that you want to type in some binary.");
       PERFETTO_LOG("Either pass a file path to the cmdline or pipe stdin");
       return Usage(argv[0]);
     }
-#endif
     input_stream = &std::cin;
   }
 
@@ -151,15 +144,9 @@
 
   std::string format(positional_args[0]);
 
-  if ((format != "profile" && format != "hprof") &&
-      (pid != 0 || !timestamps.empty())) {
+  if (format != "profile" && (pid != 0 || !timestamps.empty())) {
     PERFETTO_ELOG(
-        "--pid and --timestamps are supported only for profile "
-        "formats.");
-    return 1;
-  }
-  if (perf_profile && format != "profile") {
-    PERFETTO_ELOG("--perf requires profile format.");
+        "--pid and --timestamps are supported only for profile format.");
     return 1;
   }
 
@@ -190,16 +177,8 @@
   if (format == "text")
     return TraceToText(input_stream, output_stream);
 
-  if (format == "profile") {
-    return perf_profile
-               ? TraceToPerfProfile(input_stream, output_stream, pid,
-                                    timestamps, !profile_no_annotations)
-               : TraceToHeapProfile(input_stream, output_stream, pid,
-                                    timestamps, !profile_no_annotations);
-  }
-
-  if (format == "hprof")
-    return TraceToHprof(input_stream, output_stream, pid, timestamps);
+  if (format == "profile")
+    return TraceToProfile(input_stream, output_stream, pid, timestamps);
 
   if (format == "symbolize")
     return SymbolizeProfile(input_stream, output_stream);
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 588c438..54a1527 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -14,280 +14,160 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-
 #include "perfetto/profiling/pprof_builder.h"
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <cxxabi.h>
-#endif
-
 #include <inttypes.h>
 
 #include <algorithm>
 #include <map>
 #include <set>
-#include <unordered_map>
 #include <utility>
 #include <vector>
 
 #include "tools/trace_to_text/utils.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/hash.h"
+#include "perfetto/base/time.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/packed_repeated_fields.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/trace_processor/trace_processor.h"
+
 #include "src/profiling/symbolizer/symbolize_database.h"
 #include "src/profiling/symbolizer/symbolizer.h"
-#include "src/trace_processor/containers/string_pool.h"
 
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "protos/third_party/pprof/profile.pbzero.h"
 
-// Quick hint on navigating the file:
-// Conversions for both perf and heap profiles start with |TraceToPprof|.
-// Non-shared logic is in the |heap_profile| and |perf_profile| namespaces.
-//
-// To build one or more profiles, first the callstack information is queried
-// from the SQL tables, and converted into an in-memory representation by
-// |PreprocessLocations|. Then an instance of |GProfileBuilder| is used to
-// accumulate samples for that profile, and emit all additional information as a
-// serialized proto. Only the entities referenced by that particular
-// |GProfileBuilder| instance are emitted.
-//
-// See protos/third_party/pprof/profile.proto for the meaning of terms like
-// function/location/line.
-
-namespace {
-using StringId = ::perfetto::trace_processor::StringPool::Id;
-
-// In-memory representation of a Profile.Function.
-struct Function {
-  StringId name_id = StringId::Null();
-  StringId system_name_id = StringId::Null();
-  StringId filename_id = StringId::Null();
-
-  Function(StringId n, StringId s, StringId f)
-      : name_id(n), system_name_id(s), filename_id(f) {}
-
-  bool operator==(const Function& other) const {
-    return std::tie(name_id, system_name_id, filename_id) ==
-           std::tie(other.name_id, other.system_name_id, other.filename_id);
-  }
-};
-
-// In-memory representation of a Profile.Line.
-struct Line {
-  int64_t function_id = 0;  // LocationTracker's interned Function id
-  int64_t line_no = 0;
-
-  Line(int64_t func, int64_t line) : function_id(func), line_no(line) {}
-
-  bool operator==(const Line& other) const {
-    return function_id == other.function_id && line_no == other.line_no;
-  }
-};
-
-// In-memory representation of a Profile.Location.
-struct Location {
-  int64_t mapping_id = 0;  // sqlite row id
-  // Common case: location references a single function.
-  int64_t single_function_id = 0;  // interned Function id
-  // Alternatively: multiple inlined functions, recovered via offline
-  // symbolisation. Leaf-first ordering.
-  std::vector<Line> inlined_functions;
-
-  Location(int64_t map, int64_t func, std::vector<Line> inlines)
-      : mapping_id(map),
-        single_function_id(func),
-        inlined_functions(std::move(inlines)) {}
-
-  bool operator==(const Location& other) const {
-    return std::tie(mapping_id, single_function_id, inlined_functions) ==
-           std::tie(other.mapping_id, other.single_function_id,
-                    other.inlined_functions);
-  }
-};
-}  // namespace
-
-template <>
-struct std::hash<Function> {
-  size_t operator()(const Function& loc) const {
-    perfetto::base::Hash hasher;
-    hasher.Update(loc.name_id.raw_id());
-    hasher.Update(loc.system_name_id.raw_id());
-    hasher.Update(loc.filename_id.raw_id());
-    return static_cast<size_t>(hasher.digest());
-  }
-};
-
-template <>
-struct std::hash<Location> {
-  size_t operator()(const Location& loc) const {
-    perfetto::base::Hash hasher;
-    hasher.Update(loc.mapping_id);
-    hasher.Update(loc.single_function_id);
-    for (auto line : loc.inlined_functions) {
-      hasher.Update(line.function_id);
-      hasher.Update(line.line_no);
-    }
-    return static_cast<size_t>(hasher.digest());
-  }
-};
-
 namespace perfetto {
 namespace trace_to_text {
+
 namespace {
 
-using ::perfetto::trace_processor::Iterator;
+using ::protozero::proto_utils::kMessageLengthFieldSize;
+using ::protozero::proto_utils::MakeTagLengthDelimited;
+using ::protozero::proto_utils::WriteVarInt;
+
+struct View {
+  const char* type;
+  const char* unit;
+  const char* aggregator;
+  const char* filter;
+};
 
 void MaybeDemangle(std::string* name) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  char* data = nullptr;
-#else
   int ignored;
   char* data = abi::__cxa_demangle(name->c_str(), nullptr, nullptr, &ignored);
-#endif
   if (data) {
     *name = data;
     free(data);
   }
 }
 
-uint64_t ToPprofId(int64_t id) {
-  PERFETTO_DCHECK(id >= 0);
-  return static_cast<uint64_t>(id) + 1;
-}
+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};
 
-std::string AsCsvString(std::vector<uint64_t> vals) {
-  std::string ret;
-  for (size_t i = 0; i < vals.size(); i++) {
-    if (i != 0) {
-      ret += ",";
-    }
-    ret += std::to_string(vals[i]);
-  }
-  return ret;
-}
+const View kViews[] = {kAllocObjectsView, kObjectsView, kAllocSpaceView,
+                       kSpaceView};
 
-base::Optional<int64_t> GetStatsEntry(
-    trace_processor::TraceProcessor* tp,
-    const std::string& name,
-    base::Optional<uint64_t> idx = base::nullopt) {
-  std::string query = "select value from stats where name == '" + name + "'";
-  if (idx.has_value())
-    query += " and idx == " + std::to_string(idx.value());
+using Iterator = trace_processor::TraceProcessor::Iterator;
 
-  auto it = tp->ExecuteQuery(query);
+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 base::nullopt;
+      return -1;
     }
-    // some stats are not present unless non-zero
-    return base::make_optional(0);
+    // TODO(fmayer): Remove this case once we always get an entry in the stats
+    // table.
+    return 0;
   }
-  return base::make_optional(it.Get(0).AsLong());
+  return it.Get(0).AsLong();
 }
 
-// Interns Locations, Lines, and Functions. Interning is done by the entity's
-// contents, and has no relation to the row ids in the SQL tables.
-// Contains all data for the trace, so can be reused when emitting multiple
-// profiles.
-//
-// TODO(rsavitski): consider moving mappings into here as well. For now, they're
-// still emitted in a single scan during profile building. Mappings should be
-// unique-enough already in the SQL tables, with only incremental state clearing
-// duplicating entries.
-class LocationTracker {
- public:
-  int64_t InternLocation(Location loc) {
-    auto it = locations_.find(loc);
-    if (it == locations_.end()) {
-      bool inserted = false;
-      std::tie(it, inserted) = locations_.emplace(
-          std::move(loc), static_cast<int64_t>(locations_.size()));
-      PERFETTO_DCHECK(inserted);
-    }
-    return it->second;
+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);
   }
 
-  int64_t InternFunction(Function func) {
-    auto it = functions_.find(func);
-    if (it == functions_.end()) {
-      bool inserted = false;
-      std::tie(it, inserted) =
-          functions_.emplace(func, static_cast<int64_t>(functions_.size()));
-      PERFETTO_DCHECK(inserted);
-    }
-    return it->second;
+  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;
+}
 
-  bool IsCallsiteProcessed(int64_t callstack_id) const {
-    return callsite_to_locations_.find(callstack_id) !=
-           callsite_to_locations_.end();
-  }
-
-  void MaybeSetCallsiteLocations(int64_t callstack_id,
-                                 const std::vector<int64_t>& locs) {
-    // nop if already set
-    callsite_to_locations_.emplace(callstack_id, locs);
-  }
-
-  const std::vector<int64_t>& LocationsForCallstack(
-      int64_t callstack_id) const {
-    auto it = callsite_to_locations_.find(callstack_id);
-    PERFETTO_CHECK(callstack_id >= 0 && it != callsite_to_locations_.end());
-    return it->second;
-  }
-
-  const std::unordered_map<Location, int64_t>& AllLocations() const {
-    return locations_;
-  }
-  const std::unordered_map<Function, int64_t>& AllFunctions() const {
-    return functions_;
-  }
-
- private:
-  // Root-first location ids for a given callsite id.
-  std::unordered_map<int64_t, std::vector<int64_t>> callsite_to_locations_;
-  std::unordered_map<Location, int64_t> locations_;
-  std::unordered_map<Function, int64_t> functions_;
+struct Callsite {
+  int64_t id;
+  int64_t frame_id;
 };
 
-struct PreprocessedInline {
-  StringId system_name_id = StringId::Null();
-  StringId filename_id = StringId::Null();
-  int64_t line_no = 0;
+// 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).AsLong();
 
-  PreprocessedInline(StringId s, StringId f, int64_t line)
-      : system_name_id(s), filename_id(f), line_no(line) {}
-};
-
-std::unordered_map<int64_t, std::vector<PreprocessedInline>>
-PreprocessInliningInfo(trace_processor::TraceProcessor* tp,
-                       trace_processor::StringPool* interner) {
-  std::unordered_map<int64_t, std::vector<PreprocessedInline>> inlines;
-
-  // Most-inlined function (leaf) has the lowest id within a symbol set. Query
-  // such that the per-set line vectors are built up leaf-first.
   Iterator it = tp->ExecuteQuery(
-      "select symbol_set_id, name, source_file, line_number from "
-      "stack_profile_symbol order by symbol_set_id asc, id asc;");
+      "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 symbol_set_id = it.Get(0).AsLong();
-    auto func_sysname = it.Get(1).is_null() ? "" : it.Get(1).AsString();
-    auto filename = it.Get(2).is_null() ? "" : it.Get(2).AsString();
-    int64_t line_no = it.Get(3).AsLong();
+    int64_t id = it.Get(0).AsLong();
+    int64_t frame_id = it.Get(2).AsLong();
+    std::vector<int64_t>& path = result[static_cast<size_t>(id)];
+    path.push_back(frame_id);
 
-    inlines[symbol_set_id].emplace_back(interner->InternString(func_sysname),
-                                        interner->InternString(filename),
-                                        line_no);
+    auto parent_id_value = it.Get(1);
+    if (!parent_id_value.is_null()) {
+      const std::vector<int64_t>& parent_path =
+          result[static_cast<size_t>(parent_id_value.AsLong())];
+      path.insert(path.end(), parent_path.begin(), parent_path.end());
+    }
   }
 
   if (!it.Status().ok()) {
@@ -295,275 +175,121 @@
                             it.Status().message().c_str());
     return {};
   }
-  return inlines;
+  return result;
 }
 
-// Extracts and interns the unique frames and locations (as defined by the proto
-// format) from the callstack SQL tables.
-//
-// Approach:
-//   * for each callstack (callsite ids of the leaves):
-//     * use experimental_annotated_callstack to build the full list of
-//       constituent frames
-//     * for each frame (root to leaf):
-//         * intern the location and function(s)
-//         * remember the mapping from callsite_id to the callstack so far (from
-//            the root and including the frame being considered)
-//
-// Optionally mixes in the annotations as a frame name suffix (since there's no
-// good way to attach extra info to locations in the proto format). This relies
-// on the annotations (produced by experimental_annotated_callstack) to be
-// stable for a given callsite (equivalently: dependent only on their parents).
-LocationTracker PreprocessLocations(trace_processor::TraceProcessor* tp,
-                                    trace_processor::StringPool* interner,
-                                    bool annotate_frames) {
-  LocationTracker tracker;
+struct Line {
+  int64_t symbol_id;
+  uint32_t line_number;
+};
 
-  // Keyed by symbol_set_id, discarded once this function converts the inlines
-  // into Line and Function entries.
-  std::unordered_map<int64_t, std::vector<PreprocessedInline>> inlining_info =
-      PreprocessInliningInfo(tp, interner);
-
-  // Higher callsite ids most likely correspond to the deepest stacks, so we'll
-  // fill more of the overall callsite->location map by visiting the callsited
-  // in decreasing id order. Since processing a callstack also fills in the data
-  // for all parent callsites.
-  Iterator cid_it = tp->ExecuteQuery(
-      "select id from stack_profile_callsite order by id desc;");
-  while (cid_it.Next()) {
-    int64_t query_cid = cid_it.Get(0).AsLong();
-
-    // If the leaf has been processed, the rest of the stack is already known.
-    if (tracker.IsCallsiteProcessed(query_cid))
-      continue;
-
-    std::string annotated_query =
-        "select sp.id, sp.annotation, spf.mapping, "
-        "ifnull(spf.deobfuscated_name, spf.name), spf.symbol_set_id from "
-        "experimental_annotated_callstack(" +
-        std::to_string(query_cid) +
-        ") sp join stack_profile_frame spf on (sp.frame_id == spf.id) "
-        "order by depth asc";
-    Iterator c_it = tp->ExecuteQuery(annotated_query);
-
-    std::vector<int64_t> callstack_loc_ids;
-    while (c_it.Next()) {
-      int64_t cid = c_it.Get(0).AsLong();
-      int64_t mapping_id = c_it.Get(2).AsLong();
-      auto annotation = c_it.Get(1).is_null() ? "" : c_it.Get(1).AsString();
-      auto func_sysname = c_it.Get(3).is_null() ? "" : c_it.Get(3).AsString();
-      base::Optional<int64_t> symbol_set_id =
-          c_it.Get(4).is_null() ? base::nullopt
-                                : base::make_optional(c_it.Get(4).AsLong());
-
-      Location loc(mapping_id, /*single_function_id=*/-1, {});
-
-      auto intern_function = [interner, &tracker, annotate_frames](
-                                 StringId func_sysname_id, StringId filename_id,
-                                 const std::string& anno) {
-        std::string func_name = interner->Get(func_sysname_id).ToStdString();
-        MaybeDemangle(&func_name);
-        if (annotate_frames && !anno.empty() && !func_name.empty())
-          func_name = func_name + " [" + anno + "]";
-        StringId func_name_id =
-            interner->InternString(base::StringView(func_name));
-        Function func(func_name_id, func_sysname_id, filename_id);
-        return tracker.InternFunction(func);
-      };
-
-      // Inlining information available
-      if (symbol_set_id.has_value()) {
-        auto it = inlining_info.find(*symbol_set_id);
-        if (it == inlining_info.end()) {
-          PERFETTO_DFATAL_OR_ELOG(
-              "Failed to find stack_profile_symbol entry for symbol_set_id "
-              "%" PRIi64 "",
-              *symbol_set_id);
-          return {};
-        }
-
-        // N inlined functions
-        for (const auto& line : it->second) {
-          int64_t func_id = intern_function(line.system_name_id,
-                                            line.filename_id, annotation);
-
-          loc.inlined_functions.emplace_back(func_id, line.line_no);
-        }
-      } else {
-        // Otherwise - single function
-        int64_t func_id =
-            intern_function(interner->InternString(func_sysname),
-                            /*filename_id=*/StringId::Null(), annotation);
-        loc.single_function_id = func_id;
-      }
-
-      int64_t loc_id = tracker.InternLocation(std::move(loc));
-
-      // Update the tracker with the locations so far (for example, at depth 2,
-      // we'll have 3 root-most locations in |callstack_loc_ids|).
-      callstack_loc_ids.push_back(loc_id);
-      tracker.MaybeSetCallsiteLocations(cid, callstack_loc_ids);
-    }
-
-    if (!c_it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                              c_it.Status().message().c_str());
-      return {};
-    }
+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).AsLong();
+    int64_t id = it.Get(1).AsLong();
+    int64_t line_number = it.Get(2).AsLong();
+    result[symbol_set_id].emplace_back(
+        Line{id, static_cast<uint32_t>(line_number)});
   }
 
-  if (!cid_it.Status().ok()) {
+  if (!it.Status().ok()) {
     PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            cid_it.Status().message().c_str());
+                            it.Status().message().c_str());
     return {};
   }
-
-  return tracker;
+  return result;
 }
 
-// Builds the |perftools.profiles.Profile| proto.
 class GProfileBuilder {
  public:
-  GProfileBuilder(const LocationTracker& locations,
-                  trace_processor::StringPool* interner)
-      : locations_(locations), interner_(interner) {
-    // The pprof format requires the first entry in the string table to be the
+  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.
-    int64_t empty_id = ToStringTableId(StringId::Null());
+    int64_t empty_id = Intern("");
     PERFETTO_CHECK(empty_id == 0);
   }
 
-  void WriteSampleTypes(
-      const std::vector<std::pair<std::string, std::string>>& sample_types) {
-    for (const auto& st : sample_types) {
-      auto* sample_type = result_->add_sample_type();
-      sample_type->set_type(
-          ToStringTableId(interner_->InternString(base::StringView(st.first))));
-      sample_type->set_unit(ToStringTableId(
-          interner_->InternString(base::StringView(st.second))));
+  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 AddSample(const protozero::PackedVarInt& values, int64_t callstack_id) {
-    const auto& location_ids = locations_.LocationsForCallstack(callstack_id);
-    if (location_ids.empty()) {
-      PERFETTO_DFATAL_OR_ELOG(
-          "Failed to find frames for callstack id %" PRIi64 "", callstack_id);
-      return false;
-    }
-
-    // LocationTracker stores location lists root-first, but the pprof format
-    // requires leaf-first.
-    protozero::PackedVarInt packed_locs;
-    for (auto it = location_ids.rbegin(); it != location_ids.rend(); ++it)
-      packed_locs.Append(ToPprofId(*it));
-
-    auto* gsample = result_->add_sample();
-    gsample->set_value(values);
-    gsample->set_location_id(packed_locs);
-
-    // Remember the locations s.t. we only serialize the referenced ones.
-    seen_locations_.insert(location_ids.cbegin(), location_ids.cend());
-    return true;
-  }
-
-  std::string CompleteProfile(trace_processor::TraceProcessor* tp) {
-    std::set<int64_t> seen_mappings;
-    std::set<int64_t> seen_functions;
-
-    if (!WriteLocations(&seen_mappings, &seen_functions))
-      return {};
-    if (!WriteFunctions(seen_functions))
-      return {};
-    if (!WriteMappings(tp, seen_mappings))
-      return {};
-
-    WriteStringTable();
-    return result_.SerializeAsString();
-  }
-
- private:
-  // Serializes the Profile.Location entries referenced by this profile.
-  bool WriteLocations(std::set<int64_t>* seen_mappings,
-                      std::set<int64_t>* seen_functions) {
-    const std::unordered_map<Location, int64_t>& locations =
-        locations_.AllLocations();
-
-    size_t written_locations = 0;
-    for (const auto& loc_and_id : locations) {
-      const auto& loc = loc_and_id.first;
-      int64_t id = loc_and_id.second;
-
-      if (seen_locations_.find(id) == seen_locations_.end())
-        continue;
-
-      written_locations += 1;
-      seen_mappings->emplace(loc.mapping_id);
-
-      auto* glocation = result_->add_location();
-      glocation->set_id(ToPprofId(id));
-      glocation->set_mapping_id(ToPprofId(loc.mapping_id));
-
-      if (!loc.inlined_functions.empty()) {
-        for (const auto& line : loc.inlined_functions) {
-          seen_functions->insert(line.function_id);
-
-          auto* gline = glocation->add_line();
-          gline->set_function_id(ToPprofId(line.function_id));
-          gline->set_line(line.line_no);
+  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;
         }
-      } else {
-        seen_functions->insert(loc.single_function_id);
-
-        glocation->add_line()->set_function_id(
-            ToPprofId(loc.single_function_id));
+        all_next = all_next && next;
+        any_next = any_next || next;
       }
-    }
 
-    if (written_locations != seen_locations_.size()) {
-      PERFETTO_DFATAL_OR_ELOG(
-          "Found only %zu/%zu locations during serialization.",
-          written_locations, seen_locations_.size());
-      return false;
+      if (!all_next) {
+        PERFETTO_DCHECK(!any_next);
+        break;
+      }
+
+      auto* gsample = result_->add_sample();
+      protozero::PackedVarInt sample_values;
+      for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
+        int64_t callstack_id = (*view_its)[i].Get(0).AsLong();
+        if (i == 0) {
+          auto frames = FramesForCallstack(callstack_id);
+          if (frames.empty())
+            return false;
+          protozero::PackedVarInt location_ids;
+          for (int64_t frame : frames)
+            location_ids.Append(ToPprofId(frame));
+          gsample->set_location_id(location_ids);
+          seen_frames->insert(frames.cbegin(), frames.cend());
+        } else {
+          if (callstack_id != (*view_its)[i].Get(0).AsLong()) {
+            PERFETTO_DFATAL_OR_ELOG("Wrong callstack.");
+            return false;
+          }
+        }
+        sample_values.Append((*view_its)[i].Get(1).AsLong());
+      }
+      gsample->set_value(sample_values);
     }
     return true;
   }
 
-  // Serializes the Profile.Function entries referenced by this profile.
-  bool WriteFunctions(const std::set<int64_t>& seen_functions) {
-    const std::unordered_map<Function, int64_t>& functions =
-        locations_.AllFunctions();
-
-    size_t written_functions = 0;
-    for (const auto& func_and_id : functions) {
-      const auto& func = func_and_id.first;
-      int64_t id = func_and_id.second;
-
-      if (seen_functions.find(id) == seen_functions.end())
-        continue;
-
-      written_functions += 1;
-
-      auto* gfunction = result_->add_function();
-      gfunction->set_id(ToPprofId(id));
-      gfunction->set_name(ToStringTableId(func.name_id));
-      gfunction->set_system_name(ToStringTableId(func.system_name_id));
-      if (!func.filename_id.is_null())
-        gfunction->set_filename(ToStringTableId(func.filename_id));
-    }
-
-    if (written_functions != seen_functions.size()) {
-      PERFETTO_DFATAL_OR_ELOG(
-          "Found only %zu/%zu functions during serialization.",
-          written_functions, seen_functions.size());
-      return false;
-    }
-    return true;
-  }
-
-  // Serializes the Profile.Mapping entries referenced by this profile.
   bool WriteMappings(trace_processor::TraceProcessor* tp,
-                     const std::set<int64_t>& seen_mappings) {
+                     const std::set<int64_t> seen_mappings) {
     Iterator mapping_it = tp->ExecuteQuery(
         "SELECT id, exact_offset, start, end, name "
         "FROM stack_profile_mapping;");
@@ -573,8 +299,7 @@
       if (seen_mappings.find(id) == seen_mappings.end())
         continue;
       ++mappings_no;
-      auto interned_filename = ToStringTableId(
-          interner_->InternString(mapping_it.Get(4).AsString()));
+      auto interned_filename = Intern(mapping_it.Get(4).AsString());
       auto* gmapping = result_->add_mapping();
       gmapping->set_id(ToPprofId(id));
       // Do not set the build_id here to avoid downstream services
@@ -599,370 +324,275 @@
     return true;
   }
 
-  void WriteStringTable() {
-    for (StringId id : string_table_) {
-      trace_processor::NullTermStringView s = interner_->Get(id);
-      result_->add_string_table(s.data(), s.size());
+  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).AsLong();
+      if (seen_symbol_ids.find(id) == seen_symbol_ids.end())
+        continue;
+      ++symbols_no;
+      const std::string& name = symbol_it.Get(1).AsString();
+      std::string demangled_name = name;
+      MaybeDemangle(&demangled_name);
+
+      auto interned_demangled_name = Intern(demangled_name);
+      auto interned_system_name = Intern(name);
+      auto interned_filename = Intern(symbol_it.Get(2).AsString());
+      auto* gfunction = result_->add_function();
+      gfunction->set_id(ToPprofId(id));
+      gfunction->set_name(interned_demangled_name);
+      gfunction->set_system_name(interned_system_name);
+      gfunction->set_filename(interned_filename);
+    }
+
+    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).AsLong();
+      if (seen_frames.find(frame_id) == seen_frames.end())
+        continue;
+      frames_no++;
+      std::string frame_name = frame_it.Get(1).AsString();
+      int64_t mapping_id = frame_it.Get(2).AsLong();
+      int64_t rel_pc = frame_it.Get(3).AsLong();
+      base::Optional<int64_t> symbol_set_id;
+      if (!frame_it.Get(4).is_null())
+        symbol_set_id = frame_it.Get(4).AsLong();
+
+      seen_mappings->emplace(mapping_id);
+      auto* 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);
+          auto* 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);
+
+        auto* gline = glocation->add_line();
+        gline->set_line(0);
+        gline->set_function_id(ToPprofId(synthesized_symbol_id));
+
+        auto interned_demangled_name = Intern(demangled_name);
+        auto interned_system_name = Intern(frame_name);
+        auto* gfunction = result_->add_function();
+        gfunction->set_id(ToPprofId(synthesized_symbol_id));
+        gfunction->set_name(interned_demangled_name);
+        gfunction->set_system_name(interned_system_name);
+      }
+    }
+
+    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) {
+      Intern(kViews[i].type);
+      Intern(kViews[i].unit);
+    }
+
+    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));
     }
   }
 
-  int64_t ToStringTableId(StringId interned_id) {
-    auto it = interning_remapper_.find(interned_id);
-    if (it == interning_remapper_.end()) {
-      int64_t table_id = static_cast<int64_t>(string_table_.size());
-      string_table_.push_back(interned_id);
-      bool inserted = false;
-      std::tie(it, inserted) =
-          interning_remapper_.emplace(interned_id, table_id);
-      PERFETTO_DCHECK(inserted);
+  std::string 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 result_.SerializeAsString();
+  }
+
+  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;
   }
 
-  // Contains all locations, lines, functions (in memory):
-  const LocationTracker& locations_;
-
-  // String interner, strings referenced by LocationTracker are already
-  // interned. The new internings will come from mappings, and sample types.
-  trace_processor::StringPool* interner_;
-
-  // The profile format uses the repeated string_table field's index as an
-  // implicit id, so these structures remap the interned strings into sequential
-  // ids. Only the strings referenced by this GProfileBuilder instance will be
-  // added to the table.
-  std::unordered_map<StringId, int64_t> interning_remapper_;
-  std::vector<StringId> string_table_;
-
-  // Profile proto being serialized.
+ private:
   protozero::HeapBuffered<third_party::perftools::profiles::pbzero::Profile>
       result_;
-
-  // Set of locations referenced by the added samples.
-  std::set<int64_t> seen_locations_;
+  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 heap_profile {
-struct View {
-  const char* type;
-  const char* unit;
-  const char* aggregator;
-  const char* filter;
-};
-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};
+}  // namespace
 
-const View kViews[] = {kAllocObjectsView, kObjectsView, kAllocSpaceView,
-                       kSpaceView};
+bool TraceToPprof(std::istream* input,
+                  std::vector<SerializedProfile>* output,
+                  profiling::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);
 
-static bool VerifyPIDStats(trace_processor::TraceProcessor* tp, uint64_t pid) {
-  bool success = true;
-  base::Optional<int64_t> stat =
-      GetStatsEntry(tp, "heapprofd_buffer_corrupted", base::make_optional(pid));
-  if (!stat.has_value()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_buffer_corrupted stat");
-  } else if (stat.value() > 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 =
-      GetStatsEntry(tp, "heapprofd_buffer_overran", base::make_optional(pid));
-  if (!stat.has_value()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_buffer_overran stat");
-  } else if (stat.value() > 0) {
-    success = false;
-    PERFETTO_ELOG("WARNING: The profile for %" PRIu64
-                  " ended early due to a buffer overrun.",
-                  pid);
-  }
+  if (!ReadTrace(tp.get(), input))
+    return false;
 
-  stat = GetStatsEntry(tp, "heapprofd_rejected_concurrent", pid);
-  if (!stat.has_value()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_rejected_concurrent stat");
-  } else if (stat.value() > 0) {
-    success = false;
-    PERFETTO_ELOG("WARNING: The profile for %" PRIu64
-                  " was rejected due to a concurrent profile.",
-                  pid);
-  }
-  return success;
+  tp->NotifyEndOfFile();
+  return TraceToPprof(tp.get(), output, symbolizer, pid, timestamps);
 }
 
-static std::vector<Iterator> BuildViewIterators(
-    trace_processor::TraceProcessor* tp,
-    uint64_t upid,
-    uint64_t ts,
-    const char* heap_name) {
-  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) + " ";
-    query += "AND hpa.heap_name = '" + std::string(heap_name) + "' ";
-    if (v.filter)
-      query += "AND " + std::string(v.filter) + " ";
-    query += "GROUP BY hpa.callsite_id;";
-    view_its.emplace_back(tp->ExecuteQuery(query));
+bool TraceToPprof(trace_processor::TraceProcessor* tp,
+                  std::vector<SerializedProfile>* output,
+                  profiling::Symbolizer* symbolizer,
+                  uint64_t pid,
+                  const std::vector<uint64_t>& timestamps) {
+  if (symbolizer) {
+    profiling::SymbolizeDatabase(
+        tp, symbolizer, [tp](const std::string& trace_proto) {
+          std::unique_ptr<uint8_t[]> buf(new uint8_t[trace_proto.size()]);
+          memcpy(buf.get(), trace_proto.data(), trace_proto.size());
+          auto status = tp->Parse(std::move(buf), trace_proto.size());
+          if (!status.ok()) {
+            PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
+                                    status.message().c_str());
+            return;
+          }
+        });
   }
-  return view_its;
-}
 
-static bool WriteAllocations(GProfileBuilder* builder,
-                             std::vector<Iterator>* view_its) {
-  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_CHECK(!any_next);
-      break;
-    }
-
-    protozero::PackedVarInt sample_values;
-    int64_t callstack_id = -1;
-    for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-      if (i == 0) {
-        callstack_id = (*view_its)[i].Get(0).AsLong();
-      } else if (callstack_id != (*view_its)[i].Get(0).AsLong()) {
-        PERFETTO_DFATAL_OR_ELOG("Wrong callstack.");
-        return false;
-      }
-      sample_values.Append((*view_its)[i].Get(1).AsLong());
-    }
-
-    if (!builder->AddSample(sample_values, callstack_id))
-      return false;
+  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;
   }
-  return true;
-}
 
-static bool TraceToHeapPprof(trace_processor::TraceProcessor* tp,
-                             std::vector<SerializedProfile>* output,
-                             bool annotate_frames,
-                             uint64_t target_pid,
-                             const std::vector<uint64_t>& target_timestamps) {
-  trace_processor::StringPool interner;
-  LocationTracker locations =
-      PreprocessLocations(tp, &interner, annotate_frames);
+  int64_t max_symbol_id = max_symbol_id_it.Get(0).AsLong();
+  const auto callsite_to_frames = GetCallsiteToFrames(tp);
+  const auto symbol_set_id_to_lines = GetSymbolSetIdToLines(tp);
 
   bool any_fail = false;
-  Iterator it = tp->ExecuteQuery(
-      "select distinct hpa.upid, hpa.ts, p.pid, hpa.heap_name "
-      "from heap_profile_allocation hpa, "
-      "process p where p.upid = hpa.upid;");
+  Iterator it = tp->ExecuteQuery(kQueryProfiles);
   while (it.Next()) {
-    GProfileBuilder builder(locations, &interner);
+    GProfileBuilder builder(callsite_to_frames, symbol_set_id_to_lines,
+                            max_symbol_id);
     uint64_t upid = static_cast<uint64_t>(it.Get(0).AsLong());
     uint64_t ts = static_cast<uint64_t>(it.Get(1).AsLong());
     uint64_t profile_pid = static_cast<uint64_t>(it.Get(2).AsLong());
-    const char* heap_name = it.Get(3).AsString();
-    if ((target_pid > 0 && profile_pid != target_pid) ||
-        (!target_timestamps.empty() &&
-         std::find(target_timestamps.begin(), target_timestamps.end(), ts) ==
-             target_timestamps.end())) {
+    if ((pid > 0 && profile_pid != pid) ||
+        (!timestamps.empty() && std::find(timestamps.begin(), timestamps.end(),
+                                          ts) == timestamps.end())) {
       continue;
     }
 
-    if (!VerifyPIDStats(tp, profile_pid))
+    if (!VerifyPIDStats(tp, pid))
       any_fail = true;
 
-    std::vector<std::pair<std::string, std::string>> sample_types;
-    for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-      sample_types.emplace_back(std::string(kViews[i].type),
-                                std::string(kViews[i].unit));
-    }
-    builder.WriteSampleTypes(sample_types);
+    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());
 
-    std::vector<Iterator> view_its =
-        BuildViewIterators(tp, upid, ts, heap_name);
-    std::string profile_proto;
-    if (WriteAllocations(&builder, &view_its)) {
-      profile_proto = builder.CompleteProfile(tp);
-    }
-    output->emplace_back(
-        SerializedProfile{ProfileType::kHeapProfile, profile_pid,
-                          std::move(profile_proto), heap_name});
+    std::string profile_proto = builder.GenerateGProfile(tp, upid, ts);
+    output->emplace_back(SerializedProfile{
+        static_cast<uint64_t>(pid_it.Get(0).AsLong()), profile_proto});
   }
-
+  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;
   }
-  if (any_fail) {
-    PERFETTO_ELOG(
-        "One or more of your profiles had an issue. Please consult "
-        "https://perfetto.dev/docs/data-sources/"
-        "native-heap-profiler#troubleshooting");
-  }
   return true;
 }
-}  // namespace heap_profile
 
-namespace perf_profile {
-struct ProcessInfo {
-  uint64_t pid;
-  std::vector<uint64_t> utids;
-};
-
-// Returns a map of upid -> {pid, utids[]} for sampled processes.
-static std::map<uint64_t, ProcessInfo> GetProcessMap(
-    trace_processor::TraceProcessor* tp) {
-  Iterator it = tp->ExecuteQuery(
-      "select distinct process.upid, process.pid, thread.utid from perf_sample "
-      "join thread using (utid) join process using (upid) where callsite_id is "
-      "not null order by process.upid asc");
-  std::map<uint64_t, ProcessInfo> process_map;
-  while (it.Next()) {
-    uint64_t upid = static_cast<uint64_t>(it.Get(0).AsLong());
-    uint64_t pid = static_cast<uint64_t>(it.Get(1).AsLong());
-    uint64_t utid = static_cast<uint64_t>(it.Get(2).AsLong());
-    process_map[upid].pid = pid;
-    process_map[upid].utids.push_back(utid);
-  }
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-    return {};
-  }
-  return process_map;
-}
-
-static void LogTracePerfEventIssues(trace_processor::TraceProcessor* tp) {
-  base::Optional<int64_t> stat = GetStatsEntry(tp, "perf_samples_skipped");
-  if (!stat.has_value()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to look up perf_samples_skipped stat");
-  } else if (stat.value() > 0) {
-    PERFETTO_ELOG(
-        "Warning: the trace recorded %" PRIi64
-        " skipped samples, which otherwise matched the tracing config. This "
-        "would cause a process to be completely absent from the trace, but "
-        "does *not* imply data loss in any of the output profiles.",
-        stat.value());
-  }
-
-  stat = GetStatsEntry(tp, "perf_samples_skipped_dataloss");
-  if (!stat.has_value()) {
-    PERFETTO_DFATAL_OR_ELOG(
-        "Failed to look up perf_samples_skipped_dataloss stat");
-  } else if (stat.value() > 0) {
-    PERFETTO_ELOG("DATA LOSS: the trace recorded %" PRIi64
-                  " lost perf samples (within traced_perf). This means that "
-                  "the trace is missing information, but it is not known "
-                  "which profile that affected.",
-                  stat.value());
-  }
-
-  // Check if any per-cpu ringbuffers encountered dataloss (as recorded by the
-  // kernel).
-  Iterator it = tp->ExecuteQuery(
-      "select idx, value from stats where name == 'perf_cpu_lost_records' and "
-      "value > 0 order by idx asc");
-  while (it.Next()) {
-    PERFETTO_ELOG(
-        "DATA LOSS: during the trace, the per-cpu kernel ring buffer for cpu "
-        "%" PRIi64 " recorded %" PRIi64
-        " lost samples. This means that the trace is missing information, "
-        "but it is not known which profile that affected.",
-        static_cast<int64_t>(it.Get(0).AsLong()),
-        static_cast<int64_t>(it.Get(1).AsLong()));
-  }
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-  }
-}
-
-// TODO(rsavitski): decide whether errors in |AddSample| should result in an
-// empty profile (and/or whether they should make the overall conversion
-// unsuccessful). Furthermore, clarify the return value's semantics for both
-// perf and heap profiles.
-static bool TraceToPerfPprof(trace_processor::TraceProcessor* tp,
-                             std::vector<SerializedProfile>* output,
-                             bool annotate_frames,
-                             uint64_t target_pid) {
-  trace_processor::StringPool interner;
-  LocationTracker locations =
-      PreprocessLocations(tp, &interner, annotate_frames);
-
-  LogTracePerfEventIssues(tp);
-
-  // Aggregate samples by upid when building profiles.
-  std::map<uint64_t, ProcessInfo> process_map = GetProcessMap(tp);
-  for (const auto& p : process_map) {
-    const ProcessInfo& process = p.second;
-
-    if (target_pid != 0 && process.pid != target_pid)
-      continue;
-
-    GProfileBuilder builder(locations, &interner);
-    builder.WriteSampleTypes({{"samples", "count"}});
-
-    std::string query = "select callsite_id from perf_sample where utid in (" +
-                        AsCsvString(process.utids) +
-                        ") and callsite_id is not null order by ts asc;";
-
-    protozero::PackedVarInt single_count_value;
-    single_count_value.Append(1);
-
-    Iterator it = tp->ExecuteQuery(query);
-    while (it.Next()) {
-      int64_t callsite_id = static_cast<int64_t>(it.Get(0).AsLong());
-      builder.AddSample(single_count_value, callsite_id);
-    }
-    if (!it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Failed to iterate over samples: %s",
-                              it.Status().c_message());
-      return false;
-    }
-
-    std::string profile_proto = builder.CompleteProfile(tp);
-    output->emplace_back(SerializedProfile{
-        ProfileType::kPerfProfile, process.pid, std::move(profile_proto), ""});
-  }
-  return true;
-}
-}  // namespace perf_profile
-}  // namespace
-
-bool TraceToPprof(trace_processor::TraceProcessor* tp,
+bool TraceToPprof(std::istream* input,
                   std::vector<SerializedProfile>* output,
-                  ConversionMode mode,
-                  uint64_t flags,
                   uint64_t pid,
                   const std::vector<uint64_t>& timestamps) {
-  bool annotate_frames =
-      flags & static_cast<uint64_t>(ConversionFlags::kAnnotateFrames);
-  switch (mode) {
-    case (ConversionMode::kHeapProfile):
-      return heap_profile::TraceToHeapPprof(tp, output, annotate_frames, pid,
-                                            timestamps);
-    case (ConversionMode::kPerfProfile):
-      return perf_profile::TraceToPerfPprof(tp, output, annotate_frames, pid);
-  }
-  PERFETTO_FATAL("unknown conversion option");  // for gcc
+  return TraceToPprof(input, output, nullptr, pid, timestamps);
 }
 
 }  // namespace trace_to_text
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index 4f97f58..acf25f0 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -23,7 +23,10 @@
 
 #include "src/profiling/symbolizer/symbolize_database.h"
 #include "src/profiling/symbolizer/symbolizer.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
 #include "src/profiling/symbolizer/local_symbolizer.h"
+#endif
 
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -35,9 +38,15 @@
 // 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<profiling::Symbolizer> symbolizer =
-      profiling::LocalSymbolizerOrDie(profiling::GetPerfettoBinaryPath(),
-                                      getenv("PERFETTO_SYMBOLIZER_MODE"));
+  std::unique_ptr<profiling::Symbolizer> symbolizer;
+  auto binary_path = profiling::GetPerfettoBinaryPath();
+  if (!binary_path.empty()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+    symbolizer.reset(new profiling::LocalSymbolizer(std::move(binary_path)));
+#else
+    PERFETTO_FATAL("This build does not support local symbolization.");
+#endif
+  }
 
   if (!symbolizer)
     PERFETTO_FATAL("No symbolizer selected");
diff --git a/tools/trace_to_text/trace_to_hprof.cc b/tools/trace_to_text/trace_to_hprof.cc
deleted file mode 100644
index 20e0573..0000000
--- a/tools/trace_to_text/trace_to_hprof.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "tools/trace_to_text/trace_to_hprof.h"
-
-#include <algorithm>
-#include <limits>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/endian.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "tools/trace_to_text/utils.h"
-
-// Spec
-// http://hg.openjdk.java.net/jdk6/jdk6/jdk/raw-file/tip/src/share/demo/jvmti/hprof/manual.html#Basic_Type
-// Parser
-// https://cs.android.com/android/platform/superproject/+/master:art/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
-
-namespace perfetto {
-namespace trace_to_text {
-
-namespace {
-constexpr char kHeader[] = "PERFETTO_JAVA_HEAP";
-constexpr uint32_t kIdSz = 8;
-constexpr uint32_t kStackTraceSerialNumber = 1;
-
-class BigEndianBuffer {
- public:
-  void WriteId(uint64_t val) { WriteU8(val); }
-
-  void WriteU8(uint64_t val) {
-    val = base::HostToBE64(val);
-    Write(reinterpret_cast<char*>(&val), sizeof(uint64_t));
-  }
-
-  void WriteU4(uint32_t val) {
-    val = base::HostToBE32(val);
-    Write(reinterpret_cast<char*>(&val), sizeof(uint32_t));
-  }
-
-  void SetU4(uint32_t val, size_t pos) {
-    val = base::HostToBE32(val);
-    PERFETTO_CHECK(pos + 4 <= buf_.size());
-    memcpy(buf_.data() + pos, &val, sizeof(uint32_t));
-  }
-
-  // Uncomment when needed
-  // void WriteU2(uint16_t val) {
-  //   val = base::HostToBE16(val);
-  //   Write(reinterpret_cast<char*>(&val), sizeof(uint16_t));
-  // }
-
-  void WriteByte(uint8_t val) { buf_.emplace_back(val); }
-
-  void Write(const char* val, uint32_t sz) {
-    const char* end = val + sz;
-    while (val < end) {
-      WriteByte(static_cast<uint8_t>(*val));
-      val++;
-    }
-  }
-
-  size_t written() const { return buf_.size(); }
-
-  void Flush(std::ostream* out) const {
-    out->write(buf_.data(), static_cast<std::streamsize>(buf_.size()));
-  }
-
- private:
-  std::vector<char> buf_;
-};
-
-class HprofWriter {
- public:
-  HprofWriter(std::ostream* output) : output_(output) {}
-
-  void WriteBuffer(const BigEndianBuffer& buf) { buf.Flush(output_); }
-
-  void WriteRecord(const uint8_t type,
-                   const std::function<void(BigEndianBuffer*)>&& writer) {
-    BigEndianBuffer buf;
-    buf.WriteByte(type);
-    // ts offset
-    buf.WriteU4(0);
-    // size placeholder
-    buf.WriteU4(0);
-    writer(&buf);
-    uint32_t record_sz = static_cast<uint32_t>(buf.written() - 9);
-    buf.SetU4(record_sz, 5);
-    WriteBuffer(buf);
-  }
-
- private:
-  std::ostream* output_;
-};
-
-// A Class from the heap dump.
-class ClassData {
- public:
-  explicit ClassData(uint64_t class_name_string_id)
-      : class_name_string_id_(class_name_string_id) {}
-
-  // Writes a HPROF LOAD_CLASS record for this Class
-  void WriteHprofLoadClass(HprofWriter* writer,
-                           uint64_t class_object_id,
-                           uint32_t class_serial_number) const {
-    writer->WriteRecord(0x02, [class_object_id, class_serial_number,
-                               this](BigEndianBuffer* buf) {
-      buf->WriteU4(class_serial_number);
-      buf->WriteId(class_object_id);
-      buf->WriteU4(kStackTraceSerialNumber);
-      buf->WriteId(class_name_string_id_);
-    });
-  }
-
- private:
-  uint64_t class_name_string_id_;
-};
-
-// Ingested data from a Java Heap Profile for a name, location pair.
-// We need to support multiple class datas per pair as name, location is
-// not unique. Classloader should guarantee uniqueness but is not available
-// until S.
-class RawClassData {
- public:
-  void AddClass(uint64_t id, base::Optional<uint64_t> superclass_id) {
-    ids_.push_back(std::make_pair(id, superclass_id));
-  }
-
-  void AddTemplate(uint64_t template_id) {
-    template_ids_.push_back(template_id);
-  }
-
-  // Transforms the raw data into one or more ClassData and adds them to the
-  // parameter map.
-  void ToClassData(std::unordered_map<uint64_t, ClassData>* id_to_class,
-                   uint64_t class_name_string_id) const {
-    // TODO(dinoderek) assert the two vectors have same length, iterate on both
-    for (auto it_ids = ids_.begin(); it_ids != ids_.end(); ++it_ids) {
-      // TODO(dinoderek) more data will be needed to write CLASS_DUMP
-      id_to_class->emplace(it_ids->first, ClassData(class_name_string_id));
-    }
-  }
-
- private:
-  // Pair contains class ID and super class ID.
-  std::vector<std::pair<uint64_t, base::Optional<uint64_t>>> ids_;
-  // Class id of the template
-  std::vector<uint64_t> template_ids_;
-};
-
-// The Heap Dump data
-class HeapDump {
- public:
-  explicit HeapDump(trace_processor::TraceProcessor* tp) : tp_(tp) {}
-
-  void Ingest() { IngestClasses(); }
-
-  void Write(HprofWriter* writer) {
-    WriteStrings(writer);
-    WriteLoadClass(writer);
-  }
-
- private:
-  trace_processor::TraceProcessor* tp_;
-
-  // String IDs start from 1 as 0 appears to be reserved.
-  uint64_t next_string_id_ = 1;
-  // Strings to corresponding String ID
-  std::unordered_map<std::string, uint64_t> string_to_id_;
-  // Type ID to corresponding Class
-  std::unordered_map<uint64_t, ClassData> id_to_class_;
-
-  // Ingests and processes the class data from the heap dump.
-  void IngestClasses() {
-    // TODO(dinoderek): heap_graph_class does not support pid or ts filtering
-
-    std::map<std::pair<uint64_t, std::string>, RawClassData> raw_classes;
-
-    auto it = tp_->ExecuteQuery(R"(SELECT
-          id,
-          IFNULL(deobfuscated_name, name),
-          superclass_id,
-          location
-        FROM heap_graph_class )");
-
-    while (it.Next()) {
-      uint64_t id = static_cast<uint64_t>(it.Get(0).AsLong());
-
-      std::string raw_dname(it.Get(1).AsString());
-      std::string dname;
-      bool is_template_class =
-          base::StartsWith(raw_dname, std::string("java.lang.Class<"));
-      if (is_template_class) {
-        dname = raw_dname.substr(17, raw_dname.size() - 18);
-      } else {
-        dname = raw_dname;
-      }
-      uint64_t name_id = IngestString(dname);
-
-      auto raw_super_id = it.Get(2);
-      base::Optional<uint64_t> maybe_super_id =
-          raw_super_id.is_null()
-              ? base::nullopt
-              : base::Optional<uint64_t>(
-                    static_cast<uint64_t>(raw_super_id.AsLong()));
-
-      std::string location(it.Get(3).AsString());
-
-      auto raw_classes_it =
-          raw_classes.emplace(std::make_pair(name_id, location), RawClassData())
-              .first;
-      if (is_template_class) {
-        raw_classes_it->second.AddTemplate(id);
-      } else {
-        raw_classes_it->second.AddClass(id, maybe_super_id);
-      }
-    }
-
-    for (const auto& raw : raw_classes) {
-      auto class_name_string_id = raw.first.first;
-      raw.second.ToClassData(&id_to_class_, class_name_string_id);
-    }
-  }
-
-  // Ingests the parameter string and returns the HPROF ID for the string.
-  uint64_t IngestString(const std::string& s) {
-    auto maybe_id = string_to_id_.find(s);
-    if (maybe_id != string_to_id_.end()) {
-      return maybe_id->second;
-    } else {
-      auto id = next_string_id_;
-      next_string_id_ += 1;
-      string_to_id_[s] = id;
-      return id;
-    }
-  }
-
-  // Writes STRING sections to the output
-  void WriteStrings(HprofWriter* writer) {
-    for (const auto& it : string_to_id_) {
-      writer->WriteRecord(0x01, [it](BigEndianBuffer* buf) {
-        buf->WriteId(it.second);
-        // TODO(dinoderek): UTF-8 encoding
-        buf->Write(it.first.c_str(), static_cast<uint32_t>(it.first.length()));
-      });
-    }
-  }
-
-  // Writes LOAD CLASS sections to the output
-  void WriteLoadClass(HprofWriter* writer) {
-    uint32_t class_serial_number = 1;
-    for (const auto& it : id_to_class_) {
-      it.second.WriteHprofLoadClass(writer, it.first, class_serial_number);
-      class_serial_number += 1;
-    }
-  }
-};
-
-void WriteHeaderAndStack(HprofWriter* writer) {
-  BigEndianBuffer header;
-  header.Write(kHeader, sizeof(kHeader));
-  // Identifier size
-  header.WriteU4(kIdSz);
-  // walltime high (unused)
-  header.WriteU4(0);
-  // walltime low (unused)
-  header.WriteU4(0);
-  writer->WriteBuffer(header);
-
-  // Add placeholder stack trace (required by the format).
-  writer->WriteRecord(0x05, [](BigEndianBuffer* buf) {
-    buf->WriteU4(kStackTraceSerialNumber);
-    buf->WriteU4(0);
-    buf->WriteU4(0);
-  });
-}
-}  // namespace
-
-int TraceToHprof(trace_processor::TraceProcessor* tp,
-                 std::ostream* output,
-                 uint64_t pid,
-                 uint64_t ts) {
-  PERFETTO_DCHECK(tp != nullptr && pid != 0 && ts != 0);
-
-  HprofWriter writer(output);
-  HeapDump dump(tp);
-
-  dump.Ingest();
-  WriteHeaderAndStack(&writer);
-  dump.Write(&writer);
-
-  return 0;
-}
-
-int TraceToHprof(std::istream* input,
-                 std::ostream* output,
-                 uint64_t pid,
-                 std::vector<uint64_t> timestamps) {
-  // TODO: Simplify this for cmdline users. For example, if there is a single
-  // heap graph, use this, and only fail when there is ambiguity.
-  if (pid == 0) {
-    PERFETTO_ELOG("Must specify pid");
-    return -1;
-  }
-  if (timestamps.size() != 1) {
-    PERFETTO_ELOG("Must specify single timestamp");
-    return -1;
-  }
-  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 TraceToHprof(tp.get(), output, pid, timestamps[0]);
-}
-
-}  // namespace trace_to_text
-}  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_hprof.h b/tools/trace_to_text/trace_to_hprof.h
deleted file mode 100644
index acc142a..0000000
--- a/tools/trace_to_text/trace_to_hprof.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef TOOLS_TRACE_TO_TEXT_TRACE_TO_HPROF_H_
-#define TOOLS_TRACE_TO_TEXT_TRACE_TO_HPROF_H_
-
-#include <iostream>
-#include <vector>
-#include "perfetto/trace_processor/trace_processor.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-int TraceToHprof(trace_processor::TraceProcessor* tp,
-                 std::ostream* output,
-                 uint64_t pid,
-                 uint64_t timestamp);
-
-int TraceToHprof(std::istream* input,
-                 std::ostream* output,
-                 uint64_t pid = 0,
-                 std::vector<uint64_t> timestamps = {});
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // TOOLS_TRACE_TO_TEXT_TRACE_TO_HPROF_H_
diff --git a/tools/trace_to_text/trace_to_json.cc b/tools/trace_to_text/trace_to_json.cc
index ea9516b..7f4ba66 100644
--- a/tools/trace_to_text/trace_to_json.cc
+++ b/tools/trace_to_text/trace_to_json.cc
@@ -85,9 +85,7 @@
       compress ? new DeflateTraceWriter(output) : new TraceWriter(output));
 
   trace_processor::Config config;
-  config.sorting_mode = full_sort
-                            ? trace_processor::SortingMode::kForceFullSort
-                            : trace_processor::SortingMode::kDefaultHeuristics;
+  config.force_full_sort = full_sort;
   std::unique_ptr<trace_processor::TraceProcessor> tp =
       trace_processor::TraceProcessor::CreateInstance(config);
 
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index c71a827..1d3846c 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -16,17 +16,18 @@
 
 #include "tools/trace_to_text/trace_to_profile.h"
 
-#include <random>
 #include <string>
 #include <vector>
 
-#include "perfetto/trace_processor/trace_processor.h"
-#include "src/profiling/symbolizer/local_symbolizer.h"
+#include "perfetto/base/build_config.h"
+
 #include "src/profiling/symbolizer/symbolize_database.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+#include "src/profiling/symbolizer/local_symbolizer.h"
+#endif
 #include "tools/trace_to_text/utils.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/base/utils.h"
@@ -34,96 +35,49 @@
 #include "src/profiling/symbolizer/symbolizer.h"
 
 namespace {
+
 constexpr const char* kDefaultTmp = "/tmp";
 
 std::string GetTemp() {
-  const char* tmp = nullptr;
-  if ((tmp = getenv("TMPDIR")))
-    return tmp;
-  if ((tmp = getenv("TEMP")))
-    return tmp;
-  return kDefaultTmp;
+  const char* tmp = getenv("TMPDIR");
+  if (tmp == nullptr)
+    tmp = kDefaultTmp;
+  return tmp;
 }
+
 }  // namespace
 
 namespace perfetto {
 namespace trace_to_text {
-namespace {
 
-uint64_t ToConversionFlags(bool annotate_frames) {
-  return static_cast<uint64_t>(annotate_frames
-                                   ? ConversionFlags::kAnnotateFrames
-                                   : ConversionFlags::kNone);
-}
-
-std::string GetRandomString(size_t n) {
-  std::random_device r;
-  auto rng = std::default_random_engine(r());
-  std::uniform_int_distribution<char> dist('a', 'z');
-  std::string result(n, ' ');
-  for (size_t i = 0; i < n; ++i) {
-    result[i] = dist(rng);
+int TraceToProfile(std::istream* input,
+                   std::ostream* output,
+                   uint64_t pid,
+                   std::vector<uint64_t> timestamps) {
+  std::unique_ptr<profiling::Symbolizer> symbolizer;
+  auto binary_path = profiling::GetPerfettoBinaryPath();
+  if (!binary_path.empty()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+    symbolizer.reset(new profiling::LocalSymbolizer(std::move(binary_path)));
+#else
+    PERFETTO_ELOG(
+        "This build does not support local symbolization. "
+        "Continuing without symbolization.");
+#endif
   }
-  return result;
-}
 
-void MaybeSymbolize(trace_processor::TraceProcessor* tp) {
-  std::unique_ptr<profiling::Symbolizer> symbolizer =
-      profiling::LocalSymbolizerOrDie(profiling::GetPerfettoBinaryPath(),
-                                      getenv("PERFETTO_SYMBOLIZER_MODE"));
-  if (!symbolizer)
-    return;
-  profiling::SymbolizeDatabase(tp, symbolizer.get(),
-                               [tp](const std::string& trace_proto) {
-                                 IngestTraceOrDie(tp, trace_proto);
-                               });
-  tp->NotifyEndOfFile();
-}
-
-void MaybeDeobfuscate(trace_processor::TraceProcessor* tp) {
-  auto maybe_map = profiling::GetPerfettoProguardMapPath();
-  if (maybe_map.empty()) {
-    return;
-  }
-  profiling::ReadProguardMapsToDeobfuscationPackets(
-      maybe_map, [tp](const std::string& trace_proto) {
-        IngestTraceOrDie(tp, trace_proto);
-      });
-  tp->NotifyEndOfFile();
-}
-
-int TraceToProfile(
-    std::istream* input,
-    std::ostream* output,
-    uint64_t pid,
-    std::vector<uint64_t> timestamps,
-    ConversionMode conversion_mode,
-    uint64_t conversion_flags,
-    std::string dirname_prefix,
-    std::function<std::string(const SerializedProfile&)> filename_fn) {
   std::vector<SerializedProfile> profiles;
-  trace_processor::Config config;
-  std::unique_ptr<trace_processor::TraceProcessor> tp =
-      trace_processor::TraceProcessor::CreateInstance(config);
-
-  if (!ReadTrace(tp.get(), input))
-    return -1;
-
-  tp->NotifyEndOfFile();
-  MaybeSymbolize(tp.get());
-  MaybeDeobfuscate(tp.get());
-
-  TraceToPprof(tp.get(), &profiles, conversion_mode, conversion_flags, pid,
-               timestamps);
+  TraceToPprof(input, &profiles, symbolizer.get(), pid, timestamps);
   if (profiles.empty()) {
     return 0;
   }
 
-  std::string temp_dir = GetTemp() + "/" + dirname_prefix +
-                         base::GetTimeFmt("%y%m%d%H%M%S") + GetRandomString(5);
-  PERFETTO_CHECK(base::Mkdir(temp_dir));
+  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 + "/" + filename_fn(profile);
+    std::string filename = temp_dir + "/heap_dump." + std::to_string(++itr) +
+                           "." + std::to_string(profile.pid) + ".pb";
     base::ScopedFile fd(base::OpenFile(filename, O_CREAT | O_WRONLY, 0700));
     if (!fd)
       PERFETTO_FATAL("Failed to open %s", filename.c_str());
@@ -135,39 +89,5 @@
   return 0;
 }
 
-}  // namespace
-
-int TraceToHeapProfile(std::istream* input,
-                       std::ostream* output,
-                       uint64_t pid,
-                       std::vector<uint64_t> timestamps,
-                       bool annotate_frames) {
-  int file_idx = 0;
-  auto filename_fn = [&file_idx](const SerializedProfile& profile) {
-    return "heap_dump." + std::to_string(++file_idx) + "." +
-           std::to_string(profile.pid) + "." + profile.heap_name + ".pb";
-  };
-
-  return TraceToProfile(
-      input, output, pid, timestamps, ConversionMode::kHeapProfile,
-      ToConversionFlags(annotate_frames), "heap_profile-", filename_fn);
-}
-
-int TraceToPerfProfile(std::istream* input,
-                       std::ostream* output,
-                       uint64_t pid,
-                       std::vector<uint64_t> timestamps,
-                       bool annotate_frames) {
-  int file_idx = 0;
-  auto filename_fn = [&file_idx](const SerializedProfile& profile) {
-    return "profile." + std::to_string(++file_idx) + ".pid." +
-           std::to_string(profile.pid) + ".pb";
-  };
-
-  return TraceToProfile(
-      input, output, pid, timestamps, ConversionMode::kPerfProfile,
-      ToConversionFlags(annotate_frames), "perf_profile-", filename_fn);
-}
-
 }  // namespace trace_to_text
 }  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_profile.h b/tools/trace_to_text/trace_to_profile.h
index 313b32b..629d3ef 100644
--- a/tools/trace_to_text/trace_to_profile.h
+++ b/tools/trace_to_text/trace_to_profile.h
@@ -23,19 +23,10 @@
 namespace perfetto {
 namespace trace_to_text {
 
-// 0: success
-int TraceToHeapProfile(std::istream* input,
-                       std::ostream* output,
-                       uint64_t pid,
-                       std::vector<uint64_t> timestamps,
-                       bool annotate_frames);
-
-// 0: success
-int TraceToPerfProfile(std::istream* input,
-                       std::ostream* output,
-                       uint64_t pid,
-                       std::vector<uint64_t> timestamps,
-                       bool annotate_frames);
+int TraceToProfile(std::istream* input,
+                   std::ostream* output,
+                   uint64_t pid = 0,
+                   std::vector<uint64_t> timestamps = {});
 
 }  // 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 498b6c9..e5900c8 100644
--- a/tools/trace_to_text/trace_to_systrace.cc
+++ b/tools/trace_to_text/trace_to_systrace.cc
@@ -171,9 +171,7 @@
       ctrace ? new DeflateTraceWriter(output) : new TraceWriter(output));
 
   trace_processor::Config config;
-  config.sorting_mode = full_sort
-                            ? trace_processor::SortingMode::kForceFullSort
-                            : trace_processor::SortingMode::kDefaultHeuristics;
+  config.force_full_sort = full_sort;
   std::unique_ptr<trace_processor::TraceProcessor> tp =
       trace_processor::TraceProcessor::CreateInstance(config);
 
@@ -192,7 +190,7 @@
                     TraceWriter* trace_writer,
                     bool wrapped_in_json,
                     Keep truncate_keep) {
-  using trace_processor::Iterator;
+  using Iterator = trace_processor::TraceProcessor::Iterator;
 
   QueryWriter q_writer(tp, trace_writer);
   if (wrapped_in_json) {
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 2fef5a5..1616a2d 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -22,7 +22,6 @@
 #include <google/protobuf/text_format.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "tools/trace_to_text/proto_full_utils.h"
 #include "tools/trace_to_text/utils.h"
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index ff1ae61..64a4aee 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -25,14 +25,9 @@
 #include <utility>
 
 #include "perfetto/base/logging.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/protozero/scattered_heap_buffer.h"
 #include "perfetto/trace_processor/trace_processor.h"
 
-#include "protos/perfetto/trace/profiling/deobfuscation.pbzero.h"
 #include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
@@ -42,12 +37,57 @@
 namespace trace_to_text {
 namespace {
 
+using Iterator = trace_processor::TraceProcessor::Iterator;
+
 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
 constexpr size_t kCompressionBufferSize = 500 * 1024;
 #endif
 
+std::map<std::string, std::set<std::string>> GetHeapGraphClasses(
+    trace_processor::TraceProcessor* tp) {
+  std::map<std::string, std::set<std::string>> res;
+  Iterator it = tp->ExecuteQuery("select type_name from heap_graph_object");
+  while (it.Next())
+    res.emplace(it.Get(0).string_value, std::set<std::string>());
+
+  PERFETTO_CHECK(it.Status().ok());
+
+  it = tp->ExecuteQuery("select field_name from heap_graph_reference");
+  while (it.Next()) {
+    std::string field_name = it.Get(0).string_value;
+    if (field_name.size() == 0)
+      continue;
+    size_t n = field_name.rfind(".");
+    if (n == std::string::npos || n == field_name.size() - 1) {
+      PERFETTO_ELOG("Invalid field name: %s", field_name.c_str());
+      continue;
+    }
+    std::string class_name = field_name;
+    class_name.resize(n);
+    field_name = field_name.substr(n + 1);
+    res[class_name].emplace(field_name);
+  }
+
+  PERFETTO_CHECK(it.Status().ok());
+  return res;
+}
+
+using ::protozero::proto_utils::kMessageLengthFieldSize;
+using ::protozero::proto_utils::MakeTagLengthDelimited;
+using ::protozero::proto_utils::WriteVarInt;
+
 }  // namespace
 
+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;
+}
+
 void ForEachPacketBlobInTrace(
     std::istream* input,
     const std::function<void(std::unique_ptr<char[]>, size_t)>& f) {
@@ -93,6 +133,13 @@
   }
 }
 
+base::Optional<std::string> GetPerfettoProguardMapPath() {
+  base::Optional<std::string> proguard_map;
+  const char* env = getenv("PERFETTO_PROGUARD_MAP");
+  if (env != nullptr)
+    proguard_map = env;
+  return proguard_map;
+}
 
 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.
@@ -109,8 +156,8 @@
 
   for (int i = 0;; i++) {
     if (i % kStderrRate == 0) {
-      fprintf(stderr, "Loading trace %.2f MB%c",
-              static_cast<double>(file_size) / 1.0e6, kProgressChar);
+      fprintf(stderr, "Loading trace %.2f MB%c", file_size / 1.0e6,
+              kProgressChar);
       fflush(stderr);
     }
 
@@ -133,21 +180,51 @@
   return true;
 }
 
-void IngestTraceOrDie(trace_processor::TraceProcessor* tp,
-                      const std::string& trace_proto) {
-  std::unique_ptr<uint8_t[]> buf(new uint8_t[trace_proto.size()]);
-  memcpy(buf.get(), trace_proto.data(), trace_proto.size());
-  auto status = tp->Parse(std::move(buf), trace_proto.size());
-  if (!status.ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s", status.message().c_str());
+void DeobfuscateDatabase(
+    trace_processor::TraceProcessor* tp,
+    const std::map<std::string, profiling::ObfuscatedClass>& mapping,
+    std::function<void(const std::string&)> callback) {
+  std::map<std::string, std::set<std::string>> classes =
+      GetHeapGraphClasses(tp);
+  protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet;
+  // TODO(fmayer): Add handling for package name and version code here so we
+  // can support multiple dumps in the same trace.
+  auto* proto_mapping = packet->set_deobfuscation_mapping();
+  for (const auto& p : classes) {
+    std::string obfuscated_class_name = p.first;
+    while (obfuscated_class_name.size() > 2 &&
+           obfuscated_class_name.substr(obfuscated_class_name.size() - 2) ==
+               "[]") {
+      obfuscated_class_name.resize(obfuscated_class_name.size() - 2);
+    }
+    const std::set<std::string>& obfuscated_field_names = p.second;
+    auto it = mapping.find(obfuscated_class_name);
+    if (it == mapping.end()) {
+      // This can happen for non-obfuscated class names. Do not log.
+      continue;
+    }
+    const profiling::ObfuscatedClass& cls = it->second;
+    auto* proto_class = proto_mapping->add_obfuscated_classes();
+    proto_class->set_obfuscated_name(obfuscated_class_name);
+    proto_class->set_deobfuscated_name(cls.deobfuscated_name);
+    for (const std::string& obfuscated_field_name : obfuscated_field_names) {
+      auto field_it = cls.deobfuscated_fields.find(obfuscated_field_name);
+      if (field_it != cls.deobfuscated_fields.end()) {
+        auto* proto_member = proto_class->add_obfuscated_members();
+        proto_member->set_obfuscated_name(obfuscated_field_name);
+        proto_member->set_deobfuscated_name(field_it->second);
+      } else {
+        PERFETTO_ELOG("%s.%s not found", obfuscated_class_name.c_str(),
+                      obfuscated_field_name.c_str());
+      }
+    }
   }
+  callback(packet.SerializeAsString());
 }
 
 TraceWriter::TraceWriter(std::ostream* output) : output_(output) {}
 
-TraceWriter::~TraceWriter() {
-  output_->flush();
-}
+TraceWriter::~TraceWriter() = default;
 
 void TraceWriter::Write(const std::string& s) {
   Write(s.data(), s.size());
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index f95c3d8..e027ad1 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -18,6 +18,8 @@
 #define TOOLS_TRACE_TO_TEXT_UTILS_H_
 
 #include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
 
 #include <functional>
 #include <iostream>
@@ -27,7 +29,7 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/paged_memory.h"
-#include "src/profiling/deobfuscator.h"
+#include "perfetto/profiling/deobfuscator.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
 #include <zlib.h>
@@ -57,10 +59,19 @@
     std::istream* input,
     const std::function<void(std::unique_ptr<char[]>, size_t)>&);
 
+base::Optional<std::string> GetPerfettoProguardMapPath();
 
 bool ReadTrace(trace_processor::TraceProcessor* tp, std::istream* input);
-void IngestTraceOrDie(trace_processor::TraceProcessor* tp,
-                      const std::string& trace_proto);
+
+void WriteTracePacket(const std::string& str, std::ostream* output);
+
+// Generate ObfuscationMapping protos for all obfuscated java names in the
+// database.
+// Wrap them in proto-encoded TracePackets messages and call callback.
+void DeobfuscateDatabase(
+    trace_processor::TraceProcessor* tp,
+    const std::map<std::string, profiling::ObfuscatedClass>& mapping,
+    std::function<void(const std::string&)> callback);
 
 class TraceWriter {
  public:
diff --git a/tools/traceconv b/tools/traceconv
index 9887ec1..d6db5ac 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +21,7 @@
 # cat ./traceconv | python -
 
 BASH_FALLBACK = """ "
-exec python3 - "$@" <<'#'EOF
+exec python - "$@" <<'#'EOF
 #"""
 
 import hashlib
@@ -29,12 +29,13 @@
 import sys
 import subprocess
 import tempfile
-import platform
 
 
+# Keep this in sync with the SHAs in catapult file
+# systrace/systrace/tracing_agents/atrace_from_file_agent.py.
 TRACE_TO_TEXT_SHAS = {
-    'linux': '7e3e10dfb324e31723efd63ac25037856e06eba0',
-    'mac': '21f0f42dd019b4f09addd404a114fbf2322ca8a4',
+    'linux': '2f4ee64e3f2135f698ee665d91c489e129fe7859',
+    'mac': 'd000e01827c439357a4d6e6c5b1076357e561a26',
 }
 TRACE_TO_TEXT_PATH = tempfile.gettempdir()
 TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
@@ -71,22 +72,16 @@
 
 
 def main(argv):
-  os_name = None
+  platform = None
   if sys.platform.startswith('linux'):
-    os_name = 'linux'
+    platform = 'linux'
   elif sys.platform.startswith('darwin'):
-    os_name = 'mac'
+    platform = 'mac'
   else:
     print("Invalid platform: {}".format(sys.platform))
     return 1
 
-  arch = platform.machine()
-  if arch not in ['x86_64', 'amd64']:
-    print("Prebuilts are only available for x86_64 (found '{}' instead).".format(arch))
-    print("Follow https://perfetto.dev/docs/contributing/build-instructions to build locally.")
-    return 1
-
-  trace_to_text_binary = load_trace_to_text(os_name)
+  trace_to_text_binary = load_trace_to_text(platform)
   os.execv(trace_to_text_binary, [trace_to_text_binary] + argv[1:])
 
 
diff --git a/tools/update_trace_processor b/tools/update_trace_processor
index 3968efa..6601ca9 100755
--- a/tools/update_trace_processor
+++ b/tools/update_trace_processor
@@ -19,19 +19,18 @@
 tools/gn gen $DIR --args='is_clang=true is_debug=false'
 tools/ninja -C $DIR trace_processor_shell
 
-if is_mac; then
-  platform=mac
-else
-  platform=linux
-  strip $DIR/trace_processor_shell
-fi
-
 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
diff --git a/tools/update_traceconv b/tools/update_traceconv
index 6f397f7..2860273 100755
--- a/tools/update_traceconv
+++ b/tools/update_traceconv
@@ -19,19 +19,18 @@
 tools/gn gen $DIR --args='is_clang=true is_debug=false'
 tools/ninja -C $DIR trace_to_text
 
-if is_mac; then
-  platform=mac
-else
-  platform=linux
-  strip $DIR/trace_to_text
-fi
-
 if which shasum; then
   NEW_SHA=$(shasum $DIR/trace_to_text | cut -f1 -d' ') # Mac OS
 else
   NEW_SHA=$(sha1sum $DIR/trace_to_text | cut -f1 -d' ') # Linux
 fi
 
+if is_mac; then
+  platform=mac
+else
+  platform=linux
+fi
+
 name=trace_to_text-$platform-$NEW_SHA
 
 gsutil cp $DIR/trace_to_text gs://perfetto/$name
@@ -42,5 +41,3 @@
 echo 'Now run the following command to update tools/traceconv:'
 echo "sed \"s/'$platform': '[^']*',/'$platform': '$NEW_SHA',/\" --in-place tools/traceconv"
 
-echo 'Now run the following command to update tools/heap_profile:'
-echo "sed \"s/'$platform': '[^']*',/'$platform': '$NEW_SHA',/\" --in-place tools/heap_profile"
diff --git a/tools/write_version_header.py b/tools/write_version_header.py
deleted file mode 100755
index dd02a69..0000000
--- a/tools/write_version_header.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-Writes the perfetto_version{.gen.h, .ts} files.
-
-This tool is run as part of a genrule from GN, SoonG and Bazel builds. It
-generates a source header (or in the case of --ts_out a TypeScript file) that
-contains:
-- The version number (e.g. v9.0) obtained parsing the CHANGELOG file.
-- The git HEAD's commit-ish (e.g. 6b330b772b0e973f79c70ba2e9bb2b0110c6715d)
-- The number of CLs from the release tag to HEAD.
-
-The latter is concatenated to the version number to distinguish builds made
-fully from release tags (e.g., v9.0.0) vs builds made from the main branch which
-are N cls ahead of the latest monthly release (e.g., v9.0.42).
-"""
-
-import argparse
-import os
-import re
-import sys
-import subprocess
-
-# Note: PROJECT_ROOT is not accurate in bazel builds, where this script is
-# executed in the bazel sandbox.
-PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
-SCM_REV_NOT_AVAILABLE = 'N/A'
-
-
-def get_latest_release(changelog_path):
-  """Returns a string like 'v9.0'.
-
-  It does so by searching the latest version mentioned in the CHANGELOG."""
-  if not changelog_path:
-    if os.path.exists('CHANGELOG'):
-      changelog_path = 'CHANGELOG'
-    else:
-      changelog_path = os.path.join(PROJECT_ROOT, 'CHANGELOG')
-  with open(changelog_path) as f:
-    for line in f.readlines():
-      m = re.match('^(v\d+[.]\d+)\s.*$', line)
-      if m is not None:
-        return m.group(1)
-  raise Exception('Failed to fetch Perfetto version from %s' % changelog_path)
-
-
-def get_git_info(last_release_tag):
-  """Returns a tuple ('deadbeef', '1234').
-
-  The first value is the SHA1 of the HEAD. The second is the number of CLs from
-  the passed |last_release_tag| to HEAD."""
-  commit_sha1 = SCM_REV_NOT_AVAILABLE
-  commits_since_release = ''
-  git_dir = os.path.join(PROJECT_ROOT, '.git')
-  if os.path.exists(git_dir):
-    try:
-      commit_sha1 = subprocess.check_output(['git', 'rev-parse', 'HEAD'],
-                                            cwd=PROJECT_ROOT).strip().decode()
-      with open(os.devnull, 'wb') as devnull:
-        commits_since_release = subprocess.check_output(
-            [
-                'git', 'rev-list', '--count',
-                'refs/tags/%s..HEAD' % last_release_tag
-            ],
-            cwd=PROJECT_ROOT,
-            stderr=devnull).strip().decode()
-    except subprocess.CalledProcessError:
-      pass
-
-  return (commit_sha1, commits_since_release)
-
-
-def write_if_unchanged(path, content):
-  prev_content = None
-  if os.path.exists(path):
-    with open(path, 'r') as fprev:
-      prev_content = fprev.read()
-  if prev_content == content:
-    return 0
-  with open(path, 'w') as fout:
-    fout.write(content)
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      '--no_git',
-      action='store_true',
-      help='Skips running git rev-parse, emits only the version from CHANGELOG')
-  parser.add_argument('--cpp_out', help='Path of the generated .h file.')
-  parser.add_argument('--ts_out', help='Path of the generated .ts file.')
-  parser.add_argument('--stdout', help='Write to stdout', action='store_true')
-  parser.add_argument('--changelog', help='Path to CHANGELOG.')
-  args = parser.parse_args()
-
-  release = get_latest_release(args.changelog)
-  if args.no_git:
-    git_sha1, commits_since_release = (SCM_REV_NOT_AVAILABLE, '')
-  else:
-    git_sha1, commits_since_release = get_git_info(release)
-
-  # Try to compute the number of commits since the last release. This can fail
-  # in some environments (e.g. in android builds) because the bots pull only
-  # the main branch and don't pull the whole list of tags.
-  if commits_since_release:
-    version = '%s.%s' % (release, commits_since_release)  # e.g., 'v9.0.42'.
-  else:
-    version = release  # e.g., 'v9.0'.
-
-  if args.cpp_out:
-    guard = '%s_' % args.cpp_out.upper()
-    guard = re.sub(r'[^\w]', '_', guard)
-    lines = []
-    lines.append('// Generated by %s' % os.path.basename(__file__))
-    lines.append('')
-    lines.append('#ifndef %s' % guard)
-    lines.append('#define %s' % guard)
-    lines.append('')
-    lines.append('#define PERFETTO_VERSION_STRING() "%s"' % version)
-    lines.append('#define PERFETTO_VERSION_SCM_REVISION() "%s"' % git_sha1)
-    lines.append('')
-    lines.append('#endif  // %s' % guard)
-    lines.append('')
-    content = '\n'.join(lines)
-    write_if_unchanged(args.cpp_out, content)
-
-  if args.ts_out:
-    lines = []
-    lines.append('export const VERSION = "%s";' % version)
-    lines.append('export const SCM_REVISION = "%s";' % git_sha1)
-    content = '\n'.join(lines)
-    write_if_unchanged(args.ts_out, content)
-
-  if args.stdout:
-    print(version)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/ui/.gitignore b/ui/.gitignore
index 4f807ce..9b1c8b1 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -1,2 +1 @@
-/node_modules/
-/out
+/dist
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index 98aeb5b..00cb788 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -13,42 +13,574 @@
 # limitations under the License.
 
 import("../gn/perfetto.gni")
+import("../gn/perfetto_check_build_deps.gni")
+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)
 
-nodejs_bin = rebase_path("//tools/node", root_build_dir)
+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)
+
+# +----------------------------------------------------------------------------+
+# | The outer "ui" target to just ninja -C out/xxx ui                          |
+# +----------------------------------------------------------------------------+
 
 group("ui") {
   deps = [
-    ":ui_build($host_toolchain)",
+    ":chrome_extension_assets_dist",
+    ":chrome_extension_bundle_dist",
+    ":dist",
+    ":gen_dist_file_map",
+    ":service_worker_bundle_dist",
+    ":test_scripts",
+
+    # IMPORTANT: Only add deps here if they are NOT part of the production UI
+    # (e.g., tests, extensions, ...). Any UI dep should go in the
+    # |ui_dist_targets| list below. The only exception is the service worker
+    # target, that depends on that list.
+  ]
+}
+
+# The list of targets that produces dist/ files for the UI. This list is used
+# also by the gen_dist_file_map to generate the map of hashes of all UI files,
+# which is turn used by the service worker code for the offline caching.
+ui_dist_targets = [
+  ":assets_dist",
+  ":catapult_dist",
+  ":controller_bundle_dist",
+  ":engine_bundle_dist",
+  ":frontend_bundle_dist",
+  ":index_dist",
+  ":scss",
+  ":typefaces_dist",
+  ":wasm_dist",
+]
+
+# Buils the ui, but not service worker, tests and extensions.
+group("dist") {
+  deps = ui_dist_targets
+}
+
+# A minimal page to profile the WASM engine without the all UI.
+group("query") {
+  deps = [
+    ":query_bundle_dist",
+    ":query_dist",
+    ":ui",
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Template used to run node binaries using the hermetic node toolchain.      |
+# +----------------------------------------------------------------------------+
+template("node_bin") {
+  action(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "inputs",
+                             "outputs",
+                             "depfile",
+                           ])
+    deps = [ ":node_modules" ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+    script = "../gn/standalone/build_tool_wrapper.py"
+    _node_cmd = invoker.node_cmd
+    args = []
+    if (defined(invoker.suppress_stdout) && invoker.suppress_stdout) {
+      args += [ "--suppress_stdout" ]
+    }
+    if (defined(invoker.suppress_stderr) && invoker.suppress_stderr) {
+      args += [ "--suppress_stderr" ]
+    }
+    args += [
+              "--path=$nodejs_bin",
+              "node",
+              rebase_path("node_modules/.bin/$_node_cmd", root_build_dir),
+            ] + invoker.args
+  }
+}
+
+# +----------------------------------------------------------------------------+
+# | Template for "sorcery" the source map resolver.                            |
+# +----------------------------------------------------------------------------+
+template("sorcery") {
+  node_bin(target_name) {
+    assert(defined(invoker.input))
+    assert(defined(invoker.output))
+    forward_variables_from(invoker, [ "deps" ])
+    inputs = [ invoker.input ]
+    outputs = [
+      invoker.output,
+      invoker.output + ".map",
+    ]
+    node_cmd = "sorcery"
+    args = [
+      "-i",
+      rebase_path(invoker.input, root_build_dir),
+      "-o",
+      rebase_path(invoker.output, root_build_dir),
+    ]
+  }
+}
+
+# +----------------------------------------------------------------------------+
+# | Template for bundling js                                                   |
+# +----------------------------------------------------------------------------+
+template("bundle") {
+  node_bin(target_name) {
+    assert(defined(invoker.input))
+    assert(defined(invoker.output))
+    forward_variables_from(invoker, [ "deps" ])
+    inputs = [
+      invoker.input,
+      "rollup.config.js",
+    ]
+    outputs = [
+      invoker.output,
+      invoker.output + ".map",
+    ]
+    node_cmd = "rollup"
+    args = [
+      "-c",
+      rebase_path("rollup.config.js", root_build_dir),
+      rebase_path(invoker.input, root_build_dir),
+      "-o",
+      rebase_path(invoker.output, root_build_dir),
+      "-f",
+      "iife",
+      "-m",
+      "--silent",
+    ]
+  }
+}
+
+# +----------------------------------------------------------------------------+
+# | Bundles all *.js files together resolving CommonJS require() deps.         |
+# +----------------------------------------------------------------------------+
+
+# Bundle together all js sources into a bundle.js file, that will ultimately be
+# included by the .html files.
+
+bundle("frontend_bundle") {
+  deps = [ ":transpile_all_ts" ]
+  input = "$target_out_dir/frontend/index.js"
+  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" ]
+  input = "$target_out_dir/controller/index.js"
+  output = "$target_out_dir/controller_bundle.js"
+}
+
+bundle("engine_bundle") {
+  deps = [ ":transpile_all_ts" ]
+  input = "$target_out_dir/engine/index.js"
+  output = "$target_out_dir/engine_bundle.js"
+}
+
+bundle("service_worker_bundle") {
+  deps = [ ":transpile_service_worker_ts" ]
+  input = "$target_out_dir/service_worker/service_worker.js"
+  output = "$target_out_dir/service_worker.js"
+}
+
+bundle("query_bundle") {
+  deps = [ ":transpile_all_ts" ]
+  input = "$target_out_dir/query/index.js"
+  output = "$target_out_dir/query_bundle.js"
+}
+
+# +----------------------------------------------------------------------------+
+# | Protobuf: gen rules to create .js and .d.ts files from protos.             |
+# +----------------------------------------------------------------------------+
+node_bin("protos_to_js") {
+  inputs = []
+  foreach(proto, trace_processor_protos) {
+    inputs += [ "../protos/perfetto/trace_processor/$proto.proto" ]
+  }
+  inputs += [
+    "../protos/perfetto/common/trace_stats.proto",
+    "../protos/perfetto/common/tracing_service_capabilities.proto",
+    "../protos/perfetto/config/perfetto_config.proto",
+    "../protos/perfetto/ipc/consumer_port.proto",
+    "../protos/perfetto/ipc/wire_protocol.proto",
+    "../protos/perfetto/metrics/metrics.proto",
+  ]
+  outputs = [ "$ui_gen_dir/protos.js" ]
+  node_cmd = "pbjs"
+  args = [
+           "-t",
+           "static-module",
+           "-w",
+           "commonjs",
+           "-p",
+           rebase_path("..", root_build_dir),
+           "-o",
+           rebase_path(outputs[0], root_build_dir),
+         ] + rebase_path(inputs, root_build_dir)
+}
+
+# Protobuf.js requires to first generate .js files from the .proto and then
+# create .ts definitions for them.
+node_bin("protos_to_ts") {
+  deps = [ ":protos_to_js" ]
+  inputs = [ "$ui_gen_dir/protos.js" ]
+  outputs = [ "$ui_gen_dir/protos.d.ts" ]
+  node_cmd = "pbts"
+  args = [
+    "-p",
+    rebase_path("..", root_build_dir),
+    "-o",
+    rebase_path(outputs[0], root_build_dir),
+    rebase_path(inputs[0], root_build_dir),
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | TypeScript: transpiles all *.ts into .js                                   |
+# +----------------------------------------------------------------------------+
+
+# Builds all .ts sources in the repo under |src|.
+node_bin("transpile_all_ts") {
+  deps = [
+    ":dist_symlink",
+    ":protos_to_ts",
+    ":wasm_gen",
+  ]
+  inputs = [ "tsconfig.json" ]
+  outputs = [
+    "$target_out_dir/frontend/index.js",
+    "$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"
+  exec_script("../gn/standalone/glob.py",
+              [
+                "--root=" + rebase_path(".", root_build_dir),
+                "--filter=*.ts",
+                "--exclude=node_modules",
+                "--exclude=dist",
+                "--exclude=service_worker",
+                "--deps=obj/ui/frontend/index.js",
+                "--output=" + rebase_path(depfile),
+              ],
+              "")
+
+  node_cmd = "tsc"
+  args = [
+    "--project",
+    rebase_path(".", root_build_dir),
+    "--outDir",
+    rebase_path(target_out_dir, root_build_dir),
+  ]
+}
+
+node_bin("transpile_service_worker_ts") {
+  deps = [
+    ":dist_symlink",
+    ":gen_dist_file_map",
+  ]
+  inputs = [
+    "tsconfig.json",
+    "src/service_worker/service_worker.ts",
+  ]
+  outputs = [ "$target_out_dir/service_worker/service_worker.js" ]
+
+  node_cmd = "tsc"
+  args = [
+    "--project",
+    rebase_path("src/service_worker", root_build_dir),
+    "--outDir",
+    rebase_path(target_out_dir, root_build_dir),
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Build css.                                                                 |
+# +----------------------------------------------------------------------------+
+
+scss_root = "src/assets/perfetto.scss"
+scss_srcs = [
+  "src/assets/typefaces.scss",
+  "src/assets/sidebar.scss",
+  "src/assets/topbar.scss",
+  "src/assets/record.scss",
+  "src/assets/common.scss",
+  "src/assets/modal.scss",
+  "src/assets/details.scss",
+]
+
+# Build css.
+node_bin("scss") {
+  deps = [ ":dist_symlink" ]
+  inputs = [ scss_root ] + scss_srcs
+  outputs = [ "$ui_dir/perfetto.css" ]
+
+  node_cmd = "node-sass"
+  args = [
+    "--quiet",
+    rebase_path(scss_root, root_build_dir),
+    rebase_path(outputs[0], root_build_dir),
+  ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Copy rules: create the final output directory.                             |
+# +----------------------------------------------------------------------------+
+copy("index_dist") {
+  sources = [ "index.html" ]
+  outputs = [ "$ui_dir/index.html" ]
+}
+
+copy("typefaces_dist") {
+  sources = [
+    "../buildtools/typefaces/MaterialIcons.woff2",
+    "../buildtools/typefaces/Raleway-Regular.woff2",
+    "../buildtools/typefaces/Raleway-Thin.woff2",
+    "../buildtools/typefaces/RobotoCondensed-Light.woff2",
+    "../buildtools/typefaces/RobotoCondensed-Regular.woff2",
+    "../buildtools/typefaces/RobotoMono-Regular.woff2",
+  ]
+
+  outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
+}
+
+copy("query_dist") {
+  sources = [ "query.html" ]
+  outputs = [ "$ui_dir/query.html" ]
+}
+
+copy("assets_dist") {
+  sources = [
+              "src/assets/brand.png",
+              "src/assets/favicon.png",
+              "src/assets/logo-3d.png",
+              "src/assets/rec_atrace.png",
+              "src/assets/rec_battery_counters.png",
+              "src/assets/rec_board_voltage.png",
+              "src/assets/rec_cpu_coarse.png",
+              "src/assets/rec_cpu_fine.png",
+              "src/assets/rec_cpu_freq.png",
+              "src/assets/rec_cpu_voltage.png",
+              "src/assets/rec_cpu_wakeup.png",
+              "src/assets/rec_ftrace.png",
+              "src/assets/rec_java_heap_dump.png",
+              "src/assets/rec_lmk.png",
+              "src/assets/rec_logcat.png",
+              "src/assets/rec_long_trace.png",
+              "src/assets/rec_mem_hifreq.png",
+              "src/assets/rec_meminfo.png",
+              "src/assets/rec_native_heap_profiler.png",
+              "src/assets/rec_one_shot.png",
+              "src/assets/rec_ps_stats.png",
+              "src/assets/rec_ring_buf.png",
+              "src/assets/rec_vmstat.png",
+            ] + [ scss_root ] + scss_srcs
+  outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
+}
+copy("chrome_extension_assets_dist") {
+  sources = [
+    "src/assets/logo-128.png",
+    "src/chrome_extension/manifest.json",
+  ]
+  outputs = [ "$chrome_extension_dir/{{source_file_part}}" ]
+}
+
+sorcery("frontend_bundle_dist") {
+  deps = [ ":frontend_bundle" ]
+  input = "$target_out_dir/frontend_bundle.js"
+  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" ]
+  input = "$target_out_dir/controller_bundle.js"
+  output = "$ui_dir/controller_bundle.js"
+}
+
+sorcery("engine_bundle_dist") {
+  deps = [ ":engine_bundle" ]
+  input = "$target_out_dir/engine_bundle.js"
+  output = "$ui_dir/engine_bundle.js"
+}
+
+sorcery("service_worker_bundle_dist") {
+  deps = [ ":service_worker_bundle" ]
+  input = "$target_out_dir/service_worker.js"
+  output = "$ui_dir/service_worker.js"
+}
+
+sorcery("query_bundle_dist") {
+  deps = [ ":query_bundle" ]
+  input = "$target_out_dir/query_bundle.js"
+  output = "$ui_dir/query_bundle.js"
+}
+
+copy("wasm_dist") {
+  deps = [
     "//src/trace_processor:trace_processor.wasm($wasm_toolchain)",
     "//tools/trace_to_text:trace_to_text.wasm($wasm_toolchain)",
   ]
+  sources = [
+    "$root_build_dir/wasm/trace_processor.wasm",
+    "$root_build_dir/wasm/trace_to_text.wasm",
+  ]
+  outputs = [ "$ui_dir/{{source_file_part}}" ]
 }
 
-action("deprecation_warning") {
+copy("wasm_gen") {
+  deps = [
+    ":dist_symlink",
+
+    # trace_processor
+    "//src/trace_processor:trace_processor.d.ts($wasm_toolchain)",
+    "//src/trace_processor:trace_processor.js($wasm_toolchain)",
+    "//src/trace_processor:trace_processor.wasm($wasm_toolchain)",
+
+    # trace_to_text
+    "//tools/trace_to_text:trace_to_text.d.ts($wasm_toolchain)",
+    "//tools/trace_to_text:trace_to_text.js($wasm_toolchain)",
+    "//tools/trace_to_text:trace_to_text.wasm($wasm_toolchain)",
+  ]
+  sources = [
+    # trace_processor
+    "$root_build_dir/wasm/trace_processor.d.ts",
+    "$root_build_dir/wasm/trace_processor.js",
+    "$root_build_dir/wasm/trace_processor.wasm",
+
+    # trace_to_text
+    "$root_build_dir/wasm/trace_to_text.d.ts",
+    "$root_build_dir/wasm/trace_to_text.js",
+    "$root_build_dir/wasm/trace_to_text.wasm",
+  ]
+  if (is_debug) {
+    sources += [
+      "$root_build_dir/wasm/trace_processor.wasm.map",
+      "$root_build_dir/wasm/trace_to_text.wasm.map",
+    ]
+  }
+  outputs = [ "$ui_gen_dir/{{source_file_part}}" ]
+}
+
+# Copy over the vulcanized legacy trace viewer.
+copy("catapult_dist") {
+  sources = [
+    "../buildtools/catapult_trace_viewer/catapult_trace_viewer.html",
+    "../buildtools/catapult_trace_viewer/catapult_trace_viewer.js",
+  ]
+  outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
+}
+
+# +----------------------------------------------------------------------------+
+# | Node JS: Creates a symlink in the out directory to node_modules.           |
+# +----------------------------------------------------------------------------+
+
+perfetto_check_build_deps("check_ui_deps") {
+  args = [ "--ui" ]
+  inputs = [ "package-lock.json" ]
+}
+
+# Creates a symlink from out/xxx/ui/node_modules -> ../../../ui/node_modules.
+# This allows to run rollup and other node tools from the out/xxx directory.
+action("node_modules_symlink") {
+  deps = [ ":check_ui_deps" ]
   script = "../gn/standalone/build_tool_wrapper.py"
-  outputs = [ "$target_out_dir/never_written_always_execute_rule-2.stamp" ]
+  stamp_file = "$target_out_dir/.$target_name.stamp"
+  args = [
+    "--stamp",
+    rebase_path(stamp_file, root_build_dir),
+    "/bin/ln",
+    "-fns",
+    rebase_path("node_modules", target_out_dir),
+    rebase_path("$target_out_dir/node_modules", root_build_dir),
+  ]
+  outputs = [ stamp_file ]
+}
+
+group("node_modules") {
+  deps = [ ":node_modules_symlink" ]
+}
+
+# Creates a symlink from //ui/dist -> ../../out/xxx/ui. Used only for
+# autocompletion in IDEs. The problem this is solving is that in tsconfig.json
+# we can't possibly know the path to ../../out/xxx for outDir. Instead, we set
+# outDir to "./dist" and create a symlink on the first build.
+action("dist_symlink") {
+  script = "../gn/standalone/build_tool_wrapper.py"
+  stamp_file = "$target_out_dir/.$target_name.stamp"
+  args = [
+    "--stamp",
+    rebase_path(stamp_file, root_build_dir),
+    "/bin/ln",
+    "-fns",
+    rebase_path(target_out_dir, "."),
+    rebase_path("dist", root_build_dir),
+  ]
+  inputs = [ "$root_build_dir" ]
+  outputs = [ stamp_file ]
+}
+
+group("test_scripts") {
+  deps = [
+    ":copy_tests_script",
+    ":copy_unittests_script",
+  ]
+}
+
+copy("copy_unittests_script") {
+  sources = [ "config/ui_unittests_template" ]
+  outputs = [ "$root_build_dir/ui_unittests" ]
+}
+
+copy("copy_tests_script") {
+  sources = [ "config/ui_tests_template" ]
+  outputs = [ "$root_build_dir/ui_tests" ]
+}
+
+# This target generates an map containing all the UI subresources and their
+# hashes. This is used by the service worker code for offline caching.
+# This taarget needs to be kept at the end of the BUILD.gn file, because of the
+# get_target_outputs() call (fails otherwise due to GN's evaluation order).
+action("gen_dist_file_map") {
+  out_file_path = "$ui_gen_dir/dist_file_map.ts"
+
+  dist_files = []
+  foreach(target, ui_dist_targets) {
+    foreach(dist_file, get_target_outputs(target)) {
+      dist_files += [ rebase_path(dist_file, root_build_dir) ]
+    }
+  }
+  deps = [ ":dist" ]
+  script = "../gn/standalone/write_ui_dist_file_map.py"
   inputs = []
+  outputs = [ out_file_path ]
   args = [
-    "cat",
-    rebase_path("config/gn_deprecation_banner.txt", root_build_dir),
-  ]
-}
-
-action("ui_build") {
-  deps = [ ":deprecation_warning" ]
-  script = "../gn/standalone/build_tool_wrapper.py"
-  outputs = [ "$target_out_dir/never_written_always_execute_rule.stamp" ]
-  inputs = [
-    "//tools/node",
-    "build.js",
-  ]
-  args = [
-    nodejs_bin,
-    rebase_path("build.js", root_build_dir),
-    "--out",
-    ".",
-  ]
+           "--out",
+           rebase_path(out_file_path, root_build_dir),
+           "--strip",
+           rebase_path(ui_dir, root_build_dir),
+         ] + dist_files
 }
diff --git a/ui/OWNERS b/ui/OWNERS
index 973653f..1ae6de1 100644
--- a/ui/OWNERS
+++ b/ui/OWNERS
@@ -1,4 +1,3 @@
 hjd@google.com
-eseckler@google.com
+taylori@google.com
 dproy@google.com
-primiano@google.com
diff --git a/ui/README.md b/ui/README.md
index 3fed469..ed0cd41 100644
--- a/ui/README.md
+++ b/ui/README.md
@@ -13,7 +13,7 @@
 ```
 
 For more details on `gn` configs see
-[Build Instructions](../docs/contributing/build-instructions.md).
+[Build Instructions](../docs/build-instructions.md).
 
 To run the tests:
 ```bash
diff --git a/ui/build b/ui/build
deleted file mode 100755
index 8045f2b..0000000
--- a/ui/build
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-
-$UI_DIR/node $UI_DIR/build.js "$@"
diff --git a/ui/build.js b/ui/build.js
deleted file mode 100644
index 28f0456..0000000
--- a/ui/build.js
+++ /dev/null
@@ -1,631 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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';
-
-// This script takes care of:
-// - The build process for the whole UI and the chrome extension.
-// - The HTTP dev-server with live-reload capabilities.
-// The reason why this is a hand-rolled script rather than a conventional build
-// system is keeping incremental build fast and maintaining the set of
-// dependencies contained.
-// The only way to keep incremental build fast (i.e. O(seconds) for the
-// edit-one-line -> reload html cycles) is to run both the TypeScript compiler
-// and the rollup bundler in --watch mode. Any other attempt, leads to O(10s)
-// incremental-build times.
-// This script allows mixing build tools that support --watch mode (tsc and
-// rollup) and auto-triggering-on-file-change rules via node-watch.
-// When invoked without any argument (e.g., for production builds), this script
-// just runs all the build tasks serially. It doesn't to do any mtime-based
-// check, it always re-runs all the tasks.
-// When invoked with --watch, it mounts a pipeline of tasks based on node-watch
-// and runs them together with tsc --watch and rollup --watch.
-// The output directory structure is carefully crafted so that any change to UI
-// sources causes cascading triggers of the next steps.
-// The overall build graph looks as follows:
-// +----------------+      +-----------------------------+
-// | protos/*.proto |----->| pbjs out/tsc/gen/protos.js  |--+
-// +----------------+      +-----------------------------+  |
-//                         +-----------------------------+  |
-//                         | pbts out/tsc/gen/protos.d.ts|<-+
-//                         +-----------------------------+
-//                             |
-//                             V      +-------------------------+
-// +---------+              +-----+   |  out/tsc/frontend/*.js  |
-// | ui/*.ts |------------->| tsc |-> +-------------------------+   +--------+
-// +---------+              +-----+   | out/tsc/controller/*.js |-->| rollup |
-//                            ^       +-------------------------+   +--------+
-//                +------------+      |   out/tsc/engine/*.js   |       |
-// +-----------+  |*.wasm.js   |      +-------------------------+       |
-// |ninja *.cc |->|*.wasm.d.ts |                                        |
-// +-----------+  |*.wasm      |-----------------+                      |
-//                +------------+                 |                      |
-//                                               V                      V
-// +-----------+  +------+    +------------------------------------------------+
-// | ui/*.scss |->| scss |--->|              Final out/dist/ dir               |
-// +-----------+  +------+    +------------------------------------------------+
-// +----------------------+   | +----------+ +---------+ +--------------------+|
-// | src/assets/*.png     |   | | assets/  | |*.wasm.js| | frontend_bundle.js ||
-// +----------------------+   | |  *.css   | |*.wasm   | +--------------------+|
-// | buildtools/typefaces |-->| |  *.png   | +---------+ |controller_bundle.js||
-// +----------------------+   | |  *.woff2 |             +--------------------+|
-// | buildtools/legacy_tv |   | |  tv.html |             |  engine_bundle.js  ||
-// +----------------------+   | +----------+             +--------------------+|
-//                            +------------------------------------------------+
-
-const argparse = require('argparse');
-const child_process = require('child_process');
-const crypto = require('crypto');
-const fs = require('fs');
-const http = require('http');
-const path = require('path');
-const fswatch = require('node-watch');  // Like fs.watch(), but works on Linux.
-const pjoin = path.join;
-
-const ROOT_DIR = path.dirname(__dirname);  // The repo root.
-const VERSION_SCRIPT = pjoin(ROOT_DIR, 'tools/write_version_header.py');
-
-const cfg = {
-  watch: false,
-  verbose: false,
-  debug: false,
-  startHttpServer: false,
-  wasmModules: ['trace_processor', 'trace_to_text'],
-  testConfigs: ['jest.unit.config.js'],
-
-  // The fields below will be changed by main() after cmdline parsing.
-  // Directory structure:
-  // out/xxx/    -> outDir         : Root build dir, for both ninja/wasm and UI.
-  //   ui/       -> outUiDir       : UI dir. All outputs from this script.
-  //    tsc/     -> outTscDir      : Transpiled .ts -> .js.
-  //      gen/   -> outGenDir      : Auto-generated .ts/.js (e.g. protos).
-  //    dist/    -> outDistRootDir : Only index.html and service_worker.js
-  //      v1.2/  -> outDistDir     : JS bundles and assets
-  //    chrome_extension/          : Chrome extension.
-  outDir: pjoin(ROOT_DIR, 'out/ui'),
-  version: '',  // v1.2.3, derived from the CHANGELOG + git.
-  outUiDir: '',
-  outDistRootDir: '',
-  outTscDir: '',
-  outGenDir: '',
-  outDistDir: '',
-  outExtDir: '',
-};
-
-const RULES = [
-  {r: /ui\/src\/assets\/index.html/, f: copyIndexHtml},
-  {r: /ui\/src\/assets\/((.*)[.]png)/, f: copyAssets},
-  {r: /buildtools\/typefaces\/(.+[.]woff2)/, f: copyAssets},
-  {r: /buildtools\/catapult_trace_viewer\/(.+(js|html))/, f: copyAssets},
-  {r: /ui\/src\/assets\/.+[.]scss/, f: compileScss},
-  {r: /ui\/src\/assets\/.+[.]scss/, f: compileScss},
-  {r: /ui\/src\/chrome_extension\/.*/, f: copyExtensionAssets},
-  {r: /.*\/dist\/.+\/(?!manifest\.json).*/, f: genServiceWorkerManifestJson},
-  {r: /.*\/dist\/.*/, f: notifyLiveServer},
-];
-
-let tasks = [];
-let tasksTot = 0, tasksRan = 0;
-let serverStarted = false;
-let httpWatches = [];
-let tStart = Date.now();
-let subprocesses = [];
-
-function main() {
-  const parser = new argparse.ArgumentParser();
-  parser.addArgument('--out', {help: 'Output directory'});
-  parser.addArgument(['--watch', '-w'], {action: 'storeTrue'});
-  parser.addArgument(['--serve', '-s'], {action: 'storeTrue'});
-  parser.addArgument(['--verbose', '-v'], {action: 'storeTrue'});
-  parser.addArgument(['--no-build', '-n'], {action: 'storeTrue'});
-  parser.addArgument(['--no-wasm', '-W'], {action: 'storeTrue'});
-  parser.addArgument(['--run-tests', '-t'], {action: 'storeTrue'});
-  parser.addArgument(['--debug', '-d'], {action: 'storeTrue'});
-
-  const args = parser.parseArgs();
-  const clean = !args.no_build;
-  cfg.outDir = path.resolve(ensureDir(args.out || cfg.outDir));
-  cfg.outUiDir = ensureDir(pjoin(cfg.outDir, 'ui'), clean);
-  cfg.outExtDir = ensureDir(pjoin(cfg.outUiDir, 'chrome_extension'));
-  cfg.outDistRootDir = ensureDir(pjoin(cfg.outUiDir, 'dist'));
-  const proc = exec('python3', [VERSION_SCRIPT, '--stdout'], {stdout: 'pipe'});
-  cfg.version = proc.stdout.toString().trim();
-  cfg.outDistDir = ensureDir(pjoin(cfg.outDistRootDir, cfg.version));
-  cfg.outTscDir = ensureDir(pjoin(cfg.outUiDir, 'tsc'));
-  cfg.outGenDir = ensureDir(pjoin(cfg.outUiDir, 'tsc/gen'));
-  cfg.watch = !!args.watch;
-  cfg.verbose = !!args.verbose;
-  cfg.debug = !!args.debug;
-  cfg.startHttpServer = args.serve;
-
-  process.on('SIGINT', () => {
-    console.log('\nSIGINT received. Killing all child processes and exiting');
-    for (const proc of subprocesses) {
-      if (proc) proc.kill('SIGINT');
-    }
-    process.exit(130);  // 130 -> Same behavior of bash when killed by SIGINT.
-  });
-
-  // Check that deps are current before starting.
-  const installBuildDeps = pjoin(ROOT_DIR, 'tools/install-build-deps');
-  const checkDepsPath = pjoin(cfg.outDir, '.check_deps');
-  const depsArgs = [`--check-only=${checkDepsPath}`, '--ui'];
-  exec(installBuildDeps, depsArgs);
-
-  console.log('Entering', cfg.outDir);
-  process.chdir(cfg.outDir);
-
-  updateSymlinks();  // Links //ui/out -> //out/xxx/ui/
-
-  // Enqueue empty task. This is needed only for --no-build --serve. The HTTP
-  // server is started when the task queue reaches quiescence, but it takes at
-  // least one task for that.
-  addTask(() => {});
-
-  if (!args.no_build) {
-    buildWasm(args.no_wasm);
-    scanDir('ui/src/assets');
-    scanDir('ui/src/chrome_extension');
-    scanDir('buildtools/typefaces');
-    scanDir('buildtools/catapult_trace_viewer');
-    compileProtos();
-    genVersion();
-    transpileTsProject('ui');
-    transpileTsProject('ui/src/service_worker');
-    bundleJs('rollup.config.js');
-    genServiceWorkerManifestJson();
-
-    // Watches the /dist. When changed:
-    // - Notifies the HTTP live reload clients.
-    // - Regenerates the ServiceWorker file map.
-    scanDir(cfg.outDistRootDir);
-  }
-
-  if (args.run_tests) {
-    runTests();
-  }
-}
-
-// -----------
-// Build rules
-// -----------
-
-function runTests() {
-  const args =
-      ['--rootDir', cfg.outTscDir, '--verbose', '--runInBand', '--forceExit'];
-  for (const cfgFile of cfg.testConfigs) {
-    args.push('--projects', pjoin(ROOT_DIR, 'ui/config', cfgFile));
-  }
-  if (cfg.watch) {
-    args.push('--watchAll');
-    addTask(execNode, ['jest', args, {async: true}]);
-  } else {
-    addTask(execNode, ['jest', args]);
-  }
-}
-
-function copyIndexHtml(src) {
-  const index_html = () => {
-    let html = fs.readFileSync(src).toString();
-    // First copy the index.html as-is into the dist/v1.2.3/ directory. This is
-    // only used for archival purporses, so one can open
-    // ui.perfetto.dev/v1.2.3/ to skip the auto-update and channel logic.
-    fs.writeFileSync(pjoin(cfg.outDistDir, 'index.html'), html);
-
-    // Then copy it into the dist/ root by patching the version code.
-    // TODO(primiano): in next CLs, this script should take a
-    // --release_map=xxx.json argument, to populate this with multiple channels.
-    const versionMap = JSON.stringify({'stable': cfg.version});
-    const bodyRegex = /data-perfetto_version='[^']*'/;
-    html = html.replace(bodyRegex, `data-perfetto_version='${versionMap}'`);
-    fs.writeFileSync(pjoin(cfg.outDistRootDir, 'index.html'), html);
-  };
-  addTask(index_html);
-}
-
-function copyAssets(src, dst) {
-  addTask(cp, [src, pjoin(cfg.outDistDir, 'assets', dst)]);
-}
-
-function compileScss() {
-  const src = pjoin(ROOT_DIR, 'ui/src/assets/perfetto.scss');
-  const dst = pjoin(cfg.outDistDir, 'perfetto.css');
-  // In watch mode, don't exit(1) if scss fails. It can easily happen by
-  // having a typo in the css. It will still print an error.
-  const noErrCheck = !!cfg.watch;
-  addTask(execNode, ['node-sass', ['--quiet', src, dst], {noErrCheck}]);
-}
-
-function compileProtos() {
-  const dstJs = pjoin(cfg.outGenDir, 'protos.js');
-  const dstTs = pjoin(cfg.outGenDir, 'protos.d.ts');
-  const inputs = [
-    'protos/perfetto/trace_processor/trace_processor.proto',
-    'protos/perfetto/common/trace_stats.proto',
-    'protos/perfetto/common/tracing_service_capabilities.proto',
-    'protos/perfetto/config/perfetto_config.proto',
-    'protos/perfetto/ipc/consumer_port.proto',
-    'protos/perfetto/ipc/wire_protocol.proto',
-    'protos/perfetto/metrics/metrics.proto',
-  ];
-  const pbjsArgs = [
-    '--force-number',
-    '-t',
-    'static-module',
-    '-w',
-    'commonjs',
-    '-p',
-    ROOT_DIR,
-    '-o',
-    dstJs
-  ].concat(inputs);
-  addTask(execNode, ['pbjs', pbjsArgs]);
-  const pbtsArgs = ['-p', ROOT_DIR, '-o', dstTs, dstJs];
-  addTask(execNode, ['pbts', pbtsArgs]);
-}
-
-// Generates a .ts source that defines the VERSION and SCM_REVISION constants.
-function genVersion() {
-  const cmd = 'python3';
-  const args =
-      [VERSION_SCRIPT, '--ts_out', pjoin(cfg.outGenDir, 'perfetto_version.ts')];
-  addTask(exec, [cmd, args]);
-}
-
-function updateSymlinks() {
-  mklink(cfg.outUiDir, pjoin(ROOT_DIR, 'ui/out'));
-
-  // Creates a out/dist_version -> out/dist/v1.2.3 symlink, so rollup config
-  // can point to that without having to know the current version number.
-  mklink(
-      path.relative(cfg.outUiDir, cfg.outDistDir),
-      pjoin(cfg.outUiDir, 'dist_version'));
-
-  mklink(
-      pjoin(ROOT_DIR, 'ui/node_modules'), pjoin(cfg.outTscDir, 'node_modules'))
-}
-
-// Invokes ninja for building the {trace_processor, trace_to_text} Wasm modules.
-// It copies the .wasm directly into the out/dist/ dir, and the .js/.ts into
-// out/tsc/, so the typescript compiler and the bundler can pick them up.
-function buildWasm(skipWasmBuild) {
-  if (!skipWasmBuild) {
-    const gnArgs = ['gen', `--args=is_debug=${cfg.debug}`, cfg.outDir];
-    addTask(exec, [pjoin(ROOT_DIR, 'tools/gn'), gnArgs]);
-
-    const ninjaArgs = ['-C', cfg.outDir];
-    ninjaArgs.push(...cfg.wasmModules.map(x => `${x}_wasm`));
-    addTask(exec, [pjoin(ROOT_DIR, 'tools/ninja'), ninjaArgs]);
-  }
-
-  const wasmOutDir = pjoin(cfg.outDir, 'wasm');
-  for (const wasmMod of cfg.wasmModules) {
-    // The .wasm file goes directly into the dist dir (also .map in debug)
-    for (const ext of ['.wasm'].concat(cfg.debug ? ['.wasm.map'] : [])) {
-      const src = `${wasmOutDir}/${wasmMod}${ext}`;
-      addTask(cp, [src, pjoin(cfg.outDistDir, wasmMod + ext)]);
-    }
-    // The .js / .ts go into intermediates, they will be bundled by rollup.
-    for (const ext of ['.js', '.d.ts']) {
-      const fname = `${wasmMod}${ext}`;
-      addTask(cp, [pjoin(wasmOutDir, fname), pjoin(cfg.outGenDir, fname)]);
-    }
-  }
-}
-
-// This transpiles all the sources (frontend, controller, engine, extension) in
-// one go. The only project that has a dedicated invocation is service_worker.
-function transpileTsProject(project) {
-  const args = ['--project', pjoin(ROOT_DIR, project)];
-  if (cfg.watch) {
-    args.push('--watch', '--preserveWatchOutput');
-    addTask(execNode, ['tsc', args, {async: true}]);
-  } else {
-    addTask(execNode, ['tsc', args]);
-  }
-}
-
-// Creates the three {frontend, controller, engine}_bundle.js in one invocation.
-function bundleJs(cfgName) {
-  const rcfg = pjoin(ROOT_DIR, 'ui/config', cfgName);
-  const args = ['-c', rcfg, '--no-indent'];
-  args.push(...(cfg.verbose ? [] : ['--silent']));
-  if (cfg.watch) {
-    // --waitForBundleInput is so that we can run tsc --watch and rollup --watch
-    // together, without having to wait that tsc completes the first build.
-    args.push('--watch', '--waitForBundleInput', '--no-watch.clearScreen');
-    addTask(execNode, ['rollup', args, {async: true}]);
-  } else {
-    addTask(execNode, ['rollup', args]);
-  }
-}
-
-function genServiceWorkerManifestJson() {
-  function make_manifest() {
-    const manifest = {resources: {}};
-    // When building the subresource manifest skip source maps, the manifest
-    // itself and the copy of the index.html which is copied under /v1.2.3/.
-    // The root /index.html will be fetched by service_worker.js separately.
-    const skipRegex = /(\.map|manifest\.json|index.html)$/;
-    walk(cfg.outDistDir, absPath => {
-      const contents = fs.readFileSync(absPath);
-      const relPath = path.relative(cfg.outDistDir, absPath);
-      const b64 = crypto.createHash('sha256').update(contents).digest('base64');
-      manifest.resources[relPath] = 'sha256-' + b64;
-    }, skipRegex);
-    const manifestJson = JSON.stringify(manifest, null, 2);
-    fs.writeFileSync(pjoin(cfg.outDistDir, 'manifest.json'), manifestJson);
-  }
-  addTask(make_manifest, []);
-}
-
-function startServer() {
-  const port = 10000;
-  console.log(`Starting HTTP server on http://localhost:${port}`);
-  http.createServer(function(req, res) {
-        console.debug(req.method, req.url);
-        let uri = req.url.split('?', 1)[0];
-        if (uri.endsWith('/')) {
-          uri += 'index.html';
-        }
-
-        if (uri === '/live_reload') {
-          // Implements the Server-Side-Events protocol.
-          const head = {
-            'Content-Type': 'text/event-stream',
-            'Connection': 'keep-alive',
-            'Cache-Control': 'no-cache'
-          };
-          res.writeHead(200, head);
-          const arrayIdx = httpWatches.length;
-          // We never remove from the array, the delete leaves an undefined item
-          // around. It makes keeping track of the index easier at the cost of a
-          // small leak.
-          httpWatches.push(res);
-          req.on('close', () => delete httpWatches[arrayIdx]);
-          return;
-        }
-
-        const absPath = path.normalize(path.join(cfg.outDistRootDir, uri));
-        fs.readFile(absPath, function(err, data) {
-          if (err) {
-            res.writeHead(404);
-            res.end(JSON.stringify(err));
-            return;
-          }
-
-          const mimeMap = {
-            'html': 'text/html',
-            'css': 'text/css',
-            'js': 'application/javascript',
-            'wasm': 'application/wasm',
-          };
-          const ext = uri.split('.').pop();
-          const cType = mimeMap[ext] || 'octect/stream';
-          const head = {
-            'Content-Type': cType,
-            'Content-Length': data.length,
-            'Last-Modified': fs.statSync(absPath).mtime.toUTCString(),
-            'Cache-Control': 'no-cache',
-          };
-          res.writeHead(200, head);
-          res.write(data);
-          res.end();
-        });
-      })
-      .listen(port, '127.0.0.1');
-}
-
-// Called whenever a change in the out/dist directory is detected. It sends a
-// Server-Side-Event to the live_reload.ts script.
-function notifyLiveServer(changedFile) {
-  for (const cli of httpWatches) {
-    if (cli === undefined) continue;
-    cli.write(
-        'data: ' + path.relative(cfg.outDistRootDir, changedFile) + '\n\n');
-  }
-}
-
-function copyExtensionAssets() {
-  addTask(cp, [
-    pjoin(ROOT_DIR, 'ui/src/assets/logo-128.png'),
-    pjoin(cfg.outExtDir, 'logo-128.png')
-  ]);
-  addTask(cp, [
-    pjoin(ROOT_DIR, 'ui/src/chrome_extension/manifest.json'),
-    pjoin(cfg.outExtDir, 'manifest.json')
-  ]);
-}
-
-// -----------------------
-// Task chaining functions
-// -----------------------
-
-function addTask(func, args) {
-  const task = new Task(func, args);
-  for (const t of tasks) {
-    if (t.identity === task.identity) {
-      return;
-    }
-  }
-  tasks.push(task);
-  setTimeout(runTasks, 0);
-}
-
-function runTasks() {
-  const snapTasks = tasks.splice(0);  // snap = std::move(tasks).
-  tasksTot += snapTasks.length;
-  for (const task of snapTasks) {
-    const DIM = '\u001b[2m';
-    const BRT = '\u001b[37m';
-    const RST = '\u001b[0m';
-    const ms = (new Date(Date.now() - tStart)).toISOString().slice(17, -1);
-    const ts = `[${DIM}${ms}${RST}]`;
-    const descr = task.description.substr(0, 80);
-    console.log(`${ts} ${BRT}${++tasksRan}/${tasksTot}${RST}\t${descr}`);
-    task.func.apply(/*this=*/ undefined, task.args);
-  }
-  // Start the web server once reaching quiescence.
-  if (tasks.length === 0 && !serverStarted && cfg.startHttpServer) {
-    serverStarted = true;
-    startServer();
-  }
-}
-
-// Executes all the RULES that match the given |absPath|.
-function scanFile(absPath) {
-  console.assert(fs.existsSync(absPath));
-  console.assert(path.isAbsolute(absPath));
-  const normPath = path.relative(ROOT_DIR, absPath);
-  for (const rule of RULES) {
-    const match = rule.r.exec(normPath);
-    if (!match || match[0] !== normPath) continue;
-    const captureGroup = match.length > 1 ? match[1] : undefined;
-    rule.f(absPath, captureGroup);
-  }
-}
-
-// Walks the passed |dir| recursively and, for each file, invokes the matching
-// RULES. If --watch is used, it also installs a fswatch() and re-triggers the
-// matching RULES on each file change.
-function scanDir(dir, regex) {
-  const filterFn = regex ? absPath => regex.test(absPath) : () => true;
-  const absDir = path.isAbsolute(dir) ? dir : pjoin(ROOT_DIR, dir);
-  // Add a fs watch if in watch mode.
-  if (cfg.watch) {
-    fswatch(absDir, {recursive: true}, (_eventType, filePath) => {
-      if (!filterFn(filePath)) return;
-      if (cfg.verbose) {
-        console.log('File change detected', _eventType, filePath);
-      }
-      if (fs.existsSync(filePath)) {
-        scanFile(filePath, filterFn);
-      }
-    });
-  }
-  walk(absDir, f => {
-    if (filterFn(f)) scanFile(f);
-  });
-}
-
-function exec(cmd, args, opts) {
-  opts = opts || {};
-  opts.stdout = opts.stdout || 'inherit';
-  if (cfg.verbose) console.log(`${cmd} ${args.join(' ')}\n`);
-  const spwOpts = {cwd: cfg.outDir, stdio: ['ignore', opts.stdout, 'inherit']};
-  const checkExitCode = (code, signal) => {
-    if (signal === 'SIGINT' || signal === 'SIGTERM') return;
-    if (code !== 0 && !opts.noErrCheck) {
-      console.error(`${cmd} ${args.join(' ')} failed with code ${code}`);
-      process.exit(1);
-    }
-  };
-  if (opts.async) {
-    const proc = child_process.spawn(cmd, args, spwOpts);
-    const procIndex = subprocesses.length;
-    subprocesses.push(proc);
-    return new Promise((resolve, _reject) => {
-      proc.on('exit', (code, signal) => {
-        delete subprocesses[procIndex];
-        checkExitCode(code, signal);
-        resolve();
-      });
-    });
-  } else {
-    const spawnRes = child_process.spawnSync(cmd, args, spwOpts);
-    checkExitCode(spawnRes.status, spawnRes.signal);
-    return spawnRes;
-  }
-}
-
-function execNode(module, args, opts) {
-  const modPath = pjoin(ROOT_DIR, 'ui/node_modules/.bin', module);
-  const nodeBin = pjoin(ROOT_DIR, 'tools/node');
-  args = [modPath].concat(args || []);
-  return exec(nodeBin, args, opts);
-}
-
-// ------------------------------------------
-// File system & subprocess utility functions
-// ------------------------------------------
-
-class Task {
-  constructor(func, args) {
-    this.func = func;
-    this.args = args || [];
-    // |identity| is used to dedupe identical tasks in the queue.
-    this.identity = JSON.stringify([this.func.name, this.args]);
-  }
-
-  get description() {
-    const ret = this.func.name.startsWith('exec') ? [] : [this.func.name];
-    const flattenedArgs = [].concat.apply([], this.args);
-    for (const arg of flattenedArgs) {
-      const argStr = `${arg}`;
-      if (argStr.startsWith('/')) {
-        ret.push(path.relative(cfg.outDir, arg));
-      } else {
-        ret.push(argStr);
-      }
-    }
-    return ret.join(' ');
-  }
-}
-
-function walk(dir, callback, skipRegex) {
-  for (const child of fs.readdirSync(dir)) {
-    const childPath = pjoin(dir, child);
-    const stat = fs.lstatSync(childPath);
-    if (skipRegex !== undefined && skipRegex.test(child)) continue;
-    if (stat.isDirectory()) {
-      walk(childPath, callback, skipRegex);
-    } else if (!stat.isSymbolicLink()) {
-      callback(childPath);
-    }
-  }
-}
-
-function ensureDir(dirPath, clean) {
-  const exists = fs.existsSync(dirPath);
-  if (exists && clean) {
-    console.log('rm', dirPath);
-    fs.rmSync(dirPath, {recursive: true});
-  }
-  if (!exists || clean) fs.mkdirSync(dirPath, {recursive: true});
-  return dirPath;
-}
-
-function cp(src, dst) {
-  ensureDir(path.dirname(dst));
-  if (cfg.verbose) {
-    console.log(
-        'cp', path.relative(ROOT_DIR, src), '->', path.relative(ROOT_DIR, dst));
-  }
-  fs.copyFileSync(src, dst);
-}
-
-function mklink(src, dst) {
-  // If the symlink already points to the right place don't touch it. This is
-  // to avoid changing the mtime of the ui/ dir when unnecessary.
-  if (fs.existsSync(dst)) {
-    if (fs.lstatSync(dst).isSymbolicLink() && fs.readlinkSync(dst) === src) {
-      return;
-    } else {
-      fs.unlinkSync(dst);
-    }
-  }
-  fs.symlinkSync(src, dst);
-}
-
-main();
diff --git a/ui/config/gn_deprecation_banner.txt b/ui/config/gn_deprecation_banner.txt
deleted file mode 100644
index 06aed23..0000000
--- a/ui/config/gn_deprecation_banner.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-
--------------------------------------------------------
-WARNING: building the UI through GN+ninja is deprecated.
-Going forward use the //ui/build script
--------------------------------------------------------
-
\ No newline at end of file
diff --git a/ui/config/headless_environment.js b/ui/config/headless_environment.js
index 6c4f3ec..da1c83b 100644
--- a/ui/config/headless_environment.js
+++ b/ui/config/headless_environment.js
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+const fs = require('fs');
+const path = require('path');
 const NodeEnvironment = require('jest-environment-node');
 const puppeteer = require('puppeteer');
 
diff --git a/ui/config/jest.headless.config.js b/ui/config/jest.headless.config.js
deleted file mode 100644
index 723ab25..0000000
--- a/ui/config/jest.headless.config.js
+++ /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.
-
-module.exports = {
-  transform: {},
-  testRegex: '.*_headlesstest.js$',
-  globalSetup: './headless_setup.js',
-  globalTeardown: './headless_teardown.js',
-  testEnvironment: './headless_environment.js'
-}
diff --git a/ui/config/jest.individual.unit.config.js b/ui/config/jest.individual.unit.config.js
deleted file mode 100644
index 7d9d2f5..0000000
--- a/ui/config/jest.individual.unit.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-const path = require('path');
-
-// to be used for running individual unit tests from VsCode or from an IDE
-module.exports = {
-  'roots': [path.dirname(__dirname) + '/src'],
-  'testMatch': ['**/*unittest.ts'],
-  'transform': {'^.+\\.(ts|tsx)$': 'ts-jest'},
-}
diff --git a/ui/config/jest.jsdom.config.js b/ui/config/jest.jsdom.config.js
deleted file mode 100644
index dd07d83..0000000
--- a/ui/config/jest.jsdom.config.js
+++ /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.
-
-module.exports = {
-  transform: {},
-  testRegex: '_jsdomtest.js$',
-  testEnvironment: 'jsdom'
-}
diff --git a/ui/config/jest.unit.config.js b/ui/config/jest.unit.config.js
deleted file mode 100644
index a2ddb95..0000000
--- a/ui/config/jest.unit.config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-module.exports = {
-  transform: {},
-  testRegex: '.*_unittest.js$',
-  testEnvironment: 'node',
-  verbose: true,
-}
diff --git a/ui/config/rollup-serviceworker.config.js b/ui/config/rollup-serviceworker.config.js
deleted file mode 100644
index b7aaf21..0000000
--- a/ui/config/rollup-serviceworker.config.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 commonjs from '@rollup/plugin-commonjs';
-import nodeResolve from '@rollup/plugin-node-resolve';
-import sourcemaps from 'rollup-plugin-sourcemaps';
-
-const path = require('path');
-const ROOT_DIR = path.dirname(path.dirname(__dirname));  // The repo root.
-const OUT_SYMLINK = path.join(ROOT_DIR, 'ui/out');
-
-export default [{
-  input: `${OUT_SYMLINK}/tsc/service_worker/service_worker.js`,
-  output: {
-    name: 'service_worker',
-    format: 'iife',
-    esModule: false,
-    file: `${OUT_SYMLINK}/dist/service_worker.js`,
-    sourcemap: true,
-  },
-  plugins: [
-    nodeResolve({
-      mainFields: ['browser'],
-      browser: true,
-      preferBuiltins: false,
-    }),
-    commonjs(),
-    sourcemaps(),
-  ],
-}]
diff --git a/ui/config/rollup.config.js b/ui/config/rollup.config.js
deleted file mode 100644
index 380aa91..0000000
--- a/ui/config/rollup.config.js
+++ /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 commonjs from '@rollup/plugin-commonjs';
-import nodeResolve from '@rollup/plugin-node-resolve';
-import replace from 'rollup-plugin-re';
-import sourcemaps from 'rollup-plugin-sourcemaps';
-
-const path = require('path');
-const ROOT_DIR = path.dirname(path.dirname(__dirname));  // The repo root.
-const OUT_SYMLINK = path.join(ROOT_DIR, 'ui/out');
-
-function defBundle(bundle, distDir) {
-  return {
-    input: `${OUT_SYMLINK}/tsc/${bundle}/index.js`,
-    output: {
-      name: bundle,
-      format: 'iife',
-      esModule: false,
-      file: `${OUT_SYMLINK}/${distDir}/${bundle}_bundle.js`,
-      sourcemap: true,
-    },
-    plugins: [
-      nodeResolve({
-        mainFields: ['browser'],
-        browser: true,
-        preferBuiltins: false,
-      }),
-      // 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',
-        ]
-      }),
-      // Protobufjs's inquire() uses eval but that's not really needed in
-      // the browser.
-      // See https://github.com/protobufjs/protobuf.js/issues/593
-      replace({
-        patterns: [{test: /eval\(.*\(moduleName\);/g, replace: 'undefined;'}]
-      }),
-      // Translate source maps to point back to the .ts sources.
-      sourcemaps(),
-    ],
-  };
-}
-
-function defServiceWorkerBundle() {
-  return {
-    input: `${OUT_SYMLINK}/tsc/service_worker/service_worker.js`,
-    output: {
-      name: 'service_worker',
-      format: 'iife',
-      esModule: false,
-      file: `${OUT_SYMLINK}/dist/service_worker.js`,
-      sourcemap: true,
-    },
-    plugins: [
-      nodeResolve({
-        mainFields: ['browser'],
-        browser: true,
-        preferBuiltins: false,
-      }),
-      commonjs(),
-      sourcemaps(),
-    ],
-  };
-}
-
-export default [
-  defBundle('frontend', 'dist_version'),
-  defBundle('controller', 'dist_version'),
-  defBundle('engine', 'dist_version'),
-  defBundle('chrome_extension', 'chrome_extension'),
-  defServiceWorkerBundle(),
-]
diff --git a/ui/config/ui_tests_template b/ui/config/ui_tests_template
new file mode 100755
index 0000000..be02a37
--- /dev/null
+++ b/ui/config/ui_tests_template
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+DIR="$(dirname "${BASH_SOURCE[0]}")"
+
+exec ui/node ui/node_modules/jest/bin/jest.js \
+  --projects=ui/jest.unit.config.js \
+  --projects=ui/jest.jsdom.config.js \
+  --projects=ui/jest.headless.config.js \
+  --roots=../$DIR/obj/ui "${@:1}"
+
diff --git a/ui/config/ui_unittests_template b/ui/config/ui_unittests_template
new file mode 100755
index 0000000..8375151
--- /dev/null
+++ b/ui/config/ui_unittests_template
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+DIR="$(dirname "${BASH_SOURCE[0]}")"
+
+exec ui/node ui/node_modules/jest/bin/jest.js \
+  --projects=ui/jest.unit.config.js \
+  --projects=ui/jest.jsdom.config.js \
+  --roots=../$DIR/obj/ui ${@:1}
+
diff --git a/ui/deploy b/ui/deploy
new file mode 100755
index 0000000..d10d188
--- /dev/null
+++ b/ui/deploy
@@ -0,0 +1,122 @@
+#!/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 -e
+
+function echo_and_do {
+  echo $@
+  $@
+}
+
+PROJECT_ROOT="$(cd -P ${BASH_SOURCE[0]%/*}/..; pwd)"
+OUT_DIR="$PROJECT_ROOT/out/ui-deploy.tmp"
+UI_DIST_DIR="$OUT_DIR/ui-dist"
+
+CLEAN_OUT_DIR=true
+DEPLOY_PROD=false
+DEPLOY_STAGING=false
+DEBUG_BUILD=true
+
+while [[ $# -gt 0 ]]; do
+  key="$1"
+  case $key in
+      --no-clean)
+      CLEAN_OUT_DIR=false
+      shift
+      ;;
+      --prod)
+      DEPLOY_PROD=true
+      DEBUG_BUILD=false
+      shift
+      ;;
+      --staging)
+      DEPLOY_STAGING=true
+      shift
+      ;;
+      --release)
+      DEBUG_BUILD=false
+      shift
+      ;;
+      -h|--help)
+      echo "Usage: $0 [--no-clean] [--prod] [--staging]"
+      echo "    --no-clean  Don't remove $OUT_DIR"
+      echo "    --prod      Deploy prod version (implies --release)"
+      echo "    --staging   Deploy staging version"
+      echo "    --release   Do a release build"
+      echo "    -h|--help   Display this message"
+      exit 0
+      shift
+      ;;
+  esac
+done
+
+if [ "$CLEAN_OUT_DIR" = true ]; then
+  echo_and_do rm -rf "$OUT_DIR"
+fi
+echo_and_do mkdir -p "$UI_DIST_DIR"
+
+if [ "$DEBUG_BUILD" = true ]; then
+  echo_and_do "$PROJECT_ROOT/tools/gn" gen "$OUT_DIR" --args="is_debug=true"
+else
+  echo_and_do "$PROJECT_ROOT/tools/gn" gen "$OUT_DIR" --args="is_debug=false"
+fi
+
+echo_and_do "$PROJECT_ROOT/tools/ninja" -C "$OUT_DIR" ui
+
+echo "Writing $UI_DIST_DIR/app.yaml"
+cat<<EOF > "$UI_DIST_DIR/app.yaml"
+runtime: python27
+api_version: 1
+threadsafe: yes
+instance_class: B1
+default_expiration: "1m"
+manual_scaling:
+  instances: 1
+handlers:
+- url: /
+  static_files: static/index.html
+  upload: static/index.html
+  secure: always
+  redirect_http_response_code: 301
+- url: /(.*[.]wasm)
+  static_files: static/\1
+  upload: static/(.*[.]wasm)
+  mime_type: application/wasm
+- url: /assets/(.*)
+  static_files: static/assets/\1
+  upload: static/assets/(.*)
+- url: /(.*)
+  static_files: static/\1
+  upload: static/(.*)
+EOF
+
+echo_and_do ln -fs ../ui $UI_DIST_DIR/static
+
+(
+  echo_and_do cd "$UI_DIST_DIR";
+  if [ "$DEPLOY_PROD" = true ]; then
+    echo_and_do gcloud app deploy app.yaml --project perfetto-ui -v prod
+  elif [ "$DEPLOY_STAGING" = true ]; then
+    echo_and_do gcloud app deploy app.yaml --project perfetto-ui \
+        -v staging --no-promote --stop-previous-version
+  else
+    echo_and_do gcloud app deploy app.yaml --project perfetto-ui \
+        -v $USER --no-promote --stop-previous-version
+  fi
+)
+
+if [ "$CLEAN_OUT_DIR" = true ]; then
+  echo_and_do rm -rf "$OUT_DIR"
+fi
diff --git a/ui/index.html b/ui/index.html
new file mode 100644
index 0000000..a5dbde0
--- /dev/null
+++ b/ui/index.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html lang="en-us">
+<head>
+  <title>Perfetto UI</title>
+  <!-- See b/149573396 for CSP rationale. -->
+  <!-- TODO(b/121211019): remove script-src-elem rule once fixed. -->
+  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src-elem 'self' https://*.google.com https://*.googleusercontent.com; object-src 'none'; connect-src 'self' http://127.0.0.1:9001 https://*.googleapis.com; navigate-to https://*.perfetto.dev;">
+  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
+  <link href="perfetto.css" rel="stylesheet">
+  <link rel="icon" type="image/png" href="assets/favicon.png">
+</head>
+<body>
+  <main>
+    <div class="full-page-loading-screen"></div>
+  </main>
+  <div id="main-modal" aria-hidden="true" class="modal micromodal-slide"></div>
+</body>
+</html>
+<script src="frontend_bundle.js"></script>
+<script src="https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js" async defer></script>
diff --git a/ui/jest.headless.config.js b/ui/jest.headless.config.js
new file mode 100644
index 0000000..e2487b8
--- /dev/null
+++ b/ui/jest.headless.config.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+module.exports = {
+    "transform": {},
+    "testRegex": ".*_headlesstest.js$",
+    "globalSetup": './config/headless_setup.js',
+    "globalTeardown": './config/headless_teardown.js',
+    "testEnvironment": "./config/headless_environment.js"
+}
+
diff --git a/ui/jest.jsdom.config.js b/ui/jest.jsdom.config.js
new file mode 100644
index 0000000..51c9ede
--- /dev/null
+++ b/ui/jest.jsdom.config.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+module.exports = {
+    "transform": {},
+    "testRegex": "_jsdomtest.js$",
+    "testEnvironment": "jsdom"
+}
+
diff --git a/ui/jest.unit.config.js b/ui/jest.unit.config.js
new file mode 100644
index 0000000..a58dcbf
--- /dev/null
+++ b/ui/jest.unit.config.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+module.exports = {
+    "transform": {},
+    "testRegex": "_unittest.js$",
+    "testEnvironment": "node"
+}
+
diff --git a/ui/node b/ui/node
index 8ec17be..d3b679a 100755
--- a/ui/node
+++ b/ui/node
@@ -13,6 +13,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -e -u
-ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
-exec "$ROOT_DIR/tools/node" "$@"
+set -e
+
+readonly ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
+readonly NODE_DIR="$ROOT_DIR/buildtools/nodejs/bin"
+readonly WRAPPER="$ROOT_DIR/gn/standalone/build_tool_wrapper.py"
+
+exec python "$WRAPPER" --path $NODE_DIR node "$@"
+
diff --git a/ui/node_modules/.gitignore b/ui/node_modules/.gitignore
new file mode 100644
index 0000000..05849cd
--- /dev/null
+++ b/ui/node_modules/.gitignore
@@ -0,0 +1,3 @@
+*/
+custom_utils
+.last_install
diff --git a/ui/npm b/ui/npm
index e703031..bcbb8aa 100755
--- a/ui/npm
+++ b/ui/npm
@@ -13,6 +13,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -e -u
-ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
-exec "$ROOT_DIR/tools/npm" "$@"
+set -e
+
+readonly ROOT_DIR="$(dirname $(cd -P ${BASH_SOURCE[0]%/*}; pwd))"
+readonly NODE_DIR="$ROOT_DIR/buildtools/nodejs/bin"
+readonly WRAPPER="$ROOT_DIR/gn/standalone/build_tool_wrapper.py"
+
+exec python "$WRAPPER" --path $NODE_DIR npm "$@"
+
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 4e89a3a..c97de68 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -5,41 +5,71 @@
   "requires": true,
   "dependencies": {
     "@babel/code-frame": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
-      "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
       "dev": true,
       "requires": {
-        "@babel/highlight": "^7.12.13"
+        "@babel/highlight": "^7.0.0"
       }
     },
     "@babel/core": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.13.tgz",
-      "integrity": "sha512-BQKE9kXkPlXHPeqissfxo0lySWJcYdEP0hdtJOH/iJfDdhOCcgtNCjftCJg3qqauB4h+lz2N6ixM++b9DN1Tcw==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.1.tgz",
+      "integrity": "sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.12.13",
-        "@babel/helper-module-transforms": "^7.12.13",
-        "@babel/helpers": "^7.12.13",
-        "@babel/parser": "^7.12.13",
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.12.13",
-        "@babel/types": "^7.12.13",
+        "@babel/code-frame": "^7.10.1",
+        "@babel/generator": "^7.10.1",
+        "@babel/helper-module-transforms": "^7.10.1",
+        "@babel/helpers": "^7.10.1",
+        "@babel/parser": "^7.10.1",
+        "@babel/template": "^7.10.1",
+        "@babel/traverse": "^7.10.1",
+        "@babel/types": "^7.10.1",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.1",
         "json5": "^2.1.2",
-        "lodash": "^4.17.19",
+        "lodash": "^4.17.13",
+        "resolve": "^1.3.2",
         "semver": "^5.4.1",
         "source-map": "^0.5.0"
       },
       "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+        "@babel/code-frame": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
+          "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.1"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
+          "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.1",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         },
         "source-map": {
@@ -51,13 +81,14 @@
       }
     },
     "@babel/generator": {
-      "version": "7.12.15",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.15.tgz",
-      "integrity": "sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.1.tgz",
+      "integrity": "sha512-AT0YPLQw9DI21tliuJIdplVfLHya6mcGa8ctkv7n4Qv+hYacJrKmNWIteAK1P9iyLikFIAkwqJ7HAOqIDLFfgA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13",
+        "@babel/types": "^7.10.1",
         "jsesc": "^2.5.1",
+        "lodash": "^4.17.13",
         "source-map": "^0.5.0"
       },
       "dependencies": {
@@ -70,189 +101,144 @@
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
-      "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz",
+      "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-get-function-arity": "^7.12.13",
-        "@babel/template": "^7.12.13",
-        "@babel/types": "^7.12.13"
+        "@babel/helper-get-function-arity": "^7.10.1",
+        "@babel/template": "^7.10.1",
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
-      "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz",
+      "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-member-expression-to-functions": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz",
-      "integrity": "sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz",
+      "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-module-imports": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz",
-      "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz",
+      "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz",
-      "integrity": "sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz",
+      "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.12.13",
-        "@babel/helper-replace-supers": "^7.12.13",
-        "@babel/helper-simple-access": "^7.12.13",
-        "@babel/helper-split-export-declaration": "^7.12.13",
-        "@babel/helper-validator-identifier": "^7.12.11",
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.12.13",
-        "@babel/types": "^7.12.13",
-        "lodash": "^4.17.19"
+        "@babel/helper-module-imports": "^7.10.1",
+        "@babel/helper-replace-supers": "^7.10.1",
+        "@babel/helper-simple-access": "^7.10.1",
+        "@babel/helper-split-export-declaration": "^7.10.1",
+        "@babel/template": "^7.10.1",
+        "@babel/types": "^7.10.1",
+        "lodash": "^4.17.13"
       }
     },
     "@babel/helper-optimise-call-expression": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz",
-      "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz",
+      "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-plugin-utils": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz",
-      "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz",
+      "integrity": "sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA==",
       "dev": true
     },
     "@babel/helper-replace-supers": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz",
-      "integrity": "sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz",
+      "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==",
       "dev": true,
       "requires": {
-        "@babel/helper-member-expression-to-functions": "^7.12.13",
-        "@babel/helper-optimise-call-expression": "^7.12.13",
-        "@babel/traverse": "^7.12.13",
-        "@babel/types": "^7.12.13"
+        "@babel/helper-member-expression-to-functions": "^7.10.1",
+        "@babel/helper-optimise-call-expression": "^7.10.1",
+        "@babel/traverse": "^7.10.1",
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-simple-access": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz",
-      "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz",
+      "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/template": "^7.10.1",
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
-      "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
+      "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.13"
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/helper-validator-identifier": {
-      "version": "7.12.11",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
-      "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz",
+      "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==",
       "dev": true
     },
     "@babel/helpers": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.13.tgz",
-      "integrity": "sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
+      "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
       "dev": true,
       "requires": {
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.12.13",
-        "@babel/types": "^7.12.13"
+        "@babel/template": "^7.10.1",
+        "@babel/traverse": "^7.10.1",
+        "@babel/types": "^7.10.1"
       }
     },
     "@babel/highlight": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
-      "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
       "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.12.11",
         "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
         "js-tokens": "^4.0.0"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "dev": true,
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
           "dev": true
-        },
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
         }
       }
     },
     "@babel/parser": {
-      "version": "7.12.15",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.15.tgz",
-      "integrity": "sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.1.tgz",
+      "integrity": "sha512-AUTksaz3FqugBkbTZ1i+lDLG5qy8hIzCaAxEtttU6C0BtZZU9pkNZtWSVAht4EW9kl46YBiyTGMp9xTTGqViNg==",
       "dev": true
     },
     "@babel/plugin-syntax-async-generators": {
@@ -274,21 +260,12 @@
       }
     },
     "@babel/plugin-syntax-class-properties": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
-      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz",
+      "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.12.13"
-      }
-    },
-    "@babel/plugin-syntax-import-meta": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
-      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.10.1"
       }
     },
     "@babel/plugin-syntax-json-strings": {
@@ -301,12 +278,12 @@
       }
     },
     "@babel/plugin-syntax-logical-assignment-operators": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
-      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.1.tgz",
+      "integrity": "sha512-XyHIFa9kdrgJS91CUH+ccPVTnJShr8nLGc5bG2IhGXv5p1Rd+8BleGE5yzIg2Nc1QZAdHDa0Qp4m6066OL96Iw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.10.1"
       }
     },
     "@babel/plugin-syntax-nullish-coalescing-operator": {
@@ -319,12 +296,12 @@
       }
     },
     "@babel/plugin-syntax-numeric-separator": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
-      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz",
+      "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.10.1"
       }
     },
     "@babel/plugin-syntax-object-rest-spread": {
@@ -355,41 +332,100 @@
       }
     },
     "@babel/template": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
-      "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz",
+      "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/parser": "^7.12.13",
-        "@babel/types": "^7.12.13"
+        "@babel/code-frame": "^7.10.1",
+        "@babel/parser": "^7.10.1",
+        "@babel/types": "^7.10.1"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
+          "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.1"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
+          "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.1",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        }
       }
     },
     "@babel/traverse": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.13.tgz",
-      "integrity": "sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz",
+      "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.12.13",
-        "@babel/helper-function-name": "^7.12.13",
-        "@babel/helper-split-export-declaration": "^7.12.13",
-        "@babel/parser": "^7.12.13",
-        "@babel/types": "^7.12.13",
+        "@babel/code-frame": "^7.10.1",
+        "@babel/generator": "^7.10.1",
+        "@babel/helper-function-name": "^7.10.1",
+        "@babel/helper-split-export-declaration": "^7.10.1",
+        "@babel/parser": "^7.10.1",
+        "@babel/types": "^7.10.1",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+        "lodash": "^4.17.13"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
+          "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.1"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
+          "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.1",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
       }
     },
     "@babel/types": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.13.tgz",
-      "integrity": "sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ==",
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.1.tgz",
+      "integrity": "sha512-L2yqUOpf3tzlW9GVuipgLEcZxnO+96SzR6fjXMuxxNkIgFJ5+07mHCZ+HkHqaeZu8+3LKnNJJ1bKbjBETQAsrA==",
       "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.12.11",
-        "lodash": "^4.17.19",
+        "@babel/helper-validator-identifier": "^7.10.1",
+        "lodash": "^4.17.13",
         "to-fast-properties": "^2.0.0"
       }
     },
@@ -429,101 +465,236 @@
       "dev": true
     },
     "@jest/console": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.5.0.tgz",
-      "integrity": "sha512-T48kZa6MK1Y6k4b89sexwmSF4YLeZS/Udqg3Jj3jG/cHH+N/sLFCEoXEDMOKugJQ9FxPN1osxIknvKkxt6MKyw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.0.1.tgz",
+      "integrity": "sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
-        "jest-message-util": "^25.5.0",
-        "jest-util": "^25.5.0",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
+        "jest-message-util": "^26.0.1",
+        "jest-util": "^26.0.1",
         "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "@jest/core": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.5.4.tgz",
-      "integrity": "sha512-3uSo7laYxF00Dg/DMgbn4xMJKmDdWvZnf89n8Xj/5/AeQ2dOQmn6b6Hkj/MleyzZWXpwv+WSdYWl4cLsy2JsoA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.0.1.tgz",
+      "integrity": "sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ==",
       "dev": true,
       "requires": {
-        "@jest/console": "^25.5.0",
-        "@jest/reporters": "^25.5.1",
-        "@jest/test-result": "^25.5.0",
-        "@jest/transform": "^25.5.1",
-        "@jest/types": "^25.5.0",
+        "@jest/console": "^26.0.1",
+        "@jest/reporters": "^26.0.1",
+        "@jest/test-result": "^26.0.1",
+        "@jest/transform": "^26.0.1",
+        "@jest/types": "^26.0.1",
         "ansi-escapes": "^4.2.1",
-        "chalk": "^3.0.0",
+        "chalk": "^4.0.0",
         "exit": "^0.1.2",
         "graceful-fs": "^4.2.4",
-        "jest-changed-files": "^25.5.0",
-        "jest-config": "^25.5.4",
-        "jest-haste-map": "^25.5.1",
-        "jest-message-util": "^25.5.0",
-        "jest-regex-util": "^25.2.6",
-        "jest-resolve": "^25.5.1",
-        "jest-resolve-dependencies": "^25.5.4",
-        "jest-runner": "^25.5.4",
-        "jest-runtime": "^25.5.4",
-        "jest-snapshot": "^25.5.1",
-        "jest-util": "^25.5.0",
-        "jest-validate": "^25.5.0",
-        "jest-watcher": "^25.5.0",
+        "jest-changed-files": "^26.0.1",
+        "jest-config": "^26.0.1",
+        "jest-haste-map": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-regex-util": "^26.0.0",
+        "jest-resolve": "^26.0.1",
+        "jest-resolve-dependencies": "^26.0.1",
+        "jest-runner": "^26.0.1",
+        "jest-runtime": "^26.0.1",
+        "jest-snapshot": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jest-validate": "^26.0.1",
+        "jest-watcher": "^26.0.1",
         "micromatch": "^4.0.2",
         "p-each-series": "^2.1.0",
-        "realpath-native": "^2.0.0",
         "rimraf": "^3.0.0",
         "slash": "^3.0.0",
         "strip-ansi": "^6.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "glob": {
+          "version": "7.1.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "@jest/environment": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.5.0.tgz",
-      "integrity": "sha512-U2VXPEqL07E/V7pSZMSQCvV5Ea4lqOlT+0ZFijl/i316cRMHvZ4qC+jBdryd+lmRetjQo0YIQr6cVPNxxK87mA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.0.1.tgz",
+      "integrity": "sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g==",
       "dev": true,
       "requires": {
-        "@jest/fake-timers": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "jest-mock": "^25.5.0"
+        "@jest/fake-timers": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "jest-mock": "^26.0.1"
       }
     },
     "@jest/fake-timers": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.5.0.tgz",
-      "integrity": "sha512-9y2+uGnESw/oyOI3eww9yaxdZyHq7XvprfP/eeoCsjqKYts2yRlsHS/SgjPDV8FyMfn2nbMy8YzUk6nyvdLOpQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.0.1.tgz",
+      "integrity": "sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "jest-message-util": "^25.5.0",
-        "jest-mock": "^25.5.0",
-        "jest-util": "^25.5.0",
-        "lolex": "^5.0.0"
+        "@jest/types": "^26.0.1",
+        "@sinonjs/fake-timers": "^6.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-mock": "^26.0.1",
+        "jest-util": "^26.0.1"
       }
     },
     "@jest/globals": {
-      "version": "25.5.2",
-      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-25.5.2.tgz",
-      "integrity": "sha512-AgAS/Ny7Q2RCIj5kZ+0MuKM1wbF0WMLxbCVl/GOMoCNbODRdJ541IxJ98xnZdVSZXivKpJlNPIWa3QmY0l4CXA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.0.1.tgz",
+      "integrity": "sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "expect": "^25.5.0"
+        "@jest/environment": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "expect": "^26.0.1"
       }
     },
     "@jest/reporters": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.5.1.tgz",
-      "integrity": "sha512-3jbd8pPDTuhYJ7vqiHXbSwTJQNavczPs+f1kRprRDxETeE3u6srJ+f0NPuwvOmk+lmunZzPkYWIFZDLHQPkviw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.0.1.tgz",
+      "integrity": "sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g==",
       "dev": true,
       "requires": {
         "@bcoe/v8-coverage": "^0.2.3",
-        "@jest/console": "^25.5.0",
-        "@jest/test-result": "^25.5.0",
-        "@jest/transform": "^25.5.1",
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
+        "@jest/console": "^26.0.1",
+        "@jest/test-result": "^26.0.1",
+        "@jest/transform": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
         "collect-v8-coverage": "^1.0.0",
         "exit": "^0.1.2",
         "glob": "^7.1.2",
@@ -533,88 +704,253 @@
         "istanbul-lib-report": "^3.0.0",
         "istanbul-lib-source-maps": "^4.0.0",
         "istanbul-reports": "^3.0.2",
-        "jest-haste-map": "^25.5.1",
-        "jest-resolve": "^25.5.1",
-        "jest-util": "^25.5.0",
-        "jest-worker": "^25.5.0",
-        "node-notifier": "^6.0.0",
+        "jest-haste-map": "^26.0.1",
+        "jest-resolve": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jest-worker": "^26.0.0",
+        "node-notifier": "^7.0.0",
         "slash": "^3.0.0",
         "source-map": "^0.6.0",
-        "string-length": "^3.1.0",
+        "string-length": "^4.0.1",
         "terminal-link": "^2.0.0",
         "v8-to-istanbul": "^4.1.3"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "@jest/source-map": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.5.0.tgz",
-      "integrity": "sha512-eIGx0xN12yVpMcPaVpjXPnn3N30QGJCJQSkEDUt9x1fI1Gdvb07Ml6K5iN2hG7NmMP6FDmtPEssE3z6doOYUwQ==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.0.0.tgz",
+      "integrity": "sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ==",
       "dev": true,
       "requires": {
         "callsites": "^3.0.0",
         "graceful-fs": "^4.2.4",
         "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        }
       }
     },
     "@jest/test-result": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.5.0.tgz",
-      "integrity": "sha512-oV+hPJgXN7IQf/fHWkcS99y0smKLU2czLBJ9WA0jHITLst58HpQMtzSYxzaBvYc6U5U6jfoMthqsUlUlbRXs0A==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.0.1.tgz",
+      "integrity": "sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg==",
       "dev": true,
       "requires": {
-        "@jest/console": "^25.5.0",
-        "@jest/types": "^25.5.0",
+        "@jest/console": "^26.0.1",
+        "@jest/types": "^26.0.1",
         "@types/istanbul-lib-coverage": "^2.0.0",
         "collect-v8-coverage": "^1.0.0"
       }
     },
     "@jest/test-sequencer": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.5.4.tgz",
-      "integrity": "sha512-pTJGEkSeg1EkCO2YWq6hbFvKNXk8ejqlxiOg1jBNLnWrgXOkdY6UmqZpwGFXNnRt9B8nO1uWMzLLZ4eCmhkPNA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz",
+      "integrity": "sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^25.5.0",
+        "@jest/test-result": "^26.0.1",
         "graceful-fs": "^4.2.4",
-        "jest-haste-map": "^25.5.1",
-        "jest-runner": "^25.5.4",
-        "jest-runtime": "^25.5.4"
+        "jest-haste-map": "^26.0.1",
+        "jest-runner": "^26.0.1",
+        "jest-runtime": "^26.0.1"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        }
       }
     },
     "@jest/transform": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.5.1.tgz",
-      "integrity": "sha512-Y8CEoVwXb4QwA6Y/9uDkn0Xfz0finGkieuV0xkdF9UtZGJeLukD5nLkaVrVsODB1ojRWlaoD0AJZpVHCSnJEvg==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.0.1.tgz",
+      "integrity": "sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/types": "^25.5.0",
+        "@jest/types": "^26.0.1",
         "babel-plugin-istanbul": "^6.0.0",
-        "chalk": "^3.0.0",
+        "chalk": "^4.0.0",
         "convert-source-map": "^1.4.0",
         "fast-json-stable-stringify": "^2.0.0",
         "graceful-fs": "^4.2.4",
-        "jest-haste-map": "^25.5.1",
-        "jest-regex-util": "^25.2.6",
-        "jest-util": "^25.5.0",
+        "jest-haste-map": "^26.0.1",
+        "jest-regex-util": "^26.0.0",
+        "jest-util": "^26.0.1",
         "micromatch": "^4.0.2",
         "pirates": "^4.0.1",
-        "realpath-native": "^2.0.0",
         "slash": "^3.0.0",
         "source-map": "^0.6.1",
         "write-file-atomic": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "@jest/types": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz",
-      "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.0.1.tgz",
+      "integrity": "sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.0",
         "@types/istanbul-reports": "^1.1.1",
         "@types/yargs": "^15.0.0",
-        "chalk": "^3.0.0"
+        "chalk": "^4.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "@protobufjs/aspromise": {
@@ -671,65 +1007,33 @@
       "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
       "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
     },
-    "@rollup/plugin-commonjs": {
-      "version": "14.0.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz",
-      "integrity": "sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw==",
-      "dev": true,
-      "requires": {
-        "@rollup/pluginutils": "^3.0.8",
-        "commondir": "^1.0.1",
-        "estree-walker": "^1.0.1",
-        "glob": "^7.1.2",
-        "is-reference": "^1.1.2",
-        "magic-string": "^0.25.2",
-        "resolve": "^1.11.0"
-      }
-    },
-    "@rollup/plugin-node-resolve": {
-      "version": "8.4.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz",
-      "integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==",
-      "dev": true,
-      "requires": {
-        "@rollup/pluginutils": "^3.1.0",
-        "@types/resolve": "1.17.1",
-        "builtin-modules": "^3.1.0",
-        "deep-freeze": "^0.0.1",
-        "deepmerge": "^4.2.2",
-        "is-module": "^1.0.0",
-        "resolve": "^1.17.0"
-      }
-    },
-    "@rollup/pluginutils": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
-      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
-      "dev": true,
-      "requires": {
-        "@types/estree": "0.0.39",
-        "estree-walker": "^1.0.1",
-        "picomatch": "^2.2.2"
-      }
-    },
     "@sinonjs/commons": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
-      "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz",
+      "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==",
       "dev": true,
       "requires": {
         "type-detect": "4.0.8"
       }
     },
+    "@sinonjs/fake-timers": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
+      "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
+      "dev": true,
+      "requires": {
+        "@sinonjs/commons": "^1.7.0"
+      }
+    },
     "@tsundoku/micromodal_types": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/@tsundoku/micromodal_types/-/micromodal_types-0.0.1.tgz",
       "integrity": "sha512-9k95tyHczZp/Uwu7SysnekpA2/o/y5gb/jMwqoLuTlJqwIVwnxfpsfmxc/bMfHnct7ESSqmRUJ1qYnUPD9Z7og=="
     },
     "@types/babel__core": {
-      "version": "7.1.12",
-      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
-      "integrity": "sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==",
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz",
+      "integrity": "sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==",
       "dev": true,
       "requires": {
         "@babel/parser": "^7.1.0",
@@ -740,18 +1044,18 @@
       }
     },
     "@types/babel__generator": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz",
-      "integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==",
+      "version": "7.6.1",
+      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz",
+      "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.0.0"
       }
     },
     "@types/babel__template": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz",
-      "integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==",
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz",
+      "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==",
       "dev": true,
       "requires": {
         "@babel/parser": "^7.1.0",
@@ -759,9 +1063,9 @@
       }
     },
     "@types/babel__traverse": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.0.tgz",
-      "integrity": "sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==",
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.11.tgz",
+      "integrity": "sha512-ddHK5icION5U6q11+tV2f9Mo6CZVuT8GJKld2q9LqHSZbvLbH34Kcu2yFGckZut453+eQU6btIA3RihmnRgI+Q==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.3.0"
@@ -789,9 +1093,9 @@
       "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
     },
     "@types/estree": {
-      "version": "0.0.39",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
-      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "version": "0.0.44",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.44.tgz",
+      "integrity": "sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g==",
       "dev": true
     },
     "@types/filesystem": {
@@ -808,18 +1112,18 @@
       "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM="
     },
     "@types/graceful-fs": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz",
-      "integrity": "sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg==",
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz",
+      "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==",
       "dev": true,
       "requires": {
         "@types/node": "*"
       }
     },
     "@types/istanbul-lib-coverage": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
-      "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz",
+      "integrity": "sha512-rsZg7eL+Xcxsxk2XlBt9KcG8nOp9iYdKCOikY9x2RFJCyOdNj4MKPQty0e8oZr29vVAzKXr1BmR+kZauti3o1w==",
       "dev": true
     },
     "@types/istanbul-lib-report": {
@@ -858,9 +1162,9 @@
       "integrity": "sha512-U/wwKZT8hjstY2Q470bLMGVh/fjT2+SgBMzIILn0Z4nmgzzG6j+n18UOAxQ63aI8vXIOkQsbkAdbESt8+jIQdQ=="
     },
     "@types/node": {
-      "version": "14.14.25",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
-      "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ=="
+      "version": "14.0.10",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.10.tgz",
+      "integrity": "sha512-Bz23oN/5bi0rniKT24ExLf4cK0JdvN3dH/3k0whYkdN4eI4vS2ZW/2ENNn2uxHCzWcbdHIa/GRuWQytfzCjRYw=="
     },
     "@types/normalize-package-data": {
       "version": "2.4.0",
@@ -874,24 +1178,24 @@
       "integrity": "sha512-GdZbRSJ3Cv5fiwT6I0SQ3ckeN2PWNqxd26W9Z2fCK1tGrrasGy4puvNFtnddqH9UJFMQYXxEuuB7B8UK+LLwSg=="
     },
     "@types/prettier": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz",
-      "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.1.tgz",
+      "integrity": "sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ==",
       "dev": true
     },
     "@types/puppeteer": {
-      "version": "1.20.7",
-      "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.20.7.tgz",
-      "integrity": "sha512-LCfP/Zf/y4I/hG8ARR8htPYa1wpLpUkysJo9TffmQssVz8c1b9uDNU4benDHSldiz7HVAMek1DCWz7KbqEUg3w==",
+      "version": "1.20.6",
+      "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.20.6.tgz",
+      "integrity": "sha512-ITkr6Z2qvCiDZFB3Y+VYt+uOzqxitr1HehAn+t/PoNNZAsX+LnovMaqFYg99pvkP18AvZdAqKNMhd8JaQIEWUA==",
       "dev": true,
       "requires": {
         "@types/node": "*"
       }
     },
     "@types/resolve": {
-      "version": "1.17.1",
-      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
-      "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
+      "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
       "dev": true,
       "requires": {
         "@types/node": "*"
@@ -914,60 +1218,51 @@
       "integrity": "sha512-aaOB3EL5WCWBBOYX7W1MKuzspOM9ZJI9s3iziRVypr1N+QyvIgXzCM4lm1iiOQ1VFzZioUPX9bsa23myCbKK4A=="
     },
     "@types/yargs": {
-      "version": "15.0.13",
-      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz",
-      "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==",
+      "version": "15.0.5",
+      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz",
+      "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==",
       "dev": true,
       "requires": {
         "@types/yargs-parser": "*"
       }
     },
     "@types/yargs-parser": {
-      "version": "20.2.0",
-      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz",
-      "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
+      "version": "15.0.0",
+      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
+      "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
       "dev": true
     },
     "abab": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
-      "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
+      "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
       "dev": true
     },
     "abbrev": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-      "dev": true
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
     },
     "acorn": {
-      "version": "7.4.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
-      "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz",
+      "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==",
       "dev": true
     },
     "acorn-globals": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
-      "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
+      "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
       "dev": true,
       "requires": {
-        "acorn": "^6.0.1",
-        "acorn-walk": "^6.0.1"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "6.4.2",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
-          "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
-          "dev": true
-        }
+        "acorn": "^7.1.1",
+        "acorn-walk": "^7.1.1"
       }
     },
     "acorn-walk": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
-      "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
+      "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
       "dev": true
     },
     "agent-base": {
@@ -980,12 +1275,12 @@
       }
     },
     "ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
+      "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
       "dev": true,
       "requires": {
-        "fast-deep-equal": "^3.1.1",
+        "fast-deep-equal": "^2.0.1",
         "fast-json-stable-stringify": "^2.0.0",
         "json-schema-traverse": "^0.4.1",
         "uri-js": "^4.2.2"
@@ -1015,18 +1310,34 @@
       }
     },
     "ansi-regex": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-      "dev": true
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
     },
     "ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
       "dev": true,
       "requires": {
-        "color-convert": "^2.0.1"
+        "color-convert": "^1.9.0"
+      },
+      "dependencies": {
+        "color-convert": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+          "dev": true
+        }
       }
     },
     "anymatch": {
@@ -1042,14 +1353,12 @@
     "aproba": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-      "dev": true
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
     },
     "are-we-there-yet": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
       "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
-      "dev": true,
       "requires": {
         "delegates": "^1.0.0",
         "readable-stream": "^2.0.6"
@@ -1082,12 +1391,6 @@
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
       "dev": true
     },
-    "array-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
-      "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
-      "dev": true
-    },
     "array-filter": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
@@ -1126,12 +1429,6 @@
       "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
       "dev": true
     },
-    "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
-      "dev": true
-    },
     "async-foreach": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
@@ -1171,25 +1468,77 @@
       "dev": true
     },
     "aws4": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
-      "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
       "dev": true
     },
     "babel-jest": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.5.1.tgz",
-      "integrity": "sha512-9dA9+GmMjIzgPnYtkhBg73gOo/RHqPmLruP3BaGL4KEX3Dwz6pI8auSN8G8+iuEG90+GSswyKvslN+JYSaacaQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.0.1.tgz",
+      "integrity": "sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw==",
       "dev": true,
       "requires": {
-        "@jest/transform": "^25.5.1",
-        "@jest/types": "^25.5.0",
+        "@jest/transform": "^26.0.1",
+        "@jest/types": "^26.0.1",
         "@types/babel__core": "^7.1.7",
         "babel-plugin-istanbul": "^6.0.0",
-        "babel-preset-jest": "^25.5.0",
-        "chalk": "^3.0.0",
+        "babel-preset-jest": "^26.0.0",
+        "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "babel-plugin-istanbul": {
@@ -1206,9 +1555,9 @@
       }
     },
     "babel-plugin-jest-hoist": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.5.0.tgz",
-      "integrity": "sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz",
+      "integrity": "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.3.3",
@@ -1217,15 +1566,14 @@
       }
     },
     "babel-preset-current-node-syntax": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz",
-      "integrity": "sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==",
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz",
+      "integrity": "sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw==",
       "dev": true,
       "requires": {
         "@babel/plugin-syntax-async-generators": "^7.8.4",
         "@babel/plugin-syntax-bigint": "^7.8.3",
         "@babel/plugin-syntax-class-properties": "^7.8.3",
-        "@babel/plugin-syntax-import-meta": "^7.8.3",
         "@babel/plugin-syntax-json-strings": "^7.8.3",
         "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
@@ -1236,20 +1584,19 @@
       }
     },
     "babel-preset-jest": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.5.0.tgz",
-      "integrity": "sha512-8ZczygctQkBU+63DtSOKGh7tFL0CeCuz+1ieud9lJ1WPQ9O6A1a/r+LGn6Y705PA6whHQ3T1XuB/PmpfNYf8Fw==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz",
+      "integrity": "sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw==",
       "dev": true,
       "requires": {
-        "babel-plugin-jest-hoist": "^25.5.0",
+        "babel-plugin-jest-hoist": "^26.0.0",
         "babel-preset-current-node-syntax": "^0.1.2"
       }
     },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-      "dev": true
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
     "base": {
       "version": "0.11.2",
@@ -1328,7 +1675,6 @@
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
       "requires": {
         "balanced-match": "^1.0.0",
         "concat-map": "0.0.1"
@@ -1349,32 +1695,6 @@
       "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
       "dev": true
     },
-    "browser-resolve": {
-      "version": "1.11.3",
-      "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",
-      "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",
-      "dev": true,
-      "requires": {
-        "resolve": "1.1.7"
-      },
-      "dependencies": {
-        "resolve": {
-          "version": "1.1.7",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
-          "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
-          "dev": true
-        }
-      }
-    },
-    "bs-logger": {
-      "version": "0.2.6",
-      "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
-      "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
-      "dev": true,
-      "requires": {
-        "fast-json-stable-stringify": "2.x"
-      }
-    },
     "bser": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
@@ -1396,10 +1716,18 @@
       "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
       "dev": true
     },
+    "bufferutil": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz",
+      "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==",
+      "requires": {
+        "node-gyp-build": "~3.7.0"
+      }
+    },
     "builtin-modules": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
-      "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
+      "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
       "dev": true
     },
     "cache-base": {
@@ -1419,15 +1747,6 @@
         "unset-value": "^1.0.0"
       }
     },
-    "call-bind": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2"
-      }
-    },
     "callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1458,6 +1777,16 @@
         }
       }
     },
+    "canvas": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz",
+      "integrity": "sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==",
+      "requires": {
+        "nan": "^2.14.0",
+        "node-pre-gyp": "^0.11.0",
+        "simple-get": "^3.0.3"
+      }
+    },
     "capture-exit": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
@@ -1474,15 +1803,27 @@
       "dev": true
     },
     "chalk": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
       "dev": true,
       "requires": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
       }
     },
+    "char-regex": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+      "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+      "dev": true
+    },
+    "chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+    },
     "ci-info": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -1521,6 +1862,46 @@
         "string-width": "^4.2.0",
         "strip-ansi": "^6.0.0",
         "wrap-ansi": "^6.2.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        }
       }
     },
     "co": {
@@ -1532,8 +1913,7 @@
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
-      "dev": true
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
     },
     "collect-v8-coverage": {
       "version": "1.0.1",
@@ -1565,9 +1945,9 @@
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "combined-stream": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
       "dev": true,
       "requires": {
         "delayed-stream": "~1.0.0"
@@ -1579,12 +1959,6 @@
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true
     },
-    "commondir": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
-      "dev": true
-    },
     "component-emitter": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
@@ -1594,8 +1968,7 @@
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "dev": true
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
     "concat-stream": {
       "version": "1.6.2",
@@ -1612,8 +1985,7 @@
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
-      "dev": true
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
     },
     "convert-source-map": {
       "version": "1.7.0",
@@ -1622,14 +1994,6 @@
       "dev": true,
       "requires": {
         "safe-buffer": "~5.1.1"
-      },
-      "dependencies": {
-        "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==",
-          "dev": true
-        }
       }
     },
     "copy-descriptor": {
@@ -1641,8 +2005,7 @@
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "cross-spawn": {
       "version": "6.0.5",
@@ -1655,23 +2018,6 @@
         "semver": "^5.5.0",
         "shebang-command": "^1.2.0",
         "which": "^1.2.9"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
-        }
       }
     },
     "cssom": {
@@ -1719,23 +2065,23 @@
       }
     },
     "data-urls": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
-      "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
+      "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==",
       "dev": true,
       "requires": {
-        "abab": "^2.0.0",
-        "whatwg-mimetype": "^2.2.0",
-        "whatwg-url": "^7.0.0"
+        "abab": "^2.0.3",
+        "whatwg-mimetype": "^2.3.0",
+        "whatwg-url": "^8.0.0"
       }
     },
     "debug": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
-      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
       "dev": true,
       "requires": {
-        "ms": "2.1.2"
+        "ms": "2.0.0"
       }
     },
     "decamelize": {
@@ -1744,17 +2090,30 @@
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
+    "decimal.js": {
+      "version": "10.2.0",
+      "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz",
+      "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==",
+      "dev": true
+    },
     "decode-uri-component": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
       "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
       "dev": true
     },
-    "deep-freeze": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
-      "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=",
-      "dev": true
+    "decompress-response": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
+      "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+      "requires": {
+        "mimic-response": "^2.0.0"
+      }
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
     },
     "deep-is": {
       "version": "0.1.3",
@@ -1826,8 +2185,12 @@
     "delegates": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
-      "dev": true
+      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+    },
+    "detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
     },
     "detect-newline": {
       "version": "3.1.0",
@@ -1836,9 +2199,9 @@
       "dev": true
     },
     "devtools-protocol": {
-      "version": "0.0.847576",
-      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.847576.tgz",
-      "integrity": "sha512-0M8kobnSQE0Jmly7Mhbeq0W/PpZfnuK+WjN2ZRVPbGqYwCHCioAVp84H0TcLimgECcN5H976y5QiXMGBC9JKmg=="
+      "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": "4.0.2",
@@ -1847,9 +2210,9 @@
       "dev": true
     },
     "diff-sequences": {
-      "version": "25.2.6",
-      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz",
-      "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz",
+      "integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==",
       "dev": true
     },
     "dingusjs": {
@@ -1859,12 +2222,20 @@
       "dev": true
     },
     "domexception": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
-      "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
+      "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==",
       "dev": true,
       "requires": {
-        "webidl-conversions": "^4.0.2"
+        "webidl-conversions": "^5.0.0"
+      },
+      "dependencies": {
+        "webidl-conversions": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+          "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+          "dev": true
+        }
       }
     },
     "ecc-jsbn": {
@@ -1878,9 +2249,9 @@
       }
     },
     "emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
       "dev": true
     },
     "end-of-stream": {
@@ -1902,24 +2273,21 @@
       }
     },
     "es-abstract": {
-      "version": "1.18.0-next.2",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
-      "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
+      "version": "1.17.5",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+      "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
       "requires": {
-        "call-bind": "^1.0.2",
         "es-to-primitive": "^1.2.1",
         "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2",
         "has": "^1.0.3",
         "has-symbols": "^1.0.1",
-        "is-callable": "^1.2.2",
-        "is-negative-zero": "^2.0.1",
-        "is-regex": "^1.1.1",
-        "object-inspect": "^1.9.0",
+        "is-callable": "^1.1.5",
+        "is-regex": "^1.0.5",
+        "object-inspect": "^1.7.0",
         "object-keys": "^1.1.1",
-        "object.assign": "^4.1.2",
-        "string.prototype.trimend": "^1.0.3",
-        "string.prototype.trimstart": "^1.0.3"
+        "object.assign": "^4.1.0",
+        "string.prototype.trimleft": "^2.1.1",
+        "string.prototype.trimright": "^2.1.1"
       }
     },
     "es-to-primitive": {
@@ -1933,9 +2301,9 @@
       }
     },
     "es6-promise": {
-      "version": "4.2.8",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
-      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
+      "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
       "dev": true
     },
     "es6-promisify": {
@@ -1945,6 +2313,14 @@
       "dev": true,
       "requires": {
         "es6-promise": "^4.0.3"
+      },
+      "dependencies": {
+        "es6-promise": {
+          "version": "4.2.8",
+          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+          "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+          "dev": true
+        }
       }
     },
     "escape-string-regexp": {
@@ -1954,9 +2330,9 @@
       "dev": true
     },
     "escodegen": {
-      "version": "1.14.3",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
-      "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
+      "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
       "dev": true,
       "requires": {
         "esprima": "^4.0.1",
@@ -1979,21 +2355,21 @@
       "dev": true
     },
     "estree-walker": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
-      "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz",
+      "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==",
       "dev": true
     },
     "esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
       "dev": true
     },
     "events": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
-      "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg=="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+      "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg=="
     },
     "exec-sh": {
       "version": "0.3.4",
@@ -2037,15 +2413,6 @@
         "to-regex": "^3.0.1"
       },
       "dependencies": {
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -2063,27 +2430,42 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
         }
       }
     },
     "expect": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/expect/-/expect-25.5.0.tgz",
-      "integrity": "sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-26.0.1.tgz",
+      "integrity": "sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
+        "@jest/types": "^26.0.1",
         "ansi-styles": "^4.0.0",
-        "jest-get-type": "^25.2.6",
-        "jest-matcher-utils": "^25.5.0",
-        "jest-message-util": "^25.5.0",
-        "jest-regex-util": "^25.2.6"
+        "jest-get-type": "^26.0.0",
+        "jest-matcher-utils": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-regex-util": "^26.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        }
       }
     },
     "extend": {
@@ -2188,23 +2570,6 @@
         "debug": "^2.6.9",
         "mkdirp": "^0.5.4",
         "yauzl": "^2.10.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        }
       }
     },
     "extsprintf": {
@@ -2214,15 +2579,15 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
       "dev": true
     },
     "fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
       "dev": true
     },
     "fast-levenshtein": {
@@ -2266,6 +2631,14 @@
       "requires": {
         "locate-path": "^5.0.0",
         "path-exists": "^4.0.0"
+      },
+      "dependencies": {
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        }
       }
     },
     "for-in": {
@@ -2305,16 +2678,23 @@
         "map-cache": "^0.2.2"
       }
     },
+    "fs-minipass": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+      "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+      "requires": {
+        "minipass": "^2.6.0"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-      "dev": true
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "fsevents": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
       "dev": true,
       "optional": true
     },
@@ -2328,17 +2708,6 @@
         "inherits": "~2.0.0",
         "mkdirp": ">=0.5 0",
         "rimraf": "2"
-      },
-      "dependencies": {
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        }
       }
     },
     "function-bind": {
@@ -2350,7 +2719,6 @@
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
       "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
-      "dev": true,
       "requires": {
         "aproba": "^1.0.3",
         "console-control-strings": "^1.0.0",
@@ -2362,17 +2730,10 @@
         "wide-align": "^1.1.0"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true
-        },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
           "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-          "dev": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -2381,7 +2742,6 @@
           "version": "1.0.2",
           "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
           "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-          "dev": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -2392,7 +2752,6 @@
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -2409,9 +2768,9 @@
       }
     },
     "gensync": {
-      "version": "1.0.0-beta.2",
-      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
-      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "version": "1.0.0-beta.1",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+      "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
       "dev": true
     },
     "get-caller-file": {
@@ -2420,16 +2779,6 @@
       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
       "dev": true
     },
-    "get-intrinsic": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
-      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.1"
-      }
-    },
     "get-package-type": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@@ -2467,10 +2816,9 @@
       }
     },
     "glob": {
-      "version": "7.1.6",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
-      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
-      "dev": true,
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
       "requires": {
         "fs.realpath": "^1.0.0",
         "inflight": "^1.0.4",
@@ -2487,20 +2835,20 @@
       "dev": true
     },
     "globule": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
-      "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz",
+      "integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==",
       "dev": true,
       "requires": {
         "glob": "~7.1.1",
-        "lodash": "~4.17.10",
+        "lodash": "~4.17.12",
         "minimatch": "~3.0.2"
       }
     },
     "graceful-fs": {
-      "version": "4.2.5",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.5.tgz",
-      "integrity": "sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw==",
+      "version": "4.1.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
       "dev": true
     },
     "growly": {
@@ -2517,12 +2865,12 @@
       "dev": true
     },
     "har-validator": {
-      "version": "5.1.5",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
-      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
       "dev": true,
       "requires": {
-        "ajv": "^6.12.3",
+        "ajv": "^6.5.5",
         "har-schema": "^2.0.0"
       }
     },
@@ -2541,20 +2889,12 @@
       "dev": true,
       "requires": {
         "ansi-regex": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true
-        }
       }
     },
     "has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
       "dev": true
     },
     "has-symbols": {
@@ -2565,8 +2905,7 @@
     "has-unicode": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
-      "dev": true
+      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
     },
     "has-value": {
       "version": "1.0.0",
@@ -2621,23 +2960,18 @@
       }
     },
     "hosted-git-info": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-      "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
       "dev": true
     },
-    "hsluv": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/hsluv/-/hsluv-0.1.0.tgz",
-      "integrity": "sha512-ERcanKLAszD2XN3Vh5r5Szkrv9q0oSTudmP0rkiKAGM/3NMc9FLmMZBB7TSqTaXJfSDBOreYTfjezCOYbRKqlw=="
-    },
     "html-encoding-sniffer": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
-      "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
+      "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==",
       "dev": true,
       "requires": {
-        "whatwg-encoding": "^1.0.1"
+        "whatwg-encoding": "^1.0.5"
       }
     },
     "html-escaper": {
@@ -2668,13 +3002,19 @@
       },
       "dependencies": {
         "debug": {
-          "version": "3.2.7",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-          "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
           "dev": true,
           "requires": {
             "ms": "^2.1.1"
           }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
         }
       }
     },
@@ -2688,11 +3028,18 @@
       "version": "0.4.24",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "dev": true,
       "requires": {
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
+    "ignore-walk": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+      "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+      "requires": {
+        "minimatch": "^3.0.4"
+      }
+    },
     "immer": {
       "version": "1.12.1",
       "resolved": "https://registry.npmjs.org/immer/-/immer-1.12.1.tgz",
@@ -2733,16 +3080,20 @@
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true,
       "requires": {
         "once": "^1.3.0",
         "wrappy": "1"
       }
     },
     "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
     },
     "ip-regex": {
       "version": "2.1.0",
@@ -2771,12 +3122,9 @@
       }
     },
     "is-arguments": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
-      "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
-      "requires": {
-        "call-bind": "^1.0.0"
-      }
+      "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",
@@ -2791,9 +3139,9 @@
       "dev": true
     },
     "is-callable": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
-      "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+      "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
     },
     "is-ci": {
       "version": "2.0.0",
@@ -2804,15 +3152,6 @@
         "ci-info": "^2.0.0"
       }
     },
-    "is-core-module": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
-      "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
-      "dev": true,
-      "requires": {
-        "has": "^1.0.3"
-      }
-    },
     "is-data-descriptor": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
@@ -2858,9 +3197,9 @@
       }
     },
     "is-docker": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
-      "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz",
+      "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==",
       "dev": true,
       "optional": true
     },
@@ -2871,16 +3210,18 @@
       "dev": true
     },
     "is-finite": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
-      "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
-      "dev": true
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
     },
     "is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
     },
     "is-generator-fn": {
       "version": "2.1.0",
@@ -2889,9 +3230,9 @@
       "dev": true
     },
     "is-generator-function": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz",
-      "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ=="
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
+      "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
     },
     "is-module": {
       "version": "1.0.0",
@@ -2899,11 +3240,6 @@
       "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
       "dev": true
     },
-    "is-negative-zero": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
-      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
-    },
     "is-number": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -2919,22 +3255,18 @@
         "isobject": "^3.0.1"
       }
     },
-    "is-reference": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
-      "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
-      "dev": true,
-      "requires": {
-        "@types/estree": "*"
-      }
+    "is-potential-custom-element-name": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz",
+      "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=",
+      "dev": true
     },
     "is-regex": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
-      "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+      "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
       "requires": {
-        "call-bind": "^1.0.2",
-        "has-symbols": "^1.0.1"
+        "has": "^1.0.3"
       }
     },
     "is-stream": {
@@ -2952,13 +3284,12 @@
       }
     },
     "is-typed-array": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.4.tgz",
-      "integrity": "sha512-ILaRgn4zaSrVNXNGtON6iFNotXW3hAPF3+0fB1usg2jFlWqo5fEDdmJkz0zBfoi7Dgskr8Khi2xZ8cXqZEfXNA==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz",
+      "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==",
       "requires": {
-        "available-typed-arrays": "^1.0.2",
-        "call-bind": "^1.0.0",
-        "es-abstract": "^1.18.0-next.1",
+        "available-typed-arrays": "^1.0.0",
+        "es-abstract": "^1.17.4",
         "foreach": "^2.0.5",
         "has-symbols": "^1.0.1"
       }
@@ -2994,8 +3325,7 @@
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
     },
     "isexe": {
       "version": "2.0.0",
@@ -3031,6 +3361,14 @@
         "@istanbuljs/schema": "^0.1.2",
         "istanbul-lib-coverage": "^3.0.0",
         "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
       }
     },
     "istanbul-lib-report": {
@@ -3042,6 +3380,23 @@
         "istanbul-lib-coverage": "^3.0.0",
         "make-dir": "^3.0.0",
         "supports-color": "^7.1.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "istanbul-lib-source-maps": {
@@ -3053,6 +3408,23 @@
         "debug": "^4.1.1",
         "istanbul-lib-coverage": "^3.0.0",
         "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
       }
     },
     "istanbul-reports": {
@@ -3066,48 +3438,97 @@
       }
     },
     "jest": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest/-/jest-25.5.4.tgz",
-      "integrity": "sha512-hHFJROBTqZahnO+X+PMtT6G2/ztqAZJveGqz//FnWWHurizkD05PQGzRZOhF3XP6z7SJmL+5tCfW8qV06JypwQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest/-/jest-26.0.1.tgz",
+      "integrity": "sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg==",
       "dev": true,
       "requires": {
-        "@jest/core": "^25.5.4",
+        "@jest/core": "^26.0.1",
         "import-local": "^3.0.2",
-        "jest-cli": "^25.5.4"
+        "jest-cli": "^26.0.1"
       },
       "dependencies": {
-        "jest-cli": {
-          "version": "25.5.4",
-          "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.5.4.tgz",
-          "integrity": "sha512-rG8uJkIiOUpnREh1768/N3n27Cm+xPFkSNFO91tgg+8o2rXeVLStz+vkXkGr4UtzH6t1SNbjwoiswd7p4AhHTw==",
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
           "dev": true,
           "requires": {
-            "@jest/core": "^25.5.4",
-            "@jest/test-result": "^25.5.0",
-            "@jest/types": "^25.5.0",
-            "chalk": "^3.0.0",
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "jest-cli": {
+          "version": "26.0.1",
+          "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.0.1.tgz",
+          "integrity": "sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w==",
+          "dev": true,
+          "requires": {
+            "@jest/core": "^26.0.1",
+            "@jest/test-result": "^26.0.1",
+            "@jest/types": "^26.0.1",
+            "chalk": "^4.0.0",
             "exit": "^0.1.2",
             "graceful-fs": "^4.2.4",
             "import-local": "^3.0.2",
             "is-ci": "^2.0.0",
-            "jest-config": "^25.5.4",
-            "jest-util": "^25.5.0",
-            "jest-validate": "^25.5.0",
+            "jest-config": "^26.0.1",
+            "jest-util": "^26.0.1",
+            "jest-validate": "^26.0.1",
             "prompts": "^2.0.1",
-            "realpath-native": "^2.0.0",
             "yargs": "^15.3.1"
           }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
         }
       }
     },
     "jest-changed-files": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.5.0.tgz",
-      "integrity": "sha512-EOw9QEqapsDT7mKF162m8HFzRPbmP8qJQny6ldVOdOVBz3ACgPm/1nAn5fPQ/NDaYhX/AHkrGwwkCncpAVSXcw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.0.1.tgz",
+      "integrity": "sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "execa": "^3.2.0",
+        "@jest/types": "^26.0.1",
+        "execa": "^4.0.0",
         "throat": "^5.0.0"
       },
       "dependencies": {
@@ -3123,9 +3544,9 @@
           }
         },
         "execa": {
-          "version": "3.4.0",
-          "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
-          "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz",
+          "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==",
           "dev": true,
           "requires": {
             "cross-spawn": "^7.0.0",
@@ -3135,15 +3556,14 @@
             "merge-stream": "^2.0.0",
             "npm-run-path": "^4.0.0",
             "onetime": "^5.1.0",
-            "p-finally": "^2.0.0",
             "signal-exit": "^3.0.2",
             "strip-final-newline": "^2.0.0"
           }
         },
         "get-stream": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
-          "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+          "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
           "dev": true,
           "requires": {
             "pump": "^3.0.0"
@@ -3164,12 +3584,6 @@
             "path-key": "^3.0.0"
           }
         },
-        "p-finally": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
-          "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
-          "dev": true
-        },
         "path-key": {
           "version": "3.1.1",
           "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -3190,385 +3604,1157 @@
           "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
           "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
           "dev": true
+        },
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
         }
       }
     },
     "jest-config": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.5.4.tgz",
-      "integrity": "sha512-SZwR91SwcdK6bz7Gco8qL7YY2sx8tFJYzvg216DLihTWf+LKY/DoJXpM9nTzYakSyfblbqeU48p/p7Jzy05Atg==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.0.1.tgz",
+      "integrity": "sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/test-sequencer": "^25.5.4",
-        "@jest/types": "^25.5.0",
-        "babel-jest": "^25.5.1",
-        "chalk": "^3.0.0",
+        "@jest/test-sequencer": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "babel-jest": "^26.0.1",
+        "chalk": "^4.0.0",
         "deepmerge": "^4.2.2",
         "glob": "^7.1.1",
         "graceful-fs": "^4.2.4",
-        "jest-environment-jsdom": "^25.5.0",
-        "jest-environment-node": "^25.5.0",
-        "jest-get-type": "^25.2.6",
-        "jest-jasmine2": "^25.5.4",
-        "jest-regex-util": "^25.2.6",
-        "jest-resolve": "^25.5.1",
-        "jest-util": "^25.5.0",
-        "jest-validate": "^25.5.0",
+        "jest-environment-jsdom": "^26.0.1",
+        "jest-environment-node": "^26.0.1",
+        "jest-get-type": "^26.0.0",
+        "jest-jasmine2": "^26.0.1",
+        "jest-regex-util": "^26.0.0",
+        "jest-resolve": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jest-validate": "^26.0.1",
         "micromatch": "^4.0.2",
-        "pretty-format": "^25.5.0",
-        "realpath-native": "^2.0.0"
+        "pretty-format": "^26.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-diff": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz",
-      "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.0.1.tgz",
+      "integrity": "sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ==",
       "dev": true,
       "requires": {
-        "chalk": "^3.0.0",
-        "diff-sequences": "^25.2.6",
-        "jest-get-type": "^25.2.6",
-        "pretty-format": "^25.5.0"
+        "chalk": "^4.0.0",
+        "diff-sequences": "^26.0.0",
+        "jest-get-type": "^26.0.0",
+        "pretty-format": "^26.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-docblock": {
-      "version": "25.3.0",
-      "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz",
-      "integrity": "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz",
+      "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==",
       "dev": true,
       "requires": {
         "detect-newline": "^3.0.0"
       }
     },
     "jest-each": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.5.0.tgz",
-      "integrity": "sha512-QBogUxna3D8vtiItvn54xXde7+vuzqRrEeaw8r1s+1TG9eZLVJE5ZkKoSUlqFwRjnlaA4hyKGiu9OlkFIuKnjA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.0.1.tgz",
+      "integrity": "sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
-        "jest-get-type": "^25.2.6",
-        "jest-util": "^25.5.0",
-        "pretty-format": "^25.5.0"
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^26.0.0",
+        "jest-util": "^26.0.1",
+        "pretty-format": "^26.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-environment-jsdom": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.5.0.tgz",
-      "integrity": "sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz",
+      "integrity": "sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^25.5.0",
-        "@jest/fake-timers": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "jest-mock": "^25.5.0",
-        "jest-util": "^25.5.0",
-        "jsdom": "^15.2.1"
+        "@jest/environment": "^26.0.1",
+        "@jest/fake-timers": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "jest-mock": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jsdom": "^16.2.2"
       }
     },
     "jest-environment-node": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.5.0.tgz",
-      "integrity": "sha512-iuxK6rQR2En9EID+2k+IBs5fCFd919gVVK5BeND82fYeLWPqvRcFNPKu9+gxTwfB5XwBGBvZ0HFQa+cHtIoslA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.0.1.tgz",
+      "integrity": "sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^25.5.0",
-        "@jest/fake-timers": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "jest-mock": "^25.5.0",
-        "jest-util": "^25.5.0",
-        "semver": "^6.3.0"
+        "@jest/environment": "^26.0.1",
+        "@jest/fake-timers": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "jest-mock": "^26.0.1",
+        "jest-util": "^26.0.1"
       }
     },
     "jest-get-type": {
-      "version": "25.2.6",
-      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz",
-      "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.0.0.tgz",
+      "integrity": "sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg==",
       "dev": true
     },
     "jest-haste-map": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.5.1.tgz",
-      "integrity": "sha512-dddgh9UZjV7SCDQUrQ+5t9yy8iEgKc1AKqZR9YDww8xsVOtzPQSMVLDChc21+g29oTRexb9/B0bIlZL+sWmvAQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.0.1.tgz",
+      "integrity": "sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
+        "@jest/types": "^26.0.1",
         "@types/graceful-fs": "^4.1.2",
         "anymatch": "^3.0.3",
         "fb-watchman": "^2.0.0",
         "fsevents": "^2.1.2",
         "graceful-fs": "^4.2.4",
-        "jest-serializer": "^25.5.0",
-        "jest-util": "^25.5.0",
-        "jest-worker": "^25.5.0",
+        "jest-serializer": "^26.0.0",
+        "jest-util": "^26.0.1",
+        "jest-worker": "^26.0.0",
         "micromatch": "^4.0.2",
         "sane": "^4.0.3",
         "walker": "^1.0.7",
         "which": "^2.0.2"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
       }
     },
     "jest-jasmine2": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.5.4.tgz",
-      "integrity": "sha512-9acbWEfbmS8UpdcfqnDO+uBUgKa/9hcRh983IHdM+pKmJPL77G0sWAAK0V0kr5LK3a8cSBfkFSoncXwQlRZfkQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz",
+      "integrity": "sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg==",
       "dev": true,
       "requires": {
         "@babel/traverse": "^7.1.0",
-        "@jest/environment": "^25.5.0",
-        "@jest/source-map": "^25.5.0",
-        "@jest/test-result": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
+        "@jest/environment": "^26.0.1",
+        "@jest/source-map": "^26.0.0",
+        "@jest/test-result": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
         "co": "^4.6.0",
-        "expect": "^25.5.0",
+        "expect": "^26.0.1",
         "is-generator-fn": "^2.0.0",
-        "jest-each": "^25.5.0",
-        "jest-matcher-utils": "^25.5.0",
-        "jest-message-util": "^25.5.0",
-        "jest-runtime": "^25.5.4",
-        "jest-snapshot": "^25.5.1",
-        "jest-util": "^25.5.0",
-        "pretty-format": "^25.5.0",
+        "jest-each": "^26.0.1",
+        "jest-matcher-utils": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-runtime": "^26.0.1",
+        "jest-snapshot": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "pretty-format": "^26.0.1",
         "throat": "^5.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-leak-detector": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.5.0.tgz",
-      "integrity": "sha512-rV7JdLsanS8OkdDpZtgBf61L5xZ4NnYLBq72r6ldxahJWWczZjXawRsoHyXzibM5ed7C2QRjpp6ypgwGdKyoVA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz",
+      "integrity": "sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA==",
       "dev": true,
       "requires": {
-        "jest-get-type": "^25.2.6",
-        "pretty-format": "^25.5.0"
+        "jest-get-type": "^26.0.0",
+        "pretty-format": "^26.0.1"
       }
     },
     "jest-matcher-utils": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz",
-      "integrity": "sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz",
+      "integrity": "sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw==",
       "dev": true,
       "requires": {
-        "chalk": "^3.0.0",
-        "jest-diff": "^25.5.0",
-        "jest-get-type": "^25.2.6",
-        "pretty-format": "^25.5.0"
+        "chalk": "^4.0.0",
+        "jest-diff": "^26.0.1",
+        "jest-get-type": "^26.0.0",
+        "pretty-format": "^26.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-message-util": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.5.0.tgz",
-      "integrity": "sha512-ezddz3YCT/LT0SKAmylVyWWIGYoKHOFOFXx3/nA4m794lfVUskMcwhip6vTgdVrOtYdjeQeis2ypzes9mZb4EA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.0.1.tgz",
+      "integrity": "sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@jest/types": "^25.5.0",
+        "@jest/types": "^26.0.1",
         "@types/stack-utils": "^1.0.1",
-        "chalk": "^3.0.0",
+        "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "micromatch": "^4.0.2",
         "slash": "^3.0.0",
-        "stack-utils": "^1.0.1"
+        "stack-utils": "^2.0.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-mock": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.5.0.tgz",
-      "integrity": "sha512-eXWuTV8mKzp/ovHc5+3USJMYsTBhyQ+5A1Mak35dey/RG8GlM4YWVylZuGgVXinaW6tpvk/RSecmF37FKUlpXA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.0.1.tgz",
+      "integrity": "sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0"
+        "@jest/types": "^26.0.1"
       }
     },
     "jest-pnp-resolver": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
-      "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz",
+      "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==",
       "dev": true
     },
     "jest-regex-util": {
-      "version": "25.2.6",
-      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz",
-      "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz",
+      "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==",
       "dev": true
     },
     "jest-resolve": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.5.1.tgz",
-      "integrity": "sha512-Hc09hYch5aWdtejsUZhA+vSzcotf7fajSlPA6EZPE1RmPBAD39XtJhvHWFStid58iit4IPDLI/Da4cwdDmAHiQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.0.1.tgz",
+      "integrity": "sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "browser-resolve": "^1.11.3",
-        "chalk": "^3.0.0",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "jest-pnp-resolver": "^1.2.1",
+        "jest-util": "^26.0.1",
         "read-pkg-up": "^7.0.1",
-        "realpath-native": "^2.0.0",
         "resolve": "^1.17.0",
         "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "parse-json": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+          "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1",
+            "lines-and-columns": "^1.1.6"
+          }
+        },
+        "read-pkg": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+          "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+          "dev": true,
+          "requires": {
+            "@types/normalize-package-data": "^2.4.0",
+            "normalize-package-data": "^2.5.0",
+            "parse-json": "^5.0.0",
+            "type-fest": "^0.6.0"
+          },
+          "dependencies": {
+            "type-fest": {
+              "version": "0.6.0",
+              "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+              "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+              "dev": true
+            }
+          }
+        },
+        "read-pkg-up": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+          "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+          "dev": true,
+          "requires": {
+            "find-up": "^4.1.0",
+            "read-pkg": "^5.2.0",
+            "type-fest": "^0.8.1"
+          }
+        },
+        "resolve": {
+          "version": "1.17.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+          "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-resolve-dependencies": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.5.4.tgz",
-      "integrity": "sha512-yFmbPd+DAQjJQg88HveObcGBA32nqNZ02fjYmtL16t1xw9bAttSn5UGRRhzMHIQbsep7znWvAvnD4kDqOFM0Uw==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz",
+      "integrity": "sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "jest-regex-util": "^25.2.6",
-        "jest-snapshot": "^25.5.1"
+        "@jest/types": "^26.0.1",
+        "jest-regex-util": "^26.0.0",
+        "jest-snapshot": "^26.0.1"
       }
     },
     "jest-runner": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.5.4.tgz",
-      "integrity": "sha512-V/2R7fKZo6blP8E9BL9vJ8aTU4TH2beuqGNxHbxi6t14XzTb+x90B3FRgdvuHm41GY8ch4xxvf0ATH4hdpjTqg==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.0.1.tgz",
+      "integrity": "sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA==",
       "dev": true,
       "requires": {
-        "@jest/console": "^25.5.0",
-        "@jest/environment": "^25.5.0",
-        "@jest/test-result": "^25.5.0",
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
+        "@jest/console": "^26.0.1",
+        "@jest/environment": "^26.0.1",
+        "@jest/test-result": "^26.0.1",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
         "exit": "^0.1.2",
         "graceful-fs": "^4.2.4",
-        "jest-config": "^25.5.4",
-        "jest-docblock": "^25.3.0",
-        "jest-haste-map": "^25.5.1",
-        "jest-jasmine2": "^25.5.4",
-        "jest-leak-detector": "^25.5.0",
-        "jest-message-util": "^25.5.0",
-        "jest-resolve": "^25.5.1",
-        "jest-runtime": "^25.5.4",
-        "jest-util": "^25.5.0",
-        "jest-worker": "^25.5.0",
+        "jest-config": "^26.0.1",
+        "jest-docblock": "^26.0.0",
+        "jest-haste-map": "^26.0.1",
+        "jest-jasmine2": "^26.0.1",
+        "jest-leak-detector": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-resolve": "^26.0.1",
+        "jest-runtime": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jest-worker": "^26.0.0",
         "source-map-support": "^0.5.6",
         "throat": "^5.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-runtime": {
-      "version": "25.5.4",
-      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.5.4.tgz",
-      "integrity": "sha512-RWTt8LeWh3GvjYtASH2eezkc8AehVoWKK20udV6n3/gC87wlTbE1kIA+opCvNWyyPeBs6ptYsc6nyHUb1GlUVQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.0.1.tgz",
+      "integrity": "sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw==",
       "dev": true,
       "requires": {
-        "@jest/console": "^25.5.0",
-        "@jest/environment": "^25.5.0",
-        "@jest/globals": "^25.5.2",
-        "@jest/source-map": "^25.5.0",
-        "@jest/test-result": "^25.5.0",
-        "@jest/transform": "^25.5.1",
-        "@jest/types": "^25.5.0",
+        "@jest/console": "^26.0.1",
+        "@jest/environment": "^26.0.1",
+        "@jest/fake-timers": "^26.0.1",
+        "@jest/globals": "^26.0.1",
+        "@jest/source-map": "^26.0.0",
+        "@jest/test-result": "^26.0.1",
+        "@jest/transform": "^26.0.1",
+        "@jest/types": "^26.0.1",
         "@types/yargs": "^15.0.0",
-        "chalk": "^3.0.0",
+        "chalk": "^4.0.0",
         "collect-v8-coverage": "^1.0.0",
         "exit": "^0.1.2",
         "glob": "^7.1.3",
         "graceful-fs": "^4.2.4",
-        "jest-config": "^25.5.4",
-        "jest-haste-map": "^25.5.1",
-        "jest-message-util": "^25.5.0",
-        "jest-mock": "^25.5.0",
-        "jest-regex-util": "^25.2.6",
-        "jest-resolve": "^25.5.1",
-        "jest-snapshot": "^25.5.1",
-        "jest-util": "^25.5.0",
-        "jest-validate": "^25.5.0",
-        "realpath-native": "^2.0.0",
+        "jest-config": "^26.0.1",
+        "jest-haste-map": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-mock": "^26.0.1",
+        "jest-regex-util": "^26.0.0",
+        "jest-resolve": "^26.0.1",
+        "jest-snapshot": "^26.0.1",
+        "jest-util": "^26.0.1",
+        "jest-validate": "^26.0.1",
         "slash": "^3.0.0",
         "strip-bom": "^4.0.0",
         "yargs": "^15.3.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "glob": {
+          "version": "7.1.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "strip-bom": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+          "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-serializer": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.5.0.tgz",
-      "integrity": "sha512-LxD8fY1lByomEPflwur9o4e2a5twSQ7TaVNLlFUuToIdoJuBt8tzHfCsZ42Ok6LkKXWzFWf3AGmheuLAA7LcCA==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.0.0.tgz",
+      "integrity": "sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.2.4"
+      },
+      "dependencies": {
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        }
       }
     },
     "jest-snapshot": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.5.1.tgz",
-      "integrity": "sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.0.1.tgz",
+      "integrity": "sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.0.0",
-        "@jest/types": "^25.5.0",
-        "@types/prettier": "^1.19.0",
-        "chalk": "^3.0.0",
-        "expect": "^25.5.0",
+        "@jest/types": "^26.0.1",
+        "@types/prettier": "^2.0.0",
+        "chalk": "^4.0.0",
+        "expect": "^26.0.1",
         "graceful-fs": "^4.2.4",
-        "jest-diff": "^25.5.0",
-        "jest-get-type": "^25.2.6",
-        "jest-matcher-utils": "^25.5.0",
-        "jest-message-util": "^25.5.0",
-        "jest-resolve": "^25.5.1",
+        "jest-diff": "^26.0.1",
+        "jest-get-type": "^26.0.0",
+        "jest-matcher-utils": "^26.0.1",
+        "jest-message-util": "^26.0.1",
+        "jest-resolve": "^26.0.1",
         "make-dir": "^3.0.0",
         "natural-compare": "^1.4.0",
-        "pretty-format": "^25.5.0",
-        "semver": "^6.3.0"
+        "pretty-format": "^26.0.1",
+        "semver": "^7.3.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "semver": {
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-util": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.5.0.tgz",
-      "integrity": "sha512-KVlX+WWg1zUTB9ktvhsg2PXZVdkI1NBevOJSkTKYAyXyH4QSvh+Lay/e/v+bmaFfrkfx43xD8QTfgobzlEXdIA==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.0.1.tgz",
+      "integrity": "sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "chalk": "^3.0.0",
+        "@jest/types": "^26.0.1",
+        "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "is-ci": "^2.0.0",
         "make-dir": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.4",
+          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+          "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-validate": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.5.0.tgz",
-      "integrity": "sha512-okUFKqhZIpo3jDdtUXUZ2LxGUZJIlfdYBvZb1aczzxrlyMlqdnnws9MOxezoLGhSaFc2XYaHNReNQfj5zPIWyQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.0.1.tgz",
+      "integrity": "sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
-        "camelcase": "^5.3.1",
-        "chalk": "^3.0.0",
-        "jest-get-type": "^25.2.6",
+        "@jest/types": "^26.0.1",
+        "camelcase": "^6.0.0",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^26.0.0",
         "leven": "^3.1.0",
-        "pretty-format": "^25.5.0"
+        "pretty-format": "^26.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "camelcase": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
+          "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
+          "dev": true
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-watcher": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.5.0.tgz",
-      "integrity": "sha512-XrSfJnVASEl+5+bb51V0Q7WQx65dTSk7NL4yDdVjPnRNpM0hG+ncFmDYJo9O8jaSRcAitVbuVawyXCRoxGrT5Q==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.0.1.tgz",
+      "integrity": "sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^25.5.0",
-        "@jest/types": "^25.5.0",
+        "@jest/test-result": "^26.0.1",
+        "@jest/types": "^26.0.1",
         "ansi-escapes": "^4.2.1",
-        "chalk": "^3.0.0",
-        "jest-util": "^25.5.0",
-        "string-length": "^3.1.0"
+        "chalk": "^4.0.0",
+        "jest-util": "^26.0.1",
+        "string-length": "^4.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "jest-worker": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz",
-      "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==",
+      "version": "26.0.0",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz",
+      "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==",
       "dev": true,
       "requires": {
         "merge-stream": "^2.0.0",
         "supports-color": "^7.0.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "js-base64": {
-      "version": "2.6.4",
-      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
-      "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==",
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
+      "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==",
       "dev": true
     },
     "js-tokens": {
@@ -3578,9 +4764,9 @@
       "dev": true
     },
     "js-yaml": {
-      "version": "3.14.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
-      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+      "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
@@ -3593,38 +4779,85 @@
       "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": "15.2.1",
-      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz",
-      "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==",
+      "version": "16.2.2",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.2.tgz",
+      "integrity": "sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg==",
       "dev": true,
       "requires": {
-        "abab": "^2.0.0",
-        "acorn": "^7.1.0",
-        "acorn-globals": "^4.3.2",
-        "array-equal": "^1.0.0",
-        "cssom": "^0.4.1",
-        "cssstyle": "^2.0.0",
-        "data-urls": "^1.1.0",
-        "domexception": "^1.0.1",
-        "escodegen": "^1.11.1",
-        "html-encoding-sniffer": "^1.0.2",
+        "abab": "^2.0.3",
+        "acorn": "^7.1.1",
+        "acorn-globals": "^6.0.0",
+        "cssom": "^0.4.4",
+        "cssstyle": "^2.2.0",
+        "data-urls": "^2.0.0",
+        "decimal.js": "^10.2.0",
+        "domexception": "^2.0.1",
+        "escodegen": "^1.14.1",
+        "html-encoding-sniffer": "^2.0.1",
+        "is-potential-custom-element-name": "^1.0.0",
         "nwsapi": "^2.2.0",
-        "parse5": "5.1.0",
-        "pn": "^1.1.0",
-        "request": "^2.88.0",
-        "request-promise-native": "^1.0.7",
-        "saxes": "^3.1.9",
-        "symbol-tree": "^3.2.2",
+        "parse5": "5.1.1",
+        "request": "^2.88.2",
+        "request-promise-native": "^1.0.8",
+        "saxes": "^5.0.0",
+        "symbol-tree": "^3.2.4",
         "tough-cookie": "^3.0.1",
-        "w3c-hr-time": "^1.0.1",
-        "w3c-xmlserializer": "^1.1.2",
-        "webidl-conversions": "^4.0.2",
+        "w3c-hr-time": "^1.0.2",
+        "w3c-xmlserializer": "^2.0.0",
+        "webidl-conversions": "^6.0.0",
         "whatwg-encoding": "^1.0.5",
         "whatwg-mimetype": "^2.3.0",
-        "whatwg-url": "^7.0.0",
-        "ws": "^7.0.0",
+        "whatwg-url": "^8.0.0",
+        "ws": "^7.2.3",
         "xml-name-validator": "^3.0.0"
+      },
+      "dependencies": {
+        "request": {
+          "version": "2.88.2",
+          "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+          "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+          "dev": true,
+          "requires": {
+            "aws-sign2": "~0.7.0",
+            "aws4": "^1.8.0",
+            "caseless": "~0.12.0",
+            "combined-stream": "~1.0.6",
+            "extend": "~3.0.2",
+            "forever-agent": "~0.6.1",
+            "form-data": "~2.3.2",
+            "har-validator": "~5.1.3",
+            "http-signature": "~1.2.0",
+            "is-typedarray": "~1.0.0",
+            "isstream": "~0.1.2",
+            "json-stringify-safe": "~5.0.1",
+            "mime-types": "~2.1.19",
+            "oauth-sign": "~0.9.0",
+            "performance-now": "^2.1.0",
+            "qs": "~6.5.2",
+            "safe-buffer": "^5.1.2",
+            "tough-cookie": "~2.5.0",
+            "tunnel-agent": "^0.6.0",
+            "uuid": "^3.3.2"
+          },
+          "dependencies": {
+            "tough-cookie": {
+              "version": "2.5.0",
+              "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+              "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+              "dev": true,
+              "requires": {
+                "psl": "^1.1.28",
+                "punycode": "^2.1.1"
+              }
+            }
+          }
+        }
       }
     },
     "jsesc": {
@@ -3633,10 +4866,10 @@
       "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
       "dev": true
     },
-    "json-parse-even-better-errors": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
       "dev": true
     },
     "json-schema": {
@@ -3658,9 +4891,9 @@
       "dev": true
     },
     "json5": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
-      "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+      "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
       "dev": true,
       "requires": {
         "minimist": "^1.2.5"
@@ -3723,26 +4956,6 @@
         "pify": "^2.0.0",
         "pinkie-promise": "^2.0.0",
         "strip-bom": "^2.0.0"
-      },
-      "dependencies": {
-        "parse-json": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-          "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
-          "dev": true,
-          "requires": {
-            "error-ex": "^1.2.0"
-          }
-        },
-        "strip-bom": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
-          "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
-          "dev": true,
-          "requires": {
-            "is-utf8": "^0.2.0"
-          }
-        }
       }
     },
     "locate-path": {
@@ -3755,15 +4968,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.20",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
-      "dev": true
-    },
-    "lodash.memoize": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
       "dev": true
     },
     "lodash.sortby": {
@@ -3772,15 +4979,6 @@
       "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
       "dev": true
     },
-    "lolex": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz",
-      "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==",
-      "dev": true,
-      "requires": {
-        "@sinonjs/commons": "^1.7.0"
-      }
-    },
     "long": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
@@ -3807,12 +5005,20 @@
       }
     },
     "magic-string": {
-      "version": "0.25.7",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
-      "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+      "version": "0.25.2",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz",
+      "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==",
       "dev": true,
       "requires": {
         "sourcemap-codec": "^1.4.4"
+      },
+      "dependencies": {
+        "sourcemap-codec": {
+          "version": "1.4.4",
+          "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz",
+          "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==",
+          "dev": true
+        }
       }
     },
     "make-dir": {
@@ -3822,14 +5028,16 @@
       "dev": true,
       "requires": {
         "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
       }
     },
-    "make-error": {
-      "version": "1.3.6",
-      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
-      "dev": true
-    },
     "makeerror": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
@@ -3876,48 +5084,6 @@
         "read-pkg-up": "^1.0.1",
         "redent": "^1.0.0",
         "trim-newlines": "^1.0.0"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
-          "dev": true,
-          "requires": {
-            "path-exists": "^2.0.0",
-            "pinkie-promise": "^2.0.0"
-          }
-        },
-        "path-exists": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
-          "dev": true,
-          "requires": {
-            "pinkie-promise": "^2.0.0"
-          }
-        },
-        "read-pkg": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-          "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
-          "dev": true,
-          "requires": {
-            "load-json-file": "^1.0.0",
-            "normalize-package-data": "^2.3.2",
-            "path-type": "^1.0.0"
-          }
-        },
-        "read-pkg-up": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
-          "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
-          "dev": true,
-          "requires": {
-            "find-up": "^1.0.0",
-            "read-pkg": "^1.0.0"
-          }
-        }
       }
     },
     "merge-stream": {
@@ -3942,24 +5108,24 @@
       "integrity": "sha512-2VDso2a22jWPpqwuWT/4RomVpoU3Bl9qF9D01xzwlNp5UVsImeA0gY4nSpF44vqcQtQOtkiMUV9EZkAJSRxBsg=="
     },
     "mime": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz",
-      "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==",
+      "version": "2.4.6",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
+      "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==",
       "dev": true
     },
     "mime-db": {
-      "version": "1.45.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
-      "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
+      "version": "1.38.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
+      "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.28",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
-      "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
+      "version": "2.1.22",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
+      "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
       "dev": true,
       "requires": {
-        "mime-db": "1.45.0"
+        "mime-db": "~1.38.0"
       }
     },
     "mimic-fn": {
@@ -3968,11 +5134,15 @@
       "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
       "dev": true
     },
+    "mimic-response": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
+      "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="
+    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-      "dev": true,
       "requires": {
         "brace-expansion": "^1.1.7"
       }
@@ -3980,13 +5150,36 @@
     "minimist": {
       "version": "1.2.5",
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-      "dev": true
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+    },
+    "minipass": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+      "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+      "requires": {
+        "safe-buffer": "^5.1.2",
+        "yallist": "^3.0.0"
+      },
+      "dependencies": {
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+        }
+      }
+    },
+    "minizlib": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+      "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+      "requires": {
+        "minipass": "^2.9.0"
+      }
     },
     "mithril": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/mithril/-/mithril-2.0.4.tgz",
-      "integrity": "sha512-mgw+DMZlhMS4PpprF6dl7ZoeZq5GGcAuWnrg5e12MvaGauc4jzWsDZtVGRCktsiQczOEUr2K5teKbE5k44RlOg=="
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/mithril/-/mithril-1.1.7.tgz",
+      "integrity": "sha512-1SAkGeVrIVvkUHlPHvR3pXdWzNfTzmS/fBAe+rC2ApEBfZFFc+idi8Qg/M5JoW/sZkIDXSfQYVgvENMIhBIVAg=="
     },
     "mixin-deep": {
       "version": "1.3.2",
@@ -4013,22 +5206,20 @@
       "version": "0.5.5",
       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
       "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-      "dev": true,
       "requires": {
         "minimist": "^1.2.5"
       }
     },
     "ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
       "dev": true
     },
     "nan": {
-      "version": "2.14.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
-      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
-      "dev": true
+      "version": "2.14.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+      "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
     },
     "nanomatch": {
       "version": "1.2.13",
@@ -4055,6 +5246,31 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
+    "needle": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz",
+      "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==",
+      "requires": {
+        "debug": "^3.2.6",
+        "iconv-lite": "^0.4.4",
+        "sax": "^1.2.4"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        }
+      }
+    },
     "nice-try": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -4081,32 +5297,19 @@
         "which": "1"
       },
       "dependencies": {
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
         "semver": {
           "version": "5.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
           "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
           "dev": true
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
         }
       }
     },
+    "node-gyp-build": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz",
+      "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w=="
+    },
     "node-int64": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -4120,23 +5323,38 @@
       "dev": true
     },
     "node-notifier": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz",
-      "integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.1.tgz",
+      "integrity": "sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg==",
       "dev": true,
       "optional": true,
       "requires": {
         "growly": "^1.3.0",
         "is-wsl": "^2.1.1",
-        "semver": "^6.3.0",
+        "semver": "^7.2.1",
         "shellwords": "^0.1.1",
-        "which": "^1.3.1"
+        "uuid": "^7.0.3",
+        "which": "^2.0.2"
       },
       "dependencies": {
+        "semver": {
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "dev": true,
+          "optional": true
+        },
+        "uuid": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
+          "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
+          "dev": true,
+          "optional": true
+        },
         "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -4145,6 +5363,53 @@
         }
       }
     },
+    "node-pre-gyp": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
+      "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
+      "requires": {
+        "detect-libc": "^1.0.2",
+        "mkdirp": "^0.5.1",
+        "needle": "^2.2.1",
+        "nopt": "^4.0.1",
+        "npm-packlist": "^1.1.6",
+        "npmlog": "^4.0.2",
+        "rc": "^1.2.7",
+        "rimraf": "^2.6.1",
+        "semver": "^5.3.0",
+        "tar": "^4"
+      },
+      "dependencies": {
+        "nopt": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+          "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "tar": {
+          "version": "4.4.13",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+          "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.8.6",
+            "minizlib": "^1.2.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.3"
+          }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+        }
+      }
+    },
     "node-sass": {
       "version": "4.14.1",
       "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
@@ -4170,12 +5435,6 @@
         "true-case-path": "^1.0.2"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true
-        },
         "ansi-styles": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@@ -4205,6 +5464,12 @@
             "which": "^1.2.9"
           }
         },
+        "nan": {
+          "version": "2.14.1",
+          "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+          "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+          "dev": true
+        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -4219,24 +5484,9 @@
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
           "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
           "dev": true
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
         }
       }
     },
-    "node-watch": {
-      "version": "0.7.1",
-      "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz",
-      "integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==",
-      "dev": true
-    },
     "noice-json-rpc": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/noice-json-rpc/-/noice-json-rpc-1.2.0.tgz",
@@ -4263,11 +5513,20 @@
         "validate-npm-package-license": "^3.0.1"
       },
       "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+        "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"
+          }
         }
       }
     },
@@ -4277,6 +5536,29 @@
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
       "dev": true
     },
+    "npm-bundled": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+      "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+      "requires": {
+        "npm-normalize-package-bin": "^1.0.1"
+      }
+    },
+    "npm-normalize-package-bin": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+      "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+    },
+    "npm-packlist": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+      "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+      "requires": {
+        "ignore-walk": "^3.0.1",
+        "npm-bundled": "^1.0.1",
+        "npm-normalize-package-bin": "^1.0.1"
+      }
+    },
     "npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -4290,7 +5572,6 @@
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
       "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-      "dev": true,
       "requires": {
         "are-we-there-yet": "~1.1.2",
         "console-control-strings": "~1.1.0",
@@ -4301,8 +5582,7 @@
     "number-is-nan": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
-      "dev": true
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
     },
     "nwsapi": {
       "version": "2.2.0",
@@ -4319,8 +5599,7 @@
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
     "object-copy": {
       "version": "0.1.0",
@@ -4354,9 +5633,9 @@
       }
     },
     "object-inspect": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
-      "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+      "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
     },
     "object-keys": {
       "version": "1.1.1",
@@ -4373,14 +5652,14 @@
       }
     },
     "object.assign": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
-      "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+      "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
       "requires": {
-        "call-bind": "^1.0.0",
-        "define-properties": "^1.1.3",
-        "has-symbols": "^1.0.1",
-        "object-keys": "^1.1.1"
+        "define-properties": "^1.1.2",
+        "function-bind": "^1.1.1",
+        "has-symbols": "^1.0.0",
+        "object-keys": "^1.0.11"
       }
     },
     "object.pick": {
@@ -4396,15 +5675,14 @@
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true,
       "requires": {
         "wrappy": "1"
       }
     },
     "onetime": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
       "dev": true,
       "requires": {
         "mimic-fn": "^2.1.0"
@@ -4427,29 +5705,26 @@
     "os-homedir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-      "dev": true
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
     },
     "os-tmpdir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-      "dev": true
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
     },
     "osenv": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
       "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-      "dev": true,
       "requires": {
         "os-homedir": "^1.0.0",
         "os-tmpdir": "^1.0.0"
       }
     },
     "p-each-series": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
-      "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz",
+      "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==",
       "dev": true
     },
     "p-finally": {
@@ -4488,21 +5763,18 @@
       "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
     },
     "parse-json": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
-      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "error-ex": "^1.3.1",
-        "json-parse-even-better-errors": "^2.3.0",
-        "lines-and-columns": "^1.1.6"
+        "error-ex": "^1.2.0"
       }
     },
     "parse5": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
-      "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
+      "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
       "dev": true
     },
     "pascalcase": {
@@ -4512,16 +5784,15 @@
       "dev": true
     },
     "path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
       "dev": true
     },
     "path-is-absolute": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "dev": true
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
     },
     "path-key": {
       "version": "2.0.1",
@@ -4603,12 +5874,6 @@
         "find-up": "^4.0.0"
       }
     },
-    "pn": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
-      "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
-      "dev": true
-    },
     "posix-character-classes": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -4622,12 +5887,12 @@
       "dev": true
     },
     "pretty-format": {
-      "version": "25.5.0",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz",
-      "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==",
+      "version": "26.0.1",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.0.1.tgz",
+      "integrity": "sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^25.5.0",
+        "@jest/types": "^26.0.1",
         "ansi-regex": "^5.0.0",
         "ansi-styles": "^4.0.0",
         "react-is": "^16.12.0"
@@ -4638,14 +5903,32 @@
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
           "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
         }
       }
     },
     "process-nextick-args": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-      "dev": true
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
     },
     "progress": {
       "version": "2.0.3",
@@ -4654,19 +5937,19 @@
       "dev": true
     },
     "prompts": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz",
-      "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==",
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz",
+      "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==",
       "dev": true,
       "requires": {
         "kleur": "^3.0.3",
-        "sisteransi": "^1.0.5"
+        "sisteransi": "^1.0.4"
       }
     },
     "protobufjs": {
-      "version": "6.10.2",
-      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.2.tgz",
-      "integrity": "sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==",
+      "version": "6.9.0",
+      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz",
+      "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==",
       "requires": {
         "@protobufjs/aspromise": "^1.1.2",
         "@protobufjs/base64": "^1.1.2",
@@ -4684,9 +5967,9 @@
       },
       "dependencies": {
         "@types/node": {
-          "version": "13.13.41",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.41.tgz",
-          "integrity": "sha512-qLT9IvHiXJfdrje9VmsLzun7cQ65obsBTmtU3EOnCSLFOoSHx1hpiRHoBnpdbyFqnzqdUUIv81JcEJQCB8un9g=="
+          "version": "13.13.9",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.9.tgz",
+          "integrity": "sha512-EPZBIGed5gNnfWCiwEIwTE2Jdg4813odnG8iNPMQGrqVxrI+wL68SPtPeCX+ZxGBaA6pKAVc6jaKgP/Q0QzfdQ=="
         }
       }
     },
@@ -4703,9 +5986,9 @@
       "dev": true
     },
     "psl": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
-      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+      "version": "1.1.31",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
       "dev": true
     },
     "pump": {
@@ -4740,15 +6023,21 @@
         "ws": "^6.1.0"
       },
       "dependencies": {
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
-            "glob": "^7.1.3"
+            "ms": "^2.1.1"
           }
         },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
         "ws": {
           "version": "6.2.1",
           "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -4766,6 +6055,17 @@
       "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
       "dev": true
     },
+    "rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      }
+    },
     "react-is": {
       "version": "16.13.1",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -4773,41 +6073,51 @@
       "dev": true
     },
     "read-pkg": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
-      "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
       "dev": true,
       "requires": {
-        "@types/normalize-package-data": "^2.4.0",
-        "normalize-package-data": "^2.5.0",
-        "parse-json": "^5.0.0",
-        "type-fest": "^0.6.0"
-      },
-      "dependencies": {
-        "type-fest": {
-          "version": "0.6.0",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
-          "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
-          "dev": true
-        }
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
       }
     },
     "read-pkg-up": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
-      "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
       "dev": true,
       "requires": {
-        "find-up": "^4.1.0",
-        "read-pkg": "^5.2.0",
-        "type-fest": "^0.8.1"
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+          "dev": true,
+          "requires": {
+            "path-exists": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "dev": true,
+          "requires": {
+            "pinkie-promise": "^2.0.0"
+          }
+        }
       }
     },
     "readable-stream": {
-      "version": "2.3.7",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-      "dev": true,
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
       "requires": {
         "core-util-is": "~1.0.0",
         "inherits": "~2.0.3",
@@ -4816,22 +6126,8 @@
         "safe-buffer": "~5.1.1",
         "string_decoder": "~1.1.1",
         "util-deprecate": "~1.0.1"
-      },
-      "dependencies": {
-        "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==",
-          "dev": true
-        }
       }
     },
-    "realpath-native": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz",
-      "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==",
-      "dev": true
-    },
     "redent": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -4880,9 +6176,9 @@
       }
     },
     "request": {
-      "version": "2.88.2",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
-      "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
       "dev": true,
       "requires": {
         "aws-sign2": "~0.7.0",
@@ -4892,7 +6188,7 @@
         "extend": "~3.0.2",
         "forever-agent": "~0.6.1",
         "form-data": "~2.3.2",
-        "har-validator": "~5.1.3",
+        "har-validator": "~5.1.0",
         "http-signature": "~1.2.0",
         "is-typedarray": "~1.0.0",
         "isstream": "~0.1.2",
@@ -4902,39 +6198,45 @@
         "performance-now": "^2.1.0",
         "qs": "~6.5.2",
         "safe-buffer": "^5.1.2",
-        "tough-cookie": "~2.5.0",
+        "tough-cookie": "~2.4.3",
         "tunnel-agent": "^0.6.0",
         "uuid": "^3.3.2"
       },
       "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        },
         "tough-cookie": {
-          "version": "2.5.0",
-          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
-          "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+          "version": "2.4.3",
+          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+          "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
           "dev": true,
           "requires": {
-            "psl": "^1.1.28",
-            "punycode": "^2.1.1"
+            "psl": "^1.1.24",
+            "punycode": "^1.4.1"
           }
         }
       }
     },
     "request-promise-core": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
-      "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
+      "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
       "dev": true,
       "requires": {
-        "lodash": "^4.17.19"
+        "lodash": "^4.17.15"
       }
     },
     "request-promise-native": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
-      "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
+      "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
       "dev": true,
       "requires": {
-        "request-promise-core": "1.1.4",
+        "request-promise-core": "1.1.3",
         "stealthy-require": "^1.1.1",
         "tough-cookie": "^2.3.3"
       },
@@ -4964,13 +6266,20 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.19.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
-      "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
+      "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
       "dev": true,
       "requires": {
-        "is-core-module": "^2.1.0",
         "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
+        }
       }
     },
     "resolve-cwd": {
@@ -5001,64 +6310,46 @@
       "dev": true
     },
     "rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
       "requires": {
-        "glob": "^7.1.3"
+        "glob": "^7.0.5"
       }
     },
     "rollup": {
-      "version": "2.38.5",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
-      "integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
+      "version": "1.32.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz",
+      "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==",
       "dev": true,
       "requires": {
-        "fsevents": "~2.3.1"
+        "@types/estree": "*",
+        "@types/node": "*",
+        "acorn": "^7.1.0"
       }
     },
-    "rollup-plugin-re": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-re/-/rollup-plugin-re-1.0.7.tgz",
-      "integrity": "sha1-/hdHBO1ZzahMrwK9ATtYLm/apPY=",
+    "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==",
       "dev": true,
       "requires": {
-        "magic-string": "^0.16.0",
-        "rollup-pluginutils": "^2.0.1"
-      },
-      "dependencies": {
-        "magic-string": {
-          "version": "0.16.0",
-          "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz",
-          "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=",
-          "dev": true,
-          "requires": {
-            "vlq": "^0.2.1"
-          }
-        }
+        "estree-walker": "^0.6.0",
+        "magic-string": "^0.25.2",
+        "resolve": "^1.10.0",
+        "rollup-pluginutils": "^2.6.0"
       }
     },
-    "rollup-plugin-sourcemaps": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz",
-      "integrity": "sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw==",
+    "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==",
       "dev": true,
       "requires": {
-        "@rollup/pluginutils": "^3.0.9",
-        "source-map-resolve": "^0.6.0"
-      },
-      "dependencies": {
-        "source-map-resolve": {
-          "version": "0.6.0",
-          "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
-          "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
-          "dev": true,
-          "requires": {
-            "atob": "^2.1.2",
-            "decode-uri-component": "^0.2.0"
-          }
-        }
+        "@types/resolve": "0.0.8",
+        "builtin-modules": "^3.1.0",
+        "is-module": "^1.0.0",
+        "resolve": "^1.10.0"
       }
     },
     "rollup-pluginutils": {
@@ -5085,9 +6376,9 @@
       "dev": true
     },
     "safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safe-regex": {
       "version": "1.1.0",
@@ -5101,8 +6392,19 @@
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "sander": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
+      "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=",
+      "dev": true,
+      "requires": {
+        "es6-promise": "^3.1.2",
+        "graceful-fs": "^4.1.3",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.2"
+      }
     },
     "sane": {
       "version": "4.1.0",
@@ -5257,14 +6559,17 @@
         "yargs": "^13.3.2"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
         },
         "cliui": {
           "version": "5.0.0",
@@ -5277,27 +6582,6 @@
             "wrap-ansi": "^5.1.0"
           }
         },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "dev": true,
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-          "dev": true
-        },
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-          "dev": true
-        },
         "find-up": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@@ -5307,10 +6591,10 @@
             "locate-path": "^3.0.0"
           }
         },
-        "is-fullwidth-code-point": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
           "dev": true
         },
         "locate-path": {
@@ -5323,6 +6607,15 @@
             "path-exists": "^3.0.0"
           }
         },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
         "p-locate": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
@@ -5332,10 +6625,16 @@
             "p-limit": "^2.0.0"
           }
         },
-        "path-exists": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
           "dev": true
         },
         "string-width": {
@@ -5369,6 +6668,12 @@
             "strip-ansi": "^5.0.0"
           }
         },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+          "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+          "dev": true
+        },
         "yargs": {
           "version": "13.3.2",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
@@ -5399,13 +6704,18 @@
         }
       }
     },
+    "sax": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+    },
     "saxes": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz",
-      "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+      "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
       "dev": true,
       "requires": {
-        "xmlchars": "^2.1.1"
+        "xmlchars": "^2.2.0"
       }
     },
     "scss-tokenizer": {
@@ -5430,16 +6740,14 @@
       }
     },
     "semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-      "dev": true
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
     },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
-      "dev": true
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
     },
     "set-value": {
       "version": "2.0.1",
@@ -5487,10 +6795,24 @@
       "optional": true
     },
     "signal-exit": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
-      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
-      "dev": true
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+    },
+    "simple-concat": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
+      "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
+    },
+    "simple-get": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
+      "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
+      "requires": {
+        "decompress-response": "^4.2.0",
+        "once": "^1.3.1",
+        "simple-concat": "^1.0.0"
+      }
     },
     "sisteransi": {
       "version": "1.0.5",
@@ -5520,15 +6842,6 @@
         "use": "^3.1.0"
       },
       "dependencies": {
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -5547,12 +6860,6 @@
             "is-extendable": "^0.1.0"
           }
         },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        },
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -5632,6 +6939,18 @@
         }
       }
     },
+    "sorcery": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
+      "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=",
+      "dev": true,
+      "requires": {
+        "buffer-crc32": "^0.2.5",
+        "minimist": "^1.2.0",
+        "sander": "^0.5.0",
+        "sourcemap-codec": "^1.3.0"
+      }
+    },
     "source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -5662,21 +6981,21 @@
       }
     },
     "source-map-url": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
-      "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
       "dev": true
     },
     "sourcemap-codec": {
-      "version": "1.4.8",
-      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
-      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.1.tgz",
+      "integrity": "sha512-hX1eNBNuilj8yfFnECh0DzLgwKpBLMIvmhgEhixXNui8lMLBInTI8Kyxt++RwJnMNu7cAUo635L2+N1TxMJCzA==",
       "dev": true
     },
     "spdx-correct": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
-      "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
       "dev": true,
       "requires": {
         "spdx-expression-parse": "^3.0.0",
@@ -5684,15 +7003,15 @@
       }
     },
     "spdx-exceptions": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
       "dev": true
     },
     "spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
       "dev": true,
       "requires": {
         "spdx-exceptions": "^2.1.0",
@@ -5700,9 +7019,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
-      "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz",
+      "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==",
       "dev": true
     },
     "split-string": {
@@ -5738,9 +7057,9 @@
       }
     },
     "stack-utils": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.4.tgz",
-      "integrity": "sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz",
+      "integrity": "sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==",
       "dev": true,
       "requires": {
         "escape-string-regexp": "^2.0.0"
@@ -5790,80 +7109,14 @@
       "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
       "dev": true
     },
-    "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "~5.1.0"
-      },
-      "dependencies": {
-        "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==",
-          "dev": true
-        }
-      }
-    },
     "string-length": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz",
-      "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz",
+      "integrity": "sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw==",
       "dev": true,
       "requires": {
-        "astral-regex": "^1.0.0",
-        "strip-ansi": "^5.2.0"
-      },
-      "dependencies": {
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
-      }
-    },
-    "string-width": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
-      "dev": true,
-      "requires": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
+        "char-regex": "^1.0.2",
         "strip-ansi": "^6.0.0"
-      }
-    },
-    "string.prototype.trimend": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
-      "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==",
-      "requires": {
-        "call-bind": "^1.0.0",
-        "define-properties": "^1.1.3"
-      }
-    },
-    "string.prototype.trimstart": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz",
-      "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==",
-      "requires": {
-        "call-bind": "^1.0.0",
-        "define-properties": "^1.1.3"
-      }
-    },
-    "strip-ansi": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "^5.0.0"
       },
       "dependencies": {
         "ansi-regex": {
@@ -5871,14 +7124,96 @@
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
           "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        }
+      }
+    },
+    "string-width": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "requires": {
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^4.0.0"
+      }
+    },
+    "string.prototype.trimend": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+      "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      }
+    },
+    "string.prototype.trimleft": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+      "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5",
+        "string.prototype.trimstart": "^1.0.0"
+      }
+    },
+    "string.prototype.trimright": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+      "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5",
+        "string.prototype.trimend": "^1.0.0"
+      }
+    },
+    "string.prototype.trimstart": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+      "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      }
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "requires": {
+        "ansi-regex": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
         }
       }
     },
     "strip-bom": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
-      "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
-      "dev": true
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "dev": true,
+      "requires": {
+        "is-utf8": "^0.2.0"
+      }
     },
     "strip-eof": {
       "version": "1.0.0",
@@ -5901,13 +7236,18 @@
         "get-stdin": "^4.0.1"
       }
     },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+    },
     "supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
       "dev": true,
       "requires": {
-        "has-flag": "^4.0.0"
+        "has-flag": "^3.0.0"
       }
     },
     "supports-hyperlinks": {
@@ -5918,6 +7258,23 @@
       "requires": {
         "has-flag": "^4.0.0",
         "supports-color": "^7.0.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
       }
     },
     "symbol-tree": {
@@ -5956,6 +7313,22 @@
         "@istanbuljs/schema": "^0.1.2",
         "glob": "^7.1.4",
         "minimatch": "^3.0.4"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.1.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        }
       }
     },
     "throat": {
@@ -6029,12 +7402,12 @@
       }
     },
     "tr46": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
-      "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz",
+      "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==",
       "dev": true,
       "requires": {
-        "punycode": "^2.1.0"
+        "punycode": "^2.1.1"
       }
     },
     "trim-newlines": {
@@ -6052,28 +7425,10 @@
         "glob": "^7.1.2"
       }
     },
-    "ts-jest": {
-      "version": "25.5.1",
-      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.5.1.tgz",
-      "integrity": "sha512-kHEUlZMK8fn8vkxDjwbHlxXRB9dHYpyzqKIGDNxbzs+Rz+ssNDSDNusEK8Fk/sDd4xE6iKoQLfFkFVaskmTJyw==",
-      "dev": true,
-      "requires": {
-        "bs-logger": "0.x",
-        "buffer-from": "1.x",
-        "fast-json-stable-stringify": "2.x",
-        "json5": "2.x",
-        "lodash.memoize": "4.x",
-        "make-error": "1.x",
-        "micromatch": "4.x",
-        "mkdirp": "0.x",
-        "semver": "6.x",
-        "yargs-parser": "18.x"
-      }
-    },
     "tslib": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+      "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
       "dev": true
     },
     "tslint": {
@@ -6097,67 +7452,11 @@
         "tsutils": "^2.29.0"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
         "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
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "dev": true,
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-          "dev": true
-        },
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
-        },
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
         }
       }
     },
@@ -6222,9 +7521,9 @@
       }
     },
     "typescript": {
-      "version": "3.9.7",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
-      "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
+      "version": "3.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz",
+      "integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==",
       "dev": true
     },
     "union-value": {
@@ -6280,9 +7579,9 @@
       }
     },
     "uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
       "dev": true,
       "requires": {
         "punycode": "^2.1.0"
@@ -6300,6 +7599,14 @@
       "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
       "dev": true
     },
+    "utf-8-validate": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz",
+      "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==",
+      "requires": {
+        "node-gyp-build": "~3.7.0"
+      }
+    },
     "util": {
       "version": "0.12.3",
       "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz",
@@ -6316,8 +7623,7 @@
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-      "dev": true
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "uuid": {
       "version": "3.4.0",
@@ -6364,12 +7670,6 @@
         "extsprintf": "^1.2.0"
       }
     },
-    "vlq": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
-      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
-      "dev": true
-    },
     "w3c-hr-time": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -6380,13 +7680,11 @@
       }
     },
     "w3c-xmlserializer": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz",
-      "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
+      "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==",
       "dev": true,
       "requires": {
-        "domexception": "^1.0.1",
-        "webidl-conversions": "^4.0.2",
         "xml-name-validator": "^3.0.0"
       }
     },
@@ -6400,9 +7698,9 @@
       }
     },
     "webidl-conversions": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-      "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
+      "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
       "dev": true
     },
     "whatwg-encoding": {
@@ -6421,20 +7719,28 @@
       "dev": true
     },
     "whatwg-url": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
-      "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.1.0.tgz",
+      "integrity": "sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==",
       "dev": true,
       "requires": {
         "lodash.sortby": "^4.7.0",
-        "tr46": "^1.0.1",
-        "webidl-conversions": "^4.0.2"
+        "tr46": "^2.0.2",
+        "webidl-conversions": "^5.0.0"
+      },
+      "dependencies": {
+        "webidl-conversions": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+          "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+          "dev": true
+        }
       }
     },
     "which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
       "dev": true,
       "requires": {
         "isexe": "^2.0.0"
@@ -6447,13 +7753,12 @@
       "dev": true
     },
     "which-typed-array": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz",
-      "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz",
+      "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==",
       "requires": {
         "available-typed-arrays": "^1.0.2",
-        "call-bind": "^1.0.0",
-        "es-abstract": "^1.18.0-next.1",
+        "es-abstract": "^1.17.5",
         "foreach": "^2.0.5",
         "function-bind": "^1.1.1",
         "has-symbols": "^1.0.1",
@@ -6464,42 +7769,8 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
       "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-      "dev": true,
       "requires": {
         "string-width": "^1.0.2 || 2"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-          "dev": true
-        },
-        "string-width": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-          "dev": true,
-          "requires": {
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^4.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^3.0.0"
-          }
-        }
       }
     },
     "word-wrap": {
@@ -6517,13 +7788,71 @@
         "ansi-styles": "^4.0.0",
         "string-width": "^4.1.0",
         "strip-ansi": "^6.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        }
       }
     },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "dev": true
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "write-file-atomic": {
       "version": "3.0.3",
@@ -6538,9 +7867,9 @@
       }
     },
     "ws": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
-      "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==",
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
+      "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==",
       "dev": true
     },
     "xml-name-validator": {
@@ -6556,9 +7885,9 @@
       "dev": true
     },
     "y18n": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
-      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
       "dev": true
     },
     "yallist": {
@@ -6568,9 +7897,9 @@
       "dev": true
     },
     "yargs": {
-      "version": "15.4.1",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
-      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "version": "15.3.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
+      "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
       "dev": true,
       "requires": {
         "cliui": "^6.0.0",
@@ -6583,7 +7912,47 @@
         "string-width": "^4.2.0",
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
-        "yargs-parser": "^18.1.2"
+        "yargs-parser": "^18.1.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        }
       }
     },
     "yargs-parser": {
diff --git a/ui/package.json b/ui/package.json
index 4a2cadf..7baa4cd 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -15,40 +15,36 @@
     "@types/pako": "^1.0.1",
     "@types/uuid": "^3.4.9",
     "@types/w3c-web-usb": "^1.0.4",
+    "bufferutil": "^4.0.1",
+    "canvas": "^2.6.1",
     "color-convert": "^2.0.1",
     "custom_utils": "file:src/base/utils",
-    "devtools-protocol": "0.0.847576",
+    "devtools-protocol": "0.0.681549",
     "events": "^3.1.0",
-    "hsluv": "^0.1.0",
     "immer": "^1.12.1",
+    "jsbn-rsa": "^1.0.3",
     "micromodal": "^0.4.6",
-    "mithril": "^2.0.4",
+    "mithril": "^1.1.7",
     "noice-json-rpc": "^1.2.0",
     "pako": "^1.0.11",
     "protobufjs": "^6.9.0",
+    "utf-8-validate": "^5.0.2",
     "util": "^0.12.3",
     "uuid": "^3.4.0"
   },
   "devDependencies": {
-    "@rollup/plugin-commonjs": "^14.0.0",
-    "@rollup/plugin-node-resolve": "^8.4.0",
     "@types/jest": "^22.2.3",
     "@types/puppeteer": "^1.20.6",
     "dingusjs": "^0.0.3",
     "jest": "^25.5.4",
     "node-sass": "^4.14.1",
-    "node-watch": "^0.7.1",
     "puppeteer": "^1.20.0",
-    "rollup": "^2.38.5",
-    "rollup-plugin-re": "^1.0.7",
-    "rollup-plugin-sourcemaps": "^0.6.3",
-    "ts-jest": "^25.5.1",
+    "rollup": "^1.32.1",
+    "rollup-plugin-commonjs": "^9.3.4",
+    "rollup-plugin-node-resolve": "^4.2.4",
+    "sorcery": "^0.10.0",
     "tslib": "^1.13.0",
     "tslint": "^5.20.1",
     "typescript": "^3.9.3"
-  },
-  "scripts": {
-    "build": "node build.js",
-    "test": "node build.js --run-tests"
   }
 }
diff --git a/ui/query.html b/ui/query.html
new file mode 100644
index 0000000..bd45758
--- /dev/null
+++ b/ui/query.html
@@ -0,0 +1,84 @@
+<!doctype html>
+<html lang="en-us">
+<head>
+  <title>Perfetto - Query</title>
+  <link rel="icon" type="image/png" href="assets/favicon.png">
+  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
+  <style>
+    * {
+      box-sizing: border-box;
+    }
+
+    #root {
+      margin: 0 auto;
+      max-width: 1200px;
+    }
+
+    input[type=text] {
+      font-size: 150%;
+      width: 100%;
+    }
+
+    .query-list {
+    }
+
+    .query {
+      margin: 2rem 0;
+      border-left: 10px grey;
+      display: grid;
+      grid-template: "text    time"
+                     "content content";
+    }
+
+    .query-content {
+      grid-area: content;
+    }
+
+    .query-content:empty {
+      background: grey;
+    }
+
+    .query-text {
+      grid-area: text;
+      font-family: monospace;
+    }
+
+    .query-time{
+      grid-area: time;
+    }
+
+    table {
+      width: 100%;
+      margin-left: -1rem;
+    }
+
+    tr {
+    }
+
+    tr:hover {
+      background-color: #0000000a;
+    }
+
+    th {
+      font-weight: normal;
+      font-style: italic;
+    }
+
+    td {
+      padding: 0.25rem 0.25rem;
+    }
+
+    tr > td:first-child {
+      padding-left: 1rem;
+    }
+
+    tr > td:last-child {
+      padding-right: 1rem;
+    }
+  </style>
+</head>
+<body>
+  <div id="root"></div>
+  <script src="/query_bundle.js"></script>
+</body>
+</html>
diff --git a/ui/release/OWNERS b/ui/release/OWNERS
deleted file mode 100644
index fe8fd04..0000000
--- a/ui/release/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-set noparent
-eseckler@google.com
-hjd@google.com
-oysteine@google.com
-nyquist@google.com
-primiano@google.com
-skyostil@google.com
diff --git a/ui/release/build_all_channels.py b/ui/release/build_all_channels.py
deleted file mode 100755
index 4a61e5e..0000000
--- a/ui/release/build_all_channels.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-""" Builds all the revisions in channels.json and deploys them if --upload.
-
-See go/perfetto-ui-autopush for docs on how this works end-to-end.
-"""
-
-import argparse
-import json
-import os
-import re
-import shutil
-import subprocess
-import sys
-
-from os.path import dirname
-pjoin = os.path.join
-
-BUCKET_NAME = 'ui.perfetto.dev'
-CUR_DIR = dirname(os.path.abspath(__file__))
-ROOT_DIR = dirname(dirname(CUR_DIR))
-
-
-def check_call_and_log(args):
-  print(' '.join(args))
-  subprocess.check_call(args)
-
-
-def check_output(args):
-  return subprocess.check_output(args).decode().strip()
-
-
-def version_exists(version):
-  url = 'https://commondatastorage.googleapis.com/%s/%s/manifest.json' % (
-      BUCKET_NAME, version)
-  return 0 == subprocess.call(['curl', '-fLs', '-o', '/dev/null', url])
-
-
-def build_git_revision(channel, git_ref, tmp_dir):
-  workdir = pjoin(tmp_dir, channel)
-  check_call_and_log(['rm', '-rf', workdir])
-  check_call_and_log(['git', 'clone', '--quiet', '--shared', ROOT_DIR, workdir])
-  old_cwd = os.getcwd()
-  os.chdir(workdir)
-  try:
-    check_call_and_log(['git', 'reset', '--hard', git_ref])
-    check_call_and_log(['git', 'clean', '-dfx'])
-    git_sha = check_output(['git', 'rev-parse', 'HEAD'])
-    print('===================================================================')
-    print('Building UI for channel %s @ %s (%s)' % (channel, git_ref, git_sha))
-    print('===================================================================')
-    version = check_output(['tools/write_version_header.py', '--stdout'])
-    check_call_and_log(['tools/install-build-deps', '--ui'])
-    check_call_and_log(['ui/build'])
-    return version, pjoin(workdir, 'ui/out/dist')
-  finally:
-    os.chdir(old_cwd)
-
-
-def build_all_channels(channels, tmp_dir, merged_dist_dir):
-  channel_map = {}
-  for chan in channels:
-    channel = chan['name']
-    git_ref = chan['rev']
-    # version here is something like "v1.2.3".
-    version, dist_dir = build_git_revision(channel, git_ref, tmp_dir)
-    channel_map[channel] = version
-    check_call_and_log(['cp', '-an', pjoin(dist_dir, version), merged_dist_dir])
-    if channel != 'stable':
-      continue
-    # Copy also the /index.html and /service_worker.*, but only for the stable
-    # channel. The /index.html and SW must be shared between all channels,
-    # because they are all reachable through ui.perfetto.dev/. Both the index
-    # and the SQ are supposed to be version-independent (go/perfetto-channels).
-    # If an accidental incompatibility bug sneaks in, we should much rather
-    # crash canary (or any other channel) rather than stable. Hence why we copy
-    # the index+sw from the stable channel.
-    for fname in os.listdir(dist_dir):
-      fpath = pjoin(dist_dir, fname)
-      if os.path.isfile(fpath):
-        check_call_and_log(['cp', '-an', fpath, merged_dist_dir])
-  return channel_map
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--upload', action='store_true')
-  parser.add_argument('--tmp', default='/tmp/perfetto_ui')
-  args = parser.parse_args()
-
-  # Read the releases.json, which maps channel names to git refs, e.g.:
-  # {name:'stable', rev:'a0b1c2...0}, {name:'canary', rev:'HEAD'}
-  channels = []
-  with open(pjoin(CUR_DIR, 'channels.json')) as f:
-    channels = json.load(f)['channels']
-
-  merged_dist_dir = pjoin(args.tmp, 'dist')
-  check_call_and_log(['rm', '-rf', merged_dist_dir])
-  shutil.os.makedirs(merged_dist_dir)
-  channel_map = build_all_channels(channels, args.tmp, merged_dist_dir)
-
-  print('Updating index in ' + merged_dist_dir)
-  with open(pjoin(merged_dist_dir, 'index.html'), 'r+') as f:
-    index_html = f.read()
-    f.seek(0, 0)
-    f.truncate()
-    index_html = re.sub(r"data-perfetto_version='[^']*'",
-                        "data-perfetto_version='%s'" % json.dumps(channel_map),
-                        index_html)
-    f.write(index_html)
-
-  if not args.upload:
-    return
-
-  print('===================================================================')
-  print('Uploading to gs://%s' % BUCKET_NAME)
-  print('===================================================================')
-  cp_cmd = [
-      'gsutil', '-m', '-h', 'Cache-Control:public, max-age=3600', 'cp', '-j',
-      'html,js,css,wasm'
-  ]
-  for name in os.listdir(merged_dist_dir):
-    path = pjoin(merged_dist_dir, name)
-    if os.path.isdir(path):
-      if version_exists(name):
-        print('Skipping upload of %s because it already exists on GCS' % name)
-        continue
-      check_call_and_log(cp_cmd + ['-r', path, 'gs://%s/' % BUCKET_NAME])
-    else:
-      # /index.html or /service_worker.js{,.map}
-      check_call_and_log(cp_cmd + [path, 'gs://%s/%s' % (BUCKET_NAME, name)])
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/ui/release/builder_entrypoint.sh b/ui/release/builder_entrypoint.sh
deleted file mode 100755
index 7a940b8..0000000
--- a/ui/release/builder_entrypoint.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See go/perfetto-ui-autopush for docs on how this works end-to-end.
-
-set -exu
-
-CUR_DUR=$(dirname ${BASH_SOURCE[0]})
-
-env
-pwd
-mount
-
-# This script will be run in /workspace after the Cloud Build environment has
-# pulled the GitHub repo in shallow mode. We want to build off the official
-# AOSP repo, not the GitHub mirror though, hence why the clone below.
-# GitHub is used only as a trigger. This is because Google Cloud Build doesn't
-# support yet triggering from Gerrit.
-
-cd /workspace/
-ls -A1 | xargs rm -rf
-UPSTREAM="https://android.googlesource.com/platform/external/perfetto.git"
-git clone $UPSTREAM upstream
-
-cd upstream/
-git rev-parse HEAD
-mkdir /workspace/tmp
-python3 -u "$CUR_DUR/build_all_channels.py" --upload --tmp=/workspace/tmp
diff --git a/ui/release/channels.json b/ui/release/channels.json
deleted file mode 100644
index ffb232f..0000000
--- a/ui/release/channels.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "channels": [
-    {
-      "name": "stable",
-      "rev": "465b9a4473353091c7048b53ad90607295f86a4a"
-    },
-    {
-      "name": "canary",
-      "rev": "a284e65f883e7c543c2619115be1ee0fbe5644a3"
-    },
-    {
-      "name": "autopush",
-      "rev": "HEAD"
-    }
-  ]
-}
diff --git a/ui/rollup.config.js b/ui/rollup.config.js
new file mode 100644
index 0000000..d6389d2
--- /dev/null
+++ b/ui/rollup.config.js
@@ -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.
+
+import commonjs from 'rollup-plugin-commonjs';
+import nodeResolve from 'rollup-plugin-node-resolve';
+
+export default {
+  output: {name: 'perfetto'},
+  plugins:
+      [
+        nodeResolve({
+          mainFields: ['browser'],
+          browser: true,
+          preferBuiltins: false,
+        }),
+
+        // 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/run-dev-server b/ui/run-dev-server
index 201ed63..9faf567 100755
--- a/ui/run-dev-server
+++ b/ui/run-dev-server
@@ -14,4 +14,34 @@
 # limitations under the License.
 
 UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-$UI_DIR/node $UI_DIR/build.js --serve --watch "$@"
+ROOT_DIR=$(dirname "$UI_DIR")
+
+if [ -z "$1" ]; then
+  echo "ERROR: no output directory specified."
+  echo "Usage: $0 out/mac_debug"
+  exit 127
+fi
+OUT_DIR="$1"
+
+echo 'Initial build:'
+$ROOT_DIR/tools/ninja -C $OUT_DIR ui
+
+UI_OUT_DIR="$OUT_DIR/ui"
+if [ ! -d $UI_OUT_DIR ]; then
+  echo "ERROR: cannot find the UI output directory (\"$UI_OUT_DIR\")."
+  echo "Did you run ninja ui?"
+  exit 127
+fi
+
+$ROOT_DIR/tools/dev_server \
+  -p 10000 \
+  -i $ROOT_DIR/.git \
+  -i $ROOT_DIR/src/traced \
+  -i $ROOT_DIR/buildtools \
+  -i $ROOT_DIR/out \
+  -i $ROOT_DIR/infra \
+  -i $ROOT_DIR/ui/node_modules \
+  -s $UI_OUT_DIR \
+  "$ROOT_DIR/tools/ninja -C $OUT_DIR ui"
+
+
diff --git a/ui/run-tests b/ui/run-tests
deleted file mode 100755
index d06f7d2..0000000
--- a/ui/run-tests
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2021 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-
-$UI_DIR/node $UI_DIR/build.js --run-tests "$@"
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 0324899..16fe564 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -116,22 +116,6 @@
     overflow: hidden;
 }
 
-body.filedrag::after {
-  content: 'Drop the trace file to open it';
-  position: fixed;
-  z-index: 99;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  border: 10px dashed #404854;
-  text-align: center;
-  font-size: 3rem;
-  line-height: 100vh;
-  color: #333;
-  background: rgba(255, 255, 255, 0.5);
-}
-
 button {
   background: none;
   color: inherit;
@@ -228,6 +212,25 @@
   }
 }
 
+.home-page {
+    text-align: center;
+    padding-top: 20vh;
+    align-items: center;
+}
+
+.home-page .logo {
+    width: var(--track-shell-width);
+}
+
+.home-page-title {
+    font-size: 60px;
+    margin: 25px;
+    text-align: center;
+    font-family: 'Raleway', sans-serif;
+    font-weight: 100;
+    color: #333;
+}
+
 .query-table-container {
   width: 100%;
   overflow-x: auto;
@@ -367,7 +370,7 @@
   overflow-x: hidden;
   overflow-y: auto;
   flex: 1 1 auto;
-  // TODO(hjd): This causes the sticky header to flicker when scrolling.
+  // TODO(taylori): This causes the sticky header to flicker when scrolling.
   // Is will-change necessary in the details panel?
   // will-change: transform;
   display: grid;
@@ -531,7 +534,6 @@
   --collapsed-background: hsla(190, 49%, 97%, 1);
   --collapsed-transparent: hsla(190, 49%, 97%, 0);
   --expanded-background: hsl(215, 22%, 19%);
-  --expanded-transparent: hsl(215, 22%, 19%, 0);
   display: grid;
   grid-template-columns: auto 1fr;
   grid-template-rows: 1fr;
@@ -545,7 +547,7 @@
     margin-top: -1px;
   }
   &[collapsed=true] {
-    background-color: var(--collapsed-transparent);
+    background-color: var(--collapsed-background-transparent);
     .shell {
       border-right: 1px solid #c7d0db;
       background-color: var(--collapsed-background);
@@ -555,7 +557,7 @@
     };
   }
   &[collapsed=false] {
-    background-color: var(--expanded-transparent);
+    background-color: var(--expanded-background);
     color: white;
     font-weight: bold;
     .shell.flash {
@@ -602,43 +604,3 @@
 .time-selection-panel {
   height: 10px;
 }
-
-
-.cookie-consent {
-  position: absolute;
-  z-index: 10;
-  left: 10px;
-  bottom: 10px;
-  width: 550px;
-  background-color:#19212b;
-  font-size: 14px;
-  color:rgb(180, 183, 186);
-  border-radius: 5px;
-  padding: 20px;
-
-  .buttons {
-    display: flex;
-    justify-content: flex-end;
-    margin-top: 10px;
-    font-size: 15px
-  }
-
-  button {
-    padding: 10px;
-    border-radius: 3px;
-    color: #fff;
-    margin-left: 5px;
-    a {
-      text-decoration: none;
-      color: #fff;
-    }
-  }
-  button:hover {
-    background-color: #373f4b;
-    cursor: pointer;
-  }
-}
-
-.disallow-selection {
-  user-select: none;
-}
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index 85206d0..5efcce5 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -30,7 +30,6 @@
     .tabs {
       display: flex;
       grid-area: tabs;
-      overflow: hidden;
 
       .tab {
         font-family: 'Roboto Condensed', sans-serif;
@@ -43,9 +42,6 @@
         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);
-        overflow: hidden;
-        white-space: nowrap;
-        text-overflow: ellipsis;
 
         &[active] {
           background-color: white;
@@ -79,7 +75,6 @@
 
     .buttons {
       grid-area: buttons;
-      text-align: right;
     }
 
     .handle-title {
@@ -98,7 +93,6 @@
   font-family: 'Roboto Condensed', sans-serif;
   font-weight: 300;
   color: #3c4b5d;
-  user-select: text;
 
   .material-icons {
     @include transition(0.3s);
@@ -123,38 +117,13 @@
     top: 0px;
     display: flex;
     background: white;
+    table {
+      padding: 0 10px;
+      th {
+        font-weight: 500;
+      }
+    }
     &.aggregation {
-      padding-top: 5px;
-      display: grid;
-      grid-template-areas: "description range"
-                            "heading heading";
-      grid-template-columns: 1fr auto;
-      .states {
-        font-size: 11px;
-        margin: 0 10px 2px 10px;
-        display: flex;
-        overflow: hidden;
-        .state {
-          height: 20px;
-          line-height: 20px;
-          padding-left: 3px;
-          padding-right: 3px;
-          border-left: white 1px solid;
-          &:hover {
-            min-width: fit-content;
-          }
-        }
-
-      }
-      .time-range {
-        text-align: right;
-        font-size: 11px;
-        font-weight: 400;
-        margin-right: 5px;
-      }
-      table {
-        grid-area: heading;
-      }
       th {
         cursor: pointer;
         .material-icons {
@@ -228,8 +197,9 @@
     font-size: 14px;
     line-height: 18px;
     width: 100%;
+    table-layout: fixed;
     word-wrap: break-word;
-    padding: 0px 10px;
+    padding: 10px;
     tr:hover {
       background-color: hsl(214, 22%, 90%);
     }
@@ -238,9 +208,6 @@
       width: 30%;
       font-weight: normal;
     }
-    .array-index {
-      text-align: right;
-    }
   }
 
   button {
@@ -257,52 +224,6 @@
   }
 }
 
-.flow-link:hover {
-  cursor: pointer;
-  text-decoration: underline;
-}
-
-.flow-info i.material-icons {
-  color: rgb(60, 86, 136);
-}
-
-.warning {
-  position: relative;
-  font-size: 13px;
-  color: hsl(45, 100%, 48%);
-}
-
-.warning i.material-icons {
-  font-size: 13px;
-}
-
-.warning .tooltip {
-  visibility: hidden;
-
-  background-color: white;
-  color: #3f4040;
-  box-shadow: 1px 3px 15px rgba(23, 32, 44, 0.3);
-
-  padding: 4px;
-  border-radius: 4px;
-
-  text-align: center;
-  white-space: nowrap;
-
-  position: absolute;
-  z-index: 1;
-  top: -5px;
-  left: 105%;
-}
-
-.warning:hover .tooltip {
-  visibility: visible;
-}
-
-.flow-button {
-  color: rgb(60, 86, 136);
-}
-
 table.half-width {
   max-width: 50%;
 }
@@ -352,29 +273,16 @@
   }
 }
 
-.sum {
-  font-weight: bolder;
-  font-size: 12px;
-  .sum-data {
-    border-bottom: 1px solid rgba(60, 76, 92, 0.4);
-  }
-}
-
 .log-panel {
   width: 100%;
   height: 100%;
   display: grid;
   grid-template-rows: auto 1fr;
-  font-family: 'Roboto Condensed', sans-serif;
-  user-select: text;
 
   header {
     position: sticky;
     top: 0px;
     z-index: 1;
-    background-color: white;
-    color: #3c4b5d;
-    padding: 5px;
   }
 
   header.stale {
diff --git a/ui/src/assets/home_page.scss b/ui/src/assets/home_page.scss
deleted file mode 100644
index 8eed245..0000000
--- a/ui/src/assets/home_page.scss
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.home-page {
-  text-align: center;
-  align-items: center;
-  display: grid;
-  grid-template-columns: 1fr;
-  grid-template-rows: 2em 1fr 60px;
-  grid-template-areas: "." "center" "footer";
-
-  .home-page-center {
-    grid-area: center;
-
-    .logo {
-      width: var(--track-shell-width);
-    }
-
-    .home-page-title {
-      font-size: 60px;
-      margin: 25px;
-      text-align: center;
-      font-family: 'Raleway', sans-serif;
-      font-weight: 100;
-      color: #333;
-    }
-
-    .channel-select {
-      font-family: 'Roboto', sans-serif;
-      font-size: 1.2rem;
-      font-weight: 200;
-      margin-top: 3em;
-      --chan-width: 100px;
-      --chan-num: 2;
-
-      input[type=radio] {
-        width: 0;
-        height: 0;
-        margin: 0;
-        padding: 0;
-        -moz-appearance: none;
-        -webkit-appearance: none;
-        &:nth-of-type(1):checked ~ .highlight { margin-left: 0; }
-        &:nth-of-type(2):checked ~ .highlight {
-          margin-left: 100px;
-          background-color: hsl(54, 100%, 40%);
-        }
-        &:nth-of-type(3):checked ~ .highlight {
-          margin-left: 200px;
-          background-color: hsl(24, 80%, 42%);
-        }
-      }
-
-      fieldset {
-        margin: 30px auto 10px auto;
-        padding: 0;
-        position: relative;
-        background-color: hsl(218, 8%, 30%);
-        border-radius: 3px;
-        box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.4);
-        border: 0;
-        width: calc(var(--chan-width) * var(--chan-num));
-        height: 40px;
-        line-height: 40px;
-        z-index: 0;
-      }
-
-      label {
-        display: inline-block;
-        cursor: pointer;
-        position: relative;
-        width: var(--chan-width);
-        height: 100%;
-        color: white;
-        z-index: 2;
-        text-transform: uppercase;
-        font-size: 16px;
-        font-weight: 200;
-        letter-spacing: 0.3px;
-      }
-
-      .highlight {
-        width: var(--chan-width);
-        height: 100%;
-        position: absolute;
-        background: hsla(122, 45%, 45%, 0.99);
-        background-image: linear-gradient(rgba(255, 255, 255, 0.2), transparent);
-        top: 0;
-        left: 0;
-        z-index: 1;
-        border-radius: inherit;
-        @include transition();
-      }
-
-      .home-page-reload {
-        font-size: 12px;
-        opacity: 0;
-        color: #da4534;
-        font-weight: 400;
-        @include transition;
-        &.show { opacity: 1; }
-      }
-    }  // .channel-select
-  }  // .home-page-center
-
-  .privacy {
-    grid-area: footer;
-    text-decoration: none;
-    font-family: 'Roboto', sans-serif;
-    font-weight: 200;
-    color: #333;
-    font-size: 15px;
-  }
-}  // .home-page
diff --git a/ui/src/assets/index.html b/ui/src/assets/index.html
deleted file mode 100644
index 2e9329f..0000000
--- a/ui/src/assets/index.html
+++ /dev/null
@@ -1,118 +0,0 @@
-<!doctype html>
-<html lang="en-us">
-<head>
-  <meta charset="utf-8">
-  <title>Perfetto UI</title>
-  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
-  <link rel="shortcut icon" id="favicon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
-</head>
-<body data-perfetto_version='{"filled_by_build_js":"."}'>
-  <!--
-    Don't add any content here. The whole <body> is replaced by
-    frontend/index.ts when bootstrapping. This is only used for very early
-    error reporting.
-  -->
-  <style>
-  #app_load_failure {opacity:0;transition:opacity 1s ease;position:absolute;background:#080082;top:0;left:0;width:100%;height:100%;bottom:0;right:0;margin:0;opacity:0;user-select:text}
-  #app_load_failure > pre {color:#fff;position:absolute;margin:auto;white-space:pre-wrap;top:50%;transform:translate(0,-50%);max-width:90vw;width:880px;left:0;right:0;font-size:16px;line-height:30px;font-weight:700}
-  #app_load_failure > pre span {background:#fff;color:#080082;padding:2px}
-  #app_load_failure a {color:#fff}
-  #app_load { position: absolute; top: 0; left: 0; right:0; bottom: 0; background-color: #2c3e50;}
-  #app_load_spinner { margin: 30vh auto; width: 150px; height: 150px; border: 3px solid rgba(255,255,255,.3); border-radius: 50%; border-top-color: #fff; animation: app_load_spin 1s ease-in-out infinite; }
-  @keyframes app_load_spin { to { transform: rotate(360deg); } }
-  </style>
-  <div id="app_load"><div id="app_load_spinner"></div></div>
-  <div id="app_load_failure">
-<pre>
-<span>Perfetto UI - An unrecoverable problem occurred</span>
-
-If you are seeing this message, something went wrong while loading the UI.
-Please file a bug (details below) and try these remediation steps:
-
-* Force-reload the page with Ctrl+Shift+R (Mac: Meta+Shift+R) or
-  Shift + click on the refresh button.
-
-* <a href="javascript:clearAllCaches();">Click here</a> to clear all the site storage and caches and reload the page.
-
-* Clear the site data and caches from devtools, following <a target="_blank" href="https://developers.google.com/web/tools/chrome-devtools/storage/cache#deletecache">these instructions</a>.
-
-* If neither of these work, you can use an old fallback instance hosted at
-  <a target="_blank" href="https://staging-dot-perfetto-ui.appspot.com">staging-dot-perfetto-ui.appspot.com</a>
-
-In any case, **FILE A BUG** attaching logs and screenshots from devtools.
-  Googlers:      <a href="http://go/perfetto-ui-bug" target="_blank">go/perfetto-ui-bug</a>
-  Non-googlers:  <a href="https://github.com/google/perfetto/issues/new" target="_blank">github.com/google/perfetto/issues/new</a>
-
-<div id=app_load_failure_err></div>
-Technical Information:
-<div id=app_load_failure_dbg></div>
-</pre>
-  </div>
-  <script type="text/javascript">
-    'use strict';
-    (function () {
-      const TIMEOUT_MS = 20000;
-      let errTimerId = undefined;
-
-      function errHandler(err) {
-        // Note: we deliberately don't clearTimeout(), which means that this
-        // handler is called also in the happy case when the UI loads. In that
-        // case, though, the onCssLoaded() in frontend/index.ts will empty the
-        // <body>, so |div| below will be null and this function becomes a
-        // no-op.
-        const div = document.getElementById('app_load_failure');
-        if (!div) return;
-        div.style.opacity ='1';
-        const errDom = document.getElementById('app_load_failure_err');
-        if (!errDom) return;
-        console.error(err);
-        errDom.innerText += `${err}\n`;
-        const storageJson = JSON.stringify(window.localStorage);
-        const dbg = document.getElementById('app_load_failure_dbg');
-        if (!dbg) return;
-        dbg.innerText = `LocalStorage: ${storageJson}\n`;
-        if (errTimerId !== undefined) clearTimeout(errTimerId);
-      }
-
-      // For the 'Click here to clear all caches'.
-      window.clearAllCaches = () => {
-        if (window.localStorage) window.localStorage.clear();
-        if (window.sessionStorage) window.sessionStorage.clear();
-        const promises = [];
-        if (window.caches) {
-          window.caches.keys().then(
-            keys => keys.forEach(k => promises.push(window.caches.delete(k))));
-        }
-        if (navigator.serviceWorker) {
-          navigator.serviceWorker.getRegistrations().then(regs => {
-            regs.forEach(reg => promises.push(reg.unregister()));
-          });
-        }
-        Promise.all(promises).then(() => window.location.reload());
-      }
-
-      // If the frontend doesn't come up, make the error page above visible.
-      errTimerId = setTimeout(() => errHandler('Timed out'), TIMEOUT_MS);
-      window.onerror = errHandler;
-      window.onunhandledrejection = errHandler;
-
-      const versionStr = document.body.dataset['perfetto_version'] || '{}';
-      const versionMap = JSON.parse(versionStr);
-      const channel = localStorage.getItem('perfettoUiChannel') || 'stable';
-
-      // The '.' below is a fallback for the case of opening a pinned version
-      // (e.g., ui.perfetto.dev/v1.2.3./). In that case, the index.html has no
-      // valid version map; we want to load the frontend from the same
-      // sub-directory directory, hence ./frontend_bundle.js.
-      const version = versionMap[channel] || versionMap['stable'] || '.';
-
-      const script = document.createElement('script');
-      script.async = true;
-      script.src = version + '/frontend_bundle.js';
-      script.onerror = () => errHandler(`Failed to load ${script.src}`);
-
-      document.head.append(script);
-    })();
-  </script>
-</body>
-</html>
diff --git a/ui/src/assets/metrics_page.scss b/ui/src/assets/metrics_page.scss
deleted file mode 100644
index 4881d46..0000000
--- a/ui/src/assets/metrics_page.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.metrics-page {
-  padding: 30px;
-  font-family: 'Raleway', sans-serif;
-  overflow-y: auto;
-
-  .metric-run-button {
-    background-color: #262f3c;
-    color: #fff;
-    border-radius: 4px;
-    padding: 5px 10px;
-    font-weight: bold;
-    font-family: 'Raleway';
-  }
-
-  select {
-    margin: 10px;
-    font-family: 'Raleway';
-    font-size: 1em;
-    border: 1px solid black;
-    background-color: #eee;
-  }
-
-  pre {
-    background-color: #eee;
-    padding: 20px;
-    font-family: 'Roboto Mono';
-    line-height: 1.5em;
-    border-radius: 5px;
-    user-select: text;
-    overflow-x: auto;
-    &.metric-error {
-      color: #EF6C00;
-    }
-  }
-}
diff --git a/ui/src/assets/modal.scss b/ui/src/assets/modal.scss
index 0f54b00..c46db21 100644
--- a/ui/src/assets/modal.scss
+++ b/ui/src/assets/modal.scss
@@ -186,11 +186,9 @@
 
 .modal-pre {
   white-space: pre-line;
-  font-size: 13px;
-  user-select: text;
 }
 
-.modal-logs, .modal-bash {
+.modal-logs {
   white-space: pre-wrap;
   border: 1px solid #999;
   background: #eee;
@@ -198,26 +196,7 @@
   font-family: monospace;
   -webkit-user-select: text;
   margin-top: 10px;
-  margin-bottom: 10px;
   min-height: 50px;
   max-height: 40vh;
   overflow: scroll;
-}
-
-.modal-bash {
-  margin: 0;
-  padding: 5px 0;
-  overflow: auto;
-  min-height: 0;
-}
-
-.modal-textarea {
-  display: block;
-  margin-top: 10px;
-  margin-bottom: 10px;
-  width: 100%;
-}
-
-.modal-small {
-  font-size: 11px;
-}
+}
\ No newline at end of file
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index d3cc23a..f08e774 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -14,12 +14,9 @@
 
 @import 'typefaces';
 @import 'common';
-@import 'home_page';
 @import 'analyze_page';
-@import 'metrics_page';
 @import 'sidebar';
 @import 'topbar';
 @import 'record';
 @import 'modal';
 @import 'details';
-@import 'trace_info_page';
diff --git a/ui/src/assets/rec_cpu_wakeup.png b/ui/src/assets/rec_cpu_wakeup.png
new file mode 100644
index 0000000..0792a63
--- /dev/null
+++ b/ui/src/assets/rec_cpu_wakeup.png
Binary files differ
diff --git a/ui/src/assets/rec_frame_timeline.png b/ui/src/assets/rec_frame_timeline.png
deleted file mode 100644
index 2c83762..0000000
--- a/ui/src/assets/rec_frame_timeline.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/rec_gpu_mem_total.png b/ui/src/assets/rec_gpu_mem_total.png
deleted file mode 100644
index 4b5a44a..0000000
--- a/ui/src/assets/rec_gpu_mem_total.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/rec_syscalls.png b/ui/src/assets/rec_syscalls.png
deleted file mode 100644
index 734854a..0000000
--- a/ui/src/assets/rec_syscalls.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index 6b0a762..4f98127 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -152,9 +152,9 @@
   }
 
   .note {
-    border-radius: 3px;
-    margin-bottom: 5px;
+    border: 1px dashed #ddd;
     background: #f9eeba;
+    margin: var(--record-section-padding);
     padding: 10px;
     font-family: 'Roboto', sans-serif;
     font-size: 14px;
@@ -280,88 +280,10 @@
   }
 
   &.active {
-    display: block;
+    display: grid;
     opacity: 1;
   }
 
-  .config {
-    &:nth-of-type(2n) {
-      background-color: #e7e7e7;
-    }
-
-    height: auto;
-    width: 100%;
-    padding: 0px;
-    display: flex;
-    align-items: center;
-  }
-
-  .title-config {
-    display: inline-block;
-    margin: var(--record-section-padding);
-    flex-grow: 1;
-    word-break: break-all;
-  }
-
-  .config-button {
-    border-radius: 10px;
-    margin-right: 10px;
-    text-align: center;
-    justify-items: center;
-    font-family: 'Raleway', sans-serif;
-    padding: 7px;
-    width: 75px;
-
-    &:hover {
-      box-shadow: 0 0 4px 0px #999;
-    }
-
-    &.load {
-      background-color: hsl(88, 50%, 67%);
-    }
-
-    &.delete {
-      background-color: hsl(0, 50%, 67%);
-    }
-
-    &.save {
-      width: 160px;
-      background-color: hsl(197, 50%, 67%);
-    }
-  }
-
-  .input-config {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    display: flex;
-    align-items: center;
-    padding: 0px;
-
-    input {
-      border-radius: 20px;
-      border-color: #0000003d;
-      line-height: 36px;
-      padding: 0 10px;
-      font-size: 18px;
-      font-family: 'Roboto Condensed', sans-serif;
-      font-weight: 300;
-      color: #666;
-      flex-grow: 1;
-      margin-right: 10px;
-      margin-left: 10px;
-
-      background-color: transparent;
-      &:focus {
-        outline: none;
-      }
-      &::placeholder {
-        color: #b4b7ba;
-        font-family: 'Raleway', sans-serif;
-        font-weight: 400;
-      }
-    }
-  }
-
   // By default space all section elements by the same amount.
   --record-section-padding: 20px;
 
@@ -506,78 +428,6 @@
     }
   }  // probe
 
-  .toggle {
-    transition: color 0.2s ease;
-    padding-top: var(--record-section-padding);
-
-    &:hover {
-      >img { opacity: 1; }
-      >label {
-        color: #333;
-        input[type=checkbox]::after {
-          background: hsl(207, 60%, 60%);
-        }
-      }
-    }  // :hover
-
-    >label {
-      cursor: pointer;
-      font-size: 14px;
-      color: var(--record-text-color);
-
-      // The per-probe on-off switch.
-      input[type=checkbox] {
-        -moz-appearance: none;
-        -webkit-appearance: none;
-        cursor: pointer;
-        margin: 0 12px 0 2px;
-        position: relative;
-        display: inline-block;
-        height: 10px;
-        width: 22px;
-        background: #89898966;
-        border-radius: 100px;
-        transition: all 0.3s ease;
-        overflow: visible;
-        vertical-align: middle;
-
-        &:focus {
-          outline: none;
-        }
-
-        &::after {
-          position: absolute;
-          left: -5px;
-          top: -5px;
-          display: block;
-          width: 20px;
-          height: 20px;
-          border-radius: 100px;
-          background: #f5f5f5;
-          box-shadow: 0px 3px 3px rgba(0,0,0,0.15);
-          content: '';
-          transition: all 0.3s ease;
-        }
-        &:checked {
-          background: #8398b7;
-        }
-        &:focus::after {
-          background: hsl(207, 60%, 60%);
-        }
-        &:checked::after {
-          left: 12px;
-          background: #27303d;
-        }
-      }  // checkbox
-    }  // label
-
-    // The content of the toggle section.
-    >div.descr {
-      font-size: 12px;
-      color: #666;
-    }
-  }  // toggle
-
   // The three "Stop when full", "Ring buffer", "Long trace" buttons.
   .record-mode {
     display: grid;
@@ -1022,22 +872,6 @@
       }
     }
 
-    .permalinkconfig {
-      margin: var(--record-section-padding);
-      height: 40px;
-      max-width: 200px;
-      border-radius: 10px;
-      text-align: center;
-      justify-items: center;
-      font-family: 'Raleway', sans-serif;
-      padding: 7px;
-      background-color: hsl(88, 50%, 67%);
-
-      &:hover {
-        box-shadow: 0 0 4px 0px #999;
-      }
-    }
-
     progress {
       -webkit-appearance: none;
       appearance: none;
@@ -1054,28 +888,3 @@
     }
   }
 }  // record-section
-
-.inline-chip { 
-  @include transition();
-  &:hover, &:active {
-    box-shadow: 0 0 2px 0px #ccc;
-    background-color: #fafafa;
-  }
-
-  >i.material-icons {
-    color: rgb(60, 60, 60);
-    font-size: 14px;
-  }
-
-  line-height: 25px;
-  font-size: smaller;
-  padding: 2px 4px;
-  border: 1px solid #eee;
-  margin: 2px;
-  border-radius: 9px;
-}
-
-a.inline-chip, a.inline-chip:link, a.inline-chip:visited {
-  text-decoration: none;
-  color: var(--record-text-color);
-}
diff --git a/ui/src/assets/sidebar.scss b/ui/src/assets/sidebar.scss
index 8bded2f..a25b715 100644
--- a/ui/src/assets/sidebar.scss
+++ b/ui/src/assets/sidebar.scss
@@ -43,23 +43,6 @@
           height: 40px;
           margin-top: 4px;
         }
-        &.canary::before, &.autopush::before {
-          display: block;
-          position: absolute;
-          font-size: 10px;
-          line-height: 10px;
-          font-family: 'Roboto', sans-serif;
-          left: 155px;
-          top: 7px;
-        }
-        &.canary::before {
-          content: 'CANARY';
-          color: #ffd700;
-        }
-        &.autopush::before {
-          content: 'AUTOPUSH';
-          color: #aed581;
-        }
     }
     .sidebar-button {
       position: absolute;
@@ -67,6 +50,7 @@
       background-color: #262f3c;
       height: var(--topbar-height);
       left: calc(var(--sidebar-width) - 50px);
+      padding-top: 3px;
       border-radius: 0 5px 5px 0;
       border-bottom: inherit;
       visibility: visible;  // So stays visible when the sidebar is hidden.
@@ -171,26 +155,6 @@
                     padding: 5px 24px;
                     text-decoration: none;
                     display: block;
-                    &.pending {
-                      color: rgba(255, 255, 255, 0.3);
-                      &::after {
-                        content: ' ';
-                        display: inline-block;
-                        vertical-align: middle;
-                        box-sizing: border-box;
-                        width: 18px;
-                        height: 18px;
-                        margin-left: 10px;
-                        border-radius: 50%;
-                        border: 2px solid #b4b7ba;
-                        border-color: #b4b7ba transparent #b4b7ba transparent;
-                        animation: pending-spinner 1.25s linear infinite;
-                      }
-                      @keyframes pending-spinner {
-                        0% { transform: rotate(0deg); }
-                        100% { transform: rotate(360deg); }
-                      }
-                    }
                     &[disabled] {
                       text-decoration: line-through;
                     }
@@ -219,7 +183,6 @@
     .sidebar-footer {
       position: absolute;
       bottom: 0;
-      width: 100%;
       padding: 2px 10px;
       display: grid;
       height: - var(--sidebar-padding-bottom);
@@ -264,19 +227,6 @@
           line-height: 11px;
         }
       }
-
-      .version {
-        position: absolute;
-        right: 8px;
-        bottom: 3px;
-        font-size: 12px;
-        font-family: 'Roboto Condensed', 'Roboto', sans-serif;
-        a {
-          color: rgba(255, 255, 255, 0.5);
-          text-decoration: none;
-        }
-        margin-top: 11px;
-      }
     }
 }
 
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index 4ab3907..7daa9fc 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -36,7 +36,7 @@
         border-radius: 20px;
         background-color: #fcfcfc;
         border: 0;
-        line-height: 34px;
+        line-height: 36px;
         &:before {
             @include material-icon('search');
             margin: 5px;
@@ -62,6 +62,7 @@
             }
         }
         &.command-mode {
+            // background-color: #354252;
             background-color: #111;
             border-radius: 0;
             width: 100%;
@@ -188,18 +189,8 @@
     }
 }
 
-.error {
-    position: absolute;
-    right: 10px;
-    color: #EF6C00;
-    &:hover {
-        cursor:pointer;
-    }
-}
-
 .helpful-hint {
   position: absolute;
-  z-index: 10;
   right: 5px;
   top: 5px;
   width: 300px;
@@ -223,9 +214,3 @@
   padding: 3px;
   border-radius: 3px;
 }
-
-.hide-sidebar {
-  .command-mode {
-    padding-left: 48px;
-  }
-}
diff --git a/ui/src/assets/trace_info_page.scss b/ui/src/assets/trace_info_page.scss
deleted file mode 100644
index 38c6f9d..0000000
--- a/ui/src/assets/trace_info_page.scss
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.trace-info-page {
-  overflow-y: auto;
-  overflow-x: hidden;
-  padding: 0 20px;
-  user-select: text;
-
-  section {
-    margin: 20px auto;
-    max-width: 800px;
-    font-size: 1rem;
-    padding: 20px;
-    border-radius: 8px;
-
-    &.errors {
-      background-color: #F3E5F5;
-    }
-
-    .metric-error {
-      font-family: var(--monospace-font);
-      font-size: 12px;
-      padding: 5px;
-      word-break: break-all;
-    }
-
-    h2 {
-      font-family: 'Raleway', sans-serif;
-      font-weight: 400;
-      letter-spacing: 0.25px;
-      font-size: 2rem;
-      margin-bottom: 1rem;
-    }
-
-    h3 {
-      font-size: 0.9rem;
-      font-weight: 400;
-      line-height: 1.25rem;
-      margin: 10px 0;
-      color: #333;
-    }
-
-    .contextual-help {
-      font-size: 18px;
-      margin-left: 10px;
-      color: #43a047;
-      cursor: default;
-    }
-
-    table {
-      border-spacing: 4px 1px;
-
-      thead td {
-        margin-bottom: 5px;
-        padding-bottom: 5px;
-        border-bottom: 1px solid #333;
-        font-weight: 500;
-      }
-      tr td {
-        min-height: 20px;
-      }
-
-      tbody {
-        tr:nth-child(2n + 1) td {
-          background-color: rgba(0, 0, 0, 0.04);
-        }
-
-        td {
-          font-family: var(--monospace-font);
-          font-size: 12px;
-          padding: 5px;
-          word-break: break-all;
-          white-space: pre-wrap;
-          &:first-of-type {
-            font-weight: 800;
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/ui/src/assets/typefaces.scss b/ui/src/assets/typefaces.scss
index 5e4ba16..b5999b3 100644
--- a/ui/src/assets/typefaces.scss
+++ b/ui/src/assets/typefaces.scss
@@ -52,7 +52,6 @@
 }
 
 .material-icons {
-  font-display: block;
   font-family: 'Material Icons';
   font-weight: normal;
   font-style: normal;
diff --git a/ui/src/base/binary_search.ts b/ui/src/base/binary_search.ts
index 72a16ce..a9cef33 100644
--- a/ui/src/base/binary_search.ts
+++ b/ui/src/base/binary_search.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 type Numbers = Float64Array|Uint32Array|number[];
 type Range = [number, number];
 
diff --git a/ui/src/base/extract_utils.ts b/ui/src/base/extract_utils.ts
new file mode 100644
index 0000000..a82bfbf
--- /dev/null
+++ b/ui/src/base/extract_utils.ts
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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/logging.ts b/ui/src/base/logging.ts
index 75a02ca..caefe56 100644
--- a/ui/src/base/logging.ts
+++ b/ui/src/base/logging.ts
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import * as version from '../gen/perfetto_version';
-
 export type ErrorHandler = (err: string) => void;
 
 let errorHandler: ErrorHandler = (_: string) => {};
@@ -52,15 +50,13 @@
   } else {
     errLog = `${err}`;
   }
-  if (errorObj !== undefined && errorObj !== null) {
+  if (errorObj !== undefined) {
     const errStack = (errorObj as {stack?: string}).stack;
     errLog += '\n';
     errLog += errStack !== undefined ? errStack : JSON.stringify(errorObj);
   }
-  errLog += '\n\n';
-  errLog += `${version.VERSION} ${version.SCM_REVISION}\n`;
-  errLog += `UA: ${navigator.userAgent}\n`;
+  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
index bf44d97..efe8fb0 100644
--- a/ui/src/base/string_utils.ts
+++ b/ui/src/base/string_utils.ts
@@ -12,87 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {
-  decode as b64Decode,
-  encode as b64Encode,
-  length as b64Len
-} from '@protobufjs/base64';
-import {
-  length as utf8Len,
-  read as utf8Read,
-  write as utf8Write
-} from '@protobufjs/utf8';
-
-import {assertTrue} from './logging';
-
-// TextDecoder/Decoder requires the full DOM and isn't available in all types
-// of tests. Use fallback implementation from protbufjs.
-let UTF8Decoder: {decode: (buf: Uint8Array) => string;};
-let UTF8Encoder: {encode: (str: string) => Uint8Array;};
-try {
-  UTF8Decoder = new TextDecoder('utf-8');
-  UTF8Encoder = new TextEncoder();
-} catch (_) {
-  if (typeof process === 'undefined') {
-    // Silence the warning when we know we are running under NodeJS.
-    console.warn(
-        'Using fallback UTF8 Encoder/Decoder, This should happen only in ' +
-        'tests and NodeJS-based environments, not in browsers.');
-  }
-  UTF8Decoder = {decode: (buf: Uint8Array) => utf8Read(buf, 0, buf.length)};
-  UTF8Encoder = {
-    encode: (str: string) => {
-      const arr = new Uint8Array(utf8Len(str));
-      const written = utf8Write(str, arr, 0);
-      assertTrue(written === arr.length);
-      return arr;
-    }
-  };
+export function uint8ArrayToBase64(buffer: Uint8Array): string {
+  return btoa(uint8ArrayToString(buffer));
 }
 
-export function base64Encode(buffer: Uint8Array): string {
-  return b64Encode(buffer, 0, buffer.length);
+// 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 base64Decode(str: string): Uint8Array {
-  const arr = new Uint8Array(b64Len(str));
-  const written = b64Decode(str, arr, 0);
-  assertTrue(written === arr.length);
-  return arr;
-}
-
-export function utf8Encode(str: string): Uint8Array {
-  return UTF8Encoder.encode(str);
-}
-
-// Note: not all byte sequences can be converted to<>from UTF8. This can be
-// used only with valid unicode strings, not arbitrary byte buffers.
-export function utf8Decode(buffer: Uint8Array): string {
-  return UTF8Decoder.decode(buffer);
-}
-
-// The binaryEncode/Decode functions below allow to encode an arbitrary binary
-// buffer into a string that can be JSON-encoded. binaryEncode() applies
-// UTF-16 encoding to each byte individually.
-// Unlike utf8Encode/Decode, any arbitrary byte sequence can be converted into a
-// valid string, and viceversa.
-// This should be only used when a byte array needs to be transmitted over an
-// interface that supports only JSON serialization (e.g., postmessage to a
-// chrome extension).
-
-export function binaryEncode(buf: Uint8Array): string {
-  let str = '';
-  for (let i = 0; i < buf.length; i++) {
-    str += String.fromCharCode(buf[i]);
-  }
-  return str;
-}
-
-export function binaryDecode(str: string): Uint8Array {
-  const buf = new Uint8Array(str.length);
+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++) {
-    buf[i] = str.charCodeAt(i);
+    bufView[i] = str.charCodeAt(i);
   }
-  return buf;
-}
+  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
new file mode 100644
index 0000000..e8bae93
--- /dev/null
+++ b/ui/src/base/string_utils_jsdomtest.ts
@@ -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.
+
+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/string_utils_unittest.ts b/ui/src/base/string_utils_unittest.ts
deleted file mode 100644
index c8dce8e..0000000
--- a/ui/src/base/string_utils_unittest.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {
-  base64Decode,
-  base64Encode,
-  binaryDecode,
-  binaryEncode,
-  utf8Decode,
-  utf8Encode,
-} from './string_utils';
-
-test('string_utils.stringToBase64', () => {
-  const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
-  const buffer = new Uint8Array(bytes);
-  const b64Encoded = base64Encode(buffer);
-  expect(b64Encoded).toEqual('SGVsbG8sIHdvcmxk');
-  expect(base64Decode(b64Encoded)).toEqual(buffer);
-});
-
-test('string_utils.bufferToBase64', () => {
-  const buffer = new Uint8Array([0xff, 0, 0, 0x81, 0x2a, 0xfe]);
-  const b64Encoded = base64Encode(buffer);
-  expect(b64Encoded).toEqual('/wAAgSr+');
-  expect(base64Decode(b64Encoded)).toEqual(buffer);
-});
-
-test('string_utils.utf8EncodeAndDecode', () => {
-  const testString = '¡HéllØ wörld!';
-  const buffer = utf8Encode(testString);
-  expect(buffer).toEqual(new Uint8Array([
-    194,
-    161,
-    72,
-    195,
-    169,
-    108,
-    108,
-    195,
-    152,
-    32,
-    119,
-    195,
-    182,
-    114,
-    108,
-    100,
-    33
-  ]));
-  expect(utf8Decode(buffer)).toEqual(testString);
-});
-
-test('string_utils.binaryEncodeAndDecode', () => {
-  const buf = new Uint8Array(256 + 4);
-  for (let i = 0; i < 256; i++) {
-    buf[i] = i;
-  }
-  buf.set([0xf0, 0x28, 0x8c, 0xbc], 256);
-  const encodedStr = binaryEncode(buf);
-  expect(encodedStr.length).toEqual(buf.length);
-  const encodedThroughJson = JSON.parse(JSON.stringify(encodedStr));
-  expect(binaryDecode(encodedStr)).toEqual(buf);
-  expect(binaryDecode(encodedThroughJson)).toEqual(buf);
-});
diff --git a/ui/src/base/trace_config_utils.ts b/ui/src/base/trace_config_utils.ts
deleted file mode 100644
index 3a08963..0000000
--- a/ui/src/base/trace_config_utils.ts
+++ /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 {TraceConfig} from '../common/protos';
-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;
-  }
-}
-
-export function browserSupportsPerfettoConfig(): boolean {
-  const minimumChromeVersion = '91.0.4448.0';
-  const runningVersion = String(
-      (/Chrome\/(([0-9]+\.?){4})/.exec(navigator.userAgent) || [, 0])[1]);
-
-  if (!runningVersion) return false;
-
-  const minVerArray = minimumChromeVersion.split('.').map(Number);
-  const runVerArray = runningVersion.split('.').map(Number);
-
-  for (let index = 0; index < minVerArray.length; index++) {
-    if (runVerArray[index] === minVerArray[index]) continue;
-    return runVerArray[index] > minVerArray[index];
-  }
-  return true;  // Exact version match.
-}
-
-export function hasSystemDataSourceConfig(config: TraceConfig): boolean {
-  for (const ds of config.dataSources) {
-    if (ds.config && ds.config.name &&
-        !ds.config.name.startsWith('org.chromium.')) {
-      return true;
-    }
-  }
-  return false;
-}
diff --git a/ui/src/chrome_extension/chrome_tracing_controller.ts b/ui/src/chrome_extension/chrome_tracing_controller.ts
index 73642ab..280068a 100644
--- a/ui/src/chrome_extension/chrome_tracing_controller.ts
+++ b/ui/src/chrome_extension/chrome_tracing_controller.ts
@@ -16,12 +16,7 @@
 import {ProtocolProxyApi} from 'devtools-protocol/types/protocol-proxy-api';
 import * as rpc from 'noice-json-rpc';
 
-import {base64Encode} from '../base/string_utils';
-import {
-  browserSupportsPerfettoConfig,
-  extractTraceConfig,
-  hasSystemDataSourceConfig
-} from '../base/trace_config_utils';
+import {extractTraceConfig} from '../base/extract_utils';
 import {TraceConfig} from '../common/protos';
 import {
   ConsumerPortResponse,
@@ -33,6 +28,8 @@
 
 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 {
@@ -96,8 +93,9 @@
       this.sendErrorMessage('Invalid trace config');
       return;
     }
-
-    this.handleStartTracing(traceConfigProto);
+    const traceConfig = TraceConfig.decode(traceConfigProto);
+    const chromeConfig = this.extractChromeConfig(traceConfig);
+    this.handleStartTracing(chromeConfig);
   }
 
   toCamelCase(key: string, separator: string): string {
@@ -237,7 +235,7 @@
     this.lastBufferUsageEvent = params;
   }
 
-  handleStartTracing(traceConfigProto: Uint8Array) {
+  handleStartTracing(traceConfig: Protocol.Tracing.TraceConfig) {
     this.devtoolsSocket.attachToBrowser(async (error?: string) => {
       if (error) {
         this.sendErrorMessage(
@@ -245,35 +243,13 @@
             `(req. Chrome >= M81): ${error}`);
         return;
       }
-
-      const requestParams: Protocol.Tracing.StartRequest = {
+      await this.api.Tracing.start({
+        traceConfig,
         streamFormat: 'proto',
         transferMode: 'ReturnAsStream',
         streamCompression: 'gzip',
         bufferUsageReportingInterval: 200
-      };
-
-      if (browserSupportsPerfettoConfig()) {
-        const configEncoded = base64Encode(traceConfigProto);
-        await this.api.Tracing.start(
-            {perfettoConfig: configEncoded, ...requestParams});
-      } else {
-        console.log(
-            'Used Chrome version is too old to support ' +
-            'perfettoConfig parameter. Using chrome config only instead.');
-
-        const traceConfig = TraceConfig.decode(traceConfigProto);
-        if (hasSystemDataSourceConfig(traceConfig)) {
-          this.sendErrorMessage(
-              'System tracing is not supported by this Chrome version. Choose' +
-              ' the \'Chrome\' target instead to record a Chrome-only trace.');
-          return;
-        }
-
-        const chromeConfig = this.extractChromeConfig(traceConfig);
-        await this.api.Tracing.start(
-            {traceConfig: chromeConfig, ...requestParams});
-      }
+      });
     });
   }
 }
diff --git a/ui/src/chrome_extension/index.ts b/ui/src/chrome_extension/index.ts
index 6a55b21..6350c84 100644
--- a/ui/src/chrome_extension/index.ts
+++ b/ui/src/chrome_extension/index.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {binaryDecode} from '../base/string_utils';
+import {stringToUint8Array} from '../base/string_utils';
 import {ChromeTracingController} from './chrome_tracing_controller';
 
 let chromeTraceController: ChromeTracingController|undefined = undefined;
@@ -38,7 +38,7 @@
   // ChromeExtensionConsumerPort sends the request data as string because
   // chrome.runtime.port doesn't support ArrayBuffers.
   const requestDataArray: Uint8Array = message.requestData ?
-      binaryDecode(message.requestData) :
+      stringToUint8Array(message.requestData) :
       new Uint8Array();
   chromeTraceController.handleCommand(message.method, requestDataArray);
 }
diff --git a/ui/src/chrome_extension/manifest.json b/ui/src/chrome_extension/manifest.json
index 62b405e..5008c01 100644
--- a/ui/src/chrome_extension/manifest.json
+++ b/ui/src/chrome_extension/manifest.json
@@ -2,7 +2,7 @@
   "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.13",
+  "version": "0.0.0.11",
   "manifest_version": 2,
   "minimum_chrome_version": "81.0.4022.0",
   "permissions": [
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index e982bc9..d297813f 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -14,30 +14,19 @@
 
 import {Draft} from 'immer';
 
-import {assertExists, assertTrue} from '../base/logging';
-import {randomColor} from '../common/colorizer';
+import {assertExists} from '../base/logging';
+import {
+  Area,
+  CallsiteInfo,
+  HeapProfileFlamegraphViewingOption
+} from '../common/state';
 import {ConvertTrace, ConvertTraceToPprof} from '../controller/trace_converter';
-import {ACTUAL_FRAMES_SLICE_TRACK_KIND} from '../tracks/actual_frames/common';
-import {ASYNC_SLICE_TRACK_KIND} from '../tracks/async_slices/common';
-import {COUNTER_TRACK_KIND} from '../tracks/counter/common';
-import {DEBUG_SLICE_TRACK_KIND} from '../tracks/debug_slices/common';
-import {
-  EXPECTED_FRAMES_SLICE_TRACK_KIND
-} from '../tracks/expected_frames/common';
-import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
-import {
-  PROCESS_SCHEDULING_TRACK_KIND
-} from '../tracks/process_scheduling/common';
-import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary/common';
 
 import {DEFAULT_VIEWING_OPTION} from './flamegraph_util';
 import {
   AdbRecordingTarget,
-  Area,
-  CallsiteInfo,
   createEmptyState,
   EngineMode,
-  HeapProfileFlamegraphViewingOption,
   LogsPagination,
   NewEngineMode,
   OmniboxState,
@@ -46,38 +35,26 @@
   SCROLLING_TRACK_GROUP,
   State,
   Status,
+  TimestampedAreaSelection,
   TraceSource,
   TraceTime,
-  TrackKindPriority,
   TrackState,
   VisibleState,
 } from './state';
 
 type StateDraft = Draft<State>;
 
-const highPriorityTrackOrder = [
-  PROCESS_SCHEDULING_TRACK_KIND,
-  PROCESS_SUMMARY_TRACK,
-  EXPECTED_FRAMES_SLICE_TRACK_KIND,
-  ACTUAL_FRAMES_SLICE_TRACK_KIND
-];
-
-const lowPriorityTrackOrder =
-    [HEAP_PROFILE_TRACK_KIND, COUNTER_TRACK_KIND, ASYNC_SLICE_TRACK_KIND];
-
 export interface AddTrackArgs {
   id?: string;
   engineId: string;
   kind: string;
   name: string;
-  trackKindPriority: TrackKindPriority;
   trackGroup?: string;
   config: {};
 }
 
 export interface PostedTrace {
   title: string;
-  fileName?: string;
   url?: string;
   buffer: ArrayBuffer;
 }
@@ -87,7 +64,6 @@
   const recordConfig = state.recordConfig;
   const route = state.route;
   const recordingTarget = state.recordingTarget;
-  const updateChromeCategories = state.updateChromeCategories;
   const extensionInstalled = state.extensionInstalled;
   const availableAdbDevices = state.availableAdbDevices;
   const chromeCategories = state.chromeCategories;
@@ -98,27 +74,12 @@
   state.recordConfig = recordConfig;
   state.route = route;
   state.recordingTarget = recordingTarget;
-  state.updateChromeCategories = updateChromeCategories;
   state.extensionInstalled = extensionInstalled;
   state.availableAdbDevices = availableAdbDevices;
   state.chromeCategories = chromeCategories;
   state.newEngineMode = newEngineMode;
 }
 
-function rank(ts: TrackState): number[] {
-  const hpRank = rankIndex(ts.kind, highPriorityTrackOrder);
-  const lpRank = rankIndex(ts.kind, lowPriorityTrackOrder);
-  // TODO(hjd): Create sortBy object on TrackState to avoid this cast.
-  const tid = (ts.config as {tid?: number}).tid || 0;
-  return [hpRank, ts.trackKindPriority.valueOf(), lpRank, tid];
-}
-
-function rankIndex<T>(element: T, array: T[]): number {
-  const index = array.indexOf(element);
-  if (index === -1) return array.length;
-  return index;
-}
-
 export const StateActions = {
 
   navigate(state: StateDraft, args: {route: string}): void {
@@ -176,9 +137,8 @@
 
   // TODO(b/141359485): Actions should only modify state.
   convertTraceToJson(
-      state: StateDraft, args: {file: Blob, truncate?: 'start'|'end'}): void {
-    state.traceConversionInProgress = true;
-    ConvertTrace(args.file, 'json', args.truncate);
+      _: StateDraft, args: {file: Blob, truncate?: 'start'|'end'}): void {
+    ConvertTrace(args.file, args.truncate);
   },
 
   convertTraceToPprof(
@@ -187,10 +147,6 @@
     ConvertTraceToPprof(args.pid, args.src, args.ts1, args.ts2);
   },
 
-  clearConversionInProgress(state: StateDraft, _args: {}): void {
-    state.traceConversionInProgress = false;
-  },
-
   addTracks(state: StateDraft, args: {tracks: AddTrackArgs[]}) {
     args.tracks.forEach(track => {
       const id = track.id === undefined ? `${state.nextId++}` : track.id;
@@ -206,7 +162,7 @@
 
   addTrack(state: StateDraft, args: {
     id?: string; engineId: string; kind: string; name: string;
-    trackGroup?: string; config: {}; trackKindPriority: TrackKindPriority;
+    trackGroup?: string; config: {};
   }): void {
     const id = args.id !== undefined ? args.id : `${state.nextId++}`;
     state.tracks[id] = {
@@ -214,7 +170,6 @@
       engineId: args.engineId,
       kind: args.kind,
       name: args.name,
-      trackKindPriority: args.trackKindPriority,
       trackGroup: args.trackGroup,
       config: args.config,
     };
@@ -234,62 +189,11 @@
         collapsed: boolean;
       }): void {
     state.trackGroups[args.id] = {
-      engineId: args.engineId,
-      name: args.name,
-      id: args.id,
-      collapsed: args.collapsed,
-      tracks: [args.summaryTrackId],
+      ...args,
+      tracks: [],
     };
   },
 
-  addDebugTrack(state: StateDraft, args: {engineId: string, name: string}):
-      void {
-        if (state.debugTrackId !== undefined) return;
-        const trackId = `${state.nextId++}`;
-        state.debugTrackId = trackId;
-        this.addTrack(state, {
-          id: trackId,
-          engineId: args.engineId,
-          kind: DEBUG_SLICE_TRACK_KIND,
-          name: args.name,
-          trackKindPriority: TrackKindPriority.ORDINARY,
-          trackGroup: SCROLLING_TRACK_GROUP,
-          config: {
-            maxDepth: 1,
-          }
-        });
-        this.toggleTrackPinned(state, {trackId});
-      },
-
-  removeDebugTrack(state: StateDraft, _: {}): void {
-    const {debugTrackId} = state;
-    if (debugTrackId === undefined) return;
-    delete state.tracks[debugTrackId];
-    state.scrollingTracks =
-        state.scrollingTracks.filter(id => id !== debugTrackId);
-    state.pinnedTracks = state.pinnedTracks.filter(id => id !== debugTrackId);
-    state.debugTrackId = undefined;
-  },
-
-  sortThreadTracks(state: StateDraft, _: {}): void {
-    // Use a numeric collator so threads are sorted as T1, T2, ..., T10, T11,
-    // rather than T1, T10, T11, ..., T2, T20, T21 .
-    const coll = new Intl.Collator([], {sensitivity: 'base', numeric: true});
-    for (const group of Object.values(state.trackGroups)) {
-      group.tracks.sort((a: string, b: string) => {
-        const aRank = rank(state.tracks[a]);
-        const bRank = rank(state.tracks[b]);
-        for (let i = 0; i < aRank.length; i++) {
-          if (aRank[i] !== bRank[i]) return aRank[i] - bRank[i];
-        }
-
-        const aName = state.tracks[a].name.toLocaleLowerCase();
-        const bName = state.tracks[b].name.toLocaleLowerCase();
-        return coll.compare(aName, bName);
-      });
-    }
-  },
-
   updateAggregateSorting(
       state: StateDraft, args: {id: string, column: string}) {
     let prefs = state.aggregatePreferences[args.id];
@@ -391,23 +295,11 @@
         trackGroup.collapsed = !trackGroup.collapsed;
       },
 
-  requestTrackReload(state: StateDraft, _: {}) {
-    if (state.lastTrackReloadRequest) {
-      state.lastTrackReloadRequest++;
-    } else {
-      state.lastTrackReloadRequest = 1;
-    }
-  },
-
   setEngineReady(
       state: StateDraft,
       args: {engineId: string; ready: boolean, mode: EngineMode}): void {
-    const engine = state.engines[args.engineId];
-    if (engine === undefined) {
-      return;
-    }
-    engine.ready = args.ready;
-    engine.mode = args.mode;
+    state.engines[args.engineId].ready = args.ready;
+    state.engines[args.engineId].mode = args.mode;
   },
 
   setNewEngineMode(state: StateDraft, args: {mode: NewEngineMode}): void {
@@ -422,12 +314,8 @@
         }
       },
 
-  createPermalink(state: StateDraft, args: {isRecordingConfig: boolean}): void {
-    state.permalink = {
-      requestId: `${state.nextId++}`,
-      hash: undefined,
-      isRecordingConfig: args.isRecordingConfig
-    };
+  createPermalink(state: StateDraft, _: {}): void {
+    state.permalink = {requestId: `${state.nextId++}`, hash: undefined};
   },
 
   setPermalink(state: StateDraft, args: {requestId: string; hash: string}):
@@ -438,7 +326,10 @@
       },
 
   loadPermalink(state: StateDraft, args: {hash: string}): void {
-    state.permalink = {requestId: `${state.nextId++}`, hash: args.hash};
+    state.permalink = {
+      requestId: `${state.nextId++}`,
+      hash: args.hash,
+    };
   },
 
   clearPermalink(state: StateDraft, _: {}): void {
@@ -481,7 +372,7 @@
   addNote(
       state: StateDraft,
       args: {timestamp: number, color: string, isMovie: boolean}): void {
-    const id = `${state.nextNoteId++}`;
+    const id = `${state.nextId++}`;
     state.notes[id] = {
       noteType: 'DEFAULT',
       id,
@@ -495,56 +386,21 @@
     this.selectNote(state, {id});
   },
 
-  markCurrentArea(
-      state: StateDraft, args: {color: string, persistent: boolean}):
+  addAreaNote(
+      state: StateDraft, args: {timestamp: number, area: Area, color: string}):
       void {
-        if (state.currentSelection === null ||
-            state.currentSelection.kind !== 'AREA') {
-          return;
-        }
-        const id = args.persistent ? `${state.nextNoteId++}` : '0';
-        const color = args.persistent ? args.color : '#344596';
+        const id = `${state.nextId++}`;
         state.notes[id] = {
           noteType: 'AREA',
           id,
-          areaId: state.currentSelection.areaId,
-          color,
+          timestamp: args.timestamp,
+          area: args.area,
+          color: args.color,
           text: '',
         };
-        state.currentSelection.noteId = id;
+        this.selectNote(state, {id});
       },
 
-  toggleMarkCurrentArea(state: StateDraft, args: {persistent: boolean}) {
-    const selection = state.currentSelection;
-    if (selection != null && selection.kind === 'AREA' &&
-        selection.noteId !== undefined) {
-      this.removeNote(state, {id: selection.noteId});
-    } else {
-      const color = randomColor();
-      this.markCurrentArea(state, {color, persistent: args.persistent});
-    }
-  },
-
-  markArea(state: StateDraft, args: {area: Area, persistent: boolean}): void {
-    const areaId = `${state.nextAreaId++}`;
-    assertTrue(args.area.endSec >= args.area.startSec);
-    state.areas[areaId] = {
-      id: areaId,
-      startSec: args.area.startSec,
-      endSec: args.area.endSec,
-      tracks: args.area.tracks
-    };
-    const id = args.persistent ? `${state.nextNoteId++}` : '0';
-    const color = args.persistent ? randomColor() : '#344596';
-    state.notes[id] = {
-      noteType: 'AREA',
-      id,
-      areaId,
-      color,
-      text: '',
-    };
-  },
-
   toggleVideo(state: StateDraft, _: {}): void {
     state.videoEnabled = !state.videoEnabled;
     if (!state.videoEnabled) {
@@ -587,23 +443,16 @@
   },
 
   removeNote(state: StateDraft, args: {id: string}): void {
-    if (state.notes[args.id] === undefined) return;
     if (state.notes[args.id].noteType === 'MOVIE') {
       state.videoNoteIds = state.videoNoteIds.filter(id => {
         return id !== args.id;
       });
     }
     delete state.notes[args.id];
-    // For regular notes, we clear the current selection but for an area note
-    // we only want to clear the note/marking and leave the area selected.
     if (state.currentSelection === null) return;
     if (state.currentSelection.kind === 'NOTE' &&
         state.currentSelection.id === args.id) {
       state.currentSelection = null;
-    } else if (
-        state.currentSelection.kind === 'AREA' &&
-        state.currentSelection.noteId === args.id) {
-      state.currentSelection.noteId = undefined;
     }
   },
 
@@ -638,6 +487,11 @@
       ts: args.ts,
       type: args.type,
     };
+  },
+
+  showHeapProfileFlamegraph(
+      state: StateDraft,
+      args: {id: number, upid: number, ts: number, type: string}): void {
     state.currentHeapProfileFlamegraph = {
       kind: 'HEAP_PROFILE_FLAMEGRAPH',
       id: args.id,
@@ -689,14 +543,24 @@
         };
       },
 
-  selectThreadState(state: StateDraft, args: {id: number, trackId: string}):
-      void {
-        state.currentSelection = {
-          kind: 'THREAD_STATE',
-          id: args.id,
-          trackId: args.trackId,
-        };
-      },
+  selectThreadState(state: StateDraft, args: {
+    utid: number,
+    ts: number,
+    dur: number,
+    state: string,
+    cpu: number,
+    trackId: 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,
+    };
+  },
 
   deselect(state: StateDraft, _: {}): void {
     state.currentSelection = null;
@@ -733,10 +597,6 @@
     state.recordingTarget = args.target;
   },
 
-  setUpdateChromeCategories(state: StateDraft, args: {update: boolean}): void {
-    state.updateChromeCategories = args.update;
-  },
-
   setAvailableAdbDevices(
       state: StateDraft, args: {devices: AdbRecordingTarget[]}): void {
     state.availableAdbDevices = args.devices;
@@ -746,63 +606,8 @@
     state.frontendLocalState.omniboxState = args;
   },
 
-  selectArea(state: StateDraft, args: {area: Area}): void {
-    const areaId = `${state.nextAreaId++}`;
-    assertTrue(args.area.endSec >= args.area.startSec);
-    state.areas[areaId] = {
-      id: areaId,
-      startSec: args.area.startSec,
-      endSec: args.area.endSec,
-      tracks: args.area.tracks
-    };
-    state.currentSelection = {kind: 'AREA', areaId};
-  },
-
-  editArea(state: StateDraft, args: {area: Area, areaId: string}): void {
-    assertTrue(args.area.endSec >= args.area.startSec);
-    state.areas[args.areaId] = {
-      id: args.areaId,
-      startSec: args.area.startSec,
-      endSec: args.area.endSec,
-      tracks: args.area.tracks
-    };
-  },
-
-  reSelectArea(state: StateDraft, args: {areaId: string, noteId: string}):
-      void {
-        state.currentSelection = {
-          kind: 'AREA',
-          areaId: args.areaId,
-          noteId: args.noteId
-        };
-      },
-
-  toggleTrackSelection(
-      state: StateDraft, args: {id: string, isTrackGroup: boolean}) {
-    const selection = state.currentSelection;
-    if (selection === null || selection.kind !== 'AREA') return;
-    const areaId = selection.areaId;
-    const index = state.areas[areaId].tracks.indexOf(args.id);
-    if (index > -1) {
-      state.areas[areaId].tracks.splice(index, 1);
-      if (args.isTrackGroup) {  // Also remove all child tracks.
-        for (const childTrack of state.trackGroups[args.id].tracks) {
-          const childIndex = state.areas[areaId].tracks.indexOf(childTrack);
-          if (childIndex > -1) {
-            state.areas[areaId].tracks.splice(childIndex, 1);
-          }
-        }
-      }
-    } else {
-      state.areas[areaId].tracks.push(args.id);
-      if (args.isTrackGroup) {  // Also add all child tracks.
-        for (const childTrack of state.trackGroups[args.id].tracks) {
-          if (!state.areas[areaId].tracks.includes(childTrack)) {
-            state.areas[areaId].tracks.push(childTrack);
-          }
-        }
-      }
-    }
+  selectArea(state: StateDraft, args: TimestampedAreaSelection): void {
+    state.frontendLocalState.selectedArea = args;
   },
 
   setVisibleTraceTime(state: StateDraft, args: VisibleState): void {
@@ -825,34 +630,7 @@
 
   setAnalyzePageQuery(state: StateDraft, args: {query: string}): void {
     state.analyzePageQuery = args.query;
-  },
-
-  requestSelectedMetric(state: StateDraft, _: {}): void {
-    if (!state.metrics.availableMetrics) throw Error('No metrics available');
-    if (state.metrics.selectedIndex === undefined) {
-      throw Error('No metric selected');
-    }
-    state.metrics.requestedMetric =
-        state.metrics.availableMetrics[state.metrics.selectedIndex];
-  },
-
-  resetMetricRequest(state: StateDraft, args: {name: string}): void {
-    if (state.metrics.requestedMetric !== args.name) return;
-    state.metrics.requestedMetric = undefined;
-  },
-
-  setAvailableMetrics(state: StateDraft, args: {metrics: string[]}): void {
-    state.metrics.availableMetrics = args.metrics;
-    if (args.metrics.length > 0) state.metrics.selectedIndex = 0;
-  },
-
-  setMetricSelectedIndex(state: StateDraft, args: {index: number}): void {
-    if (!state.metrics.availableMetrics ||
-        args.index >= state.metrics.availableMetrics.length) {
-      throw Error('metric selection out of bounds');
-    }
-    state.metrics.selectedIndex = args.index;
-  },
+  }
 };
 
 // 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 8cf6acf..686da55 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -14,71 +14,26 @@
 
 import {produce} from 'immer';
 
-import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
-import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
-import {
-  PROCESS_SCHEDULING_TRACK_KIND
-} from '../tracks/process_scheduling/common';
-import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state/common';
-
 import {StateActions} from './actions';
 import {
   createEmptyState,
   SCROLLING_TRACK_GROUP,
   State,
   TraceUrlSource,
-  TrackKindPriority,
+  TrackState,
 } from './state';
 
-function fakeTrack(state: State, args: {
-  id: string,
-  kind?: string,
-  trackGroup?: string,
-  trackKindPriority?: TrackKindPriority,
-  name?: string,
-  tid?: string
-}): State {
-  return produce(state, draft => {
-    StateActions.addTrack(draft, {
-      id: args.id,
-      engineId: '0',
-      kind: args.kind || 'SOME_TRACK_KIND',
-      name: args.name || 'A track',
-      trackKindPriority: args.trackKindPriority === undefined ?
-          TrackKindPriority.ORDINARY :
-          args.trackKindPriority,
-      trackGroup: args.trackGroup || SCROLLING_TRACK_GROUP,
-      config: {tid: args.tid || '0'}
-    });
-  });
-}
-
-function fakeTrackGroup(
-    state: State, args: {id: string, summaryTrackId: string}): State {
-  return produce(state, draft => {
-    StateActions.addTrackGroup(draft, {
-      name: 'A group',
-      id: args.id,
-      engineId: '0',
-      collapsed: false,
-      summaryTrackId: args.summaryTrackId
-    });
-  });
-}
-
-function pinnedAndScrollingTracks(
-    state: State,
-    ids: string[],
-    pinnedTracks: string[],
-    scrollingTracks: string[]): State {
-  for (const id of ids) {
-    state = fakeTrack(state, {id});
-  }
-  state = produce(state, draft => {
-    draft.pinnedTracks = pinnedTracks;
-    draft.scrollingTracks = scrollingTracks;
-  });
-  return state;
+function fakeTrack(state: State, id: string): TrackState {
+  const track: TrackState = {
+    id,
+    engineId: '1',
+    kind: 'SOME_TRACK_KIND',
+    name: 'A track',
+    trackGroup: SCROLLING_TRACK_GROUP,
+    config: {},
+  };
+  state.tracks[id] = track;
+  return track;
 }
 
 test('navigate', () => {
@@ -94,7 +49,6 @@
       engineId: '1',
       kind: 'cpu',
       name: 'Cpu 1',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       trackGroup: SCROLLING_TRACK_GROUP,
       config: {},
     });
@@ -104,7 +58,6 @@
       engineId: '2',
       kind: 'cpu',
       name: 'Cpu 2',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       trackGroup: SCROLLING_TRACK_GROUP,
       config: {},
     });
@@ -115,8 +68,8 @@
 });
 
 test('add track to track group', () => {
-  let state = createEmptyState();
-  state = fakeTrack(state, {id: 's'});
+  const state = createEmptyState();
+  fakeTrack(state, 's');
 
   const afterGroup = produce(state, draft => {
     StateActions.addTrackGroup(draft, {
@@ -134,14 +87,12 @@
       engineId: '1',
       kind: 'slices',
       name: 'renderer 1',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       trackGroup: '123-123-123',
       config: {},
     });
   });
 
-  expect(afterTrackAdd.trackGroups['123-123-123'].tracks[0]).toBe('s');
-  expect(afterTrackAdd.trackGroups['123-123-123'].tracks[1]).toBe('1');
+  expect(afterTrackAdd.trackGroups['123-123-123'].tracks[0]).toBe('1');
 });
 
 test('reorder tracks', () => {
@@ -150,14 +101,12 @@
       engineId: '1',
       kind: 'cpu',
       name: 'Cpu 1',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       config: {},
     });
     StateActions.addTrack(draft, {
       engineId: '2',
       kind: 'cpu',
       name: 'Cpu 2',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       config: {},
     });
   });
@@ -178,8 +127,12 @@
 });
 
 test('reorder pinned to scrolling', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a', 'b'], ['c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a', 'b'];
+  state.scrollingTracks = ['c'];
 
   const after = produce(state, draft => {
     StateActions.moveTrack(draft, {
@@ -194,8 +147,12 @@
 });
 
 test('reorder scrolling to pinned', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a'], ['b', 'c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a'];
+  state.scrollingTracks = ['b', 'c'];
 
   const after = produce(state, draft => {
     StateActions.moveTrack(draft, {
@@ -210,8 +167,12 @@
 });
 
 test('reorder clamp bottom', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a', 'b'], ['c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a', 'b'];
+  state.scrollingTracks = ['c'];
 
   const after = produce(state, draft => {
     StateActions.moveTrack(draft, {
@@ -224,8 +185,12 @@
 });
 
 test('reorder clamp top', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a'], ['b', 'c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a'];
+  state.scrollingTracks = ['b', 'c'];
 
   const after = produce(state, draft => {
     StateActions.moveTrack(draft, {
@@ -238,8 +203,12 @@
 });
 
 test('pin', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a'], ['b', 'c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a'];
+  state.scrollingTracks = ['b', 'c'];
 
   const after = produce(state, draft => {
     StateActions.toggleTrackPinned(draft, {
@@ -251,8 +220,12 @@
 });
 
 test('unpin', () => {
-  let state = createEmptyState();
-  state = pinnedAndScrollingTracks(state, ['a', 'b', 'c'], ['a', 'b'], ['c']);
+  const state = createEmptyState();
+  fakeTrack(state, 'a');
+  fakeTrack(state, 'b');
+  fakeTrack(state, 'c');
+  state.pinnedTracks = ['a', 'b'];
+  state.scrollingTracks = ['c'];
 
   const after = produce(state, draft => {
     StateActions.toggleTrackPinned(draft, {
@@ -294,7 +267,6 @@
       engineId: '1',
       kind: 'cpu',
       name: 'Cpu 1',
-      trackKindPriority: TrackKindPriority.ORDINARY,
       config: {},
     });
   });
@@ -313,116 +285,3 @@
   expect(thrice.scrollingTracks.length).toBe(0);
   expect(thrice.route).toBe('/viewer');
 });
-
-test('setEngineReady with missing engine is ignored', () => {
-  const state = createEmptyState();
-  produce(state, draft => {
-    StateActions.setEngineReady(
-        draft, {engineId: '1', ready: true, mode: 'WASM'});
-  });
-});
-
-test('setEngineReady', () => {
-  const state = createEmptyState();
-  state.nextId = 100;
-  const after = produce(state, draft => {
-    StateActions.openTraceFromUrl(draft, {
-      url: 'https://example.com/bar',
-    });
-    StateActions.setEngineReady(
-        draft, {engineId: '100', ready: true, mode: 'WASM'});
-  });
-  expect(after.engines['100'].ready).toBe(true);
-});
-
-test('sortTracksByPriority', () => {
-  let state = createEmptyState();
-  state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'b'});
-  state = fakeTrack(
-      state, {id: 'b', kind: HEAP_PROFILE_TRACK_KIND, trackGroup: 'g'});
-  state = fakeTrack(
-      state, {id: 'a', kind: PROCESS_SCHEDULING_TRACK_KIND, trackGroup: 'g'});
-
-  const after = produce(state, draft => {
-    StateActions.sortThreadTracks(draft, {});
-  });
-
-  // High Priority tracks should be sorted before Low Priority tracks:
-  // 'b' appears twice because it's the summary track
-  expect(after.trackGroups['g'].tracks).toEqual(['a', 'b', 'b']);
-});
-
-test('sortTracksByPriorityAndKindAndName', () => {
-  let state = createEmptyState();
-  state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'b'});
-  state = fakeTrack(
-      state, {id: 'a', kind: PROCESS_SCHEDULING_TRACK_KIND, trackGroup: 'g'});
-  state = fakeTrack(state, {
-    id: 'b',
-    kind: SLICE_TRACK_KIND,
-    trackGroup: 'g',
-    trackKindPriority: TrackKindPriority.MAIN_THREAD
-  });
-  state = fakeTrack(state, {
-    id: 'c',
-    kind: SLICE_TRACK_KIND,
-    trackGroup: 'g',
-    trackKindPriority: TrackKindPriority.RENDER_THREAD
-  });
-  state = fakeTrack(state, {
-    id: 'd',
-    kind: SLICE_TRACK_KIND,
-    trackGroup: 'g',
-    trackKindPriority: TrackKindPriority.GPU_COMPLETION
-  });
-  state = fakeTrack(
-      state, {id: 'e', kind: HEAP_PROFILE_TRACK_KIND, trackGroup: 'g'});
-  state = fakeTrack(
-      state, {id: 'f', kind: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T2'});
-  state = fakeTrack(
-      state, {id: 'g', kind: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T10'});
-
-  const after = produce(state, draft => {
-    StateActions.sortThreadTracks(draft, {});
-  });
-
-  // The order should be determined by:
-  // 1.High priority
-  // 2.Non ordinary track kinds
-  // 3.Low priority
-  // 4.Collated name string (ie. 'T2' will be before 'T10')
-  expect(after.trackGroups['g'].tracks)
-      .toEqual(['a', 'b', 'b', 'c', 'd', 'e', 'f', 'g']);
-});
-
-test('sortTracksByTidThenName', () => {
-  let state = createEmptyState();
-  state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'a'});
-  state = fakeTrack(state, {
-    id: 'a',
-    kind: SLICE_TRACK_KIND,
-    trackGroup: 'g',
-    name: 'aaa',
-    tid: '1'
-  });
-  state = fakeTrack(state, {
-    id: 'b',
-    kind: SLICE_TRACK_KIND,
-    trackGroup: 'g',
-    name: 'bbb',
-    tid: '2'
-  });
-  state = fakeTrack(state, {
-    id: 'c',
-    kind: THREAD_STATE_TRACK_KIND,
-    trackGroup: 'g',
-    name: 'ccc',
-    tid: '1'
-  });
-
-  const after = produce(state, draft => {
-    StateActions.sortThreadTracks(draft, {});
-  });
-
-  expect(after.trackGroups['g'].tracks).toEqual(['a', 'a', 'c', 'b']);
-});
diff --git a/ui/src/common/aggregation_data.ts b/ui/src/common/aggregation_data.ts
index 8887857..2558e17 100644
--- a/ui/src/common/aggregation_data.ts
+++ b/ui/src/common/aggregation_data.ts
@@ -35,12 +35,10 @@
   data: Uint16Array;
 }
 
-type TypedArrayConstructor =
-    Uint16ArrayConstructor|Float64ArrayConstructor|Uint32ArrayConstructor;
+type TypedArrayConstructor = Uint16ArrayConstructor|Float64ArrayConstructor;
 export interface ColumnDef {
   title: string;
   kind: string;
-  sum?: boolean;
   columnConstructor: TypedArrayConstructor;
   columnId: string;
 }
@@ -48,16 +46,6 @@
 export interface AggregateData {
   tabName: string;
   columns: Column[];
-  columnSums: string[];
   // For string interning.
   strings: string[];
-  // Some aggregations will have extra info to display;
-  extra?: ThreadStateExtra;
-}
-
-export interface ThreadStateExtra {
-  kind: 'THREAD_STATE';
-  states: string[];
-  values: Float64Array;
-  totalMs: number;
 }
\ No newline at end of file
diff --git a/ui/src/common/arg_types.ts b/ui/src/common/arg_types.ts
deleted file mode 100644
index 6ca6a04..0000000
--- a/ui/src/common/arg_types.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2021 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.
-
-export type Arg = string|{kind: 'SLICE', trackId: string, sliceId: number};
-export type Args = Map<string, Arg>;
-
-export type ArgsTree = ArgsTreeMap|ArgsTreeArray|string;
-export type ArgsTreeArray = ArgsTree[];
-export interface ArgsTreeMap {
-  [key: string]: ArgsTree;
-}
-
-export function isArgTreeArray(item: ArgsTree): item is ArgsTreeArray {
-  return typeof item === 'object' && item.length !== undefined;
-}
-
-export function isArgTreeMap(item: ArgsTree): item is ArgsTreeMap {
-  return typeof item === 'object' && item.length === undefined;
-}
diff --git a/ui/src/common/canvas_utils.ts b/ui/src/common/canvas_utils.ts
index 96c0fc9..391d7ef 100644
--- a/ui/src/common/canvas_utils.ts
+++ b/ui/src/common/canvas_utils.ts
@@ -13,23 +13,19 @@
 // limitations under the License.
 
 export function cropText(str: string, charWidth: number, rectWidth: number) {
+  const maxTextWidth = rectWidth - 1;
   let displayText = '';
-  const maxLength = Math.floor(rectWidth / charWidth) - 1;
-  if (str.length <= maxLength) {
+  const nameLength = str.length * charWidth;
+  if (nameLength < maxTextWidth) {
     displayText = str;
   } else {
-    let limit = maxLength;
-    let maybeTripleDot = '';
-    if (maxLength > 1) {
-      limit = maxLength - 1;
-      maybeTripleDot = '\u2026';
+    // -3 for the 3 ellipsis.
+    const displayedChars = Math.floor(maxTextWidth / charWidth) - 3;
+    if (displayedChars >= 2) {
+      displayText = str.substring(0, displayedChars) + '...';
+    } else if (displayedChars >= -2) {
+      displayText = str.substring(0, 1);
     }
-    // Javascript strings are UTF-16. |limit| could point in the middle of a
-    // 32-bit double-wchar codepoint (e.g., an emoji). Here we detect if the
-    // |limit|-th wchar is a leading surrogate and attach the trailing one.
-    const lastCharCode = str.charCodeAt(limit - 1);
-    limit += (lastCharCode >= 0xD800 && lastCharCode < 0xDC00) ? 1 : 0;
-    displayText = str.substring(0, limit) + maybeTripleDot;
   }
   return displayText;
 }
diff --git a/ui/src/common/canvas_utils_unittest.ts b/ui/src/common/canvas_utils_unittest.ts
deleted file mode 100644
index 19363bf..0000000
--- a/ui/src/common/canvas_utils_unittest.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {cropText} from './canvas_utils';
-
-test('cropHelper regular text', () => {
-  const tripleDot = '\u2026';
-  const emoji = '\uD83D\uDE00';
-  expect(cropText(
-             'com.android.camera [4096]',
-             /*charWidth=*/ 5,
-             /*rectWidth=*/ 2 * 5))
-      .toBe('c');
-  expect(cropText('com.android.camera [4096]', 5, 4 * 5 + 2))
-      .toBe('co' + tripleDot);
-  expect(cropText('com.android.camera [4096]', 5, 5 * 5 + 2))
-      .toBe('com' + tripleDot);
-  expect(cropText('com.android.camera [4096]', 5, 13 * 5 + 2))
-      .toBe('com.android' + tripleDot);
-  expect(cropText('com.android.camera [4096]', 5, 26 * 5 + 2))
-      .toBe('com.android.camera [4096]');
-  expect(cropText(emoji + 'abc', 5, 2 * 5)).toBe(emoji);
-  expect(cropText(emoji + 'abc', 5, 5 * 5)).toBe(emoji + 'a' + tripleDot);
-});
diff --git a/ui/src/common/colorizer.ts b/ui/src/common/colorizer.ts
deleted file mode 100644
index 9adde38..0000000
--- a/ui/src/common/colorizer.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {hsl} from 'color-convert';
-
-export interface Color {
-  c: string;
-  h: number;
-  s: number;
-  l: number;
-  a?: number;
-}
-
-const MD_PALETTE: Color[] = [
-  {c: 'red', h: 4, s: 90, l: 58},
-  {c: 'pink', h: 340, s: 82, l: 52},
-  {c: 'purple', h: 291, s: 64, l: 42},
-  {c: 'deep purple', h: 262, s: 52, l: 47},
-  {c: 'indigo', h: 231, s: 48, l: 48},
-  {c: 'blue', h: 207, s: 90, l: 54},
-  {c: 'light blue', h: 199, s: 98, l: 48},
-  {c: 'cyan', h: 187, s: 100, l: 42},
-  {c: 'teal', h: 174, s: 100, l: 29},
-  {c: 'green', h: 122, s: 39, l: 49},
-  {c: 'light green', h: 88, s: 50, l: 53},
-  {c: 'lime', h: 66, s: 70, l: 54},
-  {c: 'amber', h: 45, s: 100, l: 51},
-  {c: 'orange', h: 36, s: 100, l: 50},
-  {c: 'deep orange', h: 14, s: 100, l: 57},
-  {c: 'brown', h: 16, s: 25, l: 38},
-  {c: 'blue gray', h: 200, s: 18, l: 46},
-  {c: 'yellow', h: 54, s: 100, l: 62},
-];
-
-const GREY_COLOR: Color = {
-  c: 'grey',
-  h: 0,
-  s: 0,
-  l: 62
-};
-
-function hash(s: string, max: number): number {
-  let hash = 0x811c9dc5 & 0xfffffff;
-  for (let i = 0; i < s.length; i++) {
-    hash ^= s.charCodeAt(i);
-    hash = (hash * 16777619) & 0xffffffff;
-  }
-  return Math.abs(hash) % max;
-}
-
-export function hueForCpu(cpu: number): number {
-  return (128 + (32 * cpu)) % 256;
-}
-
-const DESAT_RED: Color = {
-  c: 'desat red',
-  h: 3,
-  s: 30,
-  l: 49
-};
-const DARK_GREEN: Color = {
-  c: 'dark green',
-  h: 120,
-  s: 44,
-  l: 34
-};
-const LIME_GREEN: Color = {
-  c: 'lime green',
-  h: 75,
-  s: 55,
-  l: 47
-};
-const TRANSPARENT_WHITE: Color = {
-  c: 'white',
-  h: 0,
-  s: 1,
-  l: 97,
-  a: 0.55,
-};
-const ORANGE: Color = {
-  c: 'orange',
-  h: 36,
-  s: 100,
-  l: 50
-};
-const INDIGO: Color = {
-  c: 'indigo',
-  h: 231,
-  s: 48,
-  l: 48
-};
-
-export function colorForState(state: string): Readonly<Color> {
-  if (state === 'Running') {
-    return DARK_GREEN;
-  } else if (state.startsWith('Runnable')) {
-    return LIME_GREEN;
-  } else if (state.includes('Uninterruptible Sleep')) {
-    if (state.includes('non-IO')) {
-      return DESAT_RED;
-    }
-    return ORANGE;
-  } else if (state.includes('Sleeping')) {
-    return TRANSPARENT_WHITE;
-  }
-  return INDIGO;
-}
-
-export function textColorForState(stateCode: string): string {
-  const background = colorForState(stateCode);
-  return background.l > 80 ? '#404040' : '#fff';
-}
-
-export function colorForTid(tid: number): Color {
-  const colorIdx = hash(tid.toString(), MD_PALETTE.length);
-  return Object.assign({}, MD_PALETTE[colorIdx]);
-}
-
-export function colorForThread(thread?: {pid?: number, tid: number}): Color {
-  if (thread === undefined) {
-    return Object.assign({}, GREY_COLOR);
-  }
-  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]);
-}
-
-// Chooses a color uniform at random based on hash(sliceName).  Returns [hue,
-// saturation, lightness].
-//
-// Prefer converting this to an RGB color using hsluv, not the browser's
-// built-in vanilla HSL handling.  This is because this function chooses
-// hue/lightness uniform at random, but HSL is not perceptually uniform.  See
-// https://www.boronine.com/2012/03/26/Color-Spaces-for-Human-Beings/.
-//
-// If isSelected, the color will be particularly dark, making it stand out.
-export function hslForSlice(
-    sliceName: string, isSelected: boolean|null): [number, number, number] {
-  const hue = hash(sliceName, 360);
-  // Saturation 100 would give the most differentiation between colors, but it's
-  // garish.
-  const saturation = 80;
-  const lightness = isSelected ? 30 : hash(sliceName + 'x', 40) + 40;
-  return [hue, saturation, lightness];
-}
diff --git a/ui/src/common/colorizer_unittest.ts b/ui/src/common/colorizer_unittest.ts
deleted file mode 100644
index d3ed01e..0000000
--- a/ui/src/common/colorizer_unittest.ts
+++ /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.
-
-import {colorForThread, hueForCpu} from './colorizer';
-
-const PROCESS_A_THREAD_A = {
-  tid: 100,
-  pid: 100,
-};
-
-const PROCESS_A_THREAD_B = {
-  tid: 101,
-  pid: 100,
-};
-
-const PROCESS_B_THREAD_A = {
-  tid: 200,
-  pid: 200,
-};
-
-const PROCESS_UNK_THREAD_A = {
-  tid: 42,
-};
-
-const PROCESS_UNK_THREAD_B = {
-  tid: 42,
-};
-
-test('it gives threads colors by pid if present', () => {
-  const colorAA = colorForThread(PROCESS_A_THREAD_A);
-  const colorAB = colorForThread(PROCESS_A_THREAD_B);
-  const colorBA = colorForThread(PROCESS_B_THREAD_A);
-  expect(colorAA).toEqual(colorAB);
-  expect(colorAA).not.toEqual(colorBA);
-});
-
-test('it gives threads colors by tid if pid missing', () => {
-  const colorUnkA = colorForThread(PROCESS_UNK_THREAD_A);
-  const colorUnkB = colorForThread(PROCESS_UNK_THREAD_B);
-  expect(colorUnkA).toEqual(colorUnkB);
-});
-
-test('it copies colors', () => {
-  const a = colorForThread(PROCESS_A_THREAD_A);
-  const b = colorForThread(PROCESS_A_THREAD_A);
-  expect(a === b).toEqual(false);
-});
-
-test('it gives different cpus different hues', () => {
-  expect(hueForCpu(0)).not.toEqual(hueForCpu(1));
-});
diff --git a/ui/src/common/constants.ts b/ui/src/common/constants.ts
deleted file mode 100644
index 30a7a2d..0000000
--- a/ui/src/common/constants.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 const TRACE_SUFFIX = '.perfetto-trace';
-
-export const TRACE_MARGIN_TIME_S = 1 / 1e7;
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index 3d387d4..9e89581 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -18,7 +18,6 @@
   RawQueryArgs,
   RawQueryResult
 } from './protos';
-import {iter, NUM_NULL, slowlyCountRows, STR} from './query_iterator';
 import {TimeSpan} from './time';
 
 export interface LoadingTracker {
@@ -31,8 +30,6 @@
   endLoading(): void {}
 }
 
-export class QueryError extends Error {}
-
 /**
  * Abstract interface of a trace proccessor.
  * This is the TypeScript equivalent of src/trace_processor/rpc.h.
@@ -73,8 +70,8 @@
   abstract rawQuery(rawQueryArgs: Uint8Array): Promise<Uint8Array>;
 
   /*
-   * Performs computation of metrics and returns metric result and any errors.
-   * Metric result is a proto binary or text encoded TraceMetrics object.
+   * Performs computation of metrics and returns a proto-encoded TraceMetrics
+   * object.
    */
   abstract rawComputeMetric(computeMetricArgs: Uint8Array): Promise<Uint8Array>;
 
@@ -82,17 +79,7 @@
    * Shorthand for sending a SQL query to the engine.
    * Deals with {,un}marshalling of request/response args.
    */
-  async query(sqlQuery: string): Promise<RawQueryResult> {
-    const result = await this.uncheckedQuery(sqlQuery);
-    if (result.error) {
-      throw new QueryError(`Query error "${sqlQuery}": ${result.error}`);
-    }
-    return result;
-  }
-
-  // This method is for noncritical queries that shouldn't throw an error
-  // on failure. The caller must handle the failure.
-  async uncheckedQuery(sqlQuery: string): Promise<RawQueryResult> {
+  async query(sqlQuery: string, userQuery = false): Promise<RawQueryResult> {
     this.loadingTracker.beginLoading();
     try {
       const args = new RawQueryArgs();
@@ -101,7 +88,9 @@
       const argsEncoded = RawQueryArgs.encode(args).finish();
       const respEncoded = await this.rawQuery(argsEncoded);
       const result = RawQueryResult.decode(respEncoded);
-      return result;
+      if (!result.error || userQuery) return result;
+      // Query failed, throw an error since it was not a user query
+      throw new Error(`Query error "${sqlQuery}": ${result.error}`);
     } finally {
       this.loadingTracker.endLoading();
     }
@@ -114,20 +103,15 @@
   async computeMetric(metrics: string[]): Promise<ComputeMetricResult> {
     const args = new ComputeMetricArgs();
     args.metricNames = metrics;
-    args.format = ComputeMetricArgs.ResultFormat.TEXTPROTO;
     const argsEncoded = ComputeMetricArgs.encode(args).finish();
     const respEncoded = await this.rawComputeMetric(argsEncoded);
-    const result = ComputeMetricResult.decode(respEncoded);
-    if (result.error.length > 0) {
-      throw new QueryError(result.error);
-    }
-    return result;
+    return ComputeMetricResult.decode(respEncoded);
   }
 
   async queryOneRow(query: string): Promise<number[]> {
     const result = await this.query(query);
     const res: number[] = [];
-    if (slowlyCountRows(result) === 0) return res;
+    if (result.numRecords === 0) return res;
     for (const col of result.columns) {
       if (col.longValues!.length === 0) {
         console.error(
@@ -147,7 +131,7 @@
     if (!this._cpus) {
       const result =
           await this.query('select distinct(cpu) from sched order by cpu;');
-      if (slowlyCountRows(result) === 0) return [];
+      if (result.numRecords === 0) return [];
       this._cpus = result.columns[0].longValues!.map(n => +n);
     }
     return this._cpus;
@@ -177,25 +161,4 @@
     const res = (await this.queryOneRow(query));
     return new TimeSpan(res[0] / 1e9, res[1] / 1e9);
   }
-
-  async getTracingMetadataTimeBounds(): Promise<TimeSpan> {
-    const query = await this.query(`select name, int_value from metadata
-         where name = 'tracing_started_ns' or name = 'tracing_disabled_ns'
-         or name = 'all_data_source_started_ns'`);
-    let startBound = -Infinity;
-    let endBound = Infinity;
-    const it = iter({'name': STR, 'int_value': NUM_NULL}, query);
-    for (; it.valid(); it.next()) {
-      const columnName = it.row.name;
-      const timestamp = it.row.int_value;
-      if (timestamp === null) continue;
-      if (columnName === 'tracing_disabled_ns') {
-        endBound = Math.min(endBound, timestamp / 1e9);
-      } else {
-        startBound = Math.max(startBound, timestamp / 1e9);
-      }
-    }
-
-    return new TimeSpan(startBound, endBound);
-  }
 }
diff --git a/ui/src/common/flamegraph_unittest.ts b/ui/src/common/flamegraph_unittest.ts
index d25464c..dfb03a4 100644
--- a/ui/src/common/flamegraph_unittest.ts
+++ b/ui/src/common/flamegraph_unittest.ts
@@ -25,8 +25,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -36,8 +35,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -47,8 +45,7 @@
       totalSize: 4,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -58,8 +55,7 @@
       totalSize: 4,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -79,8 +75,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -90,8 +85,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -101,8 +95,7 @@
       totalSize: 6,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -112,8 +105,7 @@
       totalSize: 4,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 5,
@@ -123,8 +115,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -144,8 +135,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -155,8 +145,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -166,8 +155,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -182,8 +170,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -193,8 +180,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
   ]);
 });
@@ -209,8 +195,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -220,8 +205,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -231,8 +215,7 @@
       totalSize: 3,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -242,8 +225,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 5,
@@ -253,8 +235,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 6,
@@ -264,8 +245,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 7,
@@ -275,8 +255,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 8,
@@ -286,8 +265,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -300,8 +278,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -311,8 +288,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -322,8 +298,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 6,
@@ -333,8 +308,7 @@
       totalSize: 3,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
   ];
 
@@ -356,8 +330,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -367,8 +340,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -378,8 +350,7 @@
       totalSize: 3,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -389,8 +360,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 5,
@@ -400,8 +370,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 6,
@@ -411,8 +380,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 7,
@@ -422,8 +390,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 8,
@@ -433,8 +400,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -447,8 +413,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -458,8 +423,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -469,8 +433,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 6,
@@ -480,8 +443,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 7,
@@ -491,8 +453,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 8,
@@ -502,8 +463,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -526,8 +486,7 @@
       totalSize: 20,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -537,8 +496,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -548,8 +506,7 @@
       totalSize: 1,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -559,8 +516,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 5,
@@ -570,8 +526,7 @@
       totalSize: 3,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -584,8 +539,7 @@
       totalSize: 20,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -595,8 +549,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -606,8 +559,7 @@
       totalSize: 4,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 4,
@@ -617,8 +569,7 @@
       totalSize: 8,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -641,8 +592,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -652,8 +602,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -663,8 +612,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -683,8 +631,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -694,8 +641,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -710,8 +656,7 @@
       totalSize: 12,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
   ]);
 });
@@ -726,8 +671,7 @@
       totalSize: 60,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -737,8 +681,7 @@
       totalSize: 40,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -748,8 +691,7 @@
       totalSize: 25,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -759,8 +701,7 @@
       totalSize: 15,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 5,
@@ -770,8 +711,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 6,
@@ -781,8 +721,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 7,
@@ -792,8 +731,7 @@
       totalSize: 30,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 8,
@@ -803,8 +741,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 9,
@@ -814,8 +751,7 @@
       totalSize: 20,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 10,
@@ -825,8 +761,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 11,
@@ -836,8 +771,7 @@
       totalSize: 3,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 12,
@@ -847,8 +781,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 13,
@@ -858,8 +791,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 14,
@@ -869,8 +801,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 15,
@@ -880,8 +811,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 16,
@@ -891,8 +821,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 17,
@@ -902,8 +831,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 18,
@@ -913,8 +841,7 @@
       totalSize: 5,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 19,
@@ -924,8 +851,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 20,
@@ -935,8 +861,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
@@ -949,8 +874,7 @@
       totalSize: 60,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 2,
@@ -960,8 +884,7 @@
       totalSize: 40,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 3,
@@ -971,8 +894,7 @@
       totalSize: 25,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 4,
@@ -982,8 +904,7 @@
       totalSize: 35,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 7,
@@ -993,8 +914,7 @@
       totalSize: 30,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 8,
@@ -1004,8 +924,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 9,
@@ -1015,8 +934,7 @@
       totalSize: 20,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 10,
@@ -1026,8 +944,7 @@
       totalSize: 25,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 15,
@@ -1037,8 +954,7 @@
       totalSize: 25,
       selfSize: 0,
       mapping: 'x',
-      merged: true,
-      highlighted: false
+      merged: true
     },
     {
       id: 19,
@@ -1048,8 +964,7 @@
       totalSize: 10,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
     {
       id: 20,
@@ -1059,8 +974,7 @@
       totalSize: 2,
       selfSize: 0,
       mapping: 'x',
-      merged: false,
-      highlighted: false
+      merged: false
     },
   ];
 
diff --git a/ui/src/common/flamegraph_util.ts b/ui/src/common/flamegraph_util.ts
index f083428..a94eddd 100644
--- a/ui/src/common/flamegraph_util.ts
+++ b/ui/src/common/flamegraph_util.ts
@@ -103,7 +103,6 @@
     mapping: callsite.mapping,
     selfSize: callsite.selfSize,
     merged: callsite.merged,
-    highlighted: callsite.highlighted
   };
 }
 
diff --git a/ui/src/common/http_rpc_engine.ts b/ui/src/common/http_rpc_engine.ts
index bd1f6dd..38ed932 100644
--- a/ui/src/common/http_rpc_engine.ts
+++ b/ui/src/common/http_rpc_engine.ts
@@ -136,10 +136,6 @@
 
   static async checkConnection(): Promise<HttpRpcState> {
     const httpRpcState: HttpRpcState = {connected: false};
-    console.info(
-        `It's safe to ignore the ERR_CONNECTION_REFUSED on ${RPC_URL} below. ` +
-        `That might happen while probing the exernal native accelerator. The ` +
-        `error is non-fatal and unlikely to be the culprit for any UI bug.`);
     try {
       const resp = await fetchWithTimeout(
           RPC_URL + 'status',
diff --git a/ui/src/common/metric_data.ts b/ui/src/common/metric_data.ts
deleted file mode 100644
index a9db6c8..0000000
--- a/ui/src/common/metric_data.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-export interface MetricResult {
-  name: string;
-  // Either result or error should be set.
-  resultString?: string;
-  error?: string;
-}
diff --git a/ui/src/common/protos.ts b/ui/src/common/protos.ts
index 8b0a5fd..52160fd 100644
--- a/ui/src/common/protos.ts
+++ b/ui/src/common/protos.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import {assertFalse, assertTrue} from '../base/logging';
 import * as protos from '../gen/protos';
-import {slowlyCountRows} from './query_iterator';
 
 // Aliases protos to avoid the super nested namespaces.
 // See https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases
@@ -104,7 +104,7 @@
 export function* rawQueryResultIter(result: RawQueryResult) {
   const columns: Array<[string, number]> = rawQueryResultColumns(result).map(
       (name, i): [string, number] => [name, i]);
-  for (let rowNum = 0; rowNum < slowlyCountRows(result); rowNum++) {
+  for (let rowNum = 0; rowNum < result.numRecords; rowNum++) {
     const row: Row = {};
     for (const [name, colNum] of columns) {
       const cell = getCell(result, colNum, rowNum);
@@ -114,6 +114,96 @@
   }
 }
 
+export const NUM = 0;
+export const STR = 'str';
+export const NUM_NULL: number|null = 1;
+export const STR_NULL: string|null = 'str_null';
+
+/**
+ * This function allows for type safe use of RawQueryResults.
+ * The input is a RawQueryResult (|raw|) and a "spec".
+ * A spec is an object where the keys are column names and the values
+ * are constants representing the types. For example:
+ * {
+ *   upid: NUM,
+ *   pid: NUM_NULL,
+ *   processName: STR_NULL,
+ * }
+ * The output is a iterable of rows each row looks like the given spec:
+ * {
+ *   upid: 1,
+ *   pid: 42,
+ *   processName: null,
+ * }
+ * Each row has an appropriate typescript type based on the spec so there
+ * is no need to use ! or cast when using the result of rawQueryToRows.
+ * Note: type checking to ensure that the RawQueryResult matches the spec
+ * happens at runtime, so if a query can return null and this is not reflected
+ * in the spec this will still crash at runtime.
+ */
+export function*
+    rawQueryToRows<T>(raw: RawQueryResult, spec: T): IterableIterator<T> {
+  const allColumns = rawQueryResultColumns(raw);
+  const columns: Array<[string, (row: number) => string | number | null]> = [];
+  for (const [key, columnSpec] of Object.entries(spec)) {
+    const i = allColumns.indexOf(key);
+    assertTrue(i !== -1, `Expected column "${key}" (cols ${allColumns})`);
+
+    const column = raw.columns[i];
+    const isNulls = column.isNulls!;
+    const columnType = raw.columnDescriptors[i].type;
+
+    if (columnSpec === NUM || columnSpec === STR) {
+      for (let j = 0; j < raw.numRecords; j++) {
+        assertFalse(column.isNulls![i], `Unexpected null in ${key} row ${j}`);
+      }
+    }
+
+    if (columnSpec === NUM || columnSpec === NUM_NULL) {
+      if (columnType === COLUMN_TYPE_STR) {
+        throw new Error(`Expected numbers in column ${key} found strings`);
+      }
+    } else if (columnSpec === STR || columnSpec === STR_NULL) {
+      if (columnType === COLUMN_TYPE_LONG ||
+          columnType === COLUMN_TYPE_DOUBLE) {
+        throw new Error(`Expected strings in column ${key} found numbers`);
+      }
+    }
+
+    let accessor;
+    switch (columnType) {
+      case COLUMN_TYPE_LONG: {
+        const values = column.longValues!;
+        accessor = (i: number) => isNulls[i] ? null : +values[i];
+        break;
+      }
+      case COLUMN_TYPE_DOUBLE: {
+        const values = column.doubleValues!;
+        accessor = (i: number) => isNulls[i] ? null : values[i];
+        break;
+      }
+      case COLUMN_TYPE_STR: {
+        const values = column.stringValues!;
+        accessor = (i: number) => isNulls[i] ? null : values[i];
+        break;
+      }
+      default:
+        // We can only reach here if the column is completely null.
+        accessor = (_: number) => null;
+        break;
+    }
+    columns.push([key, accessor]);
+  }
+
+  for (let i = 0; i < raw.numRecords; i++) {
+    const row: {[_: string]: number | string | null} = {};
+    for (const [name, accessor] of columns) {
+      row[name] = accessor(i);
+    }
+    yield row as {} as T;
+  }
+}
+
 export {
   AndroidLogConfig,
   AndroidLogId,
diff --git a/ui/src/common/query_iterator.ts b/ui/src/common/query_iterator.ts
deleted file mode 100644
index 10029a5..0000000
--- a/ui/src/common/query_iterator.ts
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {assertTrue} from '../base/logging';
-
-import {RawQueryResult} from './protos';
-
-// Union of all the query result formats that we can turn into forward
-// iterators.
-// TODO(hjd): Replace someOtherEncoding place holder with the real new
-// format.
-type QueryResult = RawQueryResult|{someOtherEncoding: string};
-
-// One row extracted from an SQL result:
-interface Row {
-  [key: string]: string|number|null;
-}
-
-// API:
-// const result = await engine.query("select 42 as n;");
-// const it = iter({"answer": NUM}, result);
-// for (; it.valid(); it.next()) {
-//   console.log(it.row.answer);
-// }
-export interface RowIterator<T extends Row> {
-  valid(): boolean;
-  next(): void;
-  row: T;
-}
-
-export const NUM = 0;
-export const STR = 'str';
-export const NUM_NULL: number|null = 1;
-export const STR_NULL: string|null = 'str_null';
-export type ColumnType =
-    (typeof NUM)|(typeof STR)|(typeof NUM_NULL)|(typeof STR_NULL);
-
-// Exported for testing
-export function findColumnIndex(
-    result: RawQueryResult, name: string, columnType: number|null|string):
-    number {
-  let matchingDescriptorIndex = -1;
-  const disallowNulls = columnType === STR || columnType === NUM;
-  const expectsStrings = columnType === STR || columnType === STR_NULL;
-  const expectsNumbers = columnType === NUM || columnType === NUM_NULL;
-  const isEmpty = +result.numRecords === 0;
-
-  for (let i = 0; i < result.columnDescriptors.length; ++i) {
-    const descriptor = result.columnDescriptors[i];
-    const column = result.columns[i];
-    if (descriptor.name !== name) {
-      continue;
-    }
-
-    const hasDoubles = column.doubleValues && column.doubleValues.length;
-    const hasLongs = column.longValues && column.longValues.length;
-    const hasStrings = column.stringValues && column.stringValues.length;
-
-    if (matchingDescriptorIndex !== -1) {
-      throw new Error(`Multiple columns with the name ${name}`);
-    }
-
-    if (expectsStrings && !hasStrings && !isEmpty) {
-      throw new Error(`Expected strings for column ${name} but found numbers`);
-    }
-
-    if (expectsNumbers && !hasDoubles && !hasLongs && !isEmpty) {
-      throw new Error(`Expected numbers for column ${name} but found strings`);
-    }
-
-    if (disallowNulls) {
-      for (let j = 0; j < +result.numRecords; ++j) {
-        if (column.isNulls![j] === true) {
-          throw new Error(`Column ${name} contains nulls`);
-        }
-      }
-    }
-    matchingDescriptorIndex = i;
-  }
-
-  if (matchingDescriptorIndex === -1) {
-    throw new Error(`No column with name ${name} found in result.`);
-  }
-
-  return matchingDescriptorIndex;
-}
-
-class ColumnarRowIterator {
-  row: Row;
-  private i_: number;
-  private rowCount_: number;
-  private columnCount_: number;
-  private columnNames_: string[];
-  private columns_: Array<number[]|string[]>;
-  private nullColumns_: boolean[][];
-
-  constructor(querySpec: Row, queryResult: RawQueryResult) {
-    const row: Row = querySpec;
-    this.row = row;
-    this.i_ = 0;
-    this.rowCount_ = +queryResult.numRecords;
-    this.columnCount_ = 0;
-    this.columnNames_ = [];
-    this.columns_ = [];
-    this.nullColumns_ = [];
-
-    for (const [columnName, columnType] of Object.entries(querySpec)) {
-      const index = findColumnIndex(queryResult, columnName, columnType);
-      const column = queryResult.columns[index];
-      this.columnCount_++;
-      this.columnNames_.push(columnName);
-      let values: string[]|Array<number|Long> = [];
-      const isNum = columnType === NUM || columnType === NUM_NULL;
-      const isString = columnType === STR || columnType === STR_NULL;
-      if (isNum && column.longValues &&
-          column.longValues.length === this.rowCount_) {
-        values = column.longValues;
-      }
-      if (isNum && column.doubleValues &&
-          column.doubleValues.length === this.rowCount_) {
-        values = column.doubleValues;
-      }
-      if (isString && column.stringValues &&
-          column.stringValues.length === this.rowCount_) {
-        values = column.stringValues;
-      }
-      this.columns_.push(values as string[]);
-      this.nullColumns_.push(column.isNulls!);
-    }
-    if (this.rowCount_ > 0) {
-      for (let j = 0; j < this.columnCount_; ++j) {
-        const name = this.columnNames_[j];
-        const isNull = this.nullColumns_[j][this.i_];
-        this.row[name] = isNull ? null : this.columns_[j][this.i_];
-      }
-    }
-  }
-
-  valid(): boolean {
-    return this.i_ < this.rowCount_;
-  }
-
-  next(): void {
-    this.i_++;
-    for (let j = 0; j < this.columnCount_; ++j) {
-      const name = this.columnNames_[j];
-      const isNull = this.nullColumns_[j][this.i_];
-      this.row[name] = isNull ? null : this.columns_[j][this.i_];
-    }
-  }
-}
-
-// Deliberately not exported, use iter() below to make code easy to switch
-// to other queryResult formats.
-function iterFromColumns<T extends Row>(
-    querySpec: T, queryResult: RawQueryResult): RowIterator<T> {
-  const iter = new ColumnarRowIterator(querySpec, queryResult);
-  return iter as unknown as RowIterator<T>;
-}
-
-// Deliberately not exported, use iterUntyped() below to make code easy to
-// switch to other queryResult formats.
-function iterUntypedFromColumns(result: RawQueryResult): RowIterator<Row> {
-  const spec: Row = {};
-  const desc = result.columnDescriptors;
-  for (let i = 0; i < desc.length; ++i) {
-    const name = desc[i].name;
-    if (!name) {
-      continue;
-    }
-    spec[name] = desc[i].type === 3 ? STR_NULL : NUM_NULL;
-  }
-  const iter = new ColumnarRowIterator(spec, result);
-  return iter as unknown as RowIterator<Row>;
-}
-
-function isColumnarQueryResult(result: QueryResult): result is RawQueryResult {
-  return (result as RawQueryResult).columnDescriptors !== undefined;
-}
-
-export function iterUntyped(result: QueryResult): RowIterator<Row> {
-  if (isColumnarQueryResult(result)) {
-    return iterUntypedFromColumns(result);
-  } else {
-    throw new Error('Unsuported format');
-  }
-}
-
-export function iter<T extends Row>(
-    spec: T, result: QueryResult): RowIterator<T> {
-  if (isColumnarQueryResult(result)) {
-    return iterFromColumns(spec, result);
-  } else {
-    throw new Error('Unsuported format');
-  }
-}
-
-export function slowlyCountRows(result: QueryResult): number {
-  if (isColumnarQueryResult(result)) {
-    // This isn't actually slow for columnar data but it might be for other
-    // formats.
-    return +result.numRecords;
-  } else {
-    throw new Error('Unsuported format');
-  }
-}
-
-export function singleRow<T extends Row>(spec: T, result: QueryResult): T|
-    undefined {
-  const numRows = slowlyCountRows(result);
-  if (numRows === 0) {
-    return undefined;
-  }
-  if (numRows > 1) {
-    throw new Error(
-        `Attempted to extract single row but more than ${numRows} rows found.`);
-  }
-  const it = iter(spec, result);
-  assertTrue(it.valid());
-  return it.row;
-}
-
-export function singleRowUntyped(result: QueryResult): Row|undefined {
-  const numRows = slowlyCountRows(result);
-  if (numRows === 0) {
-    return undefined;
-  }
-  if (numRows > 1) {
-    throw new Error(
-        `Attempted to extract single row but more than ${numRows} rows found.`);
-  }
-  const it = iterUntyped(result);
-  assertTrue(it.valid());
-  return it.row;
-}
diff --git a/ui/src/common/query_iterator_unittest.ts b/ui/src/common/query_iterator_unittest.ts
deleted file mode 100644
index 402a2e9..0000000
--- a/ui/src/common/query_iterator_unittest.ts
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {RawQueryResult} from './protos';
-import {
-  findColumnIndex,
-  iter,
-  NUM,
-  NUM_NULL,
-  slowlyCountRows,
-  STR,
-  STR_NULL
-} from './query_iterator';
-
-const COLUMN_TYPE_STR = RawQueryResult.ColumnDesc.Type.STRING;
-const COLUMN_TYPE_DOUBLE = RawQueryResult.ColumnDesc.Type.DOUBLE;
-const COLUMN_TYPE_LONG = RawQueryResult.ColumnDesc.Type.LONG;
-
-test('Columnar iteration slowlyCountRows', () => {
-  const r = new RawQueryResult({
-    columnDescriptors: [{
-      name: 'string_column',
-      type: COLUMN_TYPE_STR,
-    }],
-    numRecords: 1,
-    columns: [{
-      stringValues: ['foo'],
-      isNulls: [false],
-    }],
-  });
-
-  expect(slowlyCountRows(r)).toBe(1);
-});
-
-test('Columnar iteration findColumnIndex', () => {
-  const r = new RawQueryResult({
-    columnDescriptors: [
-      {
-        name: 'strings',
-        type: COLUMN_TYPE_STR,
-      },
-      {
-        name: 'doubles',
-        type: COLUMN_TYPE_DOUBLE,
-      },
-      {
-        name: 'longs',
-        type: COLUMN_TYPE_LONG,
-      },
-      {
-        name: 'nullable_strings',
-        type: COLUMN_TYPE_STR,
-      },
-      {
-        name: 'nullable_doubles',
-        type: COLUMN_TYPE_DOUBLE,
-      },
-      {
-        name: 'nullable_longs',
-        type: COLUMN_TYPE_LONG,
-      },
-      {
-        name: 'twin',
-        type: COLUMN_TYPE_LONG,
-      },
-      {
-        name: 'twin',
-        type: COLUMN_TYPE_STR,
-      }
-    ],
-    numRecords: 1,
-    columns: [
-      {
-        stringValues: ['foo'],
-        isNulls: [false],
-      },
-      {
-        doubleValues: [1],
-        isNulls: [false],
-      },
-      {
-        longValues: [1],
-        isNulls: [false],
-      },
-      {
-        stringValues: [''],
-        isNulls: [true],
-      },
-      {
-        doubleValues: [0],
-        isNulls: [true],
-      },
-      {
-        longValues: [0],
-        isNulls: [true],
-      },
-      {
-        doubleValues: [0],
-        isNulls: [false],
-      },
-      {
-        stringValues: [''],
-        isNulls: [false],
-      }
-    ],
-  });
-
-  expect(findColumnIndex(r, 'strings', STR)).toBe(0);
-  expect(findColumnIndex(r, 'doubles', NUM)).toBe(1);
-  expect(findColumnIndex(r, 'longs', NUM)).toBe(2);
-
-  expect(findColumnIndex(r, 'nullable_strings', STR_NULL)).toBe(3);
-  expect(findColumnIndex(r, 'nullable_doubles', NUM_NULL)).toBe(4);
-  expect(findColumnIndex(r, 'nullable_longs', NUM_NULL)).toBe(5);
-
-  expect(() => findColumnIndex(r, 'no such col', NUM)).toThrow(Error);
-
-  // It's allowable to expect nulls but for the whole column to be non-null...
-  expect(findColumnIndex(r, 'strings', STR_NULL)).toBe(0);
-  expect(findColumnIndex(r, 'doubles', NUM_NULL)).toBe(1);
-  expect(findColumnIndex(r, 'longs', NUM_NULL)).toBe(2);
-
-  // ...but if we expect no-nulls there shouldn't be even one:
-  expect(() => findColumnIndex(r, 'nullable_strings', STR)).toThrow(Error);
-  expect(() => findColumnIndex(r, 'nullable_doubles', NUM)).toThrow(Error);
-  expect(() => findColumnIndex(r, 'nullable_longs', NUM)).toThrow(Error);
-
-  // If multiple columns have the desired name we error even if we could
-  // distinguish based on the type:
-  expect(() => findColumnIndex(r, 'twin', NUM)).toThrow(Error);
-
-  expect(() => findColumnIndex(r, 'strings', NUM)).toThrow(Error);
-  expect(() => findColumnIndex(r, 'longs', STR)).toThrow(Error);
-  expect(() => findColumnIndex(r, 'doubles', STR)).toThrow(Error);
-});
-
-test('Columnar iteration over two rows', () => {
-  const r = new RawQueryResult({
-    columnDescriptors: [{
-      name: 'name',
-      type: COLUMN_TYPE_STR,
-    }],
-    numRecords: 2,
-    columns: [{
-      stringValues: ['Alice', 'Bob'],
-      isNulls: [false, false],
-    }],
-  });
-
-  const it = iter({'name': STR}, r);
-
-  expect(it.valid()).toBe(true);
-  const name: string = it.row.name;
-  expect(name).toBe('Alice');
-  it.next();
-
-  expect(it.valid()).toBe(true);
-  expect(it.row.name).toBe('Bob');
-  it.next();
-
-  expect(it.valid()).toBe(false);
-});
-
-test('Columnar iteration over empty query set', () => {
-  const r = new RawQueryResult({
-    columnDescriptors: [{
-      name: 'emptyColumn',
-      type: COLUMN_TYPE_STR,
-    }],
-    numRecords: 0,
-    columns: [{
-      stringValues: [],
-      isNulls: [],
-    }],
-  });
-
-  {
-    const it = iter({'emptyColumn': STR}, r);
-    expect(it.valid()).toBe(false);
-  }
-
-  {
-    const it = iter({'emptyColumn': NUM}, r);
-    expect(it.valid()).toBe(false);
-  }
-
-  {
-    const it = iter({'emptyColumn': NUM_NULL}, r);
-    expect(it.valid()).toBe(false);
-  }
-
-  {
-    const it = iter({'emptyColumn': STR_NULL}, r);
-    expect(it.valid()).toBe(false);
-  }
-});
-
-test('Columnar iteration first row is null', () => {
-  const r = new RawQueryResult({
-    columnDescriptors: [{
-      name: 'numbers',
-      type: COLUMN_TYPE_STR,
-    }],
-    numRecords: 2,
-    columns: [{
-      stringValues: ['[NULL]'],
-      doubleValues: [0],
-      longValues: [0, 1],
-      isNulls: [true, false],
-    }],
-  });
-
-  const it = iter({'numbers': NUM_NULL}, r);
-
-  expect(it.valid()).toBe(true);
-  expect(it.row.numbers).toBe(null);
-  it.next();
-
-  expect(it.valid()).toBe(true);
-  expect(it.row.numbers).toBe(1);
-  it.next();
-
-  expect(it.valid()).toBe(false);
-});
diff --git a/ui/src/common/search_data.ts b/ui/src/common/search_data.ts
index 70bfb7f..0969c1d 100644
--- a/ui/src/common/search_data.ts
+++ b/ui/src/common/search_data.ts
@@ -19,9 +19,9 @@
 }
 
 export interface CurrentSearchResults {
-  sliceIds: number[];
-  tsStarts: number[];
-  utids: number[];
+  sliceIds: Float64Array;
+  tsStarts: Float64Array;
+  utids: Float64Array;
   trackIds: string[];
   sources: string[];
   totalResults: number;
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 347c904..028fde9 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -29,20 +29,10 @@
 export type VisibleState =
     Timestamped<{startSec: number; endSec: number; resolution: number;}>;
 
+export type TimestampedAreaSelection = Timestamped<AreaSelection>;
 export interface AreaSelection {
-  kind: 'AREA';
-  areaId: string;
-  // When an area is marked it will be assigned a unique note id and saved as
-  // an AreaNote for the user to return to later. id = 0 is the special id that
-  // is overwritten when a new area is marked. Any other id is a persistent
-  // marking that will not be overwritten.
-  // When not set, the area selection will be replaced with any
-  // new area selection (i.e. not saved anywhere).
-  noteId?: string;
+  area?: Area;
 }
-
-export type AreaById = Area&{id: string};
-
 export interface Area {
   startSec: number;
   endSec: number;
@@ -51,22 +41,13 @@
 
 export const MAX_TIME = 180;
 
-// 3: TrackKindPriority and related sorting changes.
-export const STATE_VERSION = 3;
-
 export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
 
+
 export type EngineMode = 'WASM'|'HTTP_RPC';
 
 export type NewEngineMode = 'USE_HTTP_RPC_IF_AVAILABLE'|'FORCE_BUILTIN_WASM';
 
-export enum TrackKindPriority {
-  'MAIN_THREAD' = 0,
-  'RENDER_THREAD' = 1,
-  'GPU_COMPLETION' = 2,
-  'ORDINARY' = 3
-}
-
 export type HeapProfileFlamegraphViewingOption =
     'SPACE'|'ALLOC_SPACE'|'OBJECTS'|'ALLOC_OBJECTS';
 
@@ -79,7 +60,6 @@
   selfSize: number;
   mapping: string;
   merged: boolean;
-  highlighted: boolean;
 }
 
 export interface TraceFileSource {
@@ -91,7 +71,6 @@
   type: 'ARRAY_BUFFER';
   title: string;
   url?: string;
-  fileName?: string;
   buffer: ArrayBuffer;
 }
 
@@ -112,7 +91,6 @@
   engineId: string;
   kind: string;
   name: string;
-  trackKindPriority: TrackKindPriority;
   trackGroup?: string;
   config: {};
 }
@@ -123,6 +101,7 @@
   name: string;
   collapsed: boolean;
   tracks: string[];  // Child track ids.
+  summaryTrackId: string;
 }
 
 export interface EngineConfig {
@@ -142,8 +121,6 @@
 export interface PermalinkConfig {
   requestId?: string;  // Set by the frontend to request a new permalink.
   hash?: string;       // Set by the controller when the link has been created.
-  isRecordingConfig?:
-      boolean;  // this permalink request is for a recording config only
 }
 
 export interface TraceTime {
@@ -154,6 +131,7 @@
 export interface FrontendLocalState {
   omniboxState: OmniboxState;
   visibleState: VisibleState;
+  selectedArea: TimestampedAreaSelection;
 }
 
 export interface Status {
@@ -172,7 +150,8 @@
 export interface AreaNote {
   noteType: 'AREA';
   id: string;
-  areaId: string;
+  timestamp: number;
+  area: Area;
   color: string;
   text: string;
 }
@@ -228,13 +207,16 @@
 
 export interface ThreadStateSelection {
   kind: 'THREAD_STATE';
-  id: number;
+  utid: number;
+  ts: number;
+  dur: number;
+  state: string;
+  cpu: number;
 }
 
-type Selection =
-    (NoteSelection|SliceSelection|CounterSelection|HeapProfileSelection|
-     CpuProfileSampleSelection|ChromeSliceSelection|ThreadStateSelection|
-     AreaSelection)&{trackId?: string};
+type Selection = (NoteSelection|SliceSelection|CounterSelection|
+                  HeapProfileSelection|CpuProfileSampleSelection|
+                  ChromeSliceSelection|ThreadStateSelection)&{trackId?: string};
 
 export interface LogsPagination {
   offset: number;
@@ -260,20 +242,11 @@
   sorting?: Sorting;
 }
 
-export interface MetricsState {
-  availableMetrics?: string[];  // Undefined until list is loaded.
-  selectedIndex?: number;
-  requestedMetric?: string;  // Unset after metric request is handled.
-}
-
 export interface State {
   // tslint:disable-next-line:no-any
   [key: string]: any;
-  version: number;
   route: string|null;
   nextId: number;
-  nextNoteId: number;
-  nextAreaId: number;
 
   /**
    * State of the ConfigEditor.
@@ -289,22 +262,17 @@
   traceTime: TraceTime;
   trackGroups: ObjectById<TrackGroupState>;
   tracks: ObjectById<TrackState>;
-  areas: ObjectById<AreaById>;
   aggregatePreferences: ObjectById<AggregationState>;
   visibleTracks: string[];
   scrollingTracks: string[];
   pinnedTracks: string[];
-  debugTrackId?: string;
-  lastTrackReloadRequest?: number;
   queries: ObjectById<QueryConfig>;
-  metrics: MetricsState;
   permalink: PermalinkConfig;
   notes: ObjectById<Note|AreaNote>;
   status: Status;
   currentSelection: Selection|null;
   currentHeapProfileFlamegraph: HeapProfileFlamegraph|null;
   logsPagination: LogsPagination;
-  traceConversionInProgress: boolean;
 
   /**
    * This state is updated on the frontend at 60Hz and eventually syncronised to
@@ -332,7 +300,6 @@
   lastRecordingError?: string;
   recordingStatus?: string;
 
-  updateChromeCategories: boolean;
   chromeCategories: string[]|undefined;
   analyzePageQuery?: string;
 }
@@ -346,7 +313,7 @@
     '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' | 'CrOS';
+export declare type TargetOs = 'Q' | 'P' | 'O' | 'C' | 'L';
 
 export function isAndroidP(target: RecordingTarget) {
   return target.os === 'P';
@@ -357,11 +324,7 @@
 }
 
 export function isChromeTarget(target: RecordingTarget) {
-  return ['C', 'CrOS'].includes(target.os);
-}
-
-export function isCrOSTarget(target: RecordingTarget) {
-  return target.os === 'CrOS';
+  return target.os === 'C';
 }
 
 export function isLinuxTarget(target: RecordingTarget) {
@@ -374,17 +337,6 @@
   return false;
 }
 
-export function hasActiveProbes(config: RecordConfig) {
-  const fieldsWithEmptyResult = new Set<string>(['hpBlockClient']);
-  for (const key in config) {
-    if (typeof (config[key]) === 'boolean' && config[key] === true &&
-        !fieldsWithEmptyResult.has(key)) {
-      return true;
-    }
-  }
-  return false;
-}
-
 export interface RecordConfig {
   [key: string]: null|number|boolean|string|string[];
 
@@ -396,6 +348,7 @@
   fileWritePeriodMs: number;  // Only for mode == 'LONG_TRACE'.
 
   cpuSched: boolean;
+  cpuLatency: boolean;
   cpuFreq: boolean;
   cpuCoarse: boolean;
   cpuCoarsePollMs: number;
@@ -404,7 +357,6 @@
   screenRecord: boolean;
 
   gpuFreq: boolean;
-  gpuMemTotal: boolean;
 
   ftrace: boolean;
   atrace: boolean;
@@ -416,7 +368,6 @@
   ftraceDrainPeriodMs: number;
   androidLogs: boolean;
   androidLogBuffers: string[];
-  androidFrameTimeline: boolean;
 
   batteryDrain: boolean;
   batteryDrainPollMs: number;
@@ -438,8 +389,6 @@
   hpContinuousDumpsPhase: number;
   hpContinuousDumpsInterval: number;
   hpSharedMemoryBuffer: number;
-  hpBlockClient: boolean;
-  hpAllHeaps: boolean;
 
   javaHeapDump: boolean;
   jpProcesses: string;
@@ -458,16 +407,16 @@
     durationMs: 10000.0,
     maxFileSizeMb: 100,
     fileWritePeriodMs: 2500,
-    bufferSizeMb: 64.0,
+    bufferSizeMb: 10.0,
 
     cpuSched: false,
+    cpuLatency: false,
     cpuFreq: false,
     cpuSyscall: false,
 
     screenRecord: false,
 
     gpuFreq: false,
-    gpuMemTotal: false,
 
     ftrace: false,
     atrace: false,
@@ -479,7 +428,6 @@
     ftraceDrainPeriodMs: 250,
     androidLogs: false,
     androidLogBuffers: [],
-    androidFrameTimeline: false,
 
     cpuCoarse: false,
     cpuCoarsePollMs: 1000,
@@ -504,8 +452,6 @@
     hpContinuousDumpsPhase: 0,
     hpContinuousDumpsInterval: 0,
     hpSharedMemoryBuffer: 8 * 1048576,
-    hpBlockClient: true,
-    hpAllHeaps: false,
 
     javaHeapDump: false,
     jpProcesses: '',
@@ -526,7 +472,6 @@
     {os: 'P', name: 'Android P'},
     {os: 'O', name: 'Android O-'},
     {os: 'C', name: 'Chrome'},
-    {os: 'CrOS', name: 'Chrome OS (system trace)'},
     {os: 'L', name: 'Linux desktop'}
   ];
 }
@@ -538,13 +483,11 @@
     'accessibility',
     'AccountFetcherService',
     'android_webview',
-    'aogh',
     'audio',
     'base',
     'benchmark',
     'blink',
     'blink.animations',
-    'blink.bindings',
     'blink.console',
     'blink_gc',
     'blink.net',
@@ -555,13 +498,8 @@
     'browser',
     'browsing_data',
     'CacheStorage',
-    'Calculators',
-    'CameraStream',
     'camera',
-    'cast_app',
     'cast_perf_test',
-    'cast.mdns',
-    'cast.mdns.socket',
     'cast.stream',
     'cc',
     'cc.debug',
@@ -571,17 +509,15 @@
     'compositor',
     'content',
     'content_capture',
-    'device',
     'devtools',
-    'devtools.contrast',
     'devtools.timeline',
-    'disk_cache',
+    'devtools.timeline.async',
     'download',
     'download_service',
     'drm',
     'drmcursor',
     'dwrite',
-    'DXVA_Decoding',
+    'DXVA Decoding',
     'EarlyJava',
     'evdev',
     'event',
@@ -592,12 +528,10 @@
     'fonts',
     'GAMEPAD',
     'gpu',
-    'gpu.angle',
     'gpu.capture',
     'headless',
     'hwoverlays',
     'identity',
-    'ime',
     'IndexedDB',
     'input',
     'io',
@@ -625,17 +559,12 @@
     'omnibox',
     'oobe',
     'ozone',
-    'partition_alloc',
     'passwords',
     'p2p',
     'page-serialization',
-    'paint_preview',
     'pepper',
-    'PlatformMalloc',
-    'power',
     'ppapi',
-    'ppapi_proxy',
-    'print',
+    'ppapi proxy',
     'rail',
     'renderer',
     'renderer_host',
@@ -646,26 +575,21 @@
     'sequence_manager',
     'service_manager',
     'ServiceWorker',
-    'sharing',
     'shell',
     'shortcut_viewer',
     'shutdown',
     'SiteEngagement',
     'skia',
-    'sql',
-    'stadia_media',
-    'stadia_rtc',
     'startup',
     'sync',
     'sync_lock_contention',
-    'test_gpu',
     'thread_pool',
+    'test_gpu',
+    'test_tracing',
     'toplevel',
-    'toplevel.flow',
     'ui',
     'v8',
     'v8.execute',
-    'v8.wasm',
     'ValueStoreFrontend::Backend',
     'views',
     'views.frame',
@@ -678,7 +602,6 @@
     'webrtc',
     'xr',
     'disabled-by-default-animation-worklet',
-    'disabled-by-default-audio',
     'disabled-by-default-audio-worklet',
     'disabled-by-default-blink.debug',
     'disabled-by-default-blink.debug.display_lock',
@@ -696,7 +619,6 @@
     'disabled-by-default-cc.debug.scheduler',
     'disabled-by-default-cc.debug.scheduler.frames',
     'disabled-by-default-cc.debug.scheduler.now',
-    'disabled-by-default-content.verbose',
     'disabled-by-default-cpu_profiler',
     'disabled-by-default-cpu_profiler.debug',
     'disabled-by-default-devtools.screenshot',
@@ -711,41 +633,34 @@
     'disabled-by-default-gpu_cmd_queue',
     'disabled-by-default-gpu.dawn',
     'disabled-by-default-gpu.debug',
-    'disabled-by-default-gpu.decoder',
+    'disabled-by-default-gpu_decoder',
     'disabled-by-default-gpu.device',
     'disabled-by-default-gpu.service',
-    'disabled-by-default-gpu.vulkan.vma',
     'disabled-by-default-histogram_samples',
     'disabled-by-default-ipc.flow',
     'disabled-by-default-java-heap-profiler',
     'disabled-by-default-layer-element',
-    'disabled-by-default-layout_shift.debug',
     'disabled-by-default-lifecycles',
     'disabled-by-default-loading',
-    'disabled-by-default-mediastream',
     'disabled-by-default-memory-infra',
     'disabled-by-default-memory-infra.v8.code_stats',
-    'disabled-by-default-mojom',
     'disabled-by-default-net',
     'disabled-by-default-network',
     'disabled-by-default-paint-worklet',
     'disabled-by-default-power',
     'disabled-by-default-renderer.scheduler',
     'disabled-by-default-renderer.scheduler.debug',
-    'disabled-by-default-sandbox',
     'disabled-by-default-sequence_manager',
     'disabled-by-default-sequence_manager.debug',
     'disabled-by-default-sequence_manager.verbose_snapshots',
     'disabled-by-default-skia',
     'disabled-by-default-skia.gpu',
     'disabled-by-default-skia.gpu.cache',
-    'disabled-by-default-skia.shaders',
     'disabled-by-default-SyncFileSystem',
     'disabled-by-default-system_stats',
     'disabled-by-default-thread_pool_diagnostics',
     'disabled-by-default-toplevel.flow',
     'disabled-by-default-toplevel.ipc',
-    'disabled-by-default-user_action_samples',
     'disabled-by-default-v8.compile',
     'disabled-by-default-v8.cpu_profiler',
     'disabled-by-default-v8.cpu_profiler.hires',
@@ -755,34 +670,24 @@
     'disabled-by-default-v8.runtime',
     'disabled-by-default-v8.runtime_stats',
     'disabled-by-default-v8.runtime_stats_sampling',
-    'disabled-by-default-v8.stack_trace',
     'disabled-by-default-v8.turbofan',
     'disabled-by-default-v8.wasm',
-    'disabled-by-default-v8.wasm.detailed',
-    'disabled-by-default-v8.wasm.turbofan',
     'disabled-by-default-video_and_image_capture',
     'disabled-by-default-viz.debug.overlay_planes',
-    'disabled-by-default-viz.gpu_composite_time',
     'disabled-by-default-viz.hit_testing_flow',
     'disabled-by-default-viz.overdraw',
     'disabled-by-default-viz.quads',
     'disabled-by-default-viz.surface_id_flow',
     'disabled-by-default-viz.surface_lifetime',
     'disabled-by-default-viz.triangles',
-    'disabled-by-default-webaudio.audionode',
-    'disabled-by-default-webrtc',
     'disabled-by-default-worker.scheduler',
-    'disabled-by-default-xr.debug',
   ];
 }
 
 export function createEmptyState(): State {
   return {
-    version: STATE_VERSION,
     route: null,
     nextId: 0,
-    nextNoteId: 1,  // 0 is reserved for ephemeral area marking.
-    nextAreaId: 0,
     newEngineMode: 'USE_HTTP_RPC_IF_AVAILABLE',
     engines: {},
     traceTime: {...defaultTraceTime},
@@ -792,9 +697,7 @@
     visibleTracks: [],
     pinnedTracks: [],
     scrollingTracks: [],
-    areas: {},
     queries: {},
-    metrics: {},
     permalink: {},
     notes: {},
 
@@ -813,6 +716,9 @@
         lastUpdate: 0,
         resolution: 0,
       },
+      selectedArea: {
+        lastUpdate: 0,
+      }
     },
 
     logsPagination: {
@@ -823,7 +729,6 @@
     status: {msg: '', timestamp: 0},
     currentSelection: null,
     currentHeapProfileFlamegraph: null,
-    traceConversionInProgress: false,
 
     video: null,
     videoEnabled: false,
@@ -837,7 +742,6 @@
     recordingTarget: getDefaultRecordingTargets()[0],
     availableAdbDevices: [],
 
-    updateChromeCategories: false,
     chromeCategories: undefined,
   };
 }
diff --git a/ui/src/common/state_unittest.ts b/ui/src/common/state_unittest.ts
index 2f94a6e..5216392 100644
--- a/ui/src/common/state_unittest.ts
+++ b/ui/src/common/state_unittest.ts
@@ -12,12 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {
-  createEmptyState,
-  getContainingTrackId,
-  State,
-  TrackKindPriority
-} from './state';
+import {createEmptyState, getContainingTrackId, State} from './state';
 
 test('createEmptyState', () => {
   const state: State = createEmptyState();
@@ -31,7 +26,6 @@
     engineId: 'engine',
     kind: 'Foo',
     name: 'a track',
-    trackKindPriority: TrackKindPriority.ORDINARY,
     config: {},
   };
 
@@ -40,7 +34,6 @@
     engineId: 'engine',
     kind: 'Foo',
     name: 'b track',
-    trackKindPriority: TrackKindPriority.ORDINARY,
     config: {},
     trackGroup: 'containsB',
   };
diff --git a/ui/src/common/thread_state.ts b/ui/src/common/thread_state.ts
index c0d68f5..91de9ae 100644
--- a/ui/src/common/thread_state.ts
+++ b/ui/src/common/thread_state.ts
@@ -29,18 +29,12 @@
   '+': '(Preempted)'
 };
 
-export function translateState(
-    state: string|undefined, ioWait: boolean|undefined = undefined) {
+export function translateState(state: string|undefined) {
   if (state === undefined) return '';
-  if (state === 'Running') {
+  if (state === 'Running' || state === 'Various states') {
     return state;
   }
   let result = states[state[0]];
-  if (ioWait === true) {
-    result += ' (IO)';
-  } else if (ioWait === false) {
-    result += ' (non-IO)';
-  }
   for (let i = 1; i < state.length; i++) {
     result += state[i] === '+' ? ' ' : ' + ';
     result += states[state[i]];
diff --git a/ui/src/common/upload_utils.ts b/ui/src/common/upload_utils.ts
deleted file mode 100644
index 03a9e39..0000000
--- a/ui/src/common/upload_utils.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-export const BUCKET_NAME = 'perfetto-ui-data';
-import * as uuidv4 from 'uuid/v4';
-import {State, RecordConfig} from './state';
-
-export async function saveTrace(trace: File|ArrayBuffer): Promise<string> {
-  // TODO(hjd): This should probably also be a hash but that requires
-  // trace processor support.
-  const name = uuidv4();
-  const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
-      `${BUCKET_NAME}/o?uploadType=media` +
-      `&name=${name}&predefinedAcl=publicRead`;
-  const response = await fetch(url, {
-    method: 'post',
-    headers: {'Content-Type': 'application/octet-stream;'},
-    body: trace,
-  });
-  await response.json();
-  return `https://storage.googleapis.com/${BUCKET_NAME}/${name}`;
-}
-
-export async function saveState(stateOrConfig: State|
-                                RecordConfig): Promise<string> {
-  const text = JSON.stringify(stateOrConfig);
-  const hash = await toSha256(text);
-  const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
-      `${BUCKET_NAME}/o?uploadType=media` +
-      `&name=${hash}&predefinedAcl=publicRead`;
-  const response = await fetch(url, {
-    method: 'post',
-    headers: {
-      'Content-Type': 'application/json; charset=utf-8',
-    },
-    body: text,
-  });
-  await response.json();
-  return hash;
-}
-
-export async function toSha256(str: string): Promise<string> {
-  // TODO(hjd): TypeScript bug with definition of TextEncoder.
-  // tslint:disable-next-line no-any
-  const buffer = new (TextEncoder as any)('utf-8').encode(str);
-  const digest = await crypto.subtle.digest('SHA-256', buffer);
-  return Array.from(new Uint8Array(digest)).map(x => x.toString(16)).join('');
-}
\ No newline at end of file
diff --git a/ui/src/common/wasm_engine_proxy.ts b/ui/src/common/wasm_engine_proxy.ts
index 43f7b85..3377777 100644
--- a/ui/src/common/wasm_engine_proxy.ts
+++ b/ui/src/common/wasm_engine_proxy.ts
@@ -146,11 +146,10 @@
     // Requests should be executed and ACKed by the worker in the same order
     // they came in.
     assertTrue(request.id === response.id);
-
-    // If the Wasm call fails (e.g. hits a PERFETTO_CHECK) it will throw an
-    // error in wasm_bridge.ts and show the crash dialog. In no case we can
-    // gracefully handle a Wasm crash, so we fail fast there rather than
-    // propagating the error here rejecting the promise.
-    request.respHandler.resolve(response.data);
+    if (response.aborted) {
+      request.respHandler.reject('WASM module crashed');
+    } else {
+      request.respHandler.resolve(response.data);
+    }
   }
 }
diff --git a/ui/src/controller/adb_base_controller.ts b/ui/src/controller/adb_base_controller.ts
index a429d22..31eb5ed 100644
--- a/ui/src/controller/adb_base_controller.ts
+++ b/ui/src/controller/adb_base_controller.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {extractDurationFromTraceConfig} from '../base/trace_config_utils';
-import {extractTraceConfig} from '../base/trace_config_utils';
+import {extractDurationFromTraceConfig} from '../base/extract_utils';
+import {extractTraceConfig} from '../base/extract_utils';
 import {isAdbTarget} from '../common/state';
 
 import {Adb} from './adb_interfaces';
diff --git a/ui/src/controller/adb_record_controller_jsdomtest.ts b/ui/src/controller/adb_record_controller_jsdomtest.ts
index 23730bd..204033c 100644
--- a/ui/src/controller/adb_record_controller_jsdomtest.ts
+++ b/ui/src/controller/adb_record_controller_jsdomtest.ts
@@ -14,7 +14,7 @@
 
 import {dingus} from 'dingusjs';
 
-import {utf8Encode} from '../base/string_utils';
+import {stringToUint8Array} from '../base/string_utils';
 import {perfetto} from '../gen/protos';
 
 import {AdbStream, MockAdb, MockAdbStream} from './adb_interfaces';
@@ -93,7 +93,7 @@
   expect(sendMessage).toHaveBeenCalledTimes(0);
 
 
-  stream.onData(utf8Encode('starting tracing Wrote 123 bytes'));
+  stream.onData(stringToUint8Array('starting tracing Wrote 123 bytes'));
   stream.onClose();
 
   expect(adbController.sendErrorMessage).toHaveBeenCalledTimes(0);
diff --git a/ui/src/controller/adb_shell_controller.ts b/ui/src/controller/adb_shell_controller.ts
index 9b457e7..62c8204 100644
--- a/ui/src/controller/adb_shell_controller.ts
+++ b/ui/src/controller/adb_shell_controller.ts
@@ -14,8 +14,8 @@
 
 import {_TextDecoder} from 'custom_utils';
 
-import {base64Encode} from '../base/string_utils';
-import {extractTraceConfig} from '../base/trace_config_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';
@@ -181,7 +181,7 @@
   }
 
   generateStartTracingCommand(tracingConfig: Uint8Array) {
-    const configBase64 = base64Encode(tracingConfig);
+    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
index f517f7a..1a3229b 100644
--- a/ui/src/controller/adb_socket_controller.ts
+++ b/ui/src/controller/adb_socket_controller.ts
@@ -161,11 +161,7 @@
   }
 
   private parseMessage(frameBuffer: Uint8Array) {
-    // Copy message to new array:
-    const buf = new ArrayBuffer(frameBuffer.byteLength);
-    const arr = new Uint8Array(buf);
-    arr.set(frameBuffer);
-    const frame = perfetto.protos.IPCFrame.decode(arr);
+    const frame = perfetto.protos.IPCFrame.decode(frameBuffer);
     this.handleIncomingFrame(frame);
   }
 
@@ -291,7 +287,6 @@
   sendReadBufferResponse() {
     this.sendMessage(this.generateChunkReadResponse(
         this.traceProtoWriter.finish(), /* last */ true));
-    this.traceProtoWriter = protobuf.Writer.create();
   }
 
   bind() {
@@ -326,7 +321,7 @@
   }
 
   handleIncomingFrame(frame: perfetto.protos.IPCFrame) {
-    const requestId = frame.requestId;
+    const requestId = frame.requestId as number;
     switch (frame.msg) {
       case 'msgBindServiceReply': {
         const msgBindServiceReply = frame.msgBindServiceReply;
@@ -367,4 +362,4 @@
         .set('FreeBuffers', perfetto.protos.FreeBuffersResponse.decode)
         .set('ReadBuffers', perfetto.protos.ReadBuffersResponse.decode)
         .set('DisableTracing', perfetto.protos.DisableTracingResponse.decode)
-        .set('GetTraceStats', perfetto.protos.GetTraceStatsResponse.decode);
+        .set('GetTraceStats', perfetto.protos.GetTraceStatsResponse.decode);
\ No newline at end of file
diff --git a/ui/src/controller/aggregation/aggregation_controller.ts b/ui/src/controller/aggregation/aggregation_controller.ts
index 0892e37..165eee4 100644
--- a/ui/src/controller/aggregation/aggregation_controller.ts
+++ b/ui/src/controller/aggregation/aggregation_controller.ts
@@ -12,15 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {
-  AggregateData,
-  Column,
-  ColumnDef,
-  ThreadStateExtra,
-} from '../../common/aggregation_data';
+import {AggregateData, Column, ColumnDef} from '../../common/aggregation_data';
 import {Engine} from '../../common/engine';
-import {slowlyCountRows} from '../../common/query_iterator';
-import {Area, Sorting} from '../../common/state';
+import {Sorting, TimestampedAreaSelection} from '../../common/state';
 import {Controller} from '../controller';
 import {globals} from '../globals';
 
@@ -31,16 +25,13 @@
 
 export abstract class AggregationController extends Controller<'main'> {
   readonly kind: string;
-  private previousArea?: Area;
+  private previousArea: TimestampedAreaSelection = {lastUpdate: 0};
   private previousSorting?: Sorting;
   private requestingData = false;
   private queuedRequest = false;
 
-  abstract async createAggregateView(engine: Engine, area: Area):
-      Promise<boolean>;
-
-  abstract async getExtra(engine: Engine, area: Area):
-      Promise<ThreadStateExtra|void>;
+  abstract async createAggregateView(
+      engine: Engine, area: TimestampedAreaSelection): Promise<boolean>;
 
   abstract getTabName(): string;
   abstract getDefaultSorting(): Sorting;
@@ -52,24 +43,11 @@
   }
 
   run() {
-    const selection = globals.state.currentSelection;
-    if (selection === null || selection.kind !== 'AREA') {
-      globals.publish('AggregateData', {
-        data: {
-          tabName: this.getTabName(),
-          columns: [],
-          strings: [],
-          columnSums: [],
-        },
-        kind: this.args.kind
-      });
-      return;
-    }
-    const selectedArea = globals.state.areas[selection.areaId];
+    const selectedArea = globals.state.frontendLocalState.selectedArea;
     const aggregatePreferences =
         globals.state.aggregatePreferences[this.args.kind];
 
-    const areaChanged = this.previousArea !== selectedArea;
+    const areaChanged = this.previousArea.lastUpdate < selectedArea.lastUpdate;
     const sortingChanged = aggregatePreferences &&
         this.previousSorting !== aggregatePreferences.sorting;
     if (!areaChanged && !sortingChanged) return;
@@ -79,8 +57,8 @@
     } else {
       this.requestingData = true;
       if (sortingChanged) this.previousSorting = aggregatePreferences.sorting;
-      if (areaChanged) this.previousArea = Object.assign({}, selectedArea);
-      this.getAggregateData(selectedArea, areaChanged)
+      if (areaChanged) this.previousArea = selectedArea;
+      this.getAggregateData(areaChanged)
           .then(
               data => globals.publish(
                   'AggregateData', {data, kind: this.args.kind}))
@@ -94,17 +72,13 @@
     }
   }
 
-  async getAggregateData(area: Area, areaChanged: boolean):
-      Promise<AggregateData> {
+  async getAggregateData(areaChanged: boolean): Promise<AggregateData> {
+    const selectedArea = globals.state.frontendLocalState.selectedArea;
     if (areaChanged) {
-      const viewExists = await this.createAggregateView(this.args.engine, area);
+      const viewExists =
+          await this.createAggregateView(this.args.engine, selectedArea);
       if (!viewExists) {
-        return {
-          tabName: this.getTabName(),
-          columns: [],
-          strings: [],
-          columnSums: [],
-        };
+        return {tabName: this.getTabName(), columns: [], strings: []};
       }
     }
 
@@ -119,13 +93,11 @@
     const query = `select ${colIds} from ${this.kind} order by ${sorting}`;
     const result = await this.args.engine.query(query);
 
-    const numRows = slowlyCountRows(result);
+    const numRows = +result.numRecords;
     const columns = defs.map(def => this.columnFromColumnDef(def, numRows));
-    const columnSums = await Promise.all(defs.map(def => this.getSum(def)));
-    const extraData = await this.getExtra(this.args.engine, area);
-    const extra = extraData ? extraData : undefined;
-    const data: AggregateData =
-        {tabName: this.getTabName(), columns, columnSums, strings: [], extra};
+
+    const data:
+        AggregateData = {tabName: this.getTabName(), columns, strings: []};
 
     const stringIndexes = new Map<string, number>();
     function internString(str: string) {
@@ -144,7 +116,7 @@
           data.columns[col].data[row] =
               internString(cols[col].stringValues![row]);
         } else if (cols[col].longValues && cols[col].longValues!.length > 0) {
-          data.columns[col].data[row] = cols[col].longValues![row];
+          data.columns[col].data[row] = cols[col].longValues![row] as number;
         } else if (
             cols[col].doubleValues && cols[col].doubleValues!.length > 0) {
           data.columns[col].data[row] = cols[col].doubleValues![row];
@@ -154,19 +126,8 @@
     return data;
   }
 
-  async getSum(def: ColumnDef): Promise<string> {
-    if (!def.sum) return '';
-    const result = await this.args.engine.queryOneRow(
-        `select sum(${def.columnId}) from ${this.kind}`);
-    let sum = result[0];
-    if (def.kind === 'TIMESTAMP_NS') {
-      sum = sum / 1e6;
-    }
-    return `${sum}`;
-  }
-
   columnFromColumnDef(def: ColumnDef, numRows: number): Column {
-    // TODO(hjd): The Column type should be based on the
+    // TODO(taylori): The Column type should be based on the
     // ColumnDef type or vice versa to avoid this cast.
     return {
       title: def.title,
diff --git a/ui/src/controller/aggregation/counter_aggregation_controller.ts b/ui/src/controller/aggregation/counter_aggregation_controller.ts
deleted file mode 100644
index 24d4a94..0000000
--- a/ui/src/controller/aggregation/counter_aggregation_controller.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {ColumnDef} from '../../common/aggregation_data';
-import {Engine} from '../../common/engine';
-import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
-import {Config, COUNTER_TRACK_KIND} from '../../tracks/counter/common';
-import {globals} from '../globals';
-
-import {AggregationController} from './aggregation_controller';
-
-export class CounterAggregationController extends AggregationController {
-  async createAggregateView(engine: Engine, area: Area) {
-    await engine.query(`drop view if exists ${this.kind};`);
-
-    const ids = [];
-    for (const trackId of area.tracks) {
-      const track = globals.state.tracks[trackId];
-      // Track will be undefined for track groups.
-      if (track !== undefined && track.kind === COUNTER_TRACK_KIND) {
-        const config = track.config as Config;
-        // TODO(hjd): Also aggregate annotation (with namespace) counters.
-        if (config.namespace === undefined) {
-          ids.push(config.trackId);
-        }
-      }
-    }
-    if (ids.length === 0) return false;
-
-    const query = `create view ${this.kind} as select
-    name,
-    count(1) as count,
-    round(sum(weighted_value)/${
-        toNs(area.endSec) - toNs(area.startSec)}, 2) as avg_value,
-    last as last_value,
-    first as first_value,
-    max(last) - min(first) as delta_value,
-    round((max(last) - min(first))/${area.endSec - area.startSec}, 2) as rate,
-    min(value) as min_value,
-    max(value) as max_value
-    from
-        (select *,
-        (min(ts + dur, ${toNs(area.endSec)}) - max(ts,${toNs(area.startSec)}))
-        * value as weighted_value,
-        first_value(value) over
-        (partition by track_id order by ts) as first,
-        last_value(value) over
-        (partition by track_id order by ts
-            range between unbounded preceding and unbounded following) as last
-        from experimental_counter_dur
-        where track_id in (${ids})
-        and ts + dur >= ${toNs(area.startSec)} and
-        ts <= ${toNs(area.endSec)})
-    join counter_track
-    on track_id = counter_track.id
-    group by track_id`;
-
-    await engine.query(query);
-    return true;
-  }
-
-  getColumnDefinitions(): ColumnDef[] {
-    return [
-      {
-        title: 'Name',
-        kind: 'STRING',
-        columnConstructor: Uint16Array,
-        columnId: 'name',
-      },
-      {
-        title: 'Delta value',
-        kind: 'NUMBER',
-        columnConstructor: Float64Array,
-        columnId: 'delta_value'
-      },
-      {
-        title: 'Rate /s',
-        kind: 'Number',
-        columnConstructor: Float64Array,
-        columnId: 'rate'
-      },
-      {
-        title: 'Weighted avg value',
-        kind: 'Number',
-        columnConstructor: Float64Array,
-        columnId: 'avg_value'
-      },
-      {
-        title: 'Count',
-        kind: 'Number',
-        columnConstructor: Float64Array,
-        columnId: 'count',
-        sum: true,
-      },
-      {
-        title: 'First value',
-        kind: 'NUMBER',
-        columnConstructor: Float64Array,
-        columnId: 'first_value'
-      },
-      {
-        title: 'Last value',
-        kind: 'NUMBER',
-        columnConstructor: Float64Array,
-        columnId: 'last_value'
-      },
-      {
-        title: 'Min value',
-        kind: 'NUMBER',
-        columnConstructor: Float64Array,
-        columnId: 'min_value'
-      },
-      {
-        title: 'Max value',
-        kind: 'NUMBER',
-        columnConstructor: Float64Array,
-        columnId: 'max_value'
-      },
-
-    ];
-  }
-
-  async getExtra() {}
-
-  getTabName() {
-    return 'Counters';
-  }
-
-  getDefaultSorting(): Sorting {
-    return {column: 'name', direction: 'DESC'};
-  }
-}
diff --git a/ui/src/controller/aggregation/cpu_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
index a8b1161..fcbc57a 100644
--- a/ui/src/controller/aggregation/cpu_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
@@ -14,7 +14,7 @@
 
 import {ColumnDef} from '../../common/aggregation_data';
 import {Engine} from '../../common/engine';
-import {Area, Sorting} from '../../common/state';
+import {Sorting, TimestampedAreaSelection} from '../../common/state';
 import {toNs} from '../../common/time';
 import {Config, CPU_SLICE_TRACK_KIND} from '../../tracks/cpu_slices/common';
 import {globals} from '../globals';
@@ -23,8 +23,11 @@
 
 
 export class CpuAggregationController extends AggregationController {
-  async createAggregateView(engine: Engine, area: Area) {
+  async createAggregateView(
+      engine: Engine, selectedArea: TimestampedAreaSelection) {
     await engine.query(`drop view if exists ${this.kind};`);
+    const area = selectedArea.area;
+    if (area === undefined) return false;
 
     const selectedCpus = [];
     for (const trackId of area.tracks) {
@@ -54,11 +57,9 @@
   }
 
   getTabName() {
-    return 'CPU by thread';
+    return 'CPU Slices';
   }
 
-  async getExtra() {}
-
   getDefaultSorting(): Sorting {
     return {column: 'total_dur', direction: 'DESC'};
   }
@@ -93,8 +94,7 @@
         title: 'Wall duration (ms)',
         kind: 'TIMESTAMP_NS',
         columnConstructor: Float64Array,
-        columnId: 'total_dur',
-        sum: true
+        columnId: 'total_dur'
       },
       {
         title: 'Avg Wall duration (ms)',
@@ -106,8 +106,7 @@
         title: 'Occurrences',
         kind: 'NUMBER',
         columnConstructor: Uint16Array,
-        columnId: 'occurrences',
-        sum: true
+        columnId: 'occurrences'
       }
     ];
   }
diff --git a/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
deleted file mode 100644
index baf9efe..0000000
--- a/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {ColumnDef} from '../../common/aggregation_data';
-import {Engine} from '../../common/engine';
-import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
-import {Config, CPU_SLICE_TRACK_KIND} from '../../tracks/cpu_slices/common';
-import {globals} from '../globals';
-
-import {AggregationController} from './aggregation_controller';
-
-export class CpuByProcessAggregationController extends AggregationController {
-  async createAggregateView(engine: Engine, area: Area) {
-    await engine.query(`drop view if exists ${this.kind};`);
-
-    const selectedCpus = [];
-    for (const trackId of area.tracks) {
-      const track = globals.state.tracks[trackId];
-      // Track will be undefined for track groups.
-      if (track !== undefined && track.kind === CPU_SLICE_TRACK_KIND) {
-        selectedCpus.push((track.config as Config).cpu);
-      }
-    }
-    if (selectedCpus.length === 0) return false;
-
-    const query = `create view ${this.kind} as
-        SELECT process.name as process_name, pid,
-        sum(dur) AS total_dur,
-        sum(dur)/count(1) as avg_dur,
-        count(1) as occurrences
-        FROM process
-        JOIN thread USING(upid)
-        JOIN thread_state USING(utid)
-        WHERE cpu IN (${selectedCpus}) AND
-        state = "Running" AND
-        thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
-        thread_state.ts < ${toNs(area.endSec)} group by upid`;
-
-    await engine.query(query);
-    return true;
-  }
-
-  getTabName() {
-    return 'CPU by process';
-  }
-
-  async getExtra() {}
-
-  getDefaultSorting(): Sorting {
-    return {column: 'total_dur', direction: 'DESC'};
-  }
-
-  getColumnDefinitions(): ColumnDef[] {
-    return [
-      {
-        title: 'Process',
-        kind: 'STRING',
-        columnConstructor: Uint16Array,
-        columnId: 'process_name',
-      },
-      {
-        title: 'PID',
-        kind: 'NUMBER',
-        columnConstructor: Uint16Array,
-        columnId: 'pid'
-      },
-      {
-        title: 'Wall duration (ms)',
-        kind: 'TIMESTAMP_NS',
-        columnConstructor: Float64Array,
-        columnId: 'total_dur',
-        sum: true
-      },
-      {
-        title: 'Avg Wall duration (ms)',
-        kind: 'TIMESTAMP_NS',
-        columnConstructor: Float64Array,
-        columnId: 'avg_dur'
-      },
-      {
-        title: 'Occurrences',
-        kind: 'NUMBER',
-        columnConstructor: Uint16Array,
-        columnId: 'occurrences',
-        sum: true
-      }
-    ];
-  }
-}
diff --git a/ui/src/controller/aggregation/slice_aggregation_controller.ts b/ui/src/controller/aggregation/slice_aggregation_controller.ts
deleted file mode 100644
index f3b2807..0000000
--- a/ui/src/controller/aggregation/slice_aggregation_controller.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {ColumnDef} from '../../common/aggregation_data';
-import {Engine} from '../../common/engine';
-import {Area, Sorting} from '../../common/state';
-import {toNs} from '../../common/time';
-import {
-  ASYNC_SLICE_TRACK_KIND,
-  Config as AsyncSliceConfig
-} from '../../tracks/async_slices/common';
-import {
-  Config as SliceConfig,
-  SLICE_TRACK_KIND
-} from '../../tracks/chrome_slices/common';
-import {globals} from '../globals';
-
-import {AggregationController} from './aggregation_controller';
-
-export class SliceAggregationController extends AggregationController {
-  async createAggregateView(engine: Engine, area: Area) {
-    await engine.query(`drop view if exists ${this.kind};`);
-
-    const selectedTrackIds = [];
-    for (const trackId of area.tracks) {
-      const track = globals.state.tracks[trackId];
-      // Track will be undefined for track groups.
-      if (track !== undefined) {
-        if (track.kind === SLICE_TRACK_KIND) {
-          selectedTrackIds.push((track.config as SliceConfig).trackId);
-        }
-        if (track.kind === ASYNC_SLICE_TRACK_KIND) {
-          const config = track.config as AsyncSliceConfig;
-          for (const id of config.trackIds) {
-            selectedTrackIds.push(id);
-          }
-        }
-      }
-    }
-    if (selectedTrackIds.length === 0) return false;
-
-    const query = `create view ${this.kind} as
-        SELECT
-        name,
-        sum(dur) AS total_dur,
-        sum(dur)/count(1) as avg_dur,
-        count(1) as occurrences
-        FROM slices
-        WHERE track_id IN (${selectedTrackIds}) AND
-        ts + dur > ${toNs(area.startSec)} AND
-        ts < ${toNs(area.endSec)} group by name`;
-
-    await engine.query(query);
-    return true;
-  }
-
-  getTabName() {
-    return 'Slices';
-  }
-
-  async getExtra() {}
-
-  getDefaultSorting(): Sorting {
-    return {column: 'total_dur', direction: 'DESC'};
-  }
-
-  getColumnDefinitions(): ColumnDef[] {
-    return [
-      {
-        title: 'Name',
-        kind: 'STRING',
-        columnConstructor: Uint16Array,
-        columnId: 'name',
-      },
-      {
-        title: 'Wall duration (ms)',
-        kind: 'TIMESTAMP_NS',
-        columnConstructor: Float64Array,
-        columnId: 'total_dur',
-        sum: true
-      },
-      {
-        title: 'Avg Wall duration (ms)',
-        kind: 'TIMESTAMP_NS',
-        columnConstructor: Float64Array,
-        columnId: 'avg_dur'
-      },
-      {
-        title: 'Occurrences',
-        kind: 'NUMBER',
-        columnConstructor: Uint16Array,
-        columnId: 'occurrences',
-        sum: true
-      }
-    ];
-  }
-}
diff --git a/ui/src/controller/aggregation/thread_aggregation_controller.ts b/ui/src/controller/aggregation/thread_aggregation_controller.ts
index 03eb935..b781275 100644
--- a/ui/src/controller/aggregation/thread_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/thread_aggregation_controller.ts
@@ -12,11 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {ColumnDef, ThreadStateExtra} from '../../common/aggregation_data';
+import {ColumnDef} from '../../common/aggregation_data';
 import {Engine} from '../../common/engine';
-import {slowlyCountRows} from '../../common/query_iterator';
-import {Area, Sorting} from '../../common/state';
-import {translateState} from '../../common/thread_state';
+import {Sorting, TimestampedAreaSelection} from '../../common/state';
 import {toNs} from '../../common/time';
 import {
   Config,
@@ -27,80 +25,42 @@
 import {AggregationController} from './aggregation_controller';
 
 export class ThreadAggregationController extends AggregationController {
-  private utids?: number[];
+  async createAggregateView(
+      engine: Engine, selectedArea: TimestampedAreaSelection) {
+    await engine.query(`drop view if exists ${this.kind};`);
+    const area = selectedArea.area;
+    if (area === undefined) return false;
 
-  setThreadStateUtids(tracks: string[]) {
-    this.utids = [];
-    for (const trackId of tracks) {
+    // TODO(taylori): Thread state tracks should have a real track id in the
+    // trace processor.
+    const utids = [];
+    for (const trackId of area.tracks) {
       const track = globals.state.tracks[trackId];
       // Track will be undefined for track groups.
       if (track !== undefined && track.kind === THREAD_STATE_TRACK_KIND) {
-        this.utids.push((track.config as Config).utid);
+        utids.push((track.config as Config).utid);
       }
     }
-  }
+    if (utids.length === 0) return false;
 
-  async createAggregateView(engine: Engine, area: Area) {
-    await engine.query(`drop view if exists ${this.kind};`);
-    this.setThreadStateUtids(area.tracks);
-    if (this.utids === undefined || this.utids.length === 0) return false;
-
-    const query = `
-      create view ${this.kind} as
-      SELECT
-        process.name as process_name,
-        pid,
-        thread.name as thread_name,
-        tid,
-        state || ',' || IFNULL(io_wait, 'NULL') as concat_state,
-        sum(dur) AS total_dur,
-        sum(dur)/count(1) as avg_dur,
-        count(1) as occurrences
+    const query = `create view ${this.kind} as
+      SELECT process.name as process_name, pid, thread.name as thread_name, tid,
+      state,
+      sum(dur) AS total_dur,
+      sum(dur)/count(1) as avg_dur,
+      count(1) as occurrences
       FROM process
       JOIN thread USING(upid)
       JOIN thread_state USING(utid)
-      WHERE utid IN (${this.utids}) AND
+      WHERE utid IN (${utids}) AND
       thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
       thread_state.ts < ${toNs(area.endSec)}
-      GROUP BY utid, concat_state
-    `;
+      GROUP BY utid, state`;
 
     await engine.query(query);
     return true;
   }
 
-  async getExtra(engine: Engine, area: Area): Promise<ThreadStateExtra|void> {
-    this.setThreadStateUtids(area.tracks);
-    if (this.utids === undefined || this.utids.length === 0) return;
-
-    const query = `select state, io_wait, sum(dur) as total_dur from process
-      JOIN thread USING(upid)
-      JOIN thread_state USING(utid)
-      WHERE utid IN (${this.utids}) AND thread_state.ts + thread_state.dur > ${
-        toNs(area.startSec)} AND
-      thread_state.ts < ${toNs(area.endSec)}
-      GROUP BY state, io_wait`;
-    const result = await engine.query(query);
-    const numRows = slowlyCountRows(result);
-
-    const summary: ThreadStateExtra = {
-      kind: 'THREAD_STATE',
-      states: [],
-      values: new Float64Array(numRows),
-      totalMs: 0
-    };
-    for (let row = 0; row < numRows; row++) {
-      const state = result.columns[0].stringValues![row];
-      const ioWait = result.columns[1].isNulls![row] ?
-          undefined :
-          !!result.columns[1].longValues![row];
-      summary.states.push(translateState(state, ioWait));
-      summary.values[row] = result.columns[2].longValues![row] / 1000000;  // ms
-    }
-    summary.totalMs = summary.values.reduce((a, b) => a + b, 0);
-    return summary;
-  }
-
   getColumnDefinitions(): ColumnDef[] {
     return [
       {
@@ -131,14 +91,13 @@
         title: 'State',
         kind: 'STATE',
         columnConstructor: Uint16Array,
-        columnId: 'concat_state'
+        columnId: 'state'
       },
       {
         title: 'Wall duration (ms)',
         kind: 'TIMESTAMP_NS',
         columnConstructor: Float64Array,
-        columnId: 'total_dur',
-        sum: true
+        columnId: 'total_dur'
       },
       {
         title: 'Avg Wall duration (ms)',
@@ -150,8 +109,7 @@
         title: 'Occurrences',
         kind: 'NUMBER',
         columnConstructor: Uint16Array,
-        columnId: 'occurrences',
-        sum: true
+        columnId: 'occurrences'
       }
     ];
   }
diff --git a/ui/src/controller/args_parser.ts b/ui/src/controller/args_parser.ts
deleted file mode 100644
index b5e1b56..0000000
--- a/ui/src/controller/args_parser.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (C) 2021 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 {
-  Args,
-  ArgsTree,
-  ArgsTreeArray,
-  ArgsTreeMap,
-  isArgTreeArray,
-  isArgTreeMap
-} from '../common/arg_types';
-
-// Converts a flats sequence of key-value pairs into a JSON-like nested
-// structure. Dots in keys are used to create a nested dictionary, indices in
-// brackets used to create nested array. For example, consider the following
-// sequence of key-value pairs:
-//
-// simple_key = simple_value
-// thing.key = value
-// thing.point[0].x = 10
-// thing.point[0].y = 20
-// thing.point[1].x = 0
-// thing.point[1].y = -10
-//
-// It's going to be converted to a following object:
-//
-// {
-//   "simple_key": "simple_value",
-//   "thing": {
-//     "key": "value",
-//     "point": [
-//       { "x": "10", "y": "20" },
-//       { "x": "0", "y": "-10" }
-//     ]
-//   }
-// }
-export function parseArgs(args: Args): ArgsTree|undefined {
-  const result: ArgsTreeMap = {};
-  for (const [key, value] of args) {
-    if (typeof value === 'string') {
-      fillObject(result, key.split('.'), value);
-    }
-  }
-  return result;
-}
-
-function getOrCreateMap(
-    object: ArgsTreeMap|ArgsTreeArray, key: string|number): ArgsTreeMap {
-  let value: ArgsTree;
-  if (isArgTreeMap(object) && typeof key === 'string') {
-    value = object[key];
-  } else if (isArgTreeArray(object) && typeof key === 'number') {
-    value = object[key];
-  } else {
-    throw new Error('incompatible parameters to getOrCreateSubmap');
-  }
-
-  if (value !== undefined) {
-    if (isArgTreeMap(value)) {
-      return value;
-    } else {
-      // There is a value, but it's not a map - something wrong with the key set
-      throw new Error('inconsistent keys');
-    }
-  }
-
-  value = {};
-  if (isArgTreeMap(object) && typeof key === 'string') {
-    object[key] = value;
-  } else if (isArgTreeArray(object) && typeof key === 'number') {
-    object[key] = value;
-  }
-
-  return value;
-}
-
-function getOrCreateArray(object: ArgsTreeMap, key: string): ArgsTree[] {
-  let value = object[key];
-  if (value !== undefined) {
-    if (isArgTreeArray(value)) {
-      return value;
-    } else {
-      // There is a value, but it's not an array - something wrong with the key
-      // set
-      throw new Error('inconsistent keys');
-    }
-  }
-
-  value = [];
-  object[key] = value;
-  return value;
-}
-
-function fillObject(object: ArgsTreeMap, path: string[], value: string) {
-  let current = object;
-  for (let i = 0; i < path.length - 1; i++) {
-    const [part, index] = parsePathSegment(path[i]);
-    if (index === undefined) {
-      current = getOrCreateMap(current, part);
-    } else {
-      const array = getOrCreateArray(current, part);
-      current = getOrCreateMap(array, index);
-    }
-  }
-
-  const [part, index] = parsePathSegment(path[path.length - 1]);
-  if (index === undefined) {
-    current[part] = value;
-  } else {
-    const array = getOrCreateArray(current, part);
-    array[index] = value;
-  }
-}
-
-// Segment is either a simple key (e.g. "foo") or a key with an index (e.g.
-// "bar[42]"). This function returns a pair of key and index (if present).
-function parsePathSegment(segment: string): [string, number?] {
-  if (!segment.endsWith(']')) {
-    return [segment, undefined];
-  }
-
-  const indexStart = segment.indexOf('[');
-  const indexString = segment.substring(indexStart + 1, segment.length - 1);
-  return [segment.substring(0, indexStart), Math.floor(Number(indexString))];
-}
\ No newline at end of file
diff --git a/ui/src/controller/chrome_proxy_record_controller.ts b/ui/src/controller/chrome_proxy_record_controller.ts
index 4934cc0..54a4f29 100644
--- a/ui/src/controller/chrome_proxy_record_controller.ts
+++ b/ui/src/controller/chrome_proxy_record_controller.ts
@@ -12,16 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {binaryDecode, binaryEncode} from '../base/string_utils';
-import {Actions} from '../common/actions';
-import {TRACE_SUFFIX} from '../common/constants';
+import {stringToUint8Array, uint8ArrayToString} from '../base/string_utils';
 
 import {
   ConsumerPortResponse,
+  isConsumerPortResponse,
   isReadBuffersResponse,
   Typed
 } from './consumer_port_types';
-import {globals} from './globals';
 import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
 
 export interface ChromeExtensionError extends Typed {
@@ -32,12 +30,8 @@
   status: string;
 }
 
-export interface GetCategoriesResponse extends Typed {
-  categories: string[];
-}
-
-export type ChromeExtensionMessage = ChromeExtensionError|ChromeExtensionStatus|
-    ConsumerPortResponse|GetCategoriesResponse;
+export type ChromeExtensionMessage =
+    ChromeExtensionError|ChromeExtensionStatus|ConsumerPortResponse;
 
 function isError(obj: Typed): obj is ChromeExtensionError {
   return obj.type === 'ChromeExtensionError';
@@ -47,20 +41,10 @@
   return obj.type === 'ChromeExtensionStatus';
 }
 
-function isGetCategoriesResponse(obj: Typed): obj is GetCategoriesResponse {
-  return obj.type === 'GetCategoriesResponse';
-}
-
 // 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.
-
-// Rationale for the binaryEncode / binaryDecode calls below:
-// Messages to/from extensions need to be JSON serializable. ArrayBuffers are
-// not supported. For this reason here we use binaryEncode/Decode.
-// See https://developer.chrome.com/extensions/messaging#simple
-
 export class ChromeExtensionConsumerPort extends RpcConsumerPort {
   private extensionPort: MessagePort;
 
@@ -79,25 +63,24 @@
       this.sendStatus(message.data.status);
       return;
     }
-    if (isGetCategoriesResponse(message.data)) {
-      globals.dispatch(Actions.setChromeCategories(message.data));
-      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 = binaryDecode(slice);
+      message.data.slices[0].data = stringToUint8Array(slice);
     }
     this.sendMessage(message.data);
   }
 
   handleCommand(method: string, requestData: Uint8Array): void {
-    const reqEncoded = binaryEncode(requestData);
-    this.extensionPort.postMessage({method, requestData: reqEncoded});
-  }
-
-  getRecordedTraceSuffix(): string {
-    return `${TRACE_SUFFIX}.gz`;
+    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
index cb054e1..8a249d4 100644
--- a/ui/src/controller/consumer_port_types.ts
+++ b/ui/src/controller/consumer_port_types.ts
@@ -24,15 +24,15 @@
     Typed, perfetto.protos.IEnableTracingResponse {}
 export interface GetTraceStatsResponse extends
     Typed, perfetto.protos.IGetTraceStatsResponse {}
-export interface FreeBuffersResponse extends
-    Typed, perfetto.protos.IFreeBuffersResponse {}
-export interface GetCategoriesResponse extends Typed {}
-export interface DisableTracingResponse extends
-    Typed, perfetto.protos.IDisableTracingResponse {}
 
 export type ConsumerPortResponse =
-    EnableTracingResponse|ReadBuffersResponse|GetTraceStatsResponse|
-    GetCategoriesResponse|FreeBuffersResponse|DisableTracingResponse;
+    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';
@@ -46,18 +46,4 @@
 export function isGetTraceStatsResponse(obj: Typed):
     obj is GetTraceStatsResponse {
   return obj.type === 'GetTraceStatsResponse';
-}
-
-export function isGetCategoriesResponse(obj: Typed):
-    obj is GetCategoriesResponse {
-  return obj.type === 'GetCategoriesResponse';
-}
-
-export function isFreeBuffersResponse(obj: Typed): obj is FreeBuffersResponse {
-  return obj.type === 'FreeBuffersResponse';
-}
-
-export function isDisableTracingResponse(obj: Typed):
-    obj is DisableTracingResponse {
-  return obj.type === 'DisableTracingResponse';
-}
+}
\ No newline at end of file
diff --git a/ui/src/controller/cpu_profile_controller.ts b/ui/src/controller/cpu_profile_controller.ts
index 05e03e9..d8efd0b 100644
--- a/ui/src/controller/cpu_profile_controller.ts
+++ b/ui/src/controller/cpu_profile_controller.ts
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 import {Engine} from '../common/engine';
-import {slowlyCountRows} from '../common/query_iterator';
 import {CallsiteInfo, CpuProfileSampleSelection} from '../common/state';
 import {CpuProfileDetails} from '../frontend/globals';
 
@@ -94,61 +93,69 @@
   }
 
   async getSampleData(id: number) {
-    // The goal of the query is to get all the frames of
-    // the callstack at the callsite given by |id|. To do this, it does
-    // the following:
-    // 1. Gets the leaf callsite id for the sample given by |id|.
-    // 2. For this callsite, get all the frame ids and depths
-    //    for the frame and all ancestors in the callstack.
-    // 3. For each frame, get the mapping name (i.e. library which
-    //    contains the frame).
-    // 4. Symbolize each frame using the symbol table if possible.
-    // 5. Sort the query by the depth of the callstack frames.
-    const sampleQuery = `
-      SELECT
-        samples.id,
-        IFNULL(
-          (
-            SELECT name
-            FROM stack_profile_symbol symbol
-            WHERE symbol.symbol_set_id = spf.symbol_set_id
-            LIMIT 1
-          ),
-          spf.name
-        ) AS frame_name,
-        spm.name AS mapping_name
+    const sampleQuery = `SELECT samples.id, frame_name, mapping_name
       FROM cpu_profile_stack_sample AS samples
-      LEFT JOIN (
-        SELECT
-          id,
-          frame_id,
-          depth
-        FROM stack_profile_callsite
-        UNION ALL
-        SELECT
-          leaf.id AS id,
-          callsite.frame_id AS frame_id,
-          callsite.depth AS depth
-        FROM stack_profile_callsite leaf
-        JOIN experimental_ancestor_stack_profile_callsite(leaf.id) AS callsite
-      ) AS callsites
-        ON samples.callsite_id = callsites.id
-      LEFT JOIN stack_profile_frame AS spf
-        ON callsites.frame_id = spf.id
-      LEFT JOIN stack_profile_mapping AS spm
-        ON spf.mapping = spm.id
+      LEFT JOIN
+        (
+          SELECT
+            callsite_id,
+            position,
+            spf.name AS frame_name,
+            stack_profile_mapping.name AS mapping_name
+          FROM
+            (
+              WITH
+                RECURSIVE
+                  callsite_parser(callsite_id, current_id, position)
+                  AS (
+                    SELECT id, id, 0 FROM stack_profile_callsite
+                    UNION
+                      SELECT callsite_id, parent_id, position + 1
+                      FROM callsite_parser
+                      JOIN
+                        stack_profile_callsite
+                        ON stack_profile_callsite.id = current_id
+                      WHERE stack_profile_callsite.depth > 0
+                  )
+              SELECT *
+              FROM callsite_parser
+            ) AS flattened_callsite
+          LEFT JOIN stack_profile_callsite AS spc
+          LEFT JOIN
+            (
+              SELECT
+                spf.id AS id,
+                spf.mapping AS mapping,
+                IFNULL(
+                  (
+                    SELECT name
+                    FROM stack_profile_symbol symbol
+                    WHERE symbol.symbol_set_id = spf.symbol_set_id
+                    LIMIT 1
+                  ),
+                  spf.name
+                ) AS name
+              FROM stack_profile_frame spf
+            ) AS spf
+          LEFT JOIN stack_profile_mapping
+          WHERE
+            flattened_callsite.current_id = spc.id
+            AND spc.frame_id = spf.id
+            AND spf.mapping = stack_profile_mapping.id
+          ORDER BY callsite_id, position
+        ) AS frames
+        ON samples.callsite_id = frames.callsite_id
       WHERE samples.id = ${id}
-      ORDER BY callsites.depth;
-    `;
+      ORDER BY samples.id, frames.position DESC;`;
 
     const callsites = await this.args.engine.query(sampleQuery);
 
-    if (slowlyCountRows(callsites) < 1) {
+    if (callsites.numRecords < 1) {
       return undefined;
     }
 
     const sampleData: CallsiteInfo[] = new Array();
-    for (let i = 0; i < slowlyCountRows(callsites); i++) {
+    for (let i = 0; i < callsites.numRecords; i++) {
       const id = +callsites.columns[0].longValues![i];
       const name = callsites.columns[1].stringValues![i];
       const mapping = callsites.columns[2].stringValues![i];
@@ -161,8 +168,7 @@
         name,
         selfSize: 0,
         mapping,
-        merged: false,
-        highlighted: false
+        merged: false
       });
     }
 
diff --git a/ui/src/controller/flow_events_controller.ts b/ui/src/controller/flow_events_controller.ts
deleted file mode 100644
index 87dd298..0000000
--- a/ui/src/controller/flow_events_controller.ts
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (C) 2020 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 {Engine} from '../common/engine';
-import {slowlyCountRows} from '../common/query_iterator';
-import {Area} from '../common/state';
-import {fromNs, toNs} from '../common/time';
-import {Flow} from '../frontend/globals';
-import {
-  ACTUAL_FRAMES_SLICE_TRACK_KIND,
-  Config as ActualConfig
-} from '../tracks/actual_frames/common';
-import {
-  Config as SliceConfig,
-  SLICE_TRACK_KIND
-} from '../tracks/chrome_slices/common';
-
-import {Controller} from './controller';
-import {globals} from './globals';
-
-export interface FlowEventsControllerArgs {
-  engine: Engine;
-}
-
-export class FlowEventsController extends Controller<'main'> {
-  private lastSelectedSliceId?: number;
-  private lastSelectedArea?: Area;
-  private lastSelectedKind: 'CHROME_SLICE'|'AREA'|'NONE' = 'NONE';
-
-  constructor(private args: FlowEventsControllerArgs) {
-    super('main');
-  }
-
-  queryFlowEvents(query: string, callback: (flows: Flow[]) => void) {
-    this.args.engine.query(query).then(res => {
-      const flows: Flow[] = [];
-      for (let i = 0; i < slowlyCountRows(res); i++) {
-        const beginSliceId = res.columns[0].longValues![i];
-        const beginTrackId = res.columns[1].longValues![i];
-        const beginSliceName = res.columns[2].stringValues![i];
-        const beginSliceCategory = res.columns[3].stringValues![i];
-        const beginSliceStartTs = fromNs(res.columns[4].longValues![i]);
-        const beginSliceEndTs = fromNs(res.columns[5].longValues![i]);
-        const beginDepth = res.columns[6].longValues![i];
-
-        const endSliceId = res.columns[7].longValues![i];
-        const endTrackId = res.columns[8].longValues![i];
-        const endSliceName = res.columns[9].stringValues![i];
-        const endSliceCategory = res.columns[10].stringValues![i];
-        const endSliceStartTs = fromNs(res.columns[11].longValues![i]);
-        const endSliceEndTs = fromNs(res.columns[12].longValues![i]);
-        const endDepth = res.columns[13].longValues![i];
-
-        // Category and name present only in version 1 flow events
-        // It is most likelly NULL for all other versions
-        const category = res.columns[14].isNulls![i] ?
-            undefined :
-            res.columns[14].stringValues![i];
-        const name = res.columns[15].isNulls![i] ?
-            undefined :
-            res.columns[15].stringValues![i];
-        const id = res.columns[16].longValues![i];
-
-        flows.push({
-          id,
-          begin: {
-            trackId: beginTrackId,
-            sliceId: beginSliceId,
-            sliceName: beginSliceName,
-            sliceCategory: beginSliceCategory,
-            sliceStartTs: beginSliceStartTs,
-            sliceEndTs: beginSliceEndTs,
-            depth: beginDepth
-          },
-          end: {
-            trackId: endTrackId,
-            sliceId: endSliceId,
-            sliceName: endSliceName,
-            sliceCategory: endSliceCategory,
-            sliceStartTs: endSliceStartTs,
-            sliceEndTs: endSliceEndTs,
-            depth: endDepth
-          },
-          category,
-          name
-        });
-      }
-      callback(flows);
-    });
-  }
-
-  sliceSelected(sliceId: number) {
-    if (this.lastSelectedKind === 'CHROME_SLICE' &&
-        this.lastSelectedSliceId === sliceId) {
-      return;
-    }
-    this.lastSelectedSliceId = sliceId;
-    this.lastSelectedKind = 'CHROME_SLICE';
-
-    const query = `
-    select
-      f.slice_out, t1.track_id, t1.name,
-      t1.category, t1.ts, (t1.ts+t1.dur), t1.depth,
-      f.slice_in, t2.track_id, t2.name,
-      t2.category, t2.ts, (t2.ts+t2.dur), t2.depth,
-      extract_arg(f.arg_set_id, 'cat'),
-      extract_arg(f.arg_set_id, 'name'),
-      f.id
-    from directly_connected_flow(${sliceId}) f
-    join slice t1 on f.slice_out = t1.slice_id
-    join slice t2 on f.slice_in = t2.slice_id
-    `;
-    this.queryFlowEvents(
-        query, (flows: Flow[]) => globals.publish('ConnectedFlows', flows));
-  }
-
-  areaSelected(areaId: string) {
-    const area = globals.state.areas[areaId];
-    if (this.lastSelectedKind === 'AREA' && this.lastSelectedArea &&
-        this.lastSelectedArea.tracks.join(',') === area.tracks.join(',') &&
-        this.lastSelectedArea.endSec === area.endSec &&
-        this.lastSelectedArea.startSec === area.startSec) {
-      return;
-    }
-
-    this.lastSelectedArea = area;
-    this.lastSelectedKind = 'AREA';
-
-    const trackIds: number[] = [];
-
-    for (const uiTrackId of area.tracks) {
-      const track = globals.state.tracks[uiTrackId];
-      if (track === undefined) {
-        continue;
-      }
-      if (track.kind === SLICE_TRACK_KIND) {
-        trackIds.push((track.config as SliceConfig).trackId);
-      } else if (track.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
-        const actualConfig = track.config as ActualConfig;
-        for (const trackId of actualConfig.trackIds) {
-          trackIds.push(trackId);
-        }
-      }
-    }
-
-    const tracks = `(${trackIds.join(',')})`;
-
-    const startNs = toNs(area.startSec);
-    const endNs = toNs(area.endSec);
-
-    const query = `
-    select
-      f.slice_out, t1.track_id, t1.name,
-      t1.category, t1.ts, (t1.ts+t1.dur), t1.depth,
-      f.slice_in, t2.track_id, t2.name,
-      t2.category, t2.ts, (t2.ts+t2.dur), t2.depth,
-      extract_arg(f.arg_set_id, 'cat'),
-      extract_arg(f.arg_set_id, 'name'),
-      f.id
-    from flow f
-    join slice t1 on f.slice_out = t1.slice_id
-    join slice t2 on f.slice_in = t2.slice_id
-    where
-      (t1.track_id in ${tracks}
-        and (t1.ts+t1.dur <= ${endNs} and t1.ts+t1.dur >= ${startNs}))
-      or
-      (t2.track_id in ${tracks}
-        and (t2.ts <= ${endNs} and t2.ts >= ${startNs}))
-    `;
-    this.queryFlowEvents(
-        query, (flows: Flow[]) => globals.publish('SelectedFlows', flows));
-  }
-
-  refreshVisibleFlows() {
-    const selection = globals.state.currentSelection;
-    if (!selection) {
-      this.lastSelectedKind = 'NONE';
-      globals.publish('ConnectedFlows', []);
-      globals.publish('SelectedFlows', []);
-      return;
-    }
-
-    if (selection && selection.kind === 'CHROME_SLICE') {
-      this.sliceSelected(selection.id);
-    } else {
-      globals.publish('ConnectedFlows', []);
-    }
-
-    if (selection && selection.kind === 'AREA') {
-      this.areaSelected(selection.areaId);
-    } else {
-      globals.publish('SelectedFlows', []);
-    }
-  }
-
-  run() {
-    this.refreshVisibleFlows();
-  }
-}
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index 606dab4..67a5327 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -23,9 +23,7 @@
 type PublishKinds = 'OverviewData'|'TrackData'|'Threads'|'QueryResult'|
     'LegacyTrace'|'SliceDetails'|'CounterDetails'|'HeapProfileDetails'|
     'HeapProfileFlamegraph'|'FileDownload'|'Loading'|'Search'|'BufferUsage'|
-    'RecordingLog'|'SearchResult'|'AggregateData'|'CpuProfileDetails'|
-    'TraceErrors'|'UpdateChromeCategories'|'ConnectedFlows'|'SelectedFlows'|
-    'ThreadStateDetails'|'MetricError'|'MetricResult';
+    'RecordingLog'|'SearchResult'|'AggregateData'|'CpuProfileDetails';
 
 export interface App {
   state: State;
diff --git a/ui/src/controller/heap_profile_controller.ts b/ui/src/controller/heap_profile_controller.ts
index c424b8f..ea7357f 100644
--- a/ui/src/controller/heap_profile_controller.ts
+++ b/ui/src/controller/heap_profile_controller.ts
@@ -23,7 +23,6 @@
   OBJECTS_ALLOCATED_NOT_FREED_KEY,
   SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY
 } from '../common/flamegraph_util';
-import {slowlyCountRows} from '../common/query_iterator';
 import {CallsiteInfo, HeapProfileFlamegraph} from '../common/state';
 import {fromNs} from '../common/time';
 import {HeapProfileDetails} from '../frontend/globals';
@@ -210,23 +209,22 @@
     if (this.flamegraphDatasets.has(key)) {
       currentData = this.flamegraphDatasets.get(key)!;
     } else {
-      // TODO(hjd): Show loading state.
+      // TODO(taylori): Show loading state.
 
       // Collecting data for drawing flamegraph for selected heap profile.
       // Data needs to be in following format:
       // id, name, parent_id, depth, total_size
       const tableName =
           await this.prepareViewsAndTables(ts, upid, type, focusRegex);
-      currentData = await this.getFlamegraphDataFromTables(
-          tableName, viewingOption, focusRegex);
+      currentData =
+          await this.getFlamegraphDataFromTables(tableName, viewingOption);
       this.flamegraphDatasets.set(key, currentData);
     }
     return currentData;
   }
 
   async getFlamegraphDataFromTables(
-      tableName: string, viewingOption = DEFAULT_VIEWING_OPTION,
-      focusRegex: string) {
+      tableName: string, viewingOption = DEFAULT_VIEWING_OPTION) {
     let orderBy = '';
     let sizeIndex = 4;
     let selfIndex = 9;
@@ -274,7 +272,7 @@
 
     const flamegraphData: CallsiteInfo[] = new Array();
     const hashToindex: Map<number, number> = new Map();
-    for (let i = 0; i < slowlyCountRows(callsites); i++) {
+    for (let i = 0; i < callsites.numRecords; i++) {
       const hash = callsites.columns[0].longValues![i];
       let name = callsites.columns[1].stringValues![i];
       const parentHash = callsites.columns[2].longValues![i];
@@ -282,8 +280,6 @@
       const totalSize = +callsites.columns[sizeIndex].longValues![i];
       const mapping = callsites.columns[8].stringValues![i];
       const selfSize = +callsites.columns[selfIndex].longValues![i];
-      const highlighted = focusRegex !== '' &&
-          name.toLocaleLowerCase().includes(focusRegex.toLocaleLowerCase());
       const parentId =
           hashToindex.has(+parentHash) ? hashToindex.get(+parentHash)! : -1;
       if (depth === maxDepth - 1) {
@@ -301,8 +297,7 @@
         name,
         selfSize,
         mapping,
-        merged: false,
-        highlighted
+        merged: false
       });
     }
     return flamegraphData;
@@ -329,9 +324,8 @@
   getMinSizeDisplayed(flamegraphData: CallsiteInfo[], rootSize?: number):
       number {
     const timeState = globals.state.frontendLocalState.visibleState;
-    let width = (timeState.endSec - timeState.startSec) / timeState.resolution;
-    // TODO(168048193): Remove screen size hack:
-    width = Math.max(width, 800);
+    const width =
+        (timeState.endSec - timeState.startSec) / timeState.resolution;
     if (rootSize === undefined) {
       rootSize = findRootSize(flamegraphData);
     }
diff --git a/ui/src/controller/logs_controller.ts b/ui/src/controller/logs_controller.ts
index 7d1d49f..abe5a9e 100644
--- a/ui/src/controller/logs_controller.ts
+++ b/ui/src/controller/logs_controller.ts
@@ -20,7 +20,6 @@
   LogEntriesKey,
   LogExistsKey
 } from '../common/logs';
-import {slowlyCountRows} from '../common/query_iterator';
 import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
 
 import {Controller} from './controller';
@@ -74,7 +73,7 @@
         order by ts
         limit ${pagination.start}, ${pagination.count}`);
 
-  if (!slowlyCountRows(rowsResult)) {
+  if (!rowsResult.numRecords) {
     return {
       offset: pagination.start,
       timestamps: [],
@@ -84,8 +83,8 @@
     };
   }
 
-  const timestamps = rowsResult.columns[0].longValues!;
-  const priorities = rowsResult.columns[1].longValues!;
+  const timestamps = rowsResult.columns[0].longValues! as number[];
+  const priorities = rowsResult.columns[1].longValues! as number[];
   const tags = rowsResult.columns[2].stringValues!;
   const messages = rowsResult.columns[3].stringValues!;
 
diff --git a/ui/src/controller/metrics_controller.ts b/ui/src/controller/metrics_controller.ts
deleted file mode 100644
index 6d0e835..0000000
--- a/ui/src/controller/metrics_controller.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {Actions} from '../common/actions';
-import {Engine, QueryError} from '../common/engine';
-import {iter, STR} from '../common/query_iterator';
-
-import {Controller} from './controller';
-import {globals} from './globals';
-
-export class MetricsController extends Controller<'main'> {
-  private engine: Engine;
-  private currentlyRunningMetric?: string;
-
-  constructor(args: {engine: Engine}) {
-    super('main');
-    this.engine = args.engine;
-    this.setup().finally(() => {
-      this.run();
-    });
-  }
-
-  private async getMetricNames() {
-    const metrics = [];
-    const it = iter(
-        {
-          name: STR,
-        },
-        await this.engine.query('select name from trace_metrics'));
-    for (; it.valid(); it.next()) {
-      metrics.push(it.row.name);
-    }
-    return metrics;
-  }
-
-  private async setup() {
-    const metrics = await this.getMetricNames();
-    globals.dispatch(Actions.setAvailableMetrics({metrics}));
-  }
-
-  private async computeMetric(name: string) {
-    if (name === this.currentlyRunningMetric) return;
-    this.currentlyRunningMetric = name;
-    try {
-      const metricResult = await this.engine.computeMetric([name]);
-      globals.publish(
-          'MetricResult',
-          {name, resultString: metricResult.metricsAsPrototext});
-    } catch (e) {
-      if (e instanceof QueryError) {
-        // Reroute error to be displated differently when metric is run through
-        // metric page.
-        globals.publish('MetricResult', {name, error: e.message});
-      } else {
-        throw e;
-      }
-    }
-    globals.dispatch(Actions.resetMetricRequest({name}));
-    this.currentlyRunningMetric = undefined;
-  }
-
-  run() {
-    const {requestedMetric} = globals.state.metrics;
-    if (!requestedMetric) return;
-    this.computeMetric(requestedMetric);
-  }
-}
diff --git a/ui/src/controller/permalink_controller.ts b/ui/src/controller/permalink_controller.ts
index a390443..d991a89 100644
--- a/ui/src/controller/permalink_controller.ts
+++ b/ui/src/controller/permalink_controller.ts
@@ -13,21 +13,16 @@
 // limitations under the License.
 
 import {produce} from 'immer';
+import * as uuidv4 from 'uuid/v4';
 
-import {assertExists} from '../base/logging';
+import {assertExists, assertTrue} from '../base/logging';
 import {Actions} from '../common/actions';
-import {createEmptyState, State} from '../common/state';
-import {RecordConfig, STATE_VERSION} from '../common/state';
-import {
-  BUCKET_NAME,
-  saveState,
-  saveTrace,
-  toSha256
-} from '../common/upload_utils';
+import {State} from '../common/state';
 
 import {Controller} from './controller';
 import {globals} from './globals';
-import {validateRecordConfig} from './validate_config';
+
+export const BUCKET_NAME = 'perfetto-ui-data';
 
 export class PermalinkController extends Controller<'main'> {
   private lastRequestId?: string;
@@ -43,119 +38,108 @@
     const requestId = assertExists(globals.state.permalink.requestId);
     this.lastRequestId = requestId;
 
-    // if the |hash| is not set, this is a request to create a permalink.
+    // if the |link| is not set, this is a request to create a permalink.
     if (globals.state.permalink.hash === undefined) {
-      const isRecordingConfig =
-          assertExists(globals.state.permalink.isRecordingConfig);
-
-      PermalinkController.createPermalink(isRecordingConfig)
-          .then(((hash: string) => {
-            globals.dispatch(Actions.setPermalink({requestId, hash}));
-          }));
+      PermalinkController.createPermalink().then(hash => {
+        globals.dispatch(Actions.setPermalink({requestId, hash}));
+      });
       return;
     }
 
     // Otherwise, this is a request to load the permalink.
-    PermalinkController.loadState(globals.state.permalink.hash)
-        .then(stateOrConfig => {
-          if (PermalinkController.isRecordConfig(stateOrConfig)) {
-            // This permalink state only contains a RecordConfig. Show the
-            // recording page with the config, but keep other state as-is.
-            const validConfig = validateRecordConfig(stateOrConfig);
-            if (validConfig.errorMessage) {
-              // TODO(bsebastien): Show a warning message to the user in the UI.
-              console.warn(validConfig.errorMessage);
-            }
-            globals.dispatch(
-                Actions.setRecordConfig({config: validConfig.config}));
-            globals.dispatch(Actions.navigate({route: '/record'}));
-            return;
-          }
-          globals.dispatch(Actions.setState({newState: stateOrConfig}));
-          this.lastRequestId = stateOrConfig.permalink.requestId;
-        });
+    PermalinkController.loadState(globals.state.permalink.hash).then(state => {
+      globals.dispatch(Actions.setState({newState: state}));
+      this.lastRequestId = state.permalink.requestId;
+    });
   }
 
-  private static upgradeState(state: State): State {
-    if (state.version !== STATE_VERSION) {
-      const newState = createEmptyState();
-      // Copy the URL of the trace into the empty state.
-      for (const cfg of Object.values(state.engines)) {
-        newState
-            .engines[cfg.id] = {id: cfg.id, ready: false, source: cfg.source};
-      }
-      const message = `Unable to parse old state version. Discarding state ` +
-          `and loading trace.`;
-      console.warn(message);
-      PermalinkController.updateStatus(message);
-      return newState;
+  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)}`);
     }
-    return state;
-  }
 
-  private static isRecordConfig(stateOrConfig: State|
-                                RecordConfig): stateOrConfig is RecordConfig {
-    return ['STOP_WHEN_FULL', 'RING_BUFFER', 'LONG_TRACE'].includes(
-        stateOrConfig.mode);
-  }
-
-  private static async createPermalink(isRecordingConfig: boolean) {
-    let uploadState: State|RecordConfig = globals.state;
-
-    if (isRecordingConfig) {
-      uploadState = globals.state.recordConfig;
-    } else {
-      const engine = assertExists(Object.values(globals.state.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)}`);
-      }
-
-      if (dataToUpload !== undefined) {
-        PermalinkController.updateStatus(`Uploading ${traceName}`);
-        const url = await 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 = {};
-        });
-      }
+    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 = {};
+      });
     }
 
     // Upload state.
     PermalinkController.updateStatus(`Creating permalink...`);
-    const hash = await saveState(uploadState);
+    const hash = await this.saveState(uploadState);
     PermalinkController.updateStatus(`Permalink ready`);
     return hash;
   }
 
-  private static async loadState(id: string): Promise<State|RecordConfig> {
+  private static async saveState(state: State): Promise<string> {
+    const text = JSON.stringify(state);
+    const hash = await this.toSha256(text);
+    const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
+        `${BUCKET_NAME}/o?uploadType=media` +
+        `&name=${hash}&predefinedAcl=publicRead`;
+    const response = await fetch(url, {
+      method: 'post',
+      headers: {
+        'Content-Type': 'application/json; charset=utf-8',
+      },
+      body: text,
+    });
+    await response.json();
+
+    return hash;
+  }
+
+  private static async saveTrace(trace: File|ArrayBuffer): Promise<string> {
+    // TODO(hjd): This should probably also be a hash but that requires
+    // trace processor support.
+    const name = uuidv4();
+    const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
+        `${BUCKET_NAME}/o?uploadType=media` +
+        `&name=${name}&predefinedAcl=publicRead`;
+    const response = await fetch(url, {
+      method: 'post',
+      headers: {'Content-Type': 'application/octet-stream;'},
+      body: trace,
+    });
+    await response.json();
+    return `https://storage.googleapis.com/${BUCKET_NAME}/${name}`;
+  }
+
+  private static async loadState(id: string): Promise<State> {
     const url = `https://storage.googleapis.com/${BUCKET_NAME}/${id}`;
     const response = await fetch(url);
-    if (!response.ok) {
-      throw new Error(
-          `Could not fetch permalink.\n` +
-          `Are you sure the id (${id}) is correct?\n` +
-          `URL: ${url}`);
-    }
     const text = await response.text();
-    const stateHash = await toSha256(text);
+    const stateHash = await this.toSha256(text);
     const state = JSON.parse(text);
     if (stateHash !== id) {
       throw new Error(`State hash does not match ${id} vs. ${stateHash}`);
     }
-    if (!this.isRecordConfig(state)) {
-      return this.upgradeState(state);
-    }
     return state;
   }
 
+  private static async toSha256(str: string): Promise<string> {
+    // TODO(hjd): TypeScript bug with definition of TextEncoder.
+    // tslint:disable-next-line no-any
+    const buffer = new (TextEncoder as any)('utf-8').encode(str);
+    const digest = await crypto.subtle.digest('SHA-256', buffer);
+    return Array.from(new Uint8Array(digest)).map(x => x.toString(16)).join('');
+  }
+
   private static updateStatus(msg: string): void {
     // TODO(hjd): Unify loading updates.
     globals.dispatch(Actions.updateStatus({
diff --git a/ui/src/controller/query_controller.ts b/ui/src/controller/query_controller.ts
index c4bd9d4..d1c8314 100644
--- a/ui/src/controller/query_controller.ts
+++ b/ui/src/controller/query_controller.ts
@@ -17,7 +17,6 @@
 import {Engine} from '../common/engine';
 import {rawQueryResultColumns, rawQueryResultIter, Row} from '../common/protos';
 import {QueryResponse} from '../common/queries';
-import {slowlyCountRows} from '../common/query_iterator';
 
 import {Controller} from './controller';
 import {globals} from './globals';
@@ -56,7 +55,7 @@
 
   private async runQuery(sqlQuery: string) {
     const startMs = performance.now();
-    const rawResult = await this.args.engine.uncheckedQuery(sqlQuery);
+    const rawResult = await this.args.engine.query(sqlQuery, true);
     const durationMs = performance.now() - startMs;
     const columns = rawQueryResultColumns(rawResult);
     const rows =
@@ -66,7 +65,7 @@
       query: sqlQuery,
       durationMs,
       error: rawResult.error,
-      totalRowCount: slowlyCountRows(rawResult),
+      totalRowCount: +rawResult.numRecords,
       columns,
       rows,
     };
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index a124ecf..b037f77 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -15,10 +15,9 @@
 import {Message, Method, rpc, RPCImplCallback} from 'protobufjs';
 
 import {
-  base64Encode,
+  uint8ArrayToBase64,
 } from '../base/string_utils';
 import {Actions} from '../common/actions';
-import {TRACE_SUFFIX} from '../common/constants';
 import {
   AndroidLogConfig,
   AndroidLogId,
@@ -42,7 +41,7 @@
   isAdbTarget,
   isAndroidP,
   isChromeTarget,
-  isCrOSTarget,
+  MAX_TIME,
   RecordConfig,
   RecordingTarget
 } from '../common/state';
@@ -54,9 +53,7 @@
 import {
   ConsumerPortResponse,
   GetTraceStatsResponse,
-  isDisableTracingResponse,
   isEnableTracingResponse,
-  isFreeBuffersResponse,
   isGetTraceStatsResponse,
   isReadBuffersResponse,
 } from './consumer_port_types';
@@ -76,6 +73,12 @@
   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);
@@ -102,11 +105,6 @@
       protoCfg.fileWritePeriodMs = uiCfg.fileWritePeriodMs;
       protoCfg.maxFileSizeBytes = uiCfg.maxFileSizeMb * 1e6;
     }
-
-    // Clear incremental state every 5 seconds when tracing into a ring buffer.
-    const incStateConfig = new TraceConfig.IncrementalStateConfig();
-    incStateConfig.clearPeriodMs = 5000;
-    protoCfg.incrementalStateConfig = incStateConfig;
   }
 
   const ftraceEvents = new Set<string>(uiCfg.ftrace ? uiCfg.ftraceEvents : []);
@@ -119,15 +117,17 @@
   let procThreadAssociationFtrace = false;
   let trackInitialOomScore = false;
 
-  if (uiCfg.cpuSched) {
+  if (uiCfg.cpuSched || uiCfg.cpuLatency) {
     procThreadAssociationPolling = true;
     procThreadAssociationFtrace = true;
     ftraceEvents.add('sched/sched_switch');
     ftraceEvents.add('power/suspend_resume');
-    ftraceEvents.add('sched/sched_wakeup');
-    ftraceEvents.add('sched/sched_wakeup_new');
-    ftraceEvents.add('sched/sched_waking');
-    ftraceEvents.add('power/suspend_resume');
+    if (uiCfg.cpuLatency) {
+      ftraceEvents.add('sched/sched_wakeup');
+      ftraceEvents.add('sched/sched_wakeup_new');
+      ftraceEvents.add('sched/sched_waking');
+      ftraceEvents.add('power/suspend_resume');
+    }
   }
 
   if (uiCfg.cpuFreq) {
@@ -140,17 +140,6 @@
     ftraceEvents.add('power/gpu_frequency');
   }
 
-  if (uiCfg.gpuMemTotal) {
-    ftraceEvents.add('gpu_mem/gpu_mem_total');
-
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      const ds = new TraceConfig.DataSource();
-      ds.config = new DataSourceConfig();
-      ds.config.name = 'android.gpu.memory';
-      protoCfg.dataSources.push(ds);
-    }
-  }
-
   if (uiCfg.cpuSyscall) {
     ftraceEvents.add('raw_syscalls/sys_enter');
     ftraceEvents.add('raw_syscalls/sys_exit');
@@ -175,9 +164,7 @@
       AndroidPowerConfig.BatteryCounters.BATTERY_COUNTER_CURRENT,
     ];
     ds.config.androidPowerConfig.collectPowerRails = true;
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      protoCfg.dataSources.push(ds);
-    }
+    protoCfg.dataSources.push(ds);
   }
 
   if (uiCfg.boardSensors) {
@@ -206,7 +193,6 @@
     ftraceEvents.add('mm_event/mm_event_record');
     ftraceEvents.add('kmem/rss_stat');
     ftraceEvents.add('ion/ion_stat');
-    ftraceEvents.add('dmabuf_heap/dma_heap_stat');
     ftraceEvents.add('kmem/ion_heap_grow');
     ftraceEvents.add('kmem/ion_heap_shrink');
   }
@@ -246,7 +232,7 @@
 
   let heapprofd: HeapprofdConfig|undefined = undefined;
   if (uiCfg.heapProfiling) {
-    // TODO(hjd): Check or inform user if buffer size are too small.
+    // TODO(taylori): Check or inform user if buffer size are too small.
     const cfg = new HeapprofdConfig();
     cfg.samplingIntervalBytes = uiCfg.hpSamplingIntervalBytes;
     if (uiCfg.hpSharedMemoryBuffer >= 8192 &&
@@ -269,10 +255,6 @@
         cdc.dumpPhaseMs = uiCfg.hpContinuousDumpsPhase;
       }
     }
-    cfg.blockClient = uiCfg.hpBlockClient;
-    if (uiCfg.hpAllHeaps) {
-      cfg.allHeaps = true;
-    }
     heapprofd = cfg;
   }
 
@@ -310,9 +292,7 @@
     if (procThreadAssociationPolling || trackInitialOomScore) {
       ds.config.processStatsConfig.scanAllProcessesOnStart = true;
     }
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      protoCfg.dataSources.push(ds);
-    }
+    protoCfg.dataSources.push(ds);
   }
 
   if (uiCfg.androidLogs) {
@@ -325,18 +305,7 @@
       return AndroidLogId[name as any as number] as any as number;
     });
 
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      protoCfg.dataSources.push(ds);
-    }
-  }
-
-  if (uiCfg.androidFrameTimeline) {
-    const ds = new TraceConfig.DataSource();
-    ds.config = new DataSourceConfig();
-    ds.config.name = 'android.surfaceflinger.frametimeline';
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      protoCfg.dataSources.push(ds);
-    }
+    protoCfg.dataSources.push(ds);
   }
 
   if (uiCfg.chromeLogs) {
@@ -399,22 +368,10 @@
     } else {
       chromeRecordMode = 'record-continuously';
     }
-    const configStruct = {
+    const traceConfigJson = JSON.stringify({
       record_mode: chromeRecordMode,
       included_categories: [...chromeCategories.values()],
-      memory_dump_config: {},
-    };
-    if (chromeCategories.has('disabled-by-default-memory-infra')) {
-      configStruct.memory_dump_config = {
-        allowed_dump_modes: ['background', 'light', 'detailed'],
-        triggers: [{
-          min_time_between_dumps_ms: 10000,
-          mode: 'detailed',
-          type: 'periodic_interval',
-        }],
-      };
-    }
-    const traceConfigJson = JSON.stringify(configStruct);
+    });
 
     const traceDs = new TraceConfig.DataSource();
     traceDs.config = new DataSourceConfig();
@@ -438,8 +395,7 @@
 
   // Keep these last. The stages above can enrich them.
 
-  if (sysStatsCfg !== undefined &&
-      (!isChromeTarget(target) || isCrOSTarget(target))) {
+  if (sysStatsCfg !== undefined) {
     const ds = new TraceConfig.DataSource();
     ds.config = new DataSourceConfig();
     ds.config.name = 'linux.sys_stats';
@@ -447,8 +403,7 @@
     protoCfg.dataSources.push(ds);
   }
 
-  if (heapprofd !== undefined &&
-      (!isChromeTarget(target) || isCrOSTarget(target))) {
+  if (heapprofd !== undefined) {
     const ds = new TraceConfig.DataSource();
     ds.config = new DataSourceConfig();
     ds.config.targetBuffer = 0;
@@ -457,8 +412,7 @@
     protoCfg.dataSources.push(ds);
   }
 
-  if (javaHprof !== undefined &&
-      (!isChromeTarget(target) || isCrOSTarget(target))) {
+  if (javaHprof !== undefined) {
     const ds = new TraceConfig.DataSource();
     ds.config = new DataSourceConfig();
     ds.config.targetBuffer = 0;
@@ -514,9 +468,7 @@
     ds.config.ftraceConfig.ftraceEvents = ftraceEventsArray;
     ds.config.ftraceConfig.atraceCategories = Array.from(atraceCats);
     ds.config.ftraceConfig.atraceApps = Array.from(atraceApps);
-    if (!isChromeTarget(target) || isCrOSTarget(target)) {
-      protoCfg.dataSources.push(ds);
-    }
+    protoCfg.dataSources.push(ds);
   }
 
   return protoCfg;
@@ -590,7 +542,6 @@
   private traceBuffer: Uint8Array[] = [];
   private bufferUpdateInterval: ReturnType<typeof setTimeout>|undefined;
   private adb = new AdbOverWebUsb();
-  private recordedTraceSuffix = TRACE_SUFFIX;
 
   // 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
@@ -606,14 +557,6 @@
   }
 
   run() {
-    // TODO(eseckler): Use ConsumerPort's QueryServiceState instead
-    // of posting a custom extension message to retrieve the category list.
-    if (this.app.state.updateChromeCategories === true) {
-      if (this.app.state.extensionInstalled) {
-        this.extensionPort.postMessage({method: 'GetCategories'});
-      }
-      globals.dispatch(Actions.setUpdateChromeCategories({update: false}));
-    }
     if (this.app.state.recordConfig === this.config &&
         this.app.state.recordingInProgress === this.recordingInProgress) {
       return;
@@ -623,7 +566,7 @@
     const configProto =
         genConfigProto(this.config, this.app.state.recordingTarget);
     const configProtoText = toPbtxt(configProto);
-    const configProtoBase64 = base64Encode(configProto);
+    const configProtoBase64 = uint8ArrayToBase64(configProto);
     const commandline = `
       echo '${configProtoBase64}' |
       base64 --decode |
@@ -691,10 +634,6 @@
       if (percentage) {
         globals.publish('BufferUsage', {percentage});
       }
-    } else if (isFreeBuffersResponse(data)) {
-      // No action required.
-    } else if (isDisableTracingResponse(data)) {
-      // No action required.
     } else {
       console.error('Unrecognized consumer port response:', data);
     }
@@ -710,11 +649,8 @@
       return;
     }
     const trace = this.generateTrace();
-    globals.dispatch(Actions.openTraceFromBuffer({
-      title: 'Recorded trace',
-      buffer: trace.buffer,
-      fileName: `recorded_trace${this.recordedTraceSuffix}`,
-    }));
+    globals.dispatch(Actions.openTraceFromBuffer(
+        {title: 'Recorded trace', buffer: trace.buffer}));
     this.traceBuffer = [];
   }
 
@@ -815,12 +751,8 @@
       _callback: RPCImplCallback) {
     try {
       const state = this.app.state;
-      // TODO(hjd): This is a bit weird. We implicity send each RPC message to
-      // whichever target is currently selected (creating that target if needed)
-      // it would be nicer if the setup/teardown was more explicit.
-      const target = await this.getTargetController(state.recordingTarget);
-      this.recordedTraceSuffix = target.getRecordedTraceSuffix();
-      target.handleCommand(method.name, requestData);
+      (await this.getTargetController(state.recordingTarget))
+          .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
index 2dd2c91..8c336e0 100644
--- a/ui/src/controller/record_controller_interfaces.ts
+++ b/ui/src/controller/record_controller_interfaces.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TRACE_SUFFIX} from '../common/constants';
 import {ConsumerPortResponse} from './consumer_port_types';
 
 export type ConsumerPortCallback = (_: ConsumerPortResponse) => void;
@@ -42,18 +41,10 @@
   sendStatus(status: string) {
     this.consumerPortListener.onStatus(status);
   }
-
-  // Allows the recording controller to customise the suffix added to recorded
-  // traces when they are downloaded. In the general case this will be
-  // .perfetto-trace however if the trace is recorded compressed if could be
-  // .perfetto-trace.gz etc.
-  getRecordedTraceSuffix(): string {
-    return TRACE_SUFFIX;
-  }
 }
 
 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 6d6e780..07f1487 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -126,33 +126,7 @@
 
   const expectedTraceConfig = '{"record_mode":"record-until-full",' +
       '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"],' +
-      '"memory_dump_config":{}}';
-  expect(traceConfigM).toEqual(expectedTraceConfig);
-  expect(traceConfig).toEqual(expectedTraceConfig);
-});
-
-test('ChromeMemoryConfig', () => {
-  const config = createEmptyRecordConfig();
-  config.chromeCategoriesSelected = ['disabled-by-default-memory-infra'];
-  const result =
-      TraceConfig.decode(genConfigProto(config, {os: 'C', name: 'Chrome'}));
-  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":["disabled-by-default-memory-infra"],' +
-      '"memory_dump_config":{"triggers":' +
-      '[{"mode":"detailed","periodic_interval_ms":10000}]}}';
+      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
   expect(traceConfigM).toEqual(expectedTraceConfig);
   expect(traceConfig).toEqual(expectedTraceConfig);
 });
@@ -178,8 +152,7 @@
 
   const expectedTraceConfig = '{"record_mode":"record-continuously",' +
       '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"],' +
-      '"memory_dump_config":{}}';
+      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
   expect(traceConfigM).toEqual(expectedTraceConfig);
   expect(traceConfig).toEqual(expectedTraceConfig);
 });
@@ -206,8 +179,7 @@
 
   const expectedTraceConfig = '{"record_mode":"record-continuously",' +
       '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"],' +
-      '"memory_dump_config":{}}';
+      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
   expect(traceConfigM).toEqual(expectedTraceConfig);
   expect(traceConfig).toEqual(expectedTraceConfig);
 });
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 06f2d7a..46cf95c 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -12,28 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TRACE_MARGIN_TIME_S} from '../common/constants';
 import {Engine} from '../common/engine';
-import {slowlyCountRows} from '../common/query_iterator';
 import {CurrentSearchResults, SearchSummary} from '../common/search_data';
 import {TimeSpan} from '../common/time';
 
 import {Controller} from './controller';
 import {App} from './globals';
 
-export function escapeQuery(s: string): string {
-  // See https://www.sqlite.org/lang_expr.html#:~:text=A%20string%20constant
-  s = s.replace(/\'/g, '\'\'');
-  s = s.replace(/_/g, '^_');
-  s = s.replace(/%/g, '^%');
-  return `'%${s}%' escape '^'`;
-}
-
 export interface SearchControllerArgs {
   engine: Engine;
   app: App;
 }
 
+
 export class SearchController extends Controller<'main'> {
   private engine: Engine;
   private app: App;
@@ -80,14 +71,14 @@
     }
     const newSpan = new TimeSpan(visibleState.startSec, visibleState.endSec);
     const newSearch = omniboxState.omnibox;
-    let newResolution = visibleState.resolution;
+    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, -TRACE_MARGIN_TIME_S),
+        Math.max(newSpan.start - newSpan.duration, 0),
         newSpan.end + newSpan.duration);
     this.previousResolution = newResolution;
     this.previousSearch = newSearch;
@@ -108,20 +99,8 @@
       return;
     }
 
-    let startNs = Math.round(newSpan.start * 1e9);
-    let endNs = Math.round(newSpan.end * 1e9);
-
-    // TODO(hjd): We shouldn't need to be so defensive here:
-    if (!Number.isFinite(startNs)) {
-      startNs = 0;
-    }
-    if (!Number.isFinite(endNs)) {
-      endNs = 1;
-    }
-    if (!Number.isFinite(newResolution)) {
-      newResolution = 1;
-    }
-
+    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 => {
@@ -147,8 +126,6 @@
       resolution: number): Promise<SearchSummary> {
     const quantumNs = Math.round(resolution * 10 * 1e9);
 
-    const searchLiteral = escapeQuery(search);
-
     startNs = Math.floor(startNs / quantumNs) * quantumNs;
 
     await this.query(`update search_summary_window set
@@ -158,8 +135,8 @@
       where rowid = 0;`);
 
     const rawUtidResult = await this.query(`select utid from thread join process
-      using(upid) where thread.name like ${searchLiteral}
-      or process.name like ${searchLiteral}`);
+      using(upid) where thread.name like "%${search}%" or process.name like "%${
+        search}%"`);
 
     const utids = [...rawUtidResult.columns[0].longValues!];
 
@@ -180,12 +157,12 @@
               select
               quantum_ts
               from search_summary_slice_span
-              where name like ${searchLiteral}
+              where name like '%${search}%'
           )
           group by quantum_ts
           order by quantum_ts;`);
 
-    const numRows = slowlyCountRows(rawResult);
+    const numRows = +rawResult.numRecords;
     const summary = {
       tsStarts: new Float64Array(numRows),
       tsEnds: new Float64Array(numRows),
@@ -202,7 +179,6 @@
   }
 
   private async specificSearch(search: string) {
-    const searchLiteral = escapeQuery(search);
     // 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();
@@ -212,24 +188,17 @@
         cpuToTrackId.set((track.config as {cpu: number}).cpu, track.id);
         continue;
       }
-      if (track.kind === 'ChromeSliceTrack') {
-        const config = (track.config as {trackId: number});
-        engineTrackIdToTrackId.set(config.trackId, track.id);
-        continue;
-      }
-      if (track.kind === 'AsyncSliceTrack') {
-        const config = (track.config as {trackIds: number[]});
-        for (const trackId of config.trackIds) {
-          engineTrackIdToTrackId.set(trackId, track.id);
-        }
+      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 ${searchLiteral} or
-      process.name like ${searchLiteral}`);
+    using(upid) where thread.name like "%${search}%" or process.name like "%${
+        search}%"`);
     const utids = [...rawUtidResult.columns[0].longValues!];
 
     const rawResult = await this.query(`
@@ -248,25 +217,16 @@
       track_id as source_id,
       0 as utid
       from slice
-      where slice.name like ${searchLiteral}
-    union
-    select
-      slice_id,
-      ts,
-      'track' as source,
-      track_id as source_id,
-      0 as utid
-      from slice
-      join args using(arg_set_id)
-      where string_value like ${searchLiteral}
+      inner join track on slice.track_id = track.id
+      and slice.name like '%${search}%'
     order by ts`);
 
-    const numRows = slowlyCountRows(rawResult);
+    const numRows = +rawResult.numRecords;
 
     const searchResults: CurrentSearchResults = {
-      sliceIds: [],
-      tsStarts: [],
-      utids: [],
+      sliceIds: new Float64Array(numRows),
+      tsStarts: new Float64Array(numRows),
+      utids: new Float64Array(numRows),
       trackIds: [],
       sources: [],
       totalResults: +numRows,
@@ -290,9 +250,9 @@
 
       searchResults.trackIds.push(trackId);
       searchResults.sources.push(source);
-      searchResults.sliceIds.push(+columns[0].longValues![row]);
-      searchResults.tsStarts.push(+columns[1].longValues![row]);
-      searchResults.utids.push(+columns[4].longValues![row]);
+      searchResults.sliceIds[row] = +columns[0].longValues![row];
+      searchResults.tsStarts[row] = +columns[1].longValues![row];
+      searchResults.utids[row] = +columns[4].longValues![row];
     }
     return searchResults;
   }
diff --git a/ui/src/controller/search_controller_unittest.ts b/ui/src/controller/search_controller_unittest.ts
deleted file mode 100644
index 9dec627..0000000
--- a/ui/src/controller/search_controller_unittest.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {escapeQuery} from './search_controller';
-
-test('escapeQuery', () => {
-  expect(escapeQuery(``)).toEqual(`'%%' escape '^'`);
-  expect(escapeQuery(`hello`)).toEqual(`'%hello%' escape '^'`);
-  expect(escapeQuery('foo\'bar')).toEqual(`'%foo''bar%' escape '^'`);
-  expect(escapeQuery('%_%')).toEqual(`'%^%^_^%%' escape '^'`);
-});
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 0366df1..82ab2ce 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -12,26 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Arg, Args} from '../common/arg_types';
 import {Engine} from '../common/engine';
-import {
-  NUM,
-  singleRow,
-  singleRowUntyped,
-  slowlyCountRows,
-  STR
-} from '../common/query_iterator';
-import {ChromeSliceSelection} from '../common/state';
-import {translateState} from '../common/thread_state';
 import {fromNs, toNs} from '../common/time';
-import {
-  CounterDetails,
-  SliceDetails,
-  ThreadStateDetails
-} from '../frontend/globals';
+import {Arg, Args, CounterDetails, SliceDetails} from '../frontend/globals';
 import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
 
-import {parseArgs} from './args_parser';
 import {Controller} from './controller';
 import {globals} from './globals';
 
@@ -50,10 +35,21 @@
 
   run() {
     const selection = globals.state.currentSelection;
-    if (!selection || selection.kind === 'AREA') return;
+    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 id FROM sched WHERE utid = ${selection.utid}
+                        and ts = ${toNs(selection.ts)}`;
+      this.args.engine.query(sqlQuery).then(result => {
+        if (result.columns[0].longValues!.length === 0) return;
+        this.sliceDetails(+result.columns[0].longValues![0]);
+      });
+      this.lastSelectedKind = selection.kind;
+      return;
+    }
 
-    const selectWithId =
-        ['SLICE', 'COUNTER', 'CHROME_SLICE', 'HEAP_PROFILE', 'THREAD_STATE'];
+    const selectWithId = ['SLICE', 'COUNTER', 'CHROME_SLICE', 'HEAP_PROFILE'];
     if (!selectWithId.includes(selection.kind) ||
         (selectWithId.includes(selection.kind) &&
          selection.id === this.lastSelectedId &&
@@ -80,105 +76,51 @@
           });
     } else if (selection.kind === 'SLICE') {
       this.sliceDetails(selectedId as number);
-    } else if (selection.kind === 'THREAD_STATE') {
-      this.threadStateDetails(selection.id);
     } else if (selection.kind === 'CHROME_SLICE') {
-      this.chromeSliceDetails(selection);
-    }
-  }
-
-  async chromeSliceDetails(selection: ChromeSliceSelection) {
-    const selectedId = selection.id;
-    const table = selection.table;
-
-    let leafTable: string;
-    let promisedDescription: Promise<Map<string, string>>;
-    let promisedArgs: Promise<Args>;
-    // TODO(b/155483804): This is a hack to ensure annotation slices are
-    // selectable for now. We should tidy this up when improving this class.
-    if (table === 'annotation') {
-      leafTable = 'annotation_slice';
-      promisedDescription = Promise.resolve(new Map());
-      promisedArgs = Promise.resolve(new Map());
-    } else {
-      const typeResult = singleRow(
-          {
-            leafTable: STR,
-            argSetId: NUM,
-          },
-          await this.args.engine.query(`
-        SELECT
-          type as leafTable,
-          arg_set_id as argSetId
-        FROM slice WHERE id = ${selectedId}`));
-
-      if (typeResult === undefined) {
-        return;
+      const table = selection.table;
+      let sqlQuery = `
+        SELECT ts, dur, name, cat, arg_set_id
+        FROM slice
+        WHERE id = ${selectedId}
+      `;
+      // TODO(b/155483804): This is a hack to ensure annotation slices are
+      // selectable for now. We should tidy this up when improving this class.
+      if (table === 'annotation') {
+        sqlQuery = `
+        select ts, dur, name, cat, -1
+        from annotation_slice
+        where id = ${selectedId}`;
       }
-
-      leafTable = typeResult.leafTable;
-      const argSetId = typeResult.argSetId;
-      promisedDescription = this.describeSlice(selectedId);
-      promisedArgs = this.getArgs(argSetId);
-    }
-
-    const promisedDetails = this.args.engine.query(`
-      SELECT * FROM ${leafTable} WHERE id = ${selectedId};
-    `);
-
-    const [details, args, description] =
-        await Promise.all([promisedDetails, promisedArgs, promisedDescription]);
-
-    const row = singleRowUntyped(details);
-    if (row === undefined) {
-      return;
-    }
-
-    // A few columns are hard coded as part of the SliceDetails interface.
-    // Long term these should be handled generically as args but for now
-    // handle them specially:
-    let ts = undefined;
-    let dur = undefined;
-    let name = undefined;
-    let category = undefined;
-
-    for (const [k, v] of Object.entries(row)) {
-      switch (k) {
-        case 'id':
-          break;
-        case 'ts':
-          ts = fromNs(Number(v)) - globals.state.traceTime.startSec;
-          break;
-        case 'name':
-          name = `${v}`;
-          break;
-        case 'dur':
-          dur = fromNs(Number(v));
-          break;
-        case 'category':
-        case 'cat':
-          category = `${v}`;
-          break;
-        default:
-          args.set(k, `${v}`);
-      }
-    }
-
-    const argsTree = parseArgs(args);
-    const selected: SliceDetails = {
-      id: selectedId,
-      ts,
-      dur,
-      name,
-      category,
-      args,
-      argsTree,
-      description,
-    };
-
-    // Check selection is still the same on completion of query.
-    if (selection === globals.state.currentSelection) {
-      globals.publish('SliceDetails', selected);
+      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) {
+          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];
+          const argId = result.columns[4].longValues![0] as number;
+          const argsAsync = this.getArgs(argId);
+          // Don't fetch descriptions for annotation slices.
+          const describeId = table === 'annotation' ? -1 : selectedId as number;
+          const descriptionAsync = this.describeSlice(describeId);
+          Promise.all([argsAsync, descriptionAsync])
+              .then(([args, description]) => {
+                const selected: SliceDetails = {
+                  ts: timeFromStart,
+                  dur,
+                  category,
+                  name,
+                  id: selectedId as number,
+                  args,
+                  description,
+                };
+                globals.publish('SliceDetails', selected);
+              });
+        }
+      });
     }
   }
 
@@ -191,7 +133,7 @@
       where slice_id = ${id}
     `;
     const result = await this.args.engine.query(query);
-    for (let i = 0; i < slowlyCountRows(result); i++) {
+    for (let i = 0; i < result.numRecords; i++) {
       const description = result.columns[0].stringValues![i];
       const docLink = result.columns[1].stringValues![i];
       map.set('Description', description);
@@ -204,13 +146,13 @@
     const args = new Map<string, Arg>();
     const query = `
       select
-        key AS name,
+        flat_key AS name,
         CAST(COALESCE(int_value, string_value, real_value) AS text) AS value
       FROM args
       WHERE arg_set_id = ${argId}
     `;
     const result = await this.args.engine.query(query);
-    for (let i = 0; i < slowlyCountRows(result); i++) {
+    for (let i = 0; i < result.numRecords; i++) {
       const name = result.columns[0].stringValues![i];
       const value = result.columns[1].stringValues![i];
       if (name === 'destination slice id' && !isNaN(Number(value))) {
@@ -230,7 +172,7 @@
     where slice_id = ${sliceId}`;
     const destResult = await this.args.engine.query(trackIdQuery);
     const trackIdTp = destResult.columns[0].longValues![0];
-    // TODO(hjd): If we had a consistent mapping from TP track_id
+    // TODO(taylori): If we had a consistent mapping from TP track_id
     // UI track id for slice tracks this would be unnecessary.
     let trackId = '';
     for (const track of Object.values(globals.state.tracks)) {
@@ -243,77 +185,22 @@
     return trackId;
   }
 
-  async threadStateDetails(id: number) {
-    const query = `
-      SELECT
-        ts,
-        thread_state.dur,
-        state,
-        io_wait,
-        thread_state.utid,
-        thread_state.cpu,
-        sched.id,
-        thread_state.blocked_function
-      from thread_state
-      left join sched using(ts) where thread_state.id = ${id}
-    `;
-    this.args.engine.query(query).then(result => {
-      const selection = globals.state.currentSelection;
-      const cols = result.columns;
-      if (slowlyCountRows(result) === 1 && selection) {
-        const ts = cols[0].longValues![0];
-        const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
-        const dur = fromNs(cols[1].longValues![0]);
-        const stateStr = cols[2].stringValues![0];
-        const ioWait =
-            cols[3].isNulls![0] ? undefined : !!cols[3].longValues![0];
-        const state = translateState(stateStr, ioWait);
-        const utid = cols[4].longValues![0];
-        const cpu = cols[5].isNulls![0] ? undefined : cols[5].longValues![0];
-        const sliceId =
-            cols[6].isNulls![0] ? undefined : cols[6].longValues![0];
-        const blockedFunction =
-            cols[7].isNulls![0] ? undefined : cols[7].stringValues![0];
-        const selected: ThreadStateDetails = {
-          ts: timeFromStart,
-          dur,
-          state,
-          utid,
-          cpu,
-          sliceId,
-          blockedFunction
-        };
-        globals.publish('ThreadStateDetails', selected);
-      }
-    });
-  }
-
   async sliceDetails(id: number) {
-    const sqlQuery = `SELECT ts, dur, priority, end_state, utid, cpu,
-    thread_state.id FROM sched join thread_state using(ts, utid, dur, cpu)
-    WHERE sched.id = ${id}`;
+    const sqlQuery = `SELECT ts, dur, priority, end_state, utid, cpu FROM sched
+    WHERE 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 (slowlyCountRows(result) === 1 && selection) {
-        const ts = result.columns[0].longValues![0];
+      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]);
-        const priority = result.columns[2].longValues![0];
+        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];
-        const cpu = result.columns[5].longValues![0];
-        const threadStateId = result.columns[6].longValues![0];
-        const selected: SliceDetails = {
-          ts: timeFromStart,
-          dur,
-          priority,
-          endState,
-          cpu,
-          id,
-          utid,
-          threadStateId
-        };
+        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);
@@ -350,8 +237,8 @@
         `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 (slowlyCountRows(waking) === 0) {
-      if (slowlyCountRows(wakeup) === 0) return undefined;
+    if (waking.numRecords === 0) {
+      if (wakeup.numRecords === 0) return undefined;
       // Only use sched_wakeup if waking is not in the trace.
       event = 'sched_wakeup';
     }
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 65558b2..d095482 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -14,16 +14,21 @@
 
 import '../tracks/all_controller';
 
+import * as uuidv4 from 'uuid/v4';
+
 import {assertExists, assertTrue} from '../base/logging';
 import {
   Actions,
+  AddTrackArgs,
   DeferredAction,
 } from '../common/actions';
-import {TRACE_MARGIN_TIME_S} from '../common/constants';
-import {Engine, QueryError} from '../common/engine';
+import {Engine} from '../common/engine';
 import {HttpRpcEngine} from '../common/http_rpc_engine';
-import {slowlyCountRows} from '../common/query_iterator';
-import {EngineMode} from '../common/state';
+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 {TimeSpan} from '../common/time';
 import {
@@ -32,20 +37,23 @@
   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_PROFILE_TRACK_KIND} from '../tracks/cpu_profile/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 {
-  CounterAggregationController
-} from './aggregation/counter_aggregation_controller';
+  PROCESS_SCHEDULING_TRACK_KIND
+} from '../tracks/process_scheduling/common';
+import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary/common';
+import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state/common';
+
 import {
   CpuAggregationController
 } from './aggregation/cpu_aggregation_controller';
 import {
-  CpuByProcessAggregationController
-} from './aggregation/cpu_by_process_aggregation_controller';
-import {
-  SliceAggregationController
-} from './aggregation/slice_aggregation_controller';
-import {
   ThreadAggregationController
 } from './aggregation/thread_aggregation_controller';
 import {Child, Children, Controller} from './controller';
@@ -53,10 +61,6 @@
   CpuProfileController,
   CpuProfileControllerArgs
 } from './cpu_profile_controller';
-import {
-  FlowEventsController,
-  FlowEventsControllerArgs
-} from './flow_events_controller';
 import {globals} from './globals';
 import {
   HeapProfileController,
@@ -64,7 +68,6 @@
 } from './heap_profile_controller';
 import {LoadingManager} from './loading_manager';
 import {LogsController} from './logs_controller';
-import {MetricsController} from './metrics_controller';
 import {QueryController, QueryControllerArgs} from './query_controller';
 import {SearchController} from './search_controller';
 import {
@@ -72,19 +75,20 @@
   SelectionControllerArgs
 } from './selection_controller';
 import {
-  TraceErrorController,
-} from './trace_error_controller';
-import {
   TraceBufferStream,
   TraceFileStream,
   TraceHttpStream,
   TraceStream
 } from './trace_stream';
 import {TrackControllerArgs, trackControllerRegistry} from './track_controller';
-import {decideTracks} from './track_decider';
 
 type States = 'init'|'loading_trace'|'ready';
 
+interface ThreadSliceTrack {
+  maxDepth: number;
+  trackId: number;
+}
+
 // TraceController handles handshakes with the frontend for everything that
 // concerns a single trace. It owns the WASM trace processor engine, handles
 // tracks data and SQL queries. There is one TraceController instance for each
@@ -155,11 +159,7 @@
 
         const selectionArgs: SelectionControllerArgs = {engine};
         childControllers.push(
-            Child('selection', SelectionController, selectionArgs));
-
-        const flowEventsArgs: FlowEventsControllerArgs = {engine};
-        childControllers.push(
-            Child('flowEvents', FlowEventsController, flowEventsArgs));
+          Child('selection', SelectionController, selectionArgs));
 
         const cpuProfileArgs: CpuProfileControllerArgs = {engine};
         childControllers.push(
@@ -176,18 +176,6 @@
             'thread_aggregation',
             ThreadAggregationController,
             {engine, kind: 'thread_state_aggregation'}));
-        childControllers.push(Child(
-            'cpu_process_aggregation',
-            CpuByProcessAggregationController,
-            {engine, kind: 'cpu_by_process_aggregation'}));
-        childControllers.push(Child(
-            'slice_aggregation',
-            SliceAggregationController,
-            {engine, kind: 'slice_aggregation'}));
-        childControllers.push(Child(
-            'counter_aggregation',
-            CounterAggregationController,
-            {engine, kind: 'counter_aggregation'}));
         childControllers.push(Child('search', SearchController, {
           engine,
           app: globals,
@@ -197,9 +185,7 @@
           engine,
           app: globals,
         }));
-        childControllers.push(
-            Child('traceError', TraceErrorController, {engine}));
-        childControllers.push(Child('metrics', MetricsController, {engine}));
+
         return childControllers;
 
       default:
@@ -285,39 +271,20 @@
     }
 
     const traceTime = await this.engine.getTraceTimeBounds();
-    let startSec = traceTime.start;
-    let endSec = traceTime.end;
-    startSec -= TRACE_MARGIN_TIME_S;
-    endSec += TRACE_MARGIN_TIME_S;
     const traceTimeState = {
-      startSec,
-      endSec,
+      startSec: traceTime.start,
+      endSec: traceTime.end,
     };
     const actions: DeferredAction[] = [
       Actions.setTraceTime(traceTimeState),
       Actions.navigate({route: '/viewer'}),
     ];
 
-    let visibleStartSec = startSec;
-    let visibleEndSec = endSec;
-    const mdTime = await this.engine.getTracingMetadataTimeBounds();
-    // make sure the bounds hold
-    if (Math.max(visibleStartSec, mdTime.start - TRACE_MARGIN_TIME_S) <
-        Math.min(visibleEndSec, mdTime.end + TRACE_MARGIN_TIME_S)) {
-      visibleStartSec =
-          Math.max(visibleStartSec, mdTime.start - TRACE_MARGIN_TIME_S);
-      visibleEndSec = Math.min(visibleEndSec, mdTime.end + TRACE_MARGIN_TIME_S);
-    }
-
     // We don't know the resolution at this point. However this will be
     // replaced in 50ms so a guess is fine.
-    const resolution = (visibleStartSec - visibleEndSec) / 1000;
-    actions.push(Actions.setVisibleTraceTime({
-      startSec: visibleStartSec,
-      endSec: visibleEndSec,
-      lastUpdate: Date.now() / 1000,
-      resolution
-    }));
+    const resolution = (traceTime.end - traceTime.start) / 1000;
+    actions.push(Actions.setVisibleTraceTime(
+        {...traceTimeState, lastUpdate: Date.now() / 1000, resolution}));
 
     globals.dispatchMultiple(actions);
 
@@ -334,32 +301,571 @@
 
     await this.listThreads();
     await this.loadTimelineOverview(traceTime);
-    globals.dispatch(Actions.sortThreadTracks({}));
-    await this.selectFirstHeapProfile();
-
     return engineMode;
   }
 
-  private async selectFirstHeapProfile() {
-    const query = `select * from
-    (select distinct(ts) as ts, 'native' as type,
-        upid from heap_profile_allocation
-        union
-        select distinct(graph_sample_ts) as ts, 'graph' as type, upid from
-        heap_graph_object) order by ts limit 1`;
-    const profile = await assertExists(this.engine).query(query);
-    if (profile.numRecords !== 1) return;
-    const ts = profile.columns[0].longValues![0];
-    const type = profile.columns[1].stringValues![0];
-    const upid = profile.columns[2].longValues![0];
-    globals.dispatch(Actions.selectHeapProfile({id: 0, upid, ts, type}));
-  }
-
   private async listTracks() {
     this.updateStatus('Loading tracks');
+
     const engine = assertExists<Engine>(this.engine);
-    const actions = await decideTracks(this.engineId, engine);
-    globals.dispatchMultiple(actions);
+    const numGpus = await engine.getNumberOfGpus();
+    const tracksToAdd: AddTrackArgs[] = [];
+
+    // TODO(hjd): Renable Vsync tracks when fixed.
+    //// TODO(hjd): Move this code out of TraceController.
+    // for (const counterName of ['VSYNC-sf', 'VSYNC-app']) {
+    //  const hasVsync =
+    //      !!(await engine.query(
+    //             `select ts from counters where name like "${
+    //                                                         counterName
+    //                                                       }" limit 1`))
+    //            .numRecords;
+    //  if (!hasVsync) continue;
+    //  addToTrackActions.push(Actions.addTrack({
+    //    engineId: this.engineId,
+    //    kind: 'VsyncTrack',
+    //    name: `${counterName}`,
+    //    config: {
+    //      counterName,
+    //    }
+    //  }));
+    //}
+    const maxCpuFreq = await engine.query(`
+      select max(value)
+      from counter c
+      inner join cpu_counter_track t on c.track_id = t.id
+      where name = 'cpufreq';
+    `);
+
+    const cpus = await engine.getCpus();
+
+    for (const cpu of cpus) {
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: CPU_SLICE_TRACK_KIND,
+        name: `Cpu ${cpu}`,
+        trackGroup: SCROLLING_TRACK_GROUP,
+        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
+      // events even if there are no cpu freq events.
+      const cpuFreqIdle = await engine.query(`
+        select
+          id as cpu_freq_id,
+          (
+            select id
+            from cpu_counter_track
+            where name = 'cpuidle'
+            and cpu = ${cpu}
+            limit 1
+          ) as cpu_idle_id
+        from cpu_counter_track
+        where name = 'cpufreq' and cpu = ${cpu}
+        limit 1;
+      `);
+      if (cpuFreqIdle.numRecords > 0) {
+        const freqTrackId = +cpuFreqIdle.columns[0].longValues![0];
+
+        const idleTrackExists: boolean = !cpuFreqIdle.columns[1].isNulls![0];
+        const idleTrackId = idleTrackExists ?
+            +cpuFreqIdle.columns[1].longValues![0] :
+            undefined;
+
+        tracksToAdd.push({
+          engineId: this.engineId,
+          kind: CPU_FREQ_TRACK_KIND,
+          name: `Cpu ${cpu} Frequency`,
+          trackGroup: SCROLLING_TRACK_GROUP,
+          config: {
+            cpu,
+            maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
+            freqTrackId,
+            idleTrackId,
+          }
+        });
+      }
+    }
+
+    const rawGlobalAsyncTracks = await engine.query(`
+      SELECT
+        t.name,
+        t.track_ids,
+        MAX(experimental_slice_layout.layout_depth) as max_depth
+      FROM (
+        SELECT name, GROUP_CONCAT(track.id) AS track_ids
+        FROM track
+        WHERE track.type = "track"
+        GROUP BY name
+      ) AS t CROSS JOIN experimental_slice_layout
+      WHERE t.track_ids = experimental_slice_layout.filter_track_ids
+      GROUP BY t.track_ids;
+    `);
+    for (let i = 0; i < rawGlobalAsyncTracks.numRecords; i++) {
+      const name = rawGlobalAsyncTracks.columns[0].stringValues![i];
+      const rawTrackIds = rawGlobalAsyncTracks.columns[1].stringValues![i];
+      const trackIds = rawTrackIds.split(',').map(v => Number(v));
+      const maxDepth = +rawGlobalAsyncTracks.columns[2].longValues![i];
+      const track = {
+        engineId: this.engineId,
+        kind: 'AsyncSliceTrack',
+        trackGroup: SCROLLING_TRACK_GROUP,
+        name,
+        config: {
+          maxDepth,
+          trackIds,
+        },
+      };
+      tracksToAdd.push(track);
+    }
+
+    const upidToProcessTracks = new Map();
+    const rawProcessTracks = await engine.query(`
+      SELECT
+        pt.upid,
+        pt.name,
+        pt.track_ids,
+        MAX(experimental_slice_layout.layout_depth) as max_depth
+      FROM (
+        SELECT upid, name, GROUP_CONCAT(process_track.id) AS track_ids
+        FROM process_track GROUP BY upid, name
+      ) AS pt CROSS JOIN experimental_slice_layout
+      WHERE pt.track_ids = experimental_slice_layout.filter_track_ids
+      GROUP BY pt.track_ids;
+    `);
+    for (let i = 0; i < rawProcessTracks.numRecords; i++) {
+      const upid = +rawProcessTracks.columns[0].longValues![i];
+      const name = rawProcessTracks.columns[1].stringValues![i];
+      const rawTrackIds = rawProcessTracks.columns[2].stringValues![i];
+      const trackIds = rawTrackIds.split(',').map(v => Number(v));
+      const maxDepth = +rawProcessTracks.columns[3].longValues![i];
+      const track = {
+        engineId: this.engineId,
+        kind: 'AsyncSliceTrack',
+        name,
+        config: {
+          maxDepth,
+          trackIds,
+        },
+      };
+      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
+      union
+      select distinct(upid) from heap_graph_object`);
+
+    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 counter c
+      inner join gpu_counter_track t on c.track_id = t.id
+      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 id
+        from gpu_counter_track
+        where name = 'gpufreq' and gpu_id = ${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,
+            trackId: +freqExists.columns[0].longValues![0],
+            maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
+          }
+        });
+      }
+    }
+
+    // Add global or GPU counter tracks that are not bound to any pid/tid.
+    const globalCounters = await engine.query(`
+      select name, id
+      from counter_track
+      where type = 'counter_track'
+      union
+      select name, id
+      from gpu_counter_track
+      where name != 'gpufreq'
+    `);
+    for (let i = 0; i < globalCounters.numRecords; i++) {
+      const name = globalCounters.columns[0].stringValues![i];
+      const trackId = +globalCounters.columns[1].longValues![i];
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: 'CounterTrack',
+        name,
+        trackGroup: SCROLLING_TRACK_GROUP,
+        config: {
+          name,
+          trackId,
+        }
+      });
+    }
+
+    interface CounterTrack {
+      name: string;
+      trackId: number;
+      startTs?: number;
+      endTs?: number;
+    }
+
+    const counterUtids = new Map<number, CounterTrack[]>();
+    const threadCounters = await engine.query(`
+      select thread_counter_track.name, utid, thread_counter_track.id,
+      start_ts, end_ts from thread_counter_track join thread using(utid)
+    `);
+    for (let i = 0; i < threadCounters.numRecords; i++) {
+      const name = threadCounters.columns[0].stringValues![i];
+      const utid = +threadCounters.columns[1].longValues![i];
+      const trackId = +threadCounters.columns[2].longValues![i];
+      let startTs = undefined;
+      let endTs = undefined;
+      if (!threadCounters.columns[3].isNulls![i]) {
+        startTs = +threadCounters.columns[3].longValues![i] / 1e9;
+      }
+      if (!threadCounters.columns[4].isNulls![i]) {
+        endTs = +threadCounters.columns[4].longValues![i] / 1e9;
+      }
+
+      const track: CounterTrack = {name, trackId, startTs, endTs};
+      const el = counterUtids.get(utid);
+      if (el === undefined) {
+        counterUtids.set(utid, [track]);
+      } else {
+        el.push(track);
+      }
+    }
+
+    const counterUpids = new Map<number, CounterTrack[]>();
+    const processCounters = await engine.query(`
+      select process_counter_track.name, upid, process_counter_track.id,
+      start_ts, end_ts from process_counter_track join process using(upid)
+    `);
+    for (let i = 0; i < processCounters.numRecords; i++) {
+      const name = processCounters.columns[0].stringValues![i];
+      const upid = +processCounters.columns[1].longValues![i];
+      const trackId = +processCounters.columns[2].longValues![i];
+      let startTs = undefined;
+      let endTs = undefined;
+      if (!processCounters.columns[3].isNulls![i]) {
+        startTs = +processCounters.columns[3].longValues![i] / 1e9;
+      }
+      if (!processCounters.columns[4].isNulls![i]) {
+        endTs = +processCounters.columns[4].longValues![i] / 1e9;
+      }
+
+      const track: CounterTrack = {name, trackId, startTs, endTs};
+      const el = counterUpids.get(upid);
+      if (el === undefined) {
+        counterUpids.set(upid, [track]);
+      } else {
+        el.push(track);
+      }
+    }
+
+    // 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 utidToThreadTrack = new Map<number, ThreadSliceTrack>();
+    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});
+    }
+
+    // Return all threads
+    // sorted by:
+    //  total cpu time *for the whole parent process*
+    //  upid
+    //  utid
+    const threadQuery = await engine.query(`
+        select
+          utid,
+          tid,
+          upid,
+          pid,
+          thread.name as threadName,
+          process.name as processName,
+          total_dur as totalDur,
+          ifnull(has_sched, false) as hasSched,
+          ifnull(has_cpu_samples, false) as hasCpuSamples
+        from
+          thread
+          left join (select utid, count(1), true as has_sched
+              from sched group by utid
+          ) using(utid)
+          left join (select utid, count(1), true as has_cpu_samples
+              from cpu_profile_stack_sample group by utid
+          ) using(utid)
+          left join process using(upid)
+          left join (select upid, sum(dur) as total_dur
+              from sched join thread using(utid)
+              group by upid
+            ) using(upid)
+          left join (select upid, sum(value) as total_cycles
+              from android_thread_time_in_state_annotations
+              group by upid
+            ) using(upid)
+        where utid != 0
+        group by utid, upid
+        order by total_dur desc, total_cycles desc, upid, utid`);
+
+    const upidToUuid = new Map<number, string>();
+    const utidToUuid = new Map<number, string>();
+    const addTrackGroupActions: DeferredAction[] = [];
+
+    for (const row of rawQueryToRows(threadQuery, {
+           utid: NUM,
+           upid: NUM_NULL,
+           tid: NUM_NULL,
+           pid: NUM_NULL,
+           threadName: STR_NULL,
+           processName: STR_NULL,
+           totalDur: NUM_NULL,
+           hasSched: NUM,
+           hasCpuSamples: NUM,
+         })) {
+      const utid = row.utid;
+      const tid = row.tid;
+      const upid = row.upid;
+      const pid = row.pid;
+      const threadName = row.threadName;
+      const processName = row.processName;
+      const hasSchedEvents = !!row.totalDur;
+      const threadHasSched = !!row.hasSched;
+      const threadHasCpuSamples = !!row.hasCpuSamples;
+
+      const threadTrack =
+          utid === null ? undefined : utidToThreadTrack.get(utid);
+      if (threadTrack === undefined &&
+          (upid === null || counterUpids.get(upid) === undefined) &&
+          counterUtids.get(utid) === undefined && !threadHasSched &&
+          (upid === null || upid !== null && !heapUpids.has(upid))) {
+        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();
+        if (upid === null) {
+          utidToUuid.set(utid, pUuid);
+        } else {
+          upidToUuid.set(upid, pUuid);
+        }
+
+        const pidForColor = pid || tid || upid || utid || 0;
+        const kind = hasSchedEvents ? PROCESS_SCHEDULING_TRACK_KIND :
+                                      PROCESS_SUMMARY_TRACK;
+
+        tracksToAdd.push({
+          id: summaryTrackId,
+          engineId: this.engineId,
+          kind,
+          name: `${upid === null ? tid : pid} summary`,
+          config: {pidForColor, upid, utid},
+        });
+
+        const name =
+            getTrackName({utid, processName, pid, threadName, tid, upid});
+        const addTrackGroup = Actions.addTrackGroup({
+          engineId: this.engineId,
+          summaryTrackId,
+          name,
+          id: pUuid,
+          collapsed: !(upid !== null && heapUpids.has(upid)),
+        });
+
+        // If the track group contains a heap profile, it should be before all
+        // other processes.
+        if (upid !== null && heapUpids.has(upid)) {
+          addTrackGroupActions.unshift(addTrackGroup);
+        } else {
+          addTrackGroupActions.push(addTrackGroup);
+        }
+
+        if (upid !== null) {
+          if (heapUpids.has(upid)) {
+            tracksToAdd.push({
+              engineId: this.engineId,
+              kind: HEAP_PROFILE_TRACK_KIND,
+              name: `Heap Profile`,
+              trackGroup: pUuid,
+              config: {upid}
+            });
+          }
+
+          const counterNames = counterUpids.get(upid);
+          if (counterNames !== undefined) {
+            counterNames.forEach(element => {
+              tracksToAdd.push({
+                engineId: this.engineId,
+                kind: 'CounterTrack',
+                name: element.name,
+                trackGroup: pUuid,
+                config: {
+                  name: element.name,
+                  trackId: element.trackId,
+                  startTs: element.startTs,
+                  endTs: element.endTs,
+                }
+              });
+            });
+          }
+
+          if (upidToProcessTracks.has(upid)) {
+            for (const track of upidToProcessTracks.get(upid)) {
+              tracksToAdd.push(Object.assign(track, {trackGroup: pUuid}));
+            }
+          }
+        }
+      }
+      const counterThreadNames = counterUtids.get(utid);
+      if (counterThreadNames !== undefined) {
+        counterThreadNames.forEach(element => {
+          tracksToAdd.push({
+            engineId: this.engineId,
+            kind: 'CounterTrack',
+            name: `${threadName} (${element.name})`,
+            trackGroup: pUuid,
+            config: {
+              name: element.name,
+              trackId: element.trackId,
+              startTs: element.startTs,
+              endTs: element.endTs,
+            }
+          });
+        });
+      }
+
+      if (threadHasCpuSamples) {
+        tracksToAdd.push({
+          engineId: this.engineId,
+          kind: CPU_PROFILE_TRACK_KIND,
+          name: `${threadName} (CPU Stack Samples)`,
+          trackGroup: pUuid,
+          config: {utid},
+        });
+      }
+
+      if (threadHasSched) {
+        tracksToAdd.push({
+          engineId: this.engineId,
+          kind: THREAD_STATE_TRACK_KIND,
+          name: getTrackName({utid, tid, threadName}),
+          trackGroup: pUuid,
+          config: {utid}
+        });
+      }
+
+      if (threadTrack !== undefined) {
+        tracksToAdd.push({
+          engineId: this.engineId,
+          kind: SLICE_TRACK_KIND,
+          name: getTrackName({utid, tid, threadName}),
+          trackGroup: pUuid,
+          config:
+              {maxDepth: threadTrack.maxDepth, trackId: threadTrack.trackId},
+        });
+      }
+    }
+
+    const logCount = await engine.query(`select count(1) from android_logs`);
+    if (logCount.columns[0].longValues![0] > 0) {
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: ANDROID_LOGS_TRACK_KIND,
+        name: 'Android logs',
+        trackGroup: SCROLLING_TRACK_GROUP,
+        config: {}
+      });
+    }
+
+    const annotationSliceRows = await engine.query(`
+      SELECT id, name, upid FROM annotation_slice_track`);
+    for (let i = 0; i < annotationSliceRows.numRecords; i++) {
+      const id = annotationSliceRows.columns[0].longValues![i];
+      const name = annotationSliceRows.columns[1].stringValues![i];
+      const upid = annotationSliceRows.columns[2].longValues![i] as number;
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: SLICE_TRACK_KIND,
+        name,
+        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP : upidToUuid.get(upid),
+        config: {
+          maxDepth: 0,
+          namespace: 'annotation',
+          trackId: id,
+        },
+      });
+    }
+
+    const annotationCounterRows = await engine.query(`
+      SELECT id, name, upid, min_value, max_value
+      FROM annotation_counter_track`);
+    for (let i = 0; i < annotationCounterRows.numRecords; i++) {
+      const id = annotationCounterRows.columns[0].longValues![i];
+      const name = annotationCounterRows.columns[1].stringValues![i];
+      const upid = annotationCounterRows.columns[2].longValues![i] as number;
+      const minimumValue = annotationCounterRows.columns[3].isNulls![i] ?
+          undefined :
+          annotationCounterRows.columns[3].doubleValues![i];
+      const maximumValue = annotationCounterRows.columns[4].isNulls![i] ?
+          undefined :
+          annotationCounterRows.columns[4].doubleValues![i];
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: 'CounterTrack',
+        name,
+        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP : upidToUuid.get(upid),
+        config: {
+          name,
+          namespace: 'annotation',
+          trackId: id,
+          minimumValue,
+          maximumValue,
+        }
+      });
+    }
+
+    addTrackGroupActions.push(Actions.addTracks({tracks: tracksToAdd}));
+    globals.dispatchMultiple(addTrackGroupActions);
   }
 
   private async listThreads() {
@@ -367,21 +873,19 @@
     const sqlQuery = `select utid, tid, pid, thread.name,
         ifnull(
           case when length(process.name) > 0 then process.name else null end,
-          thread.name),
-        process.cmdline
+          thread.name)
         from (select * from thread order by upid) as thread
         left join (select * from process order by upid) as process
         using(upid)`;
     const threadRows = await assertExists(this.engine).query(sqlQuery);
     const threads: ThreadDesc[] = [];
-    for (let i = 0; i < slowlyCountRows(threadRows); i++) {
-      const utid = threadRows.columns[0].longValues![i];
-      const tid = threadRows.columns[1].longValues![i];
-      const pid = threadRows.columns[2].longValues![i];
+    for (let i = 0; i < threadRows.numRecords; i++) {
+      const utid = threadRows.columns[0].longValues![i] as number;
+      const tid = threadRows.columns[1].longValues![i] as number;
+      const pid = threadRows.columns[2].longValues![i] as number;
       const threadName = threadRows.columns[3].stringValues![i];
       const procName = threadRows.columns[4].stringValues![i];
-      const cmdline = threadRows.columns[5].stringValues![i];
-      threads.push({utid, tid, threadName, pid, procName, cmdline});
+      threads.push({utid, tid, threadName, pid, procName});
     }  // for (record ...)
     globals.publish('Threads', threads);
   }
@@ -406,9 +910,9 @@
           `where ts >= ${startNs} and ts < ${endNs} and utid != 0 ` +
           'group by cpu order by cpu');
       const schedData: {[key: string]: QuantizedLoad} = {};
-      for (let i = 0; i < slowlyCountRows(schedRows); i++) {
+      for (let i = 0; i < schedRows.numRecords; i++) {
         const load = schedRows.columns[0].doubleValues![i];
-        const cpu = schedRows.columns[1].longValues![i];
+        const cpu = schedRows.columns[1].longValues![i] as number;
         schedData[cpu] = {startSec, endSec, load};
         hasSchedOverview = true;
       }  // for (record ...)
@@ -439,9 +943,9 @@
          group by bucket, upid`);
 
     const slicesData: {[key: string]: QuantizedLoad[]} = {};
-    for (let i = 0; i < slowlyCountRows(sliceSummaryQuery); i++) {
-      const bucket = sliceSummaryQuery.columns[0].longValues![i];
-      const upid = sliceSummaryQuery.columns[1].longValues![i];
+    for (let i = 0; i < sliceSummaryQuery.numRecords; i++) {
+      const bucket = sliceSummaryQuery.columns[0].longValues![i] as number;
+      const upid = sliceSummaryQuery.columns[1].longValues![i] as number;
       const load = sliceSummaryQuery.columns[2].doubleValues![i];
 
       const startSec = traceTime.start + stepSec * bucket;
@@ -459,8 +963,66 @@
 
   async initialiseHelperViews() {
     const engine = assertExists<Engine>(this.engine);
+    this.updateStatus('Creating helper views');
+    let event = 'sched_waking';
+    const waking = await engine.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 engine.query(`create view runnable AS
+      select
+        ts,
+        lead(ts, 1, (select end_ts from trace_bounds))
+          OVER(partition by ref order by ts) - ts as dur,
+        ref as utid
+      from instants
+      where name = '${event}'`);
 
-    this.updateStatus('Creating annotation counter track table');
+    // Get the first ts for each utid - whether a sched wakeup/waking
+    // or sched event.
+    await engine.query(`create view first_thread as
+      select min(ts) as ts, utid from
+      (select min(ts) as ts, utid from runnable group by utid
+       UNION
+      select min(ts) as ts,utid from sched group by utid)
+      group by 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.
+    await engine.query(`create view fill as
+      select first_thread.ts as ts,
+      coalesce(min(runnable.ts), (select end_ts from trace_bounds)) -
+      first_thread.ts as dur,
+      first_thread.utid as utid
+      from first_thread
+      LEFT JOIN runnable using(utid) group by utid`);
+
+    await engine.query(`create view full_runnable as
+        select * from runnable UNION
+        select * from fill`);
+
+    await engine.query(`create virtual table thread_span
+        using span_left_join(
+          full_runnable partitioned utid,
+          sched partitioned utid)`);
+
+    // For performance reasons we need to create a table here.
+    // Once b/145350531 is fixed this should be able to revert to a
+    // view and we can recover the extra memory use.
+    await engine.query(`create table thread_state as
+      select ts, dur, utid, cpu,
+      case when end_state is not null then 'Running'
+      when lag(end_state) over ordered is not null
+      then lag(end_state) over ordered else 'R'
+      end as state
+      from thread_span window ordered as
+      (partition by utid order by ts)`);
+
+    await engine.query(`create index utid_index on thread_state(utid)`);
+
     // Create the helper tables for all the annotations related data.
     // NULL in min/max means "figure it out per track in the usual way".
     await engine.query(`
@@ -473,7 +1035,6 @@
         max_value DOUBLE
       );
     `);
-    this.updateStatus('Creating annotation slice track table');
     await engine.query(`
       CREATE TABLE annotation_slice_track(
         id INTEGER PRIMARY KEY,
@@ -483,7 +1044,6 @@
       );
     `);
 
-    this.updateStatus('Creating annotation counter table');
     await engine.query(`
       CREATE TABLE annotation_counter(
         id BIG INT,
@@ -493,93 +1053,74 @@
         PRIMARY KEY (track_id, ts)
       ) WITHOUT ROWID;
     `);
-    this.updateStatus('Creating annotation slice table');
     await engine.query(`
       CREATE TABLE annotation_slice(
-        id INTEGER PRIMARY KEY,
+        id BIG INT,
         track_id INT,
         ts BIG INT,
         dur BIG INT,
         depth INT,
         cat STRING,
         name STRING,
-        UNIQUE(track_id, ts)
-      );
+        PRIMARY KEY (track_id, ts)
+      ) WITHOUT ROWID;
     `);
 
     for (const metric
              of ['android_startup',
                  'android_ion',
-                 'android_dma_heap',
-                 'android_thread_time_in_state',
-                 'android_surfaceflinger',
-                 'android_batt',
-                 'android_sysui_cuj',
-                 'android_jank']) {
-      this.updateStatus(`Computing ${metric} metric`);
-      try {
-        // We don't care about the actual result of metric here as we are just
-        // interested in the annotation tracks.
-        await engine.computeMetric([metric]);
-      } catch (e) {
-        if (e instanceof QueryError) {
-          globals.publish('MetricError', 'MetricError: ' + e.message);
-          continue;
-        } else {
-          throw e;
-        }
+                 'android_thread_time_in_state']) {
+      // We don't care about the actual result of metric here as we are just
+      // interested in the annotation tracks.
+      const metricResult = await engine.computeMetric([metric]);
+      assertTrue(metricResult.error.length === 0);
+
+      const result = await engine.query(`
+        SELECT * FROM ${metric}_annotations LIMIT 1`);
+
+      const hasSliceName =
+          result.columnDescriptors.some(x => x.name === 'slice_name');
+      const hasDur = result.columnDescriptors.some(x => x.name === 'dur');
+      const hasUpid = result.columnDescriptors.some(x => x.name === 'upid');
+
+      const upidColumnSelect = hasUpid ? 'upid' : '0 AS upid';
+      const upidColumnWhere = hasUpid ? 'upid' : '0';
+      if (hasSliceName && hasDur) {
+        await engine.query(`
+          INSERT INTO annotation_slice_track(name, __metric_name, upid)
+          SELECT DISTINCT
+            track_name,
+            '${metric}' as metric_name,
+            ${upidColumnSelect}
+          FROM ${metric}_annotations
+          WHERE track_type = 'slice'
+        `);
+        await engine.query(`
+          INSERT INTO annotation_slice(id, track_id, ts, dur, depth, cat, name)
+          SELECT
+            row_number() over (order by ts) as id,
+            t.id AS track_id,
+            ts,
+            dur,
+            0 AS depth,
+            a.track_name as cat,
+            slice_name AS name
+          FROM ${metric}_annotations a
+          JOIN annotation_slice_track t
+          ON a.track_name = t.name AND t.__metric_name = '${metric}'
+          ORDER BY t.id, ts
+        `);
       }
 
-      this.updateStatus(`Inserting data for ${metric} metric`);
-      try {
-        const result = await engine.query(`pragma table_info(${metric}_event)`);
-        let hasSliceName = false;
-        let hasDur = false;
-        let hasUpid = false;
-        for (let i = 0; i < slowlyCountRows(result); i++) {
-          const name = result.columns[1].stringValues![i];
-          hasSliceName = hasSliceName || name === 'slice_name';
-          hasDur = hasDur || name === 'dur';
-          hasUpid = hasUpid || name === 'upid';
-        }
-
-        const upidColumnSelect = hasUpid ? 'upid' : '0 AS upid';
-        const upidColumnWhere = hasUpid ? 'upid' : '0';
-        if (hasSliceName && hasDur) {
-          await engine.query(`
-            INSERT INTO annotation_slice_track(name, __metric_name, upid)
-            SELECT DISTINCT
-              track_name,
-              '${metric}' as metric_name,
-              ${upidColumnSelect}
-            FROM ${metric}_event
-            WHERE track_type = 'slice'
-          `);
-          await engine.query(`
-            INSERT INTO annotation_slice(track_id, ts, dur, depth, cat, name)
-            SELECT
-              t.id AS track_id,
-              ts,
-              dur,
-              0 AS depth,
-              a.track_name as cat,
-              slice_name AS name
-            FROM ${metric}_event a
-            JOIN annotation_slice_track t
-            ON a.track_name = t.name AND t.__metric_name = '${metric}'
-            ORDER BY t.id, ts
-          `);
-        }
-
-        const hasValue = result.columnDescriptors.some(x => x.name === 'value');
-        if (hasValue) {
-          const minMax = await engine.query(`
+      const hasValue = result.columnDescriptors.some(x => x.name === 'value');
+      if (hasValue) {
+        const minMax = await engine.query(`
           SELECT MIN(value) as min_value, MAX(value) as max_value
-          FROM ${metric}_event
+          FROM ${metric}_annotations
           WHERE ${upidColumnWhere} != 0`);
-          const min = minMax.columns[0].longValues![0];
-          const max = minMax.columns[1].longValues![0];
-          await engine.query(`
+        const min = minMax.columns[0].longValues![0] as number;
+        const max = minMax.columns[1].longValues![0] as number;
+        await engine.query(`
           INSERT INTO annotation_counter_track(
             name, __metric_name, min_value, max_value, upid)
           SELECT DISTINCT
@@ -588,28 +1129,21 @@
             CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${min} END,
             CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${max} END,
             ${upidColumnSelect}
-          FROM ${metric}_event
+          FROM ${metric}_annotations
           WHERE track_type = 'counter'
         `);
-          await engine.query(`
+        await engine.query(`
           INSERT INTO annotation_counter(id, track_id, ts, value)
           SELECT
             -1 as id,
             t.id AS track_id,
             ts,
             value
-          FROM ${metric}_event a
+          FROM ${metric}_annotations a
           JOIN annotation_counter_track t
           ON a.track_name = t.name AND t.__metric_name = '${metric}'
           ORDER BY t.id, ts
         `);
-        }
-      } catch (e) {
-        if (e instanceof QueryError) {
-          globals.publish('MetricError', 'MetricError: ' + e.message);
-        } else {
-          throw e;
-        }
       }
     }
   }
@@ -622,4 +1156,35 @@
   }
 }
 
+function getTrackName(args: Partial<{
+  utid: number,
+  processName: string | null,
+  pid: number | null,
+  threadName: string | null,
+  tid: number | null,
+  upid: number | null
+}>) {
+  const {upid, utid, processName, threadName, pid, tid} = args;
 
+  const hasUpid = upid !== undefined && upid !== null;
+  const hasUtid = utid !== undefined && utid !== null;
+  const hasProcessName = processName !== undefined && processName !== null;
+  const hasThreadName = threadName !== undefined && threadName !== null;
+  const hasTid = tid !== undefined && tid !== null;
+  const hasPid = pid !== undefined && pid !== null;
+
+  if (hasUpid && hasPid && hasProcessName) {
+    return `${processName} ${pid}`;
+  } else if (hasUpid && hasPid) {
+    return `Process ${pid}`;
+  } else if (hasThreadName && hasTid) {
+    return `${threadName} ${tid}`;
+  } else if (hasTid) {
+    return `Thread ${tid}`;
+  } else if (hasUpid) {
+    return `upid: ${upid}`;
+  } else if (hasUtid) {
+    return `utid: ${utid}`;
+  }
+  return 'Unknown';
+}
diff --git a/ui/src/controller/trace_converter.ts b/ui/src/controller/trace_converter.ts
index 889b76b..2a5b787 100644
--- a/ui/src/controller/trace_converter.ts
+++ b/ui/src/controller/trace_converter.ts
@@ -12,83 +12,94 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {defer} from '../base/deferred';
-import {assertExists} from '../base/logging';
 import {Actions} from '../common/actions';
 import {TraceSource} from '../common/state';
 import * as trace_to_text from '../gen/trace_to_text';
 
 import {globals} from './globals';
 
-type Format = 'json'|'systrace';
-
-export function ConvertTrace(
-    trace: Blob, format: Format, truncate?: 'start'|'end') {
-  const outPath = '/trace.json';
-  const args: string[] = [format];
-  if (truncate !== undefined) {
-    args.push('--truncate', truncate);
-  }
-  args.push('/fs/trace.proto', outPath);
-  runTraceconv(trace, args).then(module => {
-    const fsNode = module.FS.lookupPath(outPath).node;
-    const data = fsNode.contents.buffer;
-    const size = fsNode.usedBytes;
-    globals.publish('LegacyTrace', {data, size}, /*transfer=*/[data]);
-    module.FS.unlink(outPath);
-  });
-}
-
-export function ConvertTraceToPprof(
-    pid: number, src: TraceSource, ts1: number, ts2?: number) {
-  const timestamps = `${ts1}${ts2 === undefined ? '' : `,${ts2}`}`;
-  const args = [
-    'profile',
-    `--pid`,
-    `${pid}`,
-    `--timestamps`,
-    timestamps,
-    '/fs/trace.proto'
-  ];
-  generateBlob(src).then(traceBlob => {
-    runTraceconv(traceBlob, args).then(module => {
-      const heapDirName =
-          Object.keys(module.FS.lookupPath('/tmp/').node.contents)[0];
-      const heapDirContents =
-          module.FS.lookupPath(`/tmp/${heapDirName}`).node.contents;
-      const heapDumpFiles = Object.keys(heapDirContents);
-      let fileNum = 0;
-      heapDumpFiles.forEach(heapDump => {
-        const fileContents =
-            module.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`)
-                .node.contents;
-        fileNum++;
-        const fileName = `/heap_dump.${fileNum}.${pid}.pb`;
-        downloadFile(new Blob([fileContents]), fileName);
-      });
-    });
-  });
-}
-
-async function runTraceconv(trace: Blob, args: string[]) {
-  const deferredRuntimeInitialized = defer<void>();
-  const module = trace_to_text({
+export function ConvertTrace(trace: Blob, truncate?: 'start'|'end') {
+  const mod = trace_to_text({
     noInitialRun: true,
     locateFile: (s: string) => s,
     print: updateStatus,
     printErr: updateStatus,
-    onRuntimeInitialized: () => deferredRuntimeInitialized.resolve()
+    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]);
+      }
+      updateStatus('Trace conversion completed');
+      const fsNode = mod.FS.lookupPath(outPath).node;
+      const data = fsNode.contents.buffer;
+      const size = fsNode.usedBytes;
+      globals.publish('LegacyTrace', {data, size}, /*transfer=*/[data]);
+      mod.FS.unlink(outPath);
+    },
+    onAbort: () => {
+      console.log('ABORT');
+    },
   });
-  await deferredRuntimeInitialized;
-  module.FS.mkdir('/fs');
-  module.FS.mount(
-      assertExists(module.FS.filesystems.WORKERFS),
+  mod.FS.mkdir('/fs');
+  mod.FS.mount(
+      mod.FS.filesystems.WORKERFS,
       {blobs: [{name: 'trace.proto', data: trace}]},
       '/fs');
-  updateStatus('Converting trace');
-  module.callMain(args);
-  updateStatus('Trace conversion completed');
-  return module;
+
+  // TODO removeme.
+  (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) {
diff --git a/ui/src/controller/trace_error_controller.ts b/ui/src/controller/trace_error_controller.ts
deleted file mode 100644
index a8bb80b..0000000
--- a/ui/src/controller/trace_error_controller.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {Engine} from '../common/engine';
-
-import {Controller} from './controller';
-import {globals} from './globals';
-
-export interface TraceErrorControllerArgs {
-  engine: Engine;
-}
-
-export class TraceErrorController extends Controller<'main'> {
-  private hasRun = false;
-  constructor(private args: TraceErrorControllerArgs) {
-    super('main');
-  }
-
-  run() {
-    if (this.hasRun) {
-      return;
-    }
-    this.hasRun = true;
-    this.args.engine
-        .queryOneRow(`SELECT sum(value) FROM stats WHERE severity != 'info'`)
-        .then(result => {
-          globals.publish('TraceErrors', result[0]);
-        });
-  }
-}
diff --git a/ui/src/controller/trace_stream.ts b/ui/src/controller/trace_stream.ts
index 34c3861..75ef8d4 100644
--- a/ui/src/controller/trace_stream.ts
+++ b/ui/src/controller/trace_stream.ts
@@ -120,41 +120,13 @@
       this.httpStream = (response.body as any).getReader();
     }
 
-    let eof = false;
-    let bytesRead = 0;
-    const chunks = [];
-
-    // httpStream can return very small chunks which can slow down
-    // TraceProcessor. Here we accumulate chunks until we get at least 32mb
-    // or hit EOF.
-    while (!eof && bytesRead < 32 * 1024 * 1024) {
-      const res = (await this.httpStream!.read()) as
-          {value?: Uint8Array, done: boolean};
-      if (res.value) {
-        chunks.push(res.value);
-        bytesRead += res.value.length;
-      }
-      eof = res.done;
-    }
-
-    let data;
-    if (chunks.length === 1) {
-      data = chunks[0];
-    } else {
-      // Stitch all the chunks into one big array:
-      data = new Uint8Array(bytesRead);
-      let offset = 0;
-      for (const chunk of chunks) {
-        data.set(chunk, offset);
-        offset += chunk.length;
-      }
-    }
-
+    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,
+      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 75ee194..aa39a34 100644
--- a/ui/src/controller/track_controller.ts
+++ b/ui/src/controller/track_controller.ts
@@ -12,11 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertExists, assertTrue} from '../base/logging';
+import {assertExists} from '../base/logging';
 import {Engine} from '../common/engine';
 import {Registry} from '../common/registry';
 import {TraceTime, TrackState} from '../common/state';
-import {fromNs, toNs} from '../common/time';
 import {LIMIT, TrackData} from '../common/track_data';
 
 import {Controller} from './controller';
@@ -27,9 +26,6 @@
 
 type TrackConfigWithNamespace = TrackConfig&{namespace: string};
 
-// Allow to override via devtools for testing (note, needs to be done in the
-// controller-thread).
-(self as {} as {quantPx: number}).quantPx = 1;
 
 // TrackController is a base class overridden by track implementations (e.g.,
 // sched slices, nestable slices, counters).
@@ -40,12 +36,6 @@
   private data?: TrackData;
   private requestingData = false;
   private queuedRequest = false;
-  private isSetup = false;
-  private lastReloadHandled = 0;
-
-  // We choose 100000 as the table size to cache as this is roughly the point
-  // where SQLite sorts start to become expensive.
-  private static readonly MIN_TABLE_SIZE_TO_CACHE = 100000;
 
   constructor(args: TrackControllerArgs) {
     super('main');
@@ -53,18 +43,6 @@
     this.engine = args.engine;
   }
 
-  protected pxSize(): number {
-    return (self as {} as {quantPx: number}).quantPx;
-  }
-
-  // Can be overriden by the track implementation to allow one time setup work
-  // to be performed before the first onBoundsChange invcation.
-  async onSetup() {}
-
-  // Can be overriden by the track implementation to allow some one-off work
-  // when requested reload (e.g. recalculating height).
-  async onReload() {}
-
   // 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.
@@ -118,19 +96,8 @@
     return result;
   }
 
-  private shouldReload(): boolean {
-    const {lastTrackReloadRequest} = globals.state;
-    return !!lastTrackReloadRequest &&
-        this.lastReloadHandled < lastTrackReloadRequest;
-  }
-
-  private markReloadHandled() {
-    this.lastReloadHandled = globals.state.lastTrackReloadRequest || 0;
-  }
-
   shouldRequestData(traceTime: TraceTime): boolean {
     if (this.data === undefined) return true;
-    if (this.shouldReload()) return true;
 
     // If at the limit only request more data if the view has moved.
     const atLimit = this.data.length === LIMIT;
@@ -151,85 +118,6 @@
         globals.state.frontendLocalState.visibleState.resolution;
   }
 
-  // Decides, based on the the length of the trace and the number of rows
-  // provided whether a TrackController subclass should cache its quantized
-  // data. Returns the bucket size (in ns) if caching should happen and
-  // undefined otherwise.
-  // Subclasses should call this in their setup function
-  cachedBucketSizeNs(numRows: number): number|undefined {
-    // Ensure that we're not caching when the table size isn't even that big.
-    if (numRows < TrackController.MIN_TABLE_SIZE_TO_CACHE) {
-      return undefined;
-    }
-
-    const bounds = globals.state.traceTime;
-    const traceDurNs = toNs(bounds.endSec - bounds.startSec);
-
-    // For large traces, going through the raw table in the most zoomed-out
-    // states can be very expensive as this can involve going through O(millions
-    // of rows). The cost of this becomes high even for just iteration but is
-    // especially slow as quantization involves a SQLite sort on the quantized
-    // timestamp (for the group by).
-    //
-    // To get around this, we can cache a pre-quantized table which we can then
-    // in zoomed-out situations and fall back to the real table when zoomed in
-    // (which naturally constrains the amount of data by virtue of the window
-    // covering a smaller timespan)
-    //
-    // This method computes that cached table by computing an approximation for
-    // the bucket size we would use when totally zoomed out and then going a few
-    // resolution levels down which ensures that our cached table works for more
-    // than the literally most zoomed out state. Moving down a resolution level
-    // is defined as moving down a power of 2; this matches the logic in
-    // |globals.getCurResolution|.
-    //
-    // TODO(lalitm): in the future, we should consider having a whole set of
-    // quantized tables each of which cover some portion of resolution lvel
-    // range. As each table covers a large number of resolution levels, even 3-4
-    // tables should really cover the all concievable trace sizes. This set
-    // could be computed by looking at the number of events being processed one
-    // level below the cached table and computing another layer of caching if
-    // that count is too high (with respect to MIN_TABLE_SIZE_TO_CACHE).
-
-    // 4k monitors have 3840 horizontal pixels so use that for a worst case
-    // approximation of the window width.
-    const approxWidthPx = 3840;
-
-    // Compute the outermost bucket size. This acts as a starting point for
-    // computing the cached size.
-    const outermostResolutionLevel =
-        Math.ceil(Math.log2(traceDurNs / approxWidthPx));
-    const outermostBucketNs = Math.pow(2, outermostResolutionLevel);
-
-    // This constant decides how many resolution levels down from our outermost
-    // bucket computation we want to be able to use the cached table.
-    // We've chosen 7 as it seems to be empircally seems to be a good fit for
-    // trace data.
-    const resolutionLevelsCovered = 7;
-
-    // If we've got less resolution levels in the trace than the number of
-    // resolution levels we want to go down, bail out because this cached
-    // table is really not going to be used enough.
-    if (outermostResolutionLevel < resolutionLevelsCovered) {
-      return Number.MAX_SAFE_INTEGER;
-    }
-
-    // Another way to look at moving down resolution levels is to consider how
-    // many sub-intervals we are splitting the bucket into.
-    const bucketSubIntervals = Math.pow(2, resolutionLevelsCovered);
-
-    // Calculate the smallest bucket we want our table to be able to handle by
-    // dividing the outermsot bucket by the number of subintervals we should
-    // divide by.
-    const cachedBucketSizeNs = outermostBucketNs / bucketSubIntervals;
-
-    // Our logic above should make sure this is an integer but double check that
-    // here as an assertion before returning.
-    assertTrue(Number.isInteger(cachedBucketSizeNs));
-
-    return cachedBucketSizeNs;
-  }
-
   run() {
     const visibleState = globals.state.frontendLocalState.visibleState;
     if (visibleState === undefined || visibleState.resolution === undefined ||
@@ -243,28 +131,10 @@
         this.queuedRequest = true;
       } else {
         this.requestingData = true;
-        let promise = Promise.resolve();
-        if (!this.isSetup) {
-          promise = this.onSetup();
-        } else if (this.shouldReload()) {
-          promise = this.onReload().then(() => this.markReloadHandled());
-        }
-        promise
-            .then(() => {
-              this.isSetup = true;
-              let resolution = visibleState.resolution;
-              // TODO(hjd): We shouldn't have to be so defensive here.
-              if (Math.log2(toNs(resolution)) % 1 !== 0) {
-                // resolution is in pixels per second so 1000 means
-                // 1px = 1ms.
-                resolution =
-                    fromNs(Math.pow(2, Math.floor(Math.log2(toNs(1000)))));
-              }
-              return this.onBoundsChange(
-                  visibleState.startSec - dur,
-                  visibleState.endSec + dur,
-                  resolution);
-            })
+        this.onBoundsChange(
+                visibleState.startSec - dur,
+                visibleState.endSec + dur,
+                visibleState.resolution)
             .then(data => {
               this.publish(data);
             })
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
deleted file mode 100644
index 26f343b..0000000
--- a/ui/src/controller/track_decider.ts
+++ /dev/null
@@ -1,1085 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import * as uuidv4 from 'uuid/v4';
-import {assertExists} from '../base/logging';
-
-import {
-  Actions,
-  AddTrackArgs,
-  DeferredAction,
-} from '../common/actions';
-import {Engine} from '../common/engine';
-import {
-  iter,
-  NUM,
-  NUM_NULL,
-  slowlyCountRows,
-  STR,
-  STR_NULL,
-} from '../common/query_iterator';
-import {SCROLLING_TRACK_GROUP, TrackKindPriority} from '../common/state';
-import {ACTUAL_FRAMES_SLICE_TRACK_KIND} from '../tracks/actual_frames/common';
-import {ANDROID_LOGS_TRACK_KIND} from '../tracks/android_log/common';
-import {ASYNC_SLICE_TRACK_KIND} from '../tracks/async_slices/common';
-import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
-import {COUNTER_TRACK_KIND} from '../tracks/counter/common';
-import {CPU_FREQ_TRACK_KIND} from '../tracks/cpu_freq/common';
-import {CPU_PROFILE_TRACK_KIND} from '../tracks/cpu_profile/common';
-import {CPU_SLICE_TRACK_KIND} from '../tracks/cpu_slices/common';
-import {
-  EXPECTED_FRAMES_SLICE_TRACK_KIND
-} from '../tracks/expected_frames/common';
-import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
-import {
-  PROCESS_SCHEDULING_TRACK_KIND
-} from '../tracks/process_scheduling/common';
-import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary/common';
-import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state/common';
-
-const MEM_DMA_COUNTER_NAME = 'mem.dma_heap';
-const MEM_DMA = 'mem.dma_buffer';
-const MEM_ION = 'mem.ion';
-
-export async function decideTracks(
-    engineId: string, engine: Engine): Promise<DeferredAction[]> {
-  return (new TrackDecider(engineId, engine)).decideTracks();
-}
-
-class TrackDecider {
-  private engineId: string;
-  private engine: Engine;
-  private upidToUuid = new Map<number, string>();
-  private utidToUuid = new Map<number, string>();
-  private tracksToAdd: AddTrackArgs[] = [];
-  private addTrackGroupActions: DeferredAction[] = [];
-
-  constructor(engineId: string, engine: Engine) {
-    this.engineId = engineId;
-    this.engine = engine;
-  }
-
-  static getTrackName(args: Partial<{
-    name: string | null,
-    utid: number,
-    processName: string|null,
-    pid: number|null,
-    threadName: string|null,
-    tid: number|null,
-    upid: number|null,
-    kind: string,
-    threadTrack: boolean
-  }>) {
-    const {
-      name,
-      upid,
-      utid,
-      processName,
-      threadName,
-      pid,
-      tid,
-      kind,
-      threadTrack
-    } = args;
-
-    const hasName = name !== undefined && name !== null && name !== '[NULL]';
-    const hasUpid = upid !== undefined && upid !== null;
-    const hasUtid = utid !== undefined && utid !== null;
-    const hasProcessName = processName !== undefined && processName !== null;
-    const hasThreadName = threadName !== undefined && threadName !== null;
-    const hasTid = tid !== undefined && tid !== null;
-    const hasPid = pid !== undefined && pid !== null;
-    const hasKind = kind !== undefined;
-    const isThreadTrack = threadTrack !== undefined && threadTrack;
-
-    // If we don't have any useful information (better than
-    // upid/utid) we show the track kind to help with tracking
-    // down where this is coming from.
-    const kindSuffix = hasKind ? ` (${kind})` : '';
-
-    if (isThreadTrack && hasName && hasTid) {
-      return `${name} (${tid})`;
-    } else if (hasName) {
-      return `${name}`;
-    } else if (hasUpid && hasPid && hasProcessName) {
-      return `${processName} ${pid}`;
-    } else if (hasUpid && hasPid) {
-      return `Process ${pid}`;
-    } else if (hasThreadName && hasTid) {
-      return `${threadName} ${tid}`;
-    } else if (hasTid) {
-      return `Thread ${tid}`;
-    } else if (hasUpid) {
-      return `upid: ${upid}${kindSuffix}`;
-    } else if (hasUtid) {
-      return `utid: ${utid}${kindSuffix}`;
-    } else if (hasKind) {
-      return `Unnamed ${kind}`;
-    }
-    return 'Unknown';
-  }
-
-  async addCpuSchedulingTracks(): Promise<void> {
-    const cpus = await this.engine.getCpus();
-    for (const cpu of cpus) {
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: CPU_SLICE_TRACK_KIND,
-        trackKindPriority: TrackKindPriority.ORDINARY,
-        name: `Cpu ${cpu}`,
-        trackGroup: SCROLLING_TRACK_GROUP,
-        config: {
-          cpu,
-        }
-      });
-    }
-  }
-
-  async addCpuFreqTracks(): Promise<void> {
-    const cpus = await this.engine.getCpus();
-
-    const maxCpuFreq = await this.engine.query(`
-    select max(value)
-    from counter c
-    inner join cpu_counter_track t on c.track_id = t.id
-    where name = 'cpufreq';
-  `);
-
-    for (const cpu of cpus) {
-      // Only add a cpu freq track if we have
-      // cpu freq data.
-      // TODO(hjd): Find a way to display cpu idle
-      // events even if there are no cpu freq events.
-      const cpuFreqIdle = await this.engine.query(`
-      select
-        id as cpu_freq_id,
-        (
-          select id
-          from cpu_counter_track
-          where name = 'cpuidle'
-          and cpu = ${cpu}
-          limit 1
-        ) as cpu_idle_id
-      from cpu_counter_track
-      where name = 'cpufreq' and cpu = ${cpu}
-      limit 1;
-    `);
-      if (slowlyCountRows(cpuFreqIdle) > 0) {
-        const freqTrackId = +cpuFreqIdle.columns[0].longValues![0];
-
-        const idleTrackExists: boolean = !cpuFreqIdle.columns[1].isNulls![0];
-        const idleTrackId = idleTrackExists ?
-            +cpuFreqIdle.columns[1].longValues![0] :
-            undefined;
-
-        this.tracksToAdd.push({
-          engineId: this.engineId,
-          kind: CPU_FREQ_TRACK_KIND,
-          trackKindPriority: TrackKindPriority.ORDINARY,
-          name: `Cpu ${cpu} Frequency`,
-          trackGroup: SCROLLING_TRACK_GROUP,
-          config: {
-            cpu,
-            maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
-            freqTrackId,
-            idleTrackId,
-          }
-        });
-      }
-    }
-  }
-
-  async addGlobalAsyncTracks(): Promise<void> {
-    const rawGlobalAsyncTracks = await this.engine.query(`
-    SELECT
-      t.name,
-      t.track_ids,
-      MAX(experimental_slice_layout.layout_depth) as max_depth
-    FROM (
-      SELECT name, GROUP_CONCAT(track.id) AS track_ids
-      FROM track
-      WHERE track.type = "track"
-      GROUP BY name
-    ) AS t CROSS JOIN experimental_slice_layout
-    WHERE t.track_ids = experimental_slice_layout.filter_track_ids
-    GROUP BY t.track_ids;
-  `);
-    for (let i = 0; i < slowlyCountRows(rawGlobalAsyncTracks); i++) {
-      const name = rawGlobalAsyncTracks.columns[0].isNulls![i] ?
-          undefined :
-          rawGlobalAsyncTracks.columns[0].stringValues![i];
-      const rawTrackIds = rawGlobalAsyncTracks.columns[1].stringValues![i];
-      const trackIds = rawTrackIds.split(',').map(v => Number(v));
-      const maxDepth = +rawGlobalAsyncTracks.columns[2].longValues![i];
-      const kind = ASYNC_SLICE_TRACK_KIND;
-      const track = {
-        engineId: this.engineId,
-        kind,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(name),
-        trackGroup: SCROLLING_TRACK_GROUP,
-        name: TrackDecider.getTrackName({name, kind}),
-        config: {
-          maxDepth,
-          trackIds,
-        },
-      };
-      this.tracksToAdd.push(track);
-    }
-  }
-
-  async addGpuFreqTracks(): Promise<void> {
-    const numGpus = await this.engine.getNumberOfGpus();
-    const maxGpuFreq = await this.engine.query(`
-    select max(value)
-    from counter c
-    inner join gpu_counter_track t on c.track_id = t.id
-    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 this.engine.query(`
-      select id
-      from gpu_counter_track
-      where name = 'gpufreq' and gpu_id = ${gpu}
-      limit 1;
-    `);
-      if (slowlyCountRows(freqExists) > 0) {
-        this.tracksToAdd.push({
-          engineId: this.engineId,
-          kind: COUNTER_TRACK_KIND,
-          name: `Gpu ${gpu} Frequency`,
-          trackKindPriority: TrackKindPriority.ORDINARY,
-          trackGroup: SCROLLING_TRACK_GROUP,
-          config: {
-            trackId: +freqExists.columns[0].longValues![0],
-            maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
-          }
-        });
-      }
-    }
-  }
-
-  async addGlobalCounterTracks(): Promise<void> {
-    // Add global or GPU counter tracks that are not bound to any pid/tid.
-    const globalCounters = await this.engine.query(`
-    select name, id
-    from counter_track
-    where type = 'counter_track'
-    union
-    select name, id
-    from gpu_counter_track
-    where name != 'gpufreq'
-  `);
-    for (let i = 0; i < slowlyCountRows(globalCounters); i++) {
-      const name = globalCounters.columns[0].stringValues![i];
-      const trackId = +globalCounters.columns[1].longValues![i];
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: COUNTER_TRACK_KIND,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(name),
-        trackGroup: SCROLLING_TRACK_GROUP,
-        config: {
-          name,
-          trackId,
-        }
-      });
-    }
-  }
-
-  async groupGlobalIonTracks(): Promise<void> {
-    const ionTracks: AddTrackArgs[] = [];
-    let hasSummary = false;
-    for (const track of this.tracksToAdd) {
-      const isIon = track.name.startsWith(MEM_ION);
-      const isIonCounter = track.name === MEM_ION;
-      const isDmaHeapCounter = track.name === MEM_DMA_COUNTER_NAME;
-      const isDmaBuffferSlices = track.name === MEM_DMA;
-      if (isIon || isIonCounter || isDmaHeapCounter || isDmaBuffferSlices) {
-        ionTracks.push(track);
-      }
-      hasSummary = hasSummary || isIonCounter;
-      hasSummary = hasSummary || isDmaHeapCounter;
-    }
-
-    if (ionTracks.length === 0 || !hasSummary) {
-      return;
-    }
-
-    const id = uuidv4();
-    const summaryTrackId = uuidv4();
-    let foundSummary = false;
-
-    for (const track of ionTracks) {
-      if (!foundSummary &&
-          [MEM_DMA_COUNTER_NAME, MEM_ION].includes(track.name)) {
-        foundSummary = true;
-        track.id = summaryTrackId;
-        track.trackGroup = undefined;
-      } else {
-        track.trackGroup = id;
-      }
-    }
-
-    const addGroup = Actions.addTrackGroup({
-      engineId: this.engineId,
-      summaryTrackId,
-      name: MEM_DMA_COUNTER_NAME,
-      id,
-      collapsed: true,
-    });
-    this.addTrackGroupActions.push(addGroup);
-  }
-
-  async addLogsTrack(): Promise<void> {
-    const logCount =
-        await this.engine.query(`select count(1) from android_logs`);
-    if (logCount.columns[0].longValues![0] > 0) {
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: ANDROID_LOGS_TRACK_KIND,
-        name: 'Android logs',
-        trackKindPriority: TrackKindPriority.ORDINARY,
-        trackGroup: SCROLLING_TRACK_GROUP,
-        config: {}
-      });
-    }
-  }
-
-  async addAnnotationTracks(): Promise<void> {
-    const annotationSliceRows = await this.engine.query(`
-    SELECT id, name, upid FROM annotation_slice_track`);
-    for (let i = 0; i < slowlyCountRows(annotationSliceRows); i++) {
-      const id = annotationSliceRows.columns[0].longValues![i];
-      const name = annotationSliceRows.columns[1].stringValues![i];
-      const upid = annotationSliceRows.columns[2].longValues![i];
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: SLICE_TRACK_KIND,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(name),
-        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP :
-                                 this.upidToUuid.get(upid),
-        config: {
-          maxDepth: 0,
-          namespace: 'annotation',
-          trackId: id,
-        },
-      });
-    }
-
-    const annotationCounterRows = await this.engine.query(`
-    SELECT id, name, upid, min_value, max_value
-    FROM annotation_counter_track`);
-    for (let i = 0; i < slowlyCountRows(annotationCounterRows); i++) {
-      const id = annotationCounterRows.columns[0].longValues![i];
-      const name = annotationCounterRows.columns[1].stringValues![i];
-      const upid = annotationCounterRows.columns[2].longValues![i];
-      const minimumValue = annotationCounterRows.columns[3].isNulls![i] ?
-          undefined :
-          annotationCounterRows.columns[3].doubleValues![i];
-      const maximumValue = annotationCounterRows.columns[4].isNulls![i] ?
-          undefined :
-          annotationCounterRows.columns[4].doubleValues![i];
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: 'CounterTrack',
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(name),
-        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP :
-                                 this.upidToUuid.get(upid),
-        config: {
-          name,
-          namespace: 'annotation',
-          trackId: id,
-          minimumValue,
-          maximumValue,
-        }
-      });
-    }
-  }
-
-  async addThreadStateTracks(): Promise<void> {
-    const query = await this.engine.query(`
-      select
-        utid,
-        tid,
-        upid,
-        pid,
-        thread.name as threadName
-      from
-        thread_state
-        left join thread using(utid)
-        left join process using(upid)
-      where utid != 0
-      group by utid`);
-
-    const it = iter(
-        {
-          utid: NUM,
-          upid: NUM_NULL,
-          tid: NUM_NULL,
-          pid: NUM_NULL,
-          threadName: STR_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const utid = row.utid;
-      const tid = row.tid;
-      const upid = row.upid;
-      const pid = row.pid;
-      const threadName = row.threadName;
-      const uuid = this.getUuidUnchecked(utid, upid);
-      if (uuid === undefined) {
-        // If a thread has no scheduling activity (i.e. the sched table has zero
-        // rows for that uid) no track group will be created and we want to skip
-        // the track creation as well.
-        continue;
-      }
-      const kind = THREAD_STATE_TRACK_KIND;
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name: TrackDecider.getTrackName({utid, tid, threadName, kind}),
-        trackGroup: uuid,
-        trackKindPriority:
-            TrackDecider.inferTrackKindPriority(threadName, tid, pid),
-        config: {utid, tid}
-      });
-    }
-  }
-
-  async addThreadCpuSampleTracks(): Promise<void> {
-    const query = await this.engine.query(`
-      select
-        utid,
-        tid,
-        upid,
-        thread.name as threadName
-      from
-        thread
-        join (select utid
-            from cpu_profile_stack_sample group by utid
-        ) using(utid)
-        left join process using(upid)
-      where utid != 0
-      group by utid`);
-
-    const it = iter(
-        {
-          utid: NUM,
-          upid: NUM_NULL,
-          tid: NUM_NULL,
-          threadName: STR_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const utid = row.utid;
-      const upid = row.upid;
-      const threadName = row.threadName;
-      const uuid = this.getUuid(utid, upid);
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: CPU_PROFILE_TRACK_KIND,
-        // TODO(hjd): The threadName can be null, use  instead.
-        trackKindPriority: TrackDecider.inferTrackKindPriority(threadName),
-        name: `${threadName} (CPU Stack Samples)`,
-        trackGroup: uuid,
-        config: {utid},
-      });
-    }
-  }
-
-  async addThreadCounterTracks(): Promise<void> {
-    const query = await this.engine.query(`
-    select
-      thread_counter_track.name as trackName,
-      utid,
-      upid,
-      tid,
-      thread.name as threadName,
-      thread_counter_track.id as trackId,
-      thread.start_ts as startTs,
-      thread.end_ts as endTs
-    from thread_counter_track
-    join thread using(utid)
-    left join process using(upid)
-    where thread_counter_track.name not in ('time_in_state', 'thread_time')
-  `);
-
-    const it = iter(
-        {
-          trackName: STR_NULL,
-          utid: NUM,
-          upid: NUM_NULL,
-          tid: NUM_NULL,
-          threadName: STR_NULL,
-          startTs: NUM_NULL,
-          trackId: NUM,
-          endTs: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const utid = row.utid;
-      const tid = row.tid;
-      const upid = row.upid;
-      const trackId = row.trackId;
-      const trackName = row.trackName;
-      const threadName = row.threadName;
-      const uuid = this.getUuid(utid, upid);
-      const startTs = row.startTs === null ? undefined : row.startTs;
-      const endTs = row.endTs === null ? undefined : row.endTs;
-      const kind = COUNTER_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, utid, tid, kind, threadName, threadTrack: true});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(threadName),
-        trackGroup: uuid,
-        config: {name, trackId, startTs, endTs, tid}
-      });
-    }
-  }
-
-  async addProcessAsyncSliceTracks(): Promise<void> {
-    const query = await this.engine.query(`
-        select
-          process_track.upid as upid,
-          process_track.name as trackName,
-          group_concat(process_track.id) as trackIds,
-          process.name as processName,
-          process.pid as pid
-        from process_track
-        left join process using(upid)
-        where process_track.name not like "% Timeline"
-        group by
-          process_track.upid,
-          process_track.name
-  `);
-
-    const it = iter(
-        {
-          upid: NUM,
-          trackName: STR_NULL,
-          trackIds: STR,
-          processName: STR_NULL,
-          pid: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const upid = row.upid;
-      const trackName = row.trackName;
-      const rawTrackIds = row.trackIds;
-      const trackIds = rawTrackIds.split(',').map(v => Number(v));
-      const processName = row.processName;
-      const pid = row.pid;
-
-      const uuid = this.getUuid(0, upid);
-
-      // TODO(hjd): 1+N queries are bad in the track_decider
-      const depthResult = await this.engine.query(`
-      SELECT MAX(layout_depth) as max_depth
-      FROM experimental_slice_layout('${rawTrackIds}');
-    `);
-      const maxDepth = +depthResult.columns[0].longValues![0];
-
-      const kind = ASYNC_SLICE_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, upid, pid, processName, kind});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(name),
-        trackGroup: uuid,
-        config: {
-          trackIds,
-          maxDepth,
-        }
-      });
-    }
-  }
-
-  async addActualFramesTracks(): Promise<void> {
-    const query = await this.engine.query(`
-        select
-          upid,
-          trackName,
-          trackIds,
-          process.name as processName,
-          process.pid as pid
-        from (
-          select
-            process_track.upid as upid,
-            process_track.name as trackName,
-            group_concat(process_track.id) as trackIds
-          from process_track
-          where process_track.name like "Actual Timeline"
-          group by
-            process_track.upid,
-            process_track.name
-        ) left join process using(upid)
-  `);
-
-    const it = iter(
-        {
-          upid: NUM,
-          trackName: STR_NULL,
-          trackIds: STR,
-          processName: STR_NULL,
-          pid: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const upid = row.upid;
-      const trackName = row.trackName;
-      const rawTrackIds = row.trackIds;
-      const trackIds = rawTrackIds.split(',').map(v => Number(v));
-      const processName = row.processName;
-      const pid = row.pid;
-
-      const uuid = this.getUuid(0, upid);
-
-      // TODO(hjd): 1+N queries are bad in the track_decider
-      const depthResult = await this.engine.query(`
-      SELECT MAX(layout_depth) as max_depth
-      FROM experimental_slice_layout('${rawTrackIds}');
-    `);
-      const maxDepth = +depthResult.columns[0].longValues![0];
-
-      const kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, upid, pid, processName, kind});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(trackName),
-        trackGroup: uuid,
-        config: {
-          trackIds,
-          maxDepth,
-        }
-      });
-    }
-  }
-
-  async addExpectedFramesTracks(): Promise<void> {
-    const query = await this.engine.query(`
-        select
-          upid,
-          trackName,
-          trackIds,
-          process.name as processName,
-          process.pid as pid
-        from (
-          select
-            process_track.upid as upid,
-            process_track.name as trackName,
-            group_concat(process_track.id) as trackIds
-          from process_track
-          where process_track.name like "Expected Timeline"
-          group by
-            process_track.upid,
-            process_track.name
-        ) left join process using(upid)
-  `);
-
-    const it = iter(
-        {
-          upid: NUM,
-          trackName: STR_NULL,
-          trackIds: STR,
-          processName: STR_NULL,
-          pid: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const upid = row.upid;
-      const trackName = row.trackName;
-      const rawTrackIds = row.trackIds;
-      const trackIds = rawTrackIds.split(',').map(v => Number(v));
-      const processName = row.processName;
-      const pid = row.pid;
-
-      const uuid = this.getUuid(0, upid);
-
-      // TODO(hjd): 1+N queries are bad in the track_decider
-      const depthResult = await this.engine.query(`
-      SELECT MAX(layout_depth) as max_depth
-      FROM experimental_slice_layout('${rawTrackIds}');
-    `);
-      const maxDepth = +depthResult.columns[0].longValues![0];
-
-      const kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, upid, pid, processName, kind});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(trackName),
-        trackGroup: uuid,
-        config: {
-          trackIds,
-          maxDepth,
-        }
-      });
-    }
-  }
-
-  async addThreadSliceTracks(): Promise<void> {
-    const query = await this.engine.query(`
-        select
-          thread_track.utid as utid,
-          thread_track.id as trackId,
-          thread_track.name as trackName,
-          tid,
-          thread.name as threadName,
-          max(depth) as maxDepth,
-          process.upid as upid,
-          process.pid as pid
-        from slice
-        join thread_track on slice.track_id = thread_track.id
-        join thread using(utid)
-        left join process using(upid)
-        group by thread_track.id
-  `);
-
-    const it = iter(
-        {
-          utid: NUM,
-          trackId: NUM,
-          trackName: STR_NULL,
-          tid: NUM_NULL,
-          threadName: STR_NULL,
-          maxDepth: NUM,
-          upid: NUM_NULL,
-          pid: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const utid = row.utid;
-      const trackId = row.trackId;
-      const trackName = row.trackName;
-      const tid = row.tid;
-      const threadName = row.threadName;
-      const upid = row.upid;
-      const pid = row.pid;
-      const maxDepth = row.maxDepth;
-      const trackKindPriority =
-          TrackDecider.inferTrackKindPriority(threadName, tid, pid);
-
-      const uuid = this.getUuid(utid, upid);
-
-      const kind = SLICE_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, utid, tid, threadName, kind});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackGroup: uuid,
-        trackKindPriority,
-        config: {trackId, maxDepth, tid}
-      });
-    }
-  }
-
-  async addProcessCounterTracks(): Promise<void> {
-    const query = await this.engine.query(`
-    select
-      process_counter_track.id as trackId,
-      process_counter_track.name as trackName,
-      upid,
-      process.pid,
-      process.name as processName,
-      process.start_ts as startTs,
-      process.end_ts as endTs
-    from process_counter_track
-    join process using(upid);
-  `);
-    const it = iter(
-        {
-          trackId: NUM,
-          trackName: STR_NULL,
-          upid: NUM,
-          pid: NUM_NULL,
-          processName: STR_NULL,
-          startTs: NUM_NULL,
-          endTs: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const pid = row.pid;
-      const upid = row.upid;
-      const trackId = row.trackId;
-      const trackName = row.trackName;
-      const processName = row.processName;
-      const uuid = this.getUuid(0, upid);
-      const startTs = row.startTs === null ? undefined : row.startTs;
-      const endTs = row.endTs === null ? undefined : row.endTs;
-      const kind = COUNTER_TRACK_KIND;
-      const name = TrackDecider.getTrackName(
-          {name: trackName, upid, pid, kind, processName});
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind,
-        name,
-        trackKindPriority: TrackDecider.inferTrackKindPriority(trackName),
-        trackGroup: uuid,
-        config: {
-          name,
-          trackId,
-          startTs,
-          endTs,
-        }
-      });
-    }
-  }
-
-  async addProcessHeapProfileTracks(): Promise<void> {
-    const query = await this.engine.query(`
-    select distinct(upid) from heap_profile_allocation
-    union
-    select distinct(upid) from heap_graph_object
-  `);
-    const it = iter({upid: NUM}, query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const upid = it.row.upid;
-      const uuid = this.getUuid(0, upid);
-      this.tracksToAdd.push({
-        engineId: this.engineId,
-        kind: HEAP_PROFILE_TRACK_KIND,
-        trackKindPriority: TrackKindPriority.ORDINARY,
-        name: `Heap Profile`,
-        trackGroup: uuid,
-        config: {upid}
-      });
-    }
-  }
-
-  getUuidUnchecked(utid: number, upid: number|null) {
-    return upid === null ? this.utidToUuid.get(utid) :
-                           this.upidToUuid.get(upid);
-  }
-
-  getUuid(utid: number, upid: number|null) {
-    return assertExists(this.getUuidUnchecked(utid, upid));
-  }
-
-  getOrCreateUuid(utid: number, upid: number|null) {
-    let uuid = this.getUuidUnchecked(utid, upid);
-    if (uuid === undefined) {
-      uuid = uuidv4();
-      if (upid === null) {
-        this.utidToUuid.set(utid, uuid);
-      } else {
-        this.upidToUuid.set(upid, uuid);
-      }
-    }
-    return uuid;
-  }
-
-  async addProcessTrackGroups(): Promise<void> {
-    // We want to create groups of tracks in a specific order.
-    // The tracks should be grouped:
-    //    by upid
-    //    or (if upid is null) by utid
-    // the groups should be sorted by:
-    //  has a heap profile or not
-    //  total cpu time *for the whole parent process*
-    //  upid
-    //  utid
-    const query = await this.engine.query(`
-    select
-      the_tracks.upid,
-      the_tracks.utid,
-      total_dur as hasSched,
-      hasHeapProfiles,
-      process.pid as pid,
-      thread.tid as tid,
-      process.name as processName,
-      thread.name as threadName
-    from (
-      select upid, 0 as utid from process_track
-      union
-      select upid, 0 as utid from process_counter_track
-      union
-      select upid, utid from thread_counter_track join thread using(utid)
-      union
-      select upid, utid from thread_track join thread using(utid)
-      union
-      select upid, utid from sched join thread using(utid) group by utid
-      union
-      select upid, utid from (
-        select distinct(utid) from cpu_profile_stack_sample
-      ) join thread using(utid)
-      union
-      select distinct(upid) as upid, 0 as utid from heap_profile_allocation
-      union
-      select distinct(upid) as upid, 0 as utid from heap_graph_object
-    ) the_tracks
-    left join (select upid, sum(dur) as total_dur
-      from sched join thread using(utid)
-      group by upid
-    ) using(upid)
-    left join (select upid, sum(value) as total_cycles
-      from android_thread_time_in_state_event
-      group by upid
-    ) using(upid)
-    left join (
-      select
-        distinct(upid) as upid,
-        true as hasHeapProfiles
-      from heap_profile_allocation
-      union
-      select
-        distinct(upid) as upid,
-        true as hasHeapProfiles
-      from heap_graph_object
-    ) using (upid)
-    left join thread using(utid)
-    left join process using(upid)
-    order by
-      hasHeapProfiles desc,
-      total_dur desc,
-      total_cycles desc,
-      the_tracks.upid,
-      the_tracks.utid;
-  `);
-
-    const it = iter(
-        {
-          utid: NUM,
-          upid: NUM_NULL,
-          tid: NUM_NULL,
-          pid: NUM_NULL,
-          threadName: STR_NULL,
-          processName: STR_NULL,
-          hasSched: NUM_NULL,
-          hasHeapProfiles: NUM_NULL,
-        },
-        query);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      const row = it.row;
-      const utid = row.utid;
-      const tid = row.tid;
-      const upid = row.upid;
-      const pid = row.pid;
-      const threadName = row.threadName;
-      const processName = row.processName;
-      const hasSched = !!row.hasSched;
-      const hasHeapProfiles = !!row.hasHeapProfiles;
-
-      // Group by upid if present else by utid.
-      let pUuid =
-          upid === null ? this.utidToUuid.get(utid) : this.upidToUuid.get(upid);
-      // These should only happen once for each track group.
-      if (pUuid === undefined) {
-        pUuid = this.getOrCreateUuid(utid, upid);
-        const summaryTrackId = uuidv4();
-
-        const pidForColor = pid || tid || upid || utid || 0;
-        const kind =
-            hasSched ? PROCESS_SCHEDULING_TRACK_KIND : PROCESS_SUMMARY_TRACK;
-
-        this.tracksToAdd.push({
-          id: summaryTrackId,
-          engineId: this.engineId,
-          kind,
-          trackKindPriority: TrackDecider.inferTrackKindPriority(threadName),
-          name: `${upid === null ? tid : pid} summary`,
-          config: {pidForColor, upid, utid, tid},
-        });
-
-        const name = TrackDecider.getTrackName(
-            {utid, processName, pid, threadName, tid, upid});
-        const addTrackGroup = Actions.addTrackGroup({
-          engineId: this.engineId,
-          summaryTrackId,
-          name,
-          id: pUuid,
-          collapsed: !hasHeapProfiles,
-        });
-
-        this.addTrackGroupActions.push(addTrackGroup);
-      }
-    }
-  }
-
-  async decideTracks(): Promise<DeferredAction[]> {
-    // Add first the global tracks that don't require per-process track groups.
-    await this.addCpuSchedulingTracks();
-    await this.addCpuFreqTracks();
-    await this.addGlobalAsyncTracks();
-    await this.addGpuFreqTracks();
-    await this.addGlobalCounterTracks();
-    await this.groupGlobalIonTracks();
-
-    // Create the per-process track groups. Note that this won't necessarily
-    // create a track per process. If a process has been completely idle and has
-    // no sched events, no track group will be emitted.
-    // Will populate this.addTrackGroupActions
-    await this.addProcessTrackGroups();
-
-    await this.addProcessHeapProfileTracks();
-    await this.addProcessCounterTracks();
-    await this.addProcessAsyncSliceTracks();
-    await this.addActualFramesTracks();
-    await this.addExpectedFramesTracks();
-    await this.addThreadCounterTracks();
-    await this.addThreadStateTracks();
-    await this.addThreadSliceTracks();
-    await this.addThreadCpuSampleTracks();
-    await this.addLogsTrack();
-    await this.addAnnotationTracks();
-
-    this.addTrackGroupActions.push(
-        Actions.addTracks({tracks: this.tracksToAdd}));
-    return this.addTrackGroupActions;
-  }
-
-  private static inferTrackKindPriority(
-      threadName?: string|null, tid?: number|null,
-      pid?: number|null): TrackKindPriority {
-    if (pid !== undefined && pid !== null && pid === tid) {
-      return TrackKindPriority.MAIN_THREAD;
-    }
-    if (threadName === undefined || threadName === null) {
-      return TrackKindPriority.ORDINARY;
-    }
-
-    switch (true) {
-      case /.*RenderThread.*/.test(threadName):
-        return TrackKindPriority.RENDER_THREAD;
-      case /.*GPU completion.*/.test(threadName):
-        return TrackKindPriority.GPU_COMPLETION;
-      default:
-        return TrackKindPriority.ORDINARY;
-    }
-  }
-}
diff --git a/ui/src/controller/validate_config.ts b/ui/src/controller/validate_config.ts
deleted file mode 100644
index 015131f..0000000
--- a/ui/src/controller/validate_config.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {createEmptyRecordConfig, RecordConfig} from '../common/state';
-
-interface RecordConfigValidationResult {
-  config: RecordConfig;
-  errorMessage?: string;
-}
-
-export function validateRecordConfig(
-    config: {[key: string]: string|number|boolean|string[]|null}):
-    RecordConfigValidationResult {
-  // Remove the keys that are not in both createEmptyRecordConfig and
-  // config.
-  const newConfig: RecordConfig = createEmptyRecordConfig();
-  const ignoredKeys: string[] = [];
-  // TODO(bsebastien): Also check that types of properties match.
-  Object.entries(newConfig).forEach(([key, value]) => {
-    if (key in config && typeof value === typeof config[key]) {
-      newConfig[key] = config[key];
-    } else {
-      ignoredKeys.push(key);
-    }
-  });
-
-  // Check if config has additional keys that are not in
-  // createEmptyRecordConfig().
-  for (const key of Object.keys(config)) {
-    if (!(key in newConfig)) {
-      ignoredKeys.push(key);
-    }
-  }
-
-  if (ignoredKeys.length > 0) {
-    // At least return an empty RecordConfig if nothing match.
-    return {
-      errorMessage: 'Warning: Loaded config contains incompatible keys.\n\
-        It may have been created with an older version of the UI.\n\
-        Ignored keys: ' +
-          ignoredKeys.join(' '),
-      config: newConfig,
-    };
-  }
-  return {config: newConfig};
-}
diff --git a/ui/src/controller/validate_config_jsdomtest.ts b/ui/src/controller/validate_config_jsdomtest.ts
deleted file mode 100644
index 370d54a..0000000
--- a/ui/src/controller/validate_config_jsdomtest.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {createEmptyRecordConfig, RecordConfig} from '../common/state';
-import {validateRecordConfig} from './validate_config';
-
-test('validateRecordConfig test valid keys config', () => {
-  const config: RecordConfig = createEmptyRecordConfig();
-  const validationResult = validateRecordConfig(config);
-
-  expect('errorMessage' in validationResult).toEqual(false);
-
-  for (const key of Object.keys(validationResult.config)) {
-    expect(key in config).toEqual(true);
-  }
-});
-
-test('validateRecordConfig test no key config', () => {
-  const emptyRecord: RecordConfig = createEmptyRecordConfig();
-  const validationResult = validateRecordConfig({});
-
-  expect('errorMessage' in validationResult).toEqual(true);
-
-  for (const key of Object.keys(emptyRecord)) {
-    expect(key in validationResult.config).toEqual(true);
-  }
-});
-
-test('validateRecordConfig test some valid key config', () => {
-  const emptyRecord: RecordConfig = createEmptyRecordConfig();
-  const validationResult = validateRecordConfig({
-    'durationMs': 5.0,
-    'cpuSched': true,
-  });
-
-  expect('errorMessage' in validationResult).toEqual(true);
-
-  expect(validationResult.config.durationMs).toEqual(5.0);
-  expect(validationResult.config.cpuSched).toEqual(true);
-
-  for (const key of Object.keys(emptyRecord)) {
-    if (['durationMs', 'cpuSched'].includes(key) === false) {
-      expect(validationResult.config[key]).toEqual(emptyRecord[key]);
-    }
-    expect(key in validationResult.config).toEqual(true);
-  }
-});
-
-test('validateRecordConfig test some invalid key config', () => {
-  const emptyRecord: RecordConfig = createEmptyRecordConfig();
-  const validationResult = validateRecordConfig({
-    'durationMs': 5.0,
-    'invalidKey': 0,
-    'cpuSched': true,
-    'anotherInvalidKey': 'foobar',
-  });
-
-  expect('errorMessage' in validationResult).toEqual(true);
-
-  expect(validationResult.config.durationMs).toEqual(5.0);
-  expect(validationResult.config.cpuSched).toEqual(true);
-  expect('invalidKey' in validationResult.config).toEqual(false);
-  expect('anotherInvalidKey' in validationResult.config).toEqual(false);
-
-  for (const key of Object.keys(emptyRecord)) {
-    if (['durationMs', 'cpuSched'].includes(key) === false) {
-      expect(validationResult.config[key]).toEqual(emptyRecord[key]);
-    }
-    expect(key in validationResult.config).toEqual(true);
-  }
-});
-
-test('validateRecordConfig test only invalid key config', () => {
-  const emptyRecord: RecordConfig = createEmptyRecordConfig();
-  const validationResult = validateRecordConfig({
-    'invalidKey': 0,
-    'anotherInvalidKey': 'foobar',
-  });
-
-  expect('errorMessage' in validationResult).toEqual(true);
-
-  expect('invalidKey' in validationResult.config).toEqual(false);
-  expect('anotherInvalidKey' in validationResult.config).toEqual(false);
-
-  for (const key of Object.keys(emptyRecord)) {
-    expect(validationResult.config[key]).toEqual(emptyRecord[key]);
-    expect(key in validationResult.config).toEqual(true);
-  }
-});
diff --git a/ui/src/engine/wasm_bridge.ts b/ui/src/engine/wasm_bridge.ts
index fe896b1..97a3692 100644
--- a/ui/src/engine/wasm_bridge.ts
+++ b/ui/src/engine/wasm_bridge.ts
@@ -23,6 +23,10 @@
 // HEAPU8[reqBufferAddr, +REQ_BUFFER_SIZE].
 const REQ_BUF_SIZE = 32 * 1024 * 1024;
 
+function writeToUIConsole(line: string) {
+  console.log(line);
+}
+
 export interface WasmBridgeRequest {
   id: number;
   methodName: string;
@@ -31,6 +35,7 @@
 
 export interface WasmBridgeResponse {
   id: number;
+  aborted: boolean;  // If true the WASM module crashed.
   data: Uint8Array;
 }
 
@@ -42,7 +47,6 @@
   private currentRequestResult: WasmBridgeResponse|null;
   private connection: init_trace_processor.Module;
   private reqBufferAddr = 0;
-  private lastStderr: string[] = [];
 
   constructor(init: init_trace_processor.InitWasm) {
     this.aborted = false;
@@ -51,12 +55,13 @@
     const deferredRuntimeInitialized = defer<void>();
     this.connection = init({
       locateFile: (s: string) => s,
-      print: (line: string) => console.log(line),
-      printErr: (line: string) => this.appendAndLogErr(line),
+      print: writeToUIConsole,
+      printErr: writeToUIConsole,
       onRuntimeInitialized: () => deferredRuntimeInitialized.resolve(),
+      onAbort: () => this.aborted = true,
     });
     this.whenInitialized = deferredRuntimeInitialized.then(() => {
-      const fn = this.connection.addFunction(this.onReply.bind(this), 'vii');
+      const fn = this.connection.addFunction(this.onReply.bind(this), 'iii');
       this.reqBufferAddr = this.connection.ccall(
           'Initialize',
           /*return=*/ 'number',
@@ -67,31 +72,26 @@
 
   callWasm(req: WasmBridgeRequest): WasmBridgeResponse {
     if (this.aborted) {
-      throw new Error('Wasm module crashed');
+      return {
+        id: req.id,
+        aborted: true,
+        data: new Uint8Array(),
+      };
     }
     assertTrue(req.data.length <= REQ_BUF_SIZE);
     const endAddr = this.reqBufferAddr + req.data.length;
     this.connection.HEAPU8.subarray(this.reqBufferAddr, endAddr).set(req.data);
-    try {
-      this.connection.ccall(
-          req.methodName,    // C method name.
-          'void',            // Return type.
-          ['number'],        // Arg types.
-          [req.data.length]  // Args.
-      );
-      const result = assertExists(this.currentRequestResult);
-      this.currentRequestResult = null;
-      result.id = req.id;
-      return result;
-    } catch (err) {
-      this.aborted = true;
-      let abortReason = `${err}`;
-      if (err instanceof Error) {
-        abortReason = `${err.name}: ${err.message}\n${err.stack}`;
-      }
-      abortReason += '\n\nstderr: \n' + this.lastStderr.join('\n');
-      throw new Error(abortReason);
-    }
+    this.connection.ccall(
+        req.methodName,    // C method name.
+        'void',            // Return type.
+        ['number'],        // Arg types.
+        [req.data.length]  // Args.
+    );
+
+    const result = assertExists(this.currentRequestResult);
+    this.currentRequestResult = null;
+    result.id = req.id;
+    return result;
   }
 
   // This is invoked from ccall in the same call stack as callWasm.
@@ -99,16 +99,8 @@
     const data = this.connection.HEAPU8.slice(heapPtr, heapPtr + size);
     this.currentRequestResult = {
       id: 0,  // Will be set by callWasm()'s epilogue.
+      aborted: false,
       data,
     };
   }
-
-  private appendAndLogErr(line: string) {
-    console.warn(line);
-    // Keep the last N lines in the |lastStderr| buffer.
-    this.lastStderr.push(line);
-    if (this.lastStderr.length > 512) {
-      this.lastStderr.shift();
-    }
-  }
 }
diff --git a/ui/src/frontend/aggregation_panel.ts b/ui/src/frontend/aggregation_panel.ts
index 409fda2..fdcea94 100644
--- a/ui/src/frontend/aggregation_panel.ts
+++ b/ui/src/frontend/aggregation_panel.ts
@@ -15,12 +15,7 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
-import {
-  AggregateData,
-  Column,
-  ThreadStateExtra
-} from '../common/aggregation_data';
-import {colorForState, textColorForState} from '../common/colorizer';
+import {AggregateData, Column} from '../common/aggregation_data';
 import {translateState} from '../common/thread_state';
 
 import {globals} from './globals';
@@ -36,19 +31,10 @@
     return m(
         '.details-panel',
         m('.details-panel-heading.aggregation',
-          attrs.data.extra !== undefined &&
-                  attrs.data.extra.kind === 'THREAD_STATE' ?
-              this.showStateSummary(attrs.data.extra) :
-              null,
-          this.showTimeRange(),
           m('table',
             m('tr',
               attrs.data.columns.map(
-                  col => this.formatColumnHeading(col, attrs.kind))),
-            m('tr.sum', attrs.data.columnSums.map(sum => {
-              const sumClass = sum === '' ? 'td' : 'td.sum-data';
-              return m(sumClass, sum);
-            })))),
+                  col => this.formatColumnHeading(col, attrs.kind))))),
         m(
             '.details-table.aggregation',
             m('table', this.getRows(attrs.data)),
@@ -90,52 +76,17 @@
   getFormattedData(data: AggregateData, rowIndex: number, columnIndex: number) {
     switch (data.columns[columnIndex].kind) {
       case 'STRING':
-        return data.strings[data.columns[columnIndex].data[rowIndex]];
+        return `${data.strings[data.columns[columnIndex].data[rowIndex]]}`;
       case 'TIMESTAMP_NS':
         return `${data.columns[columnIndex].data[rowIndex] / 1000000}`;
-      case 'STATE': {
-        const concatState =
-            data.strings[data.columns[columnIndex].data[rowIndex]];
-        const split = concatState.split(',');
-        const ioWait =
-            split[1] === 'NULL' ? undefined : !!Number.parseInt(split[1], 10);
-        return translateState(split[0], ioWait);
-      }
+      case 'STATE':
+        return translateState(
+            `${data.strings[data.columns[columnIndex].data[rowIndex]]}`);
       case 'NUMBER':
       default:
-        return data.columns[columnIndex].data[rowIndex];
+        return `${data.columns[columnIndex].data[rowIndex]}`;
     }
   }
 
-  showTimeRange() {
-    const selection = globals.state.currentSelection;
-    if (selection === null || selection.kind !== 'AREA') return undefined;
-    const selectedArea = globals.state.areas[selection.areaId];
-    const rangeDurationMs = (selectedArea.endSec - selectedArea.startSec) * 1e3;
-    return m('.time-range', `Selected range: ${rangeDurationMs.toFixed(6)} ms`);
-  }
-
-  // Thread state aggregation panel only
-  showStateSummary(data: ThreadStateExtra) {
-    if (data === undefined) return undefined;
-    const states = [];
-    for (let i = 0; i < data.states.length; i++) {
-      const color = colorForState(data.states[i]);
-      const textColor = textColorForState(data.states[i]);
-      const width = data.values[i] / data.totalMs * 100;
-      states.push(
-          m('.state',
-            {
-              style: {
-                background: `hsl(${color.h},${color.s}%,${color.l}%)`,
-                color: `${textColor}`,
-                width: `${width}%`
-              }
-            },
-            `${data.states[i]}: ${data.values[i]} ms`));
-    }
-    return m('.states', states);
-  }
-
   renderCanvas() {}
 }
\ No newline at end of file
diff --git a/ui/src/frontend/analytics.ts b/ui/src/frontend/analytics.ts
deleted file mode 100644
index 076ed48..0000000
--- a/ui/src/frontend/analytics.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {globals} from '../frontend/globals';
-import * as version from '../gen/perfetto_version';
-
-type TraceCategories = 'Trace Actions'|'Record Trace'|'User Actions';
-const ANALYTICS_ID = 'UA-137828855-1';
-const PAGE_TITLE = 'no-page-title';
-
-export function initAnalytics() {
-  // Only initialize logging on prod or staging
-  if (window.location.origin.startsWith('http://localhost:') ||
-      window.location.origin.endsWith('.perfetto.dev') ||
-      window.location.origin.endsWith('staging-dot-perfetto-ui.appspot.com')) {
-    return new AnalyticsImpl();
-  }
-  return new NullAnalytics();
-}
-
-const gtagGlobals = window as {} as {
-  // tslint:disable-next-line no-any
-  dataLayer: any[];
-  gtag: (command: string, event: string|Date, args?: {}) => void;
-};
-
-export interface Analytics {
-  initialize(): void;
-  updatePath(_: string): void;
-  logEvent(_x: TraceCategories|null, _y: string): void;
-  logError(_x: string, _y?: boolean): void;
-}
-
-export class NullAnalytics implements Analytics {
-  initialize() {}
-  updatePath(_: string) {}
-  logEvent(_x: TraceCategories|null, _y: string) {}
-  logError(_x: string) {}
-}
-
-class AnalyticsImpl implements Analytics {
-  private initialized_ = false;
-
-  constructor() {
-    // The code below is taken from the official Google Analytics docs [1] and
-    // adapted to TypeScript. We have it here rather than as an inline script
-    // in index.html (as suggested by GA's docs) because inline scripts don't
-    // play nicely with the CSP policy, at least in Firefox (Firefox doesn't
-    // support all CSP 3 features we use).
-    // [1] https://developers.google.com/analytics/devguides/collection/gtagjs .
-    gtagGlobals.dataLayer = gtagGlobals.dataLayer || [];
-
-    // tslint:disable-next-line no-any
-    function gtagFunction(..._: any[]) {
-      // This needs to be a function and not a lambda. |arguments| behaves
-      // slightly differently in a lambda and breaks GA.
-      gtagGlobals.dataLayer.push(arguments);
-    }
-    gtagGlobals.gtag = gtagFunction;
-    gtagGlobals.gtag('js', new Date());
-  }
-
-  // This is callled only after the script that sets isInternalUser loads.
-  // It is fine to call updatePath() and log*() functions before initialize().
-  // The gtag() function internally enqueues all requests into |dataLayer|.
-  initialize() {
-    if (this.initialized_) return;
-    this.initialized_ = true;
-    const script = document.createElement('script');
-    script.src = 'https://www.googletagmanager.com/gtag/js?id=' + ANALYTICS_ID;
-    script.defer = true;
-    document.head.appendChild(script);
-    const route = globals.state.route || '/';
-    console.log(
-        `GA initialized. route=${route}`,
-        `isInternalUser=${globals.isInternalUser}`);
-    // GA's reccomendation for SPAs is to disable automatic page views and
-    // manually send page_view events. See:
-    // https://developers.google.com/analytics/devguides/collection/gtagjs/pages#manual_pageviews
-    gtagGlobals.gtag('config', ANALYTICS_ID, {
-      allow_google_signals: false,
-      anonymize_ip: true,
-      page_path: route,
-      referrer: document.referrer.split('?')[0],
-      send_page_view: false,
-      page_title: PAGE_TITLE,
-      dimension1: globals.isInternalUser ? '1' : '0',
-      dimension2: version.VERSION,
-      dimension3: globals.channel,
-    });
-    this.updatePath(route);
-  }
-
-  updatePath(path: string) {
-    gtagGlobals.gtag(
-        'event', 'page_view', {page_path: path, page_title: PAGE_TITLE});
-  }
-
-  logEvent(category: TraceCategories|null, event: string) {
-    gtagGlobals.gtag('event', event, {event_category: category});
-  }
-
-  logError(description: string, fatal = true) {
-    gtagGlobals.gtag('event', 'exception', {description, fatal});
-  }
-}
diff --git a/ui/src/frontend/android_bug_tool.ts b/ui/src/frontend/android_bug_tool.ts
deleted file mode 100644
index ff63f58..0000000
--- a/ui/src/frontend/android_bug_tool.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import {defer} from '../base/deferred';
-
-enum WebContentScriptMessageType {
-  UNKNOWN,
-  CONVERT_OBJECT_URL,
-  CONVERT_OBJECT_URL_RESPONSE,
-}
-
-const ANDROID_BUG_TOOL_EXTENSION_ID = 'mbbaofdfoekifkfpgehgffcpagbbjkmj';
-
-interface Attachment {
-  name: string;
-  objectUrl: string;
-  restrictionSeverity: number;
-}
-
-interface ConvertObjectUrlResponse {
-  action: WebContentScriptMessageType.CONVERT_OBJECT_URL_RESPONSE;
-  attachments: Attachment[];
-  issueAccessLevel: string;
-  issueId: string;
-  issueTitle: string;
-}
-
-export interface TraceFromBuganizer {
-  issueId: string;
-  issueTitle: string;
-  file: File;
-}
-
-export function loadAndroidBugToolInfo(): Promise<TraceFromBuganizer> {
-  const deferred = defer<TraceFromBuganizer>();
-
-  // Request to convert the blob object url "blob:chrome-extension://xxx"
-  // the chrome extension has to a web downloadable url "blob:http://xxx".
-  chrome.runtime.sendMessage(
-      ANDROID_BUG_TOOL_EXTENSION_ID,
-      {action: WebContentScriptMessageType.CONVERT_OBJECT_URL},
-      async (response: ConvertObjectUrlResponse) => {
-        switch (response.action) {
-          case WebContentScriptMessageType.CONVERT_OBJECT_URL_RESPONSE:
-          if (response.attachments?.length > 0) {
-            const filesBlobPromises =
-                response.attachments.map(async attachment => {
-                  const fileQueryResponse = await fetch(attachment.objectUrl);
-                  const blob = await fileQueryResponse.blob();
-                  // Note: The blob's media type is always set to "image/png".
-                  // Clone blob to clear media type.
-                  return new File([blob], attachment.name);
-                });
-            const files = await Promise.all(filesBlobPromises);
-            deferred.resolve({
-              issueId: response.issueId,
-              issueTitle: response.issueTitle,
-              file: files[0],
-            });
-          } else {
-            throw new Error('Got no attachements from extension');
-          }
-          break;
-          default:
-            throw new Error(`Received unhandled response code (${
-                response.action}) from extension.`);
-        }
-      });
-  return deferred;
-}
diff --git a/ui/src/frontend/chrome_slice_panel.ts b/ui/src/frontend/chrome_slice_panel.ts
index 0a6c31f..f211cb7 100644
--- a/ui/src/frontend/chrome_slice_panel.ts
+++ b/ui/src/frontend/chrome_slice_panel.ts
@@ -15,138 +15,44 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
-import {Arg, ArgsTree, isArgTreeArray, isArgTreeMap} from '../common/arg_types';
 import {timeToCode, toNs} from '../common/time';
 
-import {globals, SliceDetails} from './globals';
+import {Args, globals} from './globals';
 import {Panel, PanelSize} from './panel';
 import {verticalScrollToTrack} from './scroll_helper';
 
-// Table row contents is one of two things:
-// 1. Key-value pair
-interface KVPair {
-  kind: 'KVPair';
-  key: string;
-  value: Arg;
-}
-
-// 2. Common prefix for values in an array
-interface TableHeader {
-  kind: 'TableHeader';
-  header: string;
-}
-
-type RowContents = KVPair|TableHeader;
-
-function isTableHeader(contents: RowContents): contents is TableHeader {
-  return contents.kind === 'TableHeader';
-}
-
-interface Row {
-  // How many columns (empty or with an index) precede a key
-  indentLevel: number;
-  // Index if the current row is an element of array
-  index: number;
-  contents: RowContents;
-}
-
-class TableBuilder {
-  // Stack contains indices inside repeated fields, or -1 if the appropriate
-  // index is already displayed.
-  stack: number[] = [];
-
-  // Row data generated by builder
-  rows: Row[] = [];
-
-  // Maximum indent level of a key, used to determine total number of columns
-  maxIndent = 0;
-
-  // Add a key-value pair into the table
-  add(key: string, value: Arg) {
-    this.rows.push(
-        {indentLevel: 0, index: -1, contents: {kind: 'KVPair', key, value}});
-  }
-
-  // Add arguments tree into the table
-  addTree(tree: ArgsTree) {
-    this.addTreeInternal(tree, '');
-  }
-
-  // Return indent level and index for a fresh row
-  private prepareRow(): [number, number] {
-    const level = this.stack.length;
-    let index = -1;
-    if (level > 0) {
-      index = this.stack[level - 1];
-      if (index !== -1) {
-        this.stack[level - 1] = -1;
-      }
-    }
-    this.maxIndent = Math.max(this.maxIndent, level);
-    return [level, index];
-  }
-
-  private addTreeInternal(record: ArgsTree, prefix: string) {
-    if (isArgTreeArray(record)) {
-      // Add the current prefix as a separate row
-      const row = this.prepareRow();
-      this.rows.push({
-        indentLevel: row[0],
-        index: row[1],
-        contents: {kind: 'TableHeader', header: prefix}
-      });
-
-      for (let i = 0; i < record.length; i++) {
-        // Push the current array index to the stack.
-        this.stack.push(i);
-        // Prefix is empty for array elements because we don't want to repeat
-        // the common prefix
-        this.addTreeInternal(record[i], '');
-        this.stack.pop();
-      }
-    } else if (isArgTreeMap(record)) {
-      for (const [key, value] of Object.entries(record)) {
-        // If the prefix was non-empty, we have to add dot at the end as well.
-        const newPrefix = (prefix === '') ? key : prefix + '.' + key;
-        this.addTreeInternal(value, newPrefix);
-      }
-    } else {
-      // Leaf value in the tree: add to the table
-      const row = this.prepareRow();
-      this.rows.push({
-        indentLevel: row[0],
-        index: row[1],
-        contents: {kind: 'KVPair', key: prefix, value: record}
-      });
-    }
-  }
-}
-
 export class ChromeSliceDetailsPanel extends Panel {
   view() {
     const sliceInfo = globals.sliceDetails;
     if (sliceInfo.ts !== undefined && sliceInfo.dur !== undefined &&
         sliceInfo.name !== undefined) {
-      const builder = new TableBuilder();
-      builder.add('Name', sliceInfo.name);
-      builder.add(
-          'Category',
-          !sliceInfo.category || sliceInfo.category === '[NULL]' ?
-              'N/A' :
-              sliceInfo.category);
-      builder.add('Start time', timeToCode(sliceInfo.ts));
-      builder.add(
-          'Duration',
-          toNs(sliceInfo.dur) === -1 ? '-1 (Did not end)' :
-                                       timeToCode(sliceInfo.dur));
-      if (sliceInfo.description) {
-        this.fillDescription(sliceInfo.description, builder);
-      }
-      this.fillArgs(sliceInfo, builder);
       return m(
           '.details-panel',
           m('.details-panel-heading', m('h2', `Slice Details`)),
-          m('.details-table', this.renderTable(builder)));
+          m(
+              '.details-table',
+              m('table.half-width',
+                m('tr', m('th', `Name`), m('td', `${sliceInfo.name}`)),
+                m('tr',
+                  m('th', `Category`),
+                  m('td',
+                    `${
+                        sliceInfo.category === '[NULL]' ?
+                            'N/A' :
+                            sliceInfo.category}`)),
+                m('tr',
+                  m('th', `Start time`),
+                  m('td', `${timeToCode(sliceInfo.ts)}`)),
+                m('tr',
+                  m('th', `Duration`),
+                  m('td',
+                    `${
+                        toNs(sliceInfo.dur) === -1 ?
+                            '-1 (Did not end)' :
+                            timeToCode(sliceInfo.dur)}`)),
+                this.getDescription(sliceInfo.description),
+                this.getArgs(sliceInfo.args)),
+              ));
     } else {
       return m(
           '.details-panel',
@@ -160,87 +66,45 @@
 
   renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
 
-  fillArgs(slice: SliceDetails, builder: TableBuilder) {
-    if (slice.argsTree && slice.args) {
-      // Parsed arguments are available, need only to iterate over them to get
-      // slice references
-      for (const [key, value] of slice.args) {
-        if (typeof value !== 'string') {
-          builder.add(key, value);
-        }
-      }
-      builder.addTree(slice.argsTree);
-    } else if (slice.args) {
-      // Parsing has failed, but arguments are available: display them in a flat
-      // 2-column table
-      for (const [key, value] of slice.args) {
-        builder.add(key, value);
-      }
-    }
-  }
-
-  renderTable(builder: TableBuilder): m.Vnode {
-    const rows: m.Vnode[] = [];
-    const keyColumnCount = builder.maxIndent + 1;
-    for (const row of builder.rows) {
-      const renderedRow: m.Vnode[] = [];
-      let indent = row.indentLevel;
-      if (row.index !== -1) {
-        indent--;
-      }
-
-      if (indent > 0) {
-        renderedRow.push(m('td', {colspan: indent}));
-      }
-      if (row.index !== -1) {
-        renderedRow.push(m('td', {class: 'array-index'}, `[${row.index}]`));
-      }
-      if (isTableHeader(row.contents)) {
-        renderedRow.push(
-            m('th',
-              {colspan: keyColumnCount + 1 - row.indentLevel},
-              row.contents.header));
+  getArgs(args?: Args): m.Vnode[] {
+    if (!args || args.size === 0) return [];
+    const result = [];
+    for (const [key, value] of args) {
+      if (typeof value === 'string') {
+        result.push(m('tr', m('th', key), m('td', value)));
       } else {
-        renderedRow.push(
-            m('th',
-              {colspan: keyColumnCount - row.indentLevel},
-              row.contents.key));
-        const value = row.contents.value;
-        if (typeof value === 'string') {
-          renderedRow.push(m('td', value));
-        } else {
-          // Type of value being a record is not propagated into the callback
-          // for some reason, extracting necessary parts as constants instead.
-          const sliceId = value.sliceId;
-          const trackId = value.trackId;
-          renderedRow.push(
+        result.unshift(
+            m('tr',
+              m('th', key),
               m('td',
                 m('i.material-icons.grey',
                   {
                     onclick: () => {
-                      globals.makeSelection(Actions.selectChromeSlice(
-                          {id: sliceId, trackId, table: 'slice'}));
+                      globals.makeSelection(Actions.selectChromeSlice({
+                        id: value.sliceId,
+                        trackId: value.trackId,
+                        table: 'slice'
+                      }));
                       // Ideally we want to have a callback to
                       // findCurrentSelection after this selection has been
                       // made. Here we do not have the info for horizontally
                       // scrolling to ts.
-                      verticalScrollToTrack(trackId, true);
+                      verticalScrollToTrack(value.trackId, true);
                     },
                     title: 'Go to destination slice'
                   },
-                  'call_made')));
-        }
+                  'call_made'))));
       }
-
-      rows.push(m('tr', renderedRow));
     }
-
-    return m('table.half-width', rows);
+    return result;
   }
 
-  fillDescription(description: Map<string, string>, builder: TableBuilder) {
+  getDescription(description?: Map<string, string>): m.Vnode[] {
+    if (!description) return [];
+    const result = [];
     for (const [key, value] of description) {
-      builder.add(key, value);
+      result.push(m('tr', m('th', key), m('td', value)));
     }
+    return result;
   }
 }
diff --git a/ui/src/frontend/colorizer.ts b/ui/src/frontend/colorizer.ts
new file mode 100644
index 0000000..60d7038
--- /dev/null
+++ b/ui/src/frontend/colorizer.ts
@@ -0,0 +1,131 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {hsl} from 'color-convert';
+import {translateState} from '../common/thread_state';
+import {ThreadDesc} from './globals';
+
+export interface Color {
+  c: string;
+  h: number;
+  s: number;
+  l: number;
+  a?: number;
+}
+
+const MD_PALETTE: Color[] = [
+  {c: 'red', h: 4, s: 90, l: 58},
+  {c: 'pink', h: 340, s: 82, l: 52},
+  {c: 'purple', h: 291, s: 64, l: 42},
+  {c: 'deep purple', h: 262, s: 52, l: 47},
+  {c: 'indigo', h: 231, s: 48, l: 48},
+  {c: 'blue', h: 207, s: 90, l: 54},
+  {c: 'light blue', h: 199, s: 98, l: 48},
+  {c: 'cyan', h: 187, s: 100, l: 42},
+  {c: 'teal', h: 174, s: 100, l: 29},
+  {c: 'green', h: 122, s: 39, l: 49},
+  {c: 'light green', h: 88, s: 50, l: 53},
+  {c: 'lime', h: 66, s: 70, l: 54},
+  {c: 'amber', h: 45, s: 100, l: 51},
+  {c: 'orange', h: 36, s: 100, l: 50},
+  {c: 'deep orange', h: 14, s: 100, l: 57},
+  {c: 'brown', h: 16, s: 25, l: 38},
+  {c: 'blue gray', h: 200, s: 18, l: 46},
+  {c: 'yellow', h: 54, s: 100, l: 62},
+];
+
+const GREY_COLOR: Color = {
+  c: 'grey',
+  h: 0,
+  s: 0,
+  l: 62
+};
+
+function hash(s: string, max: number): number {
+  let hash = 0x811c9dc5 & 0xfffffff;
+  for (let i = 0; i < s.length; i++) {
+    hash ^= s.charCodeAt(i);
+    hash = (hash * 16777619) & 0xffffffff;
+  }
+  return Math.abs(hash) % max;
+}
+
+export function hueForCpu(cpu: number): number {
+  return (128 + (32 * cpu)) % 256;
+}
+
+const DARK_GREEN: Color = {
+  c: 'dark green',
+  h: 120,
+  s: 44,
+  l: 34
+};
+const LIME_GREEN: Color = {
+  c: 'lime green',
+  h: 75,
+  s: 55,
+  l: 47
+};
+const TRANSPARENT_WHITE: Color = {
+  c: 'white',
+  h: 0,
+  s: 1,
+  l: 97,
+  a: 0.55,
+};
+const ORANGE: Color = {
+  c: 'orange',
+  h: 36,
+  s: 100,
+  l: 50
+};
+const INDIGO: Color = {
+  c: 'indigo',
+  h: 231,
+  s: 48,
+  l: 48
+};
+
+export function colorForState(stateCode: string): Readonly<Color> {
+  const state = translateState(stateCode);
+  if (state === 'Running') {
+    return DARK_GREEN;
+  } else if (state.startsWith('Runnable')) {
+    return LIME_GREEN;
+  } else if (state.includes('Uninterruptible Sleep')) {
+    return ORANGE;
+  } else if (state.includes('Sleeping')) {
+    return TRANSPARENT_WHITE;
+  }
+  return INDIGO;
+}
+
+export function colorForTid(tid: number): Color {
+  const colorIdx = hash(tid.toString(), MD_PALETTE.length);
+  return Object.assign({}, MD_PALETTE[colorIdx]);
+}
+
+export function colorForThread(thread: ThreadDesc|undefined): Color {
+  if (thread === undefined) {
+    return Object.assign({}, GREY_COLOR);
+  }
+  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/colorizer_unittest.ts b/ui/src/frontend/colorizer_unittest.ts
new file mode 100644
index 0000000..265bb38
--- /dev/null
+++ b/ui/src/frontend/colorizer_unittest.ts
@@ -0,0 +1,76 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {colorForThread, hueForCpu} from './colorizer';
+import {ThreadDesc} from './globals';
+
+const PROCESS_A_THREAD_A: ThreadDesc = {
+  utid: 1,
+  tid: 100,
+  threadName: 'threadA',
+  pid: 100,
+  procName: 'procA',
+};
+
+const PROCESS_A_THREAD_B: ThreadDesc = {
+  utid: 2,
+  tid: 101,
+  threadName: 'threadB',
+  pid: 100,
+  procName: 'procA',
+};
+
+const PROCESS_B_THREAD_A: ThreadDesc = {
+  utid: 3,
+  tid: 200,
+  threadName: 'threadA',
+  pid: 200,
+  procName: 'procB',
+};
+
+const PROCESS_UNK_THREAD_A: ThreadDesc = {
+  utid: 4,
+  tid: 42,
+  threadName: 'unkThreadA',
+};
+
+const PROCESS_UNK_THREAD_B: ThreadDesc = {
+  utid: 5,
+  tid: 42,
+  threadName: 'unkThreadB',
+};
+
+test('it gives threads colors by pid if present', () => {
+  const colorAA = colorForThread(PROCESS_A_THREAD_A);
+  const colorAB = colorForThread(PROCESS_A_THREAD_B);
+  const colorBA = colorForThread(PROCESS_B_THREAD_A);
+  expect(colorAA).toEqual(colorAB);
+  expect(colorAA).not.toEqual(colorBA);
+});
+
+test('it gives threads colors by tid if pid missing', () => {
+  const colorUnkA = colorForThread(PROCESS_UNK_THREAD_A);
+  const colorUnkB = colorForThread(PROCESS_UNK_THREAD_B);
+  expect(colorUnkA).toEqual(colorUnkB);
+});
+
+test('it copies colors', () => {
+  const a = colorForThread(PROCESS_A_THREAD_A);
+  const b = colorForThread(PROCESS_A_THREAD_A);
+  expect(a === b).toEqual(false);
+});
+
+test('it gives different cpus different hues', () => {
+  expect(hueForCpu(0)).not.toEqual(hueForCpu(1));
+});
diff --git a/ui/src/frontend/cookie_consent.ts b/ui/src/frontend/cookie_consent.ts
deleted file mode 100644
index 3ea5ecf..0000000
--- a/ui/src/frontend/cookie_consent.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import * as m from 'mithril';
-
-import {globals} from './globals';
-
-const COOKIE_ACK_KEY = 'cookieAck';
-
-export class CookieConsent implements m.ClassComponent {
-  private showCookieConsent = true;
-
-  view() {
-    if (this.showCookieConsent) {
-      this.showCookieConsent = localStorage.getItem(COOKIE_ACK_KEY) === null;
-    }
-    if (!this.showCookieConsent) return;
-    return m(
-        '.cookie-consent',
-        m('.cookie-text',
-          `This site uses cookies from Google to deliver its services and to
-          analyze traffic.`),
-        m('.buttons',
-          m('button',
-            m('a',
-              {
-                href: 'https://policies.google.com/technologies/cookies',
-                target: '_blank'
-              },
-              'More details')),
-          m('button',
-            {
-              onclick: () => {
-                this.showCookieConsent = false;
-                localStorage.setItem(COOKIE_ACK_KEY, 'true');
-                globals.rafScheduler.scheduleFullRedraw();
-              }
-            },
-            'OK')),
-    );
-  }
-}
diff --git a/ui/src/frontend/cpu_profile_panel.ts b/ui/src/frontend/cpu_profile_panel.ts
index 6bd873d..0ccf69c 100644
--- a/ui/src/frontend/cpu_profile_panel.ts
+++ b/ui/src/frontend/cpu_profile_panel.ts
@@ -25,7 +25,7 @@
     const sampleDetails = globals.cpuProfileDetails;
     const header =
         m('.details-panel-heading', m('h2', `CPU Profile Sample Details`));
-    if (!sampleDetails || sampleDetails.id === undefined) {
+    if (!sampleDetails || !sampleDetails.id) {
       return m('.details-panel', header);
     }
 
diff --git a/ui/src/frontend/css_constants.ts b/ui/src/frontend/css_constants.ts
index 5ecaa93..a443306 100644
--- a/ui/src/frontend/css_constants.ts
+++ b/ui/src/frontend/css_constants.ts
@@ -12,31 +12,34 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// This code can be used in unittests where we can't read CSS variables.
-// Also we cannot have global constructors beacause when the javascript is
-// loaded, the CSS might not be ready yet.
-export let TRACK_SHELL_WIDTH = 100;
-export let SIDEBAR_WIDTH = 100;
-export let TRACK_BORDER_COLOR = '#ffc0cb';
-export let TOPBAR_HEIGHT = 48;
-
-export function initCssConstants() {
-  TRACK_SHELL_WIDTH = getCssNum('--track-shell-width') || TRACK_SHELL_WIDTH;
-  SIDEBAR_WIDTH = getCssNum('--sidebar-width') || SIDEBAR_WIDTH;
-  TRACK_BORDER_COLOR = getCssStr('--track-border-color') || TRACK_BORDER_COLOR;
-  TOPBAR_HEIGHT = getCssNum('--topbar-height') || TOPBAR_HEIGHT;
+function readCssVarSlow(prop: string, defaultValue: string): string {
+  // This code can be used in unittests where we can't read CSS variables.
+  if (typeof window === 'undefined') {
+    return defaultValue;
+  } else {
+    const body = window.document.body;
+    return window.getComputedStyle(body).getPropertyValue(prop);
+  }
 }
 
-function getCssStr(prop: string): string|undefined {
-  if (typeof window === 'undefined') return undefined;
-  const body = window.document.body;
-  return window.getComputedStyle(body).getPropertyValue(prop);
-}
-
-function getCssNum(prop: string): number|undefined {
-  const str = getCssStr(prop);
-  if (str === undefined) return undefined;
-  const match = str.match(/^\W*(\d+)px$/);
-  if (!match) throw Error(`Could not parse CSS property "${str}" as a number`);
+function getTrackShellWidth(): number {
+  const width = readCssVarSlow('--track-shell-width', '100px');
+  const match = width.match(/^\W*(\d+)px$/);
+  if (!match) throw Error(`Could not parse shell width as number (${width})`);
   return Number(match[1]);
 }
+
+function getTrackBorderColor(): string {
+  return readCssVarSlow('--track-border-color', '#ffc0cb');
+}
+
+function getTopbarHeight(): number {
+  const width = readCssVarSlow('--topbar-height', '48px');
+  const match = width.match(/^\W*(\d+)px$/);
+  if (!match) throw Error(`Could not parse topbar height as number (${width})`);
+  return Number(match[1]);
+}
+
+export const TRACK_SHELL_WIDTH = getTrackShellWidth();
+export const TRACK_BORDER_COLOR = getTrackBorderColor();
+export const TOPBAR_HEIGHT = getTopbarHeight();
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 9332c00..32ddab0 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 import * as m from 'mithril';
-import {QueryResponse} from 'src/common/queries';
 
 import {LogExists, LogExistsKey} from '../common/logs';
 
@@ -22,16 +21,11 @@
 import {CounterDetailsPanel} from './counter_panel';
 import {CpuProfileDetailsPanel} from './cpu_profile_panel';
 import {DragGestureHandler} from './drag_gesture_handler';
-import {
-  FlowEventsAreaSelectedPanel,
-  FlowEventsPanel
-} from './flow_events_panel';
 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 {QueryTable} from './query_table';
 import {SliceDetailsPanel} from './slice_panel';
 import {ThreadStatePanel} from './thread_state_panel';
 
@@ -55,15 +49,10 @@
   return data && data.exists;
 }
 
-interface Tab {
-  key: string;
-  name: string;
-}
-
 interface DragHandleAttrs {
   height: number;
   resize: (height: number) => void;
-  tabs: Tab[];
+  tabs: string[];
 }
 
 class DragHandle implements m.ClassComponent<DragHandleAttrs> {
@@ -75,6 +64,11 @@
   private isFullscreen = false;
   // We can't get real fullscreen height until the pan_and_zoom_handler exists.
   private fullscreenHeight = DEFAULT_DETAILS_HEIGHT_PX;
+  private tabNames = new Map<string, string>([
+    ['current_selection', 'Current Selection'],
+    ['android_logs', 'Android Logs'],
+  ]);
+
 
   oncreate({dom, attrs}: m.CVnodeDOM<DragHandleAttrs>) {
     this.resize = attrs.resize;
@@ -113,29 +107,24 @@
   view({attrs}: m.CVnode<DragHandleAttrs>) {
     const icon = this.isClosed ? UP_ICON : DOWN_ICON;
     const title = this.isClosed ? 'Show panel' : 'Hide panel';
-    const activeTabExists = globals.frontendLocalState.currentTab &&
-        attrs.tabs.map(tab => tab.key)
-            .includes(globals.frontendLocalState.currentTab);
-    if (!activeTabExists) {
-      globals.frontendLocalState.currentTab = undefined;
-    }
-    const renderTab = (tab: Tab) => {
-      if (globals.frontendLocalState.currentTab === tab.key ||
+    const renderTab = (key: string) => {
+      if (globals.frontendLocalState.currentTab === key ||
           globals.frontendLocalState.currentTab === undefined &&
-              attrs.tabs.keys().next().value === tab.key) {
-        // Update currentTab in case we didn't have one before.
-        globals.frontendLocalState.currentTab = tab.key;
-        return m('.tab[active]', tab.name);
+              attrs.tabs[0] === key) {
+        return m(
+            '.tab[active]',
+            this.tabNames.get(key) === undefined ? key :
+                                                   this.tabNames.get(key));
       }
       return m(
           '.tab',
           {
             onclick: () => {
-              globals.frontendLocalState.currentTab = tab.key;
+              globals.frontendLocalState.currentTab = key;
               globals.rafScheduler.scheduleFullRedraw();
             }
           },
-          tab.name);
+          this.tabNames.get(key) === undefined ? key : this.tabNames.get(key));
     };
     return m(
         '.handle',
@@ -158,9 +147,6 @@
               onclick: () => {
                 if (this.height === DRAG_HANDLE_HEIGHT_PX) {
                   this.isClosed = false;
-                  if (this.previousHeight === 0) {
-                    this.previousHeight = DEFAULT_DETAILS_HEIGHT_PX;
-                  }
                   this.resize(this.previousHeight);
                 } else {
                   this.isFullscreen = false;
@@ -177,148 +163,80 @@
 }
 
 export class DetailsPanel implements m.ClassComponent {
-  private detailsHeight = DEFAULT_DETAILS_HEIGHT_PX;
+  private detailsHeight = DRAG_HANDLE_HEIGHT_PX;
   // Used to set details panel to default height on selection.
   private showDetailsPanel = true;
 
   view() {
-    interface DetailsPanel {
-      key: string;
-      name: string;
-      vnode: AnyAttrsVnode;
-    }
-
-    const detailsPanels: DetailsPanel[] = [];
+    const detailsPanels: Map<string, AnyAttrsVnode> = new Map();
     const curSelection = globals.state.currentSelection;
     if (curSelection) {
       switch (curSelection.kind) {
         case 'NOTE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(NotesEditorPanel, {
-              key: 'notes',
-              id: curSelection.id,
-            })
-          });
-          break;
-        case 'AREA':
-          if (curSelection.noteId !== undefined) {
-            detailsPanels.push({
-              key: 'current_selection',
-              name: 'Current Selection',
-              vnode: m(NotesEditorPanel, {
-                key: 'area_notes',
-                id: curSelection.noteId,
-              })
-            });
-          }
+          detailsPanels.set('current_selection', m(NotesEditorPanel, {
+                              key: 'notes',
+                              id: curSelection.id,
+                            }));
           break;
         case 'SLICE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(SliceDetailsPanel, {
-              key: 'slice',
-            })
-          });
+          detailsPanels.set('current_selection', m(SliceDetailsPanel, {
+                              key: 'slice',
+                            }));
           break;
         case 'COUNTER':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(CounterDetailsPanel, {
-              key: 'counter',
-            })
-          });
+          detailsPanels.set('current_selection', m(CounterDetailsPanel, {
+                              key: 'counter',
+                            }));
           break;
         case 'HEAP_PROFILE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(HeapProfileDetailsPanel, {key: 'heap_profile'})
-          });
+          detailsPanels.set(
+              'current_selection',
+              m(HeapProfileDetailsPanel, {key: 'heap_profile'}));
           break;
         case 'CPU_PROFILE_SAMPLE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(CpuProfileDetailsPanel, {
-              key: 'cpu_profile_sample',
-            })
-          });
+          detailsPanels.set('current_selection', m(CpuProfileDetailsPanel, {
+                              key: 'cpu_profile_sample',
+                            }));
           break;
         case 'CHROME_SLICE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(ChromeSliceDetailsPanel, {key: 'chrome_slice'})
-          });
+          detailsPanels.set('current_selection', m(ChromeSliceDetailsPanel));
           break;
         case 'THREAD_STATE':
-          detailsPanels.push({
-            key: 'current_selection',
-            name: 'Current Selection',
-            vnode: m(ThreadStatePanel, {key: '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.push({
-        key: 'android_logs',
-        name: 'Android Logs',
-        vnode: m(LogPanel, {key: 'logs_panel'})
-      });
-    }
-
-    if (globals.queryResults.has('command')) {
-      const count =
-          (globals.queryResults.get('command') as QueryResponse).rows.length;
-      detailsPanels.push({
-        key: 'query_result',
-        name: `Query Result (${count})`,
-        vnode: m(QueryTable, {key: 'query', queryId: 'command'})
-      });
-    }
-
-    if (globals.connectedFlows.length > 0) {
-      detailsPanels.push({
-        key: 'bound_flows',
-        name: 'Flow Events',
-        vnode: m(FlowEventsPanel, {key: 'flow_events'})
-      });
+      detailsPanels.set('android_logs', m(LogPanel, {}));
     }
 
     for (const [key, value] of globals.aggregateDataStore.entries()) {
       if (value.columns.length > 0 && value.columns[0].data.length > 0) {
-        detailsPanels.push({
-          key: value.tabName,
-          name: value.tabName,
-          vnode: m(AggregationPanel, {kind: key, key, data: value})
-        });
+        detailsPanels.set(
+            value.tabName, m(AggregationPanel, {kind: key, data: value}));
       }
     }
 
-    // Add this after all aggregation panels, to make it appear after 'Slices'
-    if (globals.selectedFlows.length > 0) {
-      detailsPanels.push({
-        key: 'selected_flows',
-        name: 'Flow Events',
-        vnode: m(FlowEventsAreaSelectedPanel)
-      });
+    const wasShowing = this.showDetailsPanel;
+    this.showDetailsPanel = detailsPanels.size > 0;
+    // The first time the details panel appears, it should be default height.
+    if (!wasShowing && this.showDetailsPanel) {
+      this.detailsHeight = DEFAULT_DETAILS_HEIGHT_PX;
     }
 
-    this.showDetailsPanel = detailsPanels.length > 0;
-
-    const currentTabDetails = detailsPanels.filter(
-        tab => tab.key === globals.frontendLocalState.currentTab)[0];
-
-    const panel = currentTabDetails ?
-        currentTabDetails.vnode :
-        detailsPanels.values().next().value?.vnode;
+    const panel = globals.frontendLocalState.currentTab &&
+            detailsPanels.has(globals.frontendLocalState.currentTab) ?
+        detailsPanels.get(globals.frontendLocalState.currentTab) :
+        detailsPanels.values().next().value;
     const panels = panel ? [panel] : [];
 
     return m(
@@ -334,9 +252,7 @@
             this.detailsHeight = Math.max(height, DRAG_HANDLE_HEIGHT_PX);
           },
           height: this.detailsHeight,
-          tabs: detailsPanels.map(tab => {
-            return {key: tab.key, name: tab.name};
-          }),
+          tabs: [...detailsPanels.keys()],
         }),
         m('.details-panel-container',
           m(PanelContainer, {doesScroll: true, panels, kind: 'DETAILS'})));
diff --git a/ui/src/frontend/drag/border_drag_strategy.ts b/ui/src/frontend/drag/border_drag_strategy.ts
deleted file mode 100644
index f186d1f..0000000
--- a/ui/src/frontend/drag/border_drag_strategy.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {TimeScale} from '../time_scale';
-
-import {DragStrategy} from './drag_strategy';
-
-export class BorderDragStrategy extends DragStrategy {
-  private moveStart = false;
-
-  constructor(timeScale: TimeScale, private pixelBounds: [number, number]) {
-    super(timeScale);
-  }
-
-  onDrag(x: number) {
-    let tStart =
-        this.timeScale.pxToTime(this.moveStart ? x : this.pixelBounds[0]);
-    let tEnd =
-        this.timeScale.pxToTime(!this.moveStart ? x : this.pixelBounds[1]);
-    if (tStart > tEnd) {
-      this.moveStart = !this.moveStart;
-      [tEnd, tStart] = [tStart, tEnd];
-    }
-    super.updateGlobals(tStart, tEnd);
-    this.pixelBounds =
-        [this.timeScale.timeToPx(tStart), this.timeScale.timeToPx(tEnd)];
-  }
-
-  onDragStart(x: number) {
-    this.moveStart =
-        Math.abs(x - this.pixelBounds[0]) < Math.abs(x - this.pixelBounds[1]);
-  }
-}
\ No newline at end of file
diff --git a/ui/src/frontend/drag/drag_strategy.ts b/ui/src/frontend/drag/drag_strategy.ts
deleted file mode 100644
index 2896849..0000000
--- a/ui/src/frontend/drag/drag_strategy.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {TimeSpan} from '../../common/time';
-import {globals} from '../globals';
-import {TimeScale} from '../time_scale';
-
-export abstract class DragStrategy {
-  constructor(protected timeScale: TimeScale) {}
-
-  abstract onDrag(x: number): void;
-
-  abstract onDragStart(x: number): void;
-
-  protected updateGlobals(tStart: number, tEnd: number) {
-    const vizTime = new TimeSpan(tStart, tEnd);
-    globals.frontendLocalState.updateVisibleTime(vizTime);
-    globals.rafScheduler.scheduleRedraw();
-  }
-}
diff --git a/ui/src/frontend/drag/inner_drag_strategy.ts b/ui/src/frontend/drag/inner_drag_strategy.ts
deleted file mode 100644
index 2af1b39..0000000
--- a/ui/src/frontend/drag/inner_drag_strategy.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {TimeScale} from '../time_scale';
-import {DragStrategy} from './drag_strategy';
-
-export class InnerDragStrategy extends DragStrategy {
-  private dragStartPx = 0;
-
-  constructor(timeScale: TimeScale, private pixelBounds: [number, number]) {
-    super(timeScale);
-  }
-
-  onDrag(x: number) {
-    const move = x - this.dragStartPx;
-    const tStart = this.timeScale.pxToTime(this.pixelBounds[0] + move);
-    const tEnd = this.timeScale.pxToTime(this.pixelBounds[1] + move);
-    super.updateGlobals(tStart, tEnd);
-  }
-
-  onDragStart(x: number) {
-    this.dragStartPx = x;
-  }
-}
diff --git a/ui/src/frontend/drag/outer_drag_strategy.ts b/ui/src/frontend/drag/outer_drag_strategy.ts
deleted file mode 100644
index 88d127d..0000000
--- a/ui/src/frontend/drag/outer_drag_strategy.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {DragStrategy} from './drag_strategy';
-
-export class OuterDragStrategy extends DragStrategy {
-  private dragStartPx = 0;
-
-  onDrag(x: number) {
-    const dragBeginTime = this.timeScale.pxToTime(this.dragStartPx);
-    const dragEndTime = this.timeScale.pxToTime(x);
-    const tStart = Math.min(dragBeginTime, dragEndTime);
-    const tEnd = Math.max(dragBeginTime, dragEndTime);
-    super.updateGlobals(tStart, tEnd);
-  }
-
-  onDragStart(x: number) {
-    this.dragStartPx = x;
-  }
-}
\ No newline at end of file
diff --git a/ui/src/frontend/drag_gesture_handler.ts b/ui/src/frontend/drag_gesture_handler.ts
index 30c0a38..d29cac9 100644
--- a/ui/src/frontend/drag_gesture_handler.ts
+++ b/ui/src/frontend/drag_gesture_handler.ts
@@ -18,7 +18,6 @@
   private readonly boundOnMouseUp = this.onMouseUp.bind(this);
   private clientRect?: DOMRect;
   private pendingMouseDownEvent?: MouseEvent;
-  private _isDragging = false;
 
   constructor(
       private element: HTMLElement,
@@ -29,7 +28,6 @@
   }
 
   private onMouseDown(e: MouseEvent) {
-    this._isDragging = true;
     document.body.addEventListener('mousemove', this.boundOnMouseMove);
     document.body.addEventListener('mouseup', this.boundOnMouseUp);
     this.pendingMouseDownEvent = e;
@@ -64,7 +62,6 @@
   }
 
   private onMouseUp(e: MouseEvent) {
-    this._isDragging = false;
     document.body.removeEventListener('mousemove', this.boundOnMouseMove);
     document.body.removeEventListener('mouseup', this.boundOnMouseUp);
     if (!this.pendingMouseDownEvent) {
@@ -72,8 +69,4 @@
     }
     e.stopPropagation();
   }
-
-  get isDragging() {
-    return this._isDragging;
-  }
 }
diff --git a/ui/src/frontend/error_dialog.ts b/ui/src/frontend/error_dialog.ts
index 9fba9a0..565cafc 100644
--- a/ui/src/frontend/error_dialog.ts
+++ b/ui/src/frontend/error_dialog.ts
@@ -14,12 +14,7 @@
 
 import * as m from 'mithril';
 
-import {TraceUrlSource} from '../common/state';
-import {saveTrace} from '../common/upload_utils';
-
-import {globals} from './globals';
 import {showModal} from './modal';
-import {isShareable} from './trace_attrs';
 
 // Never show more than one dialog per minute.
 const MIN_REPORT_PERIOD_MS = 60000;
@@ -30,28 +25,7 @@
 const ERR_QUEUE_MAX_LEN = 10;
 
 export function maybeShowErrorDialog(errLog: string) {
-  globals.logging.logError(errLog);
   const now = performance.now();
-
-  // Here we rely on the exception message from onCannotGrowMemory function
-  if (errLog.includes('Cannot enlarge memory')) {
-    showOutOfMemoryDialog();
-    // Refresh timeLastReport to prevent a different error showing a dialog
-    timeLastReport = now;
-    return;
-  }
-
-  if (errLog.includes('Unable to claim interface.') ||
-      errLog.includes('A transfer error has occurred')) {
-    showWebUSBError();
-    timeLastReport = now;
-  }
-
-  if (errLog.includes('(ERR:fmt)')) {
-    showUnknownFileError();
-    return;
-  }
-
   if (timeLastReport > 0 && now - timeLastReport <= MIN_REPORT_PERIOD_MS) {
     queuedErrors.unshift(errLog);
     if (queuedErrors.length > ERR_QUEUE_MAX_LEN) queuedErrors.pop();
@@ -67,186 +41,26 @@
   }
 
   const errTitle = errLog.split('\n', 1)[0].substr(0, 80);
-  const userDescription = '';
-  let checked = false;
-  const engine = Object.values(globals.state.engines)[0];
+  let link = 'https://goto.google.com/perfetto-ui-bug';
+  link += '?title=' + encodeURIComponent(`UI Error: ${errTitle}`);
+  link += '&description=' + encodeURIComponent(errLog.substr(0, 32768));
 
-  const shareTraceSection: m.Vnode[] = [];
-  if (isShareable() && !urlExists()) {
-    shareTraceSection.push(
-        m(`input[type=checkbox]`, {
-          checked,
-          oninput: (ev: InputEvent) => {
-            checked = (ev.target as HTMLInputElement).checked;
-            if (checked && engine.source.type === 'FILE') {
-              saveTrace(engine.source.file).then(url => {
-                const errMessage = createErrorMessage(errLog, checked, url);
-                renderModal(
-                    errTitle, errMessage, userDescription, shareTraceSection);
-                return;
-              });
-            }
-            const errMessage = createErrorMessage(errLog, checked);
-            renderModal(
-                errTitle, errMessage, userDescription, shareTraceSection);
-          },
-        }),
-        m('span', `Check this box to share the current trace for debugging
-     purposes.`),
-        m('div.modal-small',
-          `This will create a permalink to this trace, you may
-     leave it unchecked and attach the trace manually
-     to the bug if preferred.`));
-  }
-  renderModal(
-      errTitle,
-      createErrorMessage(errLog, checked),
-      userDescription,
-      shareTraceSection);
-}
-
-function renderModal(
-    errTitle: string,
-    errMessage: string,
-    userDescription: string,
-    shareTraceSection: m.Vnode[]) {
   showModal({
-    title: 'Oops, something went wrong. Please file a bug.',
-    content:
-        m('div',
-          m('.modal-logs', errMessage),
-          m('span', `Please provide any additional details describing
-           how the crash occurred:`),
-          m('textarea.modal-textarea', {
-            rows: 3,
-            maxlength: 1000,
-            oninput: (ev: InputEvent) => {
-              userDescription = (ev.target as HTMLTextAreaElement).value;
-            },
-            onkeydown: (e: Event) => {
-              e.stopPropagation();
-            },
-            onkeyup: (e: Event) => {
-              e.stopPropagation();
-            },
-          }),
-          shareTraceSection),
+    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(
-              createLink(errTitle, errMessage, userDescription), '_blank');
+          window.open(link, '_blank');
         }
       },
     ]
   });
 }
-
-// If there is a trace URL to share, we don't have to show the upload checkbox.
-function urlExists() {
-  const engine = Object.values(globals.state.engines)[0];
-  return engine !== undefined &&
-      (engine.source.type === 'ARRAY_BUFFER' || engine.source.type === 'URL') &&
-      engine.source.url !== undefined;
-}
-
-function createErrorMessage(errLog: string, checked: boolean, url?: string) {
-  let errMessage = '';
-  const engine = Object.values(globals.state.engines)[0];
-  if (checked && url !== undefined) {
-    errMessage += `Trace: ${url}`;
-  } else if (urlExists()) {
-    errMessage += `Trace: ${(engine.source as TraceUrlSource).url}`;
-  } else {
-    errMessage += 'To assist with debugging please attach or link to the ' +
-        'trace you were viewing.';
-  }
-  return errMessage + '\n\n' +
-      'Viewed on: ' + self.location.origin + '\n\n' + errLog;
-}
-
-function createLink(
-    errTitle: string, errMessage: string, userDescription: string): string {
-  let link = 'https://goto.google.com/perfetto-ui-bug';
-  link += '?title=' + encodeURIComponent(`UI Error: ${errTitle}`);
-  link += '&description=';
-  if (userDescription !== '') {
-    link +=
-        encodeURIComponent('User description:\n' + userDescription + '\n\n');
-  }
-  link += encodeURIComponent(errMessage);
-  // 8kb is common limit on request size so restrict links to that long:
-  return link.substr(0, 8000);
-}
-
-function showOutOfMemoryDialog() {
-  const url =
-      'https://perfetto.dev/docs/quickstart/trace-analysis#get-trace-processor';
-
-  const tpCmd = 'curl -LO https://get.perfetto.dev/trace_processor\n' +
-      'chmod +x ./trace_processor\n' +
-      'trace_processor --httpd /path/to/trace.pftrace\n' +
-      '# Reload the UI, it will prompt to use the HTTP+RPC interface';
-  showModal({
-    title: 'Oops! Your WASM trace processor ran out of memory',
-    content: m(
-        'div',
-        m('span',
-          'The in-memory representation of the trace is too big ' +
-              'for the browser memory limits (typically 2GB per tab).'),
-        m('br'),
-        m('span',
-          'You can work around this problem by using the trace_processor ' +
-              'native binary as an accelerator for the UI as follows:'),
-        m('br'),
-        m('br'),
-        m('.modal-bash', tpCmd),
-        m('br'),
-        m('span', 'For details see '),
-        m('a', {href: url, target: '_blank'}, url),
-        ),
-    buttons: []
-  });
-}
-
-function showUnknownFileError() {
-  showModal({
-    title: 'Cannot open this file',
-    content: m(
-        'div',
-        m('p',
-          'The file opened doesn\'t look like a Perfetto trace or any ' +
-              'other format recognized by the Perfetto TraceProcessor.'),
-        m('p', 'Formats supported:'),
-        m(
-            'ul',
-            m('li', 'Perfetto protobuf trace'),
-            m('li', 'chrome://tracing JSON'),
-            m('li', 'Android systrace'),
-            m('li', 'Fuchsia trace'),
-            m('li', 'Ninja build log'),
-            ),
-        ),
-    buttons: []
-  });
-}
-
-function showWebUSBError() {
-  showModal({
-    title: 'A WebUSB error occurred',
-    content: m(
-        'div',
-        m('span', `Is adb already running on the host? Run this command and
-      try again.`),
-        m('br'),
-        m('.modal-bash', '> adb kill-server'),
-        m('br'),
-        m('span', 'For details see '),
-        m('a', {href: 'http://b/159048331', target: '_blank'}, 'b/159048331'),
-        ),
-    buttons: []
-  });
-}
diff --git a/ui/src/frontend/file_drop_handler.ts b/ui/src/frontend/file_drop_handler.ts
deleted file mode 100644
index 8eccc4d..0000000
--- a/ui/src/frontend/file_drop_handler.ts
+++ /dev/null
@@ -1,65 +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 {Actions} from '../common/actions';
-import {globals} from './globals';
-
-let lastDragTarget: EventTarget|null = null;
-
-export function installFileDropHandler() {
-  window.ondragenter = (evt: DragEvent) => {
-    evt.preventDefault();
-    evt.stopPropagation();
-    lastDragTarget = evt.target;
-    if (dragEventHasFiles(evt)) {
-      document.body.classList.add('filedrag');
-    }
-  };
-
-  window.ondragleave = (evt: DragEvent) => {
-    evt.preventDefault();
-    evt.stopPropagation();
-    if (evt.target === lastDragTarget) {
-      document.body.classList.remove('filedrag');
-    }
-  };
-
-  window.ondrop = (evt: DragEvent) => {
-    evt.preventDefault();
-    evt.stopPropagation();
-    document.body.classList.remove('filedrag');
-    if (evt.dataTransfer && dragEventHasFiles(evt)) {
-      const file = evt.dataTransfer.files[0];
-      if (file) {
-        globals.frontendLocalState.localOnlyMode = false;
-        globals.dispatch(Actions.openTraceFromFile({file}));
-      }
-    }
-    evt.preventDefault();
-  };
-
-  window.ondragover = (evt: DragEvent) => {
-    evt.preventDefault();
-    evt.stopPropagation();
-  };
-}
-
-function dragEventHasFiles(event: DragEvent): boolean {
-  if (event.dataTransfer && event.dataTransfer.types) {
-    for (const type of event.dataTransfer.types) {
-      if (type === 'Files') return true;
-    }
-  }
-  return false;
-}
diff --git a/ui/src/frontend/flamegraph.ts b/ui/src/frontend/flamegraph.ts
index 77e209a..ddd8c39 100644
--- a/ui/src/frontend/flamegraph.ts
+++ b/ui/src/frontend/flamegraph.ts
@@ -29,10 +29,9 @@
   width: number;
 }
 
-// Height of one 'row' on the flame chart including 1px of whitespace
-// below the box.
-const NODE_HEIGHT = 18;
+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 function findRootSize(data: CallsiteInfo[]) {
@@ -51,15 +50,12 @@
 }
 
 export class Flamegraph {
+  private isThumbnail = false;
   private nodeRendering: NodeRendering = {};
   private flamegraphData: CallsiteInfo[];
-  private highlightSomeNodes = false;
   private maxDepth = -1;
   private totalSize = -1;
-  // Initialised on first draw() call
-  private labelCharWidth = 0;
-  private labelFontStyle = '12px Roboto Mono';
-  private rolloverFontStyle = '12px Roboto Condensed';
+  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();
@@ -80,36 +76,31 @@
     this.maxDepth = Math.max(...this.flamegraphData.map(value => value.depth));
   }
 
-  // Instead of highlighting the interesting nodes, we actually want to
-  // de-emphasize the non-highlighted nodes. Returns true if there
-  // are any highlighted nodes in the flamegraph.
-  private highlightingExists() {
-    this.highlightSomeNodes = this.flamegraphData.some((e) => e.highlighted);
+  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, isGreyedOut = false, highlighted: boolean):
-      string {
+  generateColor(name: string, isGreyedOut = false): string {
+    if (this.isThumbnail) {
+      return HEAP_PROFILE_COLOR;
+    }
     if (isGreyedOut) {
       return '#d9d9d9';
     }
     if (name === 'unknown' || name === 'root') {
       return '#c0c0c0';
     }
-    let x = 0;
-    for (let i = 0; i < name.length; i += 1) {
-      x += name.charCodeAt(i) % 64;
-    }
-    x = x % 360;
-    let l = '76';
-    // Make non-highlighted node lighter.
-    if (this.highlightSomeNodes && !highlighted) {
-      l = '90';
-    }
-    return `hsl(${x}deg, 45%, ${l}%)`;
+    const hue = this.hash(name);
+    return `hsl(${hue}, 50%, 65%)`;
   }
 
   /**
-   * Caller will have to call draw method after updating data to have updated
+   * Caller will have to call draw method ater updating data to have updated
    * graph.
    */
   updateDataIfChanged(
@@ -123,7 +114,6 @@
     this.flamegraphData = flamegraphData;
     this.clickedCallsite = clickedCallsite;
     this.findMaxDepth();
-    this.highlightingExists();
     // Finding total size of roots.
     this.totalSize = findRootSize(flamegraphData);
   }
@@ -131,19 +121,15 @@
   draw(
       ctx: CanvasRenderingContext2D, width: number, height: number, x = 0,
       y = 0, unit = 'B') {
+    // TODO(taylori): Instead of pesimistic approach improve displaying text.
+    const name = '____MMMMMMQQwwZZZZZZzzzzzznnnnnnwwwwwwWWWWWqq$$mmmmmm__';
+    const charWidth = ctx.measureText(name).width / name.length;
+    const nodeHeight = this.getNodeHeight();
+    this.startingY = y;
 
     if (this.flamegraphData === undefined) {
       return;
     }
-
-    ctx.font = this.labelFontStyle;
-    ctx.textBaseline = 'middle';
-    if (this.labelCharWidth === 0) {
-      this.labelCharWidth = ctx.measureText('_').width;
-    }
-
-    this.startingY = y;
-
     // 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.
@@ -151,26 +137,24 @@
     let currentY = y;
     nodesMap.set(-1, {width, nextXForChildren: x, size: this.totalSize, x});
 
-    // Initialize data needed for click/hover behavior.
+    // Initialize data needed for click/hover behaivior.
     this.graphData = new Map();
     this.xStartsPerDepth = new Map();
 
     // Draw root node.
-    ctx.fillStyle = this.generateColor('root', false, false);
-    ctx.fillRect(x, currentY, width, NODE_HEIGHT - 1);
+    ctx.fillStyle = this.generateColor('root', false);
+    ctx.fillRect(x, currentY, width, nodeHeight);
+    ctx.font = `${this.textSize}px Roboto Condensed`;
     const text = cropText(
         `root: ${
             this.displaySize(
                 this.totalSize, unit, unit === 'B' ? 1024 : 1000)}`,
-        this.labelCharWidth,
+        charWidth,
         width - 2);
     ctx.fillStyle = 'black';
-    ctx.fillText(text, x + 5, currentY + (NODE_HEIGHT - 1) / 2);
-    currentY += NODE_HEIGHT;
+    ctx.fillText(text, x + 5, currentY + nodeHeight - 4);
+    currentY += nodeHeight;
 
-    // Set style for borders.
-    ctx.strokeStyle = 'white';
-    ctx.lineWidth = 0.5;
 
     for (let i = 0; i < this.flamegraphData.length; i++) {
       if (currentY > height) {
@@ -182,7 +166,7 @@
         continue;
       }
 
-      const isClicked = this.clickedCallsite !== undefined;
+      const isClicked = !this.isThumbnail && this.clickedCallsite !== undefined;
       const isFullWidth =
           isClicked && value.depth <= this.clickedCallsite!.depth;
       const isGreyedOut =
@@ -195,12 +179,12 @@
           (isFullWidth ? 1 : value.totalSize / parentSize) * parentNode.width;
 
       const currentX = parentNode.nextXForChildren;
-      currentY = y + NODE_HEIGHT * (value.depth + 1);
+      currentY = y + nodeHeight * (value.depth + 1);
 
       // Draw node.
       const name = this.getCallsiteName(value);
-      ctx.fillStyle = this.generateColor(name, isGreyedOut, value.highlighted);
-      ctx.fillRect(currentX, currentY, width, NODE_HEIGHT - 1);
+      ctx.fillStyle = this.generateColor(name, isGreyedOut);
+      ctx.fillRect(currentX, currentY, width, nodeHeight);
 
       // Set current node's data in map for children to use.
       nodesMap.set(value.id, {
@@ -217,26 +201,27 @@
         x: parentNode.x
       });
 
-      // Draw name.
-      const labelPaddingPx = 5;
-      const maxLabelWidth = width - labelPaddingPx * 2;
-      let text = cropText(name, this.labelCharWidth, maxLabelWidth);
-      // If cropped text and the original text are within 20% we keep the
-      // original text and just squish it a bit.
-      if (text.length * 1.2 > name.length) {
-        text = name;
+      // Thumbnail mode doesn't have name on nodes and click/hover behaviour.
+      if (this.isThumbnail) {
+        continue;
       }
-      ctx.fillStyle = 'black';
-      ctx.fillText(
-          text,
-          currentX + labelPaddingPx,
-          currentY + (NODE_HEIGHT - 1) / 2,
-          maxLabelWidth);
 
-      // Draw border on the right of node.
+      // Draw name.
+      ctx.font = `${this.textSize}px Roboto Condensed`;
+      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 + width, currentY);
-      ctx.lineTo(currentX + width, currentY + NODE_HEIGHT);
+      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.
@@ -253,25 +238,13 @@
       }
     }
 
-    // Draw the tooltip.
     if (this.hoveredX > -1 && this.hoveredY > -1 && this.hoveredCallsite) {
-      // Must set these before measureText below.
-      ctx.font = this.rolloverFontStyle;
-      ctx.textBaseline = 'top';
-
-      // Size in px of the border around the text and the edge of the rollover
-      // background.
-      const paddingPx = 8;
-      // Size in px of the x and y offset between the mouse and the top left
-      // corner of the rollover box.
-      const offsetPx = 4;
-
+      // Draw the tooltip.
       const lines: string[] = [];
       let lineSplitter: LineSplitter;
       const nameText = this.getCallsiteName(this.hoveredCallsite);
-      const nameTextSize = ctx.measureText(nameText);
       lineSplitter =
-          splitIfTooBig(nameText, width - paddingPx, nameTextSize.width);
+          splitIfTooBig(nameText, width, ctx.measureText(nameText).width);
       let textWidth = lineSplitter.lineWidth;
       lines.push(...lineSplitter.lines);
 
@@ -310,36 +283,23 @@
         lines.push(...lineSplitter.lines);
       }
 
-      // Compute a line height as the bounding box height + 50%:
-      const heightSample = ctx.measureText(
-          'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
-      const lineHeight =
-          Math.round(heightSample.actualBoundingBoxDescent * 1.5);
+      const rectWidth = textWidth + 16;
+      const rectXStart = this.hoveredX + 8 + rectWidth > width ?
+          width - rectWidth - 8 :
+          this.hoveredX + 8;
+      const rectHeight = nodeHeight * (lines.length + 1);
+      const rectYStart = this.hoveredY + 4 + rectHeight > height ?
+          height - rectHeight - 8 :
+          this.hoveredY + 4;
 
-      const rectWidth = textWidth + 2 * paddingPx;
-      const rectHeight = lineHeight * lines.length + 2 * paddingPx;
-
-      let rectXStart = this.hoveredX + offsetPx;
-      let rectYStart = this.hoveredY + offsetPx;
-
-      if (rectXStart + rectWidth > width) {
-        rectXStart = width - rectWidth;
-      }
-
-      if (rectYStart + rectHeight > height) {
-        rectYStart = height - rectHeight;
-      }
-
+      ctx.font = '12px Roboto Condensed';
       ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
       ctx.fillRect(rectXStart, rectYStart, rectWidth, rectHeight);
       ctx.fillStyle = 'hsl(200, 50%, 40%)';
       ctx.textAlign = 'left';
       for (let i = 0; i < lines.length; i++) {
         const line = lines[i];
-        ctx.fillText(
-            line,
-            rectXStart + paddingPx,
-            rectYStart + paddingPx + i * lineHeight);
+        ctx.fillText(line, rectXStart + 4, rectYStart + (i + 1) * 18);
       }
     }
   }
@@ -385,6 +345,9 @@
   }
 
   onMouseClick({x, y}: {x: number, y: number}): CallsiteInfo|undefined {
+    if (this.isThumbnail) {
+      return undefined;
+    }
     const clickedCallsite = this.findSelectedCallsite(x, y);
     // TODO(b/148596659): Allow to expand [merged] callsites. Currently,
     // this expands to the biggest of the nodes that were merged, which
@@ -396,8 +359,8 @@
   }
 
   private findSelectedCallsite(x: number, y: number): CallsiteInfo|undefined {
-    const depth =
-        Math.trunc((y - this.startingY) / NODE_HEIGHT) - 1;  // at 0 is root
+    const depth = Math.trunc((y - this.startingY) / 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}`);
@@ -416,8 +379,17 @@
   }
 
   getHeight(): number {
-    return this.flamegraphData.length === 0 ? 0 :
-                                              (this.maxDepth + 2) * NODE_HEIGHT;
+    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;
   }
 }
 
@@ -437,6 +409,6 @@
     lines.push(line.slice(0, maxLineLen));
     line = line.slice(maxLineLen);
   }
-  lineWidth = Math.min(maxLineLen * charWidth, lineWidth);
+  lineWidth = Math.min(maxWidth, lineWidth);
   return {lineWidth, lines};
 }
diff --git a/ui/src/frontend/flow_events_panel.ts b/ui/src/frontend/flow_events_panel.ts
deleted file mode 100644
index 6f15468..0000000
--- a/ui/src/frontend/flow_events_panel.ts
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2020 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 {Flow, globals} from './globals';
-import {BLANK_CHECKBOX, CHECKBOX} from './icons';
-import {Panel, PanelSize} from './panel';
-import {findUiTrackId} from './scroll_helper';
-
-export const ALL_CATEGORIES = '_all_';
-
-export function getFlowCategories(flow: Flow): string[] {
-  const categories: string[] = [];
-  // v1 flows have their own categories
-  if (flow.category) {
-    categories.push(...flow.category.split(','));
-    return categories;
-  }
-  const beginCats = flow.begin.sliceCategory.split(',');
-  const endCats = flow.end.sliceCategory.split(',');
-  categories.push(...new Set([...beginCats, ...endCats]));
-  return categories;
-}
-
-export class FlowEventsPanel extends Panel {
-  view() {
-    const selection = globals.state.currentSelection;
-    if (!selection || selection.kind !== 'CHROME_SLICE') {
-      return;
-    }
-
-    const flowClickHandler = (sliceId: number, trackId: number) => {
-      const uiTrackId = findUiTrackId(trackId);
-      if (uiTrackId) {
-        globals.makeSelection(
-            Actions.selectChromeSlice(
-                {id: sliceId, trackId: uiTrackId, table: 'slice'}),
-            'bound_flows');
-      }
-    };
-
-    // Can happen only for flow events version 1
-    const haveCategories =
-        globals.connectedFlows.filter(flow => flow.category).length > 0;
-
-    const columns = [
-      m('th', 'Direction'),
-      m('th', 'Connected Slice ID'),
-      m('th', 'Connected Slice Name')
-    ];
-
-    if (haveCategories) {
-      columns.push(m('th', 'Flow Category'));
-      columns.push(m('th', 'Flow Name'));
-    }
-
-    const rows = [m('tr', columns)];
-
-    // Fill the table with all the directly connected flow events
-    globals.connectedFlows.forEach(flow => {
-      if (selection.id !== flow.begin.sliceId &&
-          selection.id !== flow.end.sliceId) {
-        return;
-      }
-
-      const outgoing = selection.id === flow.begin.sliceId;
-      const otherEnd = (outgoing ? flow.end : flow.begin);
-
-      const args = {
-        onclick: () => flowClickHandler(otherEnd.sliceId, otherEnd.trackId),
-        onmousemove: () =>
-            globals.frontendLocalState.setHighlightedSliceId(otherEnd.sliceId),
-        onmouseleave: () => globals.frontendLocalState.setHighlightedSliceId(-1)
-      };
-
-      const data = [
-        m('td.flow-link', args, outgoing ? 'Outgoing' : 'Incoming'),
-        m('td.flow-link', args, otherEnd.sliceId.toString()),
-        m('td.flow-link', args, otherEnd.sliceName)
-      ];
-
-      if (haveCategories) {
-        data.push(m('td.flow-info', flow.category || '-'));
-        data.push(m('td.flow-info', flow.name || '-'));
-      }
-
-      rows.push(m('tr', data));
-    });
-
-    return m('.details-panel', [
-      m('.details-panel-heading', m('h2', `Flow events`)),
-      m('.flow-events-table', m('table.half-width', rows))
-    ]);
-  }
-
-  renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
-}
-
-export class FlowEventsAreaSelectedPanel extends Panel {
-  view() {
-    const selection = globals.state.currentSelection;
-    if (!selection || selection.kind !== 'AREA') {
-      return;
-    }
-
-    const columns = [
-      m('th', 'Flow Category'),
-      m('th', 'Number of flows'),
-      m('th',
-        'Show',
-        m('a.warning',
-          m('i.material-icons', 'warning'),
-          m('.tooltip',
-            'Showing a large number of flows may impact performance.')))
-    ];
-
-    const rows = [m('tr', columns)];
-
-    const categoryToFlowsNum = new Map<string, number>();
-
-    globals.selectedFlows.forEach(flow => {
-      const categories = getFlowCategories(flow);
-      categories.forEach(cat => {
-        if (!categoryToFlowsNum.has(cat)) {
-          categoryToFlowsNum.set(cat, 0);
-        }
-        categoryToFlowsNum.set(cat, categoryToFlowsNum.get(cat)! + 1);
-      });
-    });
-
-    const allWasChecked = globals.visibleFlowCategories.get(ALL_CATEGORIES);
-    rows.push(m('tr.sum', [
-      m('td.sum-data', 'All'),
-      m('td.sum-data', globals.selectedFlows.length),
-      m('td.sum-data',
-        m('i.material-icons',
-          {
-            onclick: () => {
-              if (allWasChecked) {
-                globals.visibleFlowCategories.clear();
-              } else {
-                categoryToFlowsNum.forEach((_, cat) => {
-                  globals.visibleFlowCategories.set(cat, true);
-                });
-              }
-              globals.visibleFlowCategories.set(ALL_CATEGORIES, !allWasChecked);
-              globals.rafScheduler.scheduleFullRedraw();
-            },
-          },
-          allWasChecked ? CHECKBOX : BLANK_CHECKBOX))
-    ]));
-
-    categoryToFlowsNum.forEach((num, cat) => {
-      const wasChecked = globals.visibleFlowCategories.get(cat) ||
-          globals.visibleFlowCategories.get(ALL_CATEGORIES);
-      const data = [
-        m('td.flow-info', cat),
-        m('td.flow-info', num),
-        m('td.flow-info',
-          m('i.material-icons',
-            {
-              onclick: () => {
-                if (wasChecked) {
-                  globals.visibleFlowCategories.set(ALL_CATEGORIES, false);
-                }
-                globals.visibleFlowCategories.set(cat, !wasChecked);
-                globals.rafScheduler.scheduleFullRedraw();
-              },
-            },
-            wasChecked ? CHECKBOX : BLANK_CHECKBOX))
-      ];
-      rows.push(m('tr', data));
-    });
-
-    return m('.details-panel', [
-      m('.details-panel-heading', m('h2', `Selected flow events`)),
-      m('.flow-events-table', m('table.half-width', rows)),
-    ]);
-  }
-
-  renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
-}
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
deleted file mode 100644
index 33b7dab..0000000
--- a/ui/src/frontend/flow_events_renderer.ts
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright (C) 2020 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 {TRACK_SHELL_WIDTH} from './css_constants';
-import {ALL_CATEGORIES, getFlowCategories} from './flow_events_panel';
-import {Flow, FlowPoint, globals} from './globals';
-import {PanelVNode} from './panel';
-import {findUiTrackId} from './scroll_helper';
-import {SliceRect} from './track';
-import {TrackGroupPanel} from './track_group_panel';
-import {TrackPanel} from './track_panel';
-
-const TRACK_GROUP_CONNECTION_OFFSET = 5;
-const TRIANGLE_SIZE = 5;
-const CIRCLE_RADIUS = 3;
-const BEZIER_OFFSET = 30;
-
-const CONNECTED_FLOW_HUE = 10;
-const SELECTED_FLOW_HUE = 230;
-
-const DEFAULT_FLOW_WIDTH = 2;
-const FOCUSED_FLOW_WIDTH = 3;
-
-const HIGHLIGHTED_FLOW_INTENSITY = 45;
-const FOCUSED_FLOW_INTENSITY = 55;
-const DEFAULT_FLOW_INTENSITY = 70;
-
-type LineDirection = 'LEFT'|'RIGHT'|'UP'|'DOWN';
-type ConnectionType = 'TRACK'|'TRACK_GROUP';
-
-interface TrackPanelInfo {
-  panel: TrackPanel;
-  yStart: number;
-}
-
-interface TrackGroupPanelInfo {
-  panel: TrackGroupPanel;
-  yStart: number;
-  height: number;
-}
-
-function hasTrackId(obj: {}): obj is {trackId: number} {
-  return (obj as {trackId?: number}).trackId !== undefined;
-}
-
-function hasManyTrackIds(obj: {}): obj is {trackIds: number[]} {
-  return (obj as {trackIds?: number}).trackIds !== undefined;
-}
-
-function hasId(obj: {}): obj is {id: number} {
-  return (obj as {id?: number}).id !== undefined;
-}
-
-function hasTrackGroupId(obj: {}): obj is {trackGroupId: string} {
-  return (obj as {trackGroupId?: string}).trackGroupId !== undefined;
-}
-
-export class FlowEventsRendererArgs {
-  trackIdToTrackPanel: Map<number, TrackPanelInfo>;
-  groupIdToTrackGroupPanel: Map<string, TrackGroupPanelInfo>;
-
-  constructor(public canvasWidth: number, public canvasHeight: number) {
-    this.trackIdToTrackPanel = new Map<number, TrackPanelInfo>();
-    this.groupIdToTrackGroupPanel = new Map<string, TrackGroupPanelInfo>();
-  }
-
-  registerPanel(panel: PanelVNode, yStart: number, height: number) {
-    if (panel.state instanceof TrackPanel && hasId(panel.attrs)) {
-      const config = globals.state.tracks[panel.attrs.id].config;
-      if (hasTrackId(config)) {
-        this.trackIdToTrackPanel.set(
-            config.trackId, {panel: panel.state, yStart});
-      }
-      if (hasManyTrackIds(config)) {
-        for (const trackId of config.trackIds) {
-          this.trackIdToTrackPanel.set(trackId, {panel: panel.state, yStart});
-        }
-      }
-    } else if (
-        panel.state instanceof TrackGroupPanel &&
-        hasTrackGroupId(panel.attrs)) {
-      this.groupIdToTrackGroupPanel.set(
-          panel.attrs.trackGroupId, {panel: panel.state, yStart, height});
-    }
-  }
-}
-
-export class FlowEventsRenderer {
-  private getTrackGroupIdByTrackId(trackId: number): string|undefined {
-    const uiTrackId = findUiTrackId(trackId);
-    return uiTrackId ? globals.state.tracks[uiTrackId].trackGroup : undefined;
-  }
-
-  private getTrackGroupYCoordinate(
-      args: FlowEventsRendererArgs, trackId: number): number|undefined {
-    const trackGroupId = this.getTrackGroupIdByTrackId(trackId);
-    if (!trackGroupId) {
-      return undefined;
-    }
-    const trackGroupInfo = args.groupIdToTrackGroupPanel.get(trackGroupId);
-    if (!trackGroupInfo) {
-      return undefined;
-    }
-    return trackGroupInfo.yStart + trackGroupInfo.height -
-        TRACK_GROUP_CONNECTION_OFFSET;
-  }
-
-  private getTrackYCoordinate(args: FlowEventsRendererArgs, trackId: number):
-      number|undefined {
-    return args.trackIdToTrackPanel.get(trackId) ?.yStart;
-  }
-
-  private getYConnection(
-      args: FlowEventsRendererArgs, trackId: number,
-      rect?: SliceRect): {y: number, connection: ConnectionType}|undefined {
-    if (!rect) {
-      const y = this.getTrackGroupYCoordinate(args, trackId);
-      if (y === undefined) {
-        return undefined;
-      }
-      return {y, connection: 'TRACK_GROUP'};
-    }
-    const y = (this.getTrackYCoordinate(args, trackId) || 0) + rect.top +
-        rect.height * 0.5;
-
-    return {
-      y: Math.min(Math.max(0, y), args.canvasHeight),
-      connection: 'TRACK'
-    };
-  }
-
-  private getXCoordinate(ts: number): number {
-    return globals.frontendLocalState.timeScale.timeToPx(ts);
-  }
-
-  private getSliceRect(args: FlowEventsRendererArgs, point: FlowPoint):
-      SliceRect|undefined {
-    const trackPanel = args.trackIdToTrackPanel.get(point.trackId) ?.panel;
-    if (!trackPanel) {
-      return undefined;
-    }
-    return trackPanel.getSliceRect(
-        point.sliceStartTs, point.sliceEndTs, point.depth);
-  }
-
-  render(ctx: CanvasRenderingContext2D, args: FlowEventsRendererArgs) {
-    ctx.save();
-    ctx.translate(TRACK_SHELL_WIDTH, 0);
-    ctx.rect(0, 0, args.canvasWidth - TRACK_SHELL_WIDTH, args.canvasHeight);
-    ctx.clip();
-
-    globals.connectedFlows.forEach(flow => {
-      this.drawFlow(ctx, args, flow, CONNECTED_FLOW_HUE);
-    });
-
-    globals.selectedFlows.forEach(flow => {
-      const categories = getFlowCategories(flow);
-      for (const cat of categories) {
-        if (globals.visibleFlowCategories.get(cat) ||
-            globals.visibleFlowCategories.get(ALL_CATEGORIES)) {
-          this.drawFlow(ctx, args, flow, SELECTED_FLOW_HUE);
-          break;
-        }
-      }
-    });
-
-    ctx.restore();
-  }
-
-  private drawFlow(
-      ctx: CanvasRenderingContext2D, args: FlowEventsRendererArgs, flow: Flow,
-      hue: number) {
-    const beginSliceRect = this.getSliceRect(args, flow.begin);
-    const endSliceRect = this.getSliceRect(args, flow.end);
-
-    const beginYConnection =
-        this.getYConnection(args, flow.begin.trackId, beginSliceRect);
-    const endYConnection =
-        this.getYConnection(args, flow.end.trackId, endSliceRect);
-
-    if (!beginYConnection || !endYConnection) {
-      return;
-    }
-
-    let beginDir: LineDirection = 'LEFT';
-    let endDir: LineDirection = 'RIGHT';
-    if (beginYConnection.connection === 'TRACK_GROUP') {
-      beginDir = beginYConnection.y > endYConnection.y ? 'DOWN' : 'UP';
-    }
-    if (endYConnection.connection === 'TRACK_GROUP') {
-      endDir = endYConnection.y > beginYConnection.y ? 'DOWN' : 'UP';
-    }
-
-    const begin = {
-      x: this.getXCoordinate(flow.begin.sliceEndTs),
-      y: beginYConnection.y,
-      dir: beginDir
-    };
-    const end = {
-      x: this.getXCoordinate(flow.end.sliceStartTs),
-      y: endYConnection.y,
-      dir: endDir
-    };
-    const highlighted =
-        flow.end.sliceId === globals.frontendLocalState.highlightedSliceId ||
-        flow.begin.sliceId === globals.frontendLocalState.highlightedSliceId;
-    const focused = flow.id === globals.frontendLocalState.focusedFlowIdLeft ||
-        flow.id === globals.frontendLocalState.focusedFlowIdRight;
-
-    let intensity = DEFAULT_FLOW_INTENSITY;
-    let width = DEFAULT_FLOW_WIDTH;
-    if (focused) {
-      intensity = FOCUSED_FLOW_INTENSITY;
-      width = FOCUSED_FLOW_WIDTH;
-    }
-    if (highlighted) {
-      intensity = HIGHLIGHTED_FLOW_INTENSITY;
-    }
-    this.drawFlowArrow(ctx, begin, end, hue, intensity, width);
-  }
-
-  private getDeltaX(dir: LineDirection, offset: number): number {
-    switch (dir) {
-      case 'LEFT':
-        return -offset;
-      case 'RIGHT':
-        return offset;
-      case 'UP':
-        return 0;
-      case 'DOWN':
-        return 0;
-      default:
-        return 0;
-    }
-  }
-
-  private getDeltaY(dir: LineDirection, offset: number): number {
-    switch (dir) {
-      case 'LEFT':
-        return 0;
-      case 'RIGHT':
-        return 0;
-      case 'UP':
-        return -offset;
-      case 'DOWN':
-        return offset;
-      default:
-        return 0;
-    }
-  }
-
-  private drawFlowArrow(
-      ctx: CanvasRenderingContext2D,
-      begin: {x: number, y: number, dir: LineDirection},
-      end: {x: number, y: number, dir: LineDirection}, hue: number,
-      intensity: number, width: number) {
-    const END_OFFSET =
-        (end.dir === 'RIGHT' || end.dir === 'LEFT' ? TRIANGLE_SIZE : 0);
-    const color = `hsl(${hue}, 50%, ${intensity}%)`;
-    // draw curved line from begin to end (bezier curve)
-    ctx.strokeStyle = color;
-    ctx.lineWidth = width;
-    ctx.beginPath();
-    ctx.moveTo(begin.x, begin.y);
-    ctx.bezierCurveTo(
-        begin.x - this.getDeltaX(begin.dir, BEZIER_OFFSET),
-        begin.y - this.getDeltaY(begin.dir, BEZIER_OFFSET),
-        end.x - this.getDeltaX(end.dir, BEZIER_OFFSET + END_OFFSET),
-        end.y - this.getDeltaY(end.dir, BEZIER_OFFSET + END_OFFSET),
-        end.x - this.getDeltaX(end.dir, END_OFFSET),
-        end.y - this.getDeltaY(end.dir, END_OFFSET));
-    ctx.stroke();
-
-    // TODO (andrewbb): probably we should add a parameter 'MarkerType' to be
-    // able to choose what marker we want to draw _before_ the function call.
-    // e.g. triangle, circle, square?
-    if (begin.dir !== 'RIGHT' && begin.dir !== 'LEFT') {
-      // draw a circle if we the line has a vertical connection
-      ctx.fillStyle = color;
-      ctx.beginPath();
-      ctx.arc(begin.x, begin.y, 3, 0, 2 * Math.PI);
-      ctx.closePath();
-      ctx.fill();
-    }
-
-
-    if (end.dir !== 'RIGHT' && end.dir !== 'LEFT') {
-      // draw a circle if we the line has a vertical connection
-      ctx.fillStyle = color;
-      ctx.beginPath();
-      ctx.arc(end.x, end.y, CIRCLE_RADIUS, 0, 2 * Math.PI);
-      ctx.closePath();
-      ctx.fill();
-    } else {
-      const dx = this.getDeltaX(end.dir, TRIANGLE_SIZE);
-      const dy = this.getDeltaY(end.dir, TRIANGLE_SIZE);
-      // draw small triangle
-      ctx.fillStyle = color;
-      ctx.beginPath();
-      ctx.moveTo(end.x, end.y);
-      ctx.lineTo(end.x - dx - dy, end.y + dx - dy);
-      ctx.lineTo(end.x - dx + dy, end.y - dx - dy);
-      ctx.closePath();
-      ctx.fill();
-    }
-  }
-}
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 4349f81..54b55f8 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -12,18 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertTrue} from '../base/logging';
 import {Actions} from '../common/actions';
 import {HttpRpcState} from '../common/http_rpc_engine';
 import {
-  Area,
   FrontendLocalState as FrontendState,
   OmniboxState,
   Timestamped,
+  TimestampedAreaSelection,
   VisibleState,
 } from '../common/state';
 import {TimeSpan} from '../common/time';
 
+import {randomColor} from './colorizer';
 import {globals} from './globals';
 import {debounce, ratelimit} from './rate_limiters';
 import {TimeScale} from './time_scale';
@@ -70,14 +70,10 @@
   hoveredPid = -1;
   hoveredLogsTimestamp = -1;
   hoveredNoteTimestamp = -1;
-  highlightedSliceId = -1;
-  focusedFlowIdLeft = -1;
-  focusedFlowIdRight = -1;
   vidTimestamp = -1;
   localOnlyMode = false;
   sidebarVisible = true;
   showPanningHint = false;
-  showCookieConsent = false;
   visibleTracks = new Set<string>();
   prevVisibleTracks = new Set<string>();
   searchIndex = -1;
@@ -88,6 +84,8 @@
 
   // This is used to calculate the tracks within a Y range for area selection.
   areaY: Range = {};
+  // True if the user is in the process of doing an area selection.
+  selectingArea = false;
 
   private scrollBarWidth?: number;
 
@@ -104,7 +102,9 @@
     resolution: 1,
   };
 
-  private _selectedArea?: Area;
+  private _selectedArea: TimestampedAreaSelection = {
+    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
@@ -128,21 +128,6 @@
     globals.rafScheduler.scheduleRedraw();
   }
 
-  setHighlightedSliceId(sliceId: number) {
-    this.highlightedSliceId = sliceId;
-    globals.rafScheduler.scheduleRedraw();
-  }
-
-  setHighlightedFlowLeftId(flowId: number) {
-    this.focusedFlowIdLeft = flowId;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  setHighlightedFlowRightId(flowId: number) {
-    this.focusedFlowIdRight = flowId;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
   // Sets the timestamp at which a vertical line will be drawn.
   setHoveredLogsTimestamp(ts: number) {
     if (this.hoveredLogsTimestamp === ts) return;
@@ -183,6 +168,7 @@
 
   // Called when beginning a canvas redraw.
   clearVisibleTracks() {
+    this.prevVisibleTracks = new Set(this.visibleTracks);
     this.visibleTracks.clear();
   }
 
@@ -193,34 +179,100 @@
             value => this.visibleTracks.has(value))) {
       globals.dispatch(
           Actions.setVisibleTracks({tracks: Array.from(this.visibleTracks)}));
-      this.prevVisibleTracks = new Set(this.visibleTracks);
     }
   }
 
   mergeState(state: FrontendState): void {
     this._omniboxState = chooseLatest(this._omniboxState, state.omniboxState);
     this._visibleState = chooseLatest(this._visibleState, state.visibleState);
+    this._selectedArea = chooseLatest(this._selectedArea, state.selectedArea);
     if (this._visibleState === state.visibleState) {
       this.updateLocalTime(
           new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
     }
   }
 
+  private selectAreaDebounced = debounce(() => {
+    globals.dispatch(Actions.selectArea(this._selectedArea));
+  }, 20);
+
   selectArea(
       startSec: number, endSec: number,
-      tracks = this._selectedArea ? this._selectedArea.tracks : []) {
-    assertTrue(endSec >= startSec);
+      tracks = this._selectedArea.area ? this._selectedArea.area.tracks : []) {
+    if (this.currentNoteSelectionEqualToCurrentAreaSelection()) {
+      globals.dispatch(Actions.deselect({}));
+    }
     this.showPanningHint = true;
-    this._selectedArea = {startSec, endSec, tracks},
+    this._selectedArea = {
+      area: {startSec, endSec, tracks},
+      lastUpdate: Date.now() / 1000
+    };
+    this.selectAreaDebounced();
+    globals.rafScheduler.scheduleFullRedraw();
+  }
+
+  toggleTrackSelection(id: string, isTrackGroup = false) {
+    const area = this._selectedArea.area;
+    if (!area) return;
+    const index = area.tracks.indexOf(id);
+    if (index > -1) {
+      area.tracks.splice(index, 1);
+      if (isTrackGroup) {  // Also remove all child tracks.
+        for (const childTrack of globals.state.trackGroups[id].tracks) {
+          const childIndex = area.tracks.indexOf(childTrack);
+          if (childIndex > -1) {
+            area.tracks.splice(childIndex, 1);
+          }
+        }
+      }
+    } else {
+      area.tracks.push(id);
+      if (isTrackGroup) {  // Also add all child tracks.
+        for (const childTrack of globals.state.trackGroups[id].tracks) {
+          if (!area.tracks.includes(childTrack)) {
+            area.tracks.push(childTrack);
+          }
+        }
+      }
+    }
+    this._selectedArea.lastUpdate = Date.now() / 1000;
+    this.selectAreaDebounced();
+    globals.rafScheduler.scheduleFullRedraw();
+  }
+
+  toggleLockArea() {
+    if (!this._selectedArea.area) return;
+    if (this.currentNoteSelectionEqualToCurrentAreaSelection()) {
+      if (globals.state.currentSelection != null &&
+          globals.state.currentSelection.kind === 'NOTE') {
+        globals.dispatch(
+            Actions.removeNote({id: globals.state.currentSelection.id}));
+      }
+    } else {
+      const color = randomColor();
+      globals.dispatch(Actions.addAreaNote({
+        timestamp: this._selectedArea.area.startSec,
+        area: this._selectedArea.area,
+        color
+      }));
+    }
+
     globals.rafScheduler.scheduleFullRedraw();
   }
 
   deselectArea() {
-    this._selectedArea = undefined;
-    globals.rafScheduler.scheduleRedraw();
+    // When an area is deselected (and it is marked) also deselect the current
+    // marked selection if it is for the same area.
+    if (this.currentNoteSelectionEqualToCurrentAreaSelection()) {
+      globals.dispatch(Actions.deselect({}));
+    }
+    this._selectedArea = {lastUpdate: Date.now() / 1000};
+    this.selectAreaDebounced();
+    globals.frontendLocalState.currentTab = undefined;
+    globals.rafScheduler.scheduleFullRedraw();
   }
 
-  get selectedArea(): Area|undefined {
+  get selectedArea(): TimestampedAreaSelection {
     return this._selectedArea;
   }
 
@@ -249,13 +301,27 @@
     const endSec = capBetween(ts.end, traceTime.startSec, traceTime.endSec);
     this.visibleWindowTime = new TimeSpan(startSec, endSec);
     this.timeScale.setTimeBounds(this.visibleWindowTime);
-    this.updateResolution();
+    this.updateResolution(this.timeScale.startPx, this.timeScale.endPx);
   }
 
-  private updateResolution() {
-    this._visibleState.lastUpdate = Date.now() / 1000;
-    this._visibleState.resolution = globals.getCurResolution();
-    this.ratelimitedUpdateVisible();
+  // We lock an area selection by adding an area note. When we select the note
+  // it will also select the area but then the user can select other things,
+  // like a slice or different note and the area note will be deselected even
+  // though the area selection remains. So it is useful to know if we currently
+  // have the same area note selected and area selection.
+  private currentNoteSelectionEqualToCurrentAreaSelection() {
+    if (!this._selectedArea.area) return false;
+    if (globals.state.currentSelection != null &&
+        globals.state.currentSelection.kind === 'NOTE') {
+      const curNote = globals.state.notes[globals.state.currentSelection.id];
+      // TODO(taylori): Do the tracks need to be the same too?
+      if (curNote.noteType === 'AREA' &&
+          curNote.area.startSec === this._selectedArea.area.startSec &&
+          curNote.area.endSec === this._selectedArea.area.endSec) {
+        return true;
+      }
+    }
+    return false;
   }
 
   updateVisibleTime(ts: TimeSpan) {
@@ -267,19 +333,10 @@
     this.ratelimitedUpdateVisible();
   }
 
-  getVisibleStateBounds(): [number, number] {
-    return [this.visibleWindowTime.start, this.visibleWindowTime.end];
-  }
-
-  // Whenever start/end px of the timeScale is changed, update
-  // the resolution.
-  updateLocalLimits(pxStart: number, pxEnd: number) {
-    // Numbers received here can be negative or equal, but we should fix that
-    // before updating the timescale.
-    pxStart = Math.max(0, pxStart);
-    pxEnd = Math.max(0, pxEnd);
-    if (pxStart === pxEnd) pxEnd = pxStart + 1;
+  updateResolution(pxStart: number, pxEnd: number) {
     this.timeScale.setLimitsPx(pxStart, pxEnd);
-    this.updateResolution();
+    this._visibleState.lastUpdate = Date.now() / 1000;
+    this._visibleState.resolution = globals.getCurResolution();
+    this.ratelimitedUpdateVisible();
   }
 }
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index dd1e858..5b859ad 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -15,12 +15,8 @@
 import {assertExists} from '../base/logging';
 import {DeferredAction} from '../common/actions';
 import {AggregateData} from '../common/aggregation_data';
-import {Args, ArgsTree} from '../common/arg_types';
-import {MetricResult} from '../common/metric_data';
 import {CurrentSearchResults, SearchSummary} from '../common/search_data';
 import {CallsiteInfo, createEmptyState, State} from '../common/state';
-import {fromNs, toNs} from '../common/time';
-import {Analytics, initAnalytics} from '../frontend/analytics';
 
 import {FrontendLocalState} from './frontend_local_state';
 import {RafScheduler} from './raf_scheduler';
@@ -31,6 +27,8 @@
 type QueryResultsStore = Map<string, {}>;
 type AggregateDataStore = Map<string, AggregateData>;
 type Description = Map<string, string>;
+export type Arg = string|{kind: 'SLICE', trackId: string, sliceId: number};
+export type Args = Map<string, Arg>;
 export interface SliceDetails {
   ts?: number;
   dur?: number;
@@ -38,7 +36,6 @@
   endState?: string;
   cpu?: number;
   id?: number;
-  threadStateId?: number;
   utid?: number;
   wakeupTs?: number;
   wakerUtid?: number;
@@ -46,32 +43,9 @@
   category?: string;
   name?: string;
   args?: Args;
-  argsTree?: ArgsTree;
   description?: Description;
 }
 
-export interface FlowPoint {
-  trackId: number;
-
-  sliceName: string;
-  sliceCategory: string;
-  sliceId: number;
-  sliceStartTs: number;
-  sliceEndTs: number;
-
-  depth: number;
-}
-
-export interface Flow {
-  id: number;
-
-  begin: FlowPoint;
-  end: FlowPoint;
-
-  category?: string;
-  name?: string;
-}
-
 export interface CounterDetails {
   startTime?: number;
   value?: number;
@@ -79,16 +53,6 @@
   duration?: number;
 }
 
-export interface ThreadStateDetails {
-  ts?: number;
-  dur?: number;
-  state?: string;
-  utid?: number;
-  cpu?: number;
-  sliceId?: number;
-  blockedFunction?: string;
-}
-
 export interface HeapProfileDetails {
   type?: string;
   id?: number;
@@ -122,33 +86,19 @@
   threadName: string;
   pid?: number;
   procName?: string;
-  cmdline?: string;
 }
 type ThreadMap = Map<number, ThreadDesc>;
 
-function getRoot() {
-  // Works out the root directory where the content should be served from
-  // e.g. `http://origin/v1.2.3/`.
-  let root = (document.currentScript as HTMLScriptElement).src;
-  root = root.substr(0, root.lastIndexOf('/') + 1);
-  return root;
-}
-
 /**
  * Global accessors for state/dispatch in the frontend.
  */
 class Globals {
-  readonly root = getRoot();
-
   private _dispatch?: Dispatch = undefined;
   private _controllerWorker?: Worker = undefined;
   private _state?: State = undefined;
   private _frontendLocalState?: FrontendLocalState = undefined;
   private _rafScheduler?: RafScheduler = undefined;
   private _serviceWorkerController?: ServiceWorkerController = undefined;
-  private _logging?: Analytics = undefined;
-  private _isInternalUser: boolean|undefined = undefined;
-  private _channel: string|undefined = undefined;
 
   // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
   private _trackDataStore?: TrackDataStore = undefined;
@@ -157,24 +107,17 @@
   private _aggregateDataStore?: AggregateDataStore = undefined;
   private _threadMap?: ThreadMap = undefined;
   private _sliceDetails?: SliceDetails = undefined;
-  private _threadStateDetails?: ThreadStateDetails = undefined;
-  private _connectedFlows?: Flow[] = undefined;
-  private _selectedFlows?: Flow[] = undefined;
-  private _visibleFlowCategories?: Map<string, boolean> = undefined;
   private _counterDetails?: CounterDetails = undefined;
   private _heapProfileDetails?: HeapProfileDetails = undefined;
   private _cpuProfileDetails?: CpuProfileDetails = undefined;
   private _numQueriesQueued = 0;
   private _bufferUsage?: number = undefined;
   private _recordingLog?: string = undefined;
-  private _traceErrors?: number = undefined;
-  private _metricError?: string = undefined;
-  private _metricResult?: MetricResult = undefined;
 
   private _currentSearchResults: CurrentSearchResults = {
-    sliceIds: [],
-    tsStarts: [],
-    utids: [],
+    sliceIds: new Float64Array(0),
+    tsStarts: new Float64Array(0),
+    utids: new Float64Array(0),
     trackIds: [],
     sources: [],
     totalResults: 0,
@@ -185,6 +128,11 @@
     count: new Uint8Array(0),
   };
 
+  // This variable is set by the is_internal_user.js script if the user is a
+  // googler. This is used to avoid exposing features that are not ready yet
+  // for public consumption. The gated features themselves are not secret.
+  isInternalUser = false;
+
   initialize(dispatch: Dispatch, controllerWorker: Worker) {
     this._dispatch = dispatch;
     this._controllerWorker = controllerWorker;
@@ -192,7 +140,6 @@
     this._frontendLocalState = new FrontendLocalState();
     this._rafScheduler = new RafScheduler();
     this._serviceWorkerController = new ServiceWorkerController();
-    this._logging = initAnalytics();
 
     // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
     this._trackDataStore = new Map<string, {}>();
@@ -201,11 +148,7 @@
     this._aggregateDataStore = new Map<string, AggregateData>();
     this._threadMap = new Map<number, ThreadDesc>();
     this._sliceDetails = {};
-    this._connectedFlows = [];
-    this._selectedFlows = [];
-    this._visibleFlowCategories = new Map<string, boolean>();
     this._counterDetails = {};
-    this._threadStateDetails = {};
     this._heapProfileDetails = {};
     this._cpuProfileDetails = {};
   }
@@ -230,10 +173,6 @@
     return assertExists(this._rafScheduler);
   }
 
-  get logging() {
-    return assertExists(this._logging);
-  }
-
   get serviceWorkerController() {
     return assertExists(this._serviceWorkerController);
   }
@@ -263,38 +202,6 @@
     this._sliceDetails = assertExists(click);
   }
 
-  get threadStateDetails() {
-    return assertExists(this._threadStateDetails);
-  }
-
-  set threadStateDetails(click: ThreadStateDetails) {
-    this._threadStateDetails = assertExists(click);
-  }
-
-  get connectedFlows() {
-    return assertExists(this._connectedFlows);
-  }
-
-  set connectedFlows(connectedFlows: Flow[]) {
-    this._connectedFlows = assertExists(connectedFlows);
-  }
-
-  get selectedFlows() {
-    return assertExists(this._selectedFlows);
-  }
-
-  set selectedFlows(selectedFlows: Flow[]) {
-    this._selectedFlows = assertExists(selectedFlows);
-  }
-
-  get visibleFlowCategories() {
-    return assertExists(this._visibleFlowCategories);
-  }
-
-  set visibleFlowCategories(visibleFlowCategories: Map<string, boolean>) {
-    this._visibleFlowCategories = assertExists(visibleFlowCategories);
-  }
-
   get counterDetails() {
     return assertExists(this._counterDetails);
   }
@@ -315,30 +222,6 @@
     this._heapProfileDetails = assertExists(click);
   }
 
-  get traceErrors() {
-    return this._traceErrors;
-  }
-
-  setTraceErrors(arg: number) {
-    this._traceErrors = arg;
-  }
-
-  get metricError() {
-    return this._metricError;
-  }
-
-  setMetricError(arg: string) {
-    this._metricError = arg;
-  }
-
-  get metricResult() {
-    return this._metricResult;
-  }
-
-  setMetricResult(result: MetricResult) {
-    this._metricResult = result;
-  }
-
   get cpuProfileDetails() {
     return assertExists(this._cpuProfileDetails);
   }
@@ -388,41 +271,17 @@
   }
 
   getCurResolution() {
-    // Truncate the resolution to the closest power of 2 (in nanosecond space).
-    // We choose to work in ns space because resolution is consumed be track
-    // controllers for quantization and they rely on resolution to be a power
-    // of 2 in nanosecond form. This is property does not hold if we work in
-    // second space.
-    //
-    // This effectively means the resolution changes approximately every 6 zoom
-    // levels. Logic: each zoom level represents a delta of 0.1 * (visible
-    // window span). Therefore, zooming out by six levels is 1.1^6 ~= 2.
-    // Similarily, zooming in six levels is 0.9^6 ~= 0.5.
-    const pxToSec = this.frontendLocalState.timeScale.deltaPxToDuration(1);
-    // TODO(b/186265930): Remove once fixed:
-    if (!isFinite(pxToSec)) {
-      // Resolution is in pixels per second so 1000 means 1px = 1ms.
-      console.error(`b/186265930: Bad pxToSec suppressed ${pxToSec}`);
-      return fromNs(Math.pow(2, Math.floor(Math.log2(toNs(1000)))));
-    }
-    const pxToNs = Math.max(toNs(pxToSec), 1);
-    const resolution = fromNs(Math.pow(2, Math.floor(Math.log2(pxToNs))));
-    const log2 = Math.log2(toNs(resolution));
-    if (log2 % 1 !== 0) {
-      throw new Error(`Resolution should be a power of two.
-        pxToSec: ${pxToSec},
-        pxToNs: ${pxToNs},
-        resolution: ${resolution},
-        log2: ${Math.log2(toNs(resolution))}`);
-    }
-    return resolution;
+    // Truncate the resolution to the closest power of 2.
+    // This effectively means the resolution changes every 6 zoom levels.
+    const resolution = this.frontendLocalState.timeScale.deltaPxToDuration(1);
+    return Math.pow(2, Math.floor(Math.log2(resolution)));
   }
 
-  makeSelection(action: DeferredAction<{}>, tabToOpen = 'current_selection') {
+  makeSelection(action: DeferredAction<{}>) {
     // A new selection should cancel the current search selection.
     globals.frontendLocalState.searchIndex = -1;
     globals.frontendLocalState.currentTab =
-        action.type === 'deselect' ? undefined : tabToOpen;
+        action.type === 'deselect' ? undefined : 'current_selection';
     globals.dispatch(action);
   }
 
@@ -439,45 +298,18 @@
     this._overviewStore = undefined;
     this._threadMap = undefined;
     this._sliceDetails = undefined;
-    this._threadStateDetails = undefined;
     this._aggregateDataStore = undefined;
     this._numQueriesQueued = 0;
-    this._metricResult = undefined;
     this._currentSearchResults = {
-      sliceIds: [],
-      tsStarts: [],
-      utids: [],
+      sliceIds: new Float64Array(0),
+      tsStarts: new Float64Array(0),
+      utids: new Float64Array(0),
       trackIds: [],
       sources: [],
       totalResults: 0,
     };
   }
 
-  // This variable is set by the is_internal_user.js script if the user is a
-  // googler. This is used to avoid exposing features that are not ready yet
-  // for public consumption. The gated features themselves are not secret.
-  // If a user has been detected as a Googler once, make that sticky in
-  // localStorage, so that we keep treating them as such when they connect over
-  // public networks.
-  get isInternalUser() {
-    if (this._isInternalUser === undefined) {
-      this._isInternalUser = localStorage.getItem('isInternalUser') === '1';
-    }
-    return this._isInternalUser;
-  }
-
-  set isInternalUser(value: boolean) {
-    localStorage.setItem('isInternalUser', value ? '1' : '0');
-    this._isInternalUser = value;
-  }
-
-  get channel() {
-    if (this._channel === undefined) {
-      this._channel = localStorage.getItem('perfettoUiChannel') || 'stable';
-    }
-    return this._channel;
-  }
-
   // Used when switching to the legacy TraceViewer UI.
   // Most resources are cleaned up by replacing the current |window| object,
   // however pending RAFs and workers seem to outlive the |window| and need to
diff --git a/ui/src/frontend/heap_profile_panel.ts b/ui/src/frontend/heap_profile_panel.ts
index 3957dce..d95fd77 100644
--- a/ui/src/frontend/heap_profile_panel.ts
+++ b/ui/src/frontend/heap_profile_panel.ts
@@ -99,6 +99,7 @@
                 this.onMouseMove({y: e.layerY, x: e.layerX});
                 globals.rafScheduler.scheduleRedraw();
               }
+              return false;
             },
             onmouseout: () => {
               if (this.flamegraph !== undefined) {
diff --git a/ui/src/frontend/help_modal.ts b/ui/src/frontend/help_modal.ts
index a562f47..114438d 100644
--- a/ui/src/frontend/help_modal.ts
+++ b/ui/src/frontend/help_modal.ts
@@ -15,7 +15,6 @@
 
 import * as m from 'mithril';
 
-import {globals} from './globals';
 import {hideModel, showModal} from './modal';
 
 let helpModelOpen = false;
@@ -24,7 +23,6 @@
   if (helpModelOpen) {
     hideHelp();
   } else {
-    globals.logging.logEvent('User Actions', 'Show help');
     showHelp();
   }
 }
@@ -66,31 +64,8 @@
               m('td', keycap('f'), ' (with event selected)'),
               m('td', 'Scroll + zoom to current selection')),
             m('tr',
-              m('td', keycap('['), '/', keycap(']'), ' (with event selected)'),
-              m('td',
-                'Select next/previous slice that is connected by a flow.',
-                m('br'),
-                'If there are multiple flows,' +
-                    'the one that is in focus (bold) is selected')),
-            m('tr',
-              m('td',
-                keycap('Ctrl'),
-                ' + ',
-                keycap('['),
-                '/',
-                keycap(']'),
-                ' (with event selected)'),
-              m('td', 'Switch focus to another flow')),
-            m('tr',
               m('td', keycap('m'), ' (with event or area selected)'),
-              m('td', 'Mark the area (temporarily)')),
-            m('tr',
-              m('td',
-                keycap('Shift'),
-                ' + ',
-                keycap('m'),
-                ' (with event or area selected)'),
-              m('td', 'Mark the area (persistently)')),
+              m('td', 'Mark the area')),
             m('tr', m('td', keycap('?')), m('td', 'Show help')),
             )),
     buttons: [],
diff --git a/ui/src/frontend/home_page.ts b/ui/src/frontend/home_page.ts
index 91a3186..721f0bb 100644
--- a/ui/src/frontend/home_page.ts
+++ b/ui/src/frontend/home_page.ts
@@ -13,52 +13,14 @@
 // limitations under the License.
 
 import * as m from 'mithril';
-import {globals} from './globals';
 
 import {createPage} from './pages';
 
-let channelChanged = false;
-
 export const HomePage = createPage({
   view() {
     return m(
         '.page.home-page',
-        m(
-            '.home-page-center',
-            m('.home-page-title', 'Perfetto'),
-            m(`img.logo[src=${globals.root}assets/logo-3d.png]`),
-            m(
-                'div.channel-select',
-                m('div',
-                  'Feeling adventurous? Try our bleeding edge Canary version'),
-                m(
-                    'fieldset',
-                    mkChan('stable'),
-                    mkChan('canary'),
-                    m('.highlight'),
-                    ),
-                m(`.home-page-reload${channelChanged ? '.show' : ''}`,
-                  'You need to reload the page for the changes to have effect'),
-                ),
-            ),
-        m('a.privacy',
-          {href: 'https://policies.google.com/privacy', target: '_blank'},
-          'Privacy policy'));
-  }
+        m('.home-page-title', 'Perfetto'),
+        m('img.logo[src=assets/logo-3d.png]'), );
+  },
 });
-
-function mkChan(chan: string) {
-  const checked =
-      !channelChanged && globals.channel === chan ? '[checked=true]' : '';
-  return [
-    m(`input[type=radio][name=chan][id=chan_${chan}]${checked}`,
-      {onchange: () => changeChannel(chan)}),
-    m(`label[for=chan_${chan}]`, chan),
-  ];
-}
-
-function changeChannel(chan: string) {
-  localStorage.setItem('perfettoUiChannel', chan);
-  channelChanged = true;
-  globals.rafScheduler.scheduleFullRedraw();
-}
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index 5b2814e..b7686102 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -15,9 +15,9 @@
 import '../tracks/all_frontend';
 
 import {applyPatches, Patch} from 'immer';
+import * as MicroModal from 'micromodal';
 import * as m from 'mithril';
 
-import {defer} from '../base/deferred';
 import {assertExists, reportError, setErrorHandler} from '../base/logging';
 import {forwardRemoteCalls} from '../base/remote';
 import {Actions} from '../common/actions';
@@ -28,43 +28,29 @@
   LogExists,
   LogExistsKey
 } from '../common/logs';
-import {MetricResult} from '../common/metric_data';
 import {CurrentSearchResults, SearchSummary} from '../common/search_data';
 
 import {AnalyzePage} from './analyze_page';
-import {loadAndroidBugToolInfo} from './android_bug_tool';
-import {initCssConstants} from './css_constants';
 import {maybeShowErrorDialog} from './error_dialog';
-import {installFileDropHandler} from './file_drop_handler';
 import {
   CounterDetails,
   CpuProfileDetails,
-  Flow,
   globals,
   HeapProfileDetails,
   QuantizedLoad,
   SliceDetails,
-  ThreadDesc,
-  ThreadStateDetails
+  ThreadDesc
 } from './globals';
 import {HomePage} from './home_page';
 import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer';
-import {initLiveReloadIfLocalhost} from './live_reload';
-import {MetricsPage} from './metrics_page';
 import {postMessageHandler} from './post_message_handler';
 import {RecordPage, updateAvailableAdbDevices} from './record_page';
 import {Router} from './router';
 import {CheckHttpRpcConnection} from './rpc_http_dialog';
-import {taskTracker} from './task_tracker';
-import {TraceInfoPage} from './trace_info_page';
 import {ViewerPage} from './viewer_page';
 
 const EXTENSION_ID = 'lfmkphfpdbjijhpomgecfikhfohaoine';
 
-function isLocalhostTraceUrl(url: string): boolean {
-  return ['127.0.0.1', 'localhost'].includes((new URL(url)).hostname);
-}
-
 /**
  * The API the main thread exposes to the controller.
  */
@@ -136,43 +122,6 @@
     this.redraw();
   }
 
-  publishThreadStateDetails(click: ThreadStateDetails) {
-    globals.threadStateDetails = click;
-    this.redraw();
-  }
-
-  publishConnectedFlows(connectedFlows: Flow[]) {
-    globals.connectedFlows = connectedFlows;
-    // Call resetFlowFocus() each time connectedFlows is updated to correctly
-    // navigate using hotkeys.
-    this.resetFlowFocus();
-    this.redraw();
-  }
-
-  // If a chrome slice is selected and we have any flows in connectedFlows
-  // we will find the flows on the right and left of that slice to set a default
-  // focus. In all other cases the focusedFlowId(Left|Right) will be set to -1.
-  resetFlowFocus() {
-    globals.frontendLocalState.focusedFlowIdLeft = -1;
-    globals.frontendLocalState.focusedFlowIdRight = -1;
-    if (globals.state.currentSelection?.kind === 'CHROME_SLICE') {
-      const sliceId = globals.state.currentSelection.id;
-      for (const flow of globals.connectedFlows) {
-        if (flow.begin.sliceId === sliceId) {
-          globals.frontendLocalState.focusedFlowIdRight = flow.id;
-        }
-        if (flow.end.sliceId === sliceId) {
-          globals.frontendLocalState.focusedFlowIdLeft = flow.id;
-        }
-      }
-    }
-  }
-
-  publishSelectedFlows(selectedFlows: Flow[]) {
-    globals.selectedFlows = selectedFlows;
-    this.redraw();
-  }
-
   publishCounterDetails(click: CounterDetails) {
     globals.counterDetails = click;
     this.redraw();
@@ -211,7 +160,6 @@
     const arr = new Uint8Array(args.data, 0, args.size);
     const str = (new TextDecoder('utf-8')).decode(arr);
     openBufferWithLegacyTraceViewer('trace.json', str, 0);
-    globals.dispatch(Actions.clearConversionInProgress({}));
   }
 
   publishBufferUsage(args: {percentage: number}) {
@@ -234,22 +182,6 @@
     this.redraw();
   }
 
-  publishTraceErrors(numErrors: number) {
-    globals.setTraceErrors(numErrors);
-    this.redraw();
-  }
-
-  publishMetricError(error: string) {
-    globals.setMetricError(error);
-    globals.logging.logError(error, false);
-    this.redraw();
-  }
-
-  publishMetricResult(metricResult: MetricResult) {
-    globals.setMetricResult(metricResult);
-    this.redraw();
-  }
-
   publishAggregateData(args: {data: AggregateData, kind: string}) {
     globals.setAggregateData(args.kind, args.data);
     this.redraw();
@@ -271,81 +203,27 @@
   }));
 }
 
-function setupContentSecurityPolicy() {
-  // Note: self and sha-xxx must be quoted, urls data: and blob: must not.
-  const policy = {
-    'default-src': [
-      `'self'`,
-      // Google Tag Manager bootstrap.
-      `'sha256-LirUKeorCU4uRNtNzr8tlB11uy8rzrdmqHCX38JSwHY='`,
-    ],
-    'script-src': [
-      `'self'`,
-      'https://*.google.com',
-      'https://*.googleusercontent.com',
-      'https://www.googletagmanager.com',
-      'https://www.google-analytics.com',
-    ],
-    'object-src': ['none'],
-    'connect-src': [
-      `'self'`,
-      'http://127.0.0.1:9001',  // For trace_processor_shell --httpd.
-      'https://www.google-analytics.com',
-      'https://*.googleapis.com',  // For Google Cloud Storage fetches.
-      'blob:',
-      'data:',
-    ],
-    'img-src': [
-      `'self'`,
-      'data:',
-      'blob:',
-      'https://www.google-analytics.com',
-      'https://www.googletagmanager.com',
-    ],
-    'navigate-to': ['https://*.perfetto.dev', 'self'],
-  };
-  const meta = document.createElement('meta');
-  meta.httpEquiv = 'Content-Security-Policy';
-  let policyStr = '';
-  for (const [key, list] of Object.entries(policy)) {
-    policyStr += `${key} ${list.join(' ')}; `;
+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}));
   }
-  meta.content = policyStr;
-  document.head.appendChild(meta);
 }
 
 function main() {
-  setupContentSecurityPolicy();
-
-  // Load the css. The load is asynchronous and the CSS is not ready by the time
-  // appenChild returns.
-  const cssLoadPromise = defer<void>();
-  const css = document.createElement('link');
-  css.rel = 'stylesheet';
-  css.href = globals.root + 'perfetto.css';
-  css.onload = () => cssLoadPromise.resolve();
-  css.onerror = (err) => cssLoadPromise.reject(err);
-  const favicon = document.head.querySelector('#favicon') as HTMLLinkElement;
-  if (favicon) favicon.href = globals.root + 'assets/favicon.png';
-
-  // Load the script to detect if this is a Googler (see comments on globals.ts)
-  // and initialize GA after that (or after a timeout if something goes wrong).
-  const script = document.createElement('script');
-  script.src =
-      'https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js';
-  script.async = true;
-  script.onerror = () => globals.logging.initialize();
-  script.onload = () => globals.logging.initialize();
-  setTimeout(() => globals.logging.initialize(), 5000);
-
-  document.head.append(script, css);
-
   // 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(globals.root + 'controller_bundle.js');
+  const controller = new Worker('controller_bundle.js');
   const frontendChannel = new MessageChannel();
   const controllerChannel = new MessageChannel();
   const extensionLocalChannel = new MessageChannel();
@@ -370,22 +248,18 @@
 
   const dispatch =
       controllerChannel.port2.postMessage.bind(controllerChannel.port2);
-  globals.initialize(dispatch, controller);
-  globals.serviceWorkerController.install();
-
   const router = new Router(
       '/',
       {
         '/': HomePage,
         '/viewer': ViewerPage,
         '/record': RecordPage,
-        '/query': AnalyzePage,
-        '/metrics': MetricsPage,
-        '/info': TraceInfoPage,
+        '/analyze': AnalyzePage,
       },
-      dispatch,
-      globals.logging);
+      dispatch);
   forwardRemoteCalls(frontendChannel.port2, new FrontendApi(router));
+  globals.initialize(dispatch, controller);
+  globals.serviceWorkerController.install();
 
   // We proxy messages between the extension and the controller because the
   // controller's worker can't access chrome.runtime.
@@ -404,92 +278,12 @@
     // 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);
   }
 
-  // This forwards the messages from the controller to the extension
-  extensionLocalChannel.port2.onmessage = ({data}) => {
-    if (extensionPort) extensionPort.postMessage(data);
-  };
-
-  // 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;
-
-  // Prevent pinch zoom.
-  document.body.addEventListener('wheel', (e: MouseEvent) => {
-    if (e.ctrlKey) e.preventDefault();
-  }, {passive: false});
-
-  cssLoadPromise.then(() => onCssLoaded(router));
-}
-
-function onCssLoaded(router: Router) {
-  initCssConstants();
-  // Clear all the contents of the initial page (e.g. the <pre> error message)
-  // And replace it with the root <main> element which will be used by mithril.
-  document.body.innerHTML = '<main></main>';
-  const main = assertExists(document.body.querySelector('main'));
-  globals.rafScheduler.domRedraw = () =>
-      m.render(main, m(router.resolve(globals.state.route)));
-
-  router.navigateToCurrentHash();
-
-  // /?s=xxxx for permalinks.
-  const stateHash = Router.param('s');
-  const urlHash = Router.param('url');
-  const androidBugTool = Router.param('openFromAndroidBugTool');
-  if (typeof stateHash === 'string' && stateHash) {
-    globals.dispatch(Actions.loadPermalink({
-      hash: stateHash,
-    }));
-  } else if (typeof urlHash === 'string' && urlHash) {
-    if (isLocalhostTraceUrl(urlHash)) {
-      const fileName = urlHash.split('/').pop() || 'local_trace.pftrace';
-      const request = fetch(urlHash)
-                          .then(response => response.blob())
-                          .then(blob => {
-                            globals.dispatch(Actions.openTraceFromFile({
-                              file: new File([blob], fileName),
-                            }));
-                          })
-                          .catch(e => alert(`Could not load local trace ${e}`));
-      taskTracker.trackPromise(request, 'Downloading local trace');
-    } else {
-      globals.dispatch(Actions.openTraceFromUrl({
-        url: urlHash,
-      }));
-    }
-  } else if (androidBugTool) {
-    // TODO(hjd): Unify updateStatus and TaskTracker
-    globals.dispatch(Actions.updateStatus({
-      msg: 'Loading trace from ABT extension',
-      timestamp: Date.now() / 1000
-    }));
-    const loadInfo = loadAndroidBugToolInfo();
-    taskTracker.trackPromise(loadInfo, 'Loading trace from ABT extension');
-    loadInfo
-        .then(info => {
-          globals.dispatch(Actions.openTraceFromFile({
-            file: info.file,
-          }));
-        })
-        .catch(e => {
-          console.error(e);
-        });
-  }
-
-  // Add support for opening traces from postMessage().
-  window.addEventListener('message', postMessageHandler, {passive: true});
-
-  // 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();
-  initLiveReloadIfLocalhost();
-
   updateAvailableAdbDevices();
   try {
     navigator.usb.addEventListener(
@@ -499,7 +293,49 @@
   } catch (e) {
     console.error('WebUSB API not supported');
   }
-  installFileDropHandler();
+  // 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)));
+
+  // 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.
+  document.body.addEventListener('wheel', (e: MouseEvent) => {
+    if (e.ctrlKey) e.preventDefault();
+  }, {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 7d82ac2..5b08351 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -13,30 +13,26 @@
 // limitations under the License.
 
 import {Actions} from '../common/actions';
-import {Area} from '../common/state';
 
-import {Flow, globals} from './globals';
+import {globals} from './globals';
 import {toggleHelp} from './help_modal';
 import {
-  findUiTrackId,
   horizontalScrollAndZoomToRange,
   verticalScrollToTrack
 } from './scroll_helper';
 import {executeSearch} from './search_handler';
 
-const INSTANT_FOCUS_DURATION_S = 1 / 1e9;  // 1 ns.
-type Direction = 'Forward'|'Backward';
-
 // 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();
-  const selection = globals.state.currentSelection;
   if (down && 'm' === key) {
-    if (selection && selection.kind === 'AREA') {
-      globals.dispatch(Actions.toggleMarkCurrentArea({persistent: e.shiftKey}));
-    } else if (selection) {
-      lockSliceSpan(e.shiftKey);
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
+    if (!selectedArea && globals.state.currentSelection !== null) {
+      selectSliceSpan();
+    }
+    if (selectedArea) {
+      globals.frontendLocalState.toggleLockArea();
     }
   }
   if (down && 'f' === key) {
@@ -66,103 +62,6 @@
     e.preventDefault();
     executeSearch(e.shiftKey);
   }
-  if (down && 'escape' === key) {
-    globals.frontendLocalState.deselectArea();
-    globals.makeSelection(Actions.deselect({}));
-    globals.dispatch(Actions.removeNote({id: '0'}));
-  }
-  if (down && ']' === key) {
-    if (e.ctrlKey) {
-      focusOtherFlow('Forward');
-    } else {
-      moveByFocusedFlow('Forward');
-    }
-  }
-  if (down && '[' === key) {
-    if (e.ctrlKey) {
-      focusOtherFlow('Backward');
-    } else {
-      moveByFocusedFlow('Backward');
-    }
-  }
-}
-
-// Search |boundFlows| for |flowId| and return the id following it.
-// Returns the first flow id if nothing was found or |flowId| was the last flow
-// in |boundFlows|, and -1 if |boundFlows| is empty
-function findAnotherFlowExcept(boundFlows: Flow[], flowId: number): number {
-  let selectedFlowFound = false;
-
-  if (boundFlows.length === 0) {
-    return -1;
-  }
-
-  for (const flow of boundFlows) {
-    if (selectedFlowFound) {
-      return flow.id;
-    }
-
-    if (flow.id === flowId) {
-      selectedFlowFound = true;
-    }
-  }
-  return boundFlows[0].id;
-}
-
-// Change focus to the next flow event (matching the direction)
-function focusOtherFlow(direction: Direction) {
-  if (!globals.state.currentSelection ||
-      globals.state.currentSelection.kind !== 'CHROME_SLICE') {
-    return;
-  }
-  const sliceId = globals.state.currentSelection.id;
-  if (sliceId === -1) {
-    return;
-  }
-
-  const boundFlows = globals.connectedFlows.filter(
-      flow => flow.begin.sliceId === sliceId && direction === 'Forward' ||
-          flow.end.sliceId === sliceId && direction === 'Backward');
-
-  if (direction === 'Backward') {
-    const nextFlowId = findAnotherFlowExcept(
-        boundFlows, globals.frontendLocalState.focusedFlowIdLeft);
-    globals.frontendLocalState.setHighlightedFlowLeftId(nextFlowId);
-  } else {
-    const nextFlowId = findAnotherFlowExcept(
-        boundFlows, globals.frontendLocalState.focusedFlowIdRight);
-    globals.frontendLocalState.setHighlightedFlowRightId(nextFlowId);
-  }
-}
-
-// Select the slice connected to the flow in focus
-function moveByFocusedFlow(direction: Direction) {
-  if (!globals.state.currentSelection ||
-      globals.state.currentSelection.kind !== 'CHROME_SLICE') {
-    return;
-  }
-
-  const sliceId = globals.state.currentSelection.id;
-  const flowId =
-      (direction === 'Backward' ?
-           globals.frontendLocalState.focusedFlowIdLeft :
-           globals.frontendLocalState.focusedFlowIdRight);
-
-  if (sliceId === -1 || flowId === -1) {
-    return;
-  }
-
-  // Find flow that is in focus and select corresponding slice
-  for (const flow of globals.connectedFlows) {
-    if (flow.id === flowId) {
-      const flowPoint = (direction === 'Backward' ? flow.begin : flow.end);
-      const uiTrackId = findUiTrackId(flowPoint.trackId);
-      if (uiTrackId) {
-        globals.makeSelection(Actions.selectChromeSlice(
-            {id: flowPoint.sliceId, trackId: uiTrackId, table: 'slice'}));
-      }
-    }
-  }
 }
 
 function findTimeRangeOfSelection() {
@@ -172,19 +71,13 @@
   if (selection !== null) {
     if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
       const slice = globals.sliceDetails;
-      if (slice.ts && slice.dur !== undefined && slice.dur > 0) {
+      if (slice.ts && slice.dur) {
         startTs = slice.ts + globals.state.traceTime.startSec;
         endTs = startTs + slice.dur;
-      } else if (slice.ts) {
-        startTs = slice.ts + globals.state.traceTime.startSec;
-        endTs = startTs + INSTANT_FOCUS_DURATION_S;
       }
     } else if (selection.kind === 'THREAD_STATE') {
-      const threadState = globals.threadStateDetails;
-      if (threadState.ts && threadState.dur) {
-        startTs = threadState.ts + globals.state.traceTime.startSec;
-        endTs = startTs + threadState.dur;
-      }
+      startTs = selection.ts;
+      endTs = startTs + selection.dur;
     } else if (selection.kind === 'COUNTER') {
       startTs = selection.leftTs;
       endTs = selection.rightTs;
@@ -193,16 +86,14 @@
   return {startTs, endTs};
 }
 
-
-function lockSliceSpan(persistent = false) {
+function selectSliceSpan() {
   const range = findTimeRangeOfSelection();
   if (range.startTs !== -1 && range.endTs !== -1 &&
-      globals.state.currentSelection !== null) {
+      globals.state.currentSelection) {
     const tracks = globals.state.currentSelection.trackId ?
         [globals.state.currentSelection.trackId] :
         [];
-    const area: Area = {startSec: range.startTs, endSec: range.endTs, tracks};
-    globals.dispatch(Actions.markArea({area, persistent}));
+    globals.frontendLocalState.selectArea(range.startTs, range.endTs, tracks);
   }
 }
 
diff --git a/ui/src/frontend/legacy_trace_viewer.ts b/ui/src/frontend/legacy_trace_viewer.ts
index 122a618..4f90fb7 100644
--- a/ui/src/frontend/legacy_trace_viewer.ts
+++ b/ui/src/frontend/legacy_trace_viewer.ts
@@ -15,30 +15,8 @@
 import * as m from 'mithril';
 import {inflate} from 'pako';
 import {assertTrue} from '../base/logging';
-import {globals} from './globals';
 import {showModal} from './modal';
 
-const CTRACE_HEADER = 'TRACE:\n';
-
-async function isCtrace(file: File): Promise<boolean> {
-  const fileName = file.name.toLowerCase();
-
-  if (fileName.endsWith('.ctrace')) {
-    return true;
-  }
-
-  // .ctrace files sometimes end with .txt. We can detect these via
-  // the presence of TRACE: near the top of the file.
-  if (fileName.endsWith('.txt')) {
-    const header = await readText(file.slice(0, 128));
-    if (header.includes(CTRACE_HEADER)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
 function readText(blob: Blob): Promise<string> {
   return new Promise((resolve, reject) => {
     const reader = new FileReader();
@@ -57,11 +35,8 @@
 export async function isLegacyTrace(file: File): Promise<boolean> {
   const fileName = file.name.toLowerCase();
   if (fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
-      fileName.endsWith('.zip') || fileName.endsWith('.html')) {
-    return true;
-  }
-
-  if (await isCtrace(file)) {
+      fileName.endsWith('.zip') || fileName.endsWith('.ctrace') ||
+      fileName.endsWith('.html')) {
     return true;
   }
 
@@ -86,7 +61,7 @@
   return false;
 }
 
-export async function openFileWithLegacyTraceViewer(file: File) {
+export function openFileWithLegacyTraceViewer(file: File) {
   const reader = new FileReader();
   reader.onload = () => {
     if (reader.result instanceof ArrayBuffer) {
@@ -101,7 +76,7 @@
     console.error(err);
   };
   if (file.name.endsWith('.gz') || file.name.endsWith('.zip') ||
-      await isCtrace(file)) {
+      file.name.endsWith('.ctrace')) {
     reader.readAsArrayBuffer(file);
   } else {
     reader.readAsText(file);
@@ -118,16 +93,17 @@
 
     // Handle .ctrace files.
     const enc = new TextDecoder('utf-8');
-    const header = enc.decode(data.slice(0, 128));
-    if (header.includes(CTRACE_HEADER)) {
-      const offset = header.indexOf(CTRACE_HEADER) + CTRACE_HEADER.length;
-      data = inflate(new Uint8Array(data.slice(offset)), {to: 'string'});
+    const header = enc.decode(data.slice(0, 7));
+    if (header === 'TRACE:\n') {
+      data = inflate(new Uint8Array(data.slice(7, size)), {to: 'string'});
     }
   }
 
   // The location.pathname mangling is to make this code work also when hosted
   // in a non-root sub-directory, for the case of CI artifacts.
-  const catapultUrl = globals.root + 'assets/catapult_trace_viewer.html';
+  const urlParts = location.pathname.split('/');
+  urlParts[urlParts.length - 1] = 'assets/catapult_trace_viewer.html';
+  const catapultUrl = urlParts.join('/');
   const newWin = window.open(catapultUrl) as Window;
   if (newWin) {
     // Popup succeedeed.
diff --git a/ui/src/frontend/live_reload.ts b/ui/src/frontend/live_reload.ts
deleted file mode 100644
index c30b6e0..0000000
--- a/ui/src/frontend/live_reload.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-let lastReloadDialogTime = 0;
-const kMinTimeBetweenDialogsMs = 10000;
-const changedPaths = new Set<string>();
-
-export function initLiveReloadIfLocalhost() {
-  if (!location.origin.startsWith('http://localhost:')) return;
-
-  const monitor = new EventSource('/live_reload');
-  monitor.onmessage = msg => {
-    const change = msg.data;
-    console.log('Live reload:', change);
-    changedPaths.add(change);
-    if (change.endsWith('.css')) {
-      reloadCSS();
-    } else if (change.endsWith('.html') || change.endsWith('.js')) {
-      reloadDelayed();
-    }
-  };
-  monitor.onerror = (err) => {
-    // In most cases the error is fired on reload, when the socket disconnects.
-    // Delay the error and the reconnection, so in the case of a reload we don't
-    // see any midleading message.
-    setTimeout(() => console.error('LiveReload SSE error', err), 1000);
-  };
-}
-
-function reloadCSS() {
-  const css = document.querySelector('link[rel=stylesheet]') as HTMLLinkElement;
-  if (!css) return;
-  const parent = css.parentElement!;
-  parent.removeChild(css);
-  parent.appendChild(css);
-}
-
-function reloadDelayed() {
-  setTimeout(() => {
-    let pathsStr = '';
-    for (const path of changedPaths) {
-      pathsStr += path + '\n';
-    }
-    changedPaths.clear();
-    if (Date.now() - lastReloadDialogTime < kMinTimeBetweenDialogsMs) return;
-    const reload = confirm(`${pathsStr}changed, click to reload`);
-    lastReloadDialogTime = Date.now();
-    if (reload) {
-      window.location.reload();
-    }
-  }, 1000);
-}
diff --git a/ui/src/frontend/logs_panel.ts b/ui/src/frontend/logs_panel.ts
index 3087935..f3b49e6 100644
--- a/ui/src/frontend/logs_panel.ts
+++ b/ui/src/frontend/logs_panel.ts
@@ -132,8 +132,7 @@
                 formatTimestamp(ts / 1e9 - globals.state.traceTime.startSec)),
               m('.cell', priorityLetter || '?'),
               m('.cell', tags[i]),
-              m('.cell', messages[i]),
-              m('br')));
+              m('.cell', messages[i])));
       }
     }
 
diff --git a/ui/src/frontend/metrics_page.ts b/ui/src/frontend/metrics_page.ts
deleted file mode 100644
index fa85032..0000000
--- a/ui/src/frontend/metrics_page.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import * as m from 'mithril';
-
-import {Actions} from '../common/actions';
-import {globals} from './globals';
-import {createPage} from './pages';
-
-function getCurrSelectedMetric() {
-  const {availableMetrics, selectedIndex} = globals.state.metrics;
-  if (!availableMetrics) return undefined;
-  if (selectedIndex === undefined) return undefined;
-  return availableMetrics[selectedIndex];
-}
-
-class MetricResult implements m.ClassComponent {
-  view() {
-    const metricResult = globals.metricResult;
-    if (metricResult === undefined) return undefined;
-    const currSelection = getCurrSelectedMetric();
-    if (!(metricResult && metricResult.name === currSelection)) {
-      return undefined;
-    }
-    if (metricResult.error !== undefined) {
-      return m('pre.metric-error', metricResult.error);
-    }
-    if (metricResult.resultString !== undefined) {
-      return m('pre', metricResult.resultString);
-    }
-    return undefined;
-  }
-}
-
-class MetricPicker implements m.ClassComponent {
-  view() {
-    const {availableMetrics, selectedIndex} = globals.state.metrics;
-    if (availableMetrics === undefined) return 'Loading metrics...';
-    if (availableMetrics.length === 0) return 'No metrics available';
-    if (selectedIndex === undefined) {
-      throw Error('Should not happen when avaibleMetrics is non-empty');
-    }
-
-    return m('div', [
-      'Select a metric:',
-      m('select',
-        {
-          selectedIndex: globals.state.metrics.selectedIndex,
-          onchange: (e: InputEvent) => {
-            globals.dispatch(Actions.setMetricSelectedIndex(
-                {index: (e.target as HTMLSelectElement).selectedIndex}));
-          },
-        },
-        availableMetrics.map(
-            metric => m('option', {value: metric, key: metric}, metric))),
-      m('button.metric-run-button',
-        {onclick: () => globals.dispatch(Actions.requestSelectedMetric({}))},
-        'Run'),
-    ]);
-  }
-}
-
-export const MetricsPage = createPage({
-  view() {
-    return m(
-        '.metrics-page',
-        m(MetricPicker),
-        m(MetricResult),
-    );
-  }
-});
diff --git a/ui/src/frontend/modal.ts b/ui/src/frontend/modal.ts
index 69482e3..0778e4c 100644
--- a/ui/src/frontend/modal.ts
+++ b/ui/src/frontend/modal.ts
@@ -32,23 +32,8 @@
   action: () => void;
 }
 
-// We need to create a div outside of the mithril's render root (<main>), that's
-// why the manual DOM manipulation.
-function getOrCreateDOM() {
-  let div = document.getElementById('main-modal') as HTMLElement;
-  if (div) return div;
-  div = document.createElement('div');
-  div.id = 'main-modal';
-  div.classList.add('modal');
-  div.classList.add('micromodal-slide');
-  (div as {} as {ariaHidden: boolean}).ariaHidden = true;
-  document.body.appendChild(div);
-  MicroModal.init();
-  return div;
-}
-
 export async function showModal(attrs: ModalDefinition): Promise<void> {
-  const modal = getOrCreateDOM();
+  const modal = document.querySelector('#main-modal') as HTMLElement;
   m.render(
       modal,
       m('.modal-overlay[data-micromodal-close]',
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 55dc47a..a5b9102 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -15,10 +15,10 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
-import {randomColor} from '../common/colorizer';
 import {AreaNote, Note} from '../common/state';
 import {timeToString} from '../common/time';
 
+import {randomColor} from './colorizer';
 import {TRACK_SHELL_WIDTH} from './css_constants';
 import {PerfettoMouseEvent} from './events';
 import {globals} from './globals';
@@ -36,14 +36,6 @@
   return s.slice(0, Math.min(newlineIndex, s.length, 16));
 }
 
-function getStartTimestamp(note: Note|AreaNote) {
-  if (note.noteType === 'AREA') {
-    return globals.state.areas[note.areaId].startSec;
-  } else {
-    return note.timestamp;
-  }
-}
-
 export class NotesPanel extends Panel {
   hoveredX: null|number = null;
 
@@ -93,14 +85,11 @@
     ctx.font = '10px Helvetica';
 
     for (const note of Object.values(globals.state.notes)) {
-      const timestamp = getStartTimestamp(note);
-      // TODO(hjd): We should still render area selection marks in viewport is
-      // *within* the area (e.g. both lhs and rhs are out of bounds).
+      const timestamp = note.timestamp;
       if ((note.noteType !== 'AREA' && !timeScale.timeInBounds(timestamp)) ||
           (note.noteType === 'AREA' &&
-           !timeScale.timeInBounds(globals.state.areas[note.areaId].endSec) &&
-           !timeScale.timeInBounds(
-               globals.state.areas[note.areaId].startSec))) {
+           !timeScale.timeInBounds(note.area.endSec) &&
+           !timeScale.timeInBounds(note.area.startSec))) {
         continue;
       }
       const currentIsHovered =
@@ -108,19 +97,18 @@
       if (currentIsHovered) aNoteIsHovered = true;
 
       const selection = globals.state.currentSelection;
-      const isSelected = selection !== null &&
-          ((selection.kind === 'NOTE' && selection.id === note.id) ||
-           (selection.kind === 'AREA' && selection.noteId === note.id));
+      const isSelected = selection !== null && selection.kind === 'NOTE' &&
+          selection.id === note.id;
       const x = timeScale.timeToPx(timestamp);
       const left = Math.floor(x + TRACK_SHELL_WIDTH);
 
       // Draw flag or marker.
       if (note.noteType === 'AREA') {
-        const area = globals.state.areas[note.areaId];
         this.drawAreaMarker(
             ctx,
             left,
-            Math.floor(timeScale.timeToPx(area.endSec) + TRACK_SHELL_WIDTH),
+            Math.floor(
+                timeScale.timeToPx(note.area.endSec) + TRACK_SHELL_WIDTH),
             note.color,
             isSelected);
       } else {
@@ -141,7 +129,7 @@
     }
 
     // A real note is hovered so we don't need to see the preview line.
-    // TODO(hjd): Change cursor to pointer here.
+    // TODO(taylori): Change cursor to pointer here.
     if (aNoteIsHovered) globals.frontendLocalState.setHoveredNoteTimestamp(-1);
 
     // View preview note flag when hovering on notes panel.
@@ -184,12 +172,12 @@
     ctx.stroke();
 
     // Start line after track shell section, join triangles.
-    const startDraw = Math.max(
-        x, globals.frontendLocalState.timeScale.startPx + TRACK_SHELL_WIDTH);
-    ctx.beginPath();
-    ctx.moveTo(startDraw, topOffset);
-    ctx.lineTo(xEnd, topOffset);
-    ctx.stroke();
+    const startDraw =
+        Math.max(
+            x,
+            globals.frontendLocalState.timeScale.startPx + TRACK_SHELL_WIDTH) -
+        1;
+    ctx.fillRect(startDraw, topOffset - 1, xEnd - startDraw + 1, 1);
   }
 
   private drawFlag(
@@ -218,20 +206,17 @@
 
 
   private onClick(x: number, _: number, isMovie: boolean) {
-    if (x < 0) return;
     const timeScale = globals.frontendLocalState.timeScale;
     const timestamp = timeScale.pxToTime(x);
     for (const note of Object.values(globals.state.notes)) {
       if (this.hoveredX && this.mouseOverNote(this.hoveredX, note)) {
         if (note.noteType === 'MOVIE') {
           globals.frontendLocalState.setVidTimestamp(note.timestamp);
+        } else if (note.noteType === 'AREA') {
+          globals.frontendLocalState.selectArea(
+              note.area.startSec, note.area.endSec, note.area.tracks);
         }
-        if (note.noteType === 'AREA') {
-          globals.makeSelection(
-              Actions.reSelectArea({areaId: note.areaId, noteId: note.id}));
-        } else {
-          globals.makeSelection(Actions.selectNote({id: note.id}));
-        }
+        globals.makeSelection(Actions.selectNote({id: note.id}));
         return;
       }
     }
@@ -244,12 +229,11 @@
 
   private mouseOverNote(x: number, note: AreaNote|Note): boolean {
     const timeScale = globals.frontendLocalState.timeScale;
-    const noteX = timeScale.timeToPx(getStartTimestamp(note));
+    const noteX = timeScale.timeToPx(note.timestamp);
     if (note.noteType === 'AREA') {
-      const noteArea = globals.state.areas[note.areaId];
       return (noteX <= x && x < noteX + AREA_TRIANGLE_WIDTH) ||
-          (timeScale.timeToPx(noteArea.endSec) > x &&
-           x > timeScale.timeToPx(noteArea.endSec) - AREA_TRIANGLE_WIDTH);
+          (timeScale.timeToPx(note.area.endSec) > x &&
+           x > timeScale.timeToPx(note.area.endSec) - AREA_TRIANGLE_WIDTH);
     } else {
       const width = (note.noteType === 'MOVIE') ? MOVIE_WIDTH : FLAG_WIDTH;
       return noteX <= x && x < noteX + width;
@@ -264,8 +248,7 @@
 export class NotesEditorPanel extends Panel<NotesEditorPanelAttrs> {
   view({attrs}: m.CVnode<NotesEditorPanelAttrs>) {
     const note = globals.state.notes[attrs.id];
-    const startTime =
-        getStartTimestamp(note) - globals.state.traceTime.startSec;
+    const startTime = note.timestamp - globals.state.traceTime.startSec;
     return m(
         '.notes-editor-panel',
         m('.notes-editor-panel-heading-bar',
@@ -276,23 +259,25 @@
               e.stopImmediatePropagation();
             },
             value: note.text,
-            onchange: (e: InputEvent) => {
-              const newText = (e.target as HTMLInputElement).value;
-              globals.dispatch(Actions.changeNoteText({
-                id: attrs.id,
-                newText,
-              }));
-            },
+            onchange: m.withAttr(
+                'value',
+                newText => {
+                  globals.dispatch(Actions.changeNoteText({
+                    id: attrs.id,
+                    newText,
+                  }));
+                }),
           }),
           m('span.color-change', `Change color: `, m('input[type=color]', {
               value: note.color,
-              onchange: (e: Event) => {
-                const newColor = (e.target as HTMLInputElement).value;
-                globals.dispatch(Actions.changeNoteColor({
-                  id: attrs.id,
-                  newColor,
-                }));
-              },
+              onchange: m.withAttr(
+                  'value',
+                  newColor => {
+                    globals.dispatch(Actions.changeNoteColor({
+                      id: attrs.id,
+                      newColor,
+                    }));
+                  }),
             })),
           m('button',
             {
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index d870729..cfc6ee8 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -15,28 +15,21 @@
 import * as m from 'mithril';
 
 import {assertExists} from '../base/logging';
-import {hueForCpu} from '../common/colorizer';
 import {TimeSpan, timeToString} from '../common/time';
 
-import {SIDEBAR_WIDTH, TRACK_SHELL_WIDTH} from './css_constants';
-import {BorderDragStrategy} from './drag/border_drag_strategy';
-import {DragStrategy} from './drag/drag_strategy';
-import {InnerDragStrategy} from './drag/inner_drag_strategy';
-import {OuterDragStrategy} from './drag/outer_drag_strategy';
+import {hueForCpu} from './colorizer';
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {DragGestureHandler} from './drag_gesture_handler';
 import {globals} from './globals';
 import {Panel, PanelSize} from './panel';
 import {TimeScale} from './time_scale';
 
 export class OverviewTimelinePanel extends Panel {
-  private static HANDLE_SIZE_PX = 7;
-
   private width = 0;
+  private dragStartPx = 0;
   private gesture?: DragGestureHandler;
   private timeScale?: TimeScale;
   private totTime = new TimeSpan(0, 0);
-  private dragStrategy?: DragStrategy;
-  private readonly boundOnMouseMove = this.onMouseMove.bind(this);
 
   // Must explicitly type now; arguments types are no longer auto-inferred.
   // https://github.com/Microsoft/TypeScript/issues/1373
@@ -58,13 +51,6 @@
 
   oncreate(vnode: m.CVnodeDOM) {
     this.onupdate(vnode);
-    (vnode.dom as HTMLElement)
-        .addEventListener('mousemove', this.boundOnMouseMove);
-  }
-
-  onremove({dom}: m.CVnodeDOM) {
-    (dom as HTMLElement)
-        .removeEventListener('mousemove', this.boundOnMouseMove);
   }
 
   view() {
@@ -118,8 +104,9 @@
     ctx.fillRect(0, size.height - 1, this.width, 1);
 
     // Draw semi-opaque rects that occlude the non-visible time range.
-    const [vizStartPx, vizEndPx] =
-        OverviewTimelinePanel.extractBounds(this.timeScale);
+    const vizTime = globals.frontendLocalState.visibleWindowTime;
+    const vizStartPx = Math.floor(this.timeScale.timeToPx(vizTime.start));
+    const vizEndPx = Math.ceil(this.timeScale.timeToPx(vizTime.end));
 
     ctx.fillStyle = 'rgba(200, 200, 200, 0.8)';
     ctx.fillRect(
@@ -133,79 +120,24 @@
     ctx.fillStyle = '#999';
     ctx.fillRect(vizStartPx - 1, headerHeight, 1, tracksHeight);
     ctx.fillRect(vizEndPx, headerHeight, 1, tracksHeight);
-
-    const hbarWidth = OverviewTimelinePanel.HANDLE_SIZE_PX;
-    const hbarDivisionFactor = 3.5;
-    // Draw handlebar
-    ctx.fillRect(
-        vizStartPx - Math.floor(hbarWidth / 2) - 1,
-        headerHeight,
-        hbarWidth,
-        tracksHeight / hbarDivisionFactor);
-    ctx.fillRect(
-        vizEndPx - Math.floor(hbarWidth / 2),
-        headerHeight,
-        hbarWidth,
-        tracksHeight / hbarDivisionFactor);
-  }
-
-  private onMouseMove(e: MouseEvent) {
-    if (this.gesture === undefined || this.gesture.isDragging) {
-      return;
-    }
-    (e.target as HTMLElement).style.cursor = this.chooseCursor(e.x);
-  }
-
-  private chooseCursor(x: number) {
-    if (this.timeScale === undefined) return 'default';
-    const [vizStartPx, vizEndPx] =
-        OverviewTimelinePanel.extractBounds(this.timeScale);
-    const startBound = vizStartPx - 1 + SIDEBAR_WIDTH;
-    const endBound = vizEndPx + SIDEBAR_WIDTH;
-    if (OverviewTimelinePanel.inBorderRange(x, startBound) ||
-        OverviewTimelinePanel.inBorderRange(x, endBound)) {
-      return 'ew-resize';
-    } else if (x < SIDEBAR_WIDTH + TRACK_SHELL_WIDTH) {
-      return 'default';
-    } else if (x < startBound || endBound < x) {
-      return 'crosshair';
-    } else {
-      return 'all-scroll';
-    }
   }
 
   onDrag(x: number) {
-    if (this.dragStrategy === undefined) return;
-    this.dragStrategy.onDrag(x);
+    // Set visible time limits from selection.
+    if (this.timeScale === undefined) return;
+    let tStart = this.timeScale.pxToTime(this.dragStartPx);
+    let tEnd = this.timeScale.pxToTime(x);
+    if (tStart > tEnd) [tStart, tEnd] = [tEnd, tStart];
+    const vizTime = new TimeSpan(tStart, tEnd);
+    globals.frontendLocalState.updateVisibleTime(vizTime);
+    globals.rafScheduler.scheduleRedraw();
   }
 
   onDragStart(x: number) {
-    if (this.timeScale === undefined) return;
-    const pixelBounds = OverviewTimelinePanel.extractBounds(this.timeScale);
-    if (OverviewTimelinePanel.inBorderRange(x, pixelBounds[0]) ||
-        OverviewTimelinePanel.inBorderRange(x, pixelBounds[1])) {
-      this.dragStrategy = new BorderDragStrategy(this.timeScale, pixelBounds);
-    } else if (x < pixelBounds[0] || pixelBounds[1] < x) {
-      this.dragStrategy = new OuterDragStrategy(this.timeScale);
-    } else {
-      this.dragStrategy = new InnerDragStrategy(this.timeScale, pixelBounds);
-    }
-    this.dragStrategy.onDragStart(x);
+    this.dragStartPx = x;
   }
 
   onDragEnd() {
-    this.dragStrategy = undefined;
-  }
-
-  private static extractBounds(timeScale: TimeScale): [number, number] {
-    const vizTime = globals.frontendLocalState.getVisibleStateBounds();
-    return [
-      Math.floor(timeScale.timeToPx(vizTime[0])),
-      Math.ceil(timeScale.timeToPx(vizTime[1]))
-    ];
-  }
-
-  private static inBorderRange(a: number, b: number): boolean {
-    return Math.abs(a - b) < this.HANDLE_SIZE_PX / 2;
+    this.dragStartPx = 0;
   }
 }
diff --git a/ui/src/frontend/pages.ts b/ui/src/frontend/pages.ts
index c595420..3f3e29f 100644
--- a/ui/src/frontend/pages.ts
+++ b/ui/src/frontend/pages.ts
@@ -15,8 +15,6 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
-
-import {CookieConsent} from './cookie_consent';
 import {globals} from './globals';
 import {Sidebar} from './sidebar';
 import {Topbar} from './topbar';
@@ -25,14 +23,13 @@
   const permalink = globals.state.permalink;
   if (!permalink.requestId || !permalink.hash) return null;
   const url = `${self.location.origin}/#!/?s=${permalink.hash}`;
-
   return m('.alert-permalink', [
     m('div', 'Permalink: ', m(`a[href=${url}]`, url)),
     m('button',
       {
         onclick: () => globals.dispatch(Actions.clearPermalink({})),
       },
-      m('i.material-icons.disallow-selection', 'close')),
+      m('i.material-icons', 'close')),
   ]);
 }
 
@@ -53,7 +50,6 @@
         m(Topbar),
         m(Alerts),
         m(component),
-        m(CookieConsent),
       ];
       if (globals.frontendLocalState.perfDebug) {
         children.push(m('.perf-stats'));
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index 166a3ce..c5ee552 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -97,7 +97,8 @@
   private onSelection:
       (dragStartX: number, dragStartY: number, prevX: number, currentX: number,
        currentY: number, editing: boolean) => void;
-  private endSelection: (edit: boolean) => void;
+  private selectingStarted: () => void;
+  private selectingEnded: () => void;
 
   constructor({
     element,
@@ -106,7 +107,8 @@
     onZoomed,
     editSelection,
     onSelection,
-    endSelection
+    selectingStarted,
+    selectingEnded
   }: {
     element: HTMLElement,
     contentOffsetX: number,
@@ -116,7 +118,8 @@
     onSelection:
         (dragStartX: number, dragStartY: number, prevX: number,
          currentX: number, currentY: number, editing: boolean) => void,
-    endSelection: (edit: boolean) => void,
+    selectingStarted: () => void,
+    selectingEnded: () => void,
   }) {
     this.element = element;
     this.contentOffsetX = contentOffsetX;
@@ -124,7 +127,8 @@
     this.onZoomed = onZoomed;
     this.editSelection = editSelection;
     this.onSelection = onSelection;
-    this.endSelection = endSelection;
+    this.selectingStarted = selectingStarted;
+    this.selectingEnded = selectingEnded;
 
     document.body.addEventListener('keydown', this.boundOnKeyDown);
     document.body.addEventListener('keyup', this.boundOnKeyUp);
@@ -155,6 +159,7 @@
           if (edit) {
             this.element.style.cursor = EDITING_RANGE_CURSOR;
           } else if (!this.shiftDown) {
+            this.selectingStarted();
             this.element.style.cursor = DRAG_CURSOR;
           }
         },
@@ -163,7 +168,7 @@
           this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
           dragStartX = -1;
           dragStartY = -1;
-          this.endSelection(edit);
+          this.selectingEnded();
         });
   }
 
@@ -279,7 +284,7 @@
     handleKey(e, false);
   }
 
-  // TODO(hjd): Move this shift handling into the viewer page.
+  // TODO(taylori): Move this shift handling into the viewer page.
   private updateShift(down: boolean) {
     if (down === this.shiftDown) return;
     this.shiftDown = down;
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 2131c10..a5169f0 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -13,14 +13,11 @@
 // limitations under the License.
 
 import * as m from 'mithril';
+import {TimestampedAreaSelection} from 'src/common/state';
 
 import {assertExists, assertTrue} from '../base/logging';
 
 import {TOPBAR_HEIGHT, TRACK_SHELL_WIDTH} from './css_constants';
-import {
-  FlowEventsRenderer,
-  FlowEventsRendererArgs
-} from './flow_events_renderer';
 import {globals} from './globals';
 import {isPanelVNode, Panel, PanelSize, PanelVNode} from './panel';
 import {
@@ -39,7 +36,7 @@
 
 // We need any here so we can accept vnodes with arbitrary attrs.
 // tslint:disable-next-line:no-any
-export type AnyAttrsVnode = m.Vnode<any, any>;
+export type AnyAttrsVnode = m.Vnode<any, {}>;
 
 export interface Attrs {
   panels: AnyAttrsVnode[];
@@ -63,8 +60,7 @@
   private panelPositions: PanelPosition[] = [];
   private totalPanelHeight = 0;
   private canvasHeight = 0;
-
-  private flowEventsRenderer: FlowEventsRenderer;
+  private prevAreaSelection?: TimestampedAreaSelection;
 
   private panelPerfStats = new WeakMap<Panel, RunningStatistics>();
   private perfStats = {
@@ -107,11 +103,12 @@
     return panels;
   }
 
-  // This finds the tracks covered by the in-progress area selection. When
-  // editing areaY is not set, so this will not be used.
   handleAreaSelection() {
-    const area = globals.frontendLocalState.selectedArea;
-    if (area === undefined ||
+    const selection = globals.frontendLocalState.selectedArea;
+    const area = selection.area;
+    if ((this.prevAreaSelection &&
+         this.prevAreaSelection.lastUpdate >= selection.lastUpdate) ||
+        area === undefined ||
         globals.frontendLocalState.areaY.start === undefined ||
         globals.frontendLocalState.areaY.end === undefined ||
         this.panelPositions.length === 0) {
@@ -156,6 +153,7 @@
       }
     }
     globals.frontendLocalState.selectArea(area.startSec, area.endSec, tracks);
+    this.prevAreaSelection = globals.frontendLocalState.selectedArea;
   }
 
   constructor(vnode: m.CVnode<Attrs>) {
@@ -163,7 +161,6 @@
     this.canvasRedrawer = () => this.redrawCanvas();
     globals.rafScheduler.addRedrawCallback(this.canvasRedrawer);
     perfDisplay.addContainer(this);
-    this.flowEventsRenderer = new FlowEventsRenderer();
   }
 
   oncreate(vnodeDom: m.CVnodeDOM<Attrs>) {
@@ -218,9 +215,7 @@
   view({attrs}: m.CVnode<Attrs>) {
     this.attrs = attrs;
     const renderPanel = (panel: m.Vnode) => perfDebug() ?
-        m('.panel',
-          {key: panel.key},
-          [panel, m('.debug-panel-border', {key: 'debug-panel-border'})]) :
+        m('.panel', panel, m('.debug-panel-border')) :
         m('.panel', {key: panel.key}, panel);
 
     return [
@@ -241,7 +236,7 @@
       this.updateCanvasDimensions();
       this.repositionCanvas();
       if (this.attrs.kind === 'TRACKS') {
-        globals.frontendLocalState.updateLocalLimits(
+        globals.frontendLocalState.timeScale.setLimitsPx(
             0, this.parentWidth - TRACK_SHELL_WIDTH);
       }
       this.redrawCanvas();
@@ -335,21 +330,11 @@
     const panels = assertExists(this.attrs).panels;
     assertTrue(panels.length === this.panelPositions.length);
     let totalOnCanvas = 0;
-    const flowEventsRendererArgs =
-        new FlowEventsRendererArgs(this.parentWidth, this.canvasHeight);
     for (let i = 0; i < panels.length; i++) {
       const panel = panels[i];
       const panelHeight = this.panelPositions[i].height;
       const yStartOnCanvas = panelYStart - canvasYStart;
 
-      if (!isPanelVNode(panel)) {
-        throw new Error('Vnode passed to panel container is not a panel');
-      }
-
-      // TODO(hjd): This cast should be unnecessary given the type guard above.
-      const p = panel as PanelVNode<{}>;
-      flowEventsRendererArgs.registerPanel(p, yStartOnCanvas, panelHeight);
-
       if (!this.overlapsCanvas(yStartOnCanvas, yStartOnCanvas + panelHeight)) {
         panelYStart += panelHeight;
         continue;
@@ -357,6 +342,13 @@
 
       totalOnCanvas++;
 
+      if (!isPanelVNode(panel)) {
+        throw new Error('Vnode passed to panel container is not a panel');
+      }
+
+      // TODO(hjd): This cast should be unnecessary given the type guard above.
+      const p = panel as PanelVNode<{}>;
+
       this.ctx.save();
       this.ctx.translate(0, yStartOnCanvas);
       const clipRect = new Path2D();
@@ -372,8 +364,6 @@
     }
 
     this.drawTopLayerOnCanvas();
-    this.flowEventsRenderer.render(this.ctx, flowEventsRendererArgs);
-    // Collect performance as the last thing we do.
     const redrawDur = debugNow() - redrawStart;
     this.updatePerfStats(redrawDur, panels.length, totalOnCanvas);
   }
@@ -382,10 +372,12 @@
   // the whole canvas rather than per panel.
   private drawTopLayerOnCanvas() {
     if (!this.ctx) return;
-    const area = globals.frontendLocalState.selectedArea;
+    const selection = globals.frontendLocalState.selectedArea;
+    const area = selection.area;
     if (area === undefined ||
         globals.frontendLocalState.areaY.start === undefined ||
-        globals.frontendLocalState.areaY.end === undefined) {
+        globals.frontendLocalState.areaY.end === undefined ||
+        !globals.frontendLocalState.selectingArea) {
       return;
     }
     if (this.panelPositions.length === 0 || area.tracks.length === 0) return;
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
index f4ff214..180fcb8 100644
--- a/ui/src/frontend/post_message_handler.ts
+++ b/ui/src/frontend/post_message_handler.ts
@@ -43,19 +43,17 @@
 // 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 (messageEvent.origin === 'https://tagassistant.google.com') {
-    // The GA debugger, does a window.open() and sends messages to the GA
-    // script. Ignore them.
-    return;
-  }
-
   if (document.readyState !== 'complete') {
     console.error('Ignoring message - document not ready yet.');
     return;
   }
 
-  if (messageEvent.source === null || messageEvent.source !== window.opener) {
-    // This can happen if an extension tries to postMessage.
+  if (messageEvent.source === null) {
+    throw new Error('Incoming message has no source');
+  }
+
+  // This can happen if an extension tries to postMessage.
+  if (messageEvent.source !== window.opener) {
     return;
   }
 
@@ -79,12 +77,7 @@
   } else if (messageEvent.data instanceof ArrayBuffer) {
     postedTrace = {title: 'External trace', buffer: messageEvent.data};
   } else {
-    console.warn(
-        'Unknown postMessage() event received. If you are trying to open a ' +
-        'trace via postMessage(), this is a bug in your code. If not, this ' +
-        'could be due to some Chrome extension.');
-    console.log('origin:', messageEvent.origin, 'data:', messageEvent.data);
-    return;
+    throw new Error('Incoming message data is not in a usable format');
   }
 
   if (postedTrace.buffer.byteLength === 0) {
@@ -130,7 +123,7 @@
 }
 
 function sanitizeString(str: string): string {
-  return str.replace(/[^A-Za-z0-9.\-_#:/?=&;% ]/g, ' ');
+  return str.replace(/[^A-Za-z0-9.\-_#:/ ]/g, ' ');
 }
 
 // tslint:disable:no-any
diff --git a/ui/src/frontend/query_table.ts b/ui/src/frontend/query_table.ts
index f69a8ba..078a70c 100644
--- a/ui/src/frontend/query_table.ts
+++ b/ui/src/frontend/query_table.ts
@@ -24,7 +24,6 @@
 import {globals} from './globals';
 import {Panel} from './panel';
 import {
-  findUiTrackId,
   horizontalScrollAndZoomToRange,
   verticalScrollToTrack
 } from './scroll_helper';
@@ -43,8 +42,16 @@
     return true;
   }
 
-  static rowOnClickHandler(
-      event: Event, row: Row, nextTab: 'CurrentSelection'|'QueryResults') {
+  static findUiTrackId(traceTrackId: number) {
+    for (const [uiTrackId, trackState] of Object.entries(
+             globals.state.tracks)) {
+      const config = trackState.config as {trackId: number};
+      if (config.trackId === traceTrackId) return uiTrackId;
+    }
+    return null;
+  }
+
+  static rowOnClickHandler(event: Event, row: Row) {
     // TODO(dproy): Make click handler work from analyze page.
     if (globals.state.route !== '/viewer') return;
     // If the click bubbles up to the pan and zoom handler that will deselect
@@ -56,22 +63,14 @@
     const sliceDur = fromNs(Math.max(row.dur as number, 1));
     const sliceEnd = sliceStart + sliceDur;
     const trackId = row.track_id as number;
-    const uiTrackId = findUiTrackId(trackId);
+    const uiTrackId = this.findUiTrackId(trackId);
     if (uiTrackId === null) return;
     verticalScrollToTrack(uiTrackId, true);
     horizontalScrollAndZoomToRange(sliceStart, sliceEnd);
-    let sliceId: number|undefined;
-    if (row.type?.toString().includes('slice')) {
-      sliceId = row.id as number | undefined;
-    } else {
-      sliceId = row.slice_id as number | undefined;
-    }
+    const sliceId = row.slice_id as number | undefined;
     if (sliceId !== undefined) {
-      globals.makeSelection(
-          Actions.selectChromeSlice(
-              {id: sliceId, trackId: uiTrackId, table: 'slice'}),
-          nextTab === 'QueryResults' ? globals.frontendLocalState.currentTab :
-                                       'current_selection');
+      globals.makeSelection(Actions.selectChromeSlice(
+          {id: sliceId, trackId: uiTrackId, table: 'slice'}));
     }
   }
 
@@ -84,21 +83,11 @@
     const containsSliceLocation =
         QueryTableRow.columnsContainsSliceLocation(columns);
     const maybeOnClick = containsSliceLocation ?
-        (e: Event) => QueryTableRow.rowOnClickHandler(e, row, 'QueryResults') :
-        null;
-    const maybeOnDblClick = containsSliceLocation ?
-        (e: Event) =>
-            QueryTableRow.rowOnClickHandler(e, row, 'CurrentSelection') :
+        (e: Event) => QueryTableRow.rowOnClickHandler(e, row) :
         null;
     return m(
         'tr',
-        {
-          onclick: maybeOnClick,
-          // TODO(altimin): Consider improving the logic here (e.g. delay?) to
-          // account for cases when dblclick fires late.
-          ondblclick: maybeOnDblClick,
-          'clickable': containsSliceLocation
-        },
+        {onclick: maybeOnClick, 'clickable': containsSliceLocation},
         cells);
   }
 }
diff --git a/ui/src/frontend/record_config.ts b/ui/src/frontend/record_config.ts
deleted file mode 100644
index 029f6f0..0000000
--- a/ui/src/frontend/record_config.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {RecordConfig} from '../common/state';
-import {validateRecordConfig} from '../controller/validate_config';
-
-const LOCAL_STORAGE_RECORD_CONFIGS_KEY = 'recordConfigs';
-
-class NamedRecordConfig {
-  title: string;
-  config: RecordConfig;
-  key: string;
-
-  constructor(title: string, config: RecordConfig, key: string) {
-    this.title = title;
-    this.config = this.validateData(config);
-    this.key = key;
-  }
-
-  private validateData(config: {}): RecordConfig {
-    const validConfig = validateRecordConfig(config);
-    if (validConfig.errorMessage) {
-      // TODO(bsebastien): Show a warning message to the user in the UI.
-      console.warn(validConfig.errorMessage);
-    }
-    return validConfig.config;
-  }
-
-  static isValid(jsonObject: object): jsonObject is NamedRecordConfig {
-    return (jsonObject as NamedRecordConfig).title !== undefined &&
-        (jsonObject as NamedRecordConfig).config !== undefined &&
-        (jsonObject as NamedRecordConfig).key !== undefined;
-  }
-}
-
-export class RecordConfigStore {
-  recordConfigs: NamedRecordConfig[];
-
-  constructor() {
-    this.recordConfigs = [];
-    this.reloadFromLocalStorage();
-  }
-
-  save(recordConfig: RecordConfig, title?: string): void {
-    // We reload from local storage in case of concurrent
-    // modifications of local storage from a different tab.
-    this.reloadFromLocalStorage();
-
-    const config = new NamedRecordConfig(
-        title ? title : new Date().toJSON(), recordConfig, new Date().toJSON());
-
-    this.recordConfigs.push(config);
-    window.localStorage.setItem(
-        LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
-  }
-
-  delete(key: string): void {
-    // We reload from local storage in case of concurrent
-    // modifications of local storage from a different tab.
-    this.reloadFromLocalStorage();
-
-    let idx = -1;
-    for (let i = 0; i < this.recordConfigs.length; ++i) {
-      if (this.recordConfigs[i].key === key) {
-        idx = i;
-        break;
-      }
-    }
-
-    if (idx !== -1) {
-      this.recordConfigs.splice(idx, 1);
-      window.localStorage.setItem(
-          LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
-    } else {
-      // TODO(bsebastien): Show a warning message to the user in the UI.
-      console.warn('The config selected doesn\'t exist any more');
-    }
-  }
-
-  private clearRecordConfigs(): void {
-    this.recordConfigs = [];
-    window.localStorage.setItem(
-        LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify([]));
-  }
-
-  reloadFromLocalStorage(): void {
-    const configsLocalStorage =
-        window.localStorage.getItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY);
-
-    if (configsLocalStorage) {
-      try {
-        const validConfigLocalStorage: NamedRecordConfig[] = [];
-        const parsedConfigsLocalStorage = JSON.parse(configsLocalStorage);
-
-        // Check if it's an array.
-        if (!Array.isArray(parsedConfigsLocalStorage)) {
-          this.clearRecordConfigs();
-          return;
-        }
-
-        for (let i = 0; i < parsedConfigsLocalStorage.length; ++i) {
-          if (!NamedRecordConfig.isValid(parsedConfigsLocalStorage[i])) {
-            continue;
-          }
-          validConfigLocalStorage.push(new NamedRecordConfig(
-              parsedConfigsLocalStorage[i].title,
-              parsedConfigsLocalStorage[i].config,
-              parsedConfigsLocalStorage[i].key));
-        }
-
-        this.recordConfigs = validConfigLocalStorage;
-        window.localStorage.setItem(
-            LOCAL_STORAGE_RECORD_CONFIGS_KEY,
-            JSON.stringify(validConfigLocalStorage));
-      } catch (e) {
-        this.clearRecordConfigs();
-      }
-    } else {
-      this.clearRecordConfigs();
-    }
-  }
-}
-
-// This class is a singleton to avoid many instances
-// conflicting as they attempt to edit localStorage.
-export const recordConfigStore = new RecordConfigStore();
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 182a66b..a1a4440 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -22,12 +22,10 @@
   AdbRecordingTarget,
   getBuiltinChromeCategoryList,
   getDefaultRecordingTargets,
-  hasActiveProbes,
   isAdbTarget,
   isAndroidP,
   isAndroidTarget,
   isChromeTarget,
-  isCrOSTarget,
   RecordingTarget
 } from '../common/state';
 import {MAX_TIME, RecordMode} from '../common/state';
@@ -35,7 +33,6 @@
 
 import {globals} from './globals';
 import {createPage} from './pages';
-import {recordConfigStore} from './record_config';
 import {
   CodeSnippet,
   Dropdown,
@@ -45,54 +42,51 @@
   Slider,
   SliderAttrs,
   Textarea,
-  TextareaAttrs,
-  Toggle,
-  ToggleAttrs
+  TextareaAttrs
 } from './record_widgets';
 import {Router} from './router';
 
-const LOCAL_STORAGE_SHOW_CONFIG = 'showConfigs';
-
 const POLL_INTERVAL_MS = [250, 500, 1000, 2500, 5000, 30000, 60000];
 
 const ATRACE_CATEGORIES = new Map<string, string>();
-ATRACE_CATEGORIES.set('adb', 'ADB');
-ATRACE_CATEGORIES.set('aidl', 'AIDL calls');
-ATRACE_CATEGORIES.set('am', 'Activity Manager');
-ATRACE_CATEGORIES.set('audio', 'Audio');
-ATRACE_CATEGORIES.set('binder_driver', 'Binder Kernel driver');
-ATRACE_CATEGORIES.set('binder_lock', 'Binder global lock trace');
-ATRACE_CATEGORIES.set('bionic', 'Bionic C library');
-ATRACE_CATEGORIES.set('camera', 'Camera');
-ATRACE_CATEGORIES.set('dalvik', 'ART & Dalvik');
-ATRACE_CATEGORIES.set('database', 'Database');
 ATRACE_CATEGORIES.set('gfx', 'Graphics');
-ATRACE_CATEGORIES.set('hal', 'Hardware Modules');
 ATRACE_CATEGORIES.set('input', 'Input');
-ATRACE_CATEGORIES.set('network', 'Network');
-ATRACE_CATEGORIES.set('nnapi', 'Neural Network API');
-ATRACE_CATEGORIES.set('pm', 'Package Manager');
-ATRACE_CATEGORIES.set('power', 'Power Management');
-ATRACE_CATEGORIES.set('res', 'Resource Loading');
-ATRACE_CATEGORIES.set('rro', 'Resource Overlay');
-ATRACE_CATEGORIES.set('rs', 'RenderScript');
-ATRACE_CATEGORIES.set('sm', 'Sync Manager');
-ATRACE_CATEGORIES.set('ss', 'System Server');
-ATRACE_CATEGORIES.set('vibrator', 'Vibrator');
-ATRACE_CATEGORIES.set('video', 'Video');
 ATRACE_CATEGORIES.set('view', 'View System');
 ATRACE_CATEGORIES.set('webview', 'WebView');
 ATRACE_CATEGORIES.set('wm', 'Window Manager');
+ATRACE_CATEGORIES.set('am', 'Activity Manager');
+ATRACE_CATEGORIES.set('sm', 'Sync Manager');
+ATRACE_CATEGORIES.set('audio', 'Audio');
+ATRACE_CATEGORIES.set('video', 'Video');
+ATRACE_CATEGORIES.set('camera', 'Camera');
+ATRACE_CATEGORIES.set('hal', 'Hardware Modules');
+ATRACE_CATEGORIES.set('res', 'Resource Loading');
+ATRACE_CATEGORIES.set('dalvik', 'ART & Dalvik');
+ATRACE_CATEGORIES.set('rs', 'RenderScript');
+ATRACE_CATEGORIES.set('bionic', 'Bionic C library');
+ATRACE_CATEGORIES.set('gfx', 'Graphics');
+ATRACE_CATEGORIES.set('power', 'Power Management');
+ATRACE_CATEGORIES.set('pm', 'Package Manager');
+ATRACE_CATEGORIES.set('ss', 'System Server');
+ATRACE_CATEGORIES.set('database', 'Database');
+ATRACE_CATEGORIES.set('network', 'Network');
+ATRACE_CATEGORIES.set('adb', 'ADB');
+ATRACE_CATEGORIES.set('vibrator', 'Vibrator');
+ATRACE_CATEGORIES.set('aidl', 'AIDL calls');
+ATRACE_CATEGORIES.set('nnapi', 'Neural Network API');
+ATRACE_CATEGORIES.set('rro', 'Resource Overlay');
+ATRACE_CATEGORIES.set('binder_driver', 'Binder Kernel driver');
+ATRACE_CATEGORIES.set('binder_lock', 'Binder global lock trace');
 
 const LOG_BUFFERS = new Map<string, string>();
-LOG_BUFFERS.set('LID_CRASH', 'Crash');
 LOG_BUFFERS.set('LID_DEFAULT', 'Main');
-LOG_BUFFERS.set('LID_EVENTS', 'Binary events');
-LOG_BUFFERS.set('LID_KERNEL', 'Kernel');
 LOG_BUFFERS.set('LID_RADIO', 'Radio');
-LOG_BUFFERS.set('LID_SECURITY', 'Security');
-LOG_BUFFERS.set('LID_STATS', 'Stats');
+LOG_BUFFERS.set('LID_EVENTS', 'Binary events');
 LOG_BUFFERS.set('LID_SYSTEM', 'System');
+LOG_BUFFERS.set('LID_CRASH', 'Crash');
+LOG_BUFFERS.set('LID_STATS', 'Stats');
+LOG_BUFFERS.set('LID_SECURITY', 'Security');
+LOG_BUFFERS.set('LID_KERNEL', 'Kernel');
 
 const FTRACE_CATEGORIES = new Map<string, string>();
 FTRACE_CATEGORIES.set('binder/*', 'binder');
@@ -113,7 +107,6 @@
 FTRACE_CATEGORIES.set('task/*', 'task');
 FTRACE_CATEGORIES.set('task/*', 'task');
 FTRACE_CATEGORIES.set('vmscan/*', 'vmscan');
-FTRACE_CATEGORIES.set('fastrpc/*', 'fastrpc');
 
 function RecSettings(cssClass: string) {
   const S = (x: number) => x * 1000;
@@ -125,19 +118,20 @@
   const recButton = (mode: RecordMode, title: string, img: string) => {
     const checkboxArgs = {
       checked: cfg.mode === mode,
-      onchange: (e: InputEvent) => {
-        const checked = (e.target as HTMLInputElement).checked;
-        if (!checked) return;
-        const traceCfg = produce(globals.state.recordConfig, draft => {
-          draft.mode = mode;
-        });
-        globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
-      },
+      onchange: m.withAttr(
+          'checked',
+          (checked: boolean) => {
+            if (!checked) return;
+            const traceCfg = produce(globals.state.recordConfig, draft => {
+              draft.mode = mode;
+            });
+            globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
+          })
     };
     return m(
         `label${cfg.mode === mode ? '.selected' : ''}`,
         m(`input[type=radio][name=rec_mode]`, checkboxArgs),
-        m(`img[src=${globals.root}assets/${img}]`),
+        m(`img[src=assets/${img}]`),
         m('span', title));
   };
 
@@ -188,32 +182,14 @@
 }
 
 function PowerSettings(cssClass: string) {
-  const DOC_URL = 'https://perfetto.dev/docs/data-sources/battery-counters';
-  const descr =
-      [m('div',
-         m('span', `Polls charge counters and instantaneous power draw from
-                    the battery power management IC and the power rails from
-                    the PowerStats HAL (`),
-         m('a', {href: DOC_URL, target: '_blank'}, 'see docs for more'),
-         m('span', ')'))];
-  if (globals.isInternalUser) {
-    descr.push(m(
-        'div',
-        m('span', 'Googlers: See '),
-        m('a',
-          {href: 'http://go/power-rails-internal-doc', target: '_blank'},
-          'this doc'),
-        m('span', ` for instructions on how to change the refault rail selection
-                  on internal devices.`),
-        ));
-  }
   return m(
       `.record-section${cssClass}`,
       m(Probe,
         {
-          title: 'Battery drain & power rails',
+          title: 'Battery drain',
           img: 'rec_battery_counters.png',
-          descr,
+          descr: `Polls charge counters and instantaneous power draw from
+                    the battery power management IC.`,
           setEnabled: (cfg, val) => cfg.batteryDrain = val,
           isEnabled: (cfg) => cfg.batteryDrain
         } as ProbeAttrs,
@@ -235,23 +211,13 @@
 }
 
 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),
-      m(Probe, {
-        title: 'GPU memory',
-        img: 'rec_gpu_mem_total.png',
-        descr: `Allows to track per process and global total GPU memory usages.
-                (Available on recent Android 12+ kernels)`,
-        setEnabled: (cfg, val) => cfg.gpuMemTotal = val,
-        isEnabled: (cfg) => cfg.gpuMemTotal
-      } as ProbeAttrs));
+  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) {
@@ -289,10 +255,18 @@
         isEnabled: (cfg) => cfg.cpuFreq
       } as ProbeAttrs),
       m(Probe, {
+        title: 'Scheduling chains / latency analysis',
+        img: 'rec_cpu_wakeup.png',
+        descr: `Tracks causality of scheduling transitions. When a task
+                X transitions from blocked -> runnable, keeps track of the
+                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: 'rec_syscalls.png',
-        descr: `Tracks the enter and exit of all syscalls. On Android
-                requires a userdebug or eng build.`,
+        img: null,
+        descr: `Tracks the enter and exit of all syscalls.`,
         setEnabled: (cfg, val) => cfg.cpuSyscall = val,
         isEnabled: (cfg) => cfg.cpuSyscall
       } as ProbeAttrs));
@@ -334,11 +308,8 @@
       `.${cssClass}`,
       m(Textarea, {
         title: 'Names or pids of the processes to track',
-        docsLink:
-            'https://perfetto.dev/docs/data-sources/native-heap-profiler#heapprofd-targets',
         placeholder: 'One per line, e.g.:\n' +
             'system_server\n' +
-            'com.google.android.apps.photos\n' +
             '1503',
         set: (cfg, val) => cfg.hpProcesses = val,
         get: (cfg) => cfg.hpProcesses
@@ -391,23 +362,8 @@
         min: 0,
         set: (cfg, val) => cfg.hpSharedMemoryBuffer = val,
         get: (cfg) => cfg.hpSharedMemoryBuffer
-      } as SliderAttrs),
-      m(Toggle, {
-        title: 'Block client',
-        cssClass: '.thin',
-        descr: `Slow down target application if profiler cannot keep up.`,
-        setEnabled: (cfg, val) => cfg.hpBlockClient = val,
-        isEnabled: (cfg) => cfg.hpBlockClient
-      } as ToggleAttrs),
-      m(Toggle, {
-        title: 'All custom allocators (Q+)',
-        cssClass: '.thin',
-        descr: `If the target application exposes custom allocators, also
-sample from those.`,
-        setEnabled: (cfg, val) => cfg.hpAllHeaps = val,
-        isEnabled: (cfg) => cfg.hpAllHeaps
-      } as ToggleAttrs)
-      // TODO(hjd): Add advanced options.
+      } as SliderAttrs)
+      // TODO(taylori): Add advanced options.
   );
 }
 
@@ -624,19 +580,10 @@
         } as ProbeAttrs,
         m(Dropdown, {
           title: 'Buffers',
-          cssClass: '.multicolumn',
           options: LOG_BUFFERS,
           set: (cfg, val) => cfg.androidLogBuffers = val,
           get: (cfg) => cfg.androidLogBuffers
-        } as DropdownAttrs)),
-      m(Probe, {
-        title: 'Frame timeline',
-        img: 'rec_frame_timeline.png',
-        descr: `Records expected/actual frame timings from surface_flinger.
-                    Requires Android 12 (S) or above.`,
-        setEnabled: (cfg, val) => cfg.androidFrameTimeline = val,
-        isEnabled: (cfg) => cfg.androidFrameTimeline
-      } as ProbeAttrs));
+        } as DropdownAttrs)));
 }
 
 
@@ -846,9 +793,7 @@
           m('select',
             {
               selectedIndex,
-              onchange: (e: Event) => {
-                onTargetChange((e.target as HTMLSelectElement).value);
-              },
+              onchange: m.withAttr('value', onTargetChange),
               onupdate: (select) => {
                 // Work around mithril bug
                 // (https://github.com/MithrilJS/mithril.js/issues/2107): We may
@@ -875,11 +820,6 @@
       globals.state.availableAdbDevices.find(d => d.serial === target) ||
       getDefaultRecordingTargets().find(t => t.os === target) ||
       getDefaultRecordingTargets()[0];
-
-  if (isChromeTarget(recordingTarget)) {
-    globals.dispatch(Actions.setUpdateChromeCategories({update: true}));
-  }
-
   globals.dispatch(Actions.setRecordingTarget({target: recordingTarget}));
   globals.rafScheduler.scheduleFullRedraw();
 }
@@ -887,97 +827,13 @@
 function Instructions(cssClass: string) {
   return m(
       `.record-section.instructions${cssClass}`,
-      m('header', 'Recording command'),
-      localStorage.hasOwnProperty(LOCAL_STORAGE_SHOW_CONFIG) ?
-          m('button.permalinkconfig',
-            {
-              onclick: () => {
-                globals.dispatch(
-                    Actions.createPermalink({isRecordingConfig: true}));
-              },
-            },
-            'Share recording settings') :
-          null,
+      m('header', 'Instructions'),
       RecordingSnippet(),
       BufferUsageProgressBar(),
       m('.buttons', StopCancelButtons()),
       recordingLog());
 }
 
-function displayRecordConfigs() {
-  return recordConfigStore.recordConfigs.map((item) => {
-    return m('.config', [
-      m('span.title-config', item.title),
-      m('button',
-        {
-          class: 'config-button load',
-          onclick: () => {
-            globals.dispatch(Actions.setRecordConfig({config: item.config}));
-            globals.rafScheduler.scheduleFullRedraw();
-          }
-        },
-        'load'),
-      m('button',
-        {
-          class: 'config-button delete',
-          onclick: () => {
-            recordConfigStore.delete(item.key);
-            globals.rafScheduler.scheduleFullRedraw();
-          }
-        },
-        'delete'),
-    ]);
-  });
-}
-
-function getSavedConfigList() {
-  if (recordConfigStore.recordConfigs.length === 0) {
-    return [];
-  }
-  return displayRecordConfigs();
-}
-
-export const ConfigTitleState = {
-  title: '',
-  getTitle: () => {
-    return ConfigTitleState.title;
-  },
-  setTitle: (value: string) => {
-    ConfigTitleState.title = value;
-  },
-  clearTitle: () => {
-    ConfigTitleState.title = '';
-  }
-};
-
-function Configurations(cssClass: string) {
-  return m(
-      `.record-section${cssClass}`,
-      m('header', 'Save and load configurations'),
-      m('.input-config',
-        [
-          m('input', {
-            value: ConfigTitleState.title,
-            placeholder: 'Title for config',
-            oninput() {
-              ConfigTitleState.setTitle(this.value);
-            }
-          }),
-          m('button',
-            {
-              class: 'config-button save',
-              onclick: () => {
-                recordConfigStore.save(
-                    globals.state.recordConfig, ConfigTitleState.getTitle());
-                globals.rafScheduler.scheduleFullRedraw();
-                ConfigTitleState.clearTitle();
-              }
-            },
-            'Save current config')
-        ]),
-      getSavedConfigList());
-}
-
 function BufferUsageProgressBar() {
   if (!globals.state.recordingInProgress) return [];
 
@@ -992,68 +848,44 @@
 }
 
 function RecordingNotes() {
-  const sideloadUrl =
-      'https://perfetto.dev/docs/contributing/build-instructions#get-the-code';
-  const linuxUrl = 'https://perfetto.dev/docs/quickstart/linux-tracing';
-  const cmdlineUrl =
-      'https://perfetto.dev/docs/quickstart/android-tracing#perfetto-cmdline';
+  const docUrl = '//docs.perfetto.dev/#/build-instructions?id=get-the-code';
   const extensionURL = `https://chrome.google.com/webstore/detail/
       perfetto-ui/lfmkphfpdbjijhpomgecfikhfohaoine`;
 
   const notes: m.Children = [];
+  const doc =
+      m('span', 'Follow the ', m('a', {href: docUrl}, 'instructions here.'));
 
   const msgFeatNotSupported =
-      m('span', `Some probes are only supported in Perfetto versions running
-      on Android Q+. `);
+      m('div', `Some of the probes are only supported in the
+      last version of perfetto running on Android Q+`);
 
   const msgPerfettoNotSupported =
-      m('span', `Perfetto is not supported natively before Android P. `);
-
-  const msgSideload =
-      m('span',
-        `If you have a rooted device you can `,
-        m('a',
-          {href: sideloadUrl, target: '_blank'},
-          `sideload the latest version of
-         Perfetto.`));
+      m('div', `Perfetto is not supported natively before Android P.`);
 
   const msgRecordingNotSupported =
-      m('.note',
-        `Recording Perfetto traces from the UI is not supported natively
+      m('div', `Recording Perfetto traces from the UI is not supported natively
      before Android Q. If you are using a P device, please select 'Android P'
-     as the 'Target Platform' and `,
-        m('a',
-          {href: cmdlineUrl, target: '_blank'},
-          `collect the trace using ADB.`));
+     as the 'Target Platform' and collect the trace using ADB`);
+
+  const msgSideload =
+      m('div',
+        `If you have a rooted device you can sideload the latest version of
+         perfetto. `,
+        doc);
 
   const msgChrome =
-      m('.note',
+      m('div',
         `To trace Chrome from the Perfetto UI, you need to install our `,
-        m('a', {href: extensionURL, target: '_blank'}, 'Chrome extension'),
+        m('a', {href: extensionURL}, 'Chrome extension'),
         ' and then reload this page.');
 
   const msgLinux =
-      m('.note',
-        `Use this `,
-        m('a', {href: linuxUrl, target: '_blank'}, `quickstart guide`),
-        ` to get started with tracing on Linux.`);
-
-  const msgLongTraces = m(
-      '.note',
-      `Recording in long trace mode through the UI is not supported. Please copy
-    the command and `,
-      m('a',
-        {href: cmdlineUrl, target: '_blank'},
-        `collect the trace using ADB.`));
-
-  const msgZeroProbes =
-      m('.note',
-        'It looks like you didn\'t add any probes. ' +
-            'Please add at least one to get a non-empty trace.');
-
-  if (!hasActiveProbes(globals.state.recordConfig)) {
-    notes.push(msgZeroProbes);
-  }
+      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);
 
   if (isAdbTarget(globals.state.recordingTarget)) {
     notes.push(msgRecordingNotSupported);
@@ -1062,10 +894,12 @@
     case 'Q':
       break;
     case 'P':
-      notes.push(m('.note', msgFeatNotSupported, msgSideload));
+      notes.push(msgFeatNotSupported);
+      notes.push(msgSideload);
       break;
     case 'O':
-      notes.push(m('.note', msgPerfettoNotSupported, msgSideload));
+      notes.push(msgPerfettoNotSupported);
+      notes.push(msgSideload);
       break;
     case 'L':
       notes.push(msgLinux);
@@ -1073,16 +907,10 @@
     case 'C':
       if (!globals.state.extensionInstalled) notes.push(msgChrome);
       break;
-    case 'CrOS':
-      if (!globals.state.extensionInstalled) notes.push(msgChrome);
-      break;
     default:
   }
-  if (globals.state.recordConfig.mode === 'LONG_TRACE') {
-    notes.unshift(msgLongTraces);
-  }
 
-  return notes.length > 0 ? m('div', notes) : [];
+  return notes.length > 0 ? m('.note', notes) : [];
 }
 
 function RecordingSnippet() {
@@ -1153,8 +981,7 @@
   const buttons: m.Children = [];
 
   if (isAndroidTarget(target)) {
-    if (!recInProgress && isAdbTarget(target) &&
-        globals.state.recordConfig.mode !== 'LONG_TRACE') {
+    if (!recInProgress && isAdbTarget(target)) {
       buttons.push(start);
     }
   } else if (isChromeTarget(target) && state.extensionInstalled) {
@@ -1185,7 +1012,6 @@
 
   const target = globals.state.recordingTarget;
   if (isAndroidTarget(target) || isChromeTarget(target)) {
-    globals.logging.logEvent('Record Trace', `Record trace (${target.os})`);
     globals.dispatch(Actions.startRecording({}));
   }
 }
@@ -1320,55 +1146,42 @@
         m('a[href="#!/record?p=instructions"]',
           m(`li${routePage === 'instructions' ? '.active' : ''}`,
             m('i.material-icons.rec', 'fiber_manual_record'),
-            m('.title', 'Recording command'),
-            m('.sub', 'Manually record trace'))),
-        localStorage.hasOwnProperty(LOCAL_STORAGE_SHOW_CONFIG) ?
-            m('a[href="#!/record?p=config"]',
-              {
-                onclick: () => {
-                  recordConfigStore.reloadFromLocalStorage();
-                }
-              },
-              m(`li${routePage === 'config' ? '.active' : ''}`,
-                m('i.material-icons', 'tune'),
-                m('.title', 'Saved configs'),
-                m('.sub', 'Manage local configs'))) :
-            null),
+            m('.title', 'Instructions'),
+            m('.sub', 'Generate config and instructions')))),
       m('header', 'Probes'),
-      m('ul',
-        isChromeTarget(target) && !isCrOSTarget(target) ? [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, memory'))),
-          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')))
-        ]));
+      m('ul', isChromeTarget(target) ? [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')))
+      ]));
 }
 
 
@@ -1377,7 +1190,6 @@
     const SECTIONS: {[property: string]: (cssClass: string) => m.Child} = {
       buffers: RecSettings,
       instructions: Instructions,
-      config: Configurations,
       cpu: CpuSettings,
       gpu: GpuSettings,
       power: PowerSettings,
@@ -1388,8 +1200,7 @@
     };
 
     const pages: m.Children = [];
-    const routePageParam = Router.param('p');
-    let routePage = typeof routePageParam === 'string' ? routePageParam : '';
+    let routePage = Router.param('p');
     if (!Object.keys(SECTIONS).includes(routePage)) {
       routePage = 'buffers';
     }
diff --git a/ui/src/frontend/record_widgets.ts b/ui/src/frontend/record_widgets.ts
index b107080..20d5901 100644
--- a/ui/src/frontend/record_widgets.ts
+++ b/ui/src/frontend/record_widgets.ts
@@ -27,31 +27,13 @@
 declare type Getter<T> = (cfg: RecordConfig) => T;
 
 // +---------------------------------------------------------------------------+
-// | Docs link with 'i' in circle icon.                                        |
-// +---------------------------------------------------------------------------+
-
-interface DocsChipAttrs {
-  href: string;
-}
-
-class DocsChip implements m.ClassComponent<DocsChipAttrs> {
-  view({attrs}: m.CVnode<DocsChipAttrs>) {
-    return m(
-        'a.inline-chip',
-        {href: attrs.href, title: 'Open docs in new tab', target: '_blank'},
-        m('i.material-icons', 'info'),
-        ' Docs');
-  }
-}
-
-// +---------------------------------------------------------------------------+
 // | Probe: the rectangular box on the right-hand-side with a toggle box.      |
 // +---------------------------------------------------------------------------+
 
 export interface ProbeAttrs {
   title: string;
   img: string|null;
-  descr: m.Children;
+  descr: string;
   isEnabled: Getter<boolean>;
   setEnabled: Setter<boolean>;
 }
@@ -70,58 +52,17 @@
     return m(
         `.probe${enabled ? '.enabled' : ''}`,
         attrs.img && m('img', {
-          src: `${globals.root}assets/${attrs.img}`,
+          src: `assets/${attrs.img}`,
           onclick: () => onToggle(!enabled),
         }),
         m('label',
-          m(`input[type=checkbox]`, {
-            checked: enabled,
-            oninput: (e: InputEvent) => {
-              onToggle((e.target as HTMLInputElement).checked);
-            },
-          }),
+          m(`input[type=checkbox]`,
+            {checked: enabled, oninput: m.withAttr('checked', onToggle)}),
           m('span', attrs.title)),
         m('div', m('div', attrs.descr), m('.probe-config', children)));
   }
 }
 
-// +-------------------------------------------------------------+
-// | Toggle: an on/off switch.
-// +-------------------------------------------------------------+
-
-export interface ToggleAttrs {
-  title: string;
-  descr: string;
-  cssClass?: string;
-  isEnabled: Getter<boolean>;
-  setEnabled: Setter<boolean>;
-}
-
-export class Toggle implements m.ClassComponent<ToggleAttrs> {
-  view({attrs}: m.CVnode<ToggleAttrs>) {
-    const onToggle = (enabled: boolean) => {
-      const traceCfg = produce(globals.state.recordConfig, draft => {
-        attrs.setEnabled(draft, enabled);
-      });
-      globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
-    };
-
-    const enabled = attrs.isEnabled(globals.state.recordConfig);
-
-    return m(
-        `.toggle${enabled ? '.enabled' : ''}${attrs.cssClass || ''}`,
-        m('label',
-          m(`input[type=checkbox]`, {
-            checked: enabled,
-            oninput: (e: InputEvent) => {
-              onToggle((e.target as HTMLInputElement).checked);
-            },
-          }),
-          m('span', attrs.title)),
-        m('.descr', attrs.descr));
-  }
-}
-
 // +---------------------------------------------------------------------------+
 // | Slider: draggable horizontal slider with numeric spinner.                 |
 // +---------------------------------------------------------------------------+
@@ -181,17 +122,13 @@
         type: 'text',
         pattern: '(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}',  // hh:mm:ss
         value: new Date(val).toISOString().substr(11, 8),
-        oninput: (e: InputEvent) => {
-          this.onTimeValueChange(attrs, (e.target as HTMLInputElement).value);
-        },
+        oninput: m.withAttr('value', v => this.onTimeValueChange(attrs, v))
       };
     } else {
       spinnerCfg = {
         type: 'number',
         value: val,
-        oninput: (e: InputEvent) => {
-          this.onTimeValueChange(attrs, (e.target as HTMLInputElement).value);
-        },
+        oninput: m.withAttr('value', v => this.onValueChange(attrs, v))
       };
     }
     return m(
@@ -201,11 +138,7 @@
         attrs.icon !== undefined ? m('i.material-icons', attrs.icon) : [],
         m(`input[id="${id}"][type=range][min=0][max=${maxIdx}][value=${idx}]
         ${disabled ? '[disabled]' : ''}`,
-          {
-            oninput: (e: InputEvent) => {
-              this.onSliderChange(attrs, +(e.target as HTMLInputElement).value);
-            },
-          }),
+          {oninput: m.withAttr('value', v => this.onSliderChange(attrs, v))}),
         m(`input.spinner[min=${min !== undefined ? min : 1}][for=${id}]`,
           spinnerCfg),
         m('.unit', attrs.unit));
@@ -251,9 +184,7 @@
     const options: m.Children = [];
     const selItems = attrs.get(globals.state.recordConfig);
     let numSelected = 0;
-    const entries = [...attrs.options.entries()];
-    entries.sort((a, b) => a[1].localeCompare(b[1]));
-    for (const [key, label] of entries) {
+    for (const [key, label] of attrs.options) {
       const opts = {value: key, selected: false};
       if (selItems.includes(key)) {
         opts.selected = true;
@@ -282,7 +213,6 @@
 
 export interface TextareaAttrs {
   placeholder: string;
-  docsLink?: string;
   cssClass?: string;
   get: Getter<string>;
   set: Setter<string>;
@@ -300,9 +230,7 @@
   view({attrs}: m.CVnode<TextareaAttrs>) {
     return m(
         '.textarea-holder',
-        m('header',
-          attrs.title,
-          attrs.docsLink && [' ', m(DocsChip, {href: attrs.docsLink})]),
+        m('header', attrs.title),
         m(`textarea.extra-input${attrs.cssClass || ''}`, {
           onchange: (e: Event) =>
               this.onChange(attrs, e.target as HTMLTextAreaElement),
diff --git a/ui/src/frontend/router.ts b/ui/src/frontend/router.ts
index 1c6a539..ee82482 100644
--- a/ui/src/frontend/router.ts
+++ b/ui/src/frontend/router.ts
@@ -15,7 +15,6 @@
 import * as m from 'mithril';
 
 import {Actions, DeferredAction} from '../common/actions';
-import {Analytics} from '../frontend/analytics';
 
 interface RouteMap {
   [route: string]: m.Component;
@@ -26,8 +25,7 @@
 export class Router {
   constructor(
       private defaultRoute: string, private routes: RouteMap,
-      private dispatch: (a: DeferredAction) => void,
-      private logging: Analytics) {
+      private dispatch: (a: DeferredAction) => void) {
     if (!(defaultRoute in routes)) {
       throw Error('routes must define a component for defaultRoute.');
     }
@@ -55,7 +53,6 @@
    */
   setRouteOnHash(route: string) {
     history.pushState(undefined, "", ROUTE_PREFIX + route);
-    this.logging.updatePath(route);
 
     if (!(route in this.routes)) {
       console.info(
diff --git a/ui/src/frontend/router_jsdomtest.ts b/ui/src/frontend/router_jsdomtest.ts
index 0d77e5b..52a140e 100644
--- a/ui/src/frontend/router_jsdomtest.ts
+++ b/ui/src/frontend/router_jsdomtest.ts
@@ -16,7 +16,6 @@
 
 import {Actions, DeferredAction} from '../common/actions';
 
-import {NullAnalytics} from './analytics';
 import {Router} from './router';
 
 const mockComponent = {
@@ -25,29 +24,23 @@
 
 const fakeDispatch = () => {};
 
-const mockLogging = new NullAnalytics();
-
 beforeEach(() => {
   window.onhashchange = null;
   window.location.hash = '';
 });
 
 test('Default route must be defined', () => {
-  expect(
-      () => new Router('/a', {'/b': mockComponent}, fakeDispatch, mockLogging))
-      .toThrow();
+  expect(() => new Router('/a', {'/b': mockComponent}, fakeDispatch)).toThrow();
 });
 
 test('Resolves empty route to default component', () => {
-  const router =
-      new Router('/a', {'/a': mockComponent}, fakeDispatch, mockLogging);
+  const router = new Router('/a', {'/a': mockComponent}, fakeDispatch);
   expect(router.resolve('')).toBe(mockComponent);
   expect(router.resolve(null)).toBe(mockComponent);
 });
 
 test('Parse route from hash', () => {
-  const router =
-      new Router('/', {'/': mockComponent}, fakeDispatch, mockLogging);
+  const router = new Router('/', {'/': mockComponent}, fakeDispatch);
   window.location.hash = '#!/foobar?s=42';
   expect(router.getRouteFromHash()).toBe('/foobar');
 
@@ -63,8 +56,7 @@
         '/': mockComponent,
         '/a': mockComponent,
       },
-      dispatch,
-      mockLogging);
+      dispatch);
   const prevHistoryLength = window.history.length;
 
   router.setRouteOnHash('/a');
@@ -78,7 +70,7 @@
   const dispatch = dingus<(a: DeferredAction) => void>();
   // const dispatch = () => {console.log("action received")};
 
-  const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging);
+  const router = new Router('/', {'/': mockComponent}, dispatch);
   router.setRouteOnHash('foo');
   expect(dispatch.calls.length).toBe(1);
   expect(dispatch.calls[0][1].length).toBeGreaterThanOrEqual(1);
@@ -96,8 +88,7 @@
         '/': mockComponent,
         '/viewer': mockComponent,
       },
-      mockDispatch,
-      mockLogging);
+      mockDispatch);
   window.location.hash = '#!/viewer';
 });
 
@@ -113,8 +104,7 @@
         '/': mockComponent,
         '/viewer': mockComponent,
       },
-      mockDispatch,
-      mockLogging);
+      mockDispatch);
 
   window.location.hash = '#invalid';
 });
@@ -122,8 +112,8 @@
 test('navigateToCurrentHash with valid current route', () => {
   const dispatch = dingus<(a: DeferredAction) => void>();
   window.location.hash = '#!/b';
-  const router = new Router(
-      '/', {'/': mockComponent, '/b': mockComponent}, dispatch, mockLogging);
+  const router =
+      new Router('/', {'/': mockComponent, '/b': mockComponent}, dispatch);
   router.navigateToCurrentHash();
   expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/b'}));
 });
@@ -131,7 +121,7 @@
 test('navigateToCurrentHash with invalid current route', () => {
   const dispatch = dingus<(a: DeferredAction) => void>();
   window.location.hash = '#!/invalid';
-  const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging);
+  const router = new Router('/', {'/': mockComponent}, dispatch);
   router.navigateToCurrentHash();
   expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/'}));
 });
diff --git a/ui/src/frontend/rpc_http_dialog.ts b/ui/src/frontend/rpc_http_dialog.ts
index 40e9036..37ee823 100644
--- a/ui/src/frontend/rpc_http_dialog.ts
+++ b/ui/src/frontend/rpc_http_dialog.ts
@@ -26,12 +26,12 @@
 
 YES, use loaded trace:
 Will load from the current state of Trace Processor. If you did run
-trace_processor_shell --httpd file.pftrace this is likely what you want.
+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 --httpd.
+trace_processor_shell --http.
 
 NO, Use builtin WASM:
 Will not use the accelerator in this tab.
@@ -39,8 +39,6 @@
 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.
-- You may encounter UI errors if the Trace Processor version you are using is
-too old. Get the latest version from get.perfetto.dev/trace_processor.
 `;
 
 // Try to connect to the external Trace Processor HTTP RPC accelerator (if
diff --git a/ui/src/frontend/scroll_helper.ts b/ui/src/frontend/scroll_helper.ts
index be24399..431e041 100644
--- a/ui/src/frontend/scroll_helper.ts
+++ b/ui/src/frontend/scroll_helper.ts
@@ -18,8 +18,6 @@
 
 import {globals} from './globals';
 
-const INCOMPLETE_SLICE_TIME_S = 0.00003;
-
 /**
  * Given a timestamp, if |ts| is not currently in view move the view to
  * center |ts|, keeping the same zoom level.
@@ -29,7 +27,7 @@
   const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
   const currentViewNs = endNs - startNs;
   if (ts < startNs || ts > endNs) {
-    // TODO(hjd): This is an ugly jump, we should do a smooth pan instead.
+    // 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)));
   }
@@ -42,11 +40,7 @@
 export function horizontalScrollAndZoomToRange(startTs: number, endTs: number) {
   const visibleDur = globals.frontendLocalState.visibleWindowTime.end -
       globals.frontendLocalState.visibleWindowTime.start;
-  let selectDur = endTs - startTs;
-  if (toNs(selectDur) === -1) {  // Unfinished slice
-    selectDur = INCOMPLETE_SLICE_TIME_S;
-    endTs = startTs;
-  }
+  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 ||
@@ -106,22 +100,4 @@
     verticalScrollToTrack(trackId, openGroup);
   }
   horizontalScrollToTs(ts);
-}
-
-/**
- * Returns the UI track Id that is associated with the given |traceTrackId| in
- * the trace_processor. Due to concepts like Async tracks and TrackGroups this
- * is not always a one to one mapping.
- */
-export function findUiTrackId(traceTrackId: number) {
-  for (const [uiTrackId, trackState] of Object.entries(globals.state.tracks)) {
-    const config = trackState.config as {trackId: number};
-    if (config.trackId === traceTrackId) return uiTrackId;
-    const multiple = trackState.config as {trackIds: number[]};
-    if (multiple.trackIds !== undefined &&
-        multiple.trackIds.includes(traceTrackId)) {
-      return uiTrackId;
-    }
-  }
-  return null;
-}
+}
\ No newline at end of file
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
index cfdc259..65f46fe 100644
--- a/ui/src/frontend/search_handler.ts
+++ b/ui/src/frontend/search_handler.ts
@@ -19,15 +19,6 @@
 import {globals} from './globals';
 import {scrollToTrackAndTs} from './scroll_helper';
 
-function setToPrevious(current: number) {
-  globals.frontendLocalState.setSearchIndex(Math.max(current - 1, 0));
-}
-
-function setToNext(current: number) {
-  globals.frontendLocalState.setSearchIndex(
-      Math.min(current + 1, globals.currentSearchResults.totalResults - 1));
-}
-
 export function executeSearch(reverse = false) {
   const state = globals.frontendLocalState;
   const index = state.searchIndex;
@@ -41,27 +32,24 @@
     if (reverse) {
       const [smaller,] =
         searchSegment(globals.currentSearchResults.tsStarts, endNs);
-      // If there is no item in the viewport just go to the previous.
-      smaller === -1 ? setToPrevious(index) :
-                       globals.frontendLocalState.setSearchIndex(smaller);
+      globals.frontendLocalState.setSearchIndex(smaller);
     } else {
       const [, larger] =
           searchSegment(globals.currentSearchResults.tsStarts, startNs);
-      // If there is no item in the viewport just go to the next.
-      larger === -1 ? setToNext(index) :
-                      globals.frontendLocalState.setSearchIndex(larger);
+      globals.frontendLocalState.setSearchIndex(larger);
     }
   } else {
     // If the currentTs is in the viewport, increment the index.
     if (reverse) {
-      setToPrevious(index);
+      globals.frontendLocalState.setSearchIndex(Math.max(index - 1, 0));
     } else {
-      setToNext(index);
+      globals.frontendLocalState.setSearchIndex(Math.min(
+          index + 1, globals.currentSearchResults.sliceIds.length - 1));
     }
   }
   selectCurrentSearchResult();
 
-  // TODO(hjd): If the user does a search before any other selection,
+  // 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.
diff --git a/ui/src/frontend/service_worker_controller.ts b/ui/src/frontend/service_worker_controller.ts
index bc11ee3..55bcfdc 100644
--- a/ui/src/frontend/service_worker_controller.ts
+++ b/ui/src/frontend/service_worker_controller.ts
@@ -74,24 +74,12 @@
   async install() {
     if (!('serviceWorker' in navigator)) return;  // Not supported.
 
-    if (location.pathname !== '/') {
-      // Disable the service worker when the UI is loaded from a non-root URL
-      // (e.g. from the CI artifacts GCS bucket). Supporting the case of a
-      // nested index.html is too cumbersome and has no benefits.
-      return;
-    }
-
     if (await caches.has(BYPASS_ID)) {
       this._bypassed = true;
       console.log('Skipping service worker registration, disabled by the user');
       return;
     }
-    // In production cases versionDir == VERSION. We use this here for ease of
-    // testing (so we can have /v1.0.0a/ /v1.0.0b/ even if they have the same
-    // version code).
-    const versionDir = globals.root.split('/').slice(-2)[0];
-    const swUri = `/service_worker.js?v=${versionDir}`;
-    navigator.serviceWorker.register(swUri).then(registration => {
+    navigator.serviceWorker.register('service_worker.js').then(registration => {
       this._initialWorker = registration.active;
 
       // At this point there are two options:
@@ -102,7 +90,8 @@
       this.monitorWorker(registration.installing);
       this.monitorWorker(registration.active);
 
-      // Setup the event that shows the "Updated to v1.2.3" notification.
+      // Setup the event that shows the "A new release is available"
+      // notification.
       registration.addEventListener('updatefound', () => {
         this.monitorWorker(registration.installing);
       });
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index b9f8d0f..a71d371 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -14,15 +14,12 @@
 
 import * as m from 'mithril';
 
-import {assertExists, assertTrue} from '../base/logging';
+import {assertTrue} from '../base/logging';
 import {Actions} from '../common/actions';
-import {TRACE_SUFFIX} from '../common/constants';
 import {QueryResponse} from '../common/queries';
-import {EngineMode, TraceArrayBufferSource} from '../common/state';
-import * as version from '../gen/perfetto_version';
+import {EngineMode} from '../common/state';
 
 import {Animation} from './animation';
-import {copyToClipboard} from './clipboard';
 import {globals} from './globals';
 import {toggleHelp} from './help_modal';
 import {
@@ -30,20 +27,25 @@
   openFileWithLegacyTraceViewer,
 } from './legacy_trace_viewer';
 import {showModal} from './modal';
-import {isDownloadable, isShareable} from './trace_attrs';
 
 const ALL_PROCESSES_QUERY = 'select name, pid from process order by name;';
 
 const CPU_TIME_FOR_PROCESSES = `
 select
   process.name,
-  sum(dur)/1e9 as cpu_sec
-from sched
-join thread using(utid)
+  tot_proc/1e9 as cpu_sec
+from
+  (select
+    upid,
+    sum(tot_thd) as tot_proc
+  from
+    (select
+      utid,
+      sum(dur) as tot_thd
+    from sched group by utid)
+  join thread using(utid) group by upid)
 join process using(upid)
-group by upid
-order by cpu_sec desc
-limit 100;`;
+order by cpu_sec desc limit 100;`;
 
 const CYCLES_PER_P_STATE_PER_CPU = `
 select
@@ -62,30 +64,26 @@
 ) group by cpu, freq
 order by mcycles desc limit 32;`;
 
-const CPU_TIME_BY_CPU_BY_PROCESS = `
-select
-  process.name as process,
-  thread.name as thread,
-  cpu,
-  sum(dur) / 1e9 as cpu_sec
-from sched
-inner join thread using(utid)
-inner join process using(upid)
-group by utid, cpu
-order by cpu_sec desc
-limit 30;`;
+const CPU_TIME_BY_CLUSTER_BY_PROCESS = `
+select process.name as process, thread, core, cpu_sec from (
+  select thread.name as thread, upid,
+    case when cpug = 0 then 'little' else 'big' end as core,
+    cpu_sec from (select cpu/4 as cpug, utid, sum(dur)/1e9 as cpu_sec
+    from sched group by utid, cpug order by cpu_sec desc
+  ) inner join thread using(utid)
+) inner join process using(upid) limit 30;`;
 
 const HEAP_GRAPH_BYTES_PER_TYPE = `
 select
-  o.upid,
-  o.graph_sample_ts,
-  c.name,
-  sum(o.self_size) as total_self_size
-from heap_graph_object o join heap_graph_class c on o.type_id = c.id
+  upid,
+  graph_sample_ts,
+  type_name,
+  sum(self_size) as total_self_size
+from heap_graph_object
 group by
- o.upid,
- o.graph_sample_ts,
- c.name
+ upid,
+ graph_sample_ts,
+ type_name
 order by total_self_size desc
 limit 100;`;
 
@@ -98,6 +96,8 @@
 from sqlstats, first
 order by started desc`;
 
+const TRACE_STATS = 'select * from stats order by severity, source, name, idx';
+
 let lastTabTitle = '';
 
 function createCannedQuery(query: string): (_: Event) => void {
@@ -111,16 +111,6 @@
   };
 }
 
-function showDebugTrack(): (_: Event) => void {
-  return (e: Event) => {
-    e.preventDefault();
-    globals.dispatch(Actions.addDebugTrack({
-      engineId: Object.keys(globals.state.engines)[0],
-      name: 'Debug Slices',
-    }));
-  };
-}
-
 const EXAMPLE_ANDROID_TRACE_URL =
     'https://storage.googleapis.com/perfetto-misc/example_android_trace_15s';
 
@@ -152,8 +142,9 @@
       {t: 'Show timeline', a: navigateViewer, i: 'line_style'},
       {
         t: 'Share',
-        a: shareTrace,
+        a: dispatchCreatePermalink,
         i: 'share',
+        checkDownloadDisabled: true,
         internalUserOnly: true,
       },
       {
@@ -163,9 +154,7 @@
         checkDownloadDisabled: true,
       },
       {t: 'Legacy UI', a: openCurrentTraceWithOldUI, i: 'filter_none'},
-      {t: 'Query (SQL)', a: navigateAnalyze, i: 'control_camera'},
-      {t: 'Metrics', a: navigateMetrics, i: 'speed'},
-      {t: 'Info and stats', a: navigateInfo, i: 'info'},
+      {t: 'Analyze', a: navigateAnalyze, i: 'control_camera'},
     ],
   },
   {
@@ -186,15 +175,10 @@
     ],
   },
   {
-    title: 'Sample queries',
+    title: 'Metrics and auditors',
     summary: 'Compute summary statistics',
     items: [
       {
-        t: 'Show Debug Track',
-        a: showDebugTrack(),
-        i: 'view_day',
-      },
-      {
         t: 'All Processes',
         a: createCannedQuery(ALL_PROCESSES_QUERY),
         i: 'search',
@@ -210,8 +194,8 @@
         i: 'search',
       },
       {
-        t: 'CPU Time by CPU by process',
-        a: createCannedQuery(CPU_TIME_BY_CPU_BY_PROCESS),
+        t: 'CPU Time by cluster by process',
+        a: createCannedQuery(CPU_TIME_BY_CLUSTER_BY_PROCESS),
         i: 'search',
       },
       {
@@ -220,6 +204,11 @@
         i: 'search',
       },
       {
+        t: 'Trace stats',
+        a: createCannedQuery(TRACE_STATS),
+        i: 'bug_report',
+      },
+      {
         t: 'Debug SQL performance',
         a: createCannedQuery(SQL_STATS),
         i: 'bug_report',
@@ -285,7 +274,6 @@
 function openCurrentTraceWithOldUI(e: Event) {
   e.preventDefault();
   console.assert(isTraceLoaded());
-  globals.logging.logEvent('Trace Actions', 'Open current trace in legacy UI');
   if (!isTraceLoaded) return;
   const engine = Object.values(globals.state.engines)[0];
   const src = engine.source;
@@ -293,30 +281,13 @@
     openInOldUIWithSizeCheck(new Blob([src.buffer]));
   } else if (src.type === 'FILE') {
     openInOldUIWithSizeCheck(src.file);
-  } else if (src.type === 'URL') {
-    m.request({
-       method: 'GET',
-       url: src.url,
-       // TODO(hjd): Once mithril is updated we can use responseType here rather
-       // than using config and remove the extract below.
-       config: xhr => {
-         xhr.responseType = 'blob';
-         xhr.onprogress = progress => {
-           const percent = (100 * progress.loaded / progress.total).toFixed(1);
-           globals.dispatch(Actions.updateStatus({
-             msg: `Downloading trace ${percent}%`,
-             timestamp: Date.now() / 1000,
-           }));
-         };
-       },
-       extract: xhr => {
-         return xhr.response;
-       }
-     }).then(result => {
-      openInOldUIWithSizeCheck(result as Blob);
-    });
   } else {
-    throw new Error(`Loading to catapult from source with type ${src.type}`);
+    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.
   }
 }
 
@@ -334,7 +305,6 @@
 
 function openTraceUrl(url: string): (e: Event) => void {
   return e => {
-    globals.logging.logEvent('Trace Actions', 'Open example trace');
     e.preventDefault();
     globals.frontendLocalState.localOnlyMode = false;
     globals.dispatch(Actions.openTraceFromUrl({url}));
@@ -378,13 +348,12 @@
     globals.dispatch(Actions.openVideoFromFile({file}));
     return;
   }
-  globals.logging.logEvent('Trace Actions', 'Open trace from file');
+
   globals.dispatch(Actions.openTraceFromFile({file}));
 }
 
 async function openWithLegacyUi(file: File) {
   // Switch back to the old catapult UI.
-  globals.logging.logEvent('Trace Actions', 'Open trace in Legacy UI');
   if (await isLegacyTrace(file)) {
     openFileWithLegacyTraceViewer(file);
     return;
@@ -457,17 +426,7 @@
 
 function navigateAnalyze(e: Event) {
   e.preventDefault();
-  globals.dispatch(Actions.navigate({route: '/query'}));
-}
-
-function navigateMetrics(e: Event) {
-  e.preventDefault();
-  globals.dispatch(Actions.navigate({route: '/metrics'}));
-}
-
-function navigateInfo(e: Event) {
-  e.preventDefault();
-  globals.dispatch(Actions.navigate({route: '/info'}));
+  globals.dispatch(Actions.navigate({route: '/analyze'}));
 }
 
 function navigateViewer(e: Event) {
@@ -475,61 +434,37 @@
   globals.dispatch(Actions.navigate({route: '/viewer'}));
 }
 
-function shareTrace(e: Event) {
+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();
-  const engine = assertExists(Object.values(globals.state.engines)[0]);
-  const traceUrl = (engine.source as (TraceArrayBufferSource)).url || '';
-
-  // If the trace is not shareable (has been pushed via postMessage()) but has
-  // a url, create a pseudo-permalink by echoing back the URL.
-  if (!isShareable()) {
-    const msg =
-        [m('p',
-           'This trace was opened by an external site and as such cannot ' +
-               'be re-shared preserving the UI state.')];
-    if (traceUrl) {
-      msg.push(m('p', 'By using the URL below you can open this trace again.'));
-      msg.push(m('p', 'Clicking will copy the URL into the clipboard.'));
-      msg.push(createTraceLink(traceUrl, traceUrl));
-    }
-
-    showModal({
-      title: 'Cannot create permalink from external trace',
-      content: m('div', msg),
-      buttons: []
-    });
-    return;
-  }
-
-  if (!isShareable() || !isTraceLoaded()) return;
+  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.logging.logEvent('Trace Actions', 'Create permalink');
-    globals.dispatch(Actions.createPermalink({isRecordingConfig: false}));
-  }
+  if (result) globals.dispatch(Actions.createPermalink({}));
 }
 
 function downloadTrace(e: Event) {
   e.preventDefault();
-  if (!isDownloadable() || !isTraceLoaded()) return;
-  globals.logging.logEvent('Trace Actions', 'Download trace');
+  if (!isTraceLoaded() || isDownloadAndShareDisabled()) return;
 
   const engine = Object.values(globals.state.engines)[0];
   if (!engine) return;
   let url = '';
-  let fileName = `trace${TRACE_SUFFIX}`;
+  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'});
-    if (src.fileName) {
-      fileName = src.fileName;
-    }
     url = URL.createObjectURL(blob);
   } else if (src.type === 'FILE') {
     const file = src.file;
@@ -542,7 +477,6 @@
   const a = document.createElement('a');
   a.href = url;
   a.download = fileName;
-  a.target = '_blank';
   document.body.appendChild(a);
   a.click();
   document.body.removeChild(a);
@@ -686,17 +620,6 @@
             'assessment')),
         m(EngineRPCWidget),
         m(ServiceWorkerWidget),
-        m(
-            '.version',
-            m('a',
-              {
-                href: `https://github.com/google/perfetto/tree/${
-                    version.SCM_REVISION}/ui`,
-                title: `Channel: ${globals.channel}`,
-                target: '_blank',
-              },
-              `${version.VERSION}`),
-            ),
     );
   }
 };
@@ -711,40 +634,31 @@
       if (section.hideIfNoTraceLoaded && !isTraceLoaded()) continue;
       const vdomItems = [];
       for (const item of section.items) {
-        let css = '';
         let attrs = {
           onclick: typeof item.a === 'function' ? item.a : null,
           href: typeof item.a === 'string' ? item.a : '#',
           target: typeof item.a === 'string' ? '_blank' : null,
           disabled: false,
         };
-        if (item.a === openCurrentTraceWithOldUI &&
-            globals.state.traceConversionInProgress) {
-          attrs.onclick = e => e.preventDefault();
-          css = '.pending';
-        }
         if ((item as {internalUserOnly: boolean}).internalUserOnly === true) {
           if (!globals.isInternalUser) continue;
         }
-        if (!isDownloadable() && item.hasOwnProperty('checkDownloadDisabled')) {
+        if (isDownloadAndShareDisabled() &&
+            item.hasOwnProperty('checkDownloadDisabled')) {
           attrs = {
-            onclick: e => {
-              e.preventDefault();
-              alert('Can not download external trace.');
-            },
+            onclick: () => alert('Can not download or share external trace.'),
             href: '#',
             target: null,
             disabled: true,
           };
         }
-        vdomItems.push(m(
-            'li', m(`a${css}`, attrs, m('i.material-icons', item.i), item.t)));
+        vdomItems.push(
+            m('li', m('a', attrs, m('i.material-icons', item.i), item.t)));
       }
       if (section.appendOpenedTraceTitle) {
         const engines = Object.values(globals.state.engines);
         if (engines.length === 1) {
           let traceTitle = '';
-          let traceUrl = '';
           switch (engines[0].source.type) {
             case 'FILE':
               // Split on both \ and / (because C:\Windows\paths\are\like\this).
@@ -753,12 +667,10 @@
               traceTitle += ` (${fileSizeMB} MB)`;
               break;
             case 'URL':
-              traceUrl = engines[0].source.url;
-              traceTitle = traceUrl.split('/').pop()!;
+              traceTitle = engines[0].source.url.split('/').pop()!;
               break;
             case 'ARRAY_BUFFER':
               traceTitle = engines[0].source.title;
-              traceUrl = engines[0].source.url || '';
               break;
             case 'HTTP_RPC':
               traceTitle = 'External trace (RPC)';
@@ -771,7 +683,7 @@
             if (tabTitle !== lastTabTitle) {
               document.title = lastTabTitle = tabTitle;
             }
-            vdomItems.unshift(m('li', createTraceLink(traceTitle, traceUrl)));
+            vdomItems.unshift(m('li', m('a.trace-file-name', traceTitle)));
           }
         }
       }
@@ -824,8 +736,8 @@
           ontransitionend: () => this._redrawWhileAnimating.stop(),
         },
         m(
-            `header.${globals.channel}`,
-            m(`img[src=${globals.root}assets/brand.png].brand`),
+            'header',
+            m('img[src=assets/brand.png].brand'),
             m('button.sidebar-button',
               {
                 onclick: () => {
@@ -850,23 +762,3 @@
     );
   }
 }
-
-function createTraceLink(title: string, url: string) {
-  if (url === '') {
-    return m('a.trace-file-name', title);
-  }
-  const linkProps = {
-    href: url,
-    title: 'Click to copy the URL',
-    target: '_blank',
-    onclick: (e: Event) => {
-      e.preventDefault();
-      copyToClipboard(url);
-      globals.dispatch(Actions.updateStatus({
-        msg: 'Link copied into the clipboard',
-        timestamp: Date.now() / 1000,
-      }));
-    },
-  };
-  return m('a.trace-file-name', linkProps, title);
-}
diff --git a/ui/src/frontend/slice_panel.ts b/ui/src/frontend/slice_panel.ts
index 775c829..7e7e93a 100644
--- a/ui/src/frontend/slice_panel.ts
+++ b/ui/src/frontend/slice_panel.ts
@@ -58,7 +58,6 @@
                   m('i.material-icons.grey',
                     {onclick: () => this.goToThread(), title: 'Go to thread'},
                     'call_made'))),
-              m('tr', m('th', `Cmdline`), m('td', threadInfo.cmdline)),
               m('tr',
                 m('th', `Start time`),
                 m('td', `${timeToCode(sliceInfo.ts)}`)),
@@ -68,7 +67,7 @@
               m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
               m('tr',
                 m('th', `End State`),
-                m('td', translateState(sliceInfo.endState)))
+                m('td', `${translateState(sliceInfo.endState)}`))
             ]),
       );
     }
@@ -93,9 +92,13 @@
       }
     }
 
-    if (trackId && sliceInfo.threadStateId) {
+    if (trackId) {
       globals.makeSelection(Actions.selectThreadState({
-        id: sliceInfo.threadStateId,
+        utid: threadInfo.utid,
+        ts: sliceInfo.ts + globals.state.traceTime.startSec,
+        dur: sliceInfo.dur,
+        state: 'Running',
+        cpu: sliceInfo.cpu,
         trackId: trackId.toString(),
       }));
 
diff --git a/ui/src/frontend/task_tracker.ts b/ui/src/frontend/task_tracker.ts
deleted file mode 100644
index 7a43fd8..0000000
--- a/ui/src/frontend/task_tracker.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-interface PromiseInfo {
-  startTimeMs: number;
-  message: string;
-}
-
-export class TaskTracker {
-  private promisesSeen: number;
-  private promisesRejected: number;
-  private promisesFulfilled: number;
-  private promiseInfo: Map<Promise<unknown>, PromiseInfo>;
-
-  constructor() {
-    this.promisesSeen = 0;
-    this.promisesRejected = 0;
-    this.promisesFulfilled = 0;
-    this.promiseInfo = new Map();
-  }
-
-  trackPromise(promise: Promise<unknown>, message: string): void {
-    this.promiseInfo.set(promise, {
-      startTimeMs: (new Date()).getMilliseconds(),
-      message,
-    });
-    this.promisesSeen += 1;
-    promise.then(() => {
-      this.promisesFulfilled += 1;
-    }).catch(() => {
-      this.promisesRejected += 1;
-    }).finally(() => {
-      this.promiseInfo.delete(promise);
-    });
-  }
-
-  hasPendingTasks(): boolean {
-    return this.promisesSeen > (this.promisesFulfilled + this.promisesRejected);
-  }
-
-  progressMessage(): string|undefined {
-    const {value} = this.promiseInfo.values().next();
-    if (value === undefined) {
-      return value;
-    } else {
-      const nowMs = (new Date()).getMilliseconds();
-      const runtimeSeconds = Math.round((nowMs - value.startTimeMs) / 1000);
-      return `${value.message} (${runtimeSeconds}s)`;
-    }
-  }
-}
-
-export const taskTracker = new TaskTracker();
diff --git a/ui/src/frontend/task_tracker_unittest.ts b/ui/src/frontend/task_tracker_unittest.ts
deleted file mode 100644
index f869843..0000000
--- a/ui/src/frontend/task_tracker_unittest.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {defer} from '../base/deferred';
-import {TaskTracker} from './task_tracker';
-
-test('it starts with no pending tasks', () => {
-  const tracker = new TaskTracker();
-  expect(tracker.hasPendingTasks()).toEqual(false);
-  expect(tracker.progressMessage()).toEqual(undefined);
-});
-
-test('it knows if a task is pending', () => {
-  const tracker = new TaskTracker();
-  const deferred = defer();
-
-  tracker.trackPromise(deferred, "Some task");
-
-  expect(tracker.hasPendingTasks()).toEqual(true);
-  expect(tracker.progressMessage()).toEqual("Some task (0s)");
-  deferred.resolve();
-});
-
diff --git a/ui/src/frontend/thread_state_panel.ts b/ui/src/frontend/thread_state_panel.ts
index 164b3a5..d6257d4 100644
--- a/ui/src/frontend/thread_state_panel.ts
+++ b/ui/src/frontend/thread_state_panel.ts
@@ -15,22 +15,24 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
+import {translateState} from '../common/thread_state';
 import {timeToCode, toNs} 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 {
-  view() {
-    const threadState = globals.threadStateDetails;
-    if (threadState === undefined || threadState.utid === undefined ||
-        threadState.ts === undefined || threadState.dur === undefined ||
-        threadState.state === undefined) {
-      return m('.details-panel');
-    }
-    const threadInfo = globals.threads.get(threadState.utid);
+export class ThreadStatePanel extends Panel<ThreadStateDetailsAttr> {
+  view({attrs}: m.CVnode<ThreadStateDetailsAttr>) {
+    const threadInfo = globals.threads.get(attrs.utid);
     if (threadInfo) {
       return m(
           '.details-panel',
@@ -38,48 +40,44 @@
           m('.details-table', [m('table.half-width', [
               m('tr',
                 m('th', `Start time`),
-                m('td', `${timeToCode(threadState.ts)}`)),
+                m('td',
+                  `${
+                      timeToCode(
+                          attrs.ts - globals.state.traceTime.startSec)}`)),
               m('tr',
                 m('th', `Duration`),
                 m(
                     'td',
-                    `${timeToCode(threadState.dur)} `,
+                    `${timeToCode(attrs.dur)} `,
                     )),
               m('tr',
                 m('th', `State`),
-                m('td',
-                  this.getStateContent(
-                      threadState.state,
-                      threadState.cpu,
-                      threadState.sliceId,
-                      threadState.ts))),
+                m('td', this.getStateContent(attrs.state, attrs.cpu))),
               m('tr',
                 m('th', `Process`),
                 m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
-              this.getBlockedFunctionContent(threadState.blockedFunction),
             ])]));
+    } else {
+      return m('.details-panel');
     }
-    return m('.details-panel');
   }
 
   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|undefined, sliceId: number|undefined,
-      ts: number) {
-    if (sliceId === undefined || cpu === undefined) {
-      return [state];
+  getStateContent(state: string, cpu: number) {
+    if (state !== 'Running') {
+      return [translateState(state)];
     }
 
     return [
-      `${state} on CPU ${cpu}`,
-      m(
-          'i.material-icons.grey',
-          {
-            onclick: () => {
-              // TODO(hjd): Use trackId from TP.
+      `${translateState(state)} on CPU ${cpu}`,
+      m('i.material-icons.grey',
+        {
+          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' &&
@@ -88,22 +86,19 @@
                 }
               }
               if (trackId) {
-                globals.makeSelection(
-                    Actions.selectSlice({id: sliceId, trackId}));
+                globals.makeSelection(Actions.selectSlice(
+                    {id: globals.sliceDetails.id, trackId}));
                 scrollToTrackAndTs(
-                    trackId, toNs(ts + globals.state.traceTime.startSec));
+                    trackId,
+                    toNs(
+                        globals.sliceDetails.ts +
+                        globals.state.traceTime.startSec));
               }
-            },
-            title: 'Go to CPU slice'
+            }
           },
-          'call_made')
+          title: 'Go to CPU slice'
+        },
+        'call_made')
     ];
   }
-
-  getBlockedFunctionContent(blockedFunction: string|undefined) {
-    if (blockedFunction === undefined) {
-      return null;
-    }
-    return m('tr', m('th', `Blocked Function`), m('td', blockedFunction));
-  }
 }
diff --git a/ui/src/frontend/time_scale.ts b/ui/src/frontend/time_scale.ts
index c5e92a7..e163daa 100644
--- a/ui/src/frontend/time_scale.ts
+++ b/ui/src/frontend/time_scale.ts
@@ -12,10 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertFalse, assertTrue} from '../base/logging';
 import {TimeSpan} from '../common/time';
 
-const MAX_ZOOM_SPAN_SEC = 1e-6;  // 1us.
+const MAX_ZOOM_SPAN_SEC = 1e-4;  // 0.1 ms.
 
 /**
  * Defines a mapping between number and seconds for the entire application.
@@ -61,8 +60,6 @@
   }
 
   setLimitsPx(pxStart: number, pxEnd: number) {
-    assertFalse(pxStart === pxEnd);
-    assertTrue(pxStart >= 0 && pxEnd >= 0);
     this._startPx = pxStart;
     this._endPx = pxEnd;
     this.updateSlope();
diff --git a/ui/src/frontend/time_scale_unittest.ts b/ui/src/frontend/time_scale_unittest.ts
index c6b3822..c7b72cb 100644
--- a/ui/src/frontend/time_scale_unittest.ts
+++ b/ui/src/frontend/time_scale_unittest.ts
@@ -73,5 +73,5 @@
   const scale = new TimeScale(span, [200, 300]);
   const newSpan = computeZoom(scale, span, 0.0000000001, 225);
   expect((newSpan.end - newSpan.start) / 2 + newSpan.start).toBeCloseTo(1010);
-  expect(newSpan.end - newSpan.start).toBeCloseTo(1e-6, 8);
+  expect(newSpan.end - newSpan.start).toBeCloseTo(1e-4, 8);
 });
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 8ec0748..d5dc939 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -129,35 +129,15 @@
       ctx.fillRect(xAndTime[0], 0, 1, size.height);
     }
 
-    const localArea = globals.frontendLocalState.selectedArea;
-    const selection = globals.state.currentSelection;
-    if (localArea !== undefined) {
-      const start = Math.min(localArea.startSec, localArea.endSec);
-      const end = Math.max(localArea.startSec, localArea.endSec);
-      this.renderSpan(ctx, size, new TimeSpan(start, end));
-    } else if (selection !== null && selection.kind === 'AREA') {
-      const selectedArea = globals.state.areas[selection.areaId];
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
+    if (selectedArea !== undefined) {
       const start = Math.min(selectedArea.startSec, selectedArea.endSec);
       const end = Math.max(selectedArea.startSec, selectedArea.endSec);
       this.renderSpan(ctx, size, new TimeSpan(start, end));
-    }
-
-    if (globals.frontendLocalState.hoveredLogsTimestamp !== -1) {
+    } else if (globals.frontendLocalState.hoveredLogsTimestamp !== -1) {
       this.renderHover(
           ctx, size, globals.frontendLocalState.hoveredLogsTimestamp);
     }
-
-    for (const note of Object.values(globals.state.notes)) {
-      const noteIsSelected = selection !== null && selection.kind === 'AREA' &&
-          selection.noteId === note.id;
-      if (note.noteType === 'AREA' && !noteIsSelected) {
-        const selectedArea = globals.state.areas[note.areaId];
-        this.renderSpan(
-            ctx,
-            size,
-            new TimeSpan(selectedArea.startSec, selectedArea.endSec));
-      }
-    }
   }
 
   renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: number) {
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 1f9d351..a5ef633 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -16,11 +16,9 @@
 
 import {Actions} from '../common/actions';
 import {EngineConfig} from '../common/state';
-import * as version from '../gen/perfetto_version';
 
 import {globals} from './globals';
 import {executeSearch} from './search_handler';
-import {taskTracker} from './task_tracker';
 
 const SEARCH = Symbol('search');
 const COMMAND = Symbol('command');
@@ -112,16 +110,17 @@
         `.omnibox${commandMode ? '.command-mode' : ''}`,
         m('input', {
           placeholder: PLACEHOLDER[mode],
-          oninput: (e: InputEvent) => {
-            const value = (e.target as HTMLInputElement).value;
-            globals.frontendLocalState.setOmnibox(
-                value, commandMode ? 'COMMAND' : 'SEARCH');
-            if (mode === SEARCH) {
-              globals.frontendLocalState.setSearchIndex(-1);
-              displayStepThrough = value.length >= 4;
-              globals.rafScheduler.scheduleFullRedraw();
-            }
-          },
+          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,
         }),
         displayStepThrough ?
@@ -180,7 +179,7 @@
     if (this.progressBar === undefined) return;
     const engine: EngineConfig = globals.state.engines['0'];
     if ((engine !== undefined && !engine.ready) ||
-        globals.numQueuedQueries > 0 || taskTracker.hasPendingTasks()) {
+        globals.numQueuedQueries > 0) {
       this.progressBar.classList.add('progress-anim');
     } else {
       this.progressBar.classList.remove('progress-anim');
@@ -191,12 +190,20 @@
 
 class NewVersionNotification implements m.ClassComponent {
   view() {
+    if (!globals.frontendLocalState.newVersionAvailable) return;
     return m(
         '.new-version-toast',
-        `Updated to ${version.VERSION} and ready for offline use!`,
+        'A new version of the UI is available!',
         m('button.notification-btn.preferred',
           {
             onclick: () => {
+              location.reload();
+            }
+          },
+          'Reload'),
+        m('button.notification-btn',
+          {
+            onclick: () => {
               globals.frontendLocalState.newVersionAvailable = false;
               globals.rafScheduler.scheduleFullRedraw();
             }
@@ -231,35 +238,14 @@
   }
 }
 
-class TraceErrorIcon implements m.ClassComponent {
-  view() {
-    const errors = globals.traceErrors;
-    if (!errors && !globals.metricError || mode === COMMAND) return;
-    const message = errors ? `${errors} import or data loss errors detected.` :
-                             `Metric error detected.`;
-    return m(
-        'a.error',
-        {href: '#!/info'},
-        m('i.material-icons',
-          {
-            title: message + ` Click for more info.`,
-          },
-          'announcement'));
-  }
-}
-
 export class Topbar implements m.ClassComponent {
   view() {
     return m(
         '.topbar',
-        {
-          class: globals.frontendLocalState.sidebarVisible ? '' : 'hide-sidebar'
-        },
         globals.frontendLocalState.newVersionAvailable ?
             m(NewVersionNotification) :
             m(Omnibox),
         m(Progress),
-        m(HelpPanningNotification),
-        m(TraceErrorIcon));
+        m(HelpPanningNotification));
   }
 }
diff --git a/ui/src/frontend/trace_attrs.ts b/ui/src/frontend/trace_attrs.ts
deleted file mode 100644
index 2d6ffcf..0000000
--- a/ui/src/frontend/trace_attrs.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {globals} from './globals';
-
-export function isShareable() {
-  return (globals.isInternalUser && isDownloadable());
-}
-
-export function isDownloadable() {
-  if (globals.frontendLocalState.localOnlyMode) return false;
-  const engine = Object.values(globals.state.engines)[0];
-  if (engine && engine.source.type === 'HTTP_RPC') return false;
-  return true;
-}
\ No newline at end of file
diff --git a/ui/src/frontend/trace_info_page.ts b/ui/src/frontend/trace_info_page.ts
deleted file mode 100644
index b1ba4d3..0000000
--- a/ui/src/frontend/trace_info_page.ts
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-import * as m from 'mithril';
-
-import {Actions} from '../common/actions';
-import {QueryResponse} from '../common/queries';
-
-import {globals} from './globals';
-import {createPage} from './pages';
-
-
-interface StatsSectionAttrs {
-  title: string;
-  subTitle: string;
-  sqlConstraints: string;
-  cssClass: string;
-  queryId: string;
-}
-
-// Generic class that generate a <section> + <table> from the stats table.
-// The caller defines the query constraint, title and styling.
-// Used for errors, data losses and debugging sections.
-class StatsSection implements m.ClassComponent<StatsSectionAttrs> {
-  private queryDispatched = false;
-
-  view({attrs}: m.CVnode<StatsSectionAttrs>) {
-    if (!this.queryDispatched) {
-      this.queryDispatched = true;
-      globals.dispatch(Actions.executeQuery({
-        engineId: '0',
-        queryId: attrs.queryId,
-        query: `select name, value, cast(ifnull(idx, '') as text) as idx,
-                description, severity, source from stats
-                where ${attrs.sqlConstraints || '1=1'}
-                order by name, idx`,
-      }));
-    }
-
-    const resp = globals.queryResults.get(attrs.queryId) as QueryResponse;
-    if (resp === undefined || resp.totalRowCount === 0) {
-      return m('');
-    }
-    if (resp.error) throw new Error(resp.error);
-
-    const tableRows = [];
-    for (const row of resp.rows) {
-      const help = [];
-      if (row.description) {
-        help.push(m('i.material-icons.contextual-help', 'help_outline'));
-      }
-      const idx = row.idx !== '' ? `[${row.idx}]` : '';
-      tableRows.push(m(
-          'tr',
-          m('td', {title: row.description}, `${row.name}${idx}`, help),
-          m('td', `${row.value}`),
-          m('td', `${row.severity} (${row.source})`),
-          ));
-    }
-
-    return m(
-        `section${attrs.cssClass}`,
-        m('h2', attrs.title),
-        m('h3', attrs.subTitle),
-        m(
-            'table',
-            m('thead',
-              m('tr', m('td', 'Name'), m('td', 'Value'), m('td', 'Type'))),
-            m('tbody', tableRows),
-            ),
-    );
-  }
-}
-
-class MetricErrors implements m.ClassComponent {
-  view() {
-    if (!globals.metricError) return;
-    return m(
-        `section.errors`,
-        m('h2', `Metric Errors`),
-        m('h3', `One or more metrics were not computed successfully:`),
-        m('div.metric-error', globals.metricError));
-  }
-}
-
-class TraceMetadata implements m.ClassComponent {
-  private queryDispatched = false;
-  private readonly QUERY_ID = 'info_metadata';
-
-  view() {
-    if (!this.queryDispatched) {
-      this.queryDispatched = true;
-      globals.dispatch(Actions.executeQuery({
-        engineId: '0',
-        queryId: this.QUERY_ID,
-        query: `select name, ifnull(str_value, cast(int_value as text)) as value
-                from metadata order by name`,
-      }));
-    }
-
-    const resp = globals.queryResults.get(this.QUERY_ID) as QueryResponse;
-    if (resp === undefined || resp.totalRowCount === 0) {
-      return m('');
-    }
-
-    const tableRows = [];
-    for (const row of resp.rows) {
-      tableRows.push(m(
-          'tr',
-          m('td', `${row.name}`),
-          m('td', `${row.value}`),
-          ));
-    }
-
-    return m(
-        'section',
-        m('h2', 'System info and metadata'),
-        m(
-            'table',
-            m('thead', m('tr', m('td', 'Name'), m('td', 'Value'))),
-            m('tbody', tableRows),
-            ),
-    );
-  }
-}
-
-class PackageList implements m.ClassComponent {
-  private queryDispatched = false;
-  private readonly QUERY_ID = 'info_package_list';
-
-  view() {
-    if (!this.queryDispatched) {
-      this.queryDispatched = true;
-      globals.dispatch(Actions.executeQuery({
-        engineId: '0',
-        queryId: this.QUERY_ID,
-        query: `select package_name, version_code, debuggable,
-                profileable_from_shell from package_list`,
-      }));
-    }
-
-    const resp = globals.queryResults.get(this.QUERY_ID) as QueryResponse;
-    if (resp === undefined || resp.totalRowCount === 0) {
-      return m('');
-    }
-
-    const tableRows = [];
-    for (const row of resp.rows) {
-      tableRows.push(m(
-          'tr',
-          m('td', `${row.package_name}`),
-          m('td', `${row.version_code}`),
-          m('td',
-            `${row.debuggable ? 'debuggable' : ''} ${
-                row.profileable_from_shell ? 'profileable' : ''}`),
-          ));
-    }
-
-    return m(
-        'section',
-        m('h2', 'Package list'),
-        m(
-            'table',
-            m('thead',
-              m('tr',
-                m('td', 'Name'),
-                m('td', 'Version code'),
-                m('td', 'Flags'))),
-            m('tbody', tableRows),
-            ),
-    );
-  }
-}
-
-export const TraceInfoPage = createPage({
-  view() {
-    return m(
-        '.trace-info-page',
-        m(MetricErrors),
-        m(StatsSection, {
-          queryId: 'info_errors',
-          title: 'Import errors',
-          cssClass: '.errors',
-          subTitle:
-              `The following errors have been encountered while importing the
-               trace. These errors are usually non-fatal but indicate that one
-               or more tracks might be missing or showing erroneous data.`,
-          sqlConstraints: `severity = 'error' and value > 0`,
-
-        }),
-        m(StatsSection, {
-          queryId: 'info_data_losses',
-          title: 'Data losses',
-          cssClass: '.errors',
-          subTitle:
-              `These counters are collected at trace recording time. The trace
-               data for one or more data sources was droppped and hence some
-               track contents will be incomplete.`,
-          sqlConstraints: `severity = 'data_loss' and value > 0`,
-        }),
-        m(TraceMetadata),
-        m(PackageList),
-        m(StatsSection, {
-          queryId: 'info_all',
-          title: 'Debugging stats',
-          cssClass: '',
-          subTitle: `Debugging statistics such as trace buffer usage and metrics
-                     coming from the TraceProcessor importer stages.`,
-          sqlConstraints: '',
-
-        }),
-    );
-  }
-});
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 2f491ae..4df2730 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -35,34 +35,19 @@
   create(TrackState: TrackState): Track;
 }
 
-export interface SliceRect {
-  left: number;
-  width: number;
-  top: number;
-  height: number;
-  visible: boolean;
-}
-
 /**
  * The abstract class that needs to be implemented by all tracks.
  */
 export abstract class Track<Config = {}, Data extends TrackData = TrackData> {
-  private trackId: string;
-  constructor(trackState: TrackState) {
-    this.trackId = trackState.id;
-  }
+  constructor(protected trackState: TrackState) {}
   protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
 
-  protected get trackState(): TrackState {
-    return globals.state.tracks[this.trackId];
-  }
-
   get config(): Config {
-    return globals.state.tracks[this.trackId].config as Config;
+    return this.trackState.config as Config;
   }
 
   data(): Data|undefined {
-    return globals.trackDataStore.get(this.trackId) as Data;
+    return globals.trackDataStore.get(this.trackState.id) as Data;
   }
 
   getHeight(): number {
@@ -131,15 +116,4 @@
       ctx.fillText(text2, xPos + 8, this.getHeight() / 2 + 6);
     }
   }
-
-  /**
-   * Returns a place where a given slice should be drawn. Should be implemented
-   * only for track types that support slices e.g. chrome_slice, async_slices
-   * tStart - slice start time in seconds, tEnd - slice end time in seconds,
-   * depth - slice depth
-   */
-  getSliceRect(_tStart: number, _tEnd: number, _depth: number): SliceRect
-      |undefined {
-    return undefined;
-  }
 }
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index c65af87..67d0742 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -38,6 +38,7 @@
 import {trackRegistry} from './track_registry';
 import {
   drawVerticalLineAtTime,
+  drawVerticalSelection,
 } from './vertical_line_helper';
 
 interface Attrs {
@@ -63,7 +64,8 @@
   }
 
   get summaryTrackState(): TrackState {
-    return assertExists(globals.state.tracks[this.trackGroupState.tracks[0]]);
+    return assertExists(
+        globals.state.tracks[this.trackGroupState.summaryTrackId]);
   }
 
   view({attrs}: m.CVnode<Attrs>) {
@@ -86,12 +88,10 @@
       }
     }
 
-    const selection = globals.state.currentSelection;
-
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
     const trackGroup = globals.state.trackGroups[attrs.trackGroupId];
     let checkBox = BLANK_CHECKBOX;
-    if (selection !== null && selection.kind === 'AREA') {
-      const selectedArea = globals.state.areas[selection.areaId];
+    if (selectedArea) {
       if (selectedArea.tracks.includes(attrs.trackGroupId) &&
           trackGroup.tracks.every(id => selectedArea.tracks.includes(id))) {
         checkBox = CHECKBOX;
@@ -124,17 +124,16 @@
               title: name,
             },
             name),
-          selection && selection.kind === 'AREA' ?
-              m('i.material-icons.track-button',
-                {
-                  onclick: (e: MouseEvent) => {
-                    globals.dispatch(Actions.toggleTrackSelection(
-                        {id: attrs.trackGroupId, isTrackGroup: true}));
-                    e.stopPropagation();
-                  }
-                },
-                checkBox) :
-              ''),
+          selectedArea ? m('i.material-icons.track-button',
+                           {
+                             onclick: (e: MouseEvent) => {
+                               globals.frontendLocalState.toggleTrackSelection(
+                                   attrs.trackGroupId, true /*trackGroup*/);
+                               e.stopPropagation();
+                             }
+                           },
+                           checkBox) :
+                         ''),
 
         this.summaryTrack ? m(TrackContent, {track: this.summaryTrack}) : null);
   }
@@ -146,41 +145,32 @@
   onupdate({dom}: m.CVnodeDOM<Attrs>) {
     const shell = assertExists(dom.querySelector('.shell'));
     this.shellWidth = shell.getBoundingClientRect().width;
-    // TODO(andrewbb): move this to css_constants
-    if (this.trackGroupState.collapsed) {
-      this.backgroundColor =
-          getComputedStyle(dom).getPropertyValue('--collapsed-background');
-    } else {
-      this.backgroundColor =
-          getComputedStyle(dom).getPropertyValue('--expanded-background');
-    }
+    this.backgroundColor =
+        getComputedStyle(dom).getPropertyValue('--collapsed-background');
   }
 
   highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
     const localState = globals.frontendLocalState;
-    const selection = globals.state.currentSelection;
-    if (!selection || selection.kind !== 'AREA') return;
-    const selectedArea = globals.state.areas[selection.areaId];
-    if (selectedArea.tracks.includes(this.trackGroupId)) {
-      ctx.fillStyle = 'rgba(131, 152, 230, 0.3)';
+    const area = localState.selectedArea.area;
+    if (area && area.tracks.includes(this.trackGroupId)) {
+      ctx.fillStyle = '#ebeef9';
       ctx.fillRect(
-          localState.timeScale.timeToPx(selectedArea.startSec) +
-              this.shellWidth,
+          localState.timeScale.timeToPx(area.startSec) + this.shellWidth,
           0,
-          localState.timeScale.deltaTimeToPx(
-              selectedArea.endSec - selectedArea.startSec),
+          localState.timeScale.deltaTimeToPx(area.endSec - area.startSec),
           size.height);
     }
   }
 
   renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
     const collapsed = this.trackGroupState.collapsed;
+    if (!collapsed) return;
+
+    ctx.save();
 
     ctx.fillStyle = this.backgroundColor;
     ctx.fillRect(0, 0, size.width, size.height);
 
-    if (!collapsed) return;
-
     this.highlightIfTrackSelected(ctx, size);
 
     drawGridLines(
@@ -190,15 +180,13 @@
         size.width,
         size.height);
 
-    ctx.save();
     ctx.translate(this.shellWidth, 0);
+
     if (this.summaryTrack) {
       this.summaryTrack.render(ctx);
     }
     ctx.restore();
 
-    this.highlightIfTrackSelected(ctx, size);
-
     const localState = globals.frontendLocalState;
     // Draw vertical line when hovering on the notes panel.
     if (localState.hoveredNoteTimestamp !== -1) {
@@ -215,16 +203,31 @@
           localState.timeScale,
           localState.hoveredLogsTimestamp,
           size.height,
-          `#344596`);
+          `rgb(52,69,150)`);
+    }
+    if (localState.selectedArea.area !== undefined &&
+        !globals.frontendLocalState.selectingArea) {
+      drawVerticalSelection(
+          ctx,
+          localState.timeScale,
+          localState.selectedArea.area.startSec,
+          localState.selectedArea.area.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];
-        if (note.noteType === 'DEFAULT') {
+        drawVerticalLineAtTime(ctx,
+                               localState.timeScale,
+                               note.timestamp,
+                               size.height,
+                               note.color);
+        if (note.noteType === 'AREA') {
           drawVerticalLineAtTime(
               ctx,
               localState.timeScale,
-              note.timestamp,
+              note.area.endSec,
               size.height,
               note.color);
         }
@@ -248,14 +251,14 @@
         drawVerticalLineAtTime(
             ctx,
             localState.timeScale,
-            globals.state.areas[note.areaId].startSec,
+            note.area.startSec,
             size.height,
             transparentNoteColor,
             1);
         drawVerticalLineAtTime(
             ctx,
             localState.timeScale,
-            globals.state.areas[note.areaId].endSec,
+            note.area.endSec,
             size.height,
             transparentNoteColor,
             1);
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index e982f99..92269ca 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -25,10 +25,11 @@
 import {BLANK_CHECKBOX, CHECKBOX, STAR, STAR_BORDER} from './icons';
 import {Panel, PanelSize} from './panel';
 import {verticalScrollToTrack} from './scroll_helper';
-import {SliceRect, Track} from './track';
+import {Track} from './track';
 import {trackRegistry} from './track_registry';
 import {
   drawVerticalLineAtTime,
+  drawVerticalSelection
 } from './vertical_line_helper';
 
 function isPinned(id: string) {
@@ -36,10 +37,8 @@
 }
 
 function isSelected(id: string) {
-  const selection = globals.state.currentSelection;
-  if (selection === null || selection.kind !== 'AREA') return false;
-  const selectedArea = globals.state.areas[selection.areaId];
-  return selectedArea.tracks.includes(id);
+  return globals.frontendLocalState.selectedArea.area &&
+      globals.frontendLocalState.selectedArea.area.tracks.includes(id);
 }
 
 interface TrackShellAttrs {
@@ -99,21 +98,17 @@
             tooltip: isPinned(attrs.trackState.id) ? 'Unpin' : 'Pin to top',
             showButton: isPinned(attrs.trackState.id),
           }),
-          globals.state.currentSelection !== null &&
-                  globals.state.currentSelection.kind === 'AREA' ?
-              m(TrackButton, {
-                action: (e: PerfettoMouseEvent) => {
-                  globals.dispatch(Actions.toggleTrackSelection(
-                      {id: attrs.trackState.id, isTrackGroup: false}));
-                  e.stopPropagation();
-                },
-                i: isSelected(attrs.trackState.id) ? CHECKBOX : BLANK_CHECKBOX,
-                tooltip: isSelected(attrs.trackState.id) ?
-                    'Remove track' :
-                    'Add track to selection',
-                showButton: true,
-              }) :
-              ''));
+          globals.frontendLocalState.selectedArea.area ? m(TrackButton, {
+            action: () => {
+              globals.frontendLocalState.toggleTrackSelection(
+                  attrs.trackState.id);
+            },
+            i: isSelected(attrs.trackState.id) ? CHECKBOX : BLANK_CHECKBOX,
+            tooltip: isSelected(attrs.trackState.id) ? 'Remove track' :
+                                                       'Add track to selection',
+            showButton: true,
+          }) :
+                                                         ''));
   }
 
   onmousedown(e: MouseEvent) {
@@ -175,10 +170,6 @@
 
 export interface TrackContentAttrs { track: Track; }
 export class TrackContent implements m.ClassComponent<TrackContentAttrs> {
-  private mouseDownX?: number;
-  private mouseDownY?: number;
-  private selectionOccurred = false;
-
   view({attrs}: m.CVnode<TrackContentAttrs>) {
     return m('.track-content', {
       onmousemove: (e: PerfettoMouseEvent) => {
@@ -189,32 +180,20 @@
         attrs.track.onMouseOut();
         globals.rafScheduler.scheduleRedraw();
       },
-      onmousedown: (e: PerfettoMouseEvent) => {
-        this.mouseDownX = e.layerX;
-        this.mouseDownY = e.layerY;
-      },
-      onmouseup: (e: PerfettoMouseEvent) => {
-        if (this.mouseDownX === undefined || this.mouseDownY === undefined) {
-          return;
-        }
-        if (Math.abs(e.layerX - this.mouseDownX) > 1 ||
-            Math.abs(e.layerY - this.mouseDownY) > 1) {
-          this.selectionOccurred = true;
-        }
-        this.mouseDownX = undefined;
-        this.mouseDownY = undefined;
-      },
       onclick: (e: PerfettoMouseEvent) => {
-        // This click event occurs after any selection mouse up/drag events
-        // so we have to look if the mouse moved during this click to know
-        // if a selection occurred.
-        if (this.selectionOccurred) {
-          this.selectionOccurred = false;
-          return;
-        }
-        // Returns true if something was selected, so stop propagation.
-        if (attrs.track.onMouseClick(
-                {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY})) {
+        // If we are selecting a time range - do not pass the click to the
+        // track.
+        if (globals.frontendLocalState.selectingArea) return;
+        // If the click is outside of the current time range, clear it.
+        const clickTime = globals.frontendLocalState.timeScale.pxToTime(
+            e.layerX - TRACK_SHELL_WIDTH);
+        const area = globals.frontendLocalState.selectedArea.area;
+        if (area !== undefined &&
+            (clickTime < area.startSec || clickTime > area.endSec)) {
+          globals.frontendLocalState.deselectArea();
+          e.stopPropagation();
+        } else if (attrs.track.onMouseClick(
+                       {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY})) {
           e.stopPropagation();
         }
         globals.rafScheduler.scheduleRedraw();
@@ -252,7 +231,7 @@
 }
 
 export interface TrackButtonAttrs {
-  action: (e: PerfettoMouseEvent) => void;
+  action: () => void;
   i: string;
   tooltip: string;
   showButton: boolean;
@@ -291,16 +270,14 @@
 
   highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
     const localState = globals.frontendLocalState;
-    const selection = globals.state.currentSelection;
-    if (!selection || selection.kind !== 'AREA') return;
-    const selectedArea = globals.state.areas[selection.areaId];
-    if (selectedArea.tracks.includes(this.trackState.id)) {
+    const area = localState.selectedArea.area;
+    if (area && area.tracks.includes(this.trackState.id)) {
       const timeScale = localState.timeScale;
-      ctx.fillStyle = 'rgba(131, 152, 230, 0.3)';
+      ctx.fillStyle = '#ebeef9';
       ctx.fillRect(
-          timeScale.timeToPx(selectedArea.startSec) + TRACK_SHELL_WIDTH,
+          timeScale.timeToPx(area.startSec) + TRACK_SHELL_WIDTH,
           0,
-          timeScale.deltaTimeToPx(selectedArea.endSec - selectedArea.startSec),
+          timeScale.deltaTimeToPx(area.endSec - area.startSec),
           size.height);
     }
   }
@@ -308,6 +285,8 @@
   renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
     ctx.save();
 
+    this.highlightIfTrackSelected(ctx, size);
+
     drawGridLines(
         ctx,
         globals.frontendLocalState.timeScale,
@@ -316,10 +295,10 @@
         size.height);
 
     ctx.translate(TRACK_SHELL_WIDTH, 0);
-    this.track.render(ctx);
-    ctx.restore();
 
-    this.highlightIfTrackSelected(ctx, size);
+    this.track.render(ctx);
+
+    ctx.restore();
 
     const localState = globals.frontendLocalState;
     // Draw vertical line when hovering on the notes panel.
@@ -337,16 +316,31 @@
           localState.timeScale,
           localState.hoveredLogsTimestamp,
           size.height,
-          `#344596`);
+          `rgb(52,69,150)`);
+    }
+    if (localState.selectedArea.area !== undefined &&
+        !globals.frontendLocalState.selectingArea) {
+      drawVerticalSelection(
+          ctx,
+          localState.timeScale,
+          localState.selectedArea.area.startSec,
+          localState.selectedArea.area.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];
-        if (note.noteType === 'DEFAULT') {
+        drawVerticalLineAtTime(ctx,
+                               localState.timeScale,
+                               note.timestamp,
+                               size.height,
+                               note.color);
+        if (note.noteType === 'AREA') {
           drawVerticalLineAtTime(
               ctx,
               localState.timeScale,
-              note.timestamp,
+              note.area.endSec,
               size.height,
               note.color);
         }
@@ -371,23 +365,18 @@
         drawVerticalLineAtTime(
             ctx,
             localState.timeScale,
-            globals.state.areas[note.areaId].startSec,
+            note.area.startSec,
             size.height,
             transparentNoteColor,
             1);
         drawVerticalLineAtTime(
             ctx,
             localState.timeScale,
-            globals.state.areas[note.areaId].endSec,
+            note.area.endSec,
             size.height,
             transparentNoteColor,
             1);
       }
     }
   }
-
-  getSliceRect(tStart: number, tDur: number, depth: number): SliceRect
-      |undefined {
-    return this.track.getSliceRect(tStart, tDur, depth);
-  }
 }
diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts
index b1e2cfc..d61fd70 100644
--- a/ui/src/frontend/vertical_line_helper.ts
+++ b/ui/src/frontend/vertical_line_helper.ts
@@ -41,3 +41,24 @@
     ctx.lineWidth = prevLineWidth;
 }
 
+// This draws two shaded rectangles outside of the area of interest. Effectivly
+// highlighting an area by colouring/darkening the outside areas.
+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)`);
+}
diff --git a/ui/src/frontend/video_panel.ts b/ui/src/frontend/video_panel.ts
index 405258c..9957e37 100644
--- a/ui/src/frontend/video_panel.ts
+++ b/ui/src/frontend/video_panel.ts
@@ -14,10 +14,9 @@
 
 import * as m from 'mithril';
 
-import {Actions} from '../common/actions';
-import {randomColor} from '../common/colorizer';
-
 import {globals} from './globals';
+import {Actions} from '../common/actions';
+import {randomColor} from './colorizer';
 
 export class VideoPanel implements m.ClassComponent {
   view() {
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 2d06c70..2bd33cd 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -25,6 +25,7 @@
 import {createPage} from './pages';
 import {PanAndZoomHandler} from './pan_and_zoom_handler';
 import {AnyAttrsVnode, PanelContainer} from './panel_container';
+import {QueryTable} from './query_table';
 import {TickmarkPanel} from './tickmark_panel';
 import {TimeAxisPanel} from './time_axis_panel';
 import {computeZoom} from './time_scale';
@@ -39,13 +40,8 @@
 // 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 selection = globals.state.currentSelection;
-  if (selection !== null && selection.kind === 'AREA') {
-    // If frontend selectedArea exists then we are in the process of editing the
-    // time range and need to use that value instead.
-    const area = globals.frontendLocalState.selectedArea ?
-        globals.frontendLocalState.selectedArea :
-        globals.state.areas[selection.areaId];
+  const area = globals.frontendLocalState.selectedArea.area;
+  if (area !== undefined) {
     const start = globals.frontendLocalState.timeScale.timeToPx(area.startSec);
     const end = globals.frontendLocalState.timeScale.timeToPx(area.endSec);
     const startDrag = mousePos - TRACK_SHELL_WIDTH;
@@ -74,7 +70,7 @@
     const frontendLocalState = globals.frontendLocalState;
     const updateDimensions = () => {
       const rect = vnode.dom.getBoundingClientRect();
-      frontendLocalState.updateLocalLimits(
+      frontendLocalState.updateResolution(
           0,
           rect.width - TRACK_SHELL_WIDTH -
               frontendLocalState.getScrollbarWidth());
@@ -141,36 +137,31 @@
         const scale = frontendLocalState.timeScale;
         this.keepCurrentSelection = true;
         if (editing) {
-          const selection = globals.state.currentSelection;
-          if (selection !== null && selection.kind === 'AREA') {
-            const area = globals.frontendLocalState.selectedArea ?
-                globals.frontendLocalState.selectedArea :
-                globals.state.areas[selection.areaId];
+          const selectedArea = frontendLocalState.selectedArea.area;
+          if (selectedArea !== undefined) {
             let newTime = scale.pxToTime(currentX - TRACK_SHELL_WIDTH);
             // Have to check again for when one boundary crosses over the other.
             const curBoundary = onTimeRangeBoundary(prevX);
             if (curBoundary == null) return;
-            const keepTime =
-                curBoundary === 'START' ? area.endSec : area.startSec;
+            const keepTime = curBoundary === 'START' ? selectedArea.endSec :
+                                                       selectedArea.startSec;
             // Don't drag selection outside of current screen.
             if (newTime < keepTime) {
               newTime = Math.max(newTime, scale.pxToTime(scale.startPx));
             } else {
               newTime = Math.min(newTime, scale.pxToTime(scale.endPx));
             }
-            // When editing the time range we always use the saved tracks,
-            // since these will not change.
             frontendLocalState.selectArea(
                 Math.max(Math.min(keepTime, newTime), traceTime.startSec),
                 Math.min(Math.max(keepTime, newTime), traceTime.endSec),
-                globals.state.areas[selection.areaId].tracks);
+            );
           }
         } else {
-          let startPx = Math.min(dragStartX, currentX) - TRACK_SHELL_WIDTH;
-          let endPx = Math.max(dragStartX, currentX) - TRACK_SHELL_WIDTH;
-          if (startPx < 0 && endPx < 0) return;
-          startPx = Math.max(startPx, scale.startPx);
-          endPx = Math.min(endPx, scale.endPx);
+          const startPx = Math.max(
+              Math.min(dragStartX, currentX) - TRACK_SHELL_WIDTH,
+              scale.startPx);
+          const endPx = Math.min(
+              Math.max(dragStartX, currentX) - TRACK_SHELL_WIDTH, scale.endPx);
           frontendLocalState.selectArea(
               scale.pxToTime(startPx), scale.pxToTime(endPx));
           frontendLocalState.areaY.start = dragStartY;
@@ -178,25 +169,13 @@
         }
         globals.rafScheduler.scheduleRedraw();
       },
-      endSelection: (edit: boolean) => {
+      selectingStarted: () => {
+        globals.frontendLocalState.selectingArea = true;
+      },
+      selectingEnded: () => {
+        globals.frontendLocalState.selectingArea = false;
         globals.frontendLocalState.areaY.start = undefined;
         globals.frontendLocalState.areaY.end = undefined;
-        const area = globals.frontendLocalState.selectedArea;
-        // If we are editing we need to pass the current id through to ensure
-        // the marked area with that id is also updated.
-        if (edit) {
-          const selection = globals.state.currentSelection;
-          if (selection !== null && selection.kind === 'AREA' && area) {
-            globals.dispatch(
-                Actions.editArea({area, areaId: selection.areaId}));
-          }
-        } else if (area) {
-          globals.makeSelection(Actions.selectArea({area}));
-        }
-        // Now the selection has ended we stored the final selected area in the
-        // global state and can remove the in progress selection from the
-        // frontendLocalState.
-        globals.frontendLocalState.deselectArea();
         // Full redraw to color track shell.
         globals.rafScheduler.scheduleFullRedraw();
       }
@@ -219,17 +198,15 @@
         selectable: true,
       }));
       if (group.collapsed) continue;
-      // The first track is the summary track, and is displayed as part of the
-      // group panel, we don't want to display it twice so we start from 1.
-      for (let i = 1; i < group.tracks.length; ++i) {
-        const id = group.tracks[i];
+      for (const trackId of group.tracks) {
         scrollingPanels.push(m(TrackPanel, {
-          key: `track-${group.id}-${id}`,
-          id,
+          key: `track-${group.id}-${trackId}`,
+          id: trackId,
           selectable: true,
         }));
       }
     }
+    scrollingPanels.unshift(m(QueryTable, {key: 'query', queryId: 'command'}));
 
     return m(
         '.page',
diff --git a/ui/src/gen b/ui/src/gen
index 652818c..71d53d9 120000
--- a/ui/src/gen
+++ b/ui/src/gen
@@ -1 +1 @@
-../out/tsc/gen
\ No newline at end of file
+../dist/gen
\ No newline at end of file
diff --git a/ui/src/query/index.ts b/ui/src/query/index.ts
new file mode 100644
index 0000000..bbb1f2c
--- /dev/null
+++ b/ui/src/query/index.ts
@@ -0,0 +1,317 @@
+// 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 * as m from 'mithril';
+
+import {Engine} from '../common/engine';
+import {
+  RawQueryResult,
+  rawQueryResultColumns,
+  rawQueryResultIter
+} from '../common/protos';
+import {
+  createWasmEngine,
+  destroyWasmEngine,
+  warmupWasmEngine,
+  WasmEngineProxy
+} from '../common/wasm_engine_proxy';
+
+const kEngineId = 'engine';
+const kSliceSize = 1024 * 1024;
+
+
+interface OnReadSlice {
+  (blob: Blob, end: number, slice: ArrayBuffer): void;
+}
+
+function readSlice(
+    blob: Blob, start: number, end: number, callback: OnReadSlice) {
+  const slice = blob.slice(start, end);
+  const reader = new FileReader();
+  reader.onerror = e => {
+    console.error(e);
+  };
+  reader.onloadend = _ => {
+    callback(blob, end, reader.result as ArrayBuffer);
+  };
+  reader.readAsArrayBuffer(slice);
+}
+
+
+// Represents an in flight or resolved query.
+type QueryState = QueryPendingState|QueryResultState|QueryErrorState;
+
+interface QueryResultState {
+  kind: 'QueryResultState';
+  id: number;
+  query: string;
+  result: RawQueryResult;
+  executionTimeNs: number;
+}
+
+interface QueryErrorState {
+  kind: 'QueryErrorState';
+  id: number;
+  query: string;
+  error: string;
+}
+
+interface QueryPendingState {
+  kind: 'QueryPendingState';
+  id: number;
+  query: string;
+}
+
+function isPending(q: QueryState): q is QueryPendingState {
+  return q.kind === 'QueryPendingState';
+}
+
+function isError(q: QueryState): q is QueryErrorState {
+  return q.kind === 'QueryErrorState';
+}
+
+function isResult(q: QueryState): q is QueryResultState {
+  return q.kind === 'QueryResultState';
+}
+
+
+// Helpers for accessing a query result
+function columns(result: RawQueryResult): string[] {
+  return [...rawQueryResultColumns(result)];
+}
+
+function rows(result: RawQueryResult, offset: number, count: number):
+    Array<Array<number|string>> {
+  const rows: Array<Array<number|string>> = [];
+
+  let i = 0;
+  for (const value of rawQueryResultIter(result)) {
+    if (i < offset) continue;
+    if (i > offset + count) break;
+    rows.push(Object.values(value));
+    i++;
+  }
+  return rows;
+}
+
+
+// State machine controller for the UI.
+type Input = NewFile|NewQuery|MoreData|QuerySuccess|QueryFailure;
+
+interface NewFile {
+  kind: 'NewFile';
+  file: File;
+}
+
+interface MoreData {
+  kind: 'MoreData';
+  end: number;
+  source: Blob;
+  buffer: ArrayBuffer;
+}
+
+interface NewQuery {
+  kind: 'NewQuery';
+  query: string;
+}
+
+interface QuerySuccess {
+  kind: 'QuerySuccess';
+  id: number;
+  result: RawQueryResult;
+}
+
+interface QueryFailure {
+  kind: 'QueryFailure';
+  id: number;
+  error: string;
+}
+
+class QueryController {
+  engine: Engine|undefined;
+  file: File|undefined;
+  state: 'initial'|'loading'|'ready';
+  render: (state: QueryController) => void;
+  nextQueryId: number;
+  queries: Map<number, QueryState>;
+
+  constructor(render: (state: QueryController) => void) {
+    this.render = render;
+    this.state = 'initial';
+    this.nextQueryId = 0;
+    this.queries = new Map();
+    this.render(this);
+  }
+
+  onInput(input: Input) {
+    // tslint:disable-next-line no-any
+    const f = (this as any)[`${this.state}On${input.kind}`];
+    if (f === undefined) {
+      throw new Error(`No edge for input '${input.kind}' in '${this.state}'`);
+    }
+    f.call(this, input);
+    this.render(this);
+  }
+
+  initialOnNewFile(input: NewFile) {
+    this.state = 'loading';
+    if (this.engine) {
+      destroyWasmEngine(kEngineId);
+    }
+    this.engine = new WasmEngineProxy('engine', createWasmEngine(kEngineId));
+
+    this.file = input.file;
+    this.readNextSlice(0);
+  }
+
+  loadingOnMoreData(input: MoreData) {
+    if (input.source !== this.file) return;
+    this.engine!.parse(new Uint8Array(input.buffer));
+    if (input.end === this.file.size) {
+      this.engine!.notifyEof();
+      this.state = 'ready';
+    } else {
+      this.readNextSlice(input.end);
+    }
+  }
+
+  readyOnNewQuery(input: NewQuery) {
+    const id = this.nextQueryId++;
+    this.queries.set(id, {
+      kind: 'QueryPendingState',
+      id,
+      query: input.query,
+    });
+
+    this.engine!.query(input.query)
+        .then(result => {
+          if (result.error) {
+            this.onInput({
+              kind: 'QueryFailure',
+              id,
+              error: result.error,
+            });
+          } else {
+            this.onInput({
+              kind: 'QuerySuccess',
+              id,
+              result,
+            });
+          }
+        })
+        .catch(error => {
+          this.onInput({
+            kind: 'QueryFailure',
+            id,
+            error,
+          });
+        });
+  }
+
+  readyOnQuerySuccess(input: QuerySuccess) {
+    const oldQueryState = this.queries.get(input.id);
+    console.log('sucess', input);
+    if (!oldQueryState) return;
+    this.queries.set(input.id, {
+      kind: 'QueryResultState',
+      id: oldQueryState.id,
+      query: oldQueryState.query,
+      result: input.result,
+      executionTimeNs: +input.result.executionTimeNs,
+    });
+  }
+
+  readyOnQueryFailure(input: QueryFailure) {
+    const oldQueryState = this.queries.get(input.id);
+    console.log('failure', input);
+    if (!oldQueryState) return;
+    this.queries.set(input.id, {
+      kind: 'QueryErrorState',
+      id: oldQueryState.id,
+      query: oldQueryState.query,
+      error: input.error,
+    });
+  }
+
+  readNextSlice(start: number) {
+    const end = Math.min(this.file!.size, start + kSliceSize);
+    readSlice(this.file!, start, end, (source, end, buffer) => {
+      this.onInput({
+        kind: 'MoreData',
+        end,
+        source,
+        buffer,
+      });
+    });
+  }
+}
+
+function render(root: Element, controller: QueryController) {
+  const queries = [...controller.queries.values()].sort((a, b) => b.id - a.id);
+  m.render(root, [
+    m('h1', controller.state),
+    m('input[type=file]', {
+      onchange: (e: Event) => {
+        if (!(e.target instanceof HTMLInputElement)) return;
+        if (!e.target.files) return;
+        if (!e.target.files[0]) return;
+        const file = e.target.files[0];
+        controller.onInput({
+          kind: 'NewFile',
+          file,
+        });
+      },
+    }),
+    m('input[type=text]', {
+      disabled: controller.state !== 'ready',
+      onchange: (e: Event) => {
+        controller.onInput({
+          kind: 'NewQuery',
+          query: (e.target as HTMLInputElement).value,
+        });
+      }
+    }),
+    m('.query-list',
+      queries.map(
+          q =>
+              m('.query',
+                {
+                  key: q.id,
+                },
+                m('.query-text', q.query),
+                m('.query-time',
+                  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))),
+  ]);
+}
+
+function renderTable(result: RawQueryResult) {
+  return m(
+      'table',
+      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() {
+  warmupWasmEngine();
+  const root = document.querySelector('#root');
+  if (!root) throw new Error('Could not find root element');
+  new QueryController(ctrl => render(root, ctrl));
+}
+
+main();
diff --git a/ui/src/service_worker/service_worker.ts b/ui/src/service_worker/service_worker.ts
index fbe5551..3289352 100644
--- a/ui/src/service_worker/service_worker.ts
+++ b/ui/src/service_worker/service_worker.ts
@@ -18,110 +18,38 @@
 
 // When a new version of the UI is released (e.g. v1 -> v2), the following
 // happens on the next visit:
-// 1. The v1 (old) service worker is activated. At this point we don't know yet
-//    that v2 is released.
-// 2. /index.html is requested. The SW intercepts the request and serves it from
-//    the network.
-// 3a If the request fails (offline / server unreachable) or times out, the old
-//    v1 is served.
-// 3b If the request succeeds, the browser receives the index.html for v2. That
-//    will try to fetch resources from /v2/frontend_bundle.ts.
-// 4. When the SW sees the /v2/ request, will have a cache miss and will issue
-//    a network fetch(), returning the fresh /v2/ content.
-// 4. The v2 site will call serviceWorker.register('service_worker.js?v=v2').
-//    This (i.e. the different querystring) will cause a re-installation of the
-//    service worker (even if the service_worker.js script itself is unchanged).
-// 5. In the "install" step, the service_worker.js script will fetch the newer
-//    version (v2).
-//    Note: the v2 will be fetched twice, once upon the first request that
-//    causes causes a cache-miss, the second time while re-installing the SW.
-//    The  latter though will hit a HTTP 304 (Not Changed) and will be served
-//    from the browser cache after the revalidation request.
-// 6. The 'activate' handler is triggered. The old v1 cache is deleted at this
+// 1. The v1 (old) service worker is activated (at this point we don't know yet
+//    that v2 is released).
+// 2. /index.html is requested. The SW intercepts the request and serves
+//    v1 from cache.
+// 3. The browser checks if a new version of service_worker.js is available. It
+//    does that by comparing the bytes of the current and new version.
+// 5. service_worker.js v2 will not be byte identical with v1, even if v2 was a
+//    css-only change. This is due to the hashes in UI_DIST_MAP below. For this
+//    reason v2 is installed in the background (it takes several seconds).
+// 6. The 'install' handler is triggered, the new resources are fetched and
+//    populated in the cache.
+// 7. The 'activate' handler is triggered. The old caches are deleted at this
 //    point.
+// 8. frontend/index.ts (in setupServiceWorker()) is notified about the activate
+//    and shows a notification prompting to reload the UI.
+//
+// If the user just closes the tab or hits refresh, v2 will be served anyways
+// on the next load.
+
+// UI_DIST_FILES is map of {file_name -> sha1}.
+// It is really important that this map is bundled directly in the
+// service_worker.js bundle file, as it's used to cause the browser to
+// re-install the service worker and re-fetch resources when anything changes.
+// This is why the map contains the SHA1s even if we don't directly use them in
+// the code (because it makes the final .js file content-dependent).
+
+import {UI_DIST_MAP} from '../gen/dist_file_map';
 
 declare var self: ServiceWorkerGlobalScope;
-export {};
 
-const LOG_TAG = `ServiceWorker: `;
-const CACHE_NAME = 'ui-perfetto-dev';
-
-// If the fetch() for the / doesn't respond within 3s, return a cached version.
-// This is to avoid that a user waits too much if on a flaky network.
-const INDEX_TIMEOUT_MS = 3000;
-
-// Use more relaxed timeouts when caching the subresources for the new version
-// in the background.
-const INSTALL_TIMEOUT_MS = 30000;
-
-// The install() event is fired:
-// 1. On the first visit, when there is no SW installed.
-// 2. Every time the user opens the site and the version has been updated (they
-//    will get the newer version regardless, unless we hit INDEX_TIMEOUT_MS).
-// The latter happens because:
-// - / (index.html) is always served from the network (% timeout) and it pulls
-//   /v1.2.3/frontend_bundle.js.
-// - /v1.2.3/frontend_bundle.js will register /service_worker.js?v=v1.2.3 .
-// The service_worker.js script itself never changes, but the browser
-// re-installs it because the version in the V? query-string argument changes.
-// The reinstallation will cache the new files from the v.1.2.3/manifest.json.
-self.addEventListener('install', event => {
-  const doInstall = async () => {
-    if (await caches.has('BYPASS_SERVICE_WORKER')) {
-      // Throw will prevent the installation.
-      throw new Error(LOG_TAG + 'skipping installation, bypass enabled');
-    }
-
-    // Delete old cache entries from the pre-feb-2021 service worker.
-    for (const key of await caches.keys()) {
-      if (key.startsWith('dist-')) {
-        await caches.delete(key);
-      }
-    }
-
-    // The UI should register this as service_worker.js?v=v1.2.3. Extract the
-    // version number and pre-fetch all the contents for the version.
-    const match = /\bv=([\w.]*)/.exec(location.search);
-    if (!match) {
-      throw new Error(
-          'Failed to install. Was epecting a query string like ' +
-          `?v=v1.2.3 query string, got "${location.search}" instead`);
-    }
-    await installAppVersionIntoCache(match[1]);
-
-    // skipWaiting() still waits for the install to be complete. Without this
-    // call, the new version would be activated only when all tabs are closed.
-    // Instead, we ask to activate it immediately. This is safe because the
-    // subresources are versioned (e.g. /v1.2.3/frontend_bundle.js). Even if
-    // there is an old UI tab opened while we activate() a newer version, the
-    // activate() would just cause cache-misses, hence fetch from the network,
-    // for the old tab.
-    self.skipWaiting();
-  };
-  event.waitUntil(doInstall());
-});
-
-self.addEventListener('activate', (event) => {
-  console.info(LOG_TAG + 'activated');
-  const doActivate = async () => {
-    // This makes a difference only for the very first load, when no service
-    // worker is present. In all the other cases the skipWaiting() will hot-swap
-    // the active service worker anyways.
-    await self.clients.claim();
-  };
-  event.waitUntil(doActivate());
-});
-
-self.addEventListener('fetch', event => {
-  // The early return here will cause the browser to fall back on standard
-  // network-based fetch.
-  if (!shouldHandleHttpRequest(event.request)) {
-    console.debug(LOG_TAG + `serving ${event.request.url} from network`);
-    return;
-  }
-
-  event.respondWith(handleHttpRequest(event.request));
-});
+const CACHE_NAME = 'dist-' + UI_DIST_MAP.hex_digest.substr(0, 16);
+const LOG_TAG = `ServiceWorker[${UI_DIST_MAP.hex_digest.substr(0, 16)}]: `;
 
 
 function shouldHandleHttpRequest(req: Request): boolean {
@@ -133,7 +61,6 @@
   }
 
   const url = new URL(req.url);
-  if (url.pathname === '/live_reload') return false;
   return req.method === 'GET' && url.origin === self.location.origin;
 }
 
@@ -152,90 +79,88 @@
   // resources, which is undesirable.
   // * Only Ctrl+R. Ctrl+Shift+R will always bypass service-worker for all the
   // requests (index.html and the rest) made in that tab.
-
-  const cacheOps = {cacheName: CACHE_NAME} as CacheQueryOptions;
-  const url = new URL(req.url);
-  if (url.pathname === '/') {
-    try {
-      console.debug(LOG_TAG + `Fetching live ${req.url}`);
-      // The await bleow is needed to fall through in case of an exception.
-      return await fetchWithTimeout(req, INDEX_TIMEOUT_MS);
-    } catch (err) {
-      console.warn(LOG_TAG + `Failed to fetch ${req.url}, using cache.`, err);
-      // Fall through the code below.
+  try {
+    const cacheOps = {cacheName: CACHE_NAME} as CacheQueryOptions;
+    const cachedRes = await caches.match(req, cacheOps);
+    if (cachedRes) {
+      console.debug(LOG_TAG + `serving ${req.url} from cache`);
+      return cachedRes;
     }
-  } else if (url.pathname === '/offline') {
-    // Escape hatch to force serving the offline version without attemping the
-    // network fetch.
-    const cachedRes = await caches.match(new Request('/'), cacheOps);
-    if (cachedRes) return cachedRes;
-  }
-
-  const cachedRes = await caches.match(req, cacheOps);
-  if (cachedRes) {
-    console.debug(LOG_TAG + `serving ${req.url} from cache`);
-    return cachedRes;
+    console.warn(LOG_TAG + `cache miss on ${req.url}`);
+  } catch (exc) {
+    console.error(LOG_TAG + `Cache request failed for ${req.url}`, exc);
   }
 
   // In any other case, just propagate the fetch on the network, which is the
   // safe behavior.
-  console.warn(LOG_TAG + `cache miss on ${req.url}, using live network`);
+  console.debug(LOG_TAG + `falling back on network fetch() for ${req.url}`);
   return fetch(req);
 }
 
-async function installAppVersionIntoCache(version: string) {
-  const manifestUrl = `${version}/manifest.json`;
-  try {
-    console.log(LOG_TAG + `Starting installation of ${manifestUrl}`);
-    await caches.delete(CACHE_NAME);
-    const resp = await fetchWithTimeout(manifestUrl, INSTALL_TIMEOUT_MS);
-    const manifest = await resp.json();
-    const manifestResources = manifest['resources'];
-    if (!manifestResources || !(manifestResources instanceof Object)) {
-      throw new Error(`Invalid manifest ${manifestUrl} : ${manifest}`);
+// The install() event is fired:
+// - The very first time the site is visited, after frontend/index.ts has
+//   executed the serviceWorker.register() method.
+// - *After* the site is loaded, if the service_worker.js code
+//   has changed (because of the hashes in UI_DIST_MAP, service_worker.js will
+//   change if anything in the UI has changed).
+self.addEventListener('install', event => {
+  const doInstall = async () => {
+    if (await caches.has('BYPASS_SERVICE_WORKER')) {
+      // Throw will prevent the installation.
+      throw new Error(LOG_TAG + 'skipping installation, bypass enabled');
     }
-
+    console.log(LOG_TAG + 'installation started');
     const cache = await caches.open(CACHE_NAME);
     const urlsToCache: RequestInfo[] = [];
-
-    // We use cache:reload to make sure that the index is always current and we
-    // don't end up in some cycle where we keep re-caching the index coming from
-    // the service worker itself.
-    urlsToCache.push(new Request('/', {cache: 'reload', mode: 'same-origin'}));
-
-    for (const [resource, integrity] of Object.entries(manifestResources)) {
-      // We use cache: no-cache rather then reload here because the versioned
-      // sub-resources are expected to be immutable and should never be
-      // ambiguous. A revalidation request is enough.
-      const reqOpts: RequestInit = {
-        cache: 'no-cache',
-        mode: 'same-origin',
-        integrity: `${integrity}`
-      };
-      urlsToCache.push(new Request(`${version}/${resource}`, reqOpts));
+    for (const [file, integrity] of Object.entries(UI_DIST_MAP.files)) {
+      const reqOpts:
+          RequestInit = {cache: 'reload', mode: 'same-origin', integrity};
+      urlsToCache.push(new Request(file, reqOpts));
+      if (file === 'index.html' && location.host !== 'storage.googleapis.com') {
+        // Disable cachinig of '/' for cases where the UI is hosted on GCS.
+        // GCS doesn't support auto indexes. GCS returns a 404 page on / that
+        // fails the integrity check.
+        urlsToCache.push(new Request('/', reqOpts));
+      }
     }
     await cache.addAll(urlsToCache);
-    console.log(LOG_TAG + 'installation completed for ' + version);
-  } catch (err) {
-    await caches.delete(CACHE_NAME);
-    console.error(LOG_TAG + `Installation failed for ${manifestUrl}`, err);
-    throw err;
-  }
-}
+    console.log(LOG_TAG + 'installation completed');
 
-function fetchWithTimeout(req: Request|string, timeoutMs: number) {
-  const url = (req as {url?: string}).url || `${req}`;
-  return new Promise<Response>((resolve, reject) => {
-    const timerId = setTimeout(() => {
-      reject(`Timed out while fetching ${url}`);
-    }, timeoutMs);
-    fetch(req).then(resp => {
-      clearTimeout(timerId);
-      if (resp.ok) {
-        resolve(resp);
-      } else {
-        reject(`Fetch failed for ${url}: ${resp.status} ${resp.statusText}`);
-      }
-    }, reject);
-  });
-}
+    // skipWaiting() still waits for the install to be complete. Without this
+    // call, the new version would be activated only when all tabs are closed.
+    // Instead, we ask to activate it immediately. This is safe because each
+    // service worker version uses a different cache named after the SHA256 of
+    // the contents. When the old version is activated, the activate() method
+    // below will evict the cache for the old versions. If there is an old still
+    // opened, any further request from that tab will be a cache-miss and go
+    // through the network (which is inconsitent, but not the end of the world).
+    self.skipWaiting();
+  };
+  event.waitUntil(doInstall());
+});
+
+self.addEventListener('activate', (event) => {
+  console.warn(LOG_TAG + 'activated');
+  const doActivate = async () => {
+    // Clear old caches.
+    for (const key of await caches.keys()) {
+      if (key !== CACHE_NAME) await caches.delete(key);
+    }
+    // This makes a difference only for the very first load, when no service
+    // worker is present. In all the other cases the skipWaiting() will hot-swap
+    // the active service worker anyways.
+    await self.clients.claim();
+  };
+  event.waitUntil(doActivate());
+});
+
+self.addEventListener('fetch', event => {
+  // The early return here will cause the browser to fall back on standard
+  // network-based fetch.
+  if (!shouldHandleHttpRequest(event.request)) {
+    console.debug(LOG_TAG + `serving ${event.request.url} from network`);
+    return;
+  }
+
+  event.respondWith(handleHttpRequest(event.request));
+});
diff --git a/ui/src/service_worker/tsconfig.json b/ui/src/service_worker/tsconfig.json
index 35ff5b6..7b58182 100644
--- a/ui/src/service_worker/tsconfig.json
+++ b/ui/src/service_worker/tsconfig.json
@@ -5,7 +5,6 @@
     "../gen/"
   ],
   "compilerOptions": {
-    "outDir": "../../out/tsc/service_worker",
     "lib": [
       "webworker",
       "es2018",
diff --git a/ui/src/tracks/actual_frames/common.ts b/ui/src/tracks/actual_frames/common.ts
deleted file mode 100644
index a5b5a78..0000000
--- a/ui/src/tracks/actual_frames/common.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 ACTUAL_FRAMES_SLICE_TRACK_KIND = 'ActualFramesSliceTrack';
-
-export interface Config {
-  maxDepth: number;
-  trackIds: number[];
-}
-
-export interface Data extends TrackData {
-  // 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|.
-  colors?: Uint16Array;  // Index in |strings|.
-  isInstant: Uint16Array;
-  isIncomplete: Uint16Array;
-}
diff --git a/ui/src/tracks/actual_frames/controller.ts b/ui/src/tracks/actual_frames/controller.ts
deleted file mode 100644
index b436fbe..0000000
--- a/ui/src/tracks/actual_frames/controller.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {assertTrue} from '../../base/logging';
-import {slowlyCountRows} from '../../common/query_iterator';
-import {fromNs, toNs} from '../../common/time';
-import {
-  TrackController,
-  trackControllerRegistry,
-} from '../../controller/track_controller';
-
-import {ACTUAL_FRAMES_SLICE_TRACK_KIND, Config, Data} from './common';
-
-const BLUE_COLOR = '#03A9F4';    // Blue 500
-const GREEN_COLOR = '#4CAF50';     // Green 500
-const YELLOW_COLOR = '#FFEB3B';  // Yellow 500
-const RED_COLOR = '#FF5722';      // Red 500
-const LIGHT_GREEN_COLOR = '#C0D588'; // Light Green 500
-const PINK_COLOR = '#F515E0';        // Pink 500
-
-class ActualFramesSliceTrackController extends TrackController<Config, Data> {
-  static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
-  private maxDurNs = 0;
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
-
-    const pxSize = this.pxSize();
-
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
-
-    if (this.maxDurNs === 0) {
-      const maxDurResult = await this.query(`
-        select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
-        from experimental_slice_layout
-        where filter_track_ids = '${this.config.trackIds.join(',')}'
-      `);
-      if (slowlyCountRows(maxDurResult) === 1) {
-        this.maxDurNs = maxDurResult.columns[0].longValues![0];
-      }
-    }
-
-    const rawResult = await this.query(`
-      SELECT
-        (s.ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        s.ts,
-        max(iif(s.dur = -1, (SELECT end_ts FROM trace_bounds) - s.ts, s.dur))
-            as dur,
-        s.layout_depth,
-        s.name,
-        s.id,
-        s.dur = 0 as is_instant,
-        s.dur = -1 as is_incomplete,
-        CASE afs.jank_tag
-          WHEN 'Self Jank' THEN '${RED_COLOR}'
-          WHEN 'Other Jank' THEN '${YELLOW_COLOR}'
-          WHEN 'Dropped Frame' THEN '${BLUE_COLOR}'
-          WHEN 'Buffer Stuffing' THEN '${LIGHT_GREEN_COLOR}'
-          WHEN 'SurfaceFlinger Stuffing' THEN '${LIGHT_GREEN_COLOR}'
-          WHEN 'No Jank' THEN '${GREEN_COLOR}'
-          ELSE '${PINK_COLOR}'
-        END as color
-      from experimental_slice_layout s
-      join actual_frame_timeline_slice afs using(id)
-      where
-        filter_track_ids = '${this.config.trackIds.join(',')}' and
-        s.ts >= ${startNs - this.maxDurNs} and
-        s.ts <= ${endNs}
-      group by tsq, s.layout_depth
-      order by tsq, s.layout_depth
-    `);
-
-    const numRows = slowlyCountRows(rawResult);
-    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),
-      colors: new Uint16Array(numRows),
-      isInstant: new Uint16Array(numRows),
-      isIncomplete: 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;
-    }
-
-    const cols = rawResult.columns;
-    for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      assertTrue(startNsQ !== endNsQ);
-
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.depths[row] = +cols[3].longValues![row];
-      slices.titles[row] = internString(cols[4].stringValues![row]);
-      slices.colors![row] = internString(cols[8].stringValues![row]);
-      slices.sliceIds[row] = +cols[5].longValues![row];
-      slices.isInstant[row] = +cols[6].longValues![row];
-      slices.isIncomplete[row] = +cols[7].longValues![row];
-    }
-    return slices;
-  }
-}
-
-
-trackControllerRegistry.register(ActualFramesSliceTrackController);
diff --git a/ui/src/tracks/actual_frames/frontend.ts b/ui/src/tracks/actual_frames/frontend.ts
deleted file mode 100644
index 3c91598..0000000
--- a/ui/src/tracks/actual_frames/frontend.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {ACTUAL_FRAMES_SLICE_TRACK_KIND} from './common';
-
-export class ActualFramesSliceTrack extends ChromeSliceTrack {
-  static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
-  static create(trackState: TrackState): Track {
-    return new ActualFramesSliceTrack(trackState);
-  }
-}
-
-trackRegistry.register(ActualFramesSliceTrack);
diff --git a/ui/src/tracks/all_controller.ts b/ui/src/tracks/all_controller.ts
index ca0b5c5..f2a573d 100644
--- a/ui/src/tracks/all_controller.ts
+++ b/ui/src/tracks/all_controller.ts
@@ -20,11 +20,10 @@
 import './heap_profile/controller';
 import './cpu_freq/controller';
 import './cpu_profile/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';
-import './debug_slices/controller';
-import './actual_frames/controller';
-import './expected_frames/controller';
diff --git a/ui/src/tracks/all_frontend.ts b/ui/src/tracks/all_frontend.ts
index 6af4d22..5d90e9f 100644
--- a/ui/src/tracks/all_frontend.ts
+++ b/ui/src/tracks/all_frontend.ts
@@ -20,11 +20,10 @@
 import './heap_profile/frontend';
 import './cpu_freq/frontend';
 import './cpu_profile/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';
-import './debug_slices/frontend';
-import './actual_frames/frontend';
-import './expected_frames/frontend';
diff --git a/ui/src/tracks/android_log/controller.ts b/ui/src/tracks/android_log/controller.ts
index afd235c..fba13d7 100644
--- a/ui/src/tracks/android_log/controller.ts
+++ b/ui/src/tracks/android_log/controller.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 import {
@@ -43,7 +42,7 @@
       group by ts_quant, prio
       order by ts_quant, prio limit ${LIMIT};`);
 
-    const rowCount = slowlyCountRows(rawResult);
+    const rowCount = +rawResult.numRecords;
     const result = {
       start,
       end,
diff --git a/ui/src/tracks/async_slices/common.ts b/ui/src/tracks/async_slices/common.ts
index 05ab816..daa0802 100644
--- a/ui/src/tracks/async_slices/common.ts
+++ b/ui/src/tracks/async_slices/common.ts
@@ -13,7 +13,7 @@
 // limitations under the License.
 import {TrackData} from '../../common/track_data';
 
-export const ASYNC_SLICE_TRACK_KIND = 'AsyncSliceTrack';
+export const SLICE_TRACK_KIND = 'AsyncSliceTrack';
 
 export interface Config {
   maxDepth: number;
@@ -28,6 +28,4 @@
   ends: Float64Array;
   depths: Uint16Array;
   titles: Uint16Array;  // Index in |strings|.
-  isInstant: Uint16Array;
-  isIncomplete: Uint16Array;
-}
+}
\ No newline at end of file
diff --git a/ui/src/tracks/async_slices/controller.ts b/ui/src/tracks/async_slices/controller.ts
index 50a074a..77049c8 100644
--- a/ui/src/tracks/async_slices/controller.ts
+++ b/ui/src/tracks/async_slices/controller.ts
@@ -12,61 +12,90 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
 import {
   TrackController,
   trackControllerRegistry,
 } from '../../controller/track_controller';
 
-import {ASYNC_SLICE_TRACK_KIND, Config, Data} from './common';
+import {Config, Data, SLICE_TRACK_KIND} from './common';
 
 class AsyncSliceTrackController extends TrackController<Config, Data> {
-  static readonly kind = ASYNC_SLICE_TRACK_KIND;
-  private maxDurNs = 0;
+  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);
 
-    const pxSize = this.pxSize();
+    if (!this.setup) {
+      await this.query(
+          `create virtual table ${this.tableName('window')} using window;`);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
+      await this.query(
+          `create view ${this.tableName('small')} as ` +
+          `select ts,dur,layout_depth,name,id from experimental_slice_layout ` +
+          `where filter_track_ids = "${this.config.trackIds.join(',')}" ` +
+          `and dur < ${minNs} ` +
+          `order by ts;`);
 
-    if (this.maxDurNs === 0) {
-      const maxDurResult = await this.query(`
-        select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
-        from experimental_slice_layout
-        where filter_track_ids = '${this.config.trackIds.join(',')}'
-      `);
-      if (slowlyCountRows(maxDurResult) === 1) {
-        this.maxDurNs = maxDurResult.columns[0].longValues![0];
-      }
+      await this.query(`create virtual table ${this.tableName('span')} using
+      span_join(${this.tableName('small')} PARTITIONED layout_depth,
+      ${this.tableName('window')});`);
+
+      this.setup = true;
     }
 
-    const rawResult = await this.query(`
-      SELECT
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        ts,
-        max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)) as dur,
-        layout_depth,
-        name,
-        id,
-        dur = 0 as is_instant,
-        dur = -1 as is_incomplete
-      from experimental_slice_layout
-      where
-        filter_track_ids = '${this.config.trackIds.join(',')}' and
-        ts >= ${startNs - this.maxDurNs} and
-        ts <= ${endNs}
-      group by tsq, layout_depth
-      order by tsq, layout_depth
-    `);
+    const windowDurNs = Math.max(1, endNs - startNs);
 
-    const numRows = slowlyCountRows(rawResult);
+    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,layout_depth,name,id from experimental_slice_layout ` +
+        `where filter_track_ids = "${this.config.trackIds.join(',')}" ` +
+        `and dur < ${minNs} ` +
+        `order by ts `);
+
+    await this.query(
+        `create view ${this.tableName('big')} as ` +
+        `select ts,dur,layout_depth,name,id from experimental_slice_layout ` +
+        `where filter_track_ids = "${this.config.trackIds.join(',')}" ` +
+        `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,
+      layout_depth,
+      'Busy' as name,
+      -1 as id
+      from ${this.tableName('span')}
+      group by layout_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);
+
+    const numRows = +rawResult.numRecords;
+
     const slices: Data = {
       start,
       end,
@@ -78,8 +107,6 @@
       ends: new Float64Array(numRows),
       depths: new Uint16Array(numRows),
       titles: new Uint16Array(numRows),
-      isInstant: new Uint16Array(numRows),
-      isIncomplete: new Uint16Array(numRows),
     };
 
     const stringIndexes = new Map<string, number>();
@@ -92,27 +119,14 @@
       return idx;
     }
 
-    const cols = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      if (startNsQ === endNsQ) {
-        throw new Error('Should never happen');
-      }
-
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.depths[row] = +cols[3].longValues![row];
-      slices.titles[row] = internString(cols[4].stringValues![row]);
-      slices.sliceIds[row] = +cols[5].longValues![row];
-      slices.isInstant[row] = +cols[6].longValues![row];
-      slices.isIncomplete[row] = +cols[7].longValues![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;
   }
diff --git a/ui/src/tracks/async_slices/frontend.ts b/ui/src/tracks/async_slices/frontend.ts
index 17d4d14..918f831 100644
--- a/ui/src/tracks/async_slices/frontend.ts
+++ b/ui/src/tracks/async_slices/frontend.ts
@@ -17,10 +17,10 @@
 import {trackRegistry} from '../../frontend/track_registry';
 import {ChromeSliceTrack} from '../chrome_slices/frontend';
 
-import {ASYNC_SLICE_TRACK_KIND} from './common';
+import {SLICE_TRACK_KIND} from './common';
 
 export class AsyncSliceTrack extends ChromeSliceTrack {
-  static readonly kind = ASYNC_SLICE_TRACK_KIND;
+  static readonly kind = SLICE_TRACK_KIND;
   static create(trackState: TrackState): Track {
     return new AsyncSliceTrack(trackState);
   }
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index 41fc2f8..0d476bc 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -30,7 +30,14 @@
   ends: Float64Array;
   depths: Uint16Array;
   titles: Uint16Array;  // Index into strings.
-  colors?: Uint16Array;  // Index into strings.
-  isInstant: Uint16Array;
-  isIncomplete: Uint16Array;
-}
+
+  // Start offset into into summary columns or -1 if not summarised.
+  summarizedOffset: Int16Array;
+  // Number of summary data points for this slice.
+  summarizedSize: Uint16Array;
+
+  // These arrays are length S where S is number of summarized slices * the
+  // items in each slice.
+  summaryNameId: Uint16Array;
+  summaryPercent: Float64Array;
+}
\ No newline at end of file
diff --git a/ui/src/tracks/chrome_slices/controller.ts b/ui/src/tracks/chrome_slices/controller.ts
index 2f29388..40be82e 100644
--- a/ui/src/tracks/chrome_slices/controller.ts
+++ b/ui/src/tracks/chrome_slices/controller.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
 import {
   TrackController,
   trackControllerRegistry,
@@ -21,106 +21,165 @@
 
 import {Config, Data, SLICE_TRACK_KIND} from './common';
 
-
 class ChromeSliceTrackController extends TrackController<Config, Data> {
   static readonly kind = SLICE_TRACK_KIND;
-  private maxDurNs = 0;
+  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);
 
-    const pxSize = this.pxSize();
+    if (!this.setup) {
+      await this.query(
+          `create virtual table ${this.tableName('window')} using window;`);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
-    const tableName = this.namespaceTable('slice');
+      await this.query(`create view ${this.tableName('small')} as
+        select ts, dur, depth, name, id as slice_id
+        from ${this.namespaceTable('slice')}
+        where track_id = ${this.config.trackId}
+        and dur < ${minNs}
+        order by ts;`);
 
-    if (this.maxDurNs === 0) {
-      const query = `
-          SELECT max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
-          FROM ${tableName} WHERE track_id = ${this.config.trackId}`;
-      const rawResult = await this.query(query);
-      if (slowlyCountRows(rawResult) === 1) {
-        this.maxDurNs = rawResult.columns[0].longValues![0];
-      }
+      await this.query(`create virtual table ${this.tableName('span')} using
+      span_join(${this.tableName('small')} PARTITIONED depth,
+      ${this.tableName('window')});`);
+
+      this.setup = true;
     }
 
-    const query = `
-      SELECT
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        ts,
-        max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)),
-        depth,
-        id as slice_id,
-        name,
-        dur = 0 as is_instant,
-        dur = -1 as is_incomplete
-      FROM ${tableName}
-      WHERE track_id = ${this.config.trackId} AND
-        ts >= (${startNs - this.maxDurNs}) AND
-        ts <= ${endNs}
-      GROUP BY depth, tsq`;
-    const rawResult = await this.query(query);
+    const windowDurNs = Math.max(1, endNs - startNs);
 
-    const numRows = slowlyCountRows(rawResult);
-    const slices: Data = {
+    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, id as slice_id
+      from ${this.namespaceTable('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, id as slice_id, 1.0 as percent,
+      -1 as grouping
+      from ${this.namespaceTable('slice')}
+      where track_id = ${this.config.trackId}
+      and ts >= ${startNs} - dur
+      and ts <= ${endNs}
+      and dur >= ${minNs}
+      order by ts `);
+
+    await this.query(`create view ${this.tableName('summary')} as select
+      min(min(ts)) over (partition by depth, quantum_ts) as ts,
+      sum(sum(dur)) over (partition by depth, quantum_ts) as dur,
+      depth,
+      name,
+      slice_id,
+      (sum(dur) * 1.0)/(sum(sum(dur)) over
+      (partition by depth,quantum_ts)) as percent,
+      quantum_ts as grouping
+      from ${this.tableName('span')}
+      group by depth, quantum_ts, name
+      order by ts;`);
+
+    // Since there are more rows than slices we will output, check the number of
+    // distinct groupings to find the number of slices.
+    const totalSlicesQuery = `select (
+      (select count(1) from ${this.tableName('big')}) +
+      (select count(1) from (select distinct grouping, depth
+      from ${this.tableName('summary')})))`;
+    const totalSlices = (await this.engine.queryOneRow(totalSlicesQuery))[0];
+
+    const totalSummarizedQuery =
+        `select count(1) from ${this.tableName('summary')}`;
+    const totalSummarized =
+        (await this.engine.queryOneRow(totalSummarizedQuery))[0];
+
+    const query = `select * from ${this.tableName('summary')} UNION
+      select * from ${this.tableName('big')}
+      order by ts, depth, percent desc limit ${LIMIT}`;
+    const result = await this.query(query);
+
+    const numRows = +result.numRecords;
+
+    const data: Data = {
       start,
       end,
       resolution,
-      length: numRows,
+      length: totalSlices,
       strings: [],
-      sliceIds: new Float64Array(numRows),
-      starts: new Float64Array(numRows),
-      ends: new Float64Array(numRows),
-      depths: new Uint16Array(numRows),
-      titles: new Uint16Array(numRows),
-      isInstant: new Uint16Array(numRows),
-      isIncomplete: new Uint16Array(numRows),
+      sliceIds: new Float64Array(totalSlices),
+      starts: new Float64Array(totalSlices),
+      ends: new Float64Array(totalSlices),
+      depths: new Uint16Array(totalSlices),
+      titles: new Uint16Array(totalSlices),
+      summarizedOffset: new Int16Array(totalSlices).fill(-1),
+      summarizedSize: new Uint16Array(totalSlices),
+      summaryNameId: new Uint16Array(totalSummarized),
+      summaryPercent: new Float64Array(totalSummarized)
     };
 
     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);
+      idx = data.strings.length;
+      data.strings.push(str);
       stringIndexes.set(str, idx);
       return idx;
     }
 
-    const cols = rawResult.columns;
+    let outIndex = 0;
+    let summaryIndex = 0;
+    const internedVarious = internString('Various slices');
     for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-      const isInstant = +cols[6].longValues![row];
-      const isIncomplete = +cols[7].longValues![row];
+      const cols = result.columns;
+      const start = +cols[0].longValues![row];
+      const dur = +cols[1].longValues![row];
+      const depth = +cols[2].longValues![row];
+      const name = cols[3].stringValues![row];
+      const percent = +(cols[5].doubleValues![row].toFixed(2));
+      const grouping = +cols[6].longValues![row];
 
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      if (!isInstant && startNsQ === endNsQ) {
-        throw new Error(
-            'Expected startNsQ and endNsQ to differ (' +
-            `startNsQ: ${startNsQ}, startNs: ${startNs},` +
-            ` endNsQ: ${endNsQ}, durNs: ${durNs},` +
-            ` endNs: ${endNs}, bucketNs: ${bucketNs})`);
+      // If it is a summarized slice, store the slice percentage breakdown.
+      if (percent !== 1) {
+        if (data.summarizedOffset[outIndex] === -1) {
+          data.summarizedOffset[outIndex] = summaryIndex;
+        }
+        data.summarizedSize[outIndex] = data.summarizedSize[outIndex] + 1;
+        data.summaryNameId[summaryIndex] = internString(name);
+        data.summaryPercent[summaryIndex] = percent;
+        summaryIndex++;
       }
 
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.depths[row] = +cols[3].longValues![row];
-      slices.sliceIds[row] = +cols[4].longValues![row];
-      slices.titles[row] = internString(cols[5].stringValues![row]);
-      slices.isInstant[row] = isInstant;
-      slices.isIncomplete[row] = isIncomplete;
+      const nextGrouping =
+          row + 1 < numRows ? +cols[6].longValues![row + 1] : -1;
+      const nextDepth = row + 1 < numRows ? +cols[2].longValues![row + 1] : -1;
+      // If the next grouping or next depth is different then we have reached
+      // the end of this slice.
+      if (grouping === -1 || grouping !== nextGrouping || depth !== nextDepth) {
+        const numSummarized = data.summarizedSize[outIndex];
+        data.starts[outIndex] = fromNs(start);
+        data.ends[outIndex] = fromNs(start + dur);
+        data.titles[outIndex] =
+            numSummarized > 0 ? internedVarious : internString(name);
+        data.depths[outIndex] = depth;
+        data.sliceIds[outIndex] = +cols[4].longValues![row];
+        outIndex++;
+      }
     }
-    return slices;
+    return data;
   }
+
 }
 
 
diff --git a/ui/src/tracks/chrome_slices/frontend.ts b/ui/src/tracks/chrome_slices/frontend.ts
index 403f01b..46bdf10 100644
--- a/ui/src/tracks/chrome_slices/frontend.ts
+++ b/ui/src/tracks/chrome_slices/frontend.ts
@@ -12,27 +12,29 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {hsluvToHex} from 'hsluv';
-
 import {Actions} from '../../common/actions';
 import {cropText, drawIncompleteSlice} from '../../common/canvas_utils';
-import {hslForSlice} from '../../common/colorizer';
-import {TRACE_MARGIN_TIME_S} from '../../common/constants';
 import {TrackState} from '../../common/state';
+import {toNs} from '../../common/time';
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
-import {SliceRect, Track} from '../../frontend/track';
+import {Track} from '../../frontend/track';
 import {trackRegistry} from '../../frontend/track_registry';
 
 import {Config, Data, SLICE_TRACK_KIND} from './common';
 
 const SLICE_HEIGHT = 18;
 const TRACK_PADDING = 4;
-const CHEVRON_WIDTH_PX = 10;
-const HALF_CHEVRON_WIDTH_PX = CHEVRON_WIDTH_PX / 2;
-const INNER_CHEVRON_OFFSET = -3;
-const INNER_CHEVRON_SCALE =
-    (SLICE_HEIGHT - 2 * INNER_CHEVRON_OFFSET) / SLICE_HEIGHT;
+const INCOMPLETE_SLICE_TIME_S = 0.00003;
+
+function 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;
+}
 
 export class ChromeSliceTrack extends Track<Config, Data> {
   static readonly kind: string = SLICE_TRACK_KIND;
@@ -70,6 +72,7 @@
 
     // measuretext is expensive so we only use it once.
     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.
@@ -81,157 +84,127 @@
       const depth = data.depths[i];
       const titleId = data.titles[i];
       const sliceId = data.sliceIds[i];
-      const isInstant = data.isInstant[i];
-      const isIncomplete = data.isIncomplete[i];
       const title = data.strings[titleId];
-      const colorOverride = data.colors && data.strings[data.colors[i]];
-      if (isIncomplete) {  // incomplete slice
-        tEnd = visibleWindowTime.end;
+      const summarizedOffset =
+          data.summarizedOffset ? data.summarizedOffset[i] : -1;
+      let incompleteSlice = false;
+
+      if (toNs(tEnd) - toNs(tStart) === -1) {  // incomplete slice
+        incompleteSlice = true;
+        tEnd = tStart + INCOMPLETE_SLICE_TIME_S;
       }
 
-      const rect = this.getSliceRect(tStart, tEnd, depth);
-      if (!rect || !rect.visible) {
+      if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
         continue;
       }
 
-      const currentSelection = globals.state.currentSelection;
-      const isSelected = currentSelection &&
-          currentSelection.kind === 'CHROME_SLICE' &&
-          currentSelection.id !== undefined && currentSelection.id === sliceId;
-
+      const rectXStart = Math.max(timeScale.timeToPx(tStart), 0);
+      let rectXEnd = Math.min(timeScale.timeToPx(tEnd), pxEnd);
+      let rectWidth = rectXEnd - rectXStart;
+      // All slices should be at least 1px.
+      if (rectWidth < 1) {
+        rectWidth = 1;
+        rectXEnd = rectXStart + 1;
+      }
+      const rectYStart = TRACK_PADDING + depth * SLICE_HEIGHT;
       const name = title.replace(/( )?\d+/g, '');
-      const highlighted = titleId === this.hoveredTitleId ||
-          globals.frontendLocalState.highlightedSliceId === sliceId;
-
-      const [hue, saturation, lightness] =
-          hslForSlice(name, highlighted || isSelected);
-
-      let color: string;
-      if (colorOverride === undefined) {
-        color = hsluvToHex([hue, saturation, lightness]);
+      const hue = hash(name);
+      const saturation = 50;
+      const hovered = titleId === this.hoveredTitleId;
+      const color = `hsl(${hue}, ${saturation}%, ${hovered ? 30 : 65}%)`;
+      if (summarizedOffset !== -1) {
+        const summarizedSize = data.summarizedSize[i];
+        const nameHues =
+            (data.summaryNameId.slice(
+                 summarizedOffset, summarizedOffset + summarizedSize))
+                .map(id => hash(data.strings[id]));
+        const percents = data.summaryPercent.slice(
+            summarizedOffset, summarizedOffset + summarizedSize);
+        colorSummarizedSlice(nameHues, percents, rectXStart, rectXEnd, hovered);
       } else {
-        color = colorOverride;
+        ctx.fillStyle = color;
       }
-      ctx.fillStyle = color;
-
-      // We draw instant events as upward facing chevrons starting at A:
-      //     A
-      //    ###
-      //   ##C##
-      //  ##   ##
-      // D       B
-      // Then B, C, D and back to A:
-      if (isInstant) {
-        if (isSelected) {
-          drawRectOnSelected = () => {
-            ctx.save();
-            ctx.translate(rect.left, rect.top);
-
-            // Draw outer chevron as dark border
-            ctx.save();
-            ctx.translate(0, INNER_CHEVRON_OFFSET);
-            ctx.scale(INNER_CHEVRON_SCALE, INNER_CHEVRON_SCALE);
-            ctx.fillStyle = hsluvToHex([hue, 100, 10]);
-
-            this.drawChevron(ctx);
-            ctx.restore();
-
-            // Draw inner chevron as interior
-            ctx.fillStyle = color;
-            this.drawChevron(ctx);
-
-            ctx.restore();
-          };
-        } else {
-          ctx.save();
-          ctx.translate(rect.left, rect.top);
-          this.drawChevron(ctx);
-          ctx.restore();
-        }
-        continue;
-      }
-      if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
+      if (incompleteSlice && rectWidth > SLICE_HEIGHT / 4) {
         drawIncompleteSlice(
-            ctx, rect.left, rect.top, rect.width, SLICE_HEIGHT, color);
+            ctx, rectXStart, rectYStart, rectWidth, SLICE_HEIGHT, color);
       } else {
-        ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
+        ctx.fillRect(rectXStart, rectYStart, rectWidth, SLICE_HEIGHT);
       }
+
       // Selected case
-      if (isSelected) {
+      const currentSelection = globals.state.currentSelection;
+      if (currentSelection && currentSelection.kind === 'CHROME_SLICE' &&
+          currentSelection.id !== undefined &&
+          currentSelection.id === sliceId) {
         drawRectOnSelected = () => {
-          ctx.strokeStyle = hsluvToHex([hue, 100, 10]);
+          ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 30%)`;
           ctx.beginPath();
           ctx.lineWidth = 3;
           ctx.strokeRect(
-              rect.left, rect.top - 1.5, rect.width, SLICE_HEIGHT + 3);
+              rectXStart, rectYStart - 1.5, rectWidth, SLICE_HEIGHT + 3);
           ctx.closePath();
         };
       }
 
-      ctx.fillStyle = lightness > 65 ? '#404040' : 'white';
-      const displayText = cropText(title, charWidth, rect.width);
-      const rectXCenter = rect.left + rect.width / 2;
+      ctx.fillStyle = 'white';
+      const displayText = cropText(title, charWidth, rectWidth);
+      const rectXCenter = rectXStart + rectWidth / 2;
       ctx.textBaseline = "middle";
-      ctx.fillText(displayText, rectXCenter, rect.top + SLICE_HEIGHT / 2);
+      ctx.fillText(displayText, rectXCenter, rectYStart + SLICE_HEIGHT / 2);
     }
     drawRectOnSelected();
-  }
 
-  drawChevron(ctx: CanvasRenderingContext2D) {
-    // Draw a chevron at a fixed location and size. Should be used with
-    // ctx.translate and ctx.scale to alter location and size.
-    ctx.beginPath();
-    ctx.moveTo(0, 0);
-    ctx.lineTo(HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
-    ctx.lineTo(0, SLICE_HEIGHT - HALF_CHEVRON_WIDTH_PX);
-    ctx.lineTo(-HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
-    ctx.lineTo(0, 0);
-    ctx.fill();
+    // Make a gradient ordered most common to least common slices within the
+    // summarized slice.
+    function colorSummarizedSlice(
+        nameHues: Uint16Array,
+        percents: Float64Array,
+        rectStart: number,
+        rectEnd: number,
+        hovered: boolean) {
+      const gradient = ctx.createLinearGradient(
+          rectStart, SLICE_HEIGHT, rectEnd, SLICE_HEIGHT);
+      let colorStop = 0;
+      for (let i = 0; i < nameHues.length; i++) {
+        const colorString = `hsl(${nameHues[i]}, 50%, ${hovered ? 30 : 65}%)`;
+        colorStop = Math.max(0, Math.min(1, colorStop + percents[i]));
+        gradient.addColorStop(colorStop, colorString);
+      }
+      ctx.fillStyle = gradient;
+    }
   }
 
   getSliceIndex({x, y}: {x: number, y: number}): number|void {
     const data = this.data();
+    this.hoveredTitleId = -1;
     if (data === undefined) return;
     const {timeScale} = globals.frontendLocalState;
     if (y < TRACK_PADDING) return;
-    const instantWidthTime = timeScale.deltaPxToDuration(HALF_CHEVRON_WIDTH_PX);
     const t = timeScale.pxToTime(x);
-    const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);
+    const depth = Math.floor(y / SLICE_HEIGHT);
     for (let i = 0; i < data.starts.length; i++) {
-      if (depth !== data.depths[i]) {
-        continue;
-      }
       const tStart = data.starts[i];
-      if (data.isInstant[i]) {
-        if (Math.abs(tStart - t) < instantWidthTime) {
-          return i;
-        }
-      } else {
-        let tEnd = data.ends[i];
-        if (data.isIncomplete[i]) {
-          tEnd = globals.frontendLocalState.visibleWindowTime.end;
-        }
-        if (tStart <= t && t <= tEnd) {
-          return i;
-        }
+      let tEnd = data.ends[i];
+      if (toNs(tEnd) - toNs(tStart) === -1) {
+        tEnd = tStart + INCOMPLETE_SLICE_TIME_S;
+      }
+      if (tStart <= t && t <= tEnd && depth === data.depths[i]) {
+        return i;
       }
     }
   }
 
   onMouseMove({x, y}: {x: number, y: number}) {
-    this.hoveredTitleId = -1;
-    globals.frontendLocalState.setHighlightedSliceId(-1);
     const sliceIndex = this.getSliceIndex({x, y});
     if (sliceIndex === undefined) return;
     const data = this.data();
     if (data === undefined) return;
-    this.hoveredTitleId = data.titles[sliceIndex];
-    globals.frontendLocalState.setHighlightedSliceId(data.sliceIds[sliceIndex]);
+    const titleId = data.titles[sliceIndex];
+    this.hoveredTitleId = titleId;
   }
 
   onMouseOut() {
     this.hoveredTitleId = -1;
-    globals.frontendLocalState.setHighlightedSliceId(-1);
   }
 
   onMouseClick({x, y}: {x: number, y: number}): boolean {
@@ -254,22 +227,6 @@
   getHeight() {
     return SLICE_HEIGHT * (this.config.maxDepth + 1) + 2 * TRACK_PADDING;
   }
-
-  getSliceRect(tStart: number, tEnd: number, depth: number): SliceRect
-      |undefined {
-    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
-    const pxEnd = timeScale.timeToPx(visibleWindowTime.end);
-    const left = Math.max(timeScale.timeToPx(tStart), -TRACE_MARGIN_TIME_S);
-    const right = Math.min(timeScale.timeToPx(tEnd), pxEnd);
-    return {
-      left,
-      width: Math.max(right - left, 1),
-      top: TRACK_PADDING + depth * SLICE_HEIGHT,
-      height: SLICE_HEIGHT,
-      visible:
-          !(tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end)
-    };
-  }
 }
 
 trackRegistry.register(ChromeSliceTrack);
diff --git a/ui/src/tracks/counter/common.ts b/ui/src/tracks/counter/common.ts
index 876eaf0..2eb3863 100644
--- a/ui/src/tracks/counter/common.ts
+++ b/ui/src/tracks/counter/common.ts
@@ -16,19 +16,13 @@
 
 export const COUNTER_TRACK_KIND = 'CounterTrack';
 
-export type CounterScaleOptions = 'ZERO_BASED'|'MIN_MAX'|'DELTA_FROM_PREVIOUS';
-
 export interface Data extends TrackData {
+  isQuantized: boolean;
   maximumValue: number;
   minimumValue: number;
-  maximumDelta: number;
-  minimumDelta: number;
   timestamps: Float64Array;
-  lastIds: Float64Array;
-  minValues: Float64Array;
-  maxValues: Float64Array;
-  lastValues: Float64Array;
-  totalDeltas: Float64Array;
+  values: Float64Array;
+  ids: Float64Array;
 }
 
 export interface Config {
@@ -39,5 +33,5 @@
   endTs?: number;
   namespace: string;
   trackId: number;
-  scale?: CounterScaleOptions;
+  scale?: 'DEFAULT'|'RELATIVE';
 }
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 22dffe2..deb2d46 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -12,8 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {iter, NUM, slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
+
 import {
   TrackController,
   trackControllerRegistry
@@ -30,21 +31,12 @@
   private setup = false;
   private maximumValueSeen = 0;
   private minimumValueSeen = 0;
-  private maximumDeltaSeen = 0;
-  private minimumDeltaSeen = 0;
-  private maxDurNs = 0;
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
     const startNs = toNs(start);
     const endNs = toNs(end);
 
-    const pxSize = this.pxSize();
-
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
-
     if (!this.setup) {
       if (this.config.namespace === undefined) {
         await this.query(`
@@ -53,8 +45,7 @@
             id,
             ts,
             dur,
-            value,
-            delta
+            value
           from experimental_counter_dur
           where track_id = ${this.config.trackId};
         `);
@@ -65,89 +56,101 @@
             id,
             ts,
             lead(ts, 1, ts) over (order by ts) - ts as dur,
-            lead(value, 1, value) over (order by ts) - value as delta,
             value
           from ${this.namespaceTable('counter')}
           where track_id = ${this.config.trackId};
         `);
       }
 
-      const maxDurResult = await this.query(`
-          select
-            max(
-              iif(dur != -1, dur, (select end_ts from trace_bounds) - ts)
-            )
-          from ${this.tableName('counter_view')}
-      `);
-      if (slowlyCountRows(maxDurResult) === 1) {
-        this.maxDurNs = maxDurResult.columns[0].longValues![0];
-      }
-
       const result = await this.query(`
-        select
-          max(value) as maxValue,
-          min(value) as minValue,
-          max(delta) as maxDelta,
-          min(delta) as minDelta
+        select max(value), min(value)
         from ${this.tableName('counter_view')}`);
       this.maximumValueSeen = +result.columns[0].doubleValues![0];
       this.minimumValueSeen = +result.columns[1].doubleValues![0];
-      this.maximumDeltaSeen = +result.columns[2].doubleValues![0];
-      this.minimumDeltaSeen = +result.columns[3].doubleValues![0];
+      await this.query(
+          `create virtual table ${this.tableName('window')} using window;`);
 
+      await this.query(`create virtual table ${this.tableName('span')} using
+        span_join(${this.tableName('counter_view')},
+        ${this.tableName('window')});`);
       this.setup = true;
     }
 
-    const rawResult = await this.query(`
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        min(value) as minValue,
-        max(value) as maxValue,
-        sum(delta) as totalDelta,
-        value_at_max_ts(ts, id) as lastId,
-        value_at_max_ts(ts, value) as lastValue
+    const result = await this.engine.queryOneRow(`
+      select count(*)
       from ${this.tableName('counter_view')}
-      where ts >= ${startNs - this.maxDurNs} and ts <= ${endNs}
-      group by tsq
-      order by tsq
-    `);
+      where ts <= ${endNs} and ${startNs} <= ts + dur`);
 
-    const numRows = slowlyCountRows(rawResult);
+    // Only quantize if we have too much data to draw.
+    const isQuantized = result[0] > LIMIT;
+    // |resolution| is in s/px we want # ns for 1px window:
+    const bucketSizeNs = Math.round(resolution * 1e9);
+    let windowStartNs = startNs;
+    if (isQuantized) {
+      windowStartNs = Math.floor(windowStartNs / bucketSizeNs) * bucketSizeNs;
+    }
+    const windowDurNs = Math.max(1, endNs - windowStartNs);
+
+    this.query(`update ${this.tableName('window')} set
+    window_start=${windowStartNs},
+    window_dur=${windowDurNs},
+    quantum=${isQuantized ? bucketSizeNs : 0}`);
+
+    let query = `select min(ts) as ts,
+      max(value) as value,
+      -1 as id
+      from ${this.tableName('span')}
+      group by quantum_ts limit ${LIMIT};`;
+
+    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, id
+        from ${this.tableName('counter_view')}
+        where ts <= ${startNs}
+        order by ts desc
+        limit 1
+      )
+      union
+      select *
+      from (
+        select ts, value, id
+        from ${this.tableName('counter_view')}
+        where ts <= ${endNs} and ${startNs} <= ts + dur
+        limit ${LIMIT}
+      );`;
+    }
+
+    const rawResult = await this.query(query);
+
+    const numRows = +rawResult.numRecords;
 
     const data: Data = {
       start,
       end,
       length: numRows,
+      isQuantized,
       maximumValue: this.maximumValue(),
       minimumValue: this.minimumValue(),
-      maximumDelta: this.maximumDeltaSeen,
-      minimumDelta: this.minimumDeltaSeen,
       resolution,
       timestamps: new Float64Array(numRows),
-      lastIds: new Float64Array(numRows),
-      minValues: new Float64Array(numRows),
-      maxValues: new Float64Array(numRows),
-      lastValues: new Float64Array(numRows),
-      totalDeltas: new Float64Array(numRows),
+      values: new Float64Array(numRows),
+      ids: new Float64Array(numRows),
     };
 
-    const it = iter(
-        {
-          'tsq': NUM,
-          'lastId': NUM,
-          'minValue': NUM,
-          'maxValue': NUM,
-          'lastValue': NUM,
-          'totalDelta': NUM,
-        },
-        rawResult);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      data.timestamps[i] = fromNs(it.row.tsq);
-      data.lastIds[i] = it.row.lastId;
-      data.minValues[i] = it.row.minValue;
-      data.maxValues[i] = it.row.maxValue;
-      data.lastValues[i] = it.row.lastValue;
-      data.totalDeltas[i] = it.row.totalDelta;
+    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;
@@ -168,6 +171,7 @@
       return this.config.minimumValue;
     }
   }
+
 }
 
 trackControllerRegistry.register(CounterTrackController);
diff --git a/ui/src/tracks/counter/frontend.ts b/ui/src/tracks/counter/frontend.ts
index 186b1e1..d602f41 100644
--- a/ui/src/tracks/counter/frontend.ts
+++ b/ui/src/tracks/counter/frontend.ts
@@ -28,7 +28,6 @@
 import {
   Config,
   COUNTER_TRACK_KIND,
-  CounterScaleOptions,
   Data,
 } from './common';
 
@@ -36,49 +35,6 @@
 const MARGIN_TOP = 3.5;
 const RECT_HEIGHT = 24.5;
 
-interface CounterScaleAttribute {
-  follower: CounterScaleOptions;
-  tooltip: string;
-  icon: string;
-}
-
-function scaleTooltip(scale?: CounterScaleOptions): string {
-  const description: CounterScaleAttribute = getCounterScaleAttribute(scale);
-  const source: string = description.tooltip;
-  const destination: string =
-      getCounterScaleAttribute(description.follower).tooltip;
-  return `Toggle scale from ${source} to ${destination}`;
-}
-
-function scaleIcon(scale?: CounterScaleOptions): string {
-  return getCounterScaleAttribute(scale).icon;
-}
-
-function nextScale(scale?: CounterScaleOptions): CounterScaleOptions {
-  return getCounterScaleAttribute(scale).follower;
-}
-
-function getCounterScaleAttribute(scale?: CounterScaleOptions):
-    CounterScaleAttribute {
-  switch (scale) {
-    case 'MIN_MAX':
-      return {
-        follower: 'DELTA_FROM_PREVIOUS',
-        tooltip: 'min/max',
-        icon: 'show_chart'
-      };
-    case 'DELTA_FROM_PREVIOUS':
-      return {follower: 'ZERO_BASED', tooltip: 'delta', icon: 'bar_chart'};
-    case 'ZERO_BASED':
-    default:
-      return {
-        follower: 'MIN_MAX',
-        tooltip: 'zero based',
-        icon: 'waterfall_chart'
-      };
-  }
-}
-
 class CounterTrack extends Track<Config, Data> {
   static readonly kind = COUNTER_TRACK_KIND;
   static create(trackState: TrackState): CounterTrack {
@@ -102,14 +58,19 @@
     const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
     buttons.push(m(TrackButton, {
       action: () => {
-        this.config.scale = nextScale(this.config.scale);
+        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: scaleIcon(this.config.scale),
-      tooltip: scaleTooltip(this.config.scale),
-      showButton: !!this.config.scale && this.config.scale !== 'ZERO_BASED',
+      i: 'show_chart',
+      tooltip: (this.config.scale === 'RELATIVE') ? 'Use zero-based scale' :
+                                                    'Use relative scale',
+      showButton: this.config.scale === 'RELATIVE',
     }));
     return buttons;
   }
@@ -119,38 +80,20 @@
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
-    // Can't possibly draw anything.
-    if (data === undefined || data.timestamps.length === 0) {
-      return;
-    }
+    if (data === undefined) return;  // Can't possibly draw anything.
 
-    assertTrue(data.timestamps.length === data.minValues.length);
-    assertTrue(data.timestamps.length === data.maxValues.length);
-    assertTrue(data.timestamps.length === data.lastValues.length);
-    assertTrue(data.timestamps.length === data.totalDeltas.length);
-
-    const scale: CounterScaleOptions = this.config.scale || 'ZERO_BASED';
-
-    let minValues = data.minValues;
-    let maxValues = data.maxValues;
-    let lastValues = data.lastValues;
-    let maximumValue = data.maximumValue;
-    let minimumValue = data.minimumValue;
-    if (scale === 'DELTA_FROM_PREVIOUS') {
-      lastValues = data.totalDeltas;
-      minValues = data.totalDeltas;
-      maxValues = data.totalDeltas;
-      maximumValue = data.maximumDelta;
-      minimumValue = data.minimumDelta;
-    }
+    assertTrue(data.timestamps.length === data.values.length);
 
     const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
-    const zeroY = MARGIN_TOP + RECT_HEIGHT / (minimumValue < 0 ? 2 : 1);
+    const zeroY = MARGIN_TOP + RECT_HEIGHT / (data.minimumValue < 0 ? 2 : 1);
+
+    let lastX = Math.floor(timeScale.timeToPx(data.timestamps[0]));
+    let lastY = zeroY;
 
     // Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
-    const maxValue = Math.max(maximumValue, 0);
+    const maxValue = Math.max(data.maximumValue, 0);
 
-    let yMax = Math.max(Math.abs(minimumValue), maxValue);
+    let yMax = Math.max(Math.abs(data.minimumValue), maxValue);
     const kUnits = ['', 'K', 'M', 'G', 'T', 'E'];
     const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
     const pow10 = Math.pow(10, exp);
@@ -159,17 +102,14 @@
     const unitGroup = Math.floor(exp / 3);
     let yMin = 0;
     let yLabel = '';
-    if (scale === 'MIN_MAX') {
-      yRange = maximumValue - minimumValue;
-      yMin = minimumValue;
+    if (this.config.scale === 'RELATIVE') {
+      yRange = data.maximumValue - data.minimumValue;
+      yMin = data.minimumValue;
       yLabel = 'min - max';
     } else {
-      yRange = minimumValue < 0 ? yMax * 2 : yMax;
-      yMin = minimumValue < 0 ? -yMax : 0;
+      yRange = data.minimumValue < 0 ? yMax * 2 : yMax;
+      yMin = data.minimumValue < 0 ? -yMax : 0;
       yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
-      if (scale === 'DELTA_FROM_PREVIOUS') {
-        yLabel += '\u0394';
-      }
     }
 
     // There are 360deg of hue. We want a scale that starts at green with
@@ -185,36 +125,20 @@
 
     ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
     ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
-
-    const calculateX = (ts: number) => {
-      return Math.floor(timeScale.timeToPx(ts));
-    };
-    const calculateY = (value: number) => {
-      return MARGIN_TOP + RECT_HEIGHT -
-          Math.round(((value - yMin) / yRange) * RECT_HEIGHT);
-    };
-
     ctx.beginPath();
-    ctx.moveTo(calculateX(data.timestamps[0]), zeroY);
-    let lastDrawnY = zeroY;
-    for (let i = 0; i < data.timestamps.length; i++) {
-      const x = calculateX(data.timestamps[i]);
-      const minY = calculateY(minValues[i]);
-      const maxY = calculateY(maxValues[i]);
-      const lastY = calculateY(lastValues[i]);
+    ctx.moveTo(lastX, lastY);
+    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);
+      if (nextY === lastY) continue;
 
-      ctx.lineTo(x, lastDrawnY);
-      if (minY === maxY) {
-        assertTrue(lastY === minY);
-        ctx.lineTo(x, lastY);
-      } else {
-        ctx.lineTo(x, minY);
-        ctx.lineTo(x, maxY);
-        ctx.lineTo(x, lastY);
-      }
-      lastDrawnY = lastY;
+      lastX = Math.floor(timeScale.timeToPx(startTime));
+      ctx.lineTo(lastX, lastY);
+      ctx.lineTo(lastX, nextY);
+      lastY = nextY;
     }
-    ctx.lineTo(endPx, lastDrawnY);
+    ctx.lineTo(endPx, lastY);
     ctx.lineTo(endPx, zeroY);
     ctx.closePath();
     ctx.fill();
@@ -234,7 +158,7 @@
 
     if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
       // TODO(hjd): Add units.
-      let text = scale === 'DELTA_FROM_PREVIOUS' ? 'delta: ' : 'value: ';
+      let text = (data.isQuantized) ? 'max value: ' : 'value: ';
       text += `${this.hoveredValue.toLocaleString()}`;
 
       ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
@@ -244,7 +168,7 @@
       const xEnd = this.hoveredTsEnd === undefined ?
           endPx :
           Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
-      const y = MARGIN_TOP + RECT_HEIGHT -
+      const y = zeroY -
           Math.round(((this.hoveredValue - yMin) / yRange) * RECT_HEIGHT);
 
       // Highlight line.
@@ -304,13 +228,10 @@
     const {timeScale} = globals.frontendLocalState;
     const time = timeScale.pxToTime(x);
 
-    const values = this.config.scale === 'DELTA_FROM_PREVIOUS' ?
-        data.totalDeltas :
-        data.lastValues;
     const [left, right] = searchSegment(data.timestamps, time);
     this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
     this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
-    this.hoveredValue = left === -1 ? undefined : values[left];
+    this.hoveredValue = left === -1 ? undefined : data.values[left];
   }
 
   onMouseOut() {
@@ -327,7 +248,7 @@
     if (left === -1) {
       return false;
     } else {
-      const counterId = data.lastIds[left];
+      const counterId = data.ids[left];
       if (counterId === -1) return true;
       globals.makeSelection(Actions.selectCounter({
         leftTs: toNs(data.timestamps[left]),
diff --git a/ui/src/tracks/cpu_freq/common.ts b/ui/src/tracks/cpu_freq/common.ts
index c21c47e..fff0c8f 100644
--- a/ui/src/tracks/cpu_freq/common.ts
+++ b/ui/src/tracks/cpu_freq/common.ts
@@ -18,13 +18,12 @@
 
 export interface Data extends TrackData {
   maximumValue: number;
-  maxTsEnd: number;
+  isQuantized: boolean;
 
-  timestamps: Float64Array;
-  minFreqKHz: Uint32Array;
-  maxFreqKHz: Uint32Array;
-  lastFreqKHz: Uint32Array;
-  lastIdleValues: Int8Array;
+  tsStarts: Float64Array;
+  tsEnds: Float64Array;
+  idles: Int8Array;
+  freqKHz: Uint32Array;
 }
 
 export interface Config {
diff --git a/ui/src/tracks/cpu_freq/controller.ts b/ui/src/tracks/cpu_freq/controller.ts
index 08ca0b5..9e001bb 100644
--- a/ui/src/tracks/cpu_freq/controller.ts
+++ b/ui/src/tracks/cpu_freq/controller.ts
@@ -12,10 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertTrue} from '../../base/logging';
-import {RawQueryResult} from '../../common/protos';
-import {iter, NUM, slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
+
 import {
   TrackController,
   trackControllerRegistry
@@ -29,210 +28,155 @@
 
 class CpuFreqTrackController extends TrackController<Config, Data> {
   static readonly kind = CPU_FREQ_TRACK_KIND;
-
-  private maxDurNs = 0;
-  private maxTsEndNs = 0;
+  private setup = false;
   private maximumValueSeen = 0;
-  private cachedBucketNs = Number.MAX_SAFE_INTEGER;
-
-  async onSetup() {
-    await this.createFreqIdleViews();
-
-    this.maximumValueSeen = await this.queryMaxFrequency();
-    this.maxDurNs = await this.queryMaxSourceDur();
-
-    const result = await this.query(`
-      select max(ts), dur, count(1)
-      from ${this.tableName('freq_idle')}
-    `);
-    this.maxTsEndNs =
-        result.columns[0].longValues![0] + result.columns[1].longValues![0];
-
-    const rowCount = result.columns[2].longValues![0];
-    const bucketNs = this.cachedBucketSizeNs(rowCount);
-    if (bucketNs === undefined) {
-      return;
-    }
-    await this.query(`
-      create table ${this.tableName('freq_idle_cached')} as
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cached_tsq,
-        min(freq_value) as min_freq,
-        max(freq_value) as max_freq,
-        value_at_max_ts(ts, freq_value) as last_freq,
-        value_at_max_ts(ts, idle_value) as last_idle_value
-      from ${this.tableName('freq_idle')}
-      group by cached_tsq
-      order by cached_tsq
-    `);
-    this.cachedBucketNs = bucketNs;
-  }
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    // The resolution should always be a power of two for the logic of this
-    // function to make sense.
-    const resolutionNs = toNs(resolution);
-    assertTrue(Math.log2(resolutionNs) % 1 === 0);
-
     const startNs = toNs(start);
     const endNs = toNs(end);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs =
-        Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+    if (!this.setup) {
+      const result = await this.query(`
+        select max(value)
+        from counter
+        where track_id = ${this.config.freqTrackId}`);
+      this.maximumValueSeen = +result.columns[0].doubleValues![0];
 
-    const freqResult = await this.queryData(startNs, endNs, bucketNs);
+      await this.query(
+        `create virtual table ${this.tableName('window')} using window;`);
 
-    const numRows = slowlyCountRows(freqResult);
+      await this.query(`create view ${this.tableName('freq')}
+          as select
+            ts,
+            dur,
+            value as freq_value
+          from experimental_counter_dur c
+          where track_id = ${this.config.freqTrackId};
+      `);
+
+      // If there is no idle track, just make the idle track a single row
+      // which spans the entire time range.
+      if (this.config.idleTrackId === undefined) {
+        await this.query(`create view ${this.tableName('idle')} as
+           select
+             0 as ts,
+             ${Number.MAX_SAFE_INTEGER} as dur,
+             -1 as idle_value;
+          `);
+      } else {
+        await this.query(`create view ${this.tableName('idle')}
+          as select
+            ts,
+            dur,
+            value as idle_value
+          from experimental_counter_dur c
+          where track_id = ${this.config.idleTrackId};
+        `);
+      }
+
+      await this.query(`create virtual table ${this.tableName('freq_idle')}
+              using span_join(${this.tableName('freq')},
+                              ${this.tableName('idle')});`);
+
+      await this.query(`create virtual table ${this.tableName('span_activity')}
+              using span_join(${this.tableName('freq_idle')},
+                              ${this.tableName('window')});`);
+
+      // TODO(taylori): Move the idle value processing to the TP.
+      await this.query(`create view ${this.tableName('activity')}
+      as select
+        ts,
+        dur,
+        quantum_ts,
+        case idle_value
+          when 4294967295 then -1
+          else idle_value
+        end as idle,
+        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, cast(idle as DOUBLE), 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,
+        case
+          when min(idle) = -1 then cast(-1 as DOUBLE)
+          else cast(0 as DOUBLE)
+        end as idle,
+        sum(weighted_freq)/sum(dur) as freq_avg,
+        quantum_ts
+        from (
+          select
+          ts,
+          dur,
+          quantum_ts,
+          freq*dur as weighted_freq,
+          idle
+          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(),
-      maxTsEnd: this.maxTsEndNs,
-      timestamps: new Float64Array(numRows),
-      minFreqKHz: new Uint32Array(numRows),
-      maxFreqKHz: new Uint32Array(numRows),
-      lastFreqKHz: new Uint32Array(numRows),
-      lastIdleValues: new Int8Array(numRows),
+      isQuantized,
+      tsStarts: new Float64Array(numRows),
+      tsEnds: new Float64Array(numRows),
+      idles: new Int8Array(numRows),
+      freqKHz: new Uint32Array(numRows),
     };
 
-    const it = iter(
-        {
-          'tsq': NUM,
-          'minFreq': NUM,
-          'maxFreq': NUM,
-          'lastFreq': NUM,
-          'lastIdleValue': NUM,
-        },
-        freqResult);
-    for (let i = 0; it.valid(); ++i, it.next()) {
-      data.timestamps[i] = fromNs(it.row.tsq);
-      data.minFreqKHz[i] = it.row.minFreq;
-      data.maxFreqKHz[i] = it.row.maxFreq;
-      data.lastFreqKHz[i] = it.row.lastFreq;
-      data.lastIdleValues[i] = it.row.lastIdleValue;
+    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.idles[row] = +cols[2].doubleValues![row];
+      data.freqKHz[row] = +cols[3].doubleValues![row];
     }
+
     return data;
   }
 
-  private async queryData(startNs: number, endNs: number, bucketNs: number):
-      Promise<RawQueryResult> {
-    const isCached = this.cachedBucketNs <= bucketNs;
-
-    if (isCached) {
-      return this.query(`
-        select
-          cached_tsq / ${bucketNs} * ${bucketNs} as tsq,
-          min(min_freq) as minFreq,
-          max(max_freq) as maxFreq,
-          value_at_max_ts(cached_tsq, last_freq) as lastFreq,
-          value_at_max_ts(cached_tsq, last_idle_value) as lastIdleValue
-        from ${this.tableName('freq_idle_cached')}
-        where
-          cached_tsq >= ${startNs - this.maxDurNs} and
-          cached_tsq <= ${endNs}
-        group by tsq
-        order by tsq
-      `);
-    }
-
-    const minTsFreq = await this.query(`
-      select ifnull(max(ts), 0) from ${this.tableName('freq')}
-      where ts < ${startNs}
-    `);
-    let minTs = minTsFreq.columns[0].longValues![0];
-    if (this.config.idleTrackId !== undefined) {
-      const minTsIdle = await this.query(`
-        select ifnull(max(ts), 0) from ${this.tableName('idle')}
-        where ts < ${startNs}
-      `);
-      minTs = Math.min(minTsIdle.columns[0].longValues![0], minTs);
-    }
-    const geqConstraint = this.config.idleTrackId === undefined ?
-        `ts >= ${minTs}` :
-        `source_geq(ts, ${minTs})`;
-    return this.query(`
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        min(freq_value) as minFreq,
-        max(freq_value) as maxFreq,
-        value_at_max_ts(ts, freq_value) as lastFreq,
-        value_at_max_ts(ts, idle_value) as lastIdleValue
-      from ${this.tableName('freq_idle')}
-      where
-        ${geqConstraint} and
-        ts <= ${endNs}
-      group by tsq
-      order by tsq
-    `);
-  }
-
-  private async queryMaxFrequency(): Promise<number> {
-    const result = await this.query(`
-      select max(freq_value)
-      from ${this.tableName('freq')}
-    `);
-    return result.columns[0].doubleValues![0];
-  }
-
-  private async queryMaxSourceDur(): Promise<number> {
-    const maxDurFreqResult =
-        await this.query(`select max(dur) from ${this.tableName('freq')}`);
-    const maxFreqDurNs = maxDurFreqResult.columns[0].longValues![0];
-    if (this.config.idleTrackId === undefined) {
-      return maxFreqDurNs;
-    }
-
-    const maxDurIdleResult =
-        await this.query(`select max(dur) from ${this.tableName('idle')}`);
-    return Math.max(maxFreqDurNs, maxDurIdleResult.columns[0].longValues![0]);
-  }
-
-  private async createFreqIdleViews() {
-    await this.query(`create view ${this.tableName('freq')} as
-      select
-        ts,
-        dur,
-        value as freq_value
-      from experimental_counter_dur c
-      where track_id = ${this.config.freqTrackId};
-    `);
-
-    if (this.config.idleTrackId === undefined) {
-      await this.query(`create view ${this.tableName('freq_idle')} as
-        select
-          ts,
-          dur,
-          -1 as idle_value,
-          freq_value
-        from ${this.tableName('freq')};
-      `);
-      return;
-    }
-
-    await this.query(`
-      create view ${this.tableName('idle')} as
-      select
-        ts,
-        dur,
-        iif(value = 4294967295, -1, cast(value as int)) as idle_value
-      from experimental_counter_dur c
-      where track_id = ${this.config.idleTrackId};
-    `);
-
-    await this.query(`
-      create virtual table ${this.tableName('freq_idle')}
-      using span_join(${this.tableName('freq')}, ${this.tableName('idle')});
-    `);
-  }
-
   private maximumValue() {
     return Math.max(this.config.maximumValue || 0, this.maximumValueSeen);
   }
+
 }
 
 
diff --git a/ui/src/tracks/cpu_freq/frontend.ts b/ui/src/tracks/cpu_freq/frontend.ts
index 4e5c9e4..77ba9b1 100644
--- a/ui/src/tracks/cpu_freq/frontend.ts
+++ b/ui/src/tracks/cpu_freq/frontend.ts
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {searchSegment} from '../../base/binary_search';
+import {search} from '../../base/binary_search';
 import {assertTrue} from '../../base/logging';
-import {hueForCpu} from '../../common/colorizer';
 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';
@@ -56,19 +56,18 @@
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
-    if (data === undefined || data.timestamps.length === 0) {
-      // Can't possibly draw anything.
-      return;
-    }
+    if (data === undefined) return;  // Can't possibly draw anything.
 
-    assertTrue(data.timestamps.length === data.lastFreqKHz.length);
-    assertTrue(data.timestamps.length === data.minFreqKHz.length);
-    assertTrue(data.timestamps.length === data.maxFreqKHz.length);
-    assertTrue(data.timestamps.length === data.lastIdleValues.length);
+    assertTrue(data.tsStarts.length === data.freqKHz.length);
+    assertTrue(data.freqKHz.length === data.idles.length);
 
-    const endPx = timeScale.timeToPx(visibleWindowTime.end);
+    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'];
@@ -88,47 +87,25 @@
     }
     ctx.fillStyle = `hsl(${hue}, ${saturation}%, 70%)`;
     ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 55%)`;
-
-    const calculateX = (timestamp: number) => {
-      return Math.floor(timeScale.timeToPx(timestamp));
-    };
-    const calculateY = (value: number) => {
-      return zeroY - Math.round((value / yMax) * RECT_HEIGHT);
-    };
-
-    const [rawStartIdx,] =
-      searchSegment(data.timestamps, visibleWindowTime.start);
-    const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
-
-    const [, rawEndIdx] = searchSegment(data.timestamps, visibleWindowTime.end);
-    const endIdx = rawEndIdx === -1 ? data.timestamps.length : rawEndIdx;
-
     ctx.beginPath();
-    ctx.moveTo(Math.max(calculateX(data.timestamps[startIdx]), 0), zeroY);
+    ctx.moveTo(lastX, lastY);
 
-    let lastDrawnY = zeroY;
-    for (let i = startIdx; i < endIdx; i++) {
-      const x = calculateX(data.timestamps[i]);
+    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;
 
-      const minY = calculateY(data.minFreqKHz[i]);
-      const maxY = calculateY(data.maxFreqKHz[i]);
-      const lastY = calculateY(data.lastFreqKHz[i]);
-
-      ctx.lineTo(x, lastDrawnY);
-      if (minY === maxY) {
-        assertTrue(lastY === minY);
-        ctx.lineTo(x, lastY);
-      } else {
-        ctx.lineTo(x, minY);
-        ctx.lineTo(x, maxY);
-        ctx.lineTo(x, lastY);
-      }
-      lastDrawnY = lastY;
+      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 finalX = Math.min(calculateX(data.maxTsEnd), endPx);
-    ctx.lineTo(finalX, lastDrawnY);
+    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();
@@ -137,31 +114,25 @@
 
     // Draw CPU idle rectangles that overlay the CPU freq graph.
     ctx.fillStyle = `rgba(240, 240, 240, 1)`;
+    const bottomY = MARGIN_TOP + RECT_HEIGHT;
 
-    for (let i = 0; i < data.lastIdleValues.length; i++) {
-      if (data.lastIdleValues[i] < 0) {
-        continue;
+    for (let i = 0; i < data.freqKHz.length; i++) {
+      if (data.idles[i] >= 0) {
+        const value = data.freqKHz[i];
+        const firstX = Math.floor(timeScale.timeToPx(data.tsStarts[i]));
+        const secondX = Math.floor(timeScale.timeToPx(data.tsEnds[i]));
+        const lastY = zeroY - Math.round((value / yMax) * RECT_HEIGHT);
+        ctx.fillRect(firstX, bottomY, secondX - firstX, lastY - bottomY);
       }
-
-      // We intentionally don't use the floor function here when computing x
-      // coordinates. Instead we use floating point which prevents flickering as
-      // we pan and zoom; this relies on the browser anti-aliasing pixels
-      // correctly.
-      const x = timeScale.timeToPx(data.timestamps[i]);
-      const xEnd = i === data.lastIdleValues.length - 1 ?
-          finalX :
-          timeScale.timeToPx(data.timestamps[i + 1]);
-
-      const width = xEnd - x;
-      const height = calculateY(data.lastFreqKHz[i]) - zeroY;
-
-      ctx.fillRect(x, zeroY, width, height);
     }
 
     ctx.font = '10px Roboto Condensed';
 
     if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
       let text = `${this.hoveredValue.toLocaleString()}kHz`;
+      if (data.isQuantized) {
+        text = `${this.hoveredValue.toLocaleString()}kHz (weighted avg)`;
+      }
 
       ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
       ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
@@ -222,11 +193,11 @@
     const {timeScale} = globals.frontendLocalState;
     const time = timeScale.pxToTime(x);
 
-    const [left, right] = searchSegment(data.timestamps, time);
-    this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
-    this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
-    this.hoveredValue = left === -1 ? undefined : data.lastFreqKHz[left];
-    this.hoveredIdle = left === -1 ? undefined : data.lastIdleValues[left];
+    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];
+    this.hoveredIdle = index === -1 ? undefined : data.idles[index];
   }
 
   onMouseOut() {
diff --git a/ui/src/tracks/cpu_profile/common.ts b/ui/src/tracks/cpu_profile/common.ts
index bfd3c69..cd7c0a2 100644
--- a/ui/src/tracks/cpu_profile/common.ts
+++ b/ui/src/tracks/cpu_profile/common.ts
@@ -19,7 +19,6 @@
 export interface Data extends TrackData {
   ids: Float64Array;
   tsStarts: Float64Array;
-  callsiteId: Uint32Array;
 }
 
 export interface Config {
diff --git a/ui/src/tracks/cpu_profile/controller.ts b/ui/src/tracks/cpu_profile/controller.ts
index 070cedb..cb850ee 100644
--- a/ui/src/tracks/cpu_profile/controller.ts
+++ b/ui/src/tracks/cpu_profile/controller.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {
   TrackController,
   trackControllerRegistry
@@ -28,13 +27,13 @@
   static readonly kind = CPU_PROFILE_TRACK_KIND;
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const query = `select id, ts, callsite_id from cpu_profile_stack_sample
+    const query = `select id, ts from cpu_profile_stack_sample
         where utid = ${this.config.utid}
         order by ts`;
 
     const result = await this.query(query);
 
-    const numRows = slowlyCountRows(result);
+    const numRows = +result.numRecords;
     const data: Data = {
       start,
       end,
@@ -42,13 +41,11 @@
       length: numRows,
       ids: new Float64Array(numRows),
       tsStarts: new Float64Array(numRows),
-      callsiteId: new Uint32Array(numRows),
     };
 
     for (let row = 0; row < numRows; row++) {
       data.ids[row] = +result.columns[0].longValues![row];
       data.tsStarts[row] = +result.columns[1].longValues![row];
-      data.callsiteId[row] = +result.columns[2].longValues![row];
     }
 
     return data;
diff --git a/ui/src/tracks/cpu_profile/frontend.ts b/ui/src/tracks/cpu_profile/frontend.ts
index f0cc6af..a940db0 100644
--- a/ui/src/tracks/cpu_profile/frontend.ts
+++ b/ui/src/tracks/cpu_profile/frontend.ts
@@ -12,11 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {hsluvToHex} from 'hsluv';
-
 import {searchSegment} from '../../base/binary_search';
 import {Actions} from '../../common/actions';
-import {hslForSlice} from '../../common/colorizer';
 import {TrackState} from '../../common/state';
 import {fromNs, toNs} from '../../common/time';
 import {globals} from '../../frontend/globals';
@@ -29,9 +26,8 @@
 const MARGIN_TOP = 4.5;
 const RECT_HEIGHT = 30.5;
 
-function colorForSample(callsiteId: number, isHovered: boolean): string {
-  return hsluvToHex(hslForSlice(String(callsiteId), isHovered));
-}
+const CPU_PROFILE_COLOR = 'hsl(350, 45%, 70%)';
+const CPU_PROFILE_HOVERED_COLOR = 'hsl(350, 45%, 55%)';
 
 class CpuProfileTrack extends Track<Config, Data> {
   static readonly kind = CPU_PROFILE_TRACK_KIND;
@@ -71,24 +67,23 @@
           timeScale.timeToPx(fromNs(centerX)),
           this.centerY,
           isHovered,
-          strokeWidth,
-          data.callsiteId[i]);
+          strokeWidth);
     }
   }
 
   drawMarker(
       ctx: CanvasRenderingContext2D, x: number, y: number, isHovered: boolean,
-      strokeWidth: number, callsiteId: number): void {
+      strokeWidth: number): void {
     ctx.beginPath();
     ctx.moveTo(x - this.markerWidth, y - this.markerWidth);
     ctx.lineTo(x, y + this.markerWidth);
     ctx.lineTo(x + this.markerWidth, y - this.markerWidth);
     ctx.lineTo(x - this.markerWidth, y - this.markerWidth);
     ctx.closePath();
-    ctx.fillStyle = colorForSample(callsiteId, isHovered);
+    ctx.fillStyle = isHovered ? CPU_PROFILE_HOVERED_COLOR : CPU_PROFILE_COLOR;
     ctx.fill();
     if (strokeWidth > 0) {
-      ctx.strokeStyle = colorForSample(callsiteId, false);
+      ctx.strokeStyle = CPU_PROFILE_HOVERED_COLOR;
       ctx.lineWidth = strokeWidth;
       ctx.stroke();
     }
diff --git a/ui/src/tracks/cpu_slices/common.ts b/ui/src/tracks/cpu_slices/common.ts
index c87bbe9..8bc0a09 100644
--- a/ui/src/tracks/cpu_slices/common.ts
+++ b/ui/src/tracks/cpu_slices/common.ts
@@ -16,7 +16,16 @@
 
 export const CPU_SLICE_TRACK_KIND = 'CpuSliceTrack';
 
-export interface Data extends TrackData {
+export interface SummaryData extends TrackData {
+  kind: 'summary';
+
+  bucketSizeSeconds: number;
+  utilizations: Float64Array;
+}
+
+export interface SliceData extends TrackData {
+  kind: 'slice';
+
   // Slices are stored in a columnar fashion. All fields have the same length.
   ids: Float64Array;
   starts: Float64Array;
@@ -24,4 +33,7 @@
   utids: Uint32Array;
 }
 
+export type Data = SummaryData | SliceData;
+
+
 export interface Config { cpu: number; }
diff --git a/ui/src/tracks/cpu_slices/controller.ts b/ui/src/tracks/cpu_slices/controller.ts
index 1389cb4..ec34dc2 100644
--- a/ui/src/tracks/cpu_slices/controller.ts
+++ b/ui/src/tracks/cpu_slices/controller.ts
@@ -12,101 +12,112 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertTrue} from '../../base/logging';
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
+
 import {
   TrackController,
   trackControllerRegistry
 } from '../../controller/track_controller';
 
-import {Config, CPU_SLICE_TRACK_KIND, Data} from './common';
+import {
+  Config,
+  CPU_SLICE_TRACK_KIND,
+  Data,
+  SliceData,
+  SummaryData
+} from './common';
 
 class CpuSliceTrackController extends TrackController<Config, Data> {
   static readonly kind = CPU_SLICE_TRACK_KIND;
-
-  private cachedBucketNs = Number.MAX_SAFE_INTEGER;
-  private maxDurNs = 0;
-
-  async onSetup() {
-    await this.query(`
-      create view ${this.tableName('sched')} as
-      select
-        ts,
-        dur,
-        utid,
-        id
-      from sched
-      where cpu = ${this.config.cpu} and utid != 0
-    `);
-
-    const rawResult = await this.query(`
-      select max(dur), count(1)
-      from ${this.tableName('sched')}
-    `);
-    this.maxDurNs = rawResult.columns[0].longValues![0];
-
-    const rowCount = rawResult.columns[1].longValues![0];
-    const bucketNs = this.cachedBucketSizeNs(rowCount);
-    if (bucketNs === undefined) {
-      return;
-    }
-    await this.query(`
-      create table ${this.tableName('sched_cached')} as
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cached_tsq,
-        ts,
-        max(dur) as dur,
-        utid,
-        id
-      from ${this.tableName('sched')}
-      group by cached_tsq
-      order by cached_tsq
-    `);
-    this.cachedBucketNs = bucketNs;
-  }
+  private setup = false;
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const resolutionNs = toNs(resolution);
-
-    // The resolution should always be a power of two for the logic of this
-    // function to make sense.
-    assertTrue(Math.log2(resolutionNs) % 1 === 0);
-
     const startNs = toNs(start);
     const endNs = toNs(end);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs =
-        Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+    if (this.setup === false) {
+      await this.query(
+          `create virtual table ${this.tableName('window')} using window;`);
+      await this.query(`create virtual table ${this.tableName('span')}
+              using span_join(sched PARTITIONED cpu,
+                              ${this.tableName('window')});`);
+      this.setup = true;
+    }
 
-    const isCached = this.cachedBucketNs <= bucketNs;
-    const queryTsq = isCached ?
-        `cached_tsq / ${bucketNs} * ${bucketNs}` :
-        `(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs}`;
-    const queryTable =
-        isCached ? this.tableName('sched_cached') : this.tableName('sched');
-    const constainColumn = isCached ? 'cached_tsq' : 'ts';
+    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) {
+      windowStartNs = Math.floor(windowStartNs / bucketSizeNs) * bucketSizeNs;
+    }
+    const windowDurNs = Math.max(1, endNs - windowStartNs);
 
-    const rawResult = await this.query(`
-      select
-        ${queryTsq} as tsq,
-        ts,
-        max(dur) as dur,
-        utid,
-        id
-      from ${queryTable}
-      where
-        ${constainColumn} >= ${startNs - this.maxDurNs} and
-        ${constainColumn} <= ${endNs}
-      group by tsq
-      order by tsq
-    `);
+    this.query(`update ${this.tableName('window')} set
+      window_start=${windowStartNs},
+      window_dur=${windowDurNs},
+      quantum=${isQuantized ? bucketSizeNs : 0}
+      where rowid = 0;`);
 
-    const numRows = slowlyCountRows(rawResult);
-    const slices: Data = {
+    if (isQuantized) {
+      return this.computeSummary(
+          fromNs(windowStartNs), end, resolution, bucketSizeNs);
+    } else {
+      return this.computeSlices(fromNs(windowStartNs), end, resolution);
+    }
+  }
+
+  private async computeSummary(
+      start: number, end: number, resolution: number,
+      bucketSizeNs: number): Promise<SummaryData> {
+    const startNs = toNs(start);
+    const endNs = toNs(end);
+    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')}
+        where cpu = ${this.config.cpu}
+        and utid != 0
+        group by quantum_ts limit ${LIMIT}`;
+
+    const rawResult = await this.query(query);
+    const numRows = +rawResult.numRecords;
+
+    const summary: Data = {
+      kind: 'summary',
+      start,
+      end,
+      resolution,
+      length: numRows,
+      bucketSizeSeconds: fromNs(bucketSizeNs),
+      utilizations: new Float64Array(numBuckets),
+    };
+    const cols = rawResult.columns;
+    for (let row = 0; row < numRows; row++) {
+      const bucket = +cols[0].longValues![row];
+      summary.utilizations[bucket] = +cols[1].doubleValues![row];
+    }
+    return summary;
+  }
+
+  private async computeSlices(start: number, end: number, resolution: number):
+      Promise<SliceData> {
+    // TODO(hjd): Remove LIMIT
+    const LIMIT = 10000;
+
+    const query = `select ts,dur,utid,id from ${this.tableName('span')}
+        where cpu = ${this.config.cpu}
+        and utid != 0
+        limit ${LIMIT};`;
+    const rawResult = await this.query(query);
+
+    const numRows = +rawResult.numRecords;
+    const slices: SliceData = {
+      kind: 'slice',
       start,
       end,
       resolution,
@@ -119,29 +130,25 @@
 
     const cols = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      if (startNsQ === endNsQ) {
-        throw new Error('Should never happen');
-      }
-
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.utids[row] = +cols[3].longValues![row];
-      slices.ids[row] = +cols[4].longValues![row];
+      const startSec = fromNs(+cols[0].longValues![row]);
+      slices.starts[row] = startSec;
+      slices.ends[row] = startSec + fromNs(+cols[1].longValues![row]);
+      slices.utids[row] = +cols[2].longValues![row];
+      slices.ids[row] = +cols[3].longValues![row];
     }
-
+    if (numRows === LIMIT) {
+      slices.end = slices.ends[slices.ends.length - 1];
+    }
     return slices;
   }
 
-  async onDestroy() {
-    await this.query(`drop table if exists ${this.tableName('sched_cached')}`);
+
+  onDestroy(): void {
+    if (this.setup) {
+      this.query(`drop table ${this.tableName('window')}`);
+      this.query(`drop table ${this.tableName('span')}`);
+      this.setup = false;
+    }
   }
 }
 
diff --git a/ui/src/tracks/cpu_slices/frontend.ts b/ui/src/tracks/cpu_slices/frontend.ts
index b6ca8d7..5edcc3f 100644
--- a/ui/src/tracks/cpu_slices/frontend.ts
+++ b/ui/src/tracks/cpu_slices/frontend.ts
@@ -12,14 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {search, searchEq, searchSegment} from '../../base/binary_search';
+import {search, searchEq} from '../../base/binary_search';
 import {assertTrue} from '../../base/logging';
 import {Actions} from '../../common/actions';
 import {cropText, drawDoubleHeadedArrow} from '../../common/canvas_utils';
-import {colorForThread} from '../../common/colorizer';
 import {TrackState} from '../../common/state';
 import {timeToString} from '../../common/time';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {colorForThread, hueForCpu} from '../../frontend/colorizer';
 import {globals} from '../../frontend/globals';
 import {Track} from '../../frontend/track';
 import {trackRegistry} from '../../frontend/track_registry';
@@ -28,11 +28,14 @@
   Config,
   CPU_SLICE_TRACK_KIND,
   Data,
+  SliceData,
+  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;
 
 class CpuSliceTrack extends Track<Config, Data> {
   static readonly kind = CPU_SLICE_TRACK_KIND;
@@ -41,10 +44,12 @@
   }
 
   private mouseXpos?: number;
+  private hue: number;
   private utidHoveredInThisTrack = -1;
 
   constructor(trackState: TrackState) {
     super(trackState);
+    this.hue = hueForCpu(this.config.cpu);
   }
 
   getHeight(): number {
@@ -68,10 +73,40 @@
         timeScale.timeToPx(data.start),
         timeScale.timeToPx(data.end));
 
-    this.renderSlices(ctx, data);
+    if (data.kind === 'summary') {
+      this.renderSummary(ctx, data);
+    } else if (data.kind === 'slice') {
+      this.renderSlices(ctx, data);
+    }
   }
 
-  renderSlices(ctx: CanvasRenderingContext2D, data: Data): void {
+  renderSummary(ctx: CanvasRenderingContext2D, data: SummaryData): void {
+    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+    const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
+    const bottomY = TRACK_HEIGHT;
+
+    let lastX = startPx;
+    let lastY = bottomY;
+
+    ctx.fillStyle = `hsl(${this.hue}, 50%, 60%)`;
+    ctx.beginPath();
+    ctx.moveTo(lastX, lastY);
+    for (let i = 0; i < data.utilizations.length; i++) {
+      const utilization = data.utilizations[i];
+      const startTime = i * data.bucketSizeSeconds + data.start;
+
+      lastX = Math.floor(timeScale.timeToPx(startTime));
+
+      ctx.lineTo(lastX, lastY);
+      lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
+      ctx.lineTo(lastX, lastY);
+    }
+    ctx.lineTo(lastX, bottomY);
+    ctx.closePath();
+    ctx.fill();
+  }
+
+  renderSlices(ctx: CanvasRenderingContext2D, data: SliceData): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     assertTrue(data.starts.length === data.ends.length);
     assertTrue(data.starts.length === data.utids.length);
@@ -80,24 +115,33 @@
     ctx.font = '12px Roboto Condensed';
     const charWidth = ctx.measureText('dbpqaouk').width / 8;
 
-    const rawStartIdx =
-        data.ends.findIndex(end => end >= visibleWindowTime.start);
-    const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
-
-    const [, rawEndIdx] = searchSegment(data.starts, visibleWindowTime.end);
-    const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
-
-    for (let i = startIdx; i < endIdx; i++) {
+    for (let i = 0; i < data.starts.length; i++) {
       const tStart = data.starts[i];
       const tEnd = data.ends[i];
       const utid = data.utids[i];
-
+      if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
+        continue;
+      }
       const rectStart = timeScale.timeToPx(tStart);
       const rectEnd = timeScale.timeToPx(tEnd);
       const rectWidth = Math.max(1, rectEnd - rectStart);
-
       const threadInfo = globals.threads.get(utid);
-      const pid = threadInfo && threadInfo.pid ? threadInfo.pid : -1;
+
+      // TODO: consider de-duplicating this code with the copied one from
+      // chrome_slices/frontend.ts.
+      let title = `[utid:${utid}]`;
+      let subTitle = '';
+      let pid = -1;
+      if (threadInfo) {
+        if (threadInfo.pid) {
+          pid = threadInfo.pid;
+          const procName = threadInfo.procName || '';
+          title = `${procName} [${threadInfo.pid}]`;
+          subTitle = `${threadInfo.threadName} [${threadInfo.tid}]`;
+        } else {
+          title = `${threadInfo.threadName} [${threadInfo.tid}]`;
+        }
+      }
 
       const isHovering = globals.frontendLocalState.hoveredUtid !== -1;
       const isThreadHovered = globals.frontendLocalState.hoveredUtid === utid;
@@ -121,22 +165,6 @@
       // Don't render text when we have less than 5px to play with.
       if (rectWidth < 5) continue;
 
-      // TODO: consider de-duplicating this code with the copied one from
-      // chrome_slices/frontend.ts.
-      let title = `[utid:${utid}]`;
-      let subTitle = '';
-      if (threadInfo) {
-        if (threadInfo.pid) {
-          let procName = threadInfo.procName || '';
-          if (procName.startsWith('/')) {  // Remove folder paths from name
-            procName = procName.substring(procName.lastIndexOf('/') + 1);
-          }
-          title = `${procName} [${threadInfo.pid}]`;
-          subTitle = `${threadInfo.threadName} [${threadInfo.tid}]`;
-        } else {
-          title = `${threadInfo.threadName} [${threadInfo.tid}]`;
-        }
-      }
       title = cropText(title, charWidth, rectWidth);
       subTitle = cropText(subTitle, charWidth, rectWidth);
       const rectXCenter = rectStart + rectWidth / 2;
@@ -226,7 +254,7 @@
   onMouseMove({x, y}: {x: number, y: number}) {
     const data = this.data();
     this.mouseXpos = x;
-    if (data === undefined) return;
+    if (data === undefined || data.kind === 'summary') return;
     const {timeScale} = globals.frontendLocalState;
     if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
       this.utidHoveredInThisTrack = -1;
@@ -259,7 +287,7 @@
 
   onMouseClick({x}: {x: number}) {
     const data = this.data();
-    if (data === undefined) return false;
+    if (data === undefined || data.kind === 'summary') return false;
     const {timeScale} = globals.frontendLocalState;
     const time = timeScale.pxToTime(x);
     const index = search(data.starts, time);
diff --git a/ui/src/tracks/debug_slices/common.ts b/ui/src/tracks/debug_slices/common.ts
deleted file mode 100644
index 9625d54..0000000
--- a/ui/src/tracks/debug_slices/common.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// import {Data as ChromeSlicesData} from '../chrome_slices/common';
-
-export const DEBUG_SLICE_TRACK_KIND = 'DebugSliceTrack';
-
-export interface Config {
-  maxDepth: number;
-}
-
-export {Data} from '../chrome_slices/common';
diff --git a/ui/src/tracks/debug_slices/controller.ts b/ui/src/tracks/debug_slices/controller.ts
deleted file mode 100644
index 0afcb55..0000000
--- a/ui/src/tracks/debug_slices/controller.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import {assertTrue} from '../../base/logging';
-import {Actions} from '../../common/actions';
-import {slowlyCountRows} from '../../common/query_iterator';
-import {fromNs, toNs} from '../../common/time';
-import {globals} from '../../controller/globals';
-import {
-  TrackController,
-  trackControllerRegistry,
-} from '../../controller/track_controller';
-
-import {Config, Data, DEBUG_SLICE_TRACK_KIND} from './common';
-
-class DebugSliceTrackController extends TrackController<Config, Data> {
-  static readonly kind = DEBUG_SLICE_TRACK_KIND;
-
-  async onReload() {
-    const rawResult = await this.query(`select max(depth) from debug_slices`);
-    const maxDepth = (slowlyCountRows(rawResult) === 0) ?
-        1 :
-        rawResult.columns[0].longValues![0];
-    globals.dispatch(
-        Actions.updateTrackConfig({id: this.trackId, config: {maxDepth}}));
-  }
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const rawResult = await this.query(`select id, name, ts,
-        iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur),
-        depth from debug_slices where
-        (ts + dur) >= ${toNs(start)} and ts <= ${toNs(end)}`);
-
-    assertTrue(rawResult.columns.length === 5);
-    const [idCol, nameCol, tsCol, durCol, depthCol] = rawResult.columns;
-    const idValues = idCol.longValues! || idCol.doubleValues!;
-    const tsValues = tsCol.longValues! || tsCol.doubleValues!;
-    const durValues = durCol.longValues! || durCol.doubleValues!;
-
-    const numRows = slowlyCountRows(rawResult);
-    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),
-      isInstant: new Uint16Array(numRows),
-      isIncomplete: 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 i = 0; i < slowlyCountRows(rawResult); i++) {
-      let sliceStart: number, sliceEnd: number;
-      if (tsCol.isNulls![i] || durCol.isNulls![i]) {
-        sliceStart = sliceEnd = -1;
-      } else {
-        sliceStart = tsValues[i];
-        const sliceDur = durValues[i];
-        sliceEnd = sliceStart + sliceDur;
-      }
-      slices.sliceIds[i] = idCol.isNulls![i] ? -1 : idValues[i];
-      slices.starts[i] = fromNs(sliceStart);
-      slices.ends[i] = fromNs(sliceEnd);
-      slices.depths[i] = depthCol.isNulls![i] ? 0 : depthCol.longValues![i];
-      const sliceName =
-          nameCol.isNulls![i] ? '[null]' : nameCol.stringValues![i];
-      slices.titles[i] = internString(sliceName);
-      slices.isInstant[i] = 0;
-      slices.isIncomplete[i] = 0;
-    }
-
-    return slices;
-  }
-}
-
-trackControllerRegistry.register(DebugSliceTrackController);
diff --git a/ui/src/tracks/debug_slices/frontend.ts b/ui/src/tracks/debug_slices/frontend.ts
deleted file mode 100644
index bdda433..0000000
--- a/ui/src/tracks/debug_slices/frontend.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import * as m from 'mithril';
-
-import {Actions} from '../../common/actions';
-import {TrackState} from '../../common/state';
-import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
-import {trackRegistry} from '../../frontend/track_registry';
-import {ChromeSliceTrack} from '../chrome_slices/frontend';
-
-import {DEBUG_SLICE_TRACK_KIND} from './common';
-
-export class DebugSliceTrack extends ChromeSliceTrack {
-  static readonly kind = DEBUG_SLICE_TRACK_KIND;
-  static create(trackState: TrackState): Track {
-    return new DebugSliceTrack(trackState);
-  }
-
-  getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
-    const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
-    buttons.push(m(TrackButton, {
-      action: () => {
-        globals.dispatch(Actions.requestTrackReload({}));
-      },
-      i: 'refresh',
-      tooltip: 'Refresh tracks',
-      showButton: true,
-    }));
-    buttons.push(m(TrackButton, {
-      action: () => {
-        globals.dispatch(Actions.removeDebugTrack({}));
-      },
-      i: 'close',
-      tooltip: 'Close',
-      showButton: true,
-    }));
-    return buttons;
-  }
-}
-
-trackRegistry.register(DebugSliceTrack);
diff --git a/ui/src/tracks/expected_frames/common.ts b/ui/src/tracks/expected_frames/common.ts
deleted file mode 100644
index 9245520..0000000
--- a/ui/src/tracks/expected_frames/common.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 EXPECTED_FRAMES_SLICE_TRACK_KIND = 'ExpectedFramesSliceTrack';
-
-export interface Config {
-  maxDepth: number;
-  trackIds: number[];
-}
-
-export interface Data extends TrackData {
-  // 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|.
-  colors?: Uint16Array;  // Index in |strings|.
-  isInstant: Uint16Array;
-  isIncomplete: Uint16Array;
-}
diff --git a/ui/src/tracks/expected_frames/controller.ts b/ui/src/tracks/expected_frames/controller.ts
deleted file mode 100644
index 532eaa0..0000000
--- a/ui/src/tracks/expected_frames/controller.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {slowlyCountRows} from '../../common/query_iterator';
-import {fromNs, toNs} from '../../common/time';
-import {
-  TrackController,
-  trackControllerRegistry,
-} from '../../controller/track_controller';
-
-import {Config, Data, EXPECTED_FRAMES_SLICE_TRACK_KIND} from './common';
-
-class ExpectedFramesSliceTrackController extends TrackController<Config, Data> {
-  static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
-  private maxDurNs = 0;
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
-
-    const pxSize = this.pxSize();
-
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs = Math.max(Math.round(resolution * 1e9 * pxSize / 2) * 2, 1);
-
-    if (this.maxDurNs === 0) {
-      const maxDurResult = await this.query(`
-        select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
-        from experimental_slice_layout
-        where filter_track_ids = '${this.config.trackIds.join(',')}'
-      `);
-      if (slowlyCountRows(maxDurResult) === 1) {
-        this.maxDurNs = maxDurResult.columns[0].longValues![0];
-      }
-    }
-
-    const rawResult = await this.query(`
-      SELECT
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        ts,
-        max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)) as dur,
-        layout_depth,
-        name,
-        id,
-        dur = 0 as is_instant,
-        dur = -1 as is_incomplete
-      from experimental_slice_layout
-      where
-        filter_track_ids = '${this.config.trackIds.join(',')}' and
-        ts >= ${startNs - this.maxDurNs} and
-        ts <= ${endNs}
-      group by tsq, layout_depth
-      order by tsq, layout_depth
-    `);
-
-    const numRows = slowlyCountRows(rawResult);
-    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),
-      colors: new Uint16Array(numRows),
-      isInstant: new Uint16Array(numRows),
-      isIncomplete: 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;
-    }
-    const greenIndex = internString('#4CAF50');
-
-    const cols = rawResult.columns;
-    for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      if (startNsQ === endNsQ) {
-        throw new Error('Should never happen');
-      }
-
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.depths[row] = +cols[3].longValues![row];
-      slices.titles[row] = internString(cols[4].stringValues![row]);
-      slices.sliceIds[row] = +cols[5].longValues![row];
-      slices.isInstant[row] = +cols[6].longValues![row];
-      slices.isIncomplete[row] = +cols[7].longValues![row];
-      slices.colors![row] = greenIndex;
-    }
-    return slices;
-  }
-}
-
-
-trackControllerRegistry.register(ExpectedFramesSliceTrackController);
diff --git a/ui/src/tracks/expected_frames/frontend.ts b/ui/src/tracks/expected_frames/frontend.ts
deleted file mode 100644
index 441f098..0000000
--- a/ui/src/tracks/expected_frames/frontend.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 {EXPECTED_FRAMES_SLICE_TRACK_KIND} from './common';
-
-export class ExpectedFramesSliceTrack extends ChromeSliceTrack {
-  static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
-  static create(trackState: TrackState): Track {
-    return new ExpectedFramesSliceTrack(trackState);
-  }
-}
-
-trackRegistry.register(ExpectedFramesSliceTrack);
diff --git a/ui/src/tracks/gpu_freq/common.ts b/ui/src/tracks/gpu_freq/common.ts
new file mode 100644
index 0000000..f860234
--- /dev/null
+++ b/ui/src/tracks/gpu_freq/common.ts
@@ -0,0 +1,33 @@
+
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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;
+  trackId: number;
+  maximumValue?: number;
+  minimumValue?: number;
+}
diff --git a/ui/src/tracks/gpu_freq/controller.ts b/ui/src/tracks/gpu_freq/controller.ts
new file mode 100644
index 0000000..a8bafd6
--- /dev/null
+++ b/ui/src/tracks/gpu_freq/controller.ts
@@ -0,0 +1,146 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 counter
+        where track_id = ${this.config.trackId}`);
+      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,
+            value as freq_value
+          from counter
+          where track_id = ${this.config.trackId};
+      `);
+
+      await this.query(`create virtual table ${this.tableName('span_activity')}
+        using span_join(${this.tableName('freq')}, ${
+          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
new file mode 100644
index 0000000..7f42c70
--- /dev/null
+++ b/ui/src/tracks/gpu_freq/frontend.ts
@@ -0,0 +1,182 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 Roboto Condensed';
+
+    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`;
+      }
+
+      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.
+      this.drawTrackHoverTooltip(ctx, this.mouseXpos, text);
+    }
+
+    // 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/controller.ts b/ui/src/tracks/heap_profile/controller.ts
index 2422af1..bab0b15 100644
--- a/ui/src/tracks/heap_profile/controller.ts
+++ b/ui/src/tracks/heap_profile/controller.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {
   TrackController,
   trackControllerRegistry
@@ -46,7 +45,7 @@
         select distinct(graph_sample_ts) as ts, 'graph' as type from
         heap_graph_object
         where upid = ${this.config.upid}) order by ts`);
-    const numRows = slowlyCountRows(result);
+    const numRows = +result.numRecords;
     const data: Data = {
       start,
       end,
diff --git a/ui/src/tracks/heap_profile/frontend.ts b/ui/src/tracks/heap_profile/frontend.ts
index c9c7466..86d177e 100644
--- a/ui/src/tracks/heap_profile/frontend.ts
+++ b/ui/src/tracks/heap_profile/frontend.ts
@@ -16,7 +16,10 @@
 import {Actions} from '../../common/actions';
 import {TrackState} from '../../common/state';
 import {fromNs, toNs} from '../../common/time';
-import {HEAP_PROFILE_HOVERED_COLOR} from '../../frontend/flamegraph';
+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';
@@ -24,8 +27,6 @@
 
 import {Config, Data, HEAP_PROFILE_TRACK_KIND} from './common';
 
-const HEAP_PROFILE_COLOR = 'hsl(224, 45%, 70%)';
-
 // 0.5 Makes the horizontal lines sharp.
 const MARGIN_TOP = 4.5;
 const RECT_HEIGHT = 30.5;
@@ -118,6 +119,8 @@
     if (index !== -1) {
       const ts = data.tsStarts[index];
       const type = data.types[index];
+      globals.dispatch(Actions.showHeapProfileFlamegraph(
+          {id: index, upid: this.config.upid, ts, type}));
       globals.makeSelection(Actions.selectHeapProfile(
           {id: index, upid: this.config.upid, ts, type}));
       return true;
diff --git a/ui/src/tracks/process_scheduling/common.ts b/ui/src/tracks/process_scheduling/common.ts
index 3ca8560..ed54e52 100644
--- a/ui/src/tracks/process_scheduling/common.ts
+++ b/ui/src/tracks/process_scheduling/common.ts
@@ -16,7 +16,14 @@
 
 export const PROCESS_SCHEDULING_TRACK_KIND = 'ProcessSchedulingTrack';
 
-export interface Data extends TrackData {
+export interface SummaryData extends TrackData {
+  kind: 'summary';
+
+  bucketSizeSeconds: number;
+  utilizations: Float64Array;
+}
+
+export interface SliceData extends TrackData {
   kind: 'slice';
   maxCpu: number;
 
@@ -27,6 +34,8 @@
   cpus: Uint32Array;
 }
 
+export type Data = SummaryData | SliceData;
+
 export interface Config {
   pidForColor: number;
   upid: null|number;
diff --git a/ui/src/tracks/process_scheduling/controller.ts b/ui/src/tracks/process_scheduling/controller.ts
index c7676ed..914e452 100644
--- a/ui/src/tracks/process_scheduling/controller.ts
+++ b/ui/src/tracks/process_scheduling/controller.ts
@@ -13,9 +13,8 @@
 // limitations under the License.
 
 import {assertTrue} from '../../base/logging';
-import {RawQueryResult} from '../../common/protos';
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
 import {
   TrackController,
   trackControllerRegistry
@@ -25,73 +24,110 @@
   Config,
   Data,
   PROCESS_SCHEDULING_TRACK_KIND,
+  SliceData,
+  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 setup = false;
   private maxCpu = 0;
-  private maxDurNs = 0;
-  private cachedBucketNs = Number.MAX_SAFE_INTEGER;
-
-  async onSetup() {
-    await this.createSchedView();
-
-    const cpus = await this.engine.getCpus();
-
-    // A process scheduling track should only exist in a trace that has cpus.
-    assertTrue(cpus.length > 0);
-    this.maxCpu = Math.max(...cpus) + 1;
-
-    const result = await this.query(`
-      select max(dur), count(1)
-      from ${this.tableName('process_sched')}
-    `);
-    this.maxDurNs = result.columns[0].longValues![0];
-
-    const rowCount = result.columns[1].longValues![0];
-    const bucketNs = this.cachedBucketSizeNs(rowCount);
-    if (bucketNs === undefined) {
-      return;
-    }
-    await this.query(`
-      create table ${this.tableName('process_sched_cached')} as
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as cached_tsq,
-        ts,
-        max(dur) as dur,
-        cpu,
-        utid
-      from ${this.tableName('process_sched')}
-      group by cached_tsq, cpu
-      order by cached_tsq, cpu
-    `);
-    this.cachedBucketNs = bucketNs;
-  }
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    assertTrue(this.config.upid !== null);
-
-    // The resolution should always be a power of two for the logic of this
-    // function to make sense.
-    const resolutionNs = toNs(resolution);
-    assertTrue(Math.log2(resolutionNs) % 1 === 0);
+    if (this.config.upid === null) {
+      throw new Error('Upid not set.');
+    }
 
     const startNs = toNs(start);
     const endNs = toNs(end);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs =
-        Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+    if (this.setup === false) {
+      await this.query(
+          `create virtual table ${this.tableName('window')} using window;`);
+      await this.query(`create view ${this.tableName('process')} as
+          select ts, dur, cpu, utid, upid from sched join (
+          select utid, upid from thread
+            where utid != 0 and upid = ${this.config.upid}) using(utid);`);
+      await this.query(`create virtual table ${this.tableName('span')}
+              using span_join(${this.tableName('process')} PARTITIONED utid,
+                              ${this.tableName('window')});`);
+      const cpus = await this.engine.getCpus();
+      // A process scheduling track should only exist in a trace that has cpus.
+      assertTrue(cpus.length > 0);
+      this.maxCpu = Math.max(...cpus) + 1;
+      this.setup = true;
+    }
 
-    const rawResult = await this.queryData(startNs, endNs, bucketNs);
+    const isQuantized = this.shouldSummarize(resolution);
+    // |resolution| is in s/px we want # ns for 20px window:
+    const bucketSizeNs = Math.round(resolution * 10 * 1e9 * 1.5);
+    let windowStartNs = startNs;
+    if (isQuantized) {
+      windowStartNs = Math.floor(windowStartNs / bucketSizeNs) * bucketSizeNs;
+    }
+    const windowDurNs = Math.max(1, endNs - windowStartNs);
 
-    const numRows = slowlyCountRows(rawResult);
-    const slices: Data = {
+    this.query(`update ${this.tableName('window')} set
+      window_start=${windowStartNs},
+      window_dur=${windowDurNs},
+      quantum=${isQuantized ? bucketSizeNs : 0}
+      where rowid = 0;`);
+
+    if (isQuantized) {
+      return this.computeSummary(
+          fromNs(windowStartNs), end, resolution, bucketSizeNs);
+    } else {
+      return this.computeSlices(fromNs(windowStartNs), end, resolution);
+    }
+  }
+
+  private async computeSummary(
+      start: number, end: number, resolution: number,
+      bucketSizeNs: number): Promise<SummaryData> {
+    const startNs = toNs(start);
+    const endNs = toNs(end);
+    const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
+
+    const query = `select
+        quantum_ts as bucket,
+        sum(dur)/cast(${bucketSizeNs * this.maxCpu} as float) as utilization
+        from ${this.tableName('span')}
+        group by quantum_ts
+        limit ${LIMIT}`;
+
+    const rawResult = await this.query(query);
+    const numRows = +rawResult.numRecords;
+
+    const summary: Data = {
+      kind: 'summary',
+      start,
+      end,
+      resolution,
+      length: numRows,
+      bucketSizeSeconds: fromNs(bucketSizeNs),
+      utilizations: new Float64Array(numBuckets),
+    };
+    const cols = rawResult.columns;
+    for (let row = 0; row < numRows; row++) {
+      const bucket = +cols[0].longValues![row];
+      summary.utilizations[bucket] = +cols[1].doubleValues![row];
+    }
+    return summary;
+  }
+
+  private async computeSlices(start: number, end: number, resolution: number):
+      Promise<SliceData> {
+    const query = `select ts,dur,cpu,utid from ${this.tableName('span')}
+        order by cpu, ts
+        limit ${LIMIT};`;
+    const rawResult = await this.query(query);
+
+    const numRows = +rawResult.numRecords;
+    const slices: SliceData = {
       kind: 'slice',
       start,
       end,
@@ -106,60 +142,22 @@
 
     const cols = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
-
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
-
-      if (startNsQ === endNsQ) {
-        throw new Error('Should never happen');
-      }
-
-      slices.starts[row] = fromNs(startNsQ);
-      slices.ends[row] = fromNs(endNsQ);
-      slices.cpus[row] = +cols[3].longValues![row];
-      slices.utids[row] = +cols[4].longValues![row];
+      const startSec = fromNs(+cols[0].longValues![row]);
+      slices.starts[row] = startSec;
+      slices.ends[row] = startSec + fromNs(+cols[1].longValues![row]);
+      slices.cpus[row] = +cols[2].longValues![row];
+      slices.utids[row] = +cols[3].longValues![row];
       slices.end = Math.max(slices.ends[row], slices.end);
     }
     return slices;
   }
 
-  private queryData(startNs: number, endNs: number, bucketNs: number):
-      Promise<RawQueryResult> {
-    const isCached = this.cachedBucketNs <= bucketNs;
-    const tsq = isCached ? `cached_tsq / ${bucketNs} * ${bucketNs}` :
-                           `(ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs}`;
-    const queryTable = isCached ? this.tableName('process_sched_cached') :
-                                  this.tableName('process_sched');
-    const constainColumn = isCached ? 'cached_tsq' : 'ts';
-    return this.query(`
-      select
-        ${tsq} as tsq,
-        ts,
-        max(dur) as dur,
-        cpu,
-        utid
-      from ${queryTable}
-      where
-        ${constainColumn} >= ${startNs - this.maxDurNs} and
-        ${constainColumn} <= ${endNs}
-      group by tsq, cpu
-      order by tsq, cpu
-    `);
-  }
-
-  private async createSchedView() {
-    await this.query(`
-      create view ${this.tableName('process_sched')} as
-      select ts, dur, cpu, utid
-      from experimental_sched_upid
-      where
-        utid != 0 and
-        upid = ${this.config.upid}
-    `);
+  onDestroy(): void {
+    if (this.setup) {
+      this.query(`drop table ${this.tableName('window')}`);
+      this.query(`drop table ${this.tableName('span')}`);
+      this.setup = false;
+    }
   }
 }
 
diff --git a/ui/src/tracks/process_scheduling/frontend.ts b/ui/src/tracks/process_scheduling/frontend.ts
index e7c4eb1..5246124 100644
--- a/ui/src/tracks/process_scheduling/frontend.ts
+++ b/ui/src/tracks/process_scheduling/frontend.ts
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {searchEq, searchRange, searchSegment} from '../../base/binary_search';
+import {searchEq, searchRange} from '../../base/binary_search';
 import {assertTrue} from '../../base/logging';
-import {colorForThread} from '../../common/colorizer';
 import {TrackState} from '../../common/state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {colorForThread, colorForTid} from '../../frontend/colorizer';
 import {globals} from '../../frontend/globals';
 import {Track} from '../../frontend/track';
 import {trackRegistry} from '../../frontend/track_registry';
@@ -25,11 +25,14 @@
   Config,
   Data,
   PROCESS_SCHEDULING_TRACK_KIND,
+  SliceData,
+  SummaryData
 } from './common';
 
 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;
@@ -65,24 +68,55 @@
         timeScale.timeToPx(data.start),
         timeScale.timeToPx(data.end));
 
+    if (data.kind === 'summary') {
+      this.renderSummary(ctx, data);
+    } else if (data.kind === 'slice') {
+      this.renderSlices(ctx, data);
+    }
+  }
+
+  renderSummary(ctx: CanvasRenderingContext2D, data: SummaryData): void {
+    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+    const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
+    const bottomY = TRACK_HEIGHT;
+
+    let lastX = startPx;
+    let lastY = bottomY;
+
+    const color = colorForTid(this.config.pidForColor);
+    ctx.fillStyle = `hsl(${color.h}, ${color.s}%, ${color.l}%)`;
+    ctx.beginPath();
+    ctx.moveTo(lastX, lastY);
+    for (let i = 0; i < data.utilizations.length; i++) {
+      const utilization = data.utilizations[i];
+      const startTime = i * data.bucketSizeSeconds + data.start;
+
+      lastX = Math.floor(timeScale.timeToPx(startTime));
+
+      ctx.lineTo(lastX, lastY);
+      lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
+      ctx.lineTo(lastX, lastY);
+    }
+    ctx.lineTo(lastX, bottomY);
+    ctx.closePath();
+    ctx.fill();
+  }
+
+  renderSlices(ctx: CanvasRenderingContext2D, data: SliceData): void {
+    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     assertTrue(data.starts.length === data.ends.length);
     assertTrue(data.starts.length === data.utids.length);
 
-    const rawStartIdx =
-        data.ends.findIndex(end => end >= visibleWindowTime.start);
-    const startIdx = rawStartIdx === -1 ? data.starts.length : rawStartIdx;
-
-    const [, rawEndIdx] = searchSegment(data.starts, visibleWindowTime.end);
-    const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
-
     const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
 
-    for (let i = startIdx; i < endIdx; i++) {
+    for (let i = 0; i < data.starts.length; i++) {
       const tStart = data.starts[i];
       const tEnd = data.ends[i];
       const utid = data.utids[i];
       const cpu = data.cpus[i];
-
+      if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
+        continue;
+      }
       const rectStart = timeScale.timeToPx(tStart);
       const rectEnd = timeScale.timeToPx(tEnd);
       const rectWidth = rectEnd - rectStart;
@@ -124,11 +158,10 @@
     }
   }
 
-
   onMouseMove({x, y}: {x: number, y: number}) {
     const data = this.data();
     this.mouseXpos = x;
-    if (data === undefined) return;
+    if (data === undefined || data.kind === 'summary') return;
     if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
       this.utidHoveredInThisTrack = -1;
       globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
diff --git a/ui/src/tracks/process_summary/controller.ts b/ui/src/tracks/process_summary/controller.ts
index 75242fe..d226ace 100644
--- a/ui/src/tracks/process_summary/controller.ts
+++ b/ui/src/tracks/process_summary/controller.ts
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {slowlyCountRows} from '../../common/query_iterator';
 import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
+
 import {
   TrackController,
   trackControllerRegistry
@@ -46,12 +46,12 @@
       if (this.config.upid) {
         const threadQuery = await this.query(
             `select utid from thread where upid=${this.config.upid}`);
-        utids = threadQuery.columns[0].longValues!;
+        utids = threadQuery.columns[0].longValues! as number[];
       }
 
       const trackQuery = await this.query(
           `select id from thread_track where utid in (${utids.join(',')})`);
-      const tracks = trackQuery.columns[0].longValues!;
+      const tracks = trackQuery.columns[0].longValues! as number[];
 
       const processSliceView = this.tableName('process_slice_view');
       await this.query(
@@ -99,7 +99,7 @@
       limit ${LIMIT}`;
 
     const rawResult = await this.query(query);
-    const numRows = slowlyCountRows(rawResult);
+    const numRows = +rawResult.numRecords;
 
     const summary: Data = {
       start,
diff --git a/ui/src/tracks/process_summary/frontend.ts b/ui/src/tracks/process_summary/frontend.ts
index 0a259ca..9e44b8a 100644
--- a/ui/src/tracks/process_summary/frontend.ts
+++ b/ui/src/tracks/process_summary/frontend.ts
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {colorForTid} from '../../common/colorizer';
 import {TrackState} from '../../common/state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {colorForTid} from '../../frontend/colorizer';
 import {globals} from '../../frontend/globals';
 import {Track} from '../../frontend/track';
 import {trackRegistry} from '../../frontend/track_registry';
diff --git a/ui/src/tracks/thread_state/common.ts b/ui/src/tracks/thread_state/common.ts
index 9bede66..6c21344 100644
--- a/ui/src/tracks/thread_state/common.ts
+++ b/ui/src/tracks/thread_state/common.ts
@@ -18,13 +18,15 @@
 
 export interface Data extends TrackData {
   strings: string[];
-  ids: Float64Array;
   starts: Float64Array;
   ends: Float64Array;
-  cpu: Int8Array;
   state: Uint16Array;  // Index into |strings|.
+  cpu: Uint8Array;
+  summarisedStateBreakdowns: Map<number, StatePercent>;
 }
 
+export type StatePercent = Map<string, number>;
+
 export interface Config {
   utid: number;
 }
diff --git a/ui/src/tracks/thread_state/controller.ts b/ui/src/tracks/thread_state/controller.ts
index a4718c6..521da7e 100644
--- a/ui/src/tracks/thread_state/controller.ts
+++ b/ui/src/tracks/thread_state/controller.ts
@@ -12,16 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {assertFalse} from '../../base/logging';
-import {
-  iter,
-  NUM,
-  NUM_NULL,
-  slowlyCountRows,
-  STR_NULL
-} from '../../common/query_iterator';
-import {translateState} from '../../common/thread_state';
 import {fromNs, toNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
+
 import {
   TrackController,
   trackControllerRegistry
@@ -35,125 +28,125 @@
 
 class ThreadStateTrackController extends TrackController<Config, Data> {
   static readonly kind = THREAD_STATE_TRACK_KIND;
-
-  private maxDurNs = 0;
-
-  async onSetup() {
-    await this.query(`
-      create view ${this.tableName('thread_state')} as
-      select
-        id,
-        ts,
-        dur,
-        cpu,
-        state,
-        io_wait
-      from thread_state
-      where utid = ${this.config.utid} and utid != 0
-    `);
-
-    const rawResult = await this.query(`
-      select max(dur)
-      from ${this.tableName('thread_state')}
-    `);
-    this.maxDurNs = rawResult.columns[0].longValues![0];
-  }
+  private setup = false;
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const resolutionNs = toNs(resolution);
     const startNs = toNs(start);
     const endNs = toNs(end);
+    const minNs = Math.round(resolution * 1e9);
 
-    // ns per quantization bucket (i.e. ns per pixel). /2 * 2 is to force it to
-    // be an even number, so we can snap in the middle.
-    const bucketNs =
-        Math.max(Math.round(resolutionNs * this.pxSize() / 2) * 2, 1);
+    await this.query(
+        `drop view if exists ${this.tableName('grouped_thread_states')}`);
 
-    const query = `
-      select
-        (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
-        ts,
-        max(dur) as dur,
-        cast(cpu as integer) as cpu,
-        state,
-        io_wait,
-        id
-      from ${this.tableName('thread_state')}
-      where
-        ts >= ${startNs - this.maxDurNs} and
-        ts <= ${endNs}
-      group by tsq, state, io_wait
-      order by tsq, state, io_wait
-    `;
+    // This query gives all contiguous slices less than minNs the same grouping.
+    await this.query(`create view ${this.tableName('grouped_thread_states')} as
+    select ts, dur, cpu, state,
+    ifnull(sum(value) over (order by ts), 0) as grouping
+    from
+    (select *,
+    (dur >= ${minNs}) or lag(dur >= ${minNs}) over (order by ts) as value
+    from thread_state
+    where utid = ${this.config.utid})`);
+
+    // Since there are more rows than slices we will output, check the number of
+    // distinct groupings to find the number of slices.
+    const totalSlicesQuery = `select count(distinct(grouping))
+      from ${this.tableName('grouped_thread_states')}
+      where ts <= ${endNs} and ts + dur >= ${startNs}`;
+    const totalSlices = (await this.engine.queryOneRow(totalSlicesQuery))[0];
+
+    // We have ts contraints instead of span joining with the window table
+    // because when selecting a slice we need the real duration (even if it
+    // is outside of the current viewport)
+    // TODO(b/149303809): Return this to using
+    // the window table if possible.
+    const query = `select min(min(ts)) over (partition by grouping) as ts,
+    sum(sum(dur)) over (partition by grouping) as slice_dur,
+    cpu,
+    state,
+    (sum(dur) * 1.0)/(sum(sum(dur)) over (partition by grouping)) as percent,
+    grouping
+    from ${this.tableName('grouped_thread_states')}
+    where ts <= ${endNs} and ts + dur >= ${startNs}
+    group by grouping, state
+    order by grouping
+    limit ${LIMIT}`;
 
     const result = await this.query(query);
-    const numRows = slowlyCountRows(result);
+    const numRows = +result.numRecords;
 
-    const data: Data = {
+    const summary: Data = {
       start,
       end,
       resolution,
-      length: numRows,
-      ids: new Float64Array(numRows),
-      starts: new Float64Array(numRows),
-      ends: new Float64Array(numRows),
+      length: totalSlices,
+      starts: new Float64Array(totalSlices),
+      ends: new Float64Array(totalSlices),
       strings: [],
-      state: new Uint16Array(numRows),
-      cpu: new Int8Array(numRows),
+      state: new Uint16Array(totalSlices),
+      cpu: new Uint8Array(totalSlices),
+      summarisedStateBreakdowns: new Map(),
     };
 
-    const stringIndexes =
-        new Map<{shortState: string, ioWait: boolean | undefined}, number>();
-    function internState(shortState: string, ioWait: boolean|undefined) {
-      let idx = stringIndexes.get({shortState, ioWait});
+    const stringIndexes = new Map<string, number>();
+    function internString(str: string) {
+      let idx = stringIndexes.get(str);
       if (idx !== undefined) return idx;
-      idx = data.strings.length;
-      data.strings.push(translateState(shortState, ioWait));
-      stringIndexes.set({shortState, ioWait}, idx);
+      idx = summary.strings.length;
+      summary.strings.push(str);
+      stringIndexes.set(str, idx);
       return idx;
     }
-    iter(
-        {
-          'ts': NUM,
-          'dur': NUM,
-          'cpu': NUM_NULL,
-          'state': STR_NULL,
-          'io_wait': NUM_NULL,
-          'id': NUM_NULL,
-        },
-        result);
+
+    let outIndex = 0;
     for (let row = 0; row < numRows; row++) {
       const cols = result.columns;
-      const startNsQ = +cols[0].longValues![row];
-      const startNs = +cols[1].longValues![row];
-      const durNs = +cols[2].longValues![row];
-      const endNs = startNs + durNs;
+      const start = +cols[0].longValues![row];
+      const dur = +cols[1].longValues![row];
+      const state = cols[3].stringValues![row];
+      const percent = +(cols[4].doubleValues![row].toFixed(2));
+      const grouping = +cols[5].longValues![row];
 
-      let endNsQ = Math.floor((endNs + bucketNs / 2 - 1) / bucketNs) * bucketNs;
-      endNsQ = Math.max(endNsQ, startNsQ + bucketNs);
+      if (percent !== 1) {
+        let breakdownMap = summary.summarisedStateBreakdowns.get(outIndex);
+        if (!breakdownMap) {
+          breakdownMap = new Map();
+          summary.summarisedStateBreakdowns.set(outIndex, breakdownMap);
+        }
 
-      const cpu = cols[3].isNulls![row] ? -1 : cols[3].longValues![row];
-      const state = cols[4].stringValues![row];
-      const ioWait =
-          cols[5].isNulls![row] ? undefined : !!cols[5].longValues![row];
-      const id = cols[6].isNulls![row] ? -1 : cols[6].longValues![row];
+        const currentPercent = breakdownMap.get(state);
+        if (currentPercent === undefined) {
+          breakdownMap.set(state, percent);
+        } else {
+          breakdownMap.set(state, currentPercent + percent);
+        }
+      }
 
-      // We should never have the end timestamp being the same as the bucket
-      // start.
-      assertFalse(startNsQ === endNsQ);
-
-      data.starts[row] = fromNs(startNsQ);
-      data.ends[row] = fromNs(endNsQ);
-      data.state[row] = internState(state, ioWait);
-      data.ids[row] = id;
-      data.cpu[row] = cpu;
+      const nextGrouping =
+          row + 1 < numRows ? +cols[5].longValues![row + 1] : -1;
+      // If the next grouping is different then we have reached the end of this
+      // slice.
+      if (grouping !== nextGrouping) {
+        const numStates = summary.summarisedStateBreakdowns.get(outIndex) ?
+            summary.summarisedStateBreakdowns.get(outIndex)!.entries.length :
+            1;
+        summary.starts[outIndex] = fromNs(start);
+        summary.ends[outIndex] = fromNs(start + dur);
+        summary.state[outIndex] =
+            internString(numStates === 1 ? state : 'Various states');
+        summary.cpu[outIndex] = +cols[2].longValues![row];
+        outIndex++;
+      }
     }
-    return data;
+    return summary;
   }
 
-  async onDestroy() {
-    await this.query(`drop table if exists ${this.tableName('thread_state')}`);
+  onDestroy(): void {
+    if (this.setup) {
+      this.query(`drop view ${this.tableName('grouped_thread_states')}`);
+      this.setup = false;
+    }
   }
 }
 
diff --git a/ui/src/tracks/thread_state/frontend.ts b/ui/src/tracks/thread_state/frontend.ts
index 0383010..7410a0d 100644
--- a/ui/src/tracks/thread_state/frontend.ts
+++ b/ui/src/tracks/thread_state/frontend.ts
@@ -12,12 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {search} from '../../base/binary_search';
+import {search, searchEq} from '../../base/binary_search';
 import {Actions} from '../../common/actions';
 import {cropText} from '../../common/canvas_utils';
-import {colorForState} from '../../common/colorizer';
 import {TrackState} from '../../common/state';
+import {translateState} from '../../common/thread_state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {Color, colorForState} from '../../frontend/colorizer';
 import {globals} from '../../frontend/globals';
 import {Track} from '../../frontend/track';
 import {trackRegistry} from '../../frontend/track_registry';
@@ -25,6 +26,7 @@
 import {
   Config,
   Data,
+  StatePercent,
   THREAD_STATE_TRACK_KIND,
 } from './common';
 
@@ -32,6 +34,20 @@
 const RECT_HEIGHT = 14;
 const EXCESS_WIDTH = 10;
 
+function groupBusyStates(resolution: number) {
+  return resolution >= 0.0001;
+}
+
+function getSummarizedSliceText(breakdownMap: StatePercent) {
+  let result = 'Various (';
+  const sorted =
+      new Map([...breakdownMap.entries()].sort((a, b) => b[1] - a[1]));
+  for (const [state, value] of sorted.entries()) {
+    result += `${state}: ${Math.round(value * 100)}%, `;
+  }
+  return result.slice(0, result.length - 2) + ')';
+}
+
 class ThreadStateTrack extends Track<Config, Data> {
   static readonly kind = THREAD_STATE_TRACK_KIND;
   static create(trackState: TrackState): ThreadStateTrack {
@@ -53,10 +69,6 @@
 
     if (data === undefined) return;  // Can't possibly draw anything.
 
-    // The draw of the rect on the selected slice must happen after the other
-    // drawings, otherwise it would result under another rect.
-    let drawRectOnSelected = () => {};
-
     checkerboardExcept(
         ctx,
         this.getHeight(),
@@ -66,6 +78,8 @@
         timeScale.timeToPx(data.end),
     );
 
+    const shouldGroupBusyStates = groupBusyStates(data.resolution);
+
     ctx.textAlign = 'center';
     ctx.font = '10px Roboto Condensed';
 
@@ -76,56 +90,95 @@
       if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
         continue;
       }
+      if (tStart && tEnd) {
+        // Don't display a slice for Task Dead.
+        if (state === 'x') continue;
+        const rectStart = timeScale.timeToPx(tStart);
+        const rectEnd = timeScale.timeToPx(tEnd);
+        let rectWidth = rectEnd - rectStart;
+        const color = colorForState(state);
+        let text = translateState(state);
+        const breakdown = data.summarisedStateBreakdowns.get(i);
+        if (breakdown) {
+          colorSummarizedSlice(breakdown, rectStart, rectEnd);
+          text = getSummarizedSliceText(breakdown);
+        } else {
+          let colorStr = `hsl(${color.h},${color.s}%,${color.l}%)`;
+          if (color.a) {
+            colorStr = `hsla(${color.h},${color.s}%,${color.l}%, ${color.a})`;
+          }
+          ctx.fillStyle = colorStr;
+        }
+        if (shouldGroupBusyStates && rectWidth < 1) {
+          rectWidth = 1;
+        }
+        ctx.fillRect(rectStart, MARGIN_TOP, rectWidth, RECT_HEIGHT);
 
-      // Don't display a slice for Task Dead.
-      if (state === 'x') continue;
-      const rectStart = timeScale.timeToPx(tStart);
-      const rectEnd = timeScale.timeToPx(tEnd);
-
-      const currentSelection = globals.state.currentSelection;
-      const isSelected = currentSelection &&
-          currentSelection.kind === 'THREAD_STATE' &&
-          currentSelection.id === data.ids[i];
-
-      const color = colorForState(state);
-
-      let colorStr = `hsl(${color.h},${color.s}%,${color.l}%)`;
-      if (color.a) {
-        colorStr = `hsla(${color.h},${color.s}%,${color.l}%, ${color.a})`;
-      }
-      ctx.fillStyle = colorStr;
-
-      const rectWidth = rectEnd - rectStart;
-      ctx.fillRect(rectStart, MARGIN_TOP, rectWidth, RECT_HEIGHT);
-
-      // Don't render text when we have less than 10px to play with.
-      if (rectWidth < 10 || state === 'Sleeping') continue;
-      const title = cropText(state, charWidth, rectWidth);
-      const rectXCenter = rectStart + rectWidth / 2;
-      ctx.fillStyle = color.l > 80 ? '#404040' : '#fff';
-      ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 3);
-
-      if (isSelected) {
-        drawRectOnSelected = () => {
-          const rectStart =
-              Math.max(0 - EXCESS_WIDTH, timeScale.timeToPx(tStart));
-          const rectEnd = Math.min(
-              timeScale.timeToPx(visibleWindowTime.end) + EXCESS_WIDTH,
-              timeScale.timeToPx(tEnd));
-          const color = colorForState(state);
-          ctx.strokeStyle = `hsl(${color.h},${color.s}%,${color.l * 0.7}%)`;
-          ctx.beginPath();
-          ctx.lineWidth = 3;
-          ctx.strokeRect(
-              rectStart,
-              MARGIN_TOP - 1.5,
-              rectEnd - rectStart,
-              RECT_HEIGHT + 3);
-          ctx.closePath();
-        };
+        // Don't render text when we have less than 10px to play with.
+        if (rectWidth < 10 || text === 'Sleeping') continue;
+        const title = cropText(text, charWidth, rectWidth);
+        const rectXCenter = rectStart + rectWidth / 2;
+        ctx.fillStyle = color.l > 80 || breakdown ? '#404040' : '#fff';
+        ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 3);
       }
     }
-    drawRectOnSelected();
+
+    const selection = globals.state.currentSelection;
+    if (selection !== null && selection.kind === 'THREAD_STATE' &&
+        selection.utid === this.config.utid) {
+      const [startIndex, endIndex] = searchEq(data.starts, selection.ts);
+      if (startIndex !== endIndex) {
+        const tStart = data.starts[startIndex];
+        const tEnd = data.ends[startIndex];
+        const state = data.strings[data.state[startIndex]];
+
+        // If we try to draw too far off the end of the canvas (+/-4m~),
+        // the line is not drawn. Instead limit drawing to the canvas
+        // boundaries, but allow some excess to ensure that the start and end
+        // of the rect are not shown unless that is truly when it starts/ends.
+        const rectStart =
+            Math.max(0 - EXCESS_WIDTH, timeScale.timeToPx(tStart));
+        const rectEnd = Math.min(
+            timeScale.timeToPx(visibleWindowTime.end) + EXCESS_WIDTH,
+            timeScale.timeToPx(tEnd));
+        const color = colorForState(state);
+        ctx.strokeStyle = `hsl(${color.h},${color.s}%,${color.l * 0.7}%)`;
+        ctx.beginPath();
+        ctx.lineWidth = 3;
+        ctx.strokeRect(
+            rectStart, MARGIN_TOP - 1.5, rectEnd - rectStart, RECT_HEIGHT + 3);
+        ctx.closePath();
+      }
+    }
+
+    // Make a gradient ordered most common to least based on the colors of the
+    // states within the summarized slice.
+    function colorSummarizedSlice(
+        breakdownMap: StatePercent, rectStart: number, rectEnd: number) {
+      const gradient =
+          ctx.createLinearGradient(rectStart, MARGIN_TOP, rectEnd, MARGIN_TOP);
+      // Sometimes multiple states have the same color e.g R, R+
+      const colorMap = new Map<Color, number>();
+      for (const [state, value] of breakdownMap.entries()) {
+        const color = colorForState(state);
+        const currentColorValue = colorMap.get(color);
+        if (currentColorValue === undefined) {
+          colorMap.set(color, value);
+        } else {
+          colorMap.set(color, currentColorValue + value);
+        }
+      }
+
+      const sorted =
+          new Map([...colorMap.entries()].sort((a, b) => b[1] - a[1]));
+      let colorStop = 0;
+      for (const [color, value] of sorted.entries()) {
+        const colorString = `hsl(${color.h},${color.s}%,${color.l}%)`;
+        colorStop = Math.max(0, Math.min(1, colorStop + value));
+        gradient.addColorStop(colorStop, colorString);
+      }
+      ctx.fillStyle = gradient;
+    }
   }
 
   onMouseClick({x}: {x: number}) {
@@ -134,12 +187,23 @@
     const {timeScale} = globals.frontendLocalState;
     const time = timeScale.pxToTime(x);
     const index = search(data.starts, time);
-    if (index === -1) return false;
-
-    const id = data.ids[index];
-    globals.makeSelection(
-        Actions.selectThreadState({id, trackId: this.trackState.id}));
-    return true;
+    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
+      }));
+      return true;
+    }
+    return false;
   }
 }
 
diff --git a/ui/src/tracks/vsync/common.ts b/ui/src/tracks/vsync/common.ts
new file mode 100644
index 0000000..9d8f968
--- /dev/null
+++ b/ui/src/tracks/vsync/common.ts
@@ -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.
+
+import {TrackData} from '../../common/track_data';
+
+export const KIND = 'VsyncTrack';
+
+export interface Data extends TrackData { vsyncs: Float64Array; }
+
+export interface Config { counterName: string; }
diff --git a/ui/src/tracks/vsync/controller.ts b/ui/src/tracks/vsync/controller.ts
new file mode 100644
index 0000000..4934758
--- /dev/null
+++ b/ui/src/tracks/vsync/controller.ts
@@ -0,0 +1,70 @@
+// 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 {fromNs} from '../../common/time';
+import {LIMIT} from '../../common/track_data';
+
+import {
+  TrackController,
+  trackControllerRegistry
+} from '../../controller/track_controller';
+
+import {Config, Data, KIND} from './common';
+
+class VsyncTrackController extends TrackController<Config, Data> {
+  static readonly kind = KIND;
+  private setup = false;
+
+  async onBoundsChange(start: number, end: number, resolution: number):
+      Promise<Data> {
+    if (this.setup === false) {
+      await this.query(
+          `create virtual table window_${this.trackState.id} using window;`);
+      await this.query(
+          `create virtual table span_${this.trackState.id}
+              using span_join(sched PARTITIONED cpu,
+                              window_${this.trackState.id});`);
+      this.setup = true;
+    }
+
+    const rawResult = await this.engine.query(`
+      select ts from counters
+        where name like "${this.config.counterName}%"
+        order by ts limit ${LIMIT};`);
+    const rowCount = +rawResult.numRecords;
+    const result = {
+      start,
+      end,
+      resolution,
+      length: rowCount,
+      vsyncs: new Float64Array(rowCount),
+    };
+    const cols = rawResult.columns;
+    for (let i = 0; i < rowCount; i++) {
+      const startSec = fromNs(+cols[0].longValues![i]);
+      result.vsyncs[i] = startSec;
+    }
+    return result;
+  }
+
+  onDestroy(): void {
+    if (this.setup) {
+      this.query(`drop table window_${this.trackState.id}`);
+      this.query(`drop table span_${this.trackState.id}`);
+      this.setup = false;
+    }
+  }
+}
+
+trackControllerRegistry.register(VsyncTrackController);
diff --git a/ui/src/tracks/vsync/frontend.ts b/ui/src/tracks/vsync/frontend.ts
new file mode 100644
index 0000000..d1f4f78
--- /dev/null
+++ b/ui/src/tracks/vsync/frontend.ts
@@ -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.
+
+import {TrackState} from '../../common/state';
+import {checkerboardExcept} from '../../frontend/checkerboard';
+import {globals} from '../../frontend/globals';
+import {Track} from '../../frontend/track';
+import {trackRegistry} from '../../frontend/track_registry';
+
+import {Config, Data, KIND} from './common';
+
+// TODO(hjd): De-dupe this from ChromeSliceTrack, CpuSliceTrack and VsyncTrack.
+const MARGIN_TOP = 5;
+const RECT_HEIGHT = 30;
+
+class VsyncTrack extends Track<Config, Data> {
+  static readonly kind = KIND;
+  static create(trackState: TrackState): VsyncTrack {
+    return new VsyncTrack(trackState);
+  }
+
+  constructor(trackState: TrackState) {
+    super(trackState);
+  }
+
+  renderCanvas(ctx: CanvasRenderingContext2D): void {
+    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
+
+    const data = this.data();
+    if (data === undefined) return;  // Can't possibly draw anything.
+
+    const dataStartPx = timeScale.timeToPx(data.start);
+    const dataEndPx = timeScale.timeToPx(data.end);
+    const visibleStartPx = timeScale.timeToPx(visibleWindowTime.start);
+    const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
+
+    checkerboardExcept(
+        ctx,
+        this.getHeight(),
+        visibleStartPx,
+        visibleEndPx,
+        dataStartPx,
+        dataEndPx);
+
+    const bgColor = '#5E909B';
+    const fgColor = '#323D48';
+
+    const startPx = Math.floor(Math.max(dataStartPx, visibleStartPx));
+    const endPx = Math.floor(Math.min(dataEndPx, visibleEndPx));
+
+    ctx.fillStyle = bgColor;
+    ctx.fillRect(startPx, MARGIN_TOP, endPx - startPx, RECT_HEIGHT);
+
+    ctx.fillStyle = fgColor;
+    for (let i = 0; i < data.vsyncs.length; i += 2) {
+      const leftPx = Math.floor(timeScale.timeToPx(data.vsyncs[i]));
+      const rightPx = Math.floor(timeScale.timeToPx(data.vsyncs[i + 1]));
+      if (rightPx < startPx) continue;
+      // TODO(hjd): Do some thing better when very zoomed out.
+      if ((rightPx - leftPx) <= 1) continue;
+      if (leftPx > endPx) break;
+      ctx.fillRect(leftPx, MARGIN_TOP, rightPx - leftPx, RECT_HEIGHT);
+    }
+  }
+}
+
+trackRegistry.register(VsyncTrack);
diff --git a/ui/tsconfig.base.json b/ui/tsconfig.base.json
index 075b1b3..e240301 100644
--- a/ui/tsconfig.base.json
+++ b/ui/tsconfig.base.json
@@ -8,6 +8,7 @@
     "allowJs": true,
     "declaration": false,                  // Generates corresponding '.d.ts' file.
     "sourceMap": true,                     // Generates corresponding '.map' file.
+    "outDir": "./dist",                    // Redirect output structure to the directory.
     "removeComments": false,               // Do not emit comments to output.
     "importHelpers": true,                 // Import emit helpers from 'tslib'.
     "downlevelIteration": true,            // Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index 5867aea..8f2c266 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -4,11 +4,9 @@
   "exclude": [
     "./node_modules/",
     "./src/service_worker/",
-    "./src/gen/",
-    "./out"
+    "./src/gen/"
   ],
   "compilerOptions": {
-    "outDir": "./out/tsc",
     "lib": [
       "dom",                               // Need to be explicitly mentioned now since we're overriding default included libs.
       "es2018",                            // Need this to use Object.values.